/* ==========================================================================
   Align 2026 — section layouts
   ========================================================================== */

/* --------------------------------------------------------------------------
   HERO + SHOWREEL — một scene ghim: nội dung hero trôi ra, khung video
   phóng từ thẻ nhỏ góc phải lên full-bleed. Tất cả chạy bằng --p.
   -------------------------------------------------------------------------- */

/* Tiến độ cảnh ghim. JS ghi đè bằng inline style mỗi khung hình, nhưng phải có
   sẵn giá trị 0 ngay từ CSS: var(--p) chưa khai thì MỌI khai báo dùng nó hỏng
   nguyên (transform, opacity về mặc định), nên khung video hero bung ra
   full-bleed một nhịp rồi mới co lại khi JS chạy lượt đầu.
   Chỉ đặt cho cảnh GHIM — cảnh trôi ([data-flow]) vào trang đã ở giữa mạch nên
   p thật của nó lúc tải là 1, ép 0 lại thành nháy ngược. */
[data-scene] { --p: 0; }

/* 360svh = 260svh nhu cu + 100svh dành riêng cho màn pixel. Quãng thêm nằm ở
   CUỐI phần ghim: lúc đó khung showreel đã mở hết cỡ và đứng yên, màn pixel
   cắt vào một hình tĩnh, còn The studio thì trôi lên phía sau. Trang không dài
   thêm một milimet nào: 100svh cuối của cảnh chồng đúng lên #studio. */
.hero-scene { height: 360svh; }

.hero-pin {
	position: sticky;
	top: 0;
	height: 100svh;
	overflow: hidden;
	/* Nền ĐẶC: từ vòng mười tám, #studio nằm ngay phía sau tấm này (margin-top
	   âm). Hở một mảng trong suốt là lòi chữ của nó ra trước lúc cần. */
	background: var(--ground);
	/* Và phải nằm TRÊN #studio. Không khai z-index thì không: chữ trong #studio
	   có transform (reveal theo dòng / ký tự), mà phần tử có transform thì được
	   vẽ ở lớp của các phần tử định vị — cùng lớp với tấm này nhưng đứng sau
	   trong DOM nên thắng. Đo được đúng triệu chứng: chữ The studio hiện đè lên
	   video. */
	z-index: 3;
	/* Số cột của lưới pixel. main.js đọc biến này rồi tự tính cạnh ô (= bề
	   ngang tấm / số cột) và số hàng, nên ô luôn vuông và lưới luôn vừa khít. */
	--pxc: 28;
	/* --ph: tiến độ của các chuyển động BÊN TRONG hero (chữ trôi lên, khung
	   showreel mở ra, nút play). Xong ở đúng chỗ như trước khi cảnh dài thêm,
	   rồi đứng yên suốt 100svh cuối để màn pixel chạy.
	   --pm = (chiều cao cảnh - 100svh) / (chiều cao cảnh - 200svh), tức là tỉ
	   lệ giữa quãng ghim mới và quãng ghim cũ. Đổi chiều cao cảnh thì phải đổi
	   số này, nếu không khung showreel mở chậm lại đúng bằng phần dài thêm. */
	--pm: 1.625;
	--ph: clamp(0, calc(var(--p) * var(--pm)), 1);
}

/* Trong lúc màn pixel cắt: bỏ hẳn hai lớp này ra khỏi cây vẽ. Lúc đó cả hai
   đã vô hình sẵn (chữ hero mờ hết ở --ph = 0.53, cảnh WebGL thì bị khung
   showreel phủ kín), nhưng vẫn bị vẽ lại mỗi khung — mà mỗi lớp vẽ lại nằm
   trong vùng bị clip-path cắt lại tốn thêm một lượt raster. Đo trên máy không
   GPU: 33ms/khung khi không cắt, 50ms khi cắt mà chúng còn chạy, về lại 33ms
   khi tắt. visibility: hidden KHÔNG ăn thua, phải là display: none. */
.hero-pin.is-px .hero-bg,
.hero-pin.is-px .hero-stage { display: none; }

.hero-stage {
	position: absolute;
	inset: 0;
	display: grid;
	align-content: center;
	padding: 8.5rem var(--edge) calc(var(--gutter) + 1rem);
	/* Trôi lên và mờ dần trong nửa đầu scene */
	transform: translate3d(0, calc(var(--ph) * -14svh), 0);
	opacity: clamp(0, calc(1 - var(--ph) * 1.9), 1);
	will-change: transform, opacity;
}

.hero-top {
	display: grid;
	grid-template-columns: minmax(230px, 25%) 1fr;
	gap: 3vw;
	/* Cột trái bắt đầu ngang đỉnh chữ h1 */
	align-items: start;
}

/* Cột trái: badge, rồi CTA nằm ngay bên dưới */
.hero-side {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--sp-2);
}

.hero-badge {
	display: flex;
	align-items: flex-start;
	gap: 0.7rem;
	font-size: var(--t-xs);
	line-height: var(--lh-subhead);
	/* Bù phần leading của h1 (line-height 1.06) để đỉnh chữ hai bên khớp nhau */
	margin-top: calc(var(--t-xxl3) * 0.169);
}
.hero-badge img { width: 22px; height: auto; margin-top: 2px; }

.hero-title { max-width: 20ch; }

.hero-cta {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1.15rem;
}
/* Bọc ngoài để giữ animation vào: .hero-scroll có transition hover riêng,
   đặt data-rise thẳng lên nó thì shorthand đó xoá mất transition của rise. */
.hero-scroll-w { align-self: center; }   /* căn giữa theo nút phía trên */
.hero-scroll {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
	transition: opacity 0.4s var(--ease);
}
.hero-scroll:hover { opacity: 0.62; }

/* Khung media bay: giữ nguyên kích thước full-bleed, thu nhỏ bằng scale */
.reel {
	position: absolute;
	inset: 0;
	z-index: 5;
	transform-origin: 100% 100%;
	transform:
		translate3d(calc((1 - var(--ph)) * -3.2vw), calc((1 - var(--ph)) * -5.6svh), 0)
		scale(calc(0.185 + 0.815 * var(--ph)));
	will-change: transform;
}
.reel__inner { position: relative; width: 100%; height: 100%; }
.reel video,
.reel img { width: 100%; height: 100%; object-fit: cover; }

/* Caption của showreel — hiện khi khung đã mở hết */
.reel__cap {
	position: absolute;
	left: var(--edge);
	bottom: calc(var(--gutter) + 0.6rem);
	z-index: 7;
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	width: calc(100% - var(--edge) * 2);
	gap: 3vw;
	opacity: clamp(0, calc((var(--ph) - 0.72) * 5), 1);
	transform: translate3d(0, calc((1 - var(--ph)) * 24px), 0);
}

.play {
	position: absolute;
	left: 50%; top: 50%;
	z-index: 6;
	display: grid;
	place-items: center;
	width: clamp(74px, 7vw, 104px);
	aspect-ratio: 1;
	border-radius: 50%;
	background: var(--glass-bg);
	border: 1px solid var(--glass-border);
	-webkit-backdrop-filter: blur(var(--glass-blur));
	backdrop-filter: blur(var(--glass-blur));
	transform: translate(-50%, -50%) scale(clamp(0, calc((var(--ph) - 0.66) * 3), 1));
}

/* --------------------------------------------------------------------------
   STATS
   -------------------------------------------------------------------------- */

.stats__head {
	display: grid;
	grid-template-columns: 1fr minmax(240px, 22%);
	gap: 4vw;
	align-items: end;
}
.stats__note { display: flex; flex-direction: column; gap: 1.4rem; align-items: flex-start; }

.stats__grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 2vw;
	margin-top: var(--sp-3);
}
.stat { display: flex; flex-direction: column; gap: 0.8rem; padding-top: 1.6rem; }
/* Con số là thứ đáng nhìn nhất trong khối này — cho hẳn cỡ display */
.stat__n { font-size: var(--t-xxl); line-height: 0.95; letter-spacing: -0.03em; }

/* --------------------------------------------------------------------------
   FORMS — scene ghim, các hình lắp dần vào theo --p
   -------------------------------------------------------------------------- */

/* Không ghim: section cao đúng một màn, --p chạy theo lúc nó đi qua khung
   nhìn — hình lắp dần ngay trong lúc cuộn chứ không giữ màn hình lại. */
.forms-scene { --p: 0; }

.forms-pin {
	position: relative;
	height: 100svh;
	overflow: hidden;
}

.forms-item {
	position: absolute;
	will-change: transform;
	/* mỗi hình có --dx/--dy/--dr riêng, trôi về 0 khi --p tiến tới 1 */
	transform:
		translate3d(calc((1 - var(--p)) * var(--dx, 0px)), calc((1 - var(--p)) * var(--dy, 0px)), 0)
		rotate(calc(var(--rot, 0deg) + (1 - var(--p)) * var(--dr, 0deg)));
}

.forms-cap {
	position: absolute;
	left: var(--edge);
	bottom: calc(var(--gutter) + 1rem);
	z-index: 8;
	display: flex;
	flex-direction: column;
	gap: 0.9rem;
	max-width: 30ch;
	opacity: clamp(0, calc(var(--p) * 2.4 - 0.2), 1);
}

.slot {
	display: grid;
	place-items: center;
	gap: 0.6rem;
	width: 100%;
	height: 100%;
	background: rgba(var(--ink-rgb), 0.05);
	border: 1px solid var(--hairline);
	text-align: center;
}

/* --------------------------------------------------------------------------
   SERVICES
   -------------------------------------------------------------------------- */

.svc-head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 3vw;
	margin-bottom: var(--sp-2);
}
.svc-head h2 { max-width: 22ch; }

/* .svc là tấm nền (dính khi xếp chồng), .svc__in mới là bố cục bên trong —
   tách hai tầng để tấm bị phủ lùi lại / tối đi mà nền của nó vẫn kín. */
.svc {
	position: relative;
	margin-top: var(--sp-2);
}
.svc__in {
	position: relative;
	display: grid;
	grid-template-columns: 1fr minmax(0, 46%);
	column-gap: 3.4vw;
	align-items: center;
	padding-top: var(--sp-1);
}
.svc__body { display: flex; flex-direction: column; gap: 1.4rem; }
.svc__body p { max-width: 34ch; }
.svc__tags { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.tag {
	display: inline-flex;
	align-items: center;
	height: max(34px, 2.5vw);
	padding: 0 max(14px, 1.05vw);
	border: 1px solid var(--hairline);
	border-radius: var(--radius-pill);
	font-size: var(--t-xxs);
	line-height: 1;
	color: var(--body);
}
.svc__art {
	position: relative;
	aspect-ratio: 4 / 3;
	background: rgba(var(--ink-rgb), 0.09);
	overflow: hidden;
}
.svc__art svg { width: 100%; height: 100%; }
/* Trang dịch vụ đặt ẢNH vào đúng khung này thay cho hình vẽ */
.svc__art > img { width: 100%; height: 100%; object-fit: cover; }

/* kẻ 2px trên mỗi service — nằm đúng chỗ border-top cũ, ngoài luồng grid,
   nên không đẩy nội dung xuống. Tự vẽ ra khi vào khung nhìn. */
.svc__rule {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 2px;
	background: var(--ink);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform 1.2s var(--ease-out);
}
.is-in .svc__rule,
.is-in.svc__rule { transform: scaleX(1); }

/* Kẻ đóng dưới service cuối — cùng nhịp với các kẻ phân cách phía trên */
.svc__rule--end { position: static; margin-top: var(--sp-2); }

/* --------------------------------------------------------------------------
   APPROACH
   -------------------------------------------------------------------------- */

.appr__intro {
	display: grid;
	grid-template-columns: 1fr minmax(240px, 30%);
	gap: 4vw;
	align-items: end;
	/* Cụm chữ và bảng bên dưới là hai nhịp khác nhau, cần nghỉ rõ hơn --sp-2 */
	margin-bottom: var(--sp-3);
}
.appr__claim { margin-top: 1.4rem; max-width: 26ch; }
.appr__note { max-width: 46ch; }

.appr-row {
	display: grid;
	grid-template-columns: minmax(160px, 20%) 1fr minmax(150px, 22%);
	gap: 3.4vw;
	align-items: baseline;
	padding-top: 2rem;
	border-top: 1px solid var(--hairline);
	margin-top: 2rem;
}
.appr-row__stage { display: flex; align-items: flex-start; gap: 0; }
/* Cột giữa là 1fr nên phình theo màn hình (687px ở 1440, 916px ở 1920) —
   một dòng dài 73 ký tự, mắt đọc hết dòng quay về đầu dòng sau là lạc. Chặn
   ở ~58 ký tự rồi CĂN GIỮA trong cột: dính mép trái thì cả khoảng thừa dồn
   sang phải, chữ nằm sát cột Stage. Nhãn "What happens" phải dùng đúng cùng
   bề rộng thì mép trái hai cái mới thẳng hàng — nên KHÔNG dùng ch, vì ch tính
   theo cỡ chữ của chính phần tử mà nhãn (t-xxs) với đoạn văn (t-s) khác cỡ.
   27.5 × --t-s bằng đúng 44ch của đoạn văn. */
.appr-row, .appr-head { --appr-measure: min(100%, calc(var(--t-s) * 27.5)); }
.appr-row > p,
.appr-head > :nth-child(2) { width: var(--appr-measure); justify-self: center; }
.appr-row__out {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 0.4rem;
	text-align: right;
}
.appr-head {
	display: grid;
	grid-template-columns: minmax(160px, 20%) 1fr minmax(150px, 22%);
	gap: 3.4vw;
}
.appr-head > :last-child { text-align: right; }

/* --------------------------------------------------------------------------
   PROJECTS
   -------------------------------------------------------------------------- */

.work__head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 3vw;
	margin-bottom: var(--sp-2);
}
.work__counts { display: flex; align-items: flex-end; gap: 3vw; }
.work__counts ul { display: flex; flex-direction: column; gap: 0.2rem; min-width: 150px; }
.work__counts li { display: flex; justify-content: space-between; gap: 1rem; }

.work-hero { display: flex; flex-direction: column; gap: 1rem; }
.work-hero__media {
	position: relative;
	aspect-ratio: 1352 / 685;
	overflow: hidden;
}
.work-hero__media img { width: 100%; height: 100%; object-fit: cover; }
/* Tên nằm NGOÀI khung ảnh, giống các thẻ project còn lại. Đè lên ảnh thì ở nền
   sáng chữ trùng màu với vùng sáng của ảnh, đọc không ra. */
.work-hero__name { display: block; }
.work-hero__meta { display: flex; align-items: baseline; justify-content: space-between; gap: 2vw; }

.work-grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--sp-3) 3.4vw;
	margin-top: var(--sp-3);
}
.work-card { display: flex; flex-direction: column; gap: 0.9rem; }
.work-card__media { position: relative; aspect-ratio: 4 / 3; overflow: hidden; }
.work-card__media img { width: 100%; height: 100%; object-fit: cover; }
.work-card__meta { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }

.work__foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 3vw;
	padding-top: 2.4rem;
	border-top: 1px solid var(--hairline);
	margin-top: var(--sp-3);
}

/* --------------------------------------------------------------------------
   CLIENTS
   -------------------------------------------------------------------------- */

.clients h2 { max-width: 36ch; }

/* Tường logo: hai hàng chạy ngược chiều nhau, dừng khi rê chuột vào.
   Mỗi hàng chứa danh sách hai lần, animation dịch -50% nên lặp liền mạch. */
/* Logo khách là file trắng một màu, không đổi theo theme, nên ở nền sáng chúng
   trắng-trên-giấy và gần như vô hình. Đảo màu chính ảnh: invert(1) biến nét
   trắng thành đen mà vẫn giữ nguyên kênh alpha, nên không cần nền đỡ phía sau. */
body.is-light .logo-row img { filter: invert(1); }
.logo-wall {
	--logo-h: max(34px, 2.9vw);
	display: flex;
	flex-direction: column;
	gap: 2.2rem;
	padding-block: var(--sp-2);
	border-top: 1px solid var(--hairline);
	border-bottom: 1px solid var(--hairline);
	margin-block: var(--sp-3);
	overflow: hidden;
	/* hai mép mờ dần để logo không bị cắt cụt */
	-webkit-mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
	mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
}
.logo-row {
	display: flex;
	width: max-content;
	animation: logo-run var(--speed, 56s) linear infinite;
}
.logo-row--b { animation-direction: reverse; --speed: 72s; }
.logo-wall:hover .logo-row { animation-play-state: paused; }
.logo-row > div { display: grid; place-items: center; height: var(--logo-h); padding-inline: 2.6vw; }
.logo-row img {
	height: auto;
	max-height: var(--logo-h);
	max-width: 100%;
	width: auto;
	object-fit: contain;
}
@keyframes logo-run {
	from { transform: translateX(0); }
	to { transform: translateX(-50%); }
}

/* Giảm chuyển động: bỏ chạy, xếp logo thành lưới tĩnh */
@media (prefers-reduced-motion: reduce) {
	.logo-row { animation: none; width: 100%; flex-wrap: wrap; justify-content: center; }
	.logo-row .dup { display: none; }
}

/* Đầu khối trích dẫn: nhãn bên trái, tag đánh giá Clutch bên phải */
.quotes__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 2vw;
	flex-wrap: wrap;
}
.clutch {
	display: inline-flex;
	align-items: center;
	gap: 0.7rem;
	padding: 0.5rem 1rem;
	border: 1px solid var(--hairline);
	border-radius: var(--radius-pill);
	transition: background 0.4s var(--ease);
}
.clutch:hover { background: rgba(var(--ink-rgb), 0.08); }
.clutch__stars { display: inline-flex; gap: 0.15rem; }
.clutch__stars svg { width: 12px; height: 12px; fill: var(--ink); }
/* Dấu Clutch. Cao đúng bằng chữ trong tag, tô currentColor nên theo mực nền. */
.clutch__mark { flex: none; width: 13px; height: 15px; color: var(--ink); }

/* --------------------------------------------------------------------------
   MÀN PIXEL — hero bị cắt từng ô vuông, lộ ra The studio nằm NGAY PHÍA SAU

   Không có phần tử nào cho màn này: main.js cắt thẳng vào .hero-pin bằng
   clip-path: path(). Trước đây là 728 thẻ <i> màu nền phủ LÊN hero — nhìn thì
   giống, nhưng ô chỉ là một mảng màu phẳng chứ không phải cửa sổ nhìn ra
   section sau, và 728 thẻ đó nằm luôn trong index.html.

   Vì sao clip-path chứ không phải mask: Safari không cho một phần tử HTML trỏ
   tới <mask> của SVG (MDN: "Does not support referencing an SVG <mask> element
   from a non-SVG element"), còn clip-path: path() thì Chrome 88 / Safari 13.1 /
   Firefox 71 đều chạy.
   -------------------------------------------------------------------------- */

/* The studio LEO LÊN nằm dưới tấm hero đúng một màn hình, nên lúc hero bị cắt
   đi từng ô là thấy ngay nó ở sau. Cũng nhờ vậy mà hết sạch đoạn nền phẳng
   giữa hai section: hero cắt xong là The studio đã ở đó rồi. */
#studio {
	/* Nằm DƯỚI .hero-pin (z-index 3) — xem ghi chú ở đó */
	position: relative;
	z-index: 1;
	margin-top: calc(var(--sec-gap) - 100svh);
	/* Cao bằng đúng mảng bị tấm hero phủ, để The studio chiếm trọn màn lúc lộ
	   ra thay vì bị section sau chen lên từ dưới. */
	min-height: calc(100svh - var(--sec-gap));
	/* Link "or keep scrolling" đáp xuống SAU màn pixel: trừ đi lề trên của
	   chính nó thì rơi đúng lúc hero vừa tan hết. main.js trừ giá trị này
	   trong glide(). */
	scroll-margin-top: var(--sec-gap);
}

/* Không cắt thì không được chồng: cả hai trường hợp dưới đây hero cứ thế trôi
   đi, chồng lên nhau là nuốt mất màn đầu của The studio. */
.no-js #studio { margin-top: var(--sec-gap); min-height: 0; scroll-margin-top: 0; }
@media (prefers-reduced-motion: reduce) {
	#studio { margin-top: var(--sec-gap); min-height: 0; scroll-margin-top: 0; }
}

/* --------------------------------------------------------------------------
   DECK — scene ghim, panel trượt vào từ mép phải (bố cục học pear.no)
   -------------------------------------------------------------------------- */

.deck-scene { --p: 0; }

.deck-pin {
	position: relative;
	height: 100svh;
	overflow: hidden;
	border-top: 1px solid var(--hairline);
	border-bottom: 1px solid var(--hairline);
}

.deck__lead {
	position: absolute;
	left: var(--edge);
	top: max(90px, 12svh);
	z-index: 6;
	display: flex;
	flex-direction: column;
	gap: 1.4rem;
	max-width: 30ch;
}
.deck__act {
	position: absolute;
	left: var(--edge);
	bottom: max(70px, 10svh);
	z-index: 6;
	display: flex;
	align-items: center;
	gap: 1.4rem;
}
.deck__ed {
	position: absolute;
	right: var(--edge);
	top: max(90px, 12svh);
	z-index: 6;
}

.deck__panel {
	position: absolute;
	z-index: 4;
	will-change: transform;
	transform: translate3d(calc((1 - var(--p)) * var(--dx, 46vw)), 0, 0)
	           rotate(var(--rot, 0deg));
}
.deck__panel img { width: 100%; height: 100%; object-fit: cover; }

/* --------------------------------------------------------------------------
   INSIGHTS
   -------------------------------------------------------------------------- */

.ins__head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 3vw;
	margin-bottom: var(--sp-2);
}
.ins__grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 2.4vw;
	margin-top: var(--sp-2);
}
.post { display: flex; flex-direction: column; gap: 1rem; }
.post__media { position: relative; aspect-ratio: 16 / 9; overflow: hidden; }
.post__media img { width: 100%; height: 100%; object-fit: cover; }
.post__cat {
	display: inline-flex;
	align-self: flex-start;
	align-items: center;
	height: max(30px, 2.2vw);
	padding: 0 max(13px, 0.95vw);
	border: 1px solid var(--hairline);
	border-radius: var(--radius-pill);
	font-size: var(--t-xxs);
	line-height: 1;
}

/* --------------------------------------------------------------------------
   QUESTIONS — thẻ xoay vòng theo cuộn (bố cục + chuyển động học pear.no).
   Vị trí, độ mờ, độ nét từng thẻ do JS (updateFaq) ghi mỗi khung. CSS lo
   hình thẻ và trạng thái bật (.is-on). Cuộn qua hết cảnh thì thẻ giữ nguyên
   trạng thái cuối, trôi lên theo trang.
   -------------------------------------------------------------------------- */

/* Chiều cao cảnh nhân theo SỐ THẺ (--fq-n, markup ghi vào): 96svh một thẻ.
   Trang chủ năm thẻ = 480svh như cũ, trang dịch vụ ba thẻ = 288svh. Khoá cứng
   480svh thì ba thẻ vẫn ngốn đúng quãng cuộn của năm. */
.faq { --lead: 0; height: calc(var(--fq-n, 5) * 96svh); }
/* Ghi đè nhịp chung `main > * + * { margin-top: var(--sec-gap) }` của base.css:
   khối phía trên kết thúc bằng dải logo vốn đã có sẵn margin --sp-3 (125px), nên
   cộng thêm trọn --sec-gap (216px ở 1440) thành ~341px không khí. */
#voices { margin-top: calc(var(--sec-gap) * 0.3); }
/* --exit-o / --exit-y do JS ghi ở pha thoát (khung nhìn cuối của cảnh) */
.faq__stage {
	position: absolute;
	inset: 0;
	opacity: var(--exit-o, 1);
	transform: translateY(var(--exit-y, 0px));
}
/* Lưới hai cột: nhãn chiếm trọn hàng 1, hàng 2 là tiêu đề bên trái và tag Clutch
   bên phải. align-items: end nên tag căn theo ĐÁY TIÊU ĐỀ, không phải theo nhãn. */
.faq__head {
	position: absolute;
	z-index: 3;
	left: var(--edge);
	right: var(--edge);
	top: max(104px, 15svh);
	display: grid;
	grid-template-columns: auto 1fr;
	align-items: end;
	column-gap: 2vw;
}
.faq__head .label { grid-column: 1 / -1; }
.faq__head h2 { margin-top: 1.2rem; max-width: 11ch; }
.faq__rate { justify-self: end; }

/* Mũi tên dẫn tới review trên Clutch, góc phải mỗi thẻ. Thẻ nào không có link
   thì không render phần tử này. */
/* Không vòng tròn, cỡ nhỏ: thứ nổi bật trên thẻ là LOGO khách, mũi tên chỉ là
   lối dẫn đi. stroke-width 2 trên viewBox 24 hiện ở 0.9em => nét 0.075em, xấp xỉ
   nét thân chữ. */
.fq__link {
	position: absolute;
	top: clamp(24px, 2vw, 32px);
	right: clamp(24px, 2vw, 32px);
	z-index: 4;
	display: block;
	width: 0.9em;
	opacity: 0.62;
	transition: opacity 0.3s var(--ease);
}
.fq__link:hover { opacity: 1; }
.fq__link svg { width: 100%; height: auto; display: block; }

.faq__ring { position: absolute; z-index: 1; left: 50%; top: 56%; width: 0; height: 0; }
.fq {
	position: absolute;
	left: 0;
	top: 0;
	width: clamp(230px, 19vw, 290px);
	/* min-height chứ KHÔNG phải height: chiều cao cố định là chỗ duy nhất
	   về mặt cấu trúc có thể làm chữ tràn ra ngoài viền. */
	min-height: clamp(290px, 24vw, 360px);
	/* Padding cũ 20px + h3 cỡ t-m làm nội dung lấp KHÍT hộp (đo: dư 2px ở mọi
	   thẻ, cả 390 lẫn 1440), nên space-between không còn gì để giãn và chữ ép
	   sát viền. Nới padding, hạ h3 một bậc, và đặt gap tối thiểu. */
	padding: clamp(24px, 2vw, 32px);
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: 1.2rem;
	border: 1px solid var(--hairline);
	background: rgba(var(--ink-rgb), 0.06);
	opacity: 0;
	will-change: transform, opacity, filter;
	transition: background 0.5s var(--ease), border-color 0.5s var(--ease);
	--c: 7px;
}
/* Cỡ chữ riêng cho thẻ, không mượn thang chung: thang chung có sàn 16/14px
   nên ở thẻ hẹp 230px chữ vẫn to quá so với hộp. */
/* Logo khách trên đầu thẻ. object-position trái để logo ngang (spire, unicef)
   không bị căn giữa trông như lệch so với chữ bên dưới. */
/* Thẻ không có logo (Clutch giấu tên khách): dấu Clutch đứng đúng chỗ logo,
   cùng chiều cao nên hàng đầu của mọi thẻ vẫn thẳng nhau. */
.fq__mark { display: block; height: max(25px, 1.85vw); color: var(--ink); }
.fq__mark svg { height: 100%; width: auto; }

.fq__logo {
	/* To hơn một chút: logo mới là thứ nổi bật trên thẻ */
	height: max(25px, 1.85vw);
	width: auto;
	max-width: 58%;
	object-fit: contain;
	object-position: left center;
	opacity: 0.9;
}
body.is-light .fq__logo { filter: invert(1); }
.fq h3 { font-size: clamp(15px, 1.15vw, 19px); line-height: 1.14; }
.fq p {
	font-size: clamp(12.5px, 0.88vw, 14.5px);
	opacity: 0;
	transform: translateY(10px);
	transition: opacity 0.5s var(--ease), transform 0.7s var(--ease-out);
}
.fq.is-on { border-color: rgba(var(--ink-rgb), 0.55); background: rgba(var(--ink-rgb), 0.1); }
.fq.is-on p { opacity: 1; transform: none; }
.fq > .c { transform: scale(0); transition: transform 0.5s var(--ease-out); }
.fq.is-on > .c { transform: none; }

/* Đường nối từ điểm neo trên nền tới cạnh thẻ đang bật */
.faq__lead {
	position: absolute;
	inset: 0;
	z-index: 2;
	width: 100%;
	height: 100%;
	overflow: visible;
	pointer-events: none;
	opacity: var(--lead);
}
.faq__lead line { stroke: var(--ink); stroke-width: 1; }
.faq__lead circle, .faq__lead rect { fill: var(--ink); }

@media (max-width: 720px) {
	.faq { height: 430svh; }
	/* Khổ hẹp: bỏ hai cột, tag Clutch xuống dưới tiêu đề và chiếm trọn bề ngang */
	.faq__head { top: max(88px, 12svh); grid-template-columns: 1fr; }
	.faq__rate { justify-self: stretch; margin-top: 1rem; }
	.faq__rate .clutch { display: flex; width: 100%; justify-content: center; }
	.faq__ring { top: 60%; }
	.fq { width: 66vw; height: auto; min-height: 62vw; }
	/* màn hẹp: đường nối cắt ngang chữ của thẻ, bỏ */
	.faq__lead { display: none; }
}

/* Giảm chuyển động: bỏ vòng xoay, xếp thành lưới thẻ tĩnh */
@media (prefers-reduced-motion: reduce) {
	.faq { height: auto; }
	.faq .scene__pin { position: static; height: auto; overflow: visible; }
	.faq__stage { position: static; opacity: 1; transform: none; filter: none; padding: var(--sp-3) var(--edge); }
	.faq__head { position: static; margin-bottom: var(--sp-2); }
	.faq__ring {
		position: static;
		width: auto;
		height: auto;
		display: grid;
		grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
		gap: 1rem;
	}
	.fq { position: static; width: auto; opacity: 1; transform: none !important; filter: none !important; }
	.fq p, .fq > .c { opacity: 1; transform: none; }
	.faq__lead { display: none; }
}

/* --------------------------------------------------------------------------
   CTA — cảnh riêng đứng trước footer
   -------------------------------------------------------------------------- */

.cta { position: relative; z-index: 2; padding-block: var(--sec-gap); overflow: hidden; }
.cta .container { position: relative; z-index: 1; }

/* Vệt blob lỏng chạy theo con trỏ, chỉ trong section CTA.
   Mẹo "gooey": các quả tròn ĐẶC nằm trong một khối có filter làm nhoè rồi ép
   lại độ trong (feColorMatrix) — chỗ hai quả gần nhau, hai vùng nhoè cộng lại
   vượt ngưỡng nên dính thành một khối liền, đúng kiểu giọt nước. Vì vậy quả
   phải đặc trước khi lọc; muốn nhạt thì hạ opacity của CẢ khối, không phải
   của từng quả (quả nhạt thì ngưỡng cắt xoá sạch). */
/* Vệt nằm TRÊN chữ và ĐẢO MÀU mọi thứ bên dưới nó: quả màu trắng tinh, cả khối
   trộn kiểu `difference` — trắng trừ nền chính là nghịch đảo nền. Thứ tự của
   trình duyệt là lọc (#goo) trước rồi mới trộn, nên hình lỏng đã dính liền mới
   đem đi đảo màu; chỉ một lượt lọc và một lượt trộn cho cả vệt.
   (Cách kia là backdrop-filter: invert trên từng quả, nhưng phần tử nằm trong
   một khối đã có filter thì không lấy được nền phía sau nữa.) */
.cta__goo {
	position: absolute;
	inset: 0;
	z-index: 2;
	display: none;                 /* chỉ bật ở màn rộng có chuột, xem dưới */
	filter: url(#goo);
	mix-blend-mode: difference;
	pointer-events: none;          /* chữ bên dưới vẫn bấm và hover được */
	/* Quả đầu to đúng bằng HAI dòng chữ CTA: hai hộp dòng (--t-xxl × --lh-display)
	   cộng khe giữa hai dòng (--roll-tail của .cta__h). Khoá theo --t-xxl nên
	   màn to nhỏ gì blob vẫn giữ đúng tỉ lệ với chữ. */
	--blob: calc(var(--t-xxl) * var(--lh-display) * 2 + var(--t-xxl) * 0.18);
	contain: layout paint;         /* vùng lọc khoá trong section, khỏi vẽ lan */
}
.cta__goo i {
	position: absolute;
	top: 0;
	left: 0;
	--s: calc(var(--blob) * var(--f, 1));
	width: var(--s);
	height: var(--s);
	margin: calc(var(--s) / -2);
	border-radius: 50%;
	/* Trắng TINH, không phải var(--ink): difference chỉ đảo màu đúng khi số bị
	   trừ là 1. Mực ở nền sáng là màu tối, dùng nó thì gần như không đảo gì. */
	background: #fff;
	/* JS ghi --x / --y / --r / --sx / --sy mỗi khung: quay theo hướng chạy rồi
	   dãn dọc hướng đó (translate → rotate → scale là đúng thứ tự trình duyệt
	   áp các thuộc tính riêng). KHÔNG đặt transition ở đây — transition sẽ chạy
	   đua với vòng rAF và làm cỡ lệch pha. */
	translate: var(--x, 50%) var(--y, 50%);
	rotate: var(--r, 0deg);
	scale: var(--sx, 0) var(--sy, 0);
}
@media (min-width: 1100px) and (hover: hover) {
	.cta__goo { display: block; }
}
@media (prefers-reduced-motion: reduce) {
	.cta__goo { display: none; }
}
/* CTA: mũi tên trên cùng, rồi BA dòng, canh giữa cả chữ lẫn so với khung.
   Cụm sau "something" tự đổi theo thời gian — xem initCtaWord trong main.js. */
.cta__link {
	--cta-hover: var(--coal);            /* nền cam thì cụm đổi sang đen */
	display: flex;
	justify-content: center;
	/* Co vừa nội dung rồi tự căn giữa: để mặc định thì thẻ <a> chiếm trọn bề
	   ngang container, nên vùng hover lố ra hai bên rất xa chữ. */
	width: fit-content;
	margin-inline: auto;
	color: var(--ink);
}
/* Nền cam thì cụm đổi sang đen; nền đen VÀ nền sáng đều sang cam — nền sáng mà
   để --coal thì hover trùng luôn màu chữ thường, rê vào không thấy gì đổi. */
body.is-dark .cta__link,
body.is-light .cta__link { --cta-hover: var(--flame); }
/* Dòng 1 canh trái, dòng 2 canh PHẢI theo mép phải của khối; cả khối căn giữa
   khung. Ô chữ xoay vòng cũng canh phải (justify-items: end) nên mép phải đứng
   yên khi đổi cụm, không nhảy. */
/* gap ĐÚNG BẰNG --roll-tail: .ln nhô xuống thêm ngần ấy để chừa đuôi chữ rồi
   kéo dòng sau lên lại bằng margin âm, nên không có gap thì khung cắt dòng 2
   thụt vào trong khung dòng 1 (đo được 7.2px) và đè lên đuôi chữ "g". */
.cta__h {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: var(--roll-tail);
	text-align: left;
}
.cta__row { display: flex; align-items: center; gap: 0.14em; }
.cta__row--end { justify-content: flex-end; }

/* Mũi tên NGANG, lấy nguyên hình arrow-right.svg. stroke-width 2 trên viewBox 24,
   hiển thị ở 0.95em, nên nét dày 2 x (0.95 / 24) = 0.079em — ngang đúng nét thân
   chữ Aeonik Regular. Đổi bề ngang thì PHẢI tính lại theo đúng tỉ lệ đó, muốn
   mũi tên to hơn mà giữ nét thì phải sửa stroke-width trong SVG. */
.cta__arrow {
	position: relative;
	/* align-items: center canh mũi tên theo giữa HỘP DÒNG, mà mắt đọc theo giữa
	   chiều cao chữ thường. Độ lệch giữa hai mốc đó suy ra từ chính đại lượng
	   phông: (ascender − descender) / 2 − x-height / 2 = (1.0 − 0.2) / 2 −
	   0.511 / 2 = 0.144em. Đo ở cỡ 90px ra đúng 13.0px. */
	top: 0.144em;
	width: 0.95em;
	height: auto;
	transition: transform var(--d-roll) var(--ease-text);
}
.cta__link:hover .cta__arrow { transform: translateX(0.28em); }

/* Hover: lăn chữ y như tên người ở trang About — NHƯNG không mượn được cấu trúc
   của splitLines nữa. Chế độ data-split="chars" dựng ra .ln > .wd > .w, KHÔNG có
   thẻ <i> bọc dòng và KHÔNG có data-t (chỉ chế độ "one" mới tạo hai thứ đó).
   Vì vậy cú lăn chuyển lên tầng .cta__roll: chính .ln trượt lên thoát khỏi khung,
   còn bản sao là ::after lấy data-t đặt sẵn trong markup trồi lên thay chỗ.
   Hai transform nằm ở hai tầng khác nhau (.ln và .w) nên cộng dồn, chars reveal
   bên trong vẫn chạy nguyên. Đổi chế độ split thì phải sửa lại khối này. */
/* Hover dòng 1: KHÔNG còn lăn chữ. Một đường gạch chân chạy từ trái sang phải
   dưới "Let's build something", và cả dòng đổi màu y như cụm xoay vòng bên
   dưới. Gạch là ::after của .cta__lead (không phải của .ln — .ln có
   overflow: hidden làm mặt nạ reveal, gạch nằm trong đó sẽ bị xén).
   Vị trí: chân chữ ở 0.93em tính từ đỉnh hộp dòng (nửa leading âm −0.07em +
   ascender 1.0em), gạch nằm dưới chân chữ 0.08em. Dày 0.06em — mảnh hơn nét
   thân chữ (0.079em) một chút để đọc ra là gạch chân chứ không phải một nét
   chữ nữa. */
.cta__lead, .cta__rot { --roll-tail: 0.08em; }
.cta__lead {
	position: relative;
	display: inline-block;
	transition: color 0.45s var(--ease);
}
.cta__lead::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	top: 1.01em;
	height: 0.06em;
	background: currentColor;
	transform: scaleX(0);
	transform-origin: 0 50%;
	transition: transform 0.9s var(--ease-out);
}
/* Chỉ cho gạch chạy khi chữ đã hiện XONG (JS gắn .is-ready sau khi reveal theo
   ký tự chạy hết). Rê chuột vào giữa chừng thì gạch vắt ngang đám chữ đang
   trồi lên, trông như gạch xoá. */
.cta__link.is-ready:hover .cta__lead::after { transform: scaleX(1); }
.cta__link:hover .cta__lead,
.cta__link:hover .cta__arrow { color: var(--cta-hover); }
.cta__arrow { transition: transform var(--d-roll) var(--ease-text), color 0.45s var(--ease); }

/* Ô chữ xoay vòng. LƯỚI xếp chồng cả 5 cụm vào CÙNG một ô nên bề ngang khoá
   theo cụm dài nhất — đổi chữ không làm dòng co giãn nhảy nhót. */
.cta__rot {
	display: grid;
	justify-items: end;
	overflow: hidden;
	padding-bottom: var(--roll-tail);
	margin-bottom: calc(var(--roll-tail) * -1);
	transition: color 0.45s var(--ease);
}
.cta__word {
	grid-area: 1 / 1;
	font-style: normal;
	white-space: nowrap;
	/* Đồng nhịp với mask reveal chuẩn của site — luật gốc `.ln > i` trong
	   components.css dùng --d-line / --ease-out. (Trước đây mốc so sánh là vế
	   hover của .cta__roll, nhưng vế đó không còn nằm trên `.ln > i` nữa.) */
	transform: translateY(105%);
	transition: transform var(--d-line) var(--ease-out);
}
.is-in .cta__word.is-on { transform: none; }
/* Đi lên phải QUÁ 105%: hộp dòng cao 1.06em mà đuôi chữ "g" thò xuống tới
   1.13em, nên dịch 1.05 × 1.06 = 1.113em vẫn còn 0.017em đuôi chữ nằm trong
   khung cắt — đo được đúng cái vệt cong còn sót lại dưới mũi tên. 130% thì
   quãng đi là 1.378em, thừa cho cả đuôi chữ. */
/* Và phải đi NHANH hơn cụm đang vào (0.75s so với --d-line 1.55s): chu kỳ nay
   chỉ 1.6s, nếu cụm cũ cũng bò 1.55s thì gần như lúc nào cũng có một mẩu đuôi
   chữ đang bò qua mép trên — đọc ra thành "chữ g còn sót lại". Đi 0.75s thì
   xong sớm, còn lại hơn nửa chu kỳ mép trên sạch trơn. */
.cta__word.is-out { transform: translateY(-130%); transition-duration: 0.75s; }
/* Trả về chỗ đậu phải TỨC THÌ. Phải đủ 3 class và đứng SAU luật is-live ở trên
   — để .cta__word.no-tr (2 class) thì is-live thắng, transition vẫn 0.5s và cụm
   cũ trượt ngược xuống xuyên qua vùng đang nhìn (đo được: no-tr không ăn). */
.cta__rot .cta__word.no-tr { transition: none; }

/* Chỉ cụm đổi mới đổi màu khi hover, phần chữ còn lại đã có hiệu ứng lăn */
.cta__link:hover .cta__rot { color: var(--cta-hover); }

/* Khổ hẹp: chữ to lên và BA dòng — "Let's build" / "something →" / cụm xoay.
   Cỡ chữ khoá theo bề ngang container (94vw) vì cả hai vế đều bị nó ép:
     · "worth remembering" nowrap rộng 8.79em  -> phải ≤ 94vw  -> cỡ ≤ 11.0vw
     · "Let's build something" rộng 9.44em     -> phải >  94vw -> cỡ >  9.96vw
   Lấy 10.3vw, chừa mỗi vế khoảng 3% — đổi chữ trong CTA_WORDS hay đổi phông thì
   phải đo lại hai con số trên. Trần 52px cho khổ 600–640: ở đó container đã đủ
   rộng, dòng 1 không gãy nữa và CTA trở lại hai dòng như màn lớn. */
@media (max-width: 640px) {
	.cta__h { font-size: clamp(30px, 10.3vw, 52px); }

	/* Chỗ gãy dòng KHÔNG thả nổi theo cỡ chữ: splitLines đo chữ trần, không
	   biết mũi tên ::after chiếm thêm 1.09em, nên nếu để "Let's build
	   something" vừa khít khung thì nó đo ra một dòng rồi dựng lại thành hai —
	   dòng tràn, mất cả hiệu ứng trượt. Bóp bề ngang khối chữ lại thì phép đo
	   và bản dựng nhìn cùng một khung: luôn ra "Let's build" / "something".
	   74% khung ứng với 62% chỗ mà dòng hai (chữ + mũi tên) thật sự cần. */
	.cta__link { width: 100%; }
	.cta__lead { max-width: 74%; }

	/* Mũi tên rời (phần tử .cta__arrow) nằm cạnh CẢ khối chữ nên khi dòng 1 gãy
	   đôi nó bị đẩy ra tít mép phải, cách chữ "something" cả trăm pixel. Thay
	   bằng ::after của DÒNG CUỐI trong khối chữ — nó là một ô inline nên bám
	   sát chữ dù dòng gãy ở đâu. Hình vẫn là arrow-right.svg, đắp làm mặt nạ
	   cho nền currentColor nên vẫn đổi màu theo chữ. */
	.cta__arrow { display: none; }
	.cta__lead .ln:last-child::after {
		content: '';
		display: inline-block;
		width: 0.95em;
		height: 0.95em;
		margin-left: 0.14em;
		/* Canh theo giữa chiều cao chữ thường, đúng mốc mắt đọc */
		vertical-align: middle;
		background: currentColor;
		--arr: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Cpath d='M5 12H19' stroke='%23000' stroke-width='2' stroke-linejoin='round'/%3E%3Cpath d='M12 5L19 12L12 19' stroke='%23000' stroke-width='2'/%3E%3C/svg%3E");
		-webkit-mask: var(--arr) center / contain no-repeat;
		mask: var(--arr) center / contain no-repeat;
		/* Trồi lên cùng nhịp với ký tự cuối của dòng, không hiện sẵn */
		transform: translateY(105%);
		transition: transform var(--d-char) var(--ease-out);
		transition-delay: calc(var(--stagger-line) + 9 * var(--stagger-char));
	}
	.is-in .cta__lead .ln:last-child::after { transform: none; }
	/* Gạch chân hover là chuyện của màn có chuột; ở đây dòng 1 gãy đôi nên
	   thanh gạch (absolute, trải trọn bề ngang) sẽ vắt ngang giữa hai dòng. */
	.cta__lead::after { display: none; }
}

/* --------------------------------------------------------------------------
   FOOTER — bố cục học footer pear.no: cao đúng một màn hình, cột giữa có
   khung, đường lưới hairline kéo từ cạnh khung ra tới mép màn hình. Mọi
   vị trí đều tính từ ba biến dưới đây nên đường lưới luôn khớp cạnh khung.
   -------------------------------------------------------------------------- */

.ft {
	/* MỘT cỡ chữ cho cả footer. Trước đây có tới bốn cỡ chen nhau (--ft-sm cho
	   hai cột bên, --t-xs cho dòng mời đăng ký, --t-xxs cho ô nhập và dải dưới
	   cùng, lại thêm class .t-xxs viết thẳng trong markup) nên nhìn lệch bậc.
	   Luật `.ft .t-xxs, .ft .t-xs` bên dưới đè luôn mấy class đó. */
	--ft-sm: var(--t-xs);
	font-size: var(--ft-sm);
	--ftw: clamp(340px, 30vw, 540px);   /* bề ngang cột giữa */
	--ft-t: max(88px, 13svh);           /* vạch ngang trên, tính từ đỉnh */
	--ft-b: max(64px, 10svh);           /* vạch ngang dưới, tính từ đáy */
	position: relative;
	z-index: 2;
	height: max(640px, 100svh);
	overflow: hidden;
	isolation: isolate;
}

/* Nền trong suốt, chỉ phủ quầng lửa lên: nền cam và hạt nhiễu của trang vẫn
   lộ ra, bật nền tối cũng tự đổi theo. Các cột dọc gợi lại cảnh WebGL ở hero. */
/* Nền footer đi theo nền trang — không còn quầng lửa lẫn dải sọc. Giữ .ft__bg
   trong markup cho khỏi phải đụng build.py, nhưng nó không vẽ gì nữa. */
.ft__bg { display: none; }

/* Đường lưới tự vẽ ra, mỗi đường có vạch kích hoạt riêng.
   Khung ngoài (.ft__line) KHÔNG transform: vạch kích hoạt đo top của chính
   phần tử, mà một đường dọc co về 0 theo gốc dưới thì hộp đo dồn xuống đáy
   footer (đo được top = 900 trên màn 900) nên không bao giờ chạm vạch.
   Phần co giãn nằm ở thẻ <i> bên trong. */
.ft__line { position: absolute; z-index: 1; pointer-events: none; }
.ft__line > i {
	position: absolute;
	inset: 0;
	background: var(--hairline);
	transition: transform 1.6s var(--ease-out);
}
.ft__line--t, .ft__line--b { left: 0; right: 0; height: 1px; }
.ft__line--t { top: var(--ft-t); }
.ft__line--b { bottom: var(--ft-b); }
.ft__line--t > i { transform: scaleX(0); transform-origin: left; }
.ft__line--b > i { transform: scaleX(0); transform-origin: right; }
.ft__line--l, .ft__line--r { top: 0; bottom: 0; width: 1px; }
.ft__line--l { left: calc(50% - var(--ftw) / 2); }
.ft__line--r { right: calc(50% - var(--ftw) / 2); }
/* Hai đường dọc mọc từ dưới lên THEO CUỘN: JS ghi --ftp = phần footer đã lộ ra
   (0 khi đỉnh footer chạm đáy khung nhìn, 1 khi footer lộ trọn). Không transition. */
.ft__line--l > i, .ft__line--r > i {
	transform: scaleY(var(--ftp, 0));
	transform-origin: bottom;
	transition: none;
}
.ft__line--t.is-in > i, .ft__line--b.is-in > i { transform: none; }
@media (prefers-reduced-motion: reduce) { .ft__line > i { transform: none !important; } }

.ft__frame {
	position: absolute;
	z-index: 2;
	left: calc(50% - var(--ftw) / 2);
	width: var(--ftw);
	top: var(--ft-t);
	bottom: var(--ft-b);
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-1);
	padding: clamp(24px, 2.4vw, 40px);
	text-align: center;
}
.ft__logo svg { display: block; width: calc(var(--ftw) * 0.5); height: auto; }
/* Chỉ còn viền, ruột đổ 10% đúng bằng lớp kính của thanh nav (--glass-bg).
   non-scaling-stroke: nét luôn 1px dù logo co giãn theo --ftw. */
.ft__logo svg path {
	fill: rgba(var(--ink-rgb), 0.14);
	stroke: rgba(var(--ink-rgb), 0.5);
	stroke-width: 1.2;
	vector-effect: non-scaling-stroke;
}
/* Nền tối và nền sáng: logo vẫn nhạt nhưng mang sắc cam của thương hiệu.
   Nền cam thì giữ mực trắng — cam trên cam là mất hút. */
body.is-dark .ft__logo svg path,
body.is-light .ft__logo svg path {
	fill: rgba(var(--flame-rgb), 0.16);
	stroke: rgba(var(--flame-rgb), 0.62);
}

.ft__nl { width: 100%; display: flex; flex-direction: column; gap: 0.8rem; }
.ft__nl form {
	display: flex;
	align-items: center;
	gap: 0.7rem;
	padding-bottom: 0.6rem;
	border-bottom: 1px solid var(--hairline);
}
.ft__nl form.is-sent { border-bottom: 0; padding-bottom: 0; }
.ft__nl input { flex: 1; min-width: 0; background: none; border: 0; font-size: var(--ft-sm); }
.ft__nl input::placeholder { color: var(--dim); }
.ft__nl input:focus { outline: none; }

.ft__contact {
	width: 100%;
	display: flex;
	justify-content: space-between;
	gap: 1rem;
	/* Lùi xuống bằng cỡ chữ cột Social bên ngoài; dòng mời đăng ký phía trên
	   mới là dòng chính của khung. */
	font-size: var(--ft-sm);
	text-align: left;
}
.ft__contact a { transition: opacity 0.3s var(--ease); }
.ft__contact a:hover { opacity: 0.62; }

/* Hai ô lưới hai bên cột giữa, canh ngay dưới vạch ngang trên */
.ft__side {
	position: absolute;
	z-index: 2;
	top: calc(var(--ft-t) + var(--sp-1));
	display: flex;
	gap: var(--sp-2);
}
.ft__side--l { left: var(--edge); }
.ft__side--r { right: var(--edge); }
/* Chữ nhỏ hơn một bậc so với cụm email trong khung — cụm đó giữ nguyên t-xs */
.ft__col { display: flex; flex-direction: column; gap: 0.6rem; }
/* Mọi cỡ chữ trong footer về một mối, kể cả class đặt thẳng trong markup */
.ft .t-xxs,
.ft .t-xs,
.ft__col,
.ft__base,
.ft__contact,
.ft__nl > span,
.ft__mail { font-size: var(--ft-sm); }
.ft__col a { transition: opacity 0.3s var(--ease); }
.ft__col a:hover { opacity: 0.62; }

/* Dải dưới cùng, nằm giữa vạch ngang dưới và đáy màn hình. Góc phải để trống
   cho nút đổi nền. translate (longhand) để không đè transform của data-rise. */
.ft__base {
	position: absolute;
	z-index: 2;
	left: var(--edge);
	bottom: calc(var(--ft-b) / 2);
	translate: 0 50%;
	display: flex;
	align-items: center;
	gap: 1.8rem;
}
.ft__base a { transition: opacity 0.3s var(--ease); }
.ft__base a:hover { opacity: 0.62; }

/* --------------------------------------------------------------------------
   ABOUT — hero rải ảnh (học serious.business), khối kể chuyện, số liệu, người
   -------------------------------------------------------------------------- */

.ab-hero__pin {
	position: relative;
	height: 100svh;
	overflow: hidden;
}

/* Ảnh rải: mỗi cái một vị trí/cỡ/góc riêng đặt inline, mở ra so le khi vào trang.
   Xoay đặt ở đây (transform), lớp mở dùng clip-path nên hai thứ không đá nhau. */
.ab-hero__img {
	position: absolute;
	z-index: 1;
	transform: rotate(var(--rot, 0deg));
	transition-delay: calc(var(--i, 0) * 90ms);
}
/* Ảnh để trần, không khung — giống vệt trail. Nguồn có cả bản màu lẫn trắng
   đen nên ép hết về một tông cho khỏi lệch. */
.ab-hero__img { overflow: hidden; }
.ab-hero__img > img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* --- Vệt ảnh chạy theo con trỏ ------------------------------------------
   Kho ảnh nằm sẵn trong DOM, JS chỉ đặt left/top rồi bật .is-on; hết hạn thì
   tắt. Không tạo/xoá node nên không giật. */
.ab-trail {
	position: absolute;
	inset: 0;
	z-index: 2;
	overflow: hidden;
	pointer-events: none;
	display: none;
}
/* Không khung, không đệm — ảnh trần. Cỡ và tỉ lệ đặt inline, mỗi tấm một kiểu. */
.ab-trail__i {
	position: absolute;
	top: 0;
	left: 0;
	overflow: hidden;
	transform: translate(-50%, -50%) rotate(var(--r, 0deg));
	/* Hiện/mất là TẮT PHỰT, không transition — mềm mại là hỏng cái chất của vệt */
	visibility: hidden;
}
.ab-trail__i > img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}
.ab-trail__i.is-on { visibility: visible; }

/* Vệt trail chỉ ở màn rộng có hover; khổ hẹp / cảm ứng dùng mảng rải tĩnh */
@media (min-width: 1100px) and (hover: hover) {
	.ab-trail { display: block; }
	.ab-hero__img { display: none; }
}

.ab-hero__text {
	position: absolute;
	left: var(--edge);
	right: var(--edge);
	top: 50%;
	transform: translateY(-50%);
	z-index: 4;
	pointer-events: none;
}
.ab-hero__text .label { display: block; margin-bottom: 1.6rem; }
/* Châm ngôn ngắn nên để một dòng, cỡ lớn nhất, không giới hạn bề ngang */
.ab-hero__motto { max-width: none; letter-spacing: -0.035em; }

/* --- Who we are ----------------------------------------------------------- */

/* Nhãn cột trái hẹp, chữ và ảnh cùng nằm ở cột phải */
.ab-who {
	display: grid;
	grid-template-columns: minmax(150px, 30%) 1fr;
	column-gap: 3vw;
	align-items: start;
}
.ab-who .label { grid-column: 1; padding-top: 0.5em; }
.ab-who__lead { grid-column: 2; max-width: 22ch; }

/* Ảnh bắt đầu ở mép trái cột chữ, kết thúc ở mép phải container (có lề) */
.ab-who__shot {
	grid-column: 2;
	margin-top: var(--sp-3);
	aspect-ratio: 21 / 9;
	overflow: hidden;
}
.ab-who__shot > img { width: 100%; height: 100%; object-fit: cover; }

/* Ảnh lớn: gần hết bề ngang nhưng vẫn chừa lề container */
.ab-wide { aspect-ratio: 21 / 9; overflow: hidden; }
.ab-wide > img { width: 100%; height: 100%; object-fit: cover; }

/* --- Danh sách người ------------------------------------------------------ */

.ab-team__head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 3vw;
	margin-bottom: var(--sp-2);
}
.ab-team__head > div:first-child { flex: 1; }
.ab-team__head h2 { max-width: 22ch; }
.ab-team__hint { flex: none; }

.ab-team { border-top: 2px solid var(--ink); }

.mem {
	position: relative;
	display: grid;
	grid-template-columns: minmax(56px, 6%) 1fr minmax(180px, 24%);
	gap: 3.4vw;
	align-items: baseline;
	padding-block: var(--sp-1);
	border-bottom: 1px solid var(--hairline);
}
.mem__name { line-height: 1.02; transition: opacity 0.4s var(--ease); }

/* Lăn chữ khi hover — cùng kỹ thuật với nút "Start a project" (.roll):
   dòng chữ nằm trong khung cắt, bản sao đặt ngay dưới, hover thì đẩy cả cụm
   lên 100% nên bản sao trồi lên đúng chỗ bản gốc.
   splitLines đã tạo sẵn .ln (overflow:hidden) > i, chỉ cần gắn thêm ::after. */
.mem__name .ln > i { position: relative; }
/* .ln chừa thêm 0.16em dưới đáy cho đuôi chữ (g, y, p), nên khung cắt CAO HƠN
   <i> đúng 0.16em. Đẩy -100% là thiếu bằng đúng khoảng đó, phần đuôi của bản cũ
   còn sót lại trong khung. Phải đi trọn chiều cao khung, và bản sao cũng phải
   đặt xuống thấp thêm đúng ngần ấy thì mới trồi lên khít. */
.mem__name .ln > i::after {
	content: attr(data-t);
	position: absolute;
	left: 0;
	top: calc(100% + var(--roll-tail));
}
/* Đè lên .is-in .ln > i (2 class) — chọn lọc cao hơn nên thắng */
.mem .mem__name .ln > i {
	transition: transform var(--d-roll) var(--ease-text);
	transition-delay: 0s;
}
.mem:hover .mem__name .ln > i { transform: translateY(calc(-100% - var(--roll-tail))); }
.mem__role { text-align: right; line-height: var(--lh-body); }
/* Màn rộng đã có ảnh bay theo con trỏ (data-cursor-img) nên ảnh dán cứng này
   chỉ dành cho khổ hẹp — xem khối ≤640px. */
.mem__ph { display: none; }

/* Rê vào một người thì những người còn lại mờ đi — dồn chú ý vào đúng một tên */
.ab-team:hover .mem:not(:hover) .mem__name { opacity: 0.34; }

/* ==========================================================================
   TRANG CON — Services / quy trình / Works / Blog
   ========================================================================== */

/* --- Đầu trang dùng chung ------------------------------------------------- */

/* base.css có nhịp chung `main > .section:first-child { margin-top: --sec-gap }`
   (216px ở 1440). Với trang con thì đó là một màn gần như trống trước khi thấy
   tiêu đề. Bộ chọn này cùng độ chọn lọc (0,2,1) nhưng sections.css nạp sau
   base.css nên thắng. */
main > .phero:first-child { margin-top: max(132px, 10vw); }

.phero__h { margin-top: 1.6rem; max-width: 18ch; }
.phero__lead { margin-top: var(--sp-1); max-width: 46ch; }
.phero__tags { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: var(--sp-2); }

/* --- Hero trang quy trình: căn giữa, rồi dải ảnh ló nửa dưới màn -----------
   Khối chữ cao đúng (100svh − nửa dải − lề trên) và canh giữa theo chiều dọc
   trong khoảng đó, nên lúc mở trang dải ảnh luôn ló ra đúng một nửa, màn cao
   hay thấp cũng vậy. --strip-h là chiều cao dải. */
:root { --strip-h: clamp(260px, 30vw, 480px); }
main > .phero--c:first-child {
	margin-top: 0;
	min-height: calc(100svh - var(--strip-h) / 2);
	padding-block: max(112px, 8vw) var(--sp-2);
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	text-align: center;
}
.phero--c .phero__h { margin-top: 0; max-width: none; }
.phero--c .phero__lead { max-width: 40ch; margin-inline: auto; }
/* data-split dựng mỗi dòng thành một khối riêng — căn giữa từng dòng */
.phero--c .ln { text-align: center; }

main > .phero--c + .strip { margin-top: 0; }
.strip { overflow: hidden; }
.strip__track {
	display: flex;
	align-items: center;
	gap: max(14px, 1.2vw);
	height: var(--strip-h);
	width: max-content;
	padding-inline: var(--edge);
	/* Trôi sang trái khi cuộn qua. --sp do vòng parallax ghi (0 → 1 lúc dải
	   đi từ đáy tới đỉnh khung nhìn) — dịch tối đa 24vw. */
	translate: calc(var(--sp, 0) * -24vw) 0;
}
.strip__i {
	flex: none;
	height: var(--h);
	aspect-ratio: var(--ar);
	overflow: hidden;
	/* Vào trang: từng tấm mở từ dưới lên, so le theo thứ tự */
	clip-path: inset(100% 0 0 0);
	animation: strip-in 1.4s var(--ease-out) forwards;
}
.strip__i:nth-child(2) { animation-delay: 0.08s; }
.strip__i:nth-child(3) { animation-delay: 0.16s; }
.strip__i:nth-child(4) { animation-delay: 0.24s; }
.strip__i:nth-child(5) { animation-delay: 0.32s; }
.strip__i:nth-child(6) { animation-delay: 0.40s; }
.strip__i:nth-child(n+7) { animation-delay: 0.48s; }
@keyframes strip-in { to { clip-path: inset(0 0 0 0); } }
@media (prefers-reduced-motion: reduce) {
	.strip__i { animation: none; clip-path: none; }
	.strip__track { translate: none; }
}
.strip__i img { width: 100%; height: 100%; object-fit: cover; }
#deliver .phero__tags { margin-top: 0; }

/* --- Hero trang Services: chữ / ( video ) / chữ --------------------------
   Scene ghim, --p do JS ghi. p = 0 đúng bố cục tĩnh: khung video 37vw căn
   giữa, hai ngoặc ôm sát hai bên, hai dòng chữ trên và dưới. Cuộn xuống thì
   khung mở ra tràn màn (clip-path, KHÔNG scale để video khỏi nhoè), ngoặc bị
   đẩy văng ra ngoài, chữ trôi đi và mờ dần. */
.sv-hero { height: 190svh; }
.sv-hero__pin {
	--vw-w: 31vw;                               /* bề ngang khung lúc đầu */
	--vw-h: calc(var(--vw-w) * 0.5825);         /* 747 × 435 như bản mẫu */
	--gap-y: max(26px, 2.9vw);                  /* chữ cách khung */
	--q: clamp(0, calc(var(--p) * 1.25), 1);    /* xong sớm hơn cuối cảnh một chút */
	position: sticky;
	top: 0;
	height: 100svh;
	overflow: hidden;
}
.sv-hero__media {
	position: absolute;
	inset: 0;
	--ix: calc((100vw - var(--vw-w)) / 2 * (1 - var(--q)));
	--iy: calc((100svh - var(--vw-h)) / 2 * (1 - var(--q)));
	clip-path: inset(var(--iy) var(--ix));
	background: rgba(var(--ink-rgb), 0.12);
}
.sv-hero__media video { width: 100%; height: 100%; object-fit: cover; }
/* Ngoặc là SVG chứ không phải chữ "(" — tâm hình trùng tâm hộp nên căn theo
   tâm khung video là khớp thật, còn glyph thì tâm quang học nằm lệch trong hộp
   dòng. Cao 0.34 lần chiều cao khung, bề ngang tự theo tỉ lệ 26:95. */
.sv-hero__p {
	position: absolute;
	top: 50%;
	display: block;
	height: calc(var(--vw-h) * 0.4);
	opacity: calc(1 - var(--q) * 1.6);
}
.sv-hero__pi { display: block; height: 100%; width: auto; }
/* Mép trong của ngoặc cách mép khung một nhịp cố định theo chiều cao khung */
.sv-hero__p--l {
	right: calc(50% + var(--vw-w) / 2 + var(--vw-h) * 0.085);
	transform: translate(calc(var(--q) * -40vw), -50%);
}
.sv-hero__p--r {
	left: calc(50% + var(--vw-w) / 2 + var(--vw-h) * 0.085);
	transform: translate(calc(var(--q) * 40vw), -50%);
}
/* Chữ nhỏ hơn hẳn --t-xxl để tương phản với khung video. */
.sv-hero__t {
	position: absolute;
	left: 0;
	right: 0;
	font-size: max(34px, 4.4vw);
	text-align: center;
	white-space: nowrap;
	opacity: calc(1 - var(--q) * 1.8);
}
.sv-hero__t .ln { text-align: center; }
/* Khoảng hở TRÔNG THẤY phải bằng nhau trên dưới, mà hộp dòng thì không đối
   xứng: dưới chân chữ còn 0.2em chỗ trống cho đuôi chữ, trên đỉnh chữ hoa còn
   (ascender 1.0 − cap-height 0.73) = 0.27em. Vì vậy kéo dòng trên xuống 0.2em
   và dòng dưới lên 0.27em thì hai khoảng hở mới thật sự bằng nhau. */
.sv-hero__t--top {
	bottom: calc(50% + var(--vw-h) / 2 + var(--gap-y) - 0.2em);
	transform: translateY(calc(var(--q) * -30svh));
}
.sv-hero__t--bot {
	top: calc(50% + var(--vw-h) / 2 + var(--gap-y) - 0.27em);
	transform: translateY(calc(var(--q) * 30svh));
}
/* Chuyển động giảm: giữ nguyên bố cục tĩnh, không mở khung */
@media (prefers-reduced-motion: reduce) {
	.sv-hero { height: auto; }
	.sv-hero__pin { --q: 0; }
}

/* --- Hero trang Works: một dòng, căn giữa, chữ văng khi rê chuột ----------- */
.wk-hero {
	display: grid;
	place-items: center;
	min-height: 78svh;
	padding: max(112px, 8vw) var(--edge) 0;
	text-align: center;
}
.wk-hero__h { letter-spacing: -0.035em; }
.wk-hero__h .ln { text-align: center; }
/* Sau khi reveal xong JS mới gắn .is-free: mở mặt nạ để ký tự bay ra được */
.wk-hero__h.is-free .ln { overflow: visible; }
.wk-hero__h .w { display: inline-block; }

/* --- Hàng dịch vụ: tên + "See the process" là hai lối vào -------------------- */

/* Mũi tên cạnh tên — cách canh y hệt mũi tên CTA: align-items: center đặt
   nó giữa HỘP DÒNG, rồi hạ thêm 0.144em để tâm mũi tên rơi đúng giữa chiều
   cao chữ thường ((ascender − descender) / 2 − x-height / 2 của Aeonik). Tên
   chỉ có một dòng nên giữa hộp dòng cũng là giữa khối. */
.svc__name a { display: inline-flex; align-items: center; gap: 0.1em; }
.svc__name [data-split] { display: inline-block; }
.svc__arr {
	position: relative;
	top: 0.144em;
	flex: none;
	width: 0.95em;
	height: 0.95em;
	transition: transform var(--d-roll) var(--ease-text);
}
.svc__name a:hover .svc__arr { transform: translate(0.08em, -0.08em); }

.svc__go {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	margin-top: 0.4rem;
	color: var(--ink);
}
/* Gạch chân chữ. Đặt trên từng lớp chữ của .roll (cả bản sao ::after — phần tử
   absolute không được kế thừa gạch chân của cha nên phải khai riêng). Khoảng
   cách 0.2em nằm gọn trong khung cắt của .roll (đuôi chữ chừa 0.18em). */
.svc__go .roll span,
.svc__go .roll span::after {
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.2em;
}
.svc__go svg { transition: transform 0.45s var(--ease-out); }
.svc__go:hover svg { transform: translate(4px, -4px); }

/* --- Xếp chồng (học B2B Branding Services của serious.business) ------------
   Mỗi tấm dính ở mép trên, tấm sau dính thấp hơn tấm trước một nấc nên mép
   trên (kẻ 2px) của các tấm đã qua vẫn ló ra như gáy sổ. Tấm bị phủ lùi lại
   và tối dần theo --cover do JS đo (updateStacks). Nền phải ĐẶC — trong suốt
   thì tấm dưới hiện xuyên qua. Chỉ bật khi màn đủ rộng và đủ cao để một tấm
   nằm trọn trong khung nhìn; tấm cao hơn khung thì dính là mất nửa dưới. */
@media (min-width: 1001px) and (min-height: 700px) {
	.svc-stack .svc {
		position: sticky;
		top: calc(var(--sp-1) + var(--k) * max(14px, 1vw));
		padding-bottom: var(--sp-1);
		/* Nền tràn tới hai mép màn hình (như các tấm của serious.business) mà
		   không nới hộp: một lớp nền giả tràn hai bên, clip-path chỉ giữ phần
		   ngang. Trước đây là box-shadow 0 0 0 100vmax — bóng khổng lồ đó phải
		   vẽ lại mỗi khung vì --cover đổi trên chính tấm này, là một nửa lý do
		   tụt khung ở hàng SEO / AI & GEO (xem README). */
		clip-path: inset(0 -100vmax);
	}
	/* sticky đã tạo stacking context nên z-index -1 nằm dưới nội dung tấm,
	   trên nền trang. clip-path chỉ cắt phần VẼ, lớp nền giả vẫn nới vùng cuộn
	   ngang (scrollTo(500, y) cuộn được) — nên main cắt tràn ngang bằng clip
	   (clip không tạo khung cuộn, sticky vẫn chạy). */
	main { overflow-x: clip; }
	.svc-stack .svc::before {
		content: "";
		position: absolute;
		inset: 0 -100vmax;
		z-index: -1;
		background: var(--ground);
		transition: background-color 0.7s var(--ease);
		pointer-events: none;
	}
	.svc-stack .svc + .svc { margin-top: calc(var(--sp-2) - var(--sp-1)); }
	/* Tấm đã bị phủ kín chỉ còn ló mép trên (một dải --k × 1vw, nằm trong
	   padding-top) — hình và chữ ở dưới dải đó, ẩn đi không ai thấy. */
	.svc-stack .svc.is-buried .svc__art,
	.svc-stack .svc.is-buried .svc__body { visibility: hidden; }
	.svc-stack .svc__in {
		transform-origin: 50% 0;
		/* Lớp riêng: lùi + mờ chỉ là ghép lớp trên GPU, không vẽ lại hình và
		   chữ của tấm mỗi khung (nửa lý do còn lại của tụt khung). */
		will-change: opacity, scale;
		scale: calc(1 - var(--cover, 0) * 0.05);
		opacity: calc(1 - var(--cover, 0) * 0.7);
	}
}

/* --- Các bước quy trình ---------------------------------------------------- */

.steps__g { display: block; margin-top: var(--sp-3); }
.step {
	display: grid;
	grid-template-columns: minmax(72px, 7%) minmax(0, 1fr) minmax(0, 46%);
	gap: 3.4vw;
	align-items: baseline;
	padding-top: 2rem;
	border-top: 1px solid var(--hairline);
	margin-top: 2rem;
}
/* KHÔNG đặt max-width cho .step__d nữa: bề rộng do chính cột thứ ba quyết định,
   thêm max-width vào là đoạn chữ lại co về trái trong cột. */
.step__d { max-width: none; }

/* --- Danh sách đánh số (What you get / Who it's for) ----------------------- */

.lst { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 3.4vw; }
.lst__i {
	display: grid;
	grid-template-columns: minmax(52px, 13%) minmax(0, 1fr);
	gap: 1.4vw;
	align-items: baseline;
	padding-top: 1.4rem;
	border-top: 1px solid var(--hairline);
	margin-top: 1.4rem;
}

/* --- Giá trị (trang Services) ---------------------------------------------- */

.vals { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 3.4vw; }
.val {
	display: flex;
	flex-direction: column;
	gap: 0.9rem;
	padding-block: var(--sp-1);
	border-top: 1px solid var(--hairline);
}

/* --- Ba dịch vụ còn lại ---------------------------------------------------- */

.rel { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 3.4vw; }
.rel__i {
	display: flex;
	flex-direction: column;
	gap: 0.9rem;
	padding-top: 1.6rem;
	border-top: 2px solid var(--ink);
}
.rel__d { max-width: 30ch; }
.rel__go {
	margin-top: 0.4rem;
	opacity: 0.6;
	transition: transform 0.45s var(--ease-out), opacity 0.35s var(--ease);
}
.rel__i:hover .rel__go { transform: translate(4px, -4px); opacity: 1; }

/* --- Vì sao là Align (bốn cột, kiểu humaan) -------------------------------- */

.why {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--sp-2) 2vw;
	margin-top: var(--sp-3);
}
.why__i { display: flex; flex-direction: column; gap: 1rem; padding-top: 1.6rem; }
.why__h { max-width: 18ch; }
.why__i p { max-width: 34ch; }

/* --- Ba con số (kiểu stormbrain) ------------------------------------------
   Thẻ trong hàng CAO BẰNG NHAU (grid stretch), số nằm sát mép trên còn chữ bị
   đẩy xuống đáy bằng margin-top:auto — nên mọi nhãn thẳng hàng nhau dù câu đỡ
   dài ngắn khác nhau. */

.proof {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: max(14px, 1.2vw);
	margin-top: var(--sp-3);
}
.proof__i {
	display: flex;
	flex-direction: column;
	gap: 0.8rem;
	padding: max(26px, 2.2vw);
	border: 1px solid var(--hairline);
	background: rgba(var(--ink-rgb), 0.03);
}
/* KHÔNG dùng --t-xxxl: cỡ đó là cỡ tên trang, "7–9 wks" sẽ tràn cột 1/3. */
.proof__n {
	font-size: clamp(38px, 5.4vw, 92px);
	line-height: 0.88;
	letter-spacing: -0.04em;
}
.proof__l { margin-top: auto; padding-top: 1.2rem; max-width: 24ch; }
.proof__i p { max-width: 36ch; }

/* --- Hỏi đáp --------------------------------------------------------------
   <details> thật, không phải accordion tự chế: mở được khi JS hỏng, khi in ra
   giấy, và Ctrl+F của trình duyệt tìm thấy chữ nằm trong phần đang đóng. */

.qa { margin-top: var(--sp-2); border-top: 1px solid var(--hairline); }
.qa__i { border-bottom: 1px solid var(--hairline); }
.qa__q {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 3vw;
	padding-block: max(20px, 1.5vw);
	cursor: pointer;
	list-style: none;
}
/* Safari cũ vẫn vẽ tam giác qua pseudo-element riêng */
.qa__q::-webkit-details-marker { display: none; }
.qa__t { max-width: 54ch; }
.qa__ic {
	position: relative;
	flex: none;
	width: 15px;
	height: 15px;
	margin-top: 0.4em;
}
.qa__ic::before,
.qa__ic::after {
	content: '';
	position: absolute;
	inset: 0;
	margin: auto;
	background: var(--ink);
}
.qa__ic::before { width: 100%; height: 1.5px; }
/* Mở ra thì thanh dọc co lại: dấu cộng thành dấu trừ. Không xoay cả cụm —
   xoay 90° thì cái còn lại dựng đứng, ra vẫn là một vạch dọc. */
.qa__ic::after {
	width: 1.5px;
	height: 100%;
	transition: transform 0.4s var(--ease-out);
}
.qa__i[open] .qa__ic::after { transform: scaleY(0); }
.qa__a { padding-bottom: max(20px, 1.5vw); }
.qa__a p { max-width: 70ch; }

/* Tag đánh giá Clutch nằm ở ô phải của .svc-head */
/* Băng ảnh ngang trước tường logo ở trang dịch vụ. Cùng khuôn với ảnh lớn
   trang About. Khối "In practice" bên trên dùng lại nguyên bộ class .svc của
   "What we do" nên không có CSS riêng, trừ một dòng cho ảnh ở .svc__art. */
.sv-wide { aspect-ratio: 21 / 9; overflow: hidden; }
.sv-wide > img { width: 100%; height: 100%; object-fit: cover; }

.cl-rate { display: flex; }

/* --- Nút lọc (Works + Blog) ------------------------------------------------ */

.filter { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.filter__b {
	display: inline-flex;
	align-items: center;
	height: max(34px, 2.5vw);
	padding: 0 max(14px, 1.05vw);
	border: 1px solid var(--hairline);
	border-radius: var(--radius-pill);
	font-size: var(--t-xxs);
	line-height: 1;
	color: var(--body);
	transition: background-color 0.35s var(--ease), border-color 0.35s var(--ease),
	            color 0.35s var(--ease);
}
.filter__b:hover { background: rgba(var(--ink-rgb), 0.08); }
/* Nút đang bật đảo màu: mực làm nền, nền làm chữ — chạy đúng ở cả ba theme mà
   không cần khai riêng cho từng cái. */
.filter__b.is-on { background: var(--ink); border-color: var(--ink); color: var(--ground); }

/* Thẻ bị lọc ra. Dùng class chứ không phải [hidden]: base.css không đặt
   display cho [hidden] mà .work-card/.post lại là flex, flex thắng hidden. */
.is-off { display: none !important; }

/* --- Lưới dự án (Works + Selected work trang chủ) ---------------------------
   Mỗi hàng là lưới bốn cột bằng nhau; thẻ chiếm --span cột (featured 4, big 2,
   small 1) nên cột các hàng thẳng nhau. Khung cắt riêng theo hạng (--ar) nên
   thẻ trong hàng cao thấp khác nhau, mép trên thẳng (align-items: start). */
main > .wk-hero + .section { margin-top: var(--sp-2); }
.wk-grid { display: flex; flex-direction: column; gap: var(--sp-2); }
.wk-row {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--sp-2) max(14px, 1.2vw);
	align-items: start;
}
.wk-row .work-card { grid-column: span var(--span, 1); min-width: 0; }
.wk-row .work-card__media { aspect-ratio: var(--ar); }
/* Tên có thể dài (Hung Yen Knitting & Dyeing) trong thẻ hẹp — cho xuống dòng */
.wk-row .work-card__meta { flex-wrap: wrap; row-gap: 0.2rem; }
.wk-row .work-card__media img { transition: scale 1.1s var(--ease-out); }
.wk-row .work-card:hover .work-card__media > img { scale: 1.04; }

/* --- Kho việc: rê vào dòng nào con trỏ thành thumbnail dự án đó ------------ */

.arch { border-top: 2px solid var(--ink); }
.arch__i {
	display: grid;
	grid-template-columns: minmax(52px, 6%) minmax(0, 1fr) minmax(0, 22%) auto;
	gap: 3.4vw;
	align-items: baseline;
	padding-block: max(18px, 1.3vw);
	border-bottom: 1px solid var(--hairline);
	transition: opacity 0.4s var(--ease);
}
.arch:hover .arch__i:not(:hover) { opacity: 0.38; }
.arch__go { width: max(15px, 1vw); opacity: 0.5; transition: opacity 0.35s var(--ease); }
.arch__go svg { width: 100%; height: auto; }
.arch__i:hover .arch__go { opacity: 1; }

/* --- Lưới bài viết trang Blog ---------------------------------------------- */

/* Không còn hero: trang mở thẳng vào tiêu đề danh sách, lề trên như .phero */
main > .blog-top:first-child { margin-top: max(132px, 10vw); }
.blog-top h1 { max-width: 18ch; }
.ins__grid--all { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-3) 3.4vw; }

/* Hover thẻ bài: ảnh phóng nhẹ, tiêu đề gạch chân từng dòng (học
   serious.business/blog). Gạch là nền của từng .ln — .ln thu vừa bề ngang chữ
   (fit-content) nên gạch dài đúng bằng dòng, và nằm ở đáy phần chừa đuôi chữ
   (--roll-tail) tức ngay dưới chân g/y/p. Các dòng gạch nối đuôi nhau. */
.post__media img { transition: scale 1.8s var(--ease-out); }
.post:hover .post__media > img { scale: 1.06; transition-duration: 1.1s; }
.post__t .ln {
	width: fit-content;
	background: linear-gradient(currentColor, currentColor) no-repeat 0 100% / 0 1px;
	transition: background-size 0.7s var(--ease-out);
	transition-delay: calc(var(--i, 0) * 90ms);
}
.post:hover .post__t .ln { background-size: 100% 1px; }

/* --------------------------------------------------------------------------
   BLOG DETAIL
   -------------------------------------------------------------------------- */

.post-page__h { margin-top: 1.6rem; max-width: 20ch; }
.post-page__meta { display: flex; gap: 1.6rem; margin-top: var(--sp-1); }
.post-page__shot {
	position: relative;
	aspect-ratio: 16 / 7;
	margin-top: var(--sp-2);
	overflow: hidden;
}
.post-page__shot img { width: 100%; height: 100%; object-fit: cover; }

/* Bề rộng cột chữ khoá theo CỠ CHỮ chứ không phải ch: --t-s co giãn theo màn
   nên 34 × --t-s giữ nguyên số ký tự trên một dòng ở mọi khổ (≈68 ký tự). */
.prose {
	max-width: calc(var(--t-s) * 34);
	margin: var(--sp-3) auto 0;
	font-size: var(--t-s);
	line-height: var(--lh-body);
	color: var(--body);
}
.prose > * + * { margin-top: 1.1em; }
.prose .lead { font-size: var(--t-m); line-height: var(--lh-lead); color: var(--ink); }
.prose h2 {
	margin-top: 2.2em;
	font-size: var(--t-l);
	line-height: var(--lh-subhead);
	letter-spacing: -0.01em;
	color: var(--ink);
}
.prose h2 + * { margin-top: 1em; }
.prose strong { color: var(--ink); }
.prose em { font-style: italic; }
.prose ul { display: flex; flex-direction: column; gap: 0.7em; margin-top: 1.2em; }
.prose li { position: relative; padding-left: 1.6em; }
/* Gạch đầu dòng tự vẽ: list-style đã bị reset ở base.css cho toàn site */
.prose li::before {
	content: '';
	position: absolute;
	left: 0.2em;
	top: 0.72em;
	width: 0.6em;
	height: 1px;
	background: var(--dim);
}
.prose blockquote {
	margin-top: 2em;
	padding-left: 1.4em;
	border-left: 2px solid var(--ink);
	font-size: var(--t-m);
	line-height: var(--lh-lead);
	color: var(--ink);
}

/* --- Bài nhập từ align.vn: mấy khối mà bản mẫu viết tay chưa từng dùng --- */

/* h3 là cấp phụ trong bài: nhỏ hơn h2 một bậc, vẫn là mực đậm để quét mắt
   xuống còn thấy được cấu trúc. Bài gốc trộn h3/h4/h5 lẫn lộn nên bộ nhập gộp
   hết về một cấp — hai cấp tiêu đề là đủ cho bài dài ba nghìn chữ. */
.prose h3 {
	margin-top: 1.8em;
	font-size: var(--t-m);
	line-height: var(--lh-subhead);
	color: var(--ink);
}
.prose h3 + * { margin-top: 0.8em; }

/* Liên kết trong thân bài: gạch chân mảnh, dày lên khi rê. Không đổi màu —
   kênh mực chỉ có một màu nên màu không phải là tín hiệu dùng được ở đây. */
.prose a {
	color: var(--ink);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
	text-decoration-color: rgba(var(--ink-rgb), 0.35);
	transition: text-decoration-color 0.25s var(--ease);
}
.prose a:hover,
.prose a:focus-visible { text-decoration-color: var(--ink); }

.prose code {
	font-size: 0.92em;
	padding: 0.1em 0.35em;
	border-radius: 4px;
	background: rgba(var(--ink-rgb), 0.08);
	color: var(--ink);
}

/* Danh sách đánh số: đếm bằng counter chứ không dùng list-style, vì base.css
   đã reset list-style cho toàn site. Số căn phải để mốc chữ thẳng hàng ở cả
   mục 9 lẫn mục 10. */
.prose ol {
	display: flex;
	flex-direction: column;
	gap: 0.7em;
	margin-top: 1.2em;
	counter-reset: pr;
}
.prose ol li::before {
	counter-increment: pr;
	content: counter(pr) '.';
	top: 0;
	left: 0;
	width: 1.2em;
	height: auto;
	background: none;
	text-align: right;
	color: var(--dim);
	font-variant-numeric: tabular-nums;
}

/* Ảnh trong bài tràn rộng hơn cột chữ: cột chữ hẹp cho dễ đọc, ảnh thì không
   cần hẹp theo. Ở màn nhỏ thì về đúng bề ngang cột. */
.prose__fig {
	position: relative;
	margin-top: 2.4em;
	margin-bottom: 2.4em;
	overflow: hidden;
}
.prose__fig img { display: block; width: 100%; height: auto; }
@media (min-width: 900px) {
	.prose__fig { margin-left: -8%; margin-right: -8%; }
}

/* Bảng: cuộn ngang trên điện thoại thay vì ép cột bé lại tới mức không đọc nổi. */
.prose__tbl {
	margin-top: 1.8em;
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
}
.prose__tbl table {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--t-xs);
}
.prose__tbl th,
.prose__tbl td {
	padding: 0.7em 0.9em;
	text-align: left;
	vertical-align: top;
	border-bottom: 1px solid var(--hairline);
}
.prose__tbl th { color: var(--ink); white-space: nowrap; }

.post-page__foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 2vw;
	max-width: calc(var(--t-s) * 34);
	margin: var(--sp-3) auto 0;
	padding-top: 1.6rem;
	border-top: 1px solid var(--hairline);
}
.post-page__soc { display: flex; gap: 0.7rem; }

/* --------------------------------------------------------------------------
   CASE STUDY (project-*.html)
   -------------------------------------------------------------------------- */

main > .cs-hero:first-child { margin-top: max(132px, 10vw); }
.cs-back { display: inline-block; transition: color 0.3s var(--ease); }
.cs-back:hover { color: var(--ink); }
.cs-hero__h { margin-top: 1.6rem; }
.cs-hero__sub { margin-top: 0.6rem; max-width: 36ch; }
/* Thông tin nhanh xếp ngang, cùng kiểu với Credits */
.cs-facts {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--sp-1) max(14px, 1.2vw);
	margin-top: var(--sp-2);
}
.cs-fact {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	padding-top: 1.2rem;
	border-top: 1px solid var(--hairline);
}

/* Dải video: nền tràn hai mép (ảnh nền của dự án), video nằm giữa rộng 80%
   container — như align.vn. Không khung, không góc. */
main > .cs-hero + .cs-film { margin-top: var(--sp-2); }
.cs-film {
	padding: max(56px, 7vw) 0;
	/* ảnh nền đặt inline trên thẻ: url() trong biến CSS tính theo file CSS, sai đường dẫn */
	background: center / cover no-repeat;
}
.cs-film__v {
	width: min(80%, calc(100% - 2 * var(--gutter, 24px)));
	margin-inline: auto;
	overflow: hidden;
}
.cs-film video { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; }

/* Dự án không có phim: ảnh đầu tiên được đôn lên đây, tràn trọn hai mép, không
   nền, không đệm — nó CHÍNH LÀ dải đó. Cao tối đa 78vh để tấm ảnh dọc không
   đẩy cả phần chữ xuống dưới màn hình. */
.cs-film--img { padding: 0; background: none; }
.cs-film__img {
	position: relative;
	width: 100%;
	aspect-ratio: var(--ar, 1.6);
	max-height: 78vh;
	overflow: hidden;
}
.cs-film__img img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Đoạn chữ: nhãn cột trái, chữ cột phải rộng 60% container, sát mép phải —
   rộng hơn thì một dòng quá dài, khó đọc */
.cs { display: flex; flex-direction: column; gap: var(--sp-2); }
.cs-block {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 60%);
	gap: 3.4vw;
	padding-top: 1.4rem;
	border-top: 1px solid var(--hairline);
}
.cs-block + .cs-block { margin-top: calc(var(--sp-1) - var(--sp-2)); }
.cs-block__t { color: var(--ink); }

/* Ảnh: hàng một ảnh trọn bề ngang; hàng hai ảnh cao bằng nhau (flex-grow =
   tỉ lệ ảnh), giữ nguyên bố cục ảnh gốc — không cắt. */
/* Khe giữa các ảnh — ngang lẫn dọc — bằng đúng lề của container (--gutter),
   nên mắt đọc ra một nhịp duy nhất. Nhịp --sp-2 của .cs vẫn giữ cho khoảng
   cách CHỮ với ảnh; chỉ hai ảnh liền nhau mới kéo lại. */
.cs-row { display: flex; gap: var(--gutter); align-items: flex-start; }
.cs-row + .cs-row { margin-top: calc(var(--gutter) - var(--sp-2)); }
.cs-fig { position: relative; flex: var(--ar) 1 0%; min-width: 0; aspect-ratio: var(--ar); overflow: hidden; }
/* Ảnh đứng một mình: flex-grow = tỉ lệ ảnh, ảnh dọc (tỉ lệ < 1) chỉ lấy một
   phần khoảng trống nên không trọn hàng — ép trọn bề ngang */
.cs-fig:only-child { flex: 1 1 100%; }
.cs-fig img { display: block; width: 100%; height: 100%; object-fit: cover; }
.cs-fig video { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Trích dẫn khách trong trang dự án: chữ to, logo và tên người nói ở dưới.
   Lấy nguyên văn từ trang dự án của align.vn — không rút gọn, không biên tập. */
.cs-quote {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 60%);
	gap: 3.4vw;
	padding-top: 1.4rem;
	border-top: 1px solid var(--hairline);
}
.cs-quote__t {
	grid-column: 2;
	color: var(--ink);
	text-wrap: pretty;
}
.cs-quote__f {
	grid-column: 2;
	display: flex;
	align-items: center;
	gap: 1rem;
	margin-top: var(--sp-1);
}
.cs-quote__logo {
	width: 48px;
	height: 48px;
	flex: none;
	object-fit: contain;
}
.cs-quote__who { display: flex; flex-direction: column; gap: 0.15rem; }
.cs-quote__who .t-xs { color: var(--ink); }

@media (max-width: 860px) {
	.cs-quote { grid-template-columns: 1fr; }
	.cs-quote__t,
	.cs-quote__f { grid-column: 1; }
}

.cs-res {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--sp-1) 3.4vw;
	margin-left: 40%;  /* thẳng cột chữ của .cs-block */
}
.cs-res__i {
	display: flex;
	flex-direction: column;
	gap: 0.8rem;
	padding-top: 1.2rem;
	border-top: 1px solid var(--hairline);
}
.cs-res__i p { max-width: 38ch; }

.cs-cred {
	display: grid;
	grid-template-columns: repeat(5, minmax(0, 1fr));
	gap: var(--sp-1) max(14px, 1.2vw);
	margin-top: var(--sp-2);
}
.cs-cred__i {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	padding-top: 1.2rem;
	border-top: 1px solid var(--hairline);
}
#more .wk-grid { margin-top: var(--sp-2); }

@media (max-width: 1000px) {
	.cs-block { grid-template-columns: 1fr; gap: 1rem; }
	.cs-res { margin-left: 0; }
	.cs-cred { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
	.cs-row { flex-direction: column; }
	.cs-fig { flex: none; width: 100%; }
	.cs-res { grid-template-columns: 1fr; }
	.cs-cred { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.cs-facts { grid-template-columns: 1fr; }
	.cs-film__v { width: calc(100% - 32px); }
}

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 1000px) {
	/* Màn pixel: bớt cột cho ô khỏi bé lại thành hạt cát. Số hàng main.js tự
	   tính lại cho ô vẫn vuông. */
	.hero-pin { --pxc: 20; }

	/* --- Trang con --------------------------------------------------------- */
	.phero__h { max-width: none; }
	.why { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-1) 2.4vw; }
	.why__h, .why__i p { max-width: none; }
	.proof { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
	.proof__l, .proof__i p { max-width: none; }
	.qa__t { max-width: none; }
	/* Một cột: ảnh lên trước chữ ở MỌI hàng, kể cả hàng ngược, nếu không thì
	   hàng chẵn hàng lẻ đảo nhau nhìn như lỗi chứ không ra nhịp. */
	.svs { gap: var(--sp-2); }
	.svs__r, .svs__r--b { grid-template-columns: minmax(0, 1fr); gap: 1.6rem; }
	.svs__r .svs__fig, .svs__r--b .svs__fig { grid-column: 1; grid-row: 1; }
	.svs__r .svs__b, .svs__r--b .svs__b { grid-column: 1; grid-row: 2; }
	.svs__h, .svs__b p { max-width: none; }
	.sv-wide { aspect-ratio: 16 / 10; }
	.step { grid-template-columns: 1fr; gap: 0.7rem; }
	.step__d { max-width: none; }
	.lst { grid-template-columns: 1fr; }
	.vals { grid-template-columns: 1fr; }
	.rel { grid-template-columns: 1fr; gap: 0; }
	.rel__i { margin-top: 1.6rem; }
	.rel__d { max-width: none; }
	/* Works: lưới còn hai cột — featured và big chiếm cả hàng, small đi đôi */
	.wk-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.wk-row { grid-auto-flow: row dense; }  /* small lẻ hai bên thẻ big thì dồn thành đôi */
	.wk-row .work-card { grid-column: auto; }
	.wk-row .work-card.is-wide { grid-column: 1 / -1; }
	.ins__grid--all { grid-template-columns: 1fr; gap: 2.4rem; }
	.arch__i { grid-template-columns: minmax(44px, 14%) minmax(0, 1fr) auto; gap: 1.4rem; }
	.arch__c { display: none; }
	.post-page__shot { aspect-ratio: 4 / 3; }
	/* Hero Services: khung video rộng hơn, không thì chỉ còn 144px */
	.sv-hero__pin { --vw-w: 72vw; }
	.sv-hero__t { white-space: normal; padding-inline: var(--edge); }
	.post-page__foot { flex-direction: column; align-items: flex-start; gap: 1.2rem; }

	.hero-top { grid-template-columns: 1fr; gap: 1.6rem; }
	/* Hẹp thì xếp dọc: tiêu đề lên trước, badge + CTA xuống dưới */
	.hero-title { max-width: none; order: -1; }
	.hero-side { gap: var(--sp-1); }
	.hero-pin { --pm: 1.8333; }   /* cảnh 320svh: (320-100)/(320-200) */
	.hero-badge { margin-top: 0; }
	.stats__head { grid-template-columns: 1fr; }
	.stats__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2rem; }
	.svc__in { grid-template-columns: 1fr; gap: 2rem; }
	.appr__intro { grid-template-columns: 1fr; gap: 1.8rem; }
	.appr-head { display: none; }
	.appr-row { grid-template-columns: 1fr; gap: 1rem; }
	/* Một cột thì căn giữa sẽ thụt đoạn văn vào so với tiêu đề bước ở trên */
	.appr-row > p { width: auto; justify-self: stretch; }
	.appr-row__out { align-items: flex-start; text-align: left; }
	.work-grid { grid-template-columns: 1fr; }
	.work__counts { flex-direction: column; align-items: flex-start; gap: 1.4rem; }
	.ins__grid { grid-template-columns: 1fr; gap: 2.4rem; }
	/* Footer khổ hẹp: bỏ cảnh một-màn-hình, xếp dọc theo dòng chảy; lưới dọc
	   bám mép container, lưới ngang bám đầu khung và trên dải dưới cùng. */
	.ft {
		/* Khoảng thụt của nội dung so với hai đường dọc. Khung logo phải ăn gian
		   lại đúng chừng này để bốn góc trắng nằm TRÊN đường, không lệch vào trong. */
		--ft-pad: 20px;
		height: auto;
		/* LƯỚI hai cột chứ không phải cột dọc: Social và cụm địa điểm đứng
		   cạnh nhau nên footer ngắn đi đúng một khối (~110px). Xếp dọc cả ba
		   khối thì footer cao hơn khung nhìn, cuộn hết trang vẫn cụt mất đoạn
		   đầu (đo ở 390x844: đỉnh footer nằm ở -28px). */
		display: grid;
		/* Cột phải rộng hơn: "Remote — East Coast" dài hơn hẳn mấy tên mạng
		   xã hội bên trái, chia đôi đều là nó gãy đôi dòng. */
		grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr);
		align-items: start;
		gap: var(--sp-2);
		padding: calc(var(--sp-2) + 1px) calc(var(--edge) + var(--ft-pad)) calc(var(--sp-2) + 2.6em);
	}
	.ft__line--t { top: var(--sp-2); }
	.ft__line--b { bottom: calc(var(--sp-2) + 1.6em); }
	.ft__line--l { left: var(--edge); }
	.ft__line--r { right: var(--edge); }
	/* Lề trong của khung PHẢI đúng bằng --ft-pad: khung đã ăn gian ra ngoài
	   ngần ấy (margin âm) nên chữ trong khung mới thẳng hàng với cột Social và
	   cột địa điểm bên dưới. Cộng thêm 16px là hai bên lệch nhau đúng 16px. */
	.ft__frame { position: relative; left: auto; top: auto; bottom: auto; width: auto; margin-inline: calc(var(--ft-pad) * -1); padding: 28px var(--ft-pad); gap: var(--sp-2); order: -1; grid-column: 1 / -1; }
	.ft__side { position: static; }
	/* Việt Nam và Mỹ xếp DỌC chung một cột, cột đó nằm bên phải cột Social */
	.ft__side--r { flex-direction: column; gap: 1.6rem; }
	.ft__base { position: absolute; left: calc(var(--edge) + var(--ft-pad)); bottom: calc(var(--sp-2) / 2 + 0.3em); translate: none; flex-wrap: wrap; gap: 1.2rem; }
	/* Đầu section: xuống dòng thay vì để nút/label chen bên phải làm tiêu đề
	   bị bóp (đo ở 390px: h2 còn 210 / 176 / 134px) */
	/* --- About ------------------------------------------------------------ */
	/* .ab-who có cột minmax(260px,32%) nên ở khổ hẹp tổng vượt khung, tràn ngang */
	.ab-who { grid-template-columns: 1fr; row-gap: 1.4rem; }
	.ab-who .label, .ab-who__lead, .ab-who__shot { grid-column: 1; }
	.ab-who__lead { max-width: none; }
	.ab-who__shot { aspect-ratio: 4 / 3; }
	.ab-wide { aspect-ratio: 4 / 3; }

	/* Tên người là t-xxl3, nhét vào cột 113px thì vỡ — số, tên và vai trò xếp
	   dọc thành một cột, ảnh chân dung đứng riêng cột sát mép phải. */
	.mem {
		grid-template-columns: minmax(0, 1fr) auto;
		grid-template-areas: "num pic" "name pic" "role pic";
		gap: 0.5rem 1.2rem;
	}
	.mem__n { grid-area: num; }
	.mem__name { grid-area: name; }
	.mem__role { grid-area: role; text-align: left; }
	.mem__ph {
		grid-area: pic;
		display: block;
		align-self: center;
		width: clamp(76px, 23vw, 104px);
		height: auto;
		object-fit: cover;
	}
	.ab-team__hint { display: none; }   /* khổ hẹp không có hover */

	/* Hero khổ hẹp: cả 6 ảnh, chia ĐỀU ba trên ba dưới, chừa băng giữa cho chữ.
	   Khoá theo class — .ab-trail cũng là <div> nên nth-of-type đếm lệch. */
	/* Phải !important: style inline của bố cục desktop vẫn nằm trên thẻ, reset
	   thường sẽ thua nó và ảnh bị ghim cả left lẫn right cùng lúc. */
	.ab-hero__img {
		top: auto !important; bottom: auto !important;
		left: auto !important; right: auto !important;
	}
	.ab-hero__img--1 { left: -6vw !important;  top: 9svh !important;    width: 44vw !important; }
	.ab-hero__img--2 { right: -4vw !important; top: 10svh !important;   width: 38vw !important; }
	.ab-hero__img--3 { left: 26vw !important;  top: 19svh !important;   width: 34vw !important; }
	.ab-hero__img--4 { left: -5vw !important;  bottom: 6svh !important; width: 40vw !important; }
	.ab-hero__img--5 { right: -3vw !important; bottom: 10svh !important; width: 36vw !important; }
	.ab-hero__img--6 { left: 30vw !important;  bottom: 0svh !important; width: 32vw !important; }

	.svc-head, .ins__head, .work__head, .ab-team__head {
		flex-direction: column;
		align-items: flex-start;
		gap: 2rem;
	}
	.svc-head h2 { max-width: none; }
	.deck__lead, .deck__act, .deck__ed { left: var(--edge); right: auto; max-width: 80vw; }
	.deck__ed { display: none; }

	/* --- Khổ hẹp: hai scene collage xếp lại cho to và vào giữa ---------------
	   Toạ độ gốc đặt theo vw/svh của màn rộng, xuống 390px thì hình vừa bé vừa
	   lệch: ảnh deck tràn khỏi mép phải, vòng đồng tâm rơi hẳn xuống dưới đáy
	   pin (y=793/743), chùm đường cong còn 86×59. */

	/* Deck: bỏ tấm panel mờ trang trí, ảnh phóng to và căn giữa */
	.deck-pin div.deck__panel:nth-of-type(1) { display: none; }
	.deck-pin div.deck__panel:nth-of-type(2) {
		left: 6vw !important; top: 34svh !important; width: 88vw !important;
		height: auto !important;
	}
	/* Desktop neo góc trên trái để phần tràn là gradient; màn dọc khung gần 16:9,
	   neo giữa để cắt đều trên dưới, khỏi mất chữ "Align" ở chân slide. */
	.deck-pin div.deck__panel:nth-of-type(2) img { object-position: 50% 50% !important; }

	/* Deliverables: bỏ vòng đồng tâm (vốn đã nằm ngoài khung), năm phần tử còn
	   lại xếp thành các dải ngang, mỗi dải căn giữa */
	.forms-pin svg.forms-item:nth-of-type(2) { display: none; }
	.forms-pin svg.forms-item:nth-of-type(1) {
		left: 12vw !important; top: 3svh !important; width: 76vw !important;
	}
	.forms-pin svg.forms-item:nth-of-type(3) {
		left: 27vw !important; top: 55svh !important; width: 46vw !important;
	}
	.forms-pin div.forms-item:nth-of-type(1) {
		left: 23vw !important; top: 18svh !important; width: 54vw !important;
	}
	.forms-pin div.forms-item:nth-of-type(2) {
		left: 8vw !important; right: auto !important; top: 36svh !important; width: 32vw !important;
	}
	.forms-pin div.forms-item:nth-of-type(3) {
		left: 52vw !important; top: 36svh !important; bottom: auto !important; width: 32vw !important;
	}
	.forms-pin, .deck-pin { height: 88svh; }
	.hero-scene { height: 320svh; }
}

@media (max-width: 640px) {
	/* .stats__grid giữ nguyên 2 cột của breakpoint 1000px — đổ thành một
	   cột thì bốn con số kéo dài lê thê. */
	.hero-pin { --pxc: 14; }
	/* Ba con số xếp dọc: một cột thì số to mới đọc ra được ở khổ này. */
	.proof { grid-template-columns: minmax(0, 1fr); }
	.why { grid-template-columns: minmax(0, 1fr); }
	.logo-wall { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.logo-wall { --logo-h: 28px; }
	.nav { display: none; }
	/* Một cột thì bậc tier không còn ý nghĩa gì — featured, big, small nằm
	   chồng nhau cùng một bề ngang. Ép hết về CÙNG một khung ngang để cột thẻ
	   chạy đều nhịp, thay vì cao thấp so le theo --ar của từng tier. */
	.wk-row { grid-template-columns: minmax(0, 1fr); }
	.wk-row .work-card__media { aspect-ratio: 3 / 2; }
}

/* ==========================================================================
   ĐĂNG KÝ NHẬN BÀI — khối cuối bài blog + thẻ nổi giữa bài
   ========================================================================== */

/* Khối cuối bài: chữ bên trái, ô nhập bên phải, chung một khung góc */
.nl {
	position: relative;
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(280px, 38%);
	gap: var(--sp-2) max(48px, 5vw);
	align-items: end;
	padding: clamp(28px, 3.2vw, 52px);
}
.nl__txt { display: flex; flex-direction: column; gap: 1.1rem; }
.nl__h { max-width: 18ch; }
.nl__txt p { max-width: 42ch; }

/* Ô nhập: một đường kẻ chân, nút nằm cùng hàng — cùng mạch với ô ở footer */
.nl__form { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; }
.nl__form input {
	flex: 1;
	min-width: 0;
	padding-bottom: 0.7rem;
	background: none;
	border: 0;
	border-bottom: 1px solid var(--hairline);
	font-size: var(--t-xs);
	color: var(--ink);
	transition: border-color 0.4s var(--ease);
}
.nl__form input::placeholder { color: var(--dim); }
.nl__form input:focus { outline: none; border-bottom-color: var(--ink); }
.nl__form .btn { flex: none; }

/* Lời cảm ơn thay chỗ biểu mẫu sau khi gửi — chiếm trọn hàng, không đẩy layout */
.nl__ok { flex-basis: 100%; margin: 0; color: var(--ink); }
.nl__ok:empty { display: none; }
form.is-sent input,
form.is-sent button { display: none; }

/* --- Thẻ nổi giữa bài ---------------------------------------------------
   hidden cho tới khi JS bật: không có JS thì đã có khối cuối bài rồi, thẻ nổi
   chỉ là phần thêm. Nằm góc phải dưới, tránh nút đổi nền bằng --nlpop-b. */
.nlpop {
	position: fixed;
	right: var(--edge);
	/* KHÔNG dùng --edge cho bottom: nó là calc((100% - 94vw) / 2), mà với phần
	   tử fixed thì 100% trong `bottom` là CHIỀU CAO khung nhìn — ra số âm, thẻ
	   tụt hẳn xuống dưới màn. Mốc ở đây là đỉnh nút đổi nền (cao 34px, cách
	   đáy max(18px, 2vh)) cộng một nhịp thở. */
	bottom: calc(max(18px, 2vh) + 48px);
	z-index: 60;
	width: min(360px, calc(100vw - var(--edge) * 2));
	opacity: 0;
	transform: translateY(14px);
	transition: opacity 0.55s var(--ease), transform 0.55s var(--ease-out);
	pointer-events: none;
}
.nlpop.is-on { opacity: 1; transform: none; pointer-events: auto; }
.nlpop__in {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 0.7rem;
	padding: clamp(20px, 2vw, 26px);
	/* Lớp kính như thanh nav: thẻ đè lên chữ đang đọc nên phải đặc hơn nền */
	background: var(--ground);
	border: 1px solid var(--hairline);
}
.nlpop__h { margin: 0; max-width: 20ch; }
.nlpop__in > p { margin: 0; }
.nlpop__x {
	position: absolute;
	top: 10px;
	right: 10px;
	display: grid;
	place-items: center;
	width: 30px;
	height: 30px;
	color: var(--dim);
	transition: color 0.3s var(--ease);
}
.nlpop__x svg { width: 15px; height: 15px; }
.nlpop__x:hover { color: var(--ink); }
.nlpop form {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.7rem;
	margin-top: 0.4rem;
	padding-bottom: 0.6rem;
	border-bottom: 1px solid var(--hairline);
}
.nlpop form.is-sent { border-bottom: 0; padding-bottom: 0; }
.nlpop input {
	flex: 1;
	min-width: 0;
	background: none;
	border: 0;
	font-size: var(--t-xs);
	color: var(--ink);
}
.nlpop input::placeholder { color: var(--dim); }
.nlpop input:focus { outline: none; }
.nlpop form button { flex: none; color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
	.nlpop { transition: opacity 0.2s linear; transform: none; }
}

@media (max-width: 1000px) {
	.nl { grid-template-columns: 1fr; align-items: start; gap: var(--sp-1); }
	.nl__h { max-width: none; }
}

@media (max-width: 640px) {
	/* Màn hẹp: thẻ trải trọn bề ngang, nằm sát đáy như một dải thông báo.
	   Chừa chỗ bên phải cho nút đổi nền bằng padding của chính thẻ. */
	.nlpop { left: var(--edge); right: var(--edge); width: auto; }
}

/* ==========================================================================
   TRANG CONTACT
   Biểu mẫu bên trái, khối liên hệ dính bên phải. Không dùng thư viện form nào:
   ô radio thật nằm trong nhãn, phần nhìn do :has(input:checked) lo.
   ========================================================================== */
/* Trang này kết bằng nút gửi của biểu mẫu, không phải bằng một khối tiêu đề
   như các trang khác, nên đáy <main> chạm thẳng vào vạch trên của footer. Đẩy
   ra đúng một nhịp dọc để footer không dính vào nút. */
.ct { margin-bottom: var(--sp-3); }

.ct {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(200px, 24%);
	gap: var(--sp-2) max(48px, 5vw);
	align-items: start;
}

.ct-form { border: 0; }
.ct-step { min-width: 0; padding: 0; margin: 0; border: 0; }
.ct-step + .ct-step {
	margin-top: var(--sp-2);
	padding-top: var(--sp-2);
	border-top: 1px solid var(--hairline);
}
/* <legend> là thẻ "được vẽ đè lên viền trên" của fieldset: padding-top của
   fieldset rơi xuống DƯỚI nó chứ không nằm trên — đo được khe tiêu đề → nội
   dung ở bước 02/03 là 99px, bước 01 (không có padding) chỉ 33px. Cho legend
   float thì trình duyệt thôi coi nó là legend đặc biệt, nó thành một khối
   thường nằm trong vùng padding như mọi thứ khác. */
.ct-step__h {
	float: left;
	display: flex;
	align-items: baseline;
	gap: max(14px, 1.2vw);
	width: 100%;
	padding: 0;
	margin-bottom: max(22px, 1.6vw);
}
.ct-step__h + * { clear: both; }
.ct-step__n { flex: none; }

/* --- Viên chọn ------------------------------------------------------------ */
.ct-opts { display: flex; flex-wrap: wrap; gap: 0.7rem; }
/* Phần nhìn nằm trên <span>, không phải trên <label>, để còn chọn được bằng
   input:checked + span. Đã thử .ct-opt:has(input:checked): bộ chọn khớp đúng
   (el.matches trả về true) nhưng Chrome không tính lại style cho chính cái
   <label> bọc ô radio vừa đổi — nền vẫn trong suốt. Bản sao của cùng
   phần tử chèn mới thì lại đúng màu, nên lỗi nằm ở khâu báo thay đổi.
   Bộ chọn anh em không dính chuyện đó. */
.ct-opt { position: relative; display: inline-flex; cursor: pointer; }
/* Ô thật vẫn nằm trong luồng tab, chỉ là không thấy — nên KHÔNG dùng
   display:none hay visibility:hidden. */
.ct-opt input {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	pointer-events: none;
}
.ct-opt > span {
	display: inline-flex;
	align-items: baseline;
	gap: 0.55em;
	padding: max(11px, 0.8vw) max(18px, 1.3vw);
	border: 1px solid var(--hairline);
	border-radius: var(--radius-pill);
	font-size: var(--t-xs);
	line-height: 1.15;
	color: var(--body);
	transition: color 0.45s var(--ease), border-color 0.45s var(--ease),
		background-color 0.45s var(--ease);
}
.ct-opt i { font-style: normal; color: var(--muted); transition: color 0.45s var(--ease); }
@media (hover: hover) {
	.ct-opt:hover > span { border-color: var(--ink); color: var(--ink); }
}
.ct-opt input:checked + span {
	background: var(--btn-bg);
	border-color: var(--btn-bg);
	color: var(--btn-fg);
}
.ct-opt input:checked + span i { color: var(--btn-fg); opacity: 0.7; }
.ct-opt input:focus-visible + span { outline: 2px solid var(--ink); outline-offset: 3px; }

/* --- Bảng ngân sách: hiện theo dịch vụ đang chọn --------------------------- */
.ct-bud { display: none; }
.ct-bud__hint { color: var(--dim); }
.ct-form:has(.ct-opt--svc input:checked) .ct-bud__hint { display: none; }
.ct-form:has(#svc-branding:checked) #bud-branding,
.ct-form:has(#svc-website:checked) #bud-website,
.ct-form:has(#svc-seo:checked) #bud-seo,
.ct-form:has(#svc-geo:checked) #bud-geo,
.ct-form:has(#svc-ai:checked) #bud-ai { display: flex; }

/* --- Ô nhập --------------------------------------------------------------- */
.ct-fields {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--sp-1) max(28px, 2.4vw);
}
.ct-f { margin: 0; min-width: 0; }
.ct-f--full { grid-column: 1 / -1; }
.ct-f input,
.ct-f textarea {
	display: block;
	width: 100%;
	padding: 0.85em 0;
	background: none;
	border: 0;
	border-bottom: 1px solid var(--hairline);
	border-radius: 0;
	font: inherit;
	font-size: var(--t-s);
	color: var(--ink);
	transition: border-color 0.45s var(--ease);
}
.ct-f textarea { resize: vertical; min-height: 6em; line-height: var(--lh-body); }
.ct-f input::placeholder,
.ct-f textarea::placeholder { color: var(--dim); }
.ct-f input:focus,
.ct-f textarea:focus { outline: none; border-bottom-color: var(--ink); }

.ct-file { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 1.4rem; }
.ct-file input { width: auto; padding: 0; border: 0; font-size: var(--t-xs); color: var(--muted); }
.ct-file input::file-selector-button {
	margin-right: 1rem;
	padding: 0.7em 1.3em;
	background: none;
	border: 1px solid var(--hairline);
	border-radius: var(--radius-pill);
	font: inherit;
	font-size: var(--t-xxs);
	color: var(--body);
	cursor: pointer;
	transition: color 0.45s var(--ease), border-color 0.45s var(--ease);
}
.ct-file input::file-selector-button:hover { border-color: var(--ink); color: var(--ink); }

.ct-send {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1rem max(20px, 1.8vw);
	margin-top: var(--sp-1);
}
.ct-send a { text-decoration: underline; text-underline-offset: 0.2em; }

/* --- Cột phải ------------------------------------------------------------- */
.ct-aside {
	position: sticky;
	top: calc(var(--sp-2) + max(44px, 3.2vw));
	display: flex;
	flex-direction: column;
	gap: var(--sp-1);
}
/* Tấm gom cả ba nhóm. Có NỀN và VIỀN thật, không chỉ bốn dấu góc: cột này
   đứng một mình bên phải biểu mẫu nên cần một mảng đặc để neo mắt. Nền dùng
   mực pha loãng chứ không phải màu cứng — chạy đúng ở cả ba nền. */
.ct-card {
	display: flex;
	flex-direction: column;
	padding: max(22px, 1.7vw);
	background: rgba(var(--ink-rgb), 0.04);
	border: 1px solid var(--hairline);
}
.ct-card .c { --c: 6px; }
.ct-card__g { display: flex; flex-direction: column; gap: 1.1rem; }
/* Kẻ ngăn giữa hai nhóm, lề trên dưới bằng đúng lề trong của tấm */
.ct-card__g + .ct-card__g {
	margin-top: max(22px, 1.7vw);
	padding-top: max(22px, 1.7vw);
	border-top: 1px solid var(--hairline);
}
.ct-mail { word-break: break-word; line-height: var(--lh-subhead); }
.ct-where {
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
	font-size: var(--t-xs);
	color: var(--body);
}
.ct-soc { display: flex; gap: 0.7rem; }

@media (max-width: 1000px) {
	.ct { grid-template-columns: 1fr; }
	.ct-aside { position: static; }
}
@media (max-width: 640px) {
	.ct-fields { grid-template-columns: 1fr; }
	.ct-step__h { flex-direction: column; gap: 0.6rem; }
}

/* Trang contact: tiêu đề và biểu mẫu là một cụm, không cần nguyên --sec-gap
   (216px ở 1440) chen giữa như giữa hai section khác chủ đề. */
main > .ct-hero + .ct { margin-top: var(--sp-2); }
