/*
Theme Name: Flexa Template Store
Theme URI: https://flexa.example/store
Author: Flexa
Description: Storefront theme for the Flexa Template Store. Dark, cyan-accented chrome on purpose — the products on sale are screenshots of other people's websites, and a dark frame makes those light interfaces read as lit windows instead of competing with them.
Version: 0.4.1
Requires at least: 6.4
Tested up to: 6.7
Requires PHP: 8.0
Text Domain: flexa-store
*/

/*
 * ============================================================================
 * HỆ THIẾT KẾ — nền mực xanh đêm, accent cyan
 * ============================================================================
 *
 * Bảng màu nằm trong theme.json (6 slug preset). Các token --fs-* dưới đây chỉ
 * là những sắc độ và hiệu ứng mà preset không cần phơi ra cho người sửa nội
 * dung: bóng, quầng sáng, bề mặt nâng, bán kính.
 *
 * Quy ước specificity: block flexa in CSS theo từng instance ở dạng
 * `.flexa-x-<blockId> .flexa-x__phần` (2 class). Mọi rule ghi đè bên dưới dùng
 * ≥3 class để thắng chắc chắn, không phụ thuộc thứ tự nạp stylesheet — và nhắm
 * vào `.wp-block-flexa-*` chứ không vào blockId, để một trang khác dùng cùng
 * block cũng được style, không riêng trang chủ.
 */

:root {
	--fs-bg: var(--wp--preset--color--base, #06121a);
	--fs-bg-deep: #040d13;
	--fs-surface: var(--wp--preset--color--accent, #0d2029);
	--fs-surface-2: #122c37;
	--fs-line: var(--wp--preset--color--neutral, #1b333d);
	--fs-line-bright: #27505f;
	--fs-ink: var(--wp--preset--color--contrast, #e6f4f8);
	--fs-muted: var(--wp--preset--color--secondary, #8ba9b5);
	--fs-cyan: var(--wp--preset--color--primary, #22d3ee);

	--fs-cyan-soft: rgba(34, 211, 238, 0.14);

	--fs-shadow-md: 0 10px 30px -12px rgba(0, 0, 0, 0.7);
	--fs-shadow-lg: 0 36px 80px -32px rgba(0, 0, 0, 0.85), 0 12px 28px -16px rgba(0, 0, 0, 0.6);
	--fs-glow: 0 0 0 1px rgba(34, 211, 238, 0.35), 0 18px 50px -22px rgba(34, 211, 238, 0.5);

	--fs-radius: 8px;
	--fs-radius-lg: 14px;

	--fs-ease: cubic-bezier(0.2, 0.7, 0.3, 1);
	--fs-dur: 220ms;

	--fs-z-header: 30;
	--fs-z-skip: 60;
}

html {
	scroll-behavior: smooth;
	scroll-padding-top: 100px;
}

body {
	background: var(--fs-bg);
	color: var(--fs-ink);
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

::selection {
	background: rgba(34, 211, 238, 0.28);
	color: #ffffff;
}

:where(a, button, input, select, summary, [tabindex]):focus-visible {
	outline: 2px solid var(--fs-cyan);
	outline-offset: 3px;
	border-radius: var(--fs-radius);
}

h1, h2, h3, h4, h5, h6,
.wp-block-site-title a,
.flexa-post-grid__title,
.flexa-faq__question-text,
.flexa-steps__title,
.flexa-info-box__title,
.flexa-promo__heading,
.flexa-heading__title {
	font-family: var(--wp--preset--font-family--display);
	color: var(--fs-ink);
	text-wrap: balance;
}

/* Link "nhảy tới nội dung" cho người dùng bàn phím */
.flexa-store-skip {
	position: absolute;
	left: 16px;
	top: -80px;
	z-index: var(--fs-z-skip);
	padding: 12px 20px;
	border-radius: var(--fs-radius);
	background: var(--fs-cyan);
	color: var(--fs-bg);
	font-size: 14px;
	font-weight: 600;
	text-decoration: none;
	/* `top` la thuoc tinh layout, nhung phan tu nay chi xuat hien khi focus bang
	   ban phim va nam ngoai luong cuon — khong co chi phi moi khung hinh. */
	transition: top var(--fs-dur) var(--fs-ease);
}

.flexa-store-skip:focus {
	top: 16px;
}

/* -------------------------------------------------------- nút dùng chung */

.wp-block-button__link {
	transition: transform var(--fs-dur) var(--fs-ease), background-color var(--fs-dur) var(--fs-ease),
		border-color var(--fs-dur) var(--fs-ease), box-shadow var(--fs-dur) var(--fs-ease);
}

.wp-block-button:not(.is-style-outline) .wp-block-button__link {
	box-shadow: 0 10px 26px -14px rgba(34, 211, 238, 0.9);
}

.wp-block-button__link:hover {
	transform: translateY(-2px);
}

.wp-block-button__link:active {
	transform: translateY(1px);
}

/* Nút viền: trên nền tối phải là viền sáng mờ, không phải viền màu accent đặc */
.wp-block-button.is-style-outline .wp-block-button__link {
	background: transparent;
	color: var(--fs-ink);
	border: 1px solid var(--fs-line-bright);
}

.wp-block-button.is-style-outline .wp-block-button__link:hover {
	background: rgba(255, 255, 255, 0.05);
	border-color: var(--fs-cyan);
	color: var(--fs-ink);
}

/* ------------------------------------------------------------- masthead */

.wp-site-blocks > header.wp-block-template-part {
	position: sticky;
	top: 0;
	z-index: var(--fs-z-header);
}

header.wp-block-template-part > header.fs-masthead {
	background-color: rgba(6, 18, 26, 0.82);
	-webkit-backdrop-filter: saturate(160%) blur(14px);
	backdrop-filter: saturate(160%) blur(14px);
}

.wp-block-site-title a {
	display: inline-flex;
	align-items: center;
	gap: 9px;
	color: var(--fs-ink);
	text-decoration: none;
	font-weight: 700;
	letter-spacing: -0.03em;
	white-space: nowrap;
}

/*
 * Dau nhan dien: hai khung cua so xep lech, khung truoc to dac mau cyan va co
 * mot thanh tieu de.
 *
 * Chon hinh nay vi ca site dung khung trinh duyet gia lam mo-tip — o hero, o the
 * template, o trang thu vien. Dau nhan dien lap lai chinh mo-tip do thi no noi
 * duoc "noi nay chua cac website dung san" ngay o kich thuoc 26px, thay vi chi
 * la mot hinh hoc trang tri.
 *
 * Ve bang background-image tren chinh the <a> chu khong phai mot the <img> hay
 * mot lien ket thu hai — xem ghi chu trong parts/header.html.
 */
.wp-block-site-title a::before {
	content: "";
	width: 26px;
	height: 26px;
	flex: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Crect x='7.2' y='2.8' width='14' height='14' rx='3.6' stroke='%2322d3ee' stroke-width='1.5' opacity='.5'/%3E%3Crect x='2.8' y='7.2' width='14' height='14' rx='3.6' fill='%2322d3ee'/%3E%3Cpath d='M2.8 11.4h14' stroke='%2306121a' stroke-width='1.3'/%3E%3Ccircle cx='5.9' cy='9.3' r='.85' fill='%2306121a'/%3E%3C/svg%3E");
	background-size: contain;
	background-repeat: no-repeat;
	transition: transform var(--fs-dur) var(--fs-ease);
}

.wp-block-site-title a:hover::before {
	transform: rotate(-6deg) scale(1.06);
}

/*
 * Muc menu: mot vien thuoc mo hien ra duoi chu, thay cho gach chan.
 *
 * Gach chan 1px la thu mot thanh dieu huong mien phi cung co. Vien thuoc thi cho
 * muc dang mo mot cai NEN ton tai lien tuc, nen mat doc ra vi tri hien tai ma
 * khong phai di tim mot soi chi mong.
 *
 * Vien thuoc ve bang ::before roi phong to bang transform + opacity, khong doi
 * background-color truc tiep: transform/opacity chay tren lop rieng cua GPU.
 */
.fs-masthead .wp-block-navigation-item__content {
	position: relative;
	z-index: 0;
	color: var(--fs-muted);
	text-decoration: none;
	padding: 9px 15px;
	border-radius: 999px;
	transition: color var(--fs-dur) var(--fs-ease);
}

.fs-masthead .wp-block-navigation-item__content::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.07);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07);
	opacity: 0;
	transform: scale(0.86);
	transition: opacity var(--fs-dur) var(--fs-ease), transform var(--fs-dur) var(--fs-ease);
}

.fs-masthead .wp-block-navigation-item__content:hover,
.fs-masthead .current-menu-item > .wp-block-navigation-item__content {
	color: var(--fs-ink);
}

.fs-masthead .wp-block-navigation-item__content:hover::before,
.fs-masthead .current-menu-item > .wp-block-navigation-item__content::before {
	opacity: 1;
	transform: scale(1);
}

/* Trang dang mo: vien thuoc am mau cyan de no khac voi trang thai re chuot. */
.fs-masthead .current-menu-item > .wp-block-navigation-item__content::before {
	background: rgba(34, 211, 238, 0.14);
	box-shadow: inset 0 0 0 1px rgba(34, 211, 238, 0.26);
}

/* ------------------------------------------------------------------ hero */

/*
 * Chi con hai lop phu ma thuoc tinh block khong dien dat duoc: quang sang lech
 * tam va luoi ky thuat. Padding, nen va bo cuc cua hero nam trong thuoc tinh
 * cua block flexa/banner tren chinh trang chu.
 */
.fs-hero {
	position: relative;
	isolation: isolate;
	overflow: hidden;
}

/*
 * Anh nen cua hero: mot mang anh chup template xep so le, da lam mo va toi.
 *
 * Dung chinh san pham lam nen thay vi anh stock — day la man hinh dau tien, va
 * thu no can noi la "cho nay co nhieu mau san". Anh ghep san thanh MOT file
 * (48KB) chu khong xep bang CSS: xep bang CSS thi trinh duyet phai tai ba anh
 * preview kich thuoc that ngay tren duong dan quan trong nhat cua trang.
 *
 * z-index -3 de nam duoi ca quang sang (-2) va luoi ky thuat (-1).
 */
.fs-hero::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -2;
	pointer-events: none;
	/*
	 * Bon lop trong MOT khai bao, lop dau nam tren cung:
	 *   1-2. hai quang cyan lech tam, pha do phang cua nen toi dac
	 *   3.   mang toi doc, giu chu hero doc duoc tren anh
	 *   4.   anh nen — mang anh chup template da lam mo va toi
	 *
	 * Gop lam mot pseudo-element vi .fs-hero chi con ::after (danh cho luoi ky
	 * thuat). Truoc do minh day quang sang sang .flexa-banner__box::before, nhung
	 * khoi do rong 1200px nen quang bi bo lai thay vi tran ra hai ben.
	 */
	background-image: radial-gradient(46% 44% at 14% 4%, rgba(34, 211, 238, 0.34) 0%, transparent 64%),
		radial-gradient(40% 40% at 88% 16%, rgba(56, 189, 248, 0.26) 0%, transparent 66%),
		radial-gradient(34% 46% at 62% 96%, rgba(14, 165, 183, 0.20) 0%, transparent 70%),
		/*
		 * Mang toi doc. Nang dam o NUA TRAI: cot chu nam ben trai, va anh nen o
		 * do dang canh tranh voi H1 — do vung sau chu "Xem template" thi anh con
		 * du tuong phan de mat bi keo di.
		 */
		linear-gradient(100deg, rgba(4, 13, 19, 0.94) 0%, rgba(5, 15, 22, 0.90) 38%, rgba(6, 18, 26, 0.72) 68%, rgba(6, 18, 26, 0.78) 100%),
		linear-gradient(180deg, rgba(4, 13, 19, 0.34) 0%, rgba(6, 18, 26, 0.40) 55%, rgba(6, 18, 26, 0.92) 100%),
		url("assets/img/hero-wall.jpg");
	background-size: auto, auto, auto, auto, auto, cover;
	background-position: center, center, center, center, center, center top;
	background-repeat: no-repeat;
}

.fs-hero::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	pointer-events: none;
	background-image: linear-gradient(rgba(34, 211, 238, 0.06) 1px, transparent 1px),
		linear-gradient(90deg, rgba(34, 211, 238, 0.06) 1px, transparent 1px);
	background-size: 80px 80px;
	-webkit-mask-image: radial-gradient(120% 80% at 50% 0%, #000 12%, transparent 72%);
	mask-image: radial-gradient(120% 80% at 50% 0%, #000 12%, transparent 72%);
}

/*
 * Hai chữ "chạy thật" trong H1.
 *
 * Đây là lời hứa của cả site, nên nó là từ duy nhất được tô. Màu theo TỪ thì
 * thuộc tính block không diễn đạt được — block chỉ có một ô màu cho cả tiêu đề.
 *
 * background-clip cần một màu chữ trong suốt, và nếu trình duyệt không hỗ trợ
 * thì chữ sẽ biến mất hoàn toàn. Bọc trong @supports để trường hợp đó rơi về
 * màu cyan đặc.
 */
.fs-accent {
	color: var(--fs-cyan);
}

@supports (-webkit-background-clip: text) or (background-clip: text) {
	.fs-accent {
		background-image: linear-gradient(96deg, #67e8f9 0%, #22d3ee 42%, #38bdf8 100%);
		-webkit-background-clip: text;
		background-clip: text;
		color: transparent;
	}
}

/*
 * Dải số liệu dưới hai nút. Con số tự đếm lên là tính năng của block
 * (countUp) — ở đây chỉ thêm vạch ngăn giữa các cột, thứ block không có.
 */
.fs-stats.wp-block-flexa-counter .flexa-counter__item + .flexa-counter__item {
	padding-left: 34px;
	border-left: 1px solid rgba(230, 244, 248, 0.12);
}

/* Chữ số dùng font tiêu đề và bảng số đều chiều rộng, để nó không nhảy khi đếm. */
.fs-stats.wp-block-flexa-counter .flexa-counter__value {
	font-family: var(--wp--preset--font-family--display);
	font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------- khối trưng bày */

/*
 * Hai ảnh chụp template nghiêng nhẹ về hai phía, có khung trình duyệt giả để
 * người xem đọc ngay ra "đây là một website chạy thật" chứ không phải một tấm
 * hình minh hoạ. Đây là thứ gánh phần lớn sức hút của màn hình đầu tiên.
 */
/* Bo cuc hang ngang, gap va margin am nam trong thuoc tinh cua block container. */
.fs-showcase {
	position: relative;
}

/*
 * Bệ sáng phía sau hai tấm ảnh.
 *
 * Một trong hai template đang trưng là mẫu nền đen. Đặt nó lên hero cũng gần
 * đen thì không còn ranh giới nào: đo pixel vùng đó ra trung bình RGB 50/765,
 * tức là người xem thấy đúng một tấm chứ không phải hai. Bệ sáng này nâng nền
 * ngay sau khung ảnh lên đủ để mọi ảnh chụp, sáng hay tối, đều đọc ra là một
 * cửa sổ trình duyệt.
 */
.fs-showcase::before {
	content: "";
	position: absolute;
	inset: 4% -6% 12% -6%;
	z-index: 0;
	pointer-events: none;
	border-radius: 50%;
	background: radial-gradient(closest-side, rgba(34, 211, 238, 0.16) 0%, rgba(34, 211, 238, 0.06) 55%, transparent 100%);
	filter: blur(26px);
}

.fs-showcase__pane {
	position: relative;
	flex: 1 1 0;
	max-width: 520px;
	margin: 0;
	padding-top: 32px;
	z-index: 1;
	border: 1px solid #3d6d80;
	border-radius: var(--fs-radius-lg);
	background: var(--fs-surface-2);
	/*
	 * Vành sáng là bắt buộc, không phải trang trí — xem ghi chú ở .fs-showcase::before.
	 * Lớp inset tạo mép trong sáng để khung tách khỏi ảnh chụp nền đen bên trong.
	 */
	box-shadow: var(--fs-shadow-lg), inset 0 0 0 1px rgba(255, 255, 255, 0.08),
		0 0 0 1px rgba(34, 211, 238, 0.22), 0 0 70px -18px rgba(34, 211, 238, 0.45);
	overflow: hidden;
	transition: transform 420ms var(--fs-ease), box-shadow 420ms var(--fs-ease);
}

/* Thanh trình duyệt giả: một dải mờ và ba chấm */
.fs-showcase__pane::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 32px;
	background: linear-gradient(180deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.06));
	border-bottom: 1px solid #3d6d80;
}

.fs-showcase__pane::after {
	content: "";
	position: absolute;
	top: 12px;
	left: 14px;
	width: 44px;
	height: 8px;
	border-radius: 999px;
	background: radial-gradient(circle 4px at 4px 4px, #ff5f57 98%, transparent),
		radial-gradient(circle 4px at 22px 4px, #febc2e 98%, transparent),
		radial-gradient(circle 4px at 40px 4px, #28c840 98%, transparent);
	opacity: 0.85;
}

.fs-showcase__pane img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 0;
}

/*
 * Ba tam xep chong theo chieu sau, khong phai xep hang ngang.
 *
 * Hang ngang thi ba tam co cung tam quan trong va man hinh dau doc ra nhu mot
 * bang liet ke. Xep chong thi mat co MOT diem vao (tam truoc), hai tam sau chi
 * lam day chieu sau — va no noi duoc "con nua o phia sau" ma khong ton them mot
 * dong chu nao.
 *
 * Xep bang grid mot o thay vi position:absolute: moi tam van chiem cho that nen
 * chieu cao khoi tu tinh theo ti le anh, khong phai do tay.
 */
/*
 * Phai nham vao .flexa-container__inner chu khong phai lop ngoai: block
 * container render HAI tang, va tang trong moi la cai mang display/gap. Dat
 * grid len tang ngoai thi no chi bao mot dua con duy nhat la chinh tang trong.
 *
 * Ba lop class de thang duoc CSS sinh theo tung khoi (.flexa-container-<id> >
 * .flexa-container__inner — hai lop).
 */
.fs-showcase--stack.wp-block-flexa-container > .flexa-container__inner {
	display: grid;
	grid-template-areas: "pane";
	align-items: center;
}

.fs-showcase--stack .fs-showcase__pane {
	grid-area: pane;
	/*
	 * flex:1 1 0 la di san cua bo cuc hang ngang cu. Trong mot khoi xep doc,
	 * flex-basis:0 an vao CHIEU CAO — ba tam anh cung co ve con 34px va bi cat
	 * het, chi con lai thanh trinh duyet gia.
	 */
	flex: 0 0 auto;
	max-width: none;
	width: 100%;
	transition: transform 620ms var(--fs-ease), box-shadow 620ms var(--fs-ease),
		opacity 620ms var(--fs-ease);
}

.fs-showcase--stack .fs-showcase__pane--1 {
	transform: translate3d(-7%, -13%, 0) rotate(-6deg) scale(0.84);
	z-index: 1;
	opacity: 0.5;
}

.fs-showcase--stack .fs-showcase__pane--2 {
	transform: translate3d(6%, -5%, 0) rotate(3.5deg) scale(0.92);
	z-index: 2;
	opacity: 0.78;
}

.fs-showcase--stack .fs-showcase__pane--3 {
	transform: translate3d(0, 7%, 0) rotate(-1.2deg);
	z-index: 3;
}

/*
 * Re chuot vao BAT KY dau trong khoi thi ca chong tach ra — quat nhe sang hai
 * ben va dung thang lai. Dat tren khoi CHA chu khong tren tung tam: neu moi tam
 * tu lo mep thi con tro di ngang qua se lam ba lop nhay khong dong bo.
 */
.fs-showcase--stack:hover .fs-showcase__pane--1 {
	transform: translate3d(-14%, -16%, 0) rotate(-8.5deg) scale(0.85);
	opacity: 0.68;
}

.fs-showcase--stack:hover .fs-showcase__pane--2 {
	transform: translate3d(11%, -8%, 0) rotate(5deg) scale(0.93);
	opacity: 0.92;
}

.fs-showcase--stack:hover .fs-showcase__pane--3 {
	transform: translate3d(0, 4%, 0) rotate(0deg) scale(1.02);
	box-shadow: var(--fs-shadow-lg), var(--fs-glow);
}

/* --------------------------------------------------------- thẻ template */

.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__status:not(.screen-reader-text) {
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.04em;
	margin-bottom: 28px;
}

/*
 * KHONG dat grid-template-columns o day.
 *
 * Truoc do cho nay co mot quy tac `repeat(auto-fit, minmax(min(100%,320px),1fr))`.
 * No de bep thuoc tinh `columns` cua block: khoi o trang thu vien dat 2 cot, con
 * quy tac nay bien no thanh 3 cot o be ngang 1200 — nen 4 mau thanh 3 + 1, va the
 * thu tu dung mot minh canh mot khoang trong 800px. Do la thu xau nhat tren trang.
 *
 * So cot thuoc ve block. Neu can doi, doi trong trinh soan thao.
 */

/*
 * Bố cục hai cột của thẻ nổi bật do CHÍNH block lo (grid 1.15fr/1fr từ 782px,
 * ảnh height:100% + object-fit:cover). Đừng dựng lại bằng flex ở đây — đã thử
 * một lần và hai hệ đánh nhau: ảnh mất ràng buộc chiều cao rồi phình gần 700px,
 * đè lên phần chữ. Ở đây chỉ nâng cỡ chữ cho xứng diện tích lớn hơn.
 */
@media (min-width: 782px) {
	.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__item--featured .flexa-post-grid__body {
		padding: 44px;
}

	.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__item--featured .flexa-post-grid__title {
		font-size: 30px;
}

	.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__item--featured .flexa-post-grid__excerpt {
		font-size: 16.5px;
		max-width: 46ch;
}

	/*
	 * Chặn trần chiều cao. Mẫu mới nhất là mẫu được trưng lớn, và mẫu mới thường
	 * là mẫu chưa kịp có ảnh preview — khi đó ô placeholder theo tỉ lệ 4/3 trên
	 * một cột rộng 640px sẽ tự đẩy thẻ cao gần 500px và kéo cả hàng theo.
	 */
	.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__item--featured {
		max-height: 460px;
}

	.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__item--featured .flexa-post-grid__image--placeholder {
		aspect-ratio: auto;
		height: 100%;
		min-height: 280px;
}
}

/*
 * Không khai `display` ở đây. Block tự đặt `display:flex; flex-direction:column`
 * cho thẻ thường và `display:grid` hai cột cho thẻ nổi bật (từ 782px). Rule này
 * có 3 class nên nếu nó khai display thì sẽ đè luôn cả chế độ hai cột — đúng
 * cái đã xảy ra: thẻ nổi bật xếp dọc, ô ảnh trống cao 1037px, phần chữ bị dồn
 * xuống một dải 88px ở đáy.
 */
.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__item {
	overflow: hidden;
	border: 1px solid var(--fs-line);
	border-radius: var(--fs-radius-lg);
	box-shadow: var(--fs-shadow-md);
	transition: transform var(--fs-dur) var(--fs-ease), box-shadow var(--fs-dur) var(--fs-ease),
		border-color var(--fs-dur) var(--fs-ease);
}

.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__item:hover {
	transform: translateY(-4px);
	border-color: rgba(34, 211, 238, 0.45);
	box-shadow: var(--fs-shadow-lg), 0 0 40px -18px rgba(34, 211, 238, 0.55);
}

.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__image-wrap {
	overflow: hidden;
	border-bottom: 1px solid var(--fs-line);
}

.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__image {
	transition: transform 520ms var(--fs-ease);
}

.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__item:hover .flexa-post-grid__image {
	transform: scale(1.035);
}

/*
 * Mẫu chưa có ảnh preview.
 *
 * Giữ đúng tỉ lệ để hàng thẻ không so le, và nói thẳng ra là "chưa có ảnh" thay
 * vì để một ô xám trống. Mẫu mới nhất được trưng lớn nhất, mà mẫu mới lại chính
 * là mẫu hay chưa kịp có ảnh — nên ô trống này rơi đúng vào vị trí dễ thấy nhất
 * của trang và đọc ra như một chỗ hỏng.
 *
 * Đánh đổi giống câu ở trạng thái lọc rỗng: chữ nằm trong CSS nên không qua bộ
 * dịch. Nếu store cần đa ngôn ngữ thì phải đẩy câu này ngược về block.
 */
.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__image--placeholder {
	position: relative;
	aspect-ratio: 4 / 3;
	background: linear-gradient(160deg, var(--fs-surface-2), var(--fs-surface)),
		repeating-linear-gradient(45deg, rgba(34, 211, 238, 0.05) 0 12px, transparent 12px 24px);
	background-blend-mode: normal;
	color: var(--fs-line-bright);
}

.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__image--placeholder::after {
	content: "No preview image yet";
	position: absolute;
	left: 50%;
	bottom: 26px;
	transform: translateX(-50%);
	white-space: nowrap;
	font-family: var(--wp--preset--font-family--display);
	font-size: 12.5px;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--fs-muted);
}

.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__body {
	flex: 1;
	display: flex;
	flex-direction: column;
}

.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__title a {
	text-decoration: none;
	transition: color var(--fs-dur) var(--fs-ease);
}

.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__item:hover .flexa-post-grid__title a {
	color: var(--fs-cyan);
}

.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__excerpt {
	text-wrap: pretty;
}

/*
 * Nút ghim đáy để mọi thẻ có chung một đường nút, kể cả thẻ chưa có mô tả.
 * Khoảng hở phía trên do gap của body lo — đừng đặt margin-top cố định ở đây,
 * nó sẽ đè mất `auto` và nút lại dính ngay dưới tiêu đề.
 */
.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__readmore {
	margin-top: auto;
	align-self: flex-start;
	padding: 11px 20px;
	border-radius: var(--fs-radius);
	font-family: var(--wp--preset--font-family--display);
	font-weight: 600;
	/*
	 * 13px = x-small của theme.json, đúng cỡ mọi thứ bấm được khác trên site (liên kết trên thanh
	 * điều hướng, nút "Xem thư viện"). Trước đây 14.5px — một con số không nằm trên thang nào, và
	 * quy tắc này có 3 class nên nó ĐÈ cả `buttonTypography` mà block sinh ra: chỉnh trong trình
	 * soạn thảo không có tác dụng gì, phải sửa ở đây.
	 */
	font-size: 0.8125rem;
	transition: transform var(--fs-dur) var(--fs-ease), background-color var(--fs-dur) var(--fs-ease);
}

.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__readmore:hover {
	transform: translateY(-1px);
}

/*
 * Danh mục trên thẻ đến từ get_the_term_list() nên nó là một link và ăn màu link
 * của theme. Phải nhắm đúng class terms — tiêu đề thẻ cũng là link trong cùng
 * block, style chung "link trong post-grid" sẽ bóp tiêu đề thành nhãn nhỏ luôn.
 */
/*
 * Nhãn nhóm đóng thành viên thuốc, không để chữ trần.
 *
 * Trên thẻ, chữ "SAAS" trần đọc ra như một dòng chữ nhỏ bị bỏ quên phía trên
 * tiêu đề. Đóng viên thuốc thì nó thành cùng một loại vật thể với chip trong
 * thanh lọc ngay phía trên — người xem nhận ra "bấm chip đó lọc ra đúng nhóm
 * này" mà không cần ai nói.
 */
.flexa-post-grid__terms a,
.fs-terms a {
	display: inline-block;
	padding: 5px 11px;
	border-radius: 999px;
	background: rgba(34, 211, 238, 0.10);
	box-shadow: inset 0 0 0 1px rgba(34, 211, 238, 0.24);
	color: var(--fs-cyan);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	text-decoration: none;
	transition: color var(--fs-dur) var(--fs-ease), background-color var(--fs-dur) var(--fs-ease);
}

.flexa-post-grid__terms a:hover,
.fs-terms a:hover {
	background: rgba(34, 211, 238, 0.20);
	color: var(--fs-ink);
}

.flexa-post-grid.wp-block-flexa-post-grid .flexa-pagination .page-numbers {
	transition: color var(--fs-dur) var(--fs-ease), background-color var(--fs-dur) var(--fs-ease);
}

/*
 * Trạng thái rỗng — lọc không khớp template nào.
 *
 * Block cố tình để trống câu "No posts found." khi dòng đếm kết quả đang bật, vì
 * "0 template" ngay phía trên đã nói đúng điều đó rồi (xem class-post-query.php).
 * Lý do đó hợp lý, nhưng kết quả trên màn hình là một dòng chữ nhỏ lửng lơ giữa
 * khoảng trống. Không sửa được phần chữ từ theme, nên dựng chính dòng đếm thành
 * một tấm bảng rỗng, và gợi ý lối thoát bằng ::after.
 *
 * Đánh đổi: câu gợi ý nằm trong CSS nên không đi qua bộ dịch. Chấp nhận được vì
 * đây là copy riêng của mặt tiền store; nếu store cần đa ngôn ngữ thì phải đẩy
 * câu này ngược về block.
 */
.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__status:has(+ .flexa-post-grid__empty) {
	display: block;
	margin: 8px auto 0;
	max-width: 560px;
	padding: 56px 32px;
	font-size: 15px;
	color: var(--fs-ink);
	background: var(--fs-surface);
	border: 1px dashed var(--fs-line-bright);
	border-radius: var(--fs-radius-lg);
}

.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__status:has(+ .flexa-post-grid__empty)::after {
	content: "Try a shorter search term, or switch back to “All”.";
	display: block;
	margin-top: 8px;
	font-size: 14.5px;
	font-weight: 400;
	line-height: 1.7;
	color: var(--fs-muted);
}

/* -------------------------------------------------------------- FAQ */

.flexa-faq.wp-block-flexa-faq .flexa-faq__list {
	gap: 0;
}

.flexa-faq.wp-block-flexa-faq .flexa-faq__item {
	border-top: 1px solid var(--fs-line);
}

.flexa-faq.wp-block-flexa-faq .flexa-faq__item:last-child {
	border-bottom: 1px solid var(--fs-line);
}

.flexa-faq.wp-block-flexa-faq .flexa-faq__question {
	padding-block: 24px;
	gap: 20px;
	font-size: 17px;
	transition: color var(--fs-dur) var(--fs-ease);
}

.flexa-faq.wp-block-flexa-faq .flexa-faq__question:hover {
	color: var(--fs-cyan);
}

/*
 * Nút dấu cộng: block chỉ vẽ hai thanh bằng pseudo-element với kích thước 100%
 * của khung icon, nên khi theme phóng khung lên thành vòng tròn 34px thì dấu
 * cộng chạm sát mép. Đặt lại kích thước thanh theo pixel để dấu cộng nằm gọn
 * giữa vòng tròn.
 */
.flexa-faq.wp-block-flexa-faq .flexa-faq__icon {
	flex: none;
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	border: 1px solid var(--fs-line-bright);
	border-radius: 999px;
	background: transparent;
	color: var(--fs-cyan);
	transition: transform var(--fs-dur) var(--fs-ease), background-color var(--fs-dur) var(--fs-ease),
		border-color var(--fs-dur) var(--fs-ease), color var(--fs-dur) var(--fs-ease);
}

.flexa-faq.wp-block-flexa-faq .flexa-faq__icon--plus::before,
.flexa-faq.wp-block-flexa-faq .flexa-faq__icon--plus::after {
	border-radius: 2px;
	background: currentColor;
}

.flexa-faq.wp-block-flexa-faq .flexa-faq__icon--plus::before {
	width: 13px;
	height: 1.5px;
}

.flexa-faq.wp-block-flexa-faq .flexa-faq__icon--plus::after {
	width: 1.5px;
	height: 13px;
	transition: transform var(--fs-dur) var(--fs-ease), opacity var(--fs-dur) var(--fs-ease);
}

.flexa-faq.wp-block-flexa-faq .flexa-faq__question:hover .flexa-faq__icon {
	border-color: var(--fs-cyan);
	background: var(--fs-cyan-soft);
}

/*
 * Trạng thái mở: vòng tròn thành cyan đặc, dấu cộng quay một phần tư vòng rồi
 * thu thanh dọc lại thành dấu trừ. Màu thì `iconActiveColor` làm được, nhưng
 * vòng tròn và chuyển động thì không có attribute nào tương ứng.
 */
.flexa-faq.wp-block-flexa-faq .flexa-faq__question[aria-expanded="true"] .flexa-faq__icon {
	transform: rotate(90deg);
	background: var(--fs-cyan);
	border-color: var(--fs-cyan);
	color: var(--fs-bg);
}

.flexa-faq.wp-block-flexa-faq .flexa-faq__question[aria-expanded="true"] .flexa-faq__icon--plus::after {
	opacity: 0;
	transform: translate(-50%, -50%) scaleY(0);
}

.flexa-faq.wp-block-flexa-faq .flexa-faq__answer-content {
	max-width: 68ch;
	padding-bottom: 26px;
	text-wrap: pretty;
}

@media (prefers-reduced-motion: reduce) {
	.flexa-faq.wp-block-flexa-faq .flexa-faq__icon,
	.flexa-faq.wp-block-flexa-faq .flexa-faq__icon--plus::after {
		transition: none;
	}
}

/* ------------------------------------------------------------- các bước */

/*
 * Block steps xuất hiện trong nội dung trang "Cách hoạt động". Mã màu cứng đã
 * được bóc khỏi nội dung, nên marker cần theme cấp màu — nếu không nó rơi về
 * mặc định của block.
 */
.flexa-steps.wp-block-flexa-steps .flexa-steps__marker {
	font-family: var(--wp--preset--font-family--display);
	font-weight: 600;
}

.flexa-steps.wp-block-flexa-steps .flexa-steps__description {
	max-width: 68ch;
	text-wrap: pretty;
}

/*
 * Info-box cũng nằm trong nội dung trang, cùng lý do.
 *
 * Bọc trong :where() để quy tắc này có ĐỘ ƯU TIÊN BẰNG KHÔNG. Viết thẳng
 * `.flexa-info-box.wp-block-flexa-info-box` thì nó là (0,2,0), trong khi CSS mà
 * block tự sinh ra cho từng thẻ là `.flexa-info-box-<id>` — chỉ (0,1,0). Nghĩa là
 * mọi lựa chọn viền đặt trong trình biên tập đều bị chính theme đè, im lặng: một
 * thẻ cố ý để không viền vẫn hiện ra viền. Ở dạng :where() thì đây thành mặc định
 * cho thẻ nào không nói gì, và thẻ nào có nói thì được nói.
 */
:where(.flexa-info-box.wp-block-flexa-info-box) {
	border: 1px solid var(--fs-line);
	border-radius: var(--fs-radius-lg);
}

/* --------------------------------------------------------------- CTA */

/* ---------------------------------------------- đầu trang của trang con */

/*
 * Dau trang cua cac template (Blog, ket qua tim, bai viet, 404).
 *
 * Anh nam trong theme chu khong tro vao uploads: duong dan uploads co nam/thang
 * trong no, doi anh khac la duong dan gay. Anh da nen xuong 1800px / 193KB.
 *
 * Lop gradient dat TRUOC anh trong cung mot khai bao background — thu tu nay la
 * bat buoc, lop dau tien nam tren cung. Khong co no thi chu trang tren anh sang
 * khong doc duoc, va container o day khong co lop overlay rieng.
 */
.fs-pagehead {
	position: relative;
	background-color: var(--fs-surface);
	background-image: linear-gradient(180deg, rgba(6, 18, 26, 0.82) 0%, rgba(6, 18, 26, 0.93) 62%, rgba(6, 18, 26, 0.98) 100%),
		url("assets/img/pagehead.jpg");
	background-size: cover, cover;
	background-position: center center, center 35%;
	background-repeat: no-repeat, no-repeat;
	border-bottom: 1px solid var(--fs-line);
}

/*
 * Bề rộng đọc đặt lên TỪNG phần tử con, không lên chính khối: khối vẫn là hộp
 * 1200 canh giữa như mọi khối khác, nên mép trái tiêu đề trang trùng đúng mép
 * trái của danh sách bài bên dưới.
 *
 * Hai cách sai đã thử: bóp max-width chính khối thì layout constrained của core
 * canh giữa nó (lệch phải 260px); thêm margin-left:0 !important thì nó nhảy ra
 * sát mép padding của section (lệch trái 72px).
 */
.wp-block-group.fs-measure > * {
	max-width: 680px;
}

/* Trang bài viết: thân bài do core canh giữa ở 680, nên đầu bài canh giữa theo */
.wp-block-group.fs-measure--center {
	max-width: 680px;
}

.fs-lede {
	max-width: 60ch;
	font-size: 1.1875rem;
	line-height: 1.75;
	color: var(--fs-muted);
	text-wrap: pretty;
}

/* ----------------------------------------------------- danh sách bài viết */

/*
 * Danh sách bài không dùng lưới thẻ: chữ bên trái, ảnh nhỏ bên phải, ngăn nhau
 * bằng vạch tóc. Đọc như mục lục của một tờ báo, và không bắt mọi bài phải có
 * ảnh đại diện mới trông cân.
 */
.fs-postlist {
	margin: 0;
	padding: 0;
	list-style: none;
}

.fs-postrow {
	transition: background-color var(--fs-dur) var(--fs-ease);
}

/*
 * Cả tiêu đề lẫn tóm tắt dùng chung một bề rộng đọc. Giới hạn riêng tóm tắt
 * bằng ch ở cỡ chữ nhỏ làm nó xuống dòng sớm hơn tiêu đề gần 200px, và cột chữ
 * trông như bị rách.
 */
.fs-postrow__text {
	flex: 1 1 auto;
	min-width: 0;
	max-width: 660px;
}

.fs-postrow__media {
	flex: 0 0 260px;
	margin: 0;
	overflow: hidden;
	border: 1px solid var(--fs-line);
	border-radius: var(--fs-radius);
}

.fs-postrow__media img {
	display: block;
	width: 100%;
	height: auto;
	transition: transform 520ms var(--fs-ease);
}

.fs-postrow:hover .fs-postrow__media img {
	transform: scale(1.03);
}

.fs-postrow .wp-block-post-title a {
	color: var(--fs-ink);
	text-decoration: none;
	transition: color var(--fs-dur) var(--fs-ease);
}

.fs-postrow:hover .wp-block-post-title a {
	color: var(--fs-cyan);
}

.fs-postrow .wp-block-post-excerpt__excerpt {
	color: var(--fs-muted);
	text-wrap: pretty;
}

.fs-postmeta {
	align-items: center;
}

.fs-postmeta .wp-block-post-date,
.fs-postmeta .wp-block-post-terms {
	margin: 0;
	color: var(--fs-muted);
}

.fs-pagination {
	align-items: center;
}

.fs-pagination a,
.fs-pagination .wp-block-query-pagination-numbers {
	color: var(--fs-muted);
	text-decoration: none;
	transition: color var(--fs-dur) var(--fs-ease);
}

.fs-pagination a:hover {
	color: var(--fs-cyan);
}

.fs-pagination .page-numbers.current {
	color: var(--fs-ink);
	font-weight: 600;
}

/* ------------------------------------------------------------- bài viết */

.fs-article__cover img {
	width: 100%;
	max-height: 520px;
	object-fit: cover;
}

.fs-article p,
.fs-article li {
	color: var(--fs-ink);
	text-wrap: pretty;
}

.fs-article > h2,
.fs-article > h3 {
	margin-top: 2em;
}

.fs-article blockquote {
	margin-inline: 0;
	padding-left: 24px;
	border-left: 2px solid var(--fs-cyan);
}

.fs-postnav a {
	color: var(--fs-muted);
	text-decoration: none;
	transition: color var(--fs-dur) var(--fs-ease);
}

.fs-postnav a:hover {
	color: var(--fs-cyan);
}

/* Ô tìm kiếm dùng chung ở 404 và trang kết quả */
.fs-search .wp-block-search__input {
	border: 1px solid var(--fs-line-bright);
	border-radius: var(--fs-radius);
	padding: 12px 16px;
	background: var(--fs-bg);
	color: var(--fs-ink);
}

.fs-search .wp-block-search__input::placeholder {
	color: var(--fs-muted);
}

.fs-search .wp-block-search__button {
	border: 0;
	border-radius: var(--fs-radius);
	background: var(--fs-cyan);
	color: var(--fs-bg);
	padding: 12px 22px;
	font-weight: 600;
	transition: background-color var(--fs-dur) var(--fs-ease);
}

.fs-search .wp-block-search__button:hover {
	background: #67e8f9;
}

/* -------------------------------------------------------------- footer */
/*
 * FOOTER PHẢI BÁM ĐÚNG CỘT 1200px NHƯ MỌI PHẦN KHÁC CỦA SITE.
 *
 * Khối footer khai `layout: constrained`, mà kiểu đó lấy bề rộng từ biến
 * `--wp--style--global--content-size` của WordPress. Trên site này biến đó tính ra `100%` chứ
 * không phải 1200px như theme.json khai — nên "constrained" không giới hạn gì cả, và ở màn 1920
 * chữ trong footer chạy sát mép trái màn hình trong khi mọi thứ phía trên đều dừng ở cột 1200.
 *
 * Không đi sửa biến toàn cục: nó ảnh hưởng mọi khối lõi trên mọi trang, mà cả site đang dựng bằng
 * `flexa/container` với hệ cột riêng. Chỉ ràng ngay tại footer, và dùng ĐÚNG công thức mà thanh
 * điều hướng đang dùng (`.fs-masthead__bar`) để hai đầu trang-cuối trang thẳng một mép:
 * cột 1200 + 24px đệm hai bên.
 *
 * Nhắm vào con TRỰC TIẾP của footer, nên đường kẻ ngăn phía trên dòng bản quyền cũng thu về đúng
 * cột — kẻ chạy hết bề ngang màn còn chữ thì dừng ở 1200 là hai mép khác nhau trên cùng một cụm.
 */
.fs-footer.wp-block-group > * {
	box-sizing: border-box;
	width: min(100%, calc(1200px + 48px));
	max-width: none;
	margin-inline: auto;
	padding-inline: 24px;
}


.fs-footer__label {
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--fs-ink);
}

.fs-footer__lede {
	max-width: 46ch;
	color: var(--fs-muted);
	text-wrap: pretty;
}

/*
 * Cột link ở footer là core/list, nên mặc định có chấm đầu dòng và link gạch
 * chân — đọc ra như một danh sách trong bài viết chứ không phải một cột điều
 * hướng. theme.json không nhắm được vào class, và styles.elements.link ở đó áp
 * cho mọi link của site.
 */
.fs-footer__list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.fs-footer__list a {
	color: var(--fs-muted);
	text-decoration: none;
	display: inline-block;
	transition: color var(--fs-dur) var(--fs-ease), transform var(--fs-dur) var(--fs-ease);
}

.fs-footer__list a:hover,
.fs-footer__list a:focus-visible {
	color: var(--fs-cyan);
	transform: translateX(6px);
}

/* ------------------------------------------------- xuất hiện khi tải trang */

/*
 * Chỉ hero mới có hiệu ứng vào, và nó chạy đúng một lần lúc tải trang.
 *
 * Bản trước dùng animation-timeline: view() cho cả lưới thẻ và các ô nội dung.
 * Hỏng ở hai chỗ: scroll-driven animation là hàm của vị trí cuộn, nên cuộn ngược
 * lên thì nội dung mờ đi trở lại; và ở bất kỳ ngữ cảnh nào render cả trang cùng
 * lúc (in trang, chụp toàn trang) mọi khối dưới màn hình đều nằm ở opacity 0.
 * Một reveal thì phải một chiều — cái nào đã hiện thì ở lại.
 */
@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
	}
}

/* --------------------------------------------------------- responsive */

@media (max-width: 1024px) {
	html {
		scroll-padding-top: 84px;
	}

	.fs-postrow__media {
		flex-basis: 200px;
	}
}

@media (max-width: 767px) {
	/* Header dính ăn mất chiều cao quý giá trên máy nhỏ — bỏ dính, giữ nguyên kính */
	.wp-site-blocks > header.wp-block-template-part {
		position: static;
	}

	/*
	 * Tren dien thoai chi con MOT tam. Hai tam sau da bi block an bang
	 * responsiveVisibility, nen o day chi phai go phan nghieng: mot tam nghieng
	 * don doc doc ra nhu loi bo cuc chu khong phai chieu sau.
	 */
	.fs-showcase--stack .fs-showcase__pane--3 {
		transform: none;
	}

	.fs-showcase--stack:hover .fs-showcase__pane--3 {
		transform: none;
		box-shadow: var(--fs-shadow-lg), inset 0 0 0 1px rgba(255, 255, 255, 0.08),
			0 0 0 1px rgba(34, 211, 238, 0.22), 0 0 70px -18px rgba(34, 211, 238, 0.45);
	}

	/*
	 * Hàng bài viết xếp dọc, ảnh lên trên. Ảnh là con thứ hai trong DOM nên
	 * column-reverse đưa nó lên đầu mà không phải đổi thứ tự markup.
	 */
	.fs-postrow {
		flex-direction: column-reverse;
		align-items: stretch;
		gap: 16px;
	}

	.fs-postrow__media {
		flex-basis: auto;
		width: 100%;
	}

	.fs-postrow .wp-block-post-title {
		font-size: 22px !important;
	}

	.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__item:hover {
		transform: none;
}

	.fs-pagination {
		justify-content: center;
		gap: 12px;
	}
}

/* ------------------------------------------- lưới template ở trang nhóm ngành */

/*
 * Trang nhóm ngành dựng bằng block core (query loop), không phải flexa/post-grid,
 * vì nó là một template chứ không phải nội dung trang — không có chỗ nào để người
 * dùng chọn màu. Nên ở đây theme cấp màu là đúng vai.
 */
.fs-tplgrid {
	margin: 0;
	padding: 0;
	list-style: none;
}

.fs-tplcard {
	overflow: hidden;
	box-shadow: var(--fs-shadow-md);
	transition: transform var(--fs-dur) var(--fs-ease), box-shadow var(--fs-dur) var(--fs-ease),
		border-color var(--fs-dur) var(--fs-ease);
}

.fs-tplcard:hover {
	transform: translateY(-4px);
	border-color: rgba(34, 211, 238, 0.45);
	box-shadow: var(--fs-shadow-lg), 0 0 40px -18px rgba(34, 211, 238, 0.55);
}

.fs-tplcard img {
	transition: transform 520ms var(--fs-ease);
}

.fs-tplcard:hover img {
	transform: scale(1.035);
}

.fs-tplcard .wp-block-post-title a {
	color: var(--fs-ink);
	text-decoration: none;
	transition: color var(--fs-dur) var(--fs-ease);
}

.fs-tplcard:hover .wp-block-post-title a {
	color: var(--fs-cyan);
}

/* ------------------------------------------------- hai thiết bị cạnh nhau */

/*
 * Ảnh desktop và ảnh điện thoại là hai ảnh chụp thật ở hai kích thước thật, nên
 * tỉ lệ của chúng lệch nhau rất xa (4:3 và 780×1688). Cân lại bằng chiều cao
 * chung thay vì bề rộng, và bo khung để cả hai đọc ra là màn hình.
 */
.fs-devices .fs-device img {
	display: block;
	border-radius: 12px;
	border: 1px solid var(--fs-line-bright);
	box-shadow: var(--fs-shadow-lg);
}

@media (min-width: 782px) {
	.fs-devices .fs-device--desktop img {
		height: 420px;
		width: auto;
		object-fit: cover;
		object-position: top center;
	}

	.fs-devices .fs-device--mobile img {
		height: 480px;
		width: auto;
		border-radius: 22px;
	}
}

@media (max-width: 781px) {
	.fs-devices .fs-device img {
		width: 100%;
		height: auto;
	}

	.fs-devices .fs-device--mobile img {
		max-width: 280px;
		margin-inline: auto;
		border-radius: 22px;
	}
}

/* --------------------------------------------- nhãn nhóm của bộ lọc */

/*
 * Workaround cho lỗi trong flexa-block: filter-taxonomy in ra
 *   <legend class="flexa-filter-field__label" class="screen-reader-text">
 * — hai thuộc tính class trên một thẻ, trình duyệt giữ cái đầu và bỏ cái sau,
 * nên `showLabel: false` không bao giờ có tác dụng và nhãn luôn hiện.
 *
 * Giấu bằng mắt chứ không xoá: legend là tên nhóm cho trình đọc màn hình, bỏ
 * hẳn thì dãy chip mất ngữ cảnh. Gỡ rule này khi plugin sửa render.php.
 */
.flexa-post-filter.wp-block-flexa-post-filter .flexa-filter-field--taxonomy .flexa-filter-field__label {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/*
 * ============================================================================
 * LỚP CAO CẤP — vật liệu, chuyển động, chiều sâu
 * ============================================================================
 *
 * Mọi thứ dưới đây là thứ block KHÔNG có ô để chỉnh: khung lồng hai lớp, vành
 * sáng trong, hạt nhiễu, đường cong chuyển động, vật lý khi bấm. Màu và bán kính
 * ngoài của thẻ vẫn nằm trong thuộc tính block — xem ghi chú ở đầu file.
 */

:root {
	/* Đường cong nặng, mô phỏng quán tính vật thật. Không dùng ease-in-out. */
	--fs-ease: cubic-bezier(0.32, 0.72, 0, 1);
	--fs-dur: 480ms;
	--fs-dur-fast: 260ms;
}

/* ---------------------------------------------------- hạt nhiễu toàn màn */

/*
 * Lớp hạt phủ cả màn hình, phá cái phẳng tuyệt đối của nền số. Đặt `fixed` và
 * `pointer-events:none` — gắn vào phần tử cuộn thì GPU phải vẽ lại liên tục và
 * khung hình trên máy yếu sụp ngay.
 */
body::after {
	content: "";
	position: fixed;
	inset: 0;
	z-index: 40;
	pointer-events: none;
	opacity: 0.035;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ------------------------------------------- masthead thành đảo nổi */

/*
 * Thanh điều hướng tách khỏi mép trên thành một viên thuốc kính trôi nổi, thay
 * vì dán chặt vào đỉnh màn hình.
 */
/*
 * Thanh điều hướng phải NẰM ĐÈ lên nội dung, không phải đứng phía trên nó.
 *
 * Ở dạng sticky, khối bọc chiếm 70px thật trong luồng. Nền của trang (#06121a)
 * lấp kín 70px đó suốt chiều ngang, và viên thuốc rơi vào giữa một dải đen chạy
 * hết màn hình — đúng thứ mà bố cục đảo nổi định tránh. Đo được: main bắt đầu ở
 * y=81 trong khi viên thuốc chỉ cao 70 và rộng ~850.
 *
 * Chuyển sang fixed thì khối bọc không chiếm chỗ nữa: section đầu tiên của mọi
 * trang chạy lên tới y=0 và viên thuốc trôi trên chính nền của nó.
 *
 * Đổi lại, mỗi trang phải tự chừa chỗ ở đỉnh — xem --fs-header-clear và phần
 * padding-top của section đầu ở từng trang.
 */
.wp-site-blocks > header.wp-block-template-part {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	/*
	 * Ở đỉnh trang thanh trong suốt và chạy hết chiều ngang. Nếu nó bắt chuột thì
	 * cả một dải 88px ngang màn hình sẽ nuốt cú bấm vào hero mà người dùng không
	 * hiểu vì sao. Chỉ hàng nội dung bên trong mới nhận chuột.
	 */
	pointer-events: none;
}

/*
 * Bỏ khoảng cách khối giữa header và main.
 *
 * WordPress đặt margin-block-start cho mọi con của .wp-site-blocks để tách
 * header khỏi nội dung. Header giờ đã nằm ngoài luồng, nên khoảng đó không tách
 * gì cả — nó chỉ để lộ 11px nền trang ở sát mép trên, ngay phía trên section
 * đầu tiên.
 */
.wp-site-blocks > main {
	margin-block-start: 0;
}

/*
 * Thanh trần, chạy hết chiều ngang, không viên thuốc.
 *
 * Mục đích của site là khoe template. Một khối kính bo tròn nổi ở đỉnh là thêm
 * một vật thể nữa tranh chỗ với ảnh demo — và nó luôn phải tự giải thích tại sao
 * nó rộng chừng đó. Thanh trần thì không có bề rộng nào để tranh cãi: nó chạy
 * hết màn, còn nội dung bên trong bám đúng cột 1200px như mọi section khác.
 *
 * Ở đỉnh trang thanh trong suốt hoàn toàn, ảnh hero chạy thẳng lên mép trên.
 * Cuộn xuống thì nền và đường kẻ đáy hiện dần ra — xem khối @supports bên dưới.
 */
header.wp-block-template-part > header.fs-masthead {
	width: 100%;
	max-width: none;
	margin-inline: 0;
	padding: 22px 0 !important;
	border-radius: 0;
	/*
	 * Trạng thái mặc định cho trình duyệt chưa chạy được hoạt ảnh theo cuộn:
	 * để nền mờ sẵn. Trong suốt hoàn toàn mà không có hoạt ảnh thì khi cuộn,
	 * chữ menu sẽ chồng lên nội dung trang và không đọc được.
	 */
	background-color: rgba(6, 18, 26, 0.72);
	-webkit-backdrop-filter: saturate(160%) blur(16px);
	backdrop-filter: saturate(160%) blur(16px);
}

/*
 * Hàng nội dung bám đúng cột 1200px của site, và là phần DUY NHẤT nhận chuột.
 * Dùng chính padding ngang của section hero (24px) nên dấu nhận diện thẳng mép
 * trái tiêu đề hero, nút hành động thẳng mép phải của lưới.
 */
.fs-masthead__bar.wp-block-group {
	box-sizing: border-box;
	width: min(100%, calc(1200px + 48px));
	max-width: none;
	margin-inline: auto;
	padding-inline: 24px;
	gap: 30px;
	pointer-events: auto;
}

.fs-masthead__end.wp-block-group {
	gap: 0;
}

/*
 * Vách ngăn giữa cụm menu và nút hành động.
 *
 * Không có nó thì bốn liên kết và một nút nằm cùng một hàng đều tăm tắp, và mắt
 * đọc cái nút như liên kết thứ năm. Vách ngăn tách hai nhóm ra: bên trái là đi
 * đâu, bên phải là làm gì.
 */
.fs-masthead__cta {
	position: relative;
	margin-left: 18px;
	padding-left: 18px;
}

.fs-masthead__cta::before {
	content: "";
	position: absolute;
	left: 0;
	top: 50%;
	width: 1px;
	height: 22px;
	transform: translateY(-50%);
	background: linear-gradient(180deg, transparent, rgba(230, 244, 248, 0.20), transparent);
}

/*
 * Thanh đặc dần khi cuộn.
 *
 * Ở đỉnh trang thanh gần như trong suốt, để ảnh hero đi xuyên qua. Cuộn xuống thì
 * nó đặc lại và đổ bóng sâu hơn, tách hẳn khỏi nội dung chạy bên dưới.
 *
 * Chạy bằng scroll-timeline nên KHÔNG có listener cuộn nào — mỗi khung hình
 * trình duyệt tự nội suy. Chỉ đổi background-color và box-shadow: cả hai là
 * thuộc tính vẽ, không đụng tới kích thước. Thanh này là phần tử sticky nên nó
 * vẫn chiếm chỗ trong luồng; đổi padding theo cuộn sẽ đẩy toàn bộ trang nhảy.
 *
 * Trình duyệt chưa hỗ trợ thì @supports bỏ qua và thanh giữ nguyên trạng thái
 * mặc định — không có bước thoái lui nào cần viết thêm.
 */
@supports (animation-timeline: scroll()) {
	@media (prefers-reduced-motion: no-preference) {
		header.wp-block-template-part > header.fs-masthead {
			/*
			 * Viet tach tung thuoc tinh, khong dung shorthand `animation`.
			 * Shorthand se dat animation-duration ve 0s, va mot hoat anh chay
			 * theo cuon can duration `auto` — de 0s thi no khong chay gi ca.
			 */
			animation-name: fs-masthead-dac;
			animation-duration: auto;
			animation-timing-function: linear;
			animation-fill-mode: both;
			animation-timeline: scroll(root block);
			animation-range: 0 180px;
		}

		@keyframes fs-masthead-dac {
			from {
				background-color: rgba(6, 18, 26, 0);
				-webkit-backdrop-filter: saturate(100%) blur(0);
				backdrop-filter: saturate(100%) blur(0);
				box-shadow: 0 1px 0 rgba(230, 244, 248, 0);
			}

			to {
				background-color: rgba(6, 18, 26, 0.82);
				-webkit-backdrop-filter: saturate(165%) blur(16px);
				backdrop-filter: saturate(165%) blur(16px);
				/*
				 * Đường kẻ đáy vẽ bằng box-shadow chứ không phải border-bottom:
				 * border làm thanh cao thêm 1px, và chiều cao thanh là con số mà
				 * padding-top của section đầu ở mọi trang đang bám theo.
				 */
				box-shadow: 0 1px 0 rgba(230, 244, 248, 0.10),
					0 18px 40px -32px rgba(0, 0, 0, 0.9);
			}
		}
	}
}

/* -------------------------------------------- khung lồng hai lớp */

/*
 * Thẻ template và info-box: vỏ ngoài giữ một dải đệm mỏng, lõi trong có bán kính
 * nhỏ hơn đúng bằng phần đệm, nên hai đường cong đồng tâm. Đây là thứ làm cái
 * thẻ đọc ra như vật thể có bề dày chứ không phải một hình chữ nhật tô màu.
 */
.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__item {
	padding: 6px;
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06),
		0 20px 50px -28px rgba(0, 0, 0, 0.9);
}

.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__image-wrap {
	border-radius: 8px;
	border-bottom: 0;
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05);
}

.flexa-post-grid.wp-block-flexa-post-grid .flexa-post-grid__item:hover {
	transform: translateY(-6px);
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.10),
		0 40px 80px -34px rgba(0, 0, 0, 0.95),
		0 0 50px -20px rgba(34, 211, 238, 0.5);
}

.flexa-info-box.wp-block-flexa-info-box {
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05),
		0 18px 44px -30px rgba(0, 0, 0, 0.85);
	transition: transform var(--fs-dur) var(--fs-ease), box-shadow var(--fs-dur) var(--fs-ease);
}

.flexa-info-box.wp-block-flexa-info-box:hover {
	transform: translateY(-4px);
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.10),
		0 34px 70px -34px rgba(0, 0, 0, 0.92);
}

.flexa-info-box.wp-block-flexa-info-box .flexa-info-box__media {
	box-shadow: inset 0 0 0 1px rgba(34, 211, 238, 0.18);
	transition: transform var(--fs-dur) var(--fs-ease);
}

.flexa-info-box.wp-block-flexa-info-box:hover .flexa-info-box__media {
	transform: translateY(-2px) scale(1.06);
}

/* ------------------------------------------- nút: vòng tròn lồng trong nút */

/*
 * Mũi tên không đứng trần cạnh chữ mà nằm trong vòng tròn riêng, ép sát lề phải
 * trong lòng nút. Dựng bằng ::after nên không phải sửa markup của block.
 */
.flexa-button--fill .flexa-button__link,
.flexa-post-grid__readmore,
.flexa-promo__button--primary,
.wp-block-button:not(.is-style-outline) .wp-block-button__link {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 12px;
	padding-right: 8px !important;
	transition: transform var(--fs-dur-fast) var(--fs-ease), box-shadow var(--fs-dur) var(--fs-ease),
		background-color var(--fs-dur) var(--fs-ease);
}

.flexa-button--fill .flexa-button__link::after,
.flexa-post-grid__readmore::after,
.flexa-promo__button--primary::after,
.wp-block-button:not(.is-style-outline) .wp-block-button__link::after {
	content: "↗";
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	flex: none;
	border-radius: 999px;
	background: rgba(6, 18, 26, 0.16);
	font-size: 14px;
	line-height: 1;
	transition: transform var(--fs-dur) var(--fs-ease), background-color var(--fs-dur) var(--fs-ease);
}

/* Sức căng bên trong nút: vòng tròn nhích chéo lên khi rê chuột */
.flexa-button--fill .flexa-button__link:hover::after,
.flexa-post-grid__readmore:hover::after,
.flexa-promo__button--primary:hover::after,
.wp-block-button:not(.is-style-outline) .wp-block-button__link:hover::after {
	transform: translate(3px, -3px) scale(1.06);
	background: rgba(6, 18, 26, 0.26);
}

/* Bấm xuống: cả nút lún lại, mô phỏng lực ấn */
.flexa-button .flexa-button__link:active,
.flexa-post-grid__readmore:active,
.flexa-promo__button:active,
.wp-block-button__link:active {
	transform: scale(0.975);
}

/* --------------------------------------- vào khung: mờ dần + nhoè dần */

/*
 * Bổ sung cho hiệu ứng của block: thêm một lớp nhoè tan dần, làm chuyển động có
 * chiều sâu quang học thay vì chỉ trượt lên. Chỉ dùng transform/filter/opacity —
 * không đụng vào thuộc tính gây reflow.
 */
@media (prefers-reduced-motion: no-preference) {
	.flexa-anim[data-flexa-animate] {
		filter: blur(10px);
		transition: filter 900ms var(--fs-ease);
	}

	.flexa-anim[data-flexa-animated="true"] {
		filter: blur(0);
	}
}

/* ------------------------------------------------ menu trên điện thoại */

/*
 * Nút mở menu: một vòng tròn có vành mảnh, cùng ngôn ngữ với nút hành động bên
 * cạnh. Mặc định của WordPress là ba vạch trần nằm trơ trên nền — cạnh một cái
 * nút bo tròn đặc thì nó đọc ra như phần chưa làm xong.
 */
/*
 * Phai khoanh trong media query: block navigation an nut nay bang
 * `display:none` o >=600px, va mot khai bao `display:flex` khong dieu kien se
 * de bep quy tac do — nut hamburger hien ra giua thanh dieu huong desktop.
 * 599px la nguong cua chinh block khi overlayMenu = "mobile".
 */
@media (max-width: 599px) {
	.fs-masthead .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
		align-items: center;
		justify-content: center;
		width: 40px;
		height: 40px;
		border-radius: 999px;
		color: var(--fs-ink);
		background: rgba(255, 255, 255, 0.05);
		box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.10);
		transition: background-color var(--fs-dur) var(--fs-ease), transform var(--fs-dur-fast) var(--fs-ease);
	}

	.fs-masthead .wp-block-navigation__responsive-container-open:active {
		transform: scale(0.94);
	}
}

/* Nút đóng lặp lại đúng hình dạng của nút mở, để nó đọc ra là cùng một cái nút. */
.fs-masthead .wp-block-navigation__responsive-container-close {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border-radius: 999px;
	color: var(--fs-ink);
	background: rgba(255, 255, 255, 0.05);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.10);
	transition: transform var(--fs-dur-fast) var(--fs-ease);
}

.fs-masthead .wp-block-navigation__responsive-container-close:active {
	transform: scale(0.94);
}

/*
 * Khi menu mở, masthead phải bỏ `backdrop-filter`.
 *
 * Một phần tử có backdrop-filter trở thành KHỐI CHỨA cho mọi hậu duệ
 * `position: fixed`. Lớp phủ menu của block nằm bên trong masthead và khai báo
 * `position:fixed; inset:0` — nhưng nó tính theo viên thuốc chứ không phải theo
 * màn hình, nên nó ra đúng 390×74 và bị cắt còn hai dòng chữ ở đỉnh trang.
 *
 * WordPress gắn `has-modal-open` lên <html> khi lớp phủ mở, nên dùng đúng cái đó
 * làm công tắc. Bỏ kính đúng lúc này không mất gì: chính lớp phủ đã che kín màn.
 */
html.has-modal-open header.wp-block-template-part > header.fs-masthead {
	/*
	 * Phải tắt cả hoạt ảnh, không chỉ ghi đè thuộc tính.
	 *
	 * Hoạt ảnh thắng mọi khai báo thường bất kể độ đặc hiệu, nên @keyframes của
	 * hiệu ứng đặc-dần-theo-cuộn sẽ khẳng định lại backdrop-filter và khối chứa
	 * quay lại. Ngay cả `blur(0)` cũng đủ tạo khối chứa — bất kỳ giá trị nào
	 * khác `none` đều tính.
	 */
	animation-name: none;
	-webkit-backdrop-filter: none;
	backdrop-filter: none;
}

/* Lớp phủ: kính dày phủ kín màn. Nó cố định nên được phép dùng backdrop-filter. */
.fs-masthead .wp-block-navigation__responsive-container.is-menu-open {
	padding: 26px 22px 40px;
	background-color: rgba(4, 13, 19, 0.86);
	-webkit-backdrop-filter: saturate(150%) blur(26px);
	backdrop-filter: saturate(150%) blur(26px);
}

/*
 * Bốn dòng dồn lên đỉnh để lại 500px trống phía dưới, đọc ra như lớp phủ chưa
 * tải xong. Căn giữa theo chiều dọc thì khoảng trống chia đều hai đầu và trở
 * thành khoảng thở. Dùng dvh chứ không phải vh: trên Safari iOS thanh địa chỉ
 * thu vào nhả ra làm vh nhảy, và menu sẽ giật theo.
 */
.fs-masthead .is-menu-open .wp-block-navigation__responsive-container-content {
	display: flex;
	flex-direction: column;
	justify-content: center;
	min-height: calc(100dvh - 150px);
}

/*
 * Canh trái, không canh phải.
 *
 * Thanh desktop canh phải vì menu bám vào mép phải của viên thuốc. Trong lớp phủ
 * toàn màn thì mỗi dòng bắt đầu ở một chỗ khác nhau, mắt phải nhảy để tìm đầu
 * dòng tiếp theo. Bốn dòng thẳng một mép trái đọc trong một lượt.
 */
.fs-masthead .is-menu-open .wp-block-navigation__container {
	/*
	 * Phai ghi de bien, khong phai ghi de align-items.
	 *
	 * Core doc canh le tu `--navigation-layout-justification-setting`, va bien do
	 * dang la flex-end vi thanh desktop canh phai. Ghi thang `align-items` thi hai
	 * quy tac cung do dac hieu va thang thua phu thuoc vao thu tu nap stylesheet —
	 * lan dau minh viet nhu vay va core thang.
	 */
	--navigation-layout-justification-setting: flex-start;
	--navigation-layout-align: flex-start;
	gap: 2px;
	width: 100%;
	/*
	 * <ul> dang gian ra day chieu cao lop phu (638px cho 210px noi dung), nen
	 * canh giua dat tren no khong co tac dung. Cho no co lai bang chinh noi dung
	 * roi de khoi cha canh giua — mot cho quyet dinh, khong phai hai.
	 */
	flex: 0 0 auto;
	text-align: left;
}

.fs-masthead .is-menu-open .wp-block-navigation-item__content {
	padding: 12px 0;
	font-size: 27px;
	font-family: var(--wp--preset--font-family--display);
	font-weight: 600;
	letter-spacing: -0.03em;
	color: var(--fs-ink);
}

/* Trong lớp phủ, viên thuốc nền không còn hợp — chữ đã đủ lớn để tự đứng. */
.fs-masthead .is-menu-open .wp-block-navigation-item__content::before {
	display: none;
}

.fs-masthead .is-menu-open .current-menu-item > .wp-block-navigation-item__content {
	color: var(--fs-cyan);
}

/*
 * Các mục hiện lên lần lượt chứ không bật ra cùng một lúc.
 *
 * Độ trễ tăng dần làm mắt đi từ trên xuống theo đúng thứ tự đọc. Bật ra cùng lúc
 * thì lớp phủ đọc như một tấm ảnh chèn vào, không phải một thứ vừa mở ra.
 */
@media (prefers-reduced-motion: no-preference) {
	.fs-masthead .is-menu-open .wp-block-navigation__container > li {
		animation: fs-nav-vao 620ms var(--fs-ease) both;
	}

	.fs-masthead .is-menu-open .wp-block-navigation__container > li:nth-child(1) { animation-delay: 60ms; }
	.fs-masthead .is-menu-open .wp-block-navigation__container > li:nth-child(2) { animation-delay: 110ms; }
	.fs-masthead .is-menu-open .wp-block-navigation__container > li:nth-child(3) { animation-delay: 160ms; }
	.fs-masthead .is-menu-open .wp-block-navigation__container > li:nth-child(4) { animation-delay: 210ms; }
	.fs-masthead .is-menu-open .wp-block-navigation__container > li:nth-child(n + 5) { animation-delay: 260ms; }

	@keyframes fs-nav-vao {
		from {
			opacity: 0;
			transform: translateY(26px);
		}

		to {
			opacity: 1;
			transform: none;
		}
	}
}

/* --------------------------------------------------------- responsive */

@media (max-width: 900px) {
	header.wp-block-template-part > header.fs-masthead {
		padding: 13px 0 !important;
	}

	.fs-masthead__bar.wp-block-group {
		padding-inline: 18px;
		gap: 14px;
	}

	/*
	 * Bỏ `background-attachment: fixed` ở màn hẹp.
	 *
	 * Với `fixed`, ảnh nền được co về đúng khổ viewport chứ không phải khổ của
	 * dải chứa nó. Trên màn 390px thì `cover` cắt lấy đúng vùng giữa ảnh — chỗ
	 * tối nhất — nên kết cấu biến mất, dải CTA thành một mảng đen trơn.
	 *
	 * Đây cũng là thuộc tính iOS Safari xử lý sai từ lâu (phóng ảnh và giật khi
	 * cuộn). Mình chưa kiểm được trên máy iOS thật, nên đây là phòng ngừa.
	 */
	.wp-block-flexa-container {
		background-attachment: scroll !important;
	}

	.fs-masthead__end.wp-block-group {
		gap: 10px;
	}

	/*
	 * .fs-pagehead là core/group, và core/group chỉ có MỘT giá trị padding cho
	 * mọi khổ màn. 132px chừa chỗ cho viên thuốc nổi ở desktop; xuống dưới 900px
	 * thanh đã bám sát đỉnh và chỉ cao ~62px, nên 132 thành một mảng trống thừa.
	 */
	.fs-pagehead {
		padding-top: 96px !important;
	}
}

/*
 * Chỉ khi menu đã thu thành nút hamburger (dưới 600px) thì nút hành động mới
 * đảo lên trước. Ở khoảng 600–900px bốn liên kết vẫn hiện, và đẩy nút lên trước
 * chúng thì thứ tự đọc thành: tên site — nút — menu, tức là cái nút chen ngang
 * giữa hai thứ vốn liền nhau.
 */
@media (max-width: 599px) {
	.fs-masthead__cta {
		order: -1;
		margin-left: 0;
		padding-left: 0;
	}

	.fs-masthead__cta::before {
		display: none;
	}
}

/*
 * Dưới 430px cả hàng vừa đủ chỗ, không dư. Thu nhỏ tên thương hiệu và bóp nút
 * hành động lại, chứ không giấu tên đi: một dấu nhận diện không kèm tên thì trên
 * màn hình đầu tiên người xem không biết mình đang ở đâu.
 */
@media (max-width: 430px) {
	.wp-block-site-title a {
		font-size: 16px !important;
		gap: 7px;
	}

	.wp-block-site-title a::before {
		width: 23px;
		height: 23px;
	}

	.fs-masthead__cta .wp-block-button__link {
		padding-left: 15px !important;
		font-size: 13.5px;
	}

	.fs-masthead__cta .wp-block-button__link::after {
		width: 26px;
		height: 26px;
	}
}

/*
 * ============================================================================
 * TRANG THƯ VIỆN — khung trình duyệt trên thẻ, và thanh lọc thành thanh công cụ
 * ============================================================================
 *
 * Cả hai thứ dưới đây block không có ô để chỉnh. Số cột, tỉ lệ ảnh, hiệu ứng
 * phóng khi rê chuột, nhãn nút — tất cả vẫn nằm trong thuộc tính của block.
 *
 * Chỉ nhắm vào đúng hai khối của trang này (`-libgrid`, `-libfilter`) chứ không
 * nhắm chung mọi post-grid: thẻ ở trang chủ hẹp hơn nhiều, một thanh tiêu đề giả
 * 32px trên đó chiếm mất phần đáng kể của ảnh.
 */

/* ---------------------------------------- thẻ template thành cửa sổ trình duyệt */

/*
 * Ảnh preview đóng trong một khung trình duyệt giả — đúng mô-típ đang dùng ở
 * màn hình đầu trang chủ. Nó trả lời ngay câu hỏi đầu tiên người xem đặt ra khi
 * nhìn một ô ảnh: "đây là ảnh minh hoạ hay một website thật?"
 */
.flexa-post-grid-libgrid .flexa-post-grid__grid {
	counter-reset: fs-tpl;
}

.flexa-post-grid-libgrid .flexa-post-grid__item {
	position: relative;
	counter-increment: fs-tpl;
}

/*
 * Khung ảnh giờ là vật thể của thẻ, nên nó mang luôn phần bo góc và vành mảnh mà cái hộp thẻ cũ
 * từng mang. Bo 14 chứ không phải 24: đây là một cửa sổ trình duyệt, không phải một tấm thẻ.
 */
.flexa-post-grid-libgrid .flexa-post-grid__image-wrap {
	position: relative;
	padding-top: 24px;
	overflow: hidden;
	z-index: 1;
	border-radius: 12px;
	background: var(--fs-surface-2);
	box-shadow: inset 0 0 0 1px rgba(230, 244, 248, 0.09);
	transition: box-shadow var(--fs-dur) var(--fs-ease);
}

.flexa-post-grid-libgrid .flexa-post-grid__item:hover .flexa-post-grid__image-wrap {
	box-shadow: inset 0 0 0 1px rgba(34, 211, 238, 0.35);
}

/* Thanh tiêu đề giả */
.flexa-post-grid-libgrid .flexa-post-grid__image-wrap::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 24px;
	background: linear-gradient(180deg, rgba(255, 255, 255, 0.13), rgba(255, 255, 255, 0.045));
	border-bottom: 1px solid rgba(255, 255, 255, 0.09);
	transition: background-color var(--fs-dur) var(--fs-ease);
}

/* Ba chấm đèn giao thông */
.flexa-post-grid-libgrid .flexa-post-grid__image-wrap::after {
	content: "";
	position: absolute;
	top: 9px;
	left: 11px;
	width: 32px;
	height: 6px;
	border-radius: 999px;
	background: radial-gradient(circle 3px at 3px 3px, #ff5f57 98%, transparent),
		radial-gradient(circle 3px at 16px 3px, #febc2e 98%, transparent),
		radial-gradient(circle 3px at 29px 3px, #28c840 98%, transparent);
	opacity: 0.85;
}

/* Rê chuột: thanh tiêu đề ám cyan, cùng nhịp với vành sáng của cả thẻ */
.flexa-post-grid-libgrid .flexa-post-grid__item:hover .flexa-post-grid__image-wrap::before {
	background: linear-gradient(180deg, rgba(34, 211, 238, 0.22), rgba(34, 211, 238, 0.07));
}

/* ------------------------------------------------ thư viện: thanh lọc */

/*
 * VÌ SAO VIẾT LẠI.
 *
 * Bản trước gói cả thanh vào một cái khay: nền mờ, vành 1px, bo 16, đổ bóng. Bên trong khay là một
 * ô tìm bo 999, rồi ba viên thuốc cũng bo 999, rồi một liên kết gạch chân. Hộp lồng viên thuốc lồng
 * viên thuốc — bốn mức bo tròn khác nhau chồng lên nhau trong một dải cao 74px, và cái được nhấn
 * mạnh nhất lại là cái khay, thứ không bấm được.
 *
 * Giờ bỏ khay. Thanh lọc là một hàng đặt trên một đường kẻ, giống thanh công cụ: thứ duy nhất có
 * hình dạng đóng kín là những cái bấm được.
 */
.flexa-post-filter-libfilter.wp-block-flexa-post-filter {
	align-items: center;
	justify-content: flex-start;
	/*
	 * KHÔNG xuống dòng từ 768px trở lên.
	 *
	 * Dãy chip là một vùng cuộn, nên bề rộng nội dung của nó bằng tổng bề rộng mọi chip — với mười
	 * bốn danh mục là 1396px. Flexbox quyết định xuống dòng theo bề rộng CƠ SỞ đó, trước khi nó co
	 * bất cứ thứ gì lại: hàng thấy 1396 + 216 không vừa 1160 nên đá ô tìm xuống dòng hai, và thanh
	 * lọc cao 100px thay vì 38px.
	 *
	 * `nowrap` buộc mọi thứ ở lại một hàng, và lúc đó `min-width: 0` trên dãy chip mới có tác dụng:
	 * nó co xuống đúng phần còn thừa và phần dôi ra thành nội dung cuộn.
	 */
	flex-wrap: nowrap;
	width: 100%;
	max-width: 100%;
	/* Bám mép trái của lưới. Tiêu đề, thanh này và hàng thẻ dùng chung một trục dọc. */
	margin-inline: 0;
	gap: 10px;
	padding: 0 0 18px;
	border-bottom: 1px solid rgba(230, 244, 248, 0.1);
	border-radius: 0;
	background: none;
	box-shadow: none;
}

/*
 * Nhóm trường co vừa nội dung, KHÔNG giãn hết hàng.
 *
 * `flex: 1` là thứ đẩy nút "Xoá bộ lọc" ra tận mép phải — nó nằm ngoài nhóm này, nên nhóm giãn tới
 * đâu là nút bị đẩy tới đó. Co lại thì cả cụm điều khiển đứng liền nhau ở mép trái.
 */
.flexa-post-filter-libfilter .flexa-post-filter__fields {
	align-items: center;
	gap: 10px;
	flex: 1 1 auto;
	min-width: 0;
	/*
	 * Ba trường là con của KHỐI NÀY, không phải của cái form — nên `nowrap` phải đặt ở đây thì mới
	 * chặn được ô tìm rơi xuống dòng hai. Đặt ở form là đặt sai tầng.
	 */
	flex-wrap: nowrap;
}

/*
 * CẢ HÀNG CÙNG MỘT HÌNH DẠNG.
 *
 * Bản trước cho ô tìm bo 10 còn chip bo 999, ngăn nhau bằng một vạch dọc: ba hình dạng khác nhau
 * trong một hàng cao 38px, và ô tìm rộng 300px cao hơn chip nên nó đọc ra như một khối lạc vào.
 *
 * Giờ tất cả cùng là viên thuốc, cùng chiều cao, chỉ khác nhau ở chức năng — ô tìm có kính lúp và
 * một mặt nền nhạt, chip thì rỗng.
 */

/*
 * THỨ TỰ: DANH MỤC BÊN TRÁI, Ô TÌM BÊN PHẢI.
 *
 * Duyệt danh mục là việc chính ở trang này; gõ tên là việc của người đã biết mình tìm gì. Cái
 * chính đứng trước.
 *
 * Đổi chỗ còn giải quyết chuyện bố cục: ô tìm rộng cố định 216px neo ở mép phải, dãy chip bám mép
 * trái và nở theo số danh mục. Hai đầu hàng luôn có thứ để nhìn, dù có 2 danh mục hay 20 — khác
 * bản trước, nơi mọi thứ dồn trái và mép phải bỏ trống 600px.
 */
.flexa-post-filter-libfilter .flexa-filter-field--search {
	order: 3;
	flex: 0 0 auto;
	width: 280px;
	margin-left: auto;
}

/*
 * CỠ CHỮ BÁM THANG CỦA THEME.
 *
 * `theme.json` khai x-small 0.8125rem = 13px, và cả site dùng đúng cỡ đó cho mọi thứ bấm được:
 * liên kết trên thanh điều hướng 13px, nút "Xem thư viện" cũng 13px. Thanh lọc trước đây 14.5px —
 * một con số không nằm trên thang nào cả, và to hơn cả nav ngay phía trên nó.
 */
.flexa-post-filter-libfilter .flexa-filter-field__control {
	min-width: 0;
	font-size: 0.8125rem;
}

.flexa-post-filter-libfilter .flexa-filter-field__search-wrap .flexa-filter-field__control {
	padding-left: 40px;
}

.flexa-post-filter-libfilter .flexa-filter-field__search-icon {
	left: 15px;
	width: 15px;
	height: 15px;
}

/*
 * DÃY DANH MỤC PHẢI CHỊU ĐƯỢC NHIỀU DANH MỤC.
 *
 * Với hai ba danh mục thì kiểu gì cũng đẹp. Thêm tới mười lăm cái thì dãy chip xuống dòng thành
 * một mảng chip ba hàng cao 130px, đẩy cả lưới xuống và biến thanh lọc thành phần nặng nhất màn
 * hình — trong khi nó chỉ là công cụ.
 *
 * Nên dãy chip chạy MỘT HÀNG, cuộn ngang khi không đủ chỗ:
 *   - `flex: 0 1 auto` + `min-width: 0`: ít danh mục thì rộng đúng bằng nội dung; nhiều thì co lại
 *     đúng phần còn thừa của hàng và phần dôi ra nằm trong vùng cuộn.
 *   - `nowrap`: không bao giờ xuống dòng, nên chiều cao thanh lọc là hằng số.
 *   - Ẩn thanh cuộn: một thanh cuộn ngang 15px dưới dãy chip cao 32px trông như lỗi. Chip bị cắt
 *     nửa ở mép phải đã là dấu hiệu đủ rõ rằng còn nữa.
 */
.flexa-post-filter-libfilter .flexa-filter-field--taxonomy {
	order: 1;
	flex: 0 1 auto;
	min-width: 0;
	/* Khi dãy chip đầy và chip cuối bị cắt giữa chừng, chừa chỗ để nó không dính vào ô tìm. */
	margin-right: 8px;
}

.flexa-post-filter-libfilter .flexa-filter-field__options--pills {
	flex-wrap: nowrap;
	overflow-x: auto;
	scrollbar-width: none;
	-ms-overflow-style: none;
	/* Chừa chỗ cho vành focus 2px của chip khỏi bị vùng cuộn cắt mất. */
	padding: 3px;
	margin: -3px;
	scroll-padding-inline: 3px;
}

.flexa-post-filter-libfilter .flexa-filter-field__options--pills::-webkit-scrollbar {
	display: none;
}

/* Chip không được co lại thành chữ xuống dòng khi hàng chật — nó cuộn, không nén. */
.flexa-post-filter-libfilter .flexa-filter-field__option {
	flex: 0 0 auto;
}

/*
 * Vòng sáng lúc con trỏ ở trong ô: mảnh thôi.
 *
 * Mặc định là một quầng dày 3px quanh ô rộng 258px — mảng màu lớn nhất trên cả thanh, trong khi nó
 * chỉ cần báo "đang gõ ở đây".
 */
.flexa-post-filter-libfilter .flexa-filter-field__control:focus,
.flexa-post-filter-libfilter .flexa-filter-field__control:focus-visible {
	box-shadow: 0 0 0 1px rgba(34, 211, 238, 0.35);
}

/*
 * Chỉ còn phần hình dạng ở đây; toàn bộ màu của chip do thuộc tính block sinh ra (xem ghi chú ở
 * `controlBackground` trong page-library.php). Riêng vành lúc rê chuột thì bộ sinh CSS không đụng
 * tới, nên nó ở lại đây.
 */
.flexa-post-filter-libfilter .flexa-filter-field__options--pills .flexa-filter-field__option-text {
	padding: 7px 15px;
	font-size: 0.8125rem;
}

.flexa-post-filter-libfilter
	.flexa-filter-field__options--pills
	.flexa-filter-field__option:hover
	.flexa-filter-field__option-input:not(:checked)
	+ .flexa-filter-field__option-text {
	border-color: rgba(230, 244, 248, 0.3);
	box-shadow: none;
	transform: none;
}

/*
 * Nền của chip: đè lên CSS block sinh ra, nên phải đặc hiệu hơn nó.
 *
 * Block in ra `.flexa-post-filter-libfilter .…__option-text` (3 class) và đặt nền chip theo
 * `buttonBackground` — giá trị đó đang phải dành cho màu chữ nút "Xoá bộ lọc" (xem ghi chú ở
 * page-library.php). Thêm hai class của chính khối vào đầu chuỗi là đủ thắng, không cần
 * `!important`.
 */
.flexa-post-filter.wp-block-flexa-post-filter.flexa-post-filter-libfilter
	.flexa-filter-field__options--pills
	.flexa-filter-field__option:hover
	.flexa-filter-field__option-input:not(:checked)
	+ .flexa-filter-field__option-text {
	background-color: rgba(255, 255, 255, 0.06);
	color: var(--fs-text, #e6f4f8);
}

.flexa-post-filter.wp-block-flexa-post-filter.flexa-post-filter-libfilter
	.flexa-filter-field__options--pills
	.flexa-filter-field__option-input:checked
	+ .flexa-filter-field__option-text {
	border-color: rgba(34, 211, 238, 0.5);
	background-color: rgba(34, 211, 238, 0.16);
	box-shadow: none;
}

/*
 * Nút xoá đứng ngay sau dãy chip, KHÔNG dạt sang mép phải.
 *
 * Dạt sang phải thì cụm điều khiển chiếm một phần ba trái, nút xoá dính mép phải, và ở giữa là
 * 600px trống — mà đường kẻ bên dưới lại kéo hết bề ngang nên nó tô đậm đúng chỗ trống đó. Cả
 * thanh đọc ra như một hàng bị đứt.
 *
 * Đặt nó cạnh dãy chip thì cụm điều khiển là một khối liền. Quan hệ cũng đúng hơn: xoá bộ lọc là
 * huỷ đúng mấy cái chip đó, không phải huỷ cả thanh.
 *
 * Bỏ gạch chân — gạch chân trong một hàng toàn nút đọc ra như liên kết lạc từ đoạn văn sang.
 */
.flexa-post-filter-libfilter .flexa-filter-field--reset {
	order: 2;
	flex: 0 0 auto;
	margin-left: 14px;
	align-items: center;
}

.flexa-post-filter-libfilter .flexa-filter-reset__control--link {
	opacity: 1;
	font-size: 0.8125rem;
	color: var(--fs-muted);
	text-decoration: none;
	transition: color var(--fs-dur) var(--fs-ease);
}

.flexa-post-filter-libfilter .flexa-filter-reset__control--link:hover,
.flexa-post-filter-libfilter .flexa-filter-reset__control--link:focus-visible {
	color: var(--fs-ink);
}

/*
 * Dòng đếm kết quả đứng ngay dưới thanh, ở đầu lưới.
 *
 * Bản trước đặt tuyệt đối nó vào mép phải khay, và ở trạng thái đã lọc nó chồng chữ lên nút "Xoá
 * bộ lọc" — phải chừa tay 132px cuối khay để tránh. Trả về đúng chỗ nó vốn nằm trong DOM thì hết
 * cả hai vấn đề, và nó vẫn ở ngay cạnh thứ làm nó thay đổi.
 */
.flexa-post-grid-libgrid .flexa-post-grid__status {
	margin: 0 0 22px;
	font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
	font-size: 0.8125rem;
	letter-spacing: 0.04em;
}

@media (max-width: 767px) {
	/*
	 * Màn hẹp thì đổi hẳn cách xếp: ô tìm một hàng riêng chiếm trọn bề ngang, dãy chip hàng dưới.
	 * Nhét cả hai vào một hàng 390px thì ô tìm còn chưa tới 150px.
	 */
	.flexa-post-filter-libfilter.wp-block-flexa-post-filter {
		flex-wrap: wrap;
	}

	.flexa-post-filter-libfilter .flexa-filter-field--search {
		order: 0;
		margin-left: 0;
	}

	.flexa-post-filter-libfilter .flexa-post-filter__fields {
		flex-wrap: wrap;
		width: 100%;
	}

	.flexa-post-filter-libfilter .flexa-filter-field--taxonomy {
		padding-left: 0;
		margin-left: 0;
	}

	.flexa-post-filter-libfilter .flexa-filter-field--taxonomy::before {
		display: none;
	}

	.flexa-post-filter-libfilter .flexa-filter-field--search {
		width: 100%;
	}
}

/* ------------------------------------------ thư viện: chiều sâu phía sau đầu trang */

/*
 * Nền đầu trang, viết lại.
 *
 * Bản trước là ba thứ chồng lên nhau: một radial teal canh giữa, hai quầng sáng lệch tâm, và một
 * lưới kỹ thuật 84px. Trên màn 1920 chúng cộng lại thành một mảng xanh đục chiếm gần hết màn hình
 * đầu — nền tranh chỗ với năm ảnh chụp template, đúng thứ mà ghi chú cũ ở đây dặn là đừng làm.
 *
 * Giờ còn một thứ: MỘT quầng cyan mờ neo ở góc trên bên trái, ngay sau chữ. Lệch tâm nên nó là bố
 * cục chứ không phải hoạ tiết, và ở 0.13 thì nó nâng mép trên lên chứ không nhuộm cả dải. Nền của
 * dải này = nền của trang, nên chỗ nối với khối bên dưới không còn đường ranh nào.
 *
 * Lưới kỹ thuật bỏ hẳn: nó là chi tiết duy nhất trên trang không nói gì về template nào cả.
 */
.fs-libhead {
	position: relative;
	isolation: isolate;
	overflow: hidden;
}

/*
 * Màn hẹp: neo ảnh nền về mép TRÁI, không canh giữa.
 *
 * Ảnh dựng cho khung 1440x600. Trên khung 390x700 thì `cover` phóng theo chiều cao, ảnh thành rộng
 * ~1685px và chỉ 390px lọt vào khung. Canh giữa thì đúng phần dàn thẻ sáng nhất nằm ngay sau đoạn
 * dẫn. Neo trái thì lọt vào khung là nửa trái — phần đã cố tình để gần như đen đặc, chính là chỗ
 * dành cho chữ.
 *
 * Đè bằng hai class để thắng CSS block sinh ra (một class, in inline nên nó thắng khi hoà).
 */
@media (max-width: 767px) {
	.fs-libhead.wp-block-flexa-container {
		background-position: left center;
	}
}

/*
 * Quầng sáng vẽ bằng CSS ở đây đã BỎ.
 *
 * Dải này giờ có ảnh nền thật, và trong ảnh đã có hai nguồn sáng riêng. Giữ thêm một quầng cyan
 * của CSS đè lên nữa thì thành ba nguồn sáng trong một khung hình, mỗi cái một tâm — nền đục lên
 * và mất luôn chiều sâu mà phối cảnh của ảnh tạo ra.
 */

/*
 * Không còn vạch tóc khép dải đầu trang: băng ngay dưới giờ là nền ngà, nên ranh giới tối-sáng đã
 * rõ hơn bất cứ đường 1px nào — và một vạch sáng đặt đúng chỗ chuyển đó thì không nhìn thấy.
 */
/* --------------------------------------------- thư viện: nhịp của lưới thẻ */

/*
 * Không còn ngoại lệ nào về kích thước thẻ.
 *
 * Trước đây có hai: `featureFirst` cho thẻ ĐẦU tràn cả hàng, và một quy tắc ở đây cho thẻ CUỐI
 * tràn hàng khi nó đứng một mình. Với đủ 5 mẫu thì ra 1 + 2 + 2, nhìn cân. Nhưng lọc "Product" còn
 * 4 mẫu thì ra 1 + 2 + 1-tràn-hàng — hai thẻ khổng lồ ở hai đầu, ảnh to gấp bốn hai thẻ giữa.
 *
 * Hình dạng của danh sách đổi theo số kết quả trả về, mà số đó do người dùng bấm chip quyết định.
 * Không có cách nào canh cho đẹp mọi trường hợp, và bản thân việc nó nhảy hình khi lọc đã là một
 * lỗi. Trong một danh sách template thì mẫu nào cũng là một sản phẩm ngang nhau — thẻ bằng nhau ở
 * mọi số lượng là câu trả lời đúng, không phải một ngoại lệ khéo hơn.
 */
/* --------------------------------------- thư viện: mọi thứ chung một mép trái */

/*
 * Canh trái cho dòng đếm kết quả nằm ở THUỘC TÍNH block (`resultCountAlign`),
 * không ở đây — block có sẵn ô đó.
 */

/* ------------------------------- thư viện: dải ảnh, lớp phủ đổi chiều khi hết chỗ cho hai cột */

/*
 * Lớp phủ của dải ảnh là gradient NGANG: đậm bên trái nơi đặt chữ, nhạt dần sang phải để tấm ảnh
 * còn nhìn được. Thuộc tính `background` của block chỉ giữ được MỘT gradient, không có ô theo thiết
 * bị, nên dưới 900px — nơi cột chữ chiếm trọn bề ngang — đoạn nhạt bên phải nằm ngay dưới chữ và
 * dòng nào chạm tới đó cũng mất tương phản. Đo ở 390px: hai dòng cuối của đoạn mô tả.
 *
 * Ở bề ngang đó không còn "bên trái" để mà đậm, nên phủ đều cả dải và chấp nhận ảnh mờ hơn: đọc
 * được chữ quan trọng hơn nhìn rõ tấm ảnh nền.
 */
@media (max-width: 899px) {
	.fs-libwall.wp-block-flexa-container {
		background-image: linear-gradient(
			180deg,
			rgba(4, 13, 19, 0.9) 0%,
			rgba(4, 13, 19, 0.93) 55%,
			rgba(4, 13, 19, 0.96) 100%
		);
	}
}

/* ------------------------------------------------ thư viện: độ dài dòng của các đoạn dẫn */

/*
 * `flexa/text` và `flexa/heading` KHÔNG khai báo `size` hay `width` trong block.json — viết vào thì
 * bị bỏ đi lúc lưu, không báo lỗi, và đoạn văn chạy hết bề ngang cột. Đoạn dẫn của dải ảnh vì thế
 * dài 1160px: khoảng 150 ký tự một dòng, gấp đôi ngưỡng đọc thoải mái.
 *
 * Trong block thứ duy nhất đặt được bề ngang là containerType `boxed`, mà `boxed` thì căn giữa —
 * sai với hai khối này, cả hai đều bám mép trái. Nên đo chữ đặt ở đây.
 */
.fs-libhead .fs-lib-lead {
	max-width: 34rem;
}

.fs-libwall .flexa-container-libwallcopy {
	max-width: 34rem;
}

/* ------------------------------------------------- thư viện: thẻ bỏ hộp, chữ nằm trên nền trang */

/*
 * Nhãn nhóm ngành GIỮ NGUYÊN viên thuốc.
 *
 * Bỏ hộp thẻ rồi thì phản xạ đầu tiên là bỏ luôn viên thuốc cho nhẹ, nhưng lý do nó tồn tại không
 * nằm ở cái thẻ: nó cùng hình dạng với chip trong thanh lọc ngay phía trên, nên người xem tự nối
 * được "bấm chip Product thì ra đúng những mẫu mang nhãn này". Ghi chú ở quy tắc chung
 * (`.flexa-post-grid__terms a`) nói đúng chỗ đó, và nó vẫn đúng khi thẻ không còn hộp.
 */

/* Tiêu đề gần nhãn hơn một chút so với mặc định của block: hai thứ này là một cụm. */
.flexa-post-grid-libgrid .flexa-post-grid__title {
	margin-top: 2px;
}

/* ------------------------------------------------- thư viện: thẻ có vỏ, có viền, có bóng */

/*
 * Thẻ quay lại là một cái hộp thật.
 *
 * Bản trước bỏ vỏ thẻ và thay bằng một quầng màu nhoè sau tấm ảnh. Ở khổ một-cột-một-hàng thì quầng
 * đó tách được tấm ảnh khỏi nền, nhưng ở bốn cột nó loang xuống cả phần chữ: mỗi thẻ ngồi trên một
 * vệt màu không có mép, bốn vệt cạnh nhau thành một dải ám màu chạy ngang trang. Ranh giới giữa hai
 * thẻ biến mất.
 *
 * Viền và bóng làm đúng việc đó mà không cần màu: viền cho thẻ một mép rõ, bóng đẩy nó ra trước nền.
 * Đây cũng là cách trình bày thẻ dùng chung của theme — lưới này thôi làm ngoại lệ, chỉ chỉnh lại
 * bo góc và đệm cho vừa khổ 260px.
 */
.flexa-post-grid.wp-block-flexa-post-grid.flexa-post-grid-libgrid .flexa-post-grid__item {
	padding: 10px 10px 18px;
	overflow: hidden;
	border: 1px solid rgba(230, 244, 248, 0.1);
	border-radius: 16px;
	background: var(--fs-surface);
	box-shadow: 0 16px 36px -28px rgba(0, 0, 0, 0.95);
	transition: transform var(--fs-dur) var(--fs-ease), border-color var(--fs-dur) var(--fs-ease),
		box-shadow var(--fs-dur) var(--fs-ease);
}

/*
 * Rê chuột: mép thẻ ám màu CỦA MẪU đó, không phải cyan dùng chung. Đây là chỗ duy nhất còn giữ lại
 * màu riêng của từng template sau khi bỏ quầng sáng — nhãn nhóm ngành và tiêu đề lo phần còn lại.
 */
.flexa-post-grid.wp-block-flexa-post-grid.flexa-post-grid-libgrid .flexa-post-grid__item:hover {
	transform: translateY(-3px);
	border-color: color-mix(in srgb, var(--fs-tpl) 45%, transparent);
	box-shadow: 0 26px 50px -28px rgba(0, 0, 0, 0.95);
}

/* Ảnh nằm trong lòng thẻ nên bỏ bóng riêng: hai lớp bóng lồng nhau chỉ làm mép ảnh đục đi. */
.flexa-post-grid.wp-block-flexa-post-grid.flexa-post-grid-libgrid .flexa-post-grid__image-wrap {
	border-radius: 9px;
	border-bottom: 0;
	box-shadow: inset 0 0 0 1px rgba(230, 244, 248, 0.09);
	transition: box-shadow var(--fs-dur) var(--fs-ease);
}

/* ========================================================================== *
 * ÁNH SÁNG TRÔI SAU ĐẦU TRANG
 * ========================================================================== */

/*
 * TÊN LỚP: `fs-heroart`, KHÔNG PHẢI `fs-hero`.
 *
 * `.fs-hero` đã có sẵn trong theme từ trước, dành riêng cho banner trang chủ: nó mang `::before`
 * (ảnh ghép các bản xem trước) và `::after` (lưới kỹ thuật). Lần đầu tôi đặt trùng tên — hậu quả là
 * `::after` của tôi ghi đè lưới kỹ thuật của trang chủ, và hai trang kia thừa hưởng cả ảnh ghép
 * không liên quan.

/*
 * Ảnh nền đầu trang là một tấm JPEG tĩnh. Đặt lên trên nó một vệt sáng đi rất chậm thì cả dải thở,
 * mà không phải đổi màu gì: vệt dùng đúng cyan sẵn có, chỉ 8% độ đục.
 *
 * BA RÀNG BUỘC KỸ THUẬT, không phải để đẹp:
 *   - Chỉ chạy `transform` và `opacity`. Hai thứ này chạy trên luồng ghép hình, không bắt trình
 *     duyệt tính lại bố cục lần nào trong suốt 26 giây.
 *   - `mix-blend-mode: screen` để vệt CỘNG ánh sáng vào ảnh chứ không phủ một lớp đục lên trên —
 *     phủ thì phần tối của ảnh bị nâng lên xám và mất hết chiều sâu.
 *   - `pointer-events: none`, và nằm dưới nội dung: nó là ánh sáng, không phải một lớp chắn.
 */
.fs-libhead,
.fs-heroart {
	position: relative;
	overflow: hidden;
}

/*
 * XẾP LỚP BẰNG z-index DƯƠNG, KHÔNG DÙNG `isolation` + z-index ÂM.
 *
 * Bản đầu tôi để `isolation: isolate` trên băng và `z-index: -1` cho vệt sáng. Kết quả: ẢNH NỀN
 * BIẾN MẤT. Đo trên ảnh chụp trang, cùng một điểm ở sườn trái: có `isolation` thì ra (6,18,24) —
 * đúng bằng màu nền trang; bỏ đi thì ra (19,55,65) — màu thật của ảnh. Tắt riêng vệt sáng không
 * đổi gì, nên thủ phạm là `isolation`, không phải vệt sáng.
 *
 * Bỏ `isolation` thì vệt sáng ở z-index âm lại chui xuống dưới cả ảnh nền và không ai thấy. Nên
 * xếp lại cho tường minh: ảnh nền (nền của chính băng) → vệt sáng (z 0) → nội dung (z 1).
 */
.fs-libhead > *,
.fs-heroart > * {
	position: relative;
	z-index: 1;
}

.fs-libhead::after,
.fs-heroart::after {
	content: "";
	position: absolute;
	z-index: 0;
	top: -40%;
	left: -20%;
	width: 70%;
	height: 180%;
	pointer-events: none;
	border-radius: 50%;
	background: radial-gradient(closest-side, rgba(34, 211, 238, 0.28), transparent 70%);
	filter: blur(60px);
	opacity: 0.8;
	mix-blend-mode: screen;
	animation: fs-hero-troi 26s ease-in-out infinite alternate;
}

@keyframes fs-hero-troi {
	from {
		transform: translate3d(0, 0, 0) scale(1);
	}
	to {
		/* Đi ngang gần trọn dải và phình nhẹ. Không xoay: xoay một vệt tròn thì không ai thấy gì. */
		transform: translate3d(115%, 6%, 0) scale(1.25);
	}
}

/*
 * Nút chính: quầng sáng thở theo, chỉ ở trạng thái nghỉ.
 *
 * KHÔNG animate `box-shadow`. Bản đầu tôi làm thế và nó để lại một KHUNG CHỮ NHẬT rõ mép quanh nút:
 * box-shadow là thuộc tính phải VẼ LẠI, nên trình duyệt tách nút thành một lớp ghép hình riêng, và
 * cạnh của lớp đó hiện ra ngay trên nền đang blend của đầu trang.
 *
 * Thay bằng một lớp giả nhoè sẵn, chỉ cho `opacity` lên xuống. Opacity chạy trên luồng ghép hình,
 * không vẽ lại gì, nên không sinh mép nào cả.
 */
.fs-libhead .flexa-button--fill,
.fs-heroart .flexa-button--fill {
	position: relative;
}

.fs-libhead .flexa-button--fill::after,
.fs-heroart .flexa-button--fill::after {
	content: "";
	position: absolute;
	z-index: -1;
	inset: -10px;
	pointer-events: none;
	border-radius: inherit;
	background: var(--fs-cyan);
	filter: blur(16px);
	opacity: 0.22;
	animation: fs-nut-tho 3.8s ease-in-out infinite;
}

/* Rê chuột thì dừng: lúc đó nút phải trả lời cú rê chuột, không tiếp tục nhịp riêng. */
.fs-libhead .flexa-button--fill:hover::after,
.fs-heroart .flexa-button--fill:hover::after {
	animation: none;
	opacity: 0.38;
}

@keyframes fs-nut-tho {
	0%,
	100% {
		opacity: 0.16;
	}
	50% {
		opacity: 0.42;
	}
}

/*
 * Máy xin giảm chuyển động thì tắt cả hai. Vệt sáng vẫn ở lại nhưng đứng yên — nó là một phần của
 * hình, không phải hiệu ứng; bỏ hẳn thì đầu trang tối đi thấy rõ.
 */
@media (prefers-reduced-motion: reduce) {
	.fs-libhead::after,
	.fs-heroart::after,
	.fs-libhead .flexa-button--fill::after,
	.fs-heroart .flexa-button--fill::after {
		animation: none;
	}
}

/* -------------------------------------- thư viện: rê chuột thì ô ảnh chạy trang demo thật */

/*
 * Phần nhìn thấy của hiệu ứng hover-preview. Toàn bộ phần điều khiển nằm ở
 * assets/js/hover-preview.js — ở đây chỉ có chỗ đặt, tỉ lệ và nhịp chuyển.
 *
 * `.fs-live` là KHUNG CẮT: nó đứng yên, chỉ lo `overflow: hidden` và việc hiện ra khi tài liệu con
 * dựng xong. Thứ bị dịch là chính IFRAME bên trong.
 *
 * Đừng đảo hai vai này. Dịch khung cắt thì vùng cắt đi theo, cả cụm bay khỏi màn hình thay vì lộ
 * dần phần dưới trang — lần dựng đầu tôi làm đúng cái đó và đo được khung nằm ở y = -384px.
 */
.flexa-post-grid-libgrid .fs-live {
	position: absolute;
	/* Chừa đúng thanh tiêu đề giả phía trên (đệm trên của chính khung ảnh). */
	top: 24px;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 2;
	overflow: hidden;
	/*
	 * Không nhận chuột. Cả tấm ảnh nằm trong một thẻ <a> — để iframe ăn sự kiện thì bấm vào giữa
	 * thẻ sẽ không mở được demo, và cái được bấm lại là một trang nằm trong khung.
	 */
	pointer-events: none;
	opacity: 0;
	/*
	 * HOÀ HÌNH, không phải bật đèn.
	 *
	 * Trước dùng `var(--fs-ease)` — đường cong expo-out của theme, hợp cho một cú nhấc nút nhưng
	 * sai hẳn cho việc đổi ảnh: đo được độ mờ nhảy 0 → 0.73 trong khoảng 25ms đầu rồi bò nốt. Mắt
	 * đọc ra đúng một cú giật, vì ảnh tĩnh và trang demo không khung hình nào giống khung hình nào.
	 *
	 * Đường cong đều và dài hơn thì hai hình chồng lên nhau thật sự, thành một cú hoà hình.
	 */
	transition: opacity 340ms cubic-bezier(0.4, 0, 0.6, 1);
}

/*
 * Hai điều kiện, không phải một: `is-ready` = tài liệu con đã dựng xong, `is-on` = đang rê chuột.
 *
 * Khung giờ được dựng sẵn từ lúc thẻ lọt vào khung nhìn, nên nếu chỉ dựa vào `is-ready` thì mọi thẻ
 * đều hiện trang demo thay cho ảnh đại diện ngay khi trang mở — không ai rê chuột mà ảnh đã đổi.
 */
.flexa-post-grid-libgrid .fs-live.is-ready.is-on {
	opacity: 1;
}

.flexa-post-grid-libgrid .fs-live__frame {
	display: block;
	border: 0;
	/*
	 * Bề ngang cố định 1440px rồi thu nhỏ bằng transform, KHÔNG đặt `width: 100%`. Đặt 100% thì
	 * trang demo tự dựng lại ở bề ngang ~260px và rơi vào bố cục điện thoại — người xem sẽ thấy
	 * một bản mobile, đúng thứ mà thẻ này không định khoe.
	 */
	width: 1440px;
	transform-origin: top left;
	background: var(--fs-surface);
	/*
	 * Thời lượng do JS ghi đè theo quãng đường; ở đây chỉ định NHỊP.
	 *
	 * Đây là một cú lia dài vài giây, không phải một cú dịch ngắn — nên cần đường cong ĐỀU ở giữa.
	 *
	 * Bản trước tôi để `cubic-bezier(0.37, 0.02, 0.28, 1)`: điểm điều khiển thứ hai có y = 1 ngay tại
	 * x = 0.28, nghĩa là gần hết quãng đường bị dồn vào một phần ba thời gian đầu rồi bò nốt phần
	 * còn lại. Đo được đi 681/769px chỉ trong 0,7 giây dù thời lượng đặt là 2,5 giây — nhìn vẫn thấy
	 * vụt qua, đúng như đã bị chê.
	 *
	 * ease-in-out chuẩn: mềm ở hai đầu, đúng nửa quãng ở đúng nửa thời gian.
	 */
	transition: transform 600ms cubic-bezier(0.42, 0, 0.58, 1);
	will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
	.flexa-post-grid-libgrid .fs-live__frame {
		transition: none;
	}
}

/* ============================ thư viện: mỗi mẫu mang màu thương hiệu của chính nó */

/*
 * VÌ SAO PHẢI CÓ KHỐI NÀY.
 *
 * Cả trang thư viện chạy trên đúng một nền xanh đen, và thứ duy nhất có màu là một nút cyan cùng
 * mấy chữ "Xem demo" cũng cyan. Mọi băng, mọi hàng, mọi nhãn đều cùng một sắc. Đọc từ trên xuống
 * dưới thì không có gì để mắt bám vào — đó mới là cái làm trang trông rẻ tiền, không phải chuyện
 * thẻ xếp mấy cột.
 *
 * Mà màu thì đã có sẵn, đang nằm không: mỗi template mang một bộ token riêng, trong đó có
 * `nav-accent` — lime cho Axiom, teal cho Lumio, cam đất cho Marlo, tím cho Pulse, xanh lá cho
 * Sill. Dải ảnh chạy ngang ở đầu trang đã dùng màu đó rồi. Danh sách bên dưới thì chưa.
 *
 * Cho mỗi hàng mượn màu của chính mẫu nó giới thiệu: năm hàng thành năm thế giới khác nhau, đúng
 * bản chất của một danh sách template — mỗi mẫu vốn LÀ một hướng thiết kế riêng.
 *
 * CÁCH GẮN MÀU. Bắt theo đường dẫn của mẫu (`:has(a[href*="…"])`) chứ không theo thứ tự hàng
 * (`:nth-child`). Lọc "Product" thì thứ tự hàng đổi hết, màu sẽ nhảy lung tung; đường dẫn thì
 * không đổi. Đổi slug thì hàng đó rơi về cyan mặc định — hỏng nhẹ, không vỡ.
 *
 * MÀU HIỂN THỊ ≠ MÀU GỐC. Teal #0f766e của Lumio và xanh lá #1d6b46 của Sill là màu dùng trên nền
 * SÁNG của chính template đó; đặt lên nền #06121a thì tương phản còn ~2:1, đọc không ra. Hai mẫu
 * đó lấy bậc sáng hơn cùng tông. Ba mẫu còn lại vốn đã sáng, giữ nguyên.
 */
.flexa-post-grid-libgrid .flexa-post-grid__item {
	--fs-tpl: var(--fs-cyan);
}

.flexa-post-grid-libgrid .flexa-post-grid__item:has(a[href*="/axiom-saas"]) {
	--fs-tpl: #c2f04b;
}

.flexa-post-grid-libgrid .flexa-post-grid__item:has(a[href*="/lumio-saas"]) {
	--fs-tpl: #2dd4bf; /* gốc #0f766e — nâng bậc cho nền tối */
}

.flexa-post-grid-libgrid .flexa-post-grid__item:has(a[href*="/marlo-fintech"]) {
	--fs-tpl: #ff8b6b;
}

.flexa-post-grid-libgrid .flexa-post-grid__item:has(a[href*="/pulse-support"]) {
	--fs-tpl: #9b8cff;
}

.flexa-post-grid-libgrid .flexa-post-grid__item:has(a[href*="/sill-plants"]) {
	--fs-tpl: #4ade80; /* gốc #1d6b46 — nâng bậc cho nền tối */
}

/* ------------------------------------------------------------ nhãn, nút và quầng sáng */

/* Nhãn nhóm ngành mượn màu mẫu: vành và chữ, nền vẫn trong suốt để nó không thành mảng đặc. */
.flexa-post-grid.wp-block-flexa-post-grid.flexa-post-grid-libgrid .flexa-post-grid__terms a {
	border-color: color-mix(in srgb, var(--fs-tpl) 45%, transparent);
	background: color-mix(in srgb, var(--fs-tpl) 10%, transparent);
	color: var(--fs-tpl);
}

.flexa-post-grid.wp-block-flexa-post-grid.flexa-post-grid-libgrid .flexa-post-grid__terms a:hover {
	border-color: var(--fs-tpl);
	background: color-mix(in srgb, var(--fs-tpl) 18%, transparent);
	color: var(--fs-tpl);
}

/* Tiêu đề đổi sang màu mẫu khi rê chuột, thay cho cyan dùng chung của theme. */
.flexa-post-grid.wp-block-flexa-post-grid.flexa-post-grid-libgrid
	.flexa-post-grid__item:hover
	.flexa-post-grid__title a {
	color: var(--fs-tpl);
}

/* ------------------------------------------- thư viện: ô bento của khối "mẫu nào cũng có" */

/*
 * Bốn tấm đồ hoạ tự dựng (`build/gfx/board.html`) có nền riêng đậm hơn nền băng một chút, nên
 * chúng đã tách ra rồi — nhưng chỉ bằng độ sáng, và ở màn hình chỉnh sáng thấp thì mép biến mất.
 * Thêm một vành 1px làm mép chắc chắn, và cho ô nhấc lên khi rê chuột: cùng một ngôn ngữ với thẻ
 * template ở lưới phía trên, nên cả trang chỉ có MỘT cách "vật thể phản ứng lại con trỏ".
 */
.fs-bento__art .flexa-image__frame,
.fs-bento__art img {
	border-radius: 16px;
}

.fs-bento__art {
	border-radius: 16px;
	box-shadow: inset 0 0 0 1px rgba(230, 244, 248, 0.09),
		0 18px 44px -30px rgba(0, 0, 0, 0.9);
	transition: box-shadow var(--fs-dur) var(--fs-ease), transform var(--fs-dur) var(--fs-ease);
}

.fs-bento__art:hover {
	transform: translateY(-3px);
	box-shadow: inset 0 0 0 1px rgba(34, 211, 238, 0.32),
		0 26px 56px -30px rgba(0, 0, 0, 0.95);
}

/* Tiêu đề khối này bám mép trái và không cần dài hết cột — xem ghi chú về đo chữ ở trên. */
.fs-lib-h2 {
	max-width: 30rem;
}

/* --------------------------------- thư viện: chỗ cho thanh điều hướng khi nhảy mỏ neo */

/*
 * Mỏ neo #thu-vien nằm ngay đầu băng duyệt mẫu, mà thanh điều hướng là `position: fixed` cao 94px
 * — nhảy tới nó thì khay lọc chui xuống dưới thanh. `scroll-margin-top` chừa đúng chỗ đó ra.
 */
.fs-libtools {
	scroll-margin-top: 118px;
}
