/* =========================================================================
   LAYOUT — tầng KHUNG của theme (file 1/2, nạp TRƯỚC style.css)

   Hợp đồng 2 file (triage 2026-08-22):
   • layout.css  = KHUNG: site frame, grid, và toàn bộ máy móc overlay/bar/dock
                   (modal .layer/#actions, bottom bar + filter/destinations
                   popup, chat teaser/window). Không style component ở đây.
   • style.css   = BASIC + ENHANCE: token, base, component, trang, WC overrides;
                   đuôi file là khối ENHANCE (các cụm skin chuyển từ ut.css cũ,
                   giữ nguyên thứ tự gốc — vị trí CUỐI là cố ý, vài rule thắng
                   nhờ cascade: Book Now var(--color), inclusion padding 15px).
   Thứ tự nạp do dependency 'tb-layout' → 'tb-main' đảm bảo (functions.php +
   inc/enqueue.php), không dựa thứ tự đăng ký.

   Mục lục:
     1. Site wrapper / Header–Footer placeholder / Grid / Stack / PAGE
     2. Loop <ul> khung (ul.products block + center)
     3. #actions: layer docked ↔ popup, tab bar
     4. Bottom bar trang loop: in-flow ↔ dock, filter popup (.ut-fpop) + busy
        ring, destinations inline/in-flow/popup
     5. Layer scroll polish (mask + scrollbar)
     6. Chat teaser + chat window height (overlay của ut-assistant)

   Cụm nhòe đã CHỐT (triage 22/08): base .layer (vỏ backdrop fixed), chiều cao
   modal 88% và loop card 35/65 Ở LẠI style.css — chúng là DESIGN của owner;
   file này chỉ giữ máy móc ĐỔI VAI (docked ↔ popup, in-flow ↔ dock, popup
   position). Sửa hình dạng modal/card → style.css; sửa cơ chế bay/neo → đây.

   ⚠️ CẤM viết chuỗi kiểu hàm calc/min/max/clamp kèm ngoặc mở trong COMMENT —
   regex hide-calc của Autoptimize ăn xuyên comment (đã cắn 2026-08-09).
   ========================================================================= */

/* -------- Site wrapper -------- */
.site {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
}

.site-main {
	flex: 1 0 auto;
}

/* -------- Header (placeholder — your custom design overrides this) -------- */
.site-header {
	position: relative;
	background-color: var(--color-bg);
	border-bottom: 1px solid var(--color-border);
}

/* -------- Footer (placeholder — your custom design overrides this) -------- */
.site-footer {
	background-color: var(--color-bg-dark);
	color: var(--color-text-inverse);
}

/* -------- Grid utilities -------- */
.grid {
	display: grid;
	gap: var(--space-5);
}

.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }

@media (max-width: 1024px) {
	.grid-4 { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 768px) {
	.grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 480px) {
	.grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
}

/* -------- Stack (vertical spacing helper) -------- */
.stack > * + * {
	margin-top: var(--space-4);
}

.stack-lg > * + * {
	margin-top: var(--space-6);
}

/* -------- PAGE -------- */

.entry-header,
.page .entry-content {margin: 30px 0}

body.page .site-content {padding: 0 15px;}




/* ---------------------------------------------------------------------------
   WooCommerce loop: the razzi-child loop design lives in style.css. The
   scaffold's competing grid/card block was removed from
   assets/css/woocommerce.css so style.css governs the loop. Here we only keep
   the <ul> a plain block (full-width horizontal cards) and center it.
   --------------------------------------------------------------------------- */
.woocommerce ul.products,
.woocommerce-page ul.products,
ul.products {
  display: block;
  margin: 0 auto 30px auto;
}





/* ─── #actions DOCKED (2026-08-04): cùng MỘT node hai vai — ngồi inline cuối
   phần mô tả (is-docked) / bay lên popup (.open, flow cũ nguyên byte vì JS gỡ
   is-docked trước khi thêm open). Vỏ .layer vốn LÀ backdrop đen fixed 0×0 nên
   docked phải trung hoà trọn bộ vỏ. ── */
.layer.is-docked {position: static; width: auto; height: auto; opacity: 1;
	overflow: visible; background: none; backdrop-filter: none; display: block;
	transition: none; margin: 30px 0 0;     background-image: linear-gradient(125deg, #6492b2, #d2e6f6);
    padding: 150px 20px;
    margin: 0 auto;
    border-radius: 10px;}

@media screen and (max-width: 500px) {
	.layer.is-docked {padding: 50px 20px;}
}

.layer.is-docked .layer-header {overflow: hidden;}


.layer.is-docked .layer-body {opacity: 1; width: 100%; max-width: 100%; display: flex; flex-direction: column; background: #fff; border-radius: 5px; max-height: none; overflow: visible; margin: 0 auto;}
.layer.is-docked .layer-content {overflow: visible;}
.layer.is-docked .layer-close {display: none;} /* không có gì để đóng khi docked */
/* Popup phủ luôn bottom bar (bar fixed z-1000, trước đây hoà z và thắng nhờ
   DOM order — owner chốt backdrop đè bar). ID nên thắng mọi thứ tự nạp css. */
#actions {z-index: 1001;}

/* ─── Modal chung #actions (2026-07-21): tab bar giả lập button bottom-bar ── */
#actions .layer-body {width: 700px;}
#actions .layer-header {align-items: stretch;}
.ut-actions-tabs {display: flex; flex: 1; min-width: 0; overflow-x: auto;}
.ut-actions-tab {display: flex; flex-direction:column; align-items: center; padding: 10px 12px; background: transparent; border: none; font-size: 11px; font-weight: bold; text-transform: uppercase; color: var(--color-dark-blue, #16324c); cursor: pointer; white-space: nowrap; gap: 5px;}
.ut-svg-icon {flex: 0 0 auto; display: inline-block; vertical-align: middle;}
/* #tool: icon trong vòng tròn .wr — trắng như filter-white cũ của PNG. */
#tool .wr .ut-svg-icon {color: #fff; display: block;}
.bottom-bar .rg > * .ut-svg-icon {margin-right: 4px;}
.ut-actions-tab .ut-svg-icon {margin-right: 5px;}
.ut-actions-tab.is-active {background: var(--color-dark-blue, #16324c); color: #fff;}

.ut-actions-panel {display: none;}
.ut-actions-panel.is-active {display: block;}
#actions .layer-content {padding: 50px; width: 100%; box-sizing: border-box;
	/* Equal height theo TAB CAO NHẤT — JS đo lúc mở modal và set min-height
	   cho từng panel (footer.php equalizeActionPanels): modal không đổi cao
	   khi chuyển tab, không có không gian chết. Trần chiều cao đã do
	   max-height của layer-body gate; quá trần thì cuộn bên trong. */
	overflow-y: auto;}
@media screen and (max-width: 781px) {
	#actions .layer-content {padding: 25px 14px;}
	.ut-actions-tab {padding: 9px 9px;}
}

/* Animation chuyển tab trong #actions: panel mới fade + trượt nhẹ lên.
   Dùng animation (không phải transition) vì panel đi từ display:none —
   keyframes vẫn chạy khi class .is-active được gắn. */
.ut-actions-tab {transition: background .18s, color .18s;}
.ut-actions-panel.is-active {animation: utActionsPanelIn .28s ease;}
@keyframes utActionsPanelIn {
	from {opacity: 0; transform: translateY(8px);}
	to {opacity: 1; transform: none;}
}
@media (prefers-reduced-motion: reduce) {
	.ut-actions-panel.is-active {animation: none;}
	.ut-actions-tab {transition: none;}
}

/* ==================== BOTTOM BAR TRANG LOOP (2026-07-21) ==================== */
/* Nút Filter + Destinations bên trái thay chỗ giá — pill giống các button .rg
   (style.css). */
/* BAR TRONG DÒNG CHẢY (2026-08-03) — chỉ áp cho bar của trang loop.
   Bar trang product single giữ nguyên hành vi cũ (fixed + .stick).
   `position: static` thắng luật fixed ở style.css nhờ hai class, và opacity 1
   để khách chưa cuộn nhìn thấy ngay — đó là toàn bộ mục đích. */
.bottom-bar.loop-bar {position: static; opacity: 1; pointer-events: auto; visibility: visible;
	margin: 0 auto 14px; transition: none;}
/* Cuộn qua khỏi chỗ của nó → trả về fixed đáy đúng như trước. transition chỉ
   bật ở trạng thái này, nếu không lúc tải trang sẽ thấy nó trôi vào. */
.bottom-bar.loop-bar.is-docked {position: fixed; bottom: 0; left: 0; right: 0; margin: 0 auto;
	opacity: 1; pointer-events: auto; visibility: visible; transition: opacity .4s;
	box-shadow: 0px 0px 20px 0px rgba(0,0,0,.2); border-radius: 6px 6px 0 0;}
/* Chỗ trống giữ nguyên chiều cao khi bar rời khỏi dòng chảy — không có nó thì
   trang giật lên đúng bằng chiều cao bar tại khoảnh khắc dock. */
.ut-barslot {display: none;}
.ut-barslot.is-active {display: block;}

.bottom-bar.loop-bar .lf {display: flex; align-items: stretch;}
.bottom-bar .lf .ut-loop-filter,
.bottom-bar .lf .ut-loop-dest {padding: 5px 10px; display: flex; flex-direction: column;
	align-items: center; justify-content: center; gap: 3px; font-size: 11px;
	font-weight: bold; text-transform: uppercase; color: var(--color-dark-blue);
	white-space: nowrap; border-right: 1px solid #ccc; cursor: pointer;}
.bottom-bar .lf .ut-loop-filter:hover,
.bottom-bar .lf .ut-loop-filter.on,
.bottom-bar .lf .ut-loop-dest:hover,
.bottom-bar .lf .ut-loop-dest.on {background: #ddd;}

/* Body filter (.few = [fe_widget] sẵn có của loop) bật dạng popup cạnh nút
   Filter của bottom bar. .ut-fpop CHỈ đổi cách đặt (fixed ngay trên bar, mép
   trái theo mép bar) — hiện/ẩn nội dung vẫn đi qua class .on sẵn có của theme,
   nên mở từ nút .feb đầu trang vẫn là collapse in-flow như cũ. */
/* Gỡ cụm "Edit Filter Set" của FE (link admin, vô nghĩa với khách). display:none
   để nó không chiếm chỗ; markup vẫn do FE sinh nên đây là cách gỡ an toàn nhất
   khỏi phải chặn ở PHP. */
.wpc-edit-filter-set {display: none !important;}

.few.ut-fpop {position: fixed; bottom: 64px;
	/* Full-width (thiết kế cũ "mép trái khớp mép bar" đã bỏ 2026-08).
	   ⚠️ CẤM viết chuỗi kiểu hàm-calc/-min/-max/-clamp kèm ngoặc mở trong
	   comment CSS: regex hide-calc của Autoptimize (autoptimizeCSSmin::run)
	   không phân biệt comment, match tham lam tới dấu chấm-phẩy kế tiếp sẽ
	   nuốt cả dấu đóng comment lẫn declaration thật phía sau — chính bug đã
	   làm rule này mất left/right (2026-08-09). */
	left: 0; right: 0;
	/* !important vì .archive.woocommerce #main > * (style.css) set width/max-width
	   cho MỌI con trực tiếp của #main với specificity chứa ID. */
	max-height: calc(100vh - 140px);
	overflow-y: auto; overscroll-behavior: contain; z-index: 1001; background: #fff;
	border-radius: 10px;
	box-shadow: 0px 0px 25px 0px rgba(0,0,0,.3); padding: 5px 15px;
	/* Mode popup KHÔNG dùng bộ máy collapse của mode in-flow: bỏ grid 0fr/1fr
	   và mọi clamp trên con — container này là CHỦ CUỘN duy nhất. Thiếu các
	   override này, con bị .few.on > * {max-height:100%; overflow:hidden}
	   tự clip (nội dung dài bị cắt/tràn mà container không cuộn). */
	display: block;}

.few.ut-fpop.on > * {margin: 0; max-height: none !important; overflow: visible !important;}

/* Heading bar của popup filter: title "Filter" trái + nút close phải, sticky
   trên đỉnh scrollport (tham khảo head bar của hotel/inquiry modal). Selector
   đủ mạnh để thoát các rule con chung .few > * (max-height/opacity/bg). */
.few .ut-fpop-head {display: none;}
.few.ut-fpop {padding-top: 0;}
.few.ut-fpop .ut-fpop-head {display: flex; position: sticky; top: 0; z-index: 5;
	align-items: center; justify-content: space-between; gap: 10px;
	margin: 0 -15px 10px; padding: 5px 15px;
	background: #eee; border-bottom: 1px solid #eee;
	border-radius: 10px 10px 0 0;
	max-height: none !important; overflow: visible !important;
	/* Fade WITH the panel, not after it. The exemptions above exist so the
	   collapse machinery of `.few > *` cannot clip the head while the popup is
	   open — but an unconditional `opacity:1 !important` also pinned it through
	   the CLOSE: the body faded out, the head stayed at full strength, and 550ms
	   later the JS pulled `.ut-fpop` and it vanished in one frame. Tying the
	   opacity to `.on` keeps the exemption where it was needed and returns the
	   head to the shared fade. */
	opacity: 0; transition: opacity .35s ease;}
.few.ut-fpop.on .ut-fpop-head {opacity: 1 !important;}

/* The panel itself, same reasoning: while `.ut-fpop` is on the element it is a
   fixed white box with a shadow, and it kept both for the whole 550ms after the
   content had gone — a blank card hanging over the page. Fading the container
   takes the head, the background and the shadow out together, and the JS still
   removes the class afterwards, so nothing is cut short. */
.few.ut-fpop {opacity: 0; transition: opacity .35s ease;}
.few.ut-fpop.on {opacity: 1;}
/* Busy state: no curtain, no cursor games — just a ring beside the word FILTER.
   FE Pro's own signals were a full-screen overlay that swallowed clicks and a
   spinner parked away from what the user was looking at. Both are switched off
   in the plugin's settings (use_loader, dark_overlay); the two rules below are
   the belt to that braces, because the overlay ALSO has an unconditional
   `html.is-active` rule of its own — turning the "dark" option off only changes
   its colour, it still covers the page and still blocks the click.

   Interaction stays live throughout: filtering is fast and idempotent, and a
   second click during a request simply supersedes the first. Nothing needs
   protecting from the user here. */
.wpc-filters-overlay {display: none !important;}
.wpc-spinner {display: none !important;}

/* The ring lives inside the title, so the feedback appears where the eye
   already is. Its space is reserved at all times — an indicator that pushes the
   heading sideways as it appears reads as a glitch, not as progress. */
.ut-fpop-head__title {display: inline-flex; align-items: center; gap: 8px;}
.ut-fpop-head__title::after {content: ""; width: 13px; height: 13px; flex: 0 0 auto;
	border-radius: 50%; border: 2px solid rgba(0,0,0,.16); border-top-color: #2766ad;
	opacity: 0; transition: opacity .15s ease;}
/* `html.is-active` is FE Pro's own in-flight flag (filter-everything.js sets it
   when a request starts and clears it when the markup is back), so this tracks
   the real request rather than guessing at a duration. */
html.is-active .ut-fpop-head__title::after {opacity: 1; animation: ut-fpop-spin .7s linear infinite;}
@keyframes ut-fpop-spin {to {transform: rotate(360deg);}}
@media (prefers-reduced-motion: reduce) {
	html.is-active .ut-fpop-head__title::after {animation: none; border-top-color: rgba(0,0,0,.16); background: #2766ad;
		width: 7px; height: 7px; border: 0;}
}

.ut-fpop-head__title {font-size: 14px; font-weight: bold; text-transform: uppercase;
	letter-spacing: .5px; color: var(--color-dark-blue, #16324c);}
.ut-fpop-close {display: flex; align-items: center; justify-content: center;
	width: 32px; height: 32px; padding: 0; border: 0; border-radius: 50%;
	color: #000; font-size: 25px; line-height: 1; cursor: pointer; background: transparent;
	flex-shrink: 0;}
.ut-fpop-close:hover {color: #c90000;}

/* Destinations INLINE giữa bottom bar ở màn rộng (2026-07-22): ≥800px menu
   hiện mặc định trong khoảng trống giữa bar; nút Destinations thu/phóng qua
   class ut-dest-collapsed trên #bottombar (max-width transition). <800px các
   override này không áp → quay về popup .ut-cpop bên dưới. */
@media screen and (min-width: 800px) {
	.bottom-bar .caw {flex: 1; display: flex; justify-content: center; min-width: 0;
		overflow: hidden; max-width: 100%; opacity: 1;
		transition: max-width .3s ease, opacity .3s ease;}
	.bottom-bar.ut-dest-collapsed .caw {max-width: 0; opacity: 0;}
	.bottom-bar .caw .cm {position: static; opacity: 1; visibility: visible;
		background: none; padding: 0; justify-content: center; transition: none;}
	.bottom-bar .catbar {width: auto; max-width: none; background: none;
		box-shadow: none; padding: 0; font-size: 13px; border-radius: 0;
		backdrop-filter: none;}
	.bottom-bar .catbar ul {flex-wrap: nowrap; justify-content: center;}
	.bottom-bar .catbar ul li {width: auto; font-weight: normal; white-space: nowrap;}
}

/* Destinations IN-FLOW (mobile, bar CHƯA dock — 2026-08-06): bản clone .catbar
   trong #ut-dest-flow chèn ngay sau bar, nằm trong dòng chảy nên cuộn theo
   trang (fixed thì dính viewport, cuộn là "bơi" theo). Docked vẫn .ut-cpop. */
#ut-dest-flow {display: none;}
#ut-dest-flow.on {display: block;
	position: absolute; z-index: 1001;
	left: 50%; transform: translateX(-50%);
	width: var(--wid); max-width: var(--max, calc(100% - 30px));
	border-radius: 10px;}
#ut-dest-flow .catbar ul {flex-direction: column;}
#ut-dest-flow .catbar ul li a {padding: 10px 15px; display: block; width: 100%;}

/* Destinations popup từ bottom bar (<800px): .ut-cpop đổi .cm từ absolute
   (neo .caw) sang fixed ngay trên bar, mép trái khớp mép bar như popup filter;
   hiện/ẩn vẫn qua .caw.on (style.css). */
.caw .cm.ut-cpop {position: fixed; top: auto; right: auto; bottom: 64px;
	left: max(30px, calc((100% - var(--wid, 1170px)) / 2));
	max-width: calc(100vw - 60px); z-index: 1001; justify-content: flex-start;
	/* base .caw .cm để transition: all → đổi vị trí (left 0 → mép bar) cũng bị
	   animate thành slide ngang khi mở. Chỉ giữ fade. */
	transition: opacity .5s, visibility .5s;}

/* ========= LAYER SCROLL POLISH (2026-08-11) ========= */
/* Hộp cuộn thật là .layer-content bên trong .layer-body (bo góc + clip).
   1) Scrollbar mảnh, bo tròn, lùi vào trong — không đè lên góc bo của body.
   2) "Độ thở": nội dung mờ dần ~10px trước hai mép trên/dưới thay vì bị cắt
      phẳng đúng mép (mask áp cả lên scrollbar nên thanh cuộn cũng thở theo).
   Chỉ áp cho trạng thái popup (.open), KHÔNG áp khi is-docked (inline). */
.layer.open .layer-content {
	-webkit-mask-image: linear-gradient(180deg, transparent 0, #000 12px, #000 calc(100% - 12px), transparent 100%);
	mask-image: linear-gradient(180deg, transparent 0, #000 12px, #000 calc(100% - 12px), transparent 100%);
}
.layer.open .layer-content::-webkit-scrollbar {width: 8px;}
.layer.open .layer-content::-webkit-scrollbar-track {background: transparent; margin: 12px 0;}
.layer.open .layer-content::-webkit-scrollbar-thumb {background: #d5d5d8; border-radius: 8px; border: 2px solid #fff;}
.layer.open .layer-content::-webkit-scrollbar-thumb:hover {background: #bfbfc4;}
.layer.open .layer-content {scrollbar-width: thin; scrollbar-color: #d5d5d8 transparent;}

/* ========= CHAT TEASER (2026-08-11) ========= */
/* Bubble "Have some questions? Chat now." neo trên nút Chat của bottom bar.
   Nằm TRONG .bottom-bar nên thừa kế opacity/visibility theo .stick. */
.bottom-bar .ut-chat-teaser {
	position: absolute;
	bottom: calc(100% + 14px);
	right: 20px;
	background: #fff;
	color: #1d2327;
	border: 2px solid #1d2327;
	border-radius: 12px;
	padding: 10px 16px;
	font-size: 13px;
	font-weight: 600;
	line-height: 1.3;
	white-space: nowrap;
	cursor: pointer;
	box-shadow: 0 6px 20px rgba(0, 0, 0, .15);
	opacity: 0;
	transform: translateY(6px);
	transition: opacity .3s, transform .3s;
}
.bottom-bar .ut-chat-teaser.is-on {opacity: 1; transform: none;}
.bottom-bar .ut-chat-teaser:hover {background: #f5f8fb;}
/* Đuôi bubble chỉ xuống nút Chat: 2 lớp tam giác tạo viền như ảnh mẫu */
.bottom-bar .ut-chat-teaser::after {
	content: "";
	position: absolute;
	top: 100%;
	right: 26px;
	border: 9px solid transparent;
	border-top-color: #1d2327;
	border-left-width: 12px;
	border-right-width: 4px;
}
.bottom-bar .ut-chat-teaser::before {
	content: "";
	position: absolute;
	top: calc(100% - 3px);
	right: 28px;
	border: 7px solid transparent;
	border-top-color: #fff;
	border-left-width: 9px;
	border-right-width: 3px;
	z-index: 1;
}
.bottom-bar .ut-chat-teaser:hover::before {border-top-color: #f5f8fb;}
.ut-chat-teaser__close {
	position: absolute;
	top: -10px;
	right: -10px;
	width: 22px;
	height: 22px;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	border: 2px solid #1d2327;
	border-radius: 50%;
	background: #fff;
	color: #1d2327;
	font-size: 14px;
	line-height: 1;
	cursor: pointer;
}
.ut-chat-teaser__close:hover {background: #1d2327; color: #fff;}

/* ========= CHAT WINDOW HEIGHT (2026-08-11) ========= */
/* Theme timeless của assistant chỉ đặt max-height (trần) cho khung hội thoại
   nên phiên MỚI (ít tin nhắn, vd ẩn danh) khung lùn theo nội dung; phiên có
   lịch sử dài mới chạm trần. Ép cao cố định = --uta-maxHeight (admin set,
   đang 60vh) để mọi khách thấy khung cùng cỡ. Fullscreen giữ flex riêng. */
.uta-timeless-theme.uta-window:not(.uta-fullscreen) .uta-body {
	height: var(--uta-maxHeight);
}
.uta-timeless-theme.uta-window:not(.uta-fullscreen) .uta-conversation {
	flex: 1 1 auto;
	max-height: none;
	min-height: 0;
}
