/* =============================================================================================
 * Đại Ngàn — design token layer.
 *
 * Loaded last from templates/layout/css.php, after style.css and responsive.css, so it wins
 * on equal specificity without needing !important to do ordinary work.
 *
 * What this file can and cannot reach:
 * style.css carries 674 hardcoded hex literals against 287 var() uses — hardcoded colour
 * outnumbers variables 2.3 to 1 — and 220 hardcoded font-size rules, every one of them more
 * specific than a :root token. So a token layer alone cannot deliver the palette. The 16
 * literal occurrences of the legacy purple are substituted in place, in style.css and
 * style_slider.css, as a separate bounded edit; everything else is remapped from here.
 *
 * Colour is asserted in tests as *computed* style, never as stylesheet text, because a
 * literal-text search cannot see a value arriving through a variable or a later override.
 * ============================================================================================= */

/* ---------------------------------------------------------------------------------------------
 * 1. Typefaces
 *
 * Two families, aliased to new names rather than reusing the engine's sixteen. The aliases
 * mean Phase 8 can delete the unused @font-face blocks without any risk of pulling the two
 * that are in use out from under the site.
 *
 * Both are already hosted locally under assets/fonts/frontend/ and both cover the Vietnamese
 * precomposed range (ạ ệ ở ủ đ ỹ ắ ồ), verified against the files' cmap tables.
 *
 * Not Inter, which is what the engine's --fontInter* variables point at: all three Inter faces
 * 404. Every rule using them has been silently falling back to a system font.
 *
 * font-display: swap, not the engine's `block` — blocking on a webfont hides text for up to
 * three seconds on a cold cache.
 * ------------------------------------------------------------------------------------------- */

@font-face {
    font-family: 'RG Display';
    src: url('../fonts/frontend/Baloo2-Regular.woff') format('woff'),
         url('../fonts/frontend/Baloo2-Regular.ttf') format('truetype');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'RG Display';
    src: url('../fonts/frontend/Baloo2-Medium.woff') format('woff'),
         url('../fonts/frontend/Baloo2-Medium.ttf') format('truetype');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'RG Display';
    src: url('../fonts/frontend/Baloo2-SemiBold.woff') format('woff'),
         url('../fonts/frontend/Baloo2-SemiBold.ttf') format('truetype');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'RG Display';
    src: url('../fonts/frontend/Baloo2-Bold.woff') format('woff'),
         url('../fonts/frontend/Baloo2-Bold.ttf') format('truetype');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

/* Mulish ships Medium, Bold and Black only — no Regular — so 400 and 500 share Medium. */
@font-face {
    font-family: 'RG Text';
    src: url('../fonts/frontend/Mulish-Medium.woff') format('woff'),
         url('../fonts/frontend/Mulish-Medium.ttf') format('truetype');
    font-weight: 400 500;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'RG Text';
    src: url('../fonts/frontend/Mulish-Bold.woff') format('woff'),
         url('../fonts/frontend/Mulish-Bold.ttf') format('truetype');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'RG Text';
    src: url('../fonts/frontend/Mulish-Black.woff') format('woff'),
         url('../fonts/frontend/Mulish-Black.ttf') format('truetype');
    font-weight: 900;
    font-style: normal;
    font-display: swap;
}

/* ---------------------------------------------------------------------------------------------
 * 2. Tokens
 * ------------------------------------------------------------------------------------------- */

:root {
    /* Palette */
    --rg-forest: #0E1A13;   /* ink, hero scrim base */
    --rg-moss:   #3E6B4C;   /* secondary surface, footer */
    --rg-paper:  #EFEBE0;   /* page ground */
    --rg-card:   #F7F4EC;   /* cards, booking rail */
    --rg-ruby:   #8E2A38;   /* primary action only */
    --rg-ochre:  #D98B3A;   /* F&B and trải nghiệm — direction B texture */
    --rg-ok:     #2F7A4F;   /* còn phòng */
    --rg-warn:   #B3641B;   /* sắp hết */

    /* Derived surfaces. Kept as tokens so the ratios below stay checkable. */
    --rg-ink-muted: #47554C;
    --rg-rule: #D8D2C4;
    --rg-ruby-dark: #6E1F2B;
    --rg-moss-dark: #2C4D37;

    /* Type. --rg-text is the body face; --rg-display carries headings and numerals. */
    --rg-display: 'RG Display', 'Baloo2-SemiBold', system-ui, sans-serif;
    --rg-text: 'RG Text', 'Mulish-Medium', system-ui, sans-serif;

    /* Type scale. Body sits at 1rem so the 16px floor is a consequence, not a patch. */
    --rg-size-sm: 0.9375rem;  /* 15px — captions and meta only, never body copy */
    --rg-size-base: 1rem;     /* 16px */
    --rg-size-md: 1.125rem;   /* 18px */
    --rg-size-lg: 1.375rem;   /* 22px */
    --rg-size-xl: 1.75rem;    /* 28px */
    --rg-size-2xl: 2.25rem;   /* 36px */
    --rg-size-3xl: 3rem;      /* 48px */

    --rg-leading-tight: 1.2;
    --rg-leading: 1.6;

    /* Spacing rhythm */
    --rg-space-1: 8px;
    --rg-space-2: 12px;
    --rg-space-3: 20px;
    --rg-space-4: 32px;
    --rg-space-5: 52px;
    --rg-space-6: 84px;

    --rg-radius: 4px;
    --rg-radius-lg: 12px;
    --rg-focus: 0 0 0 3px rgba(142, 42, 56, 0.45);

    /* -----------------------------------------------------------------------------------------
     * 3. Legacy remap.
     *
     * The engine's own variables, re-pointed at the tokens above. Everything in style.css that
     * already goes through var() moves with these; the literals that do not are substituted in
     * place.
     *
     * --color-hover is deliberately absent: `grep 'var(--color-hover'` returns nothing, so
     * remapping it would ship a dead token that reads as if it did something.
     * --------------------------------------------------------------------------------------- */
    --colormain: var(--rg-ruby);
    --bgmain: var(--rg-ruby);
    --bgmainhv: var(--rg-ruby-dark);
    --colormainhv: var(--rg-moss);
    --colormainxam: var(--rg-ink-muted);
    --bgbtntienich: var(--rg-moss);
    --mxh: var(--rg-moss-dark);
    --color-main: var(--rg-moss);
    --color-black: var(--rg-forest);
    --color-gray: var(--rg-ink-muted);
    --color-static: var(--rg-forest);
    --background-static: var(--rg-moss);
    --background-hover: var(--rg-ochre);
}

/* ---------------------------------------------------------------------------------------------
 * 4. Ground and body copy.
 *
 * The size rules are selector-level rather than token-level on purpose: style.css sets
 * font-size on 220 selectors, every one more specific than :root, so a token alone changes
 * nothing about what the browser computes.
 * ------------------------------------------------------------------------------------------- */

html {
    font-size: 100%;
}

body {
    background-color: var(--rg-paper);
    color: var(--rg-forest);
    font-family: var(--rg-text);
    font-size: var(--rg-size-base);
    line-height: var(--rg-leading);
}

p,
li,
dd,
dt,
blockquote,
td,
th,
label,
figcaption {
    font-size: var(--rg-size-base);
    line-height: var(--rg-leading);
}

/* Small print may sit one step down, but only where it is genuinely secondary text.
   .text-sm and .date_news are deliberately not on this list: in this codebase they are
   applied to form inputs and to body paragraphs respectively. */
small,
.desc {
    font-size: var(--rg-size-sm);
    line-height: var(--rg-leading);
}

/* -----------------------------------------------------------------------------------------
 * The legacy rules that undercut the floor.
 *
 * These are the complete set, enumerated from the rendered page rather than guessed: every
 * selector that still computed under 16px once the element-level rules above were in place.
 * Naming them beats blanketing the site with `font-size: … !important`, which would flatten
 * the deliberately larger sizes along with the too-small ones.
 *
 * The two !important declarations exist only because the rule being overridden is itself
 * !important — style.css:2200 `.text-sm { font-size: 0.875rem !important }`. Specificity
 * alone cannot reach it.
 * --------------------------------------------------------------------------------------- */

.date_news p,
.desc-dongy,
.search-res .search-grid p,
/* `font: 15px var(--font)` — the shorthand, which is why the element-level rule above loses
   to it and why a search for `font-size` in style.css does not find it. 71 of these exist;
   this is the only one that lands on body copy anywhere in the 42 routes. */
.price-product {
    font-size: var(--rg-size-base);
    line-height: var(--rg-leading);
}

.search-res .search-grid input,
.btn-sm,
.btn-group-sm > .btn,
input.form-control,
select.form-select,
textarea.form-control {
    font-size: var(--rg-size-base);
}

.text-sm {
    font-size: var(--rg-size-base) !important;
}

input.text-sm,
select.text-sm,
textarea.text-sm {
    font-size: var(--rg-size-base) !important;
}

h1, h2, h3, h4, h5, h6,
.title_product h2,
.title h2 {
    font-family: var(--rg-display);
    color: var(--rg-forest);
    line-height: var(--rg-leading-tight);
}

h1 { font-size: var(--rg-size-3xl); }
h2 { font-size: var(--rg-size-2xl); }
h3 { font-size: var(--rg-size-xl); }
h4 { font-size: var(--rg-size-lg); }
h5, h6 { font-size: var(--rg-size-md); }

a {
    color: var(--rg-moss-dark);
}

a:hover,
a:focus {
    color: var(--rg-ruby);
}

/* ---------------------------------------------------------------------------------------------
 * 5. Form controls.
 *
 * 16px is not a style preference here: iOS Safari zooms the viewport on focus for any input
 * under 16px, which throws the page layout mid-interaction. The booking form in Phase 5 is the
 * reason this matters.
 * ------------------------------------------------------------------------------------------- */

input,
select,
textarea,
button,
.form-control,
.form-select {
    font-family: var(--rg-text);
    font-size: var(--rg-size-base);
    line-height: var(--rg-leading);
}

.form-control,
.form-select {
    background-color: #FFFFFF;
    border: 1px solid var(--rg-rule);
    border-radius: var(--rg-radius);
    color: var(--rg-forest);
    padding: var(--rg-space-2) var(--rg-space-2);
}

.form-control::placeholder {
    /* #6A7169 on white is 4.54:1 — placeholders are text and are held to the same bar. */
    color: #6A7169;
    opacity: 1;
}

/* ---------------------------------------------------------------------------------------------
 * 6. Actions.
 *
 * --rg-ruby carries white at 8.3:1. The legacy button put black on #47006A, which measured
 * 1.48:1 — the single worst contrast on the page and the reason the button case exists.
 * ------------------------------------------------------------------------------------------- */

.btn,
button,
.btn-primary,
input[type="submit"],
.bg-default {
    font-family: var(--rg-display);
    font-weight: 600;
}

.btn-primary,
input[type="submit"],
.bg-default,
button.submit-newsletter,
.btn.bg-default {
    background: var(--rg-ruby);
    border-color: var(--rg-ruby);
    color: #FFFFFF;
    border-radius: var(--rg-radius);
}

.btn-primary:hover,
input[type="submit"]:hover,
.bg-default:hover,
button.submit-newsletter:hover,
.btn.bg-default:hover {
    background: var(--rg-ruby-dark);
    border-color: var(--rg-ruby-dark);
    color: #FFFFFF;
}

/*
 * Anything the substitution repainted in --rg-ruby needs a foreground to match. These two
 * selectors are the complete set on the rendered page: style.css painted them #47006A and
 * left the text colour to inherit, which was black-on-purple at 1.48:1 — the worst measured
 * contrast on the site — and is black-on-ruby at 2.54:1 until it is stated.
 */
#rightMenu button,
.name_tienich span {
    color: #FFFFFF;
}

/* A visible focus ring on every interactive element. The engine ships none. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--rg-ruby);
    outline-offset: 2px;
    box-shadow: var(--rg-focus);
}

/* ---------------------------------------------------------------------------------------------
 * 7. Surfaces.
 *
 * The engine decorates seven section backgrounds with raster doodles — bg_khonggian.png,
 * bg_vs.png, bg_tc.png, bgalbum.png, bg_sp.png, bg_danhmuc.jpg, bgmenu.png — plus a raster
 * button face. They belong to the palette this phase replaces, so they are overridden here
 * rather than deleted: the files stay on disk and the edit stays reversible.
 * ------------------------------------------------------------------------------------------- */

.wrap-menu-home,
.section-dichvuHome,
.section-why,
.section-tienich,
.section-albumhome,
.section-albumHome,
.bannerdanhmuc,
.section-product:nth-child(2n) {
    background-image: none;
}

.section-dichvuHome,
.section-albumhome,
.section-albumHome {
    background-color: var(--rg-card);
}

.section-why,
.section-tienich {
    background-color: var(--rg-paper);
}

/*
 * Chips that were painted #FFFFFF against a white page ground and so read as plain text.
 * On the paper ground they became visible rectangles — not a regression introduced by the
 * remap so much as one it exposed. Enumerated by sweeping all 42 routes for small white
 * elements sitting directly on --rg-paper; real white cards are larger and are left alone.
 */
.list-hot a,
.nav-tabs .nav-link,
.btn-view-full-content,
.wrap-content > ul,
.title_product + ul {
    background-color: transparent;
}

/* The active filter chip still needs to read as selected without the white block. */
.list-hot a.active,
.nav-tabs .nav-link.active {
    background-color: transparent;
    color: var(--rg-ruby);
    border-bottom: 2px solid var(--rg-ruby);
}

footer {
    background-color: var(--rg-moss-dark);
    color: var(--rg-card);
}

footer a {
    color: var(--rg-card);
}

footer a:hover {
    color: var(--rg-ochre);
}

/* Direction B texture: the woven rule. A hairline that reads as woven cane at small sizes. */
.animate-border,
.rg-rule {
    background-image: repeating-linear-gradient(
        90deg,
        var(--rg-ochre) 0,
        var(--rg-ochre) 6px,
        transparent 6px,
        transparent 10px
    );
    background-color: transparent;
    height: 2px;
    border: 0;
}

/* Direction B texture: the arch mask, for hero and card media. */
.rg-arch {
    border-top-left-radius: 50% 22%;
    border-top-right-radius: 50% 22%;
    overflow: hidden;
}

/* ---------------------------------------------------------------------------------------------
 * 8. Motion.
 *
 * The engine loads AOS and animate.css and applies them liberally. Respecting the OS setting
 * is one rule; not respecting it is a vestibular-safety problem, not a taste question.
 * ------------------------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* =============================================================================================
 * 9. Booking surface (Phase 5)
 *
 * Direction C's booking behaviour: the request is on the page, not behind a button. The rail
 * sits under the hero on the homepage; the same field set renders inside the modal, reachable
 * from the sticky bar on narrow screens.
 * ============================================================================================= */

.rg-rail-section {
    padding: var(--rg-space-5) 0;
    background-color: var(--rg-paper);
}

.rg-rail {
    background-color: var(--rg-card);
    border: 1px solid var(--rg-rule);
    border-radius: var(--rg-radius-lg);
    padding: var(--rg-space-4);
    max-width: 960px;
    margin: 0 auto;
}

/* Direction B's arch, at the card's top edge. */
.rg-arch-card {
    border-top-left-radius: 32% 12%;
    border-top-right-radius: 32% 12%;
}

.rg-rail-head {
    text-align: center;
    margin-bottom: var(--rg-space-4);
}

.rg-rail-eyebrow {
    font-family: var(--rg-display);
    /* The 16px floor applies to this file's own markup too. */
    font-size: var(--rg-size-base);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--rg-ruby);
    margin: 0 0 var(--rg-space-1);
}

.rg-rail-head h2 {
    margin: 0 0 var(--rg-space-1);
    font-size: var(--rg-size-2xl);
}

.rg-rail-sub {
    color: var(--rg-ink-muted);
    margin: 0 0 var(--rg-space-2);
}

.rg-rail-head .animate-border {
    max-width: 120px;
    margin: 0 auto;
}

/* Two columns from the tablet breakpoint up; one on a phone, where side-by-side fields
   squeeze the date inputs below a usable width. */
.rg-booking-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--rg-space-3);
}

@media (min-width: 768px) {
    .rg-booking-grid {
        grid-template-columns: repeat(4, 1fr);
    }
    .rg-field { grid-column: span 2; }
    .rg-field-narrow { grid-column: span 1; }
    .rg-field-full { grid-column: 1 / -1; }
}

.rg-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.rg-field label,
.rg-intent legend {
    font-family: var(--rg-display);
    font-weight: 600;
    font-size: var(--rg-size-base);
    color: var(--rg-forest);
}

/* 44px minimum target: below 16px iOS also zooms the viewport on focus, which throws the
   layout mid-interaction. Both are set here rather than left to the engine's 13-15px inputs. */
.rg-booking-grid .form-control,
.rg-rail-submit,
.rg-sticky-book,
.rg-sticky-call {
    min-height: 44px;
}

.rg-booking-grid textarea.form-control {
    min-height: 88px;
    resize: vertical;
}

.rg-hint {
    font-size: var(--rg-size-base);
    color: var(--rg-ink-muted);
    margin: 0;
}

/* A fieldset's legend does not participate in the parent's flex layout, so the legend is a
   block above its choices rather than a flex sibling beside them. */
.rg-intent {
    border: 0;
    margin: 0;
    padding: 0;
    display: block;
}

.rg-intent legend {
    float: none;
    width: auto;
    margin: 0 0 var(--rg-space-1);
    padding: 0;
}

.rg-intent .rg-choice + .rg-choice {
    margin-left: var(--rg-space-2);
}

/* The radio itself is small; the label is the target, and it is the label that must clear
   44px. The visual spec measures the label for exactly this reason. */
.rg-choice {
    display: inline-flex;
    align-items: center;
    gap: var(--rg-space-1);
    min-height: 44px;
    padding: 0 var(--rg-space-3) 0 var(--rg-space-2);
    border: 1px solid var(--rg-rule);
    border-radius: 999px;
    background-color: #FFFFFF;
    cursor: pointer;
}

.rg-choice input {
    width: 18px;
    height: 18px;
    accent-color: var(--rg-ruby);
}

.rg-choice:has(input:checked) {
    border-color: var(--rg-ruby);
    box-shadow: inset 0 0 0 1px var(--rg-ruby);
}

.rg-rail-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--rg-space-2);
    margin-top: var(--rg-space-4);
}

.rg-rail-submit {
    padding: var(--rg-space-2) var(--rg-space-5);
    font-size: var(--rg-size-md);
}

/* ---------------------------------------------------------------------------------------------
 * Sticky booking bar.
 *
 * The bar reserves its own height as body padding so it cannot swallow the end of the page —
 * the failure the phase's risk note names, and what the landscape case checks.
 * ------------------------------------------------------------------------------------------- */

.rg-sticky-booking {
    display: none;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1030;              /* above the toolbar, below Bootstrap's modal at 1055 */
    gap: var(--rg-space-2);
    padding: var(--rg-space-1) var(--rg-space-3);
    padding-bottom: calc(var(--rg-space-1) + env(safe-area-inset-bottom, 0px));
    background-color: var(--rg-card);
    border-top: 1px solid var(--rg-rule);
}

@media (max-width: 767.98px) {
    .rg-sticky-booking {
        display: flex;
        align-items: center;
    }

    /* Reserve the bar's height. Without this the footer's last rows sit underneath it. */
    body {
        padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px));
    }
}

.rg-sticky-call {
    display: inline-flex;
    align-items: center;
    gap: var(--rg-space-1);
    padding: 0 var(--rg-space-3);
    border: 1px solid var(--rg-rule);
    border-radius: var(--rg-radius);
    color: var(--rg-forest);
    text-decoration: none;
    white-space: nowrap;
}

.rg-sticky-book {
    flex: 1 1 auto;
}

/* ---------------------------------------------------------------------------------------------
 * Contact toolbar.
 *
 * templates/index.php rendered phone.php only when device detection said "mobile", so a
 * desktop visitor had no contact affordance outside the footer. It now renders at every width;
 * these rules keep it clear of the sticky bar rather than stacked on top of it.
 * ------------------------------------------------------------------------------------------- */

.toolbar {
    z-index: 1020;             /* one step below the sticky bar's 1030 */
}



/* ---------------------------------------------------------------------------------------------
 * Contact toolbar visibility.
 *
 * style.css:4579 sets `.toolbar { display: none }` unconditionally, and only a mobile media
 * query ever positioned it — which is why gating its PHP behind device detection looked
 * harmless. With the include un-gated, the toolbar still needs to be shown.
 * ------------------------------------------------------------------------------------------- */

/*
 * Shown only from the tablet breakpoint up.
 *
 * style.css:4579 sets `display: none` unconditionally; turning it on inside the media query
 * rather than turning it on globally and off again below 768px matters, because an
 * unconditional rule later in this file would beat the media query it was meant to be
 * overridden by. Below the breakpoint the sticky booking bar already offers "Gọi ngay", and
 * stacking both left two call affordances competing for the same corner — the collision the
 * phase's risk note warns about, removed rather than negotiated.
 */
@media (min-width: 768px) {
    .toolbar {
        display: block;
    }

    /* Clear of the page edge on desktop, where there is no sticky booking bar below it. */
    .toolbar {
        bottom: var(--rg-space-3);
        left: auto;
        right: var(--rg-space-3);
        width: auto;
    }

    .toolbar .list-phone a {
        display: inline-flex;
        align-items: center;
        gap: var(--rg-space-1);
        min-height: 44px;
        padding: 0 var(--rg-space-3);
        background-color: var(--rg-card);
        border: 1px solid var(--rg-rule);
        border-radius: 999px;
        color: var(--rg-forest);
        text-decoration: none;
    }

    .toolbar .list-phone {
        position: static;
        display: block;
    }
}

/* The hero's second call to action is a button now, not an anchor with href="" — which
   reloaded the page. Keep it looking like its sibling. */
button.more_abouts {
    cursor: pointer;
}

/* =============================================================================================
 * 10. Hero (Phase 6)
 *
 * Replaces an inline jssor slider that carried a library, a stylesheet and a loading spinner to
 * animate one static image.
 *
 * The scrim is CSS rather than a darkened export, so the headline's contrast can be tuned
 * without re-exporting the photograph — and so the contrast test measures the same pixels a
 * reader sees. It is a gradient, not a flat wash, because the text sits in the lower half and
 * a flat overlay dark enough for the bright sky would flatten the whole image.
 * ============================================================================================= */

.rg-hero {
    position: relative;
    display: grid;
    isolation: isolate;
    min-height: min(78vh, 720px);
    background-color: var(--rg-forest);
    overflow: hidden;
}

.rg-hero-image,
.rg-hero-scrim,
.rg-hero-body {
    grid-area: 1 / 1;
}

/*
 * Intrinsic width and height are declared on the element so the browser reserves the box before
 * the file arrives; `object-fit` then does the cropping. Without both, the hero is the site's
 * largest layout shift.
 */
.rg-hero-image {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center 40%;
}

/*
 * Two gradients, not one. The vertical pass keeps the nav legible against the sky and lifts the
 * foot of the image; the horizontal pass darkens the left column where the headline sits, so
 * the text has its contrast without flattening the whole photograph.
 */
.rg-hero-scrim {
    background:
        linear-gradient(
            90deg,
            rgba(14, 26, 19, 0.86) 0%,
            rgba(14, 26, 19, 0.62) 38%,
            rgba(14, 26, 19, 0.10) 72%,
            rgba(14, 26, 19, 0.02) 100%
        ),
        linear-gradient(
            180deg,
            rgba(14, 26, 19, 0.55) 0%,
            rgba(14, 26, 19, 0.20) 30%,
            rgba(14, 26, 19, 0.20) 70%,
            rgba(14, 26, 19, 0.60) 100%
        );
}

@media (max-width: 767.98px) {
    /* No room for a left column on a phone: the text spans the width, so the scrim must too. */
    .rg-hero-scrim {
        background: linear-gradient(
            180deg,
            rgba(14, 26, 19, 0.55) 0%,
            rgba(14, 26, 19, 0.45) 35%,
            rgba(14, 26, 19, 0.88) 100%
        );
    }
}

.rg-hero-body {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: flex-end;
    padding: var(--rg-space-6) 0 var(--rg-space-5);
    color: var(--rg-card);
}

.rg-hero-eyebrow {
    font-family: var(--rg-display);
    font-size: var(--rg-size-base);
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--rg-ochre);
    margin: 0 0 var(--rg-space-2);
}

.rg-hero-title {
    font-family: var(--rg-display);
    font-size: clamp(2rem, 5.2vw, var(--rg-size-3xl));
    line-height: var(--rg-leading-tight);
    color: #FFFFFF;
    margin: 0 0 var(--rg-space-3);
    max-width: 18ch;
    /* A soft shadow buys contrast where the scrim alone is not enough, without darkening the
       photograph further. */
    text-shadow: 0 2px 18px rgba(14, 26, 19, 0.8);
}

.rg-hero-desc {
    color: var(--rg-card);
    max-width: 52ch;
    margin: 0 0 var(--rg-space-4);
    text-shadow: 0 1px 10px rgba(14, 26, 19, 0.75);
}

.rg-hero-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--rg-space-3);
}

.rg-hero-cta {
    min-height: 48px;
    display: inline-flex;
    align-items: center;
    padding: 0 var(--rg-space-5);
    font-size: var(--rg-size-md);
    text-decoration: none;
}

.rg-hero-secondary {
    display: inline-flex;
    align-items: center;
    gap: var(--rg-space-1);
    min-height: 48px;
    padding: 0 var(--rg-space-3);
    border: 1px solid rgba(247, 244, 236, 0.55);
    border-radius: var(--rg-radius);
    color: #FFFFFF;
    text-decoration: none;
}

.rg-hero-secondary:hover,
.rg-hero-secondary:focus {
    background-color: rgba(247, 244, 236, 0.12);
    color: #FFFFFF;
}

@media (max-width: 767.98px) {
    .rg-hero {
        min-height: min(70vh, 560px);
    }

    .rg-hero-body {
        padding: var(--rg-space-5) 0 var(--rg-space-4);
    }

    .rg-hero-actions > * {
        flex: 1 1 100%;
        justify-content: center;
    }
}

/* The off-canvas contact block's brand line, formerly an <h2> that sat in the page outline. */
.rg-offcanvas-brand {
    font-family: var(--rg-display);
    font-size: var(--rg-size-lg);
    font-weight: 600;
    margin: 0 0 var(--rg-space-1);
}

/*
 * Hide the contact toolbar below the tablet breakpoint.
 *
 * A separate rule rather than relying on style.css's own default, because style.css:4579's
 * `display: none` is itself overridden there by `@media (max-width: 1001px) { .toolbar
 * { display: block } }` — so on a phone the engine turns the toolbar back on. This has to be a
 * matching media query later in the cascade, which is what theme.css being last provides.
 *
 * Below this width the sticky booking bar already offers "Gọi ngay". Two call affordances in
 * the same corner is the z-index collision the phase warns about; the fix is to have one.
 */
@media (max-width: 767.98px) {
    .toolbar,
    .check-toolbar {
        display: none !important;
    }
}

/* =============================================================================================
 * 11. Sections and cards (Phase 7)
 * ============================================================================================= */

/*
 * Section rhythm varies rather than repeating one spacing. Every band on this page used the
 * same padding and the same "Khám phá" eyebrow, so eight distinct sections read as one long
 * scroll with nothing to navigate by.
 */
.rg-section {
    padding: var(--rg-space-6) 0;
}

.rg-section + .rg-section {
    padding-top: var(--rg-space-5);
}

.section-banggia .title_product,
.rg-section .title_product {
    text-align: center;
    margin-bottom: var(--rg-space-4);
}

.rg-section .title_product .animate-border {
    max-width: 96px;
    margin: var(--rg-space-2) auto 0;
}

/* ---- price cards ---------------------------------------------------------------------- */

.rg-price-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: var(--rg-space-3);
}

.rg-price-card {
    display: flex;
    flex-direction: column;
    background-color: var(--rg-card);
    border: 1px solid var(--rg-rule);
    border-radius: var(--rg-radius-lg);
    overflow: hidden;
    min-width: 0;
}

.rg-price-media {
    display: block;
    aspect-ratio: 4 / 3;
    overflow: hidden;
}

.rg-price-media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.rg-price-body {
    display: flex;
    flex-direction: column;
    gap: var(--rg-space-1);
    padding: var(--rg-space-3);
}

/*
 * Titles wrap. The engine clamps card titles with -webkit-line-clamp, which hides the end of a
 * name without removing it — a room called "Bungalow gỗ vòm Ruby Garden" became "Bungalow gỗ
 * vòm Ruby…" with no way to read the rest.
 */
.rg-card-title {
    font-size: var(--rg-size-lg);
    line-height: var(--rg-leading-tight);
    margin: 0;
    overflow: visible;
    text-overflow: clip;
    -webkit-line-clamp: none;
    display: block;
    overflow-wrap: anywhere;
}

.rg-card-title a {
    color: var(--rg-forest);
    text-decoration: none;
}

.rg-card-title a:hover,
.rg-card-title a:focus {
    color: var(--rg-ruby);
}

.rg-price-meta {
    color: var(--rg-ink-muted);
    margin: 0;
}

/*
 * Tabular figures so a column of prices aligns on the digit rather than drifting, and one
 * locale format — 1.250.000 đ — set by number_format in the template, not by the browser.
 */
.rg-price-value {
    font-family: var(--rg-display);
    font-size: var(--rg-size-xl);
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
    color: var(--rg-ruby);
    margin: var(--rg-space-1) 0 0;
}

.rg-price-unit {
    font-size: var(--rg-size-base);
    color: var(--rg-ink-muted);
}

.rg-price-link {
    align-self: flex-start;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    color: var(--rg-moss-dark);
    font-weight: 600;
    text-decoration: none;
}

.rg-price-link::after {
    content: " →";
}

/*
 * Card titles wrap instead of being clipped.
 *
 * style.css clamps them with -webkit-line-clamp, which hides the end of a name without
 * removing it: "Khu du lịch Buôn Đôn mang vẻ đẹp bình yên giữa đại ngàn Đắk Lắk" rendered as
 * "Khu du lịch Buôn Đôn mang vẻ đẹp bình yê…" with no way to read the rest and no indication
 * to a screen reader that anything was missing. A card is allowed to be as tall as its title.
 */
.name_post,
.name_tienich,
.dichvu-item-name,
.rg-card-title,
.text-split-1 {
    display: block;
    -webkit-line-clamp: none;
    -webkit-box-orient: unset;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: anywhere;
}

/*
 * The clamp lives on `.item_tin .name_post` and `.news_left .name_post` — two classes deep, so
 * a single-class override loses on specificity no matter how late it appears. Matching the
 * original selectors is what actually unclamps them.
 */
.item_tin .name_post,
.news_left .name_post,
.item_tin h3,
.news_left h3 {
    display: block;
    -webkit-line-clamp: none;
    -webkit-box-orient: unset;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: anywhere;
}

/* ---- room cards ----------------------------------------------------------------------- */

.rg-room-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: var(--rg-space-3);
    margin-top: var(--rg-space-3);
}

.rg-room-card {
    display: flex;
    flex-direction: column;
    background-color: var(--rg-card);
    border: 1px solid var(--rg-rule);
    border-radius: var(--rg-radius-lg);
    overflow: hidden;
    min-width: 0;
}

.rg-room-media {
    display: block;
    aspect-ratio: 4 / 3;
    overflow: hidden;
}

.rg-room-media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.rg-room-body {
    display: flex;
    flex-direction: column;
    gap: var(--rg-space-1);
    padding: var(--rg-space-3);
}

.rg-room-meta {
    color: var(--rg-ink-muted);
    margin: 0;
}

/* The filter tabs are buttons now, not anchors to nowhere. */
.rg-room-filter {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--rg-space-2);
    margin-top: var(--rg-space-3);
}

.rg-room-filter button {
    min-height: 44px;
    padding: 0 var(--rg-space-3);
    background: transparent;
    border: 1px solid transparent;
    border-radius: 999px;
    color: var(--rg-ink-muted);
    font-family: var(--rg-display);
    font-weight: 600;
    cursor: pointer;
}

.rg-room-filter button.active {
    color: var(--rg-ruby);
    border-color: var(--rg-ruby);
}

/* Text for assistive technology only. Bootstrap ships .visually-hidden but the engine's
   stylesheet load order makes it unreliable here, so it is defined alongside its use. */
.visually-hidden {
    position: absolute !important;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/*
 * Secondary text that still meets 4.5:1.
 *
 * Bootstrap's `.text-muted` is #6c757d, which measures 4.0:1 on this project's card ground —
 * under the bar, and axe reports it on every detail page. --rg-ink-muted is the token that was
 * already chosen to clear it.
 */
.rg-muted {
    color: var(--rg-ink-muted);
}

/*
 * Bootstrap utilities that fail contrast on this project's ground.
 *
 * Measured, not guessed: `.text-muted` is #6c757d, which is 3.93:1 on --rg-paper, and
 * `.btn-info` puts white on #0dcaf0 at 1.95:1 — the worst ratio left on the site. Both are
 * Bootstrap defaults the engine's templates use directly, so they are remapped here rather
 * than hunted down template by template.
 */
.text-muted {
    color: var(--rg-ink-muted) !important;
}

.btn-info {
    background-color: var(--rg-moss-dark);
    border-color: var(--rg-moss-dark);
    color: #FFFFFF;
}

.btn-info:hover,
.btn-info:focus {
    background-color: var(--rg-forest);
    border-color: var(--rg-forest);
    color: #FFFFFF;
}

/*
 * Reveal a dropdown when anything inside it takes focus.
 *
 * The submenu is revealed on `:hover` only, so its links stayed focusable while
 * `visibility: hidden` with a zero-height box — a keyboard user could tab into "Hạng phòng 01"
 * and see nothing at all, no focus ring and no menu. Mirroring the hover rule on
 * `:focus-within` is the whole fix; the transform and opacity values are the engine's own.
 */
.menu ul li:focus-within > ul {
    -webkit-transform: perspective(600px) rotateX(0deg);
    transform: perspective(600px) rotateX(0deg);
    opacity: 1;
    visibility: visible;
}

/*
 * A real focus ring on form controls.
 *
 * Bootstrap sets `outline: 0` on `.form-control:focus` and replaces it with its own blue glow,
 * which this project's palette overrides to transparent — leaving fields that take focus and
 * show nothing. The ring is stated here in the project's own colour, on :focus rather than
 * :focus-visible, because a text field that has focus should say so however it was reached.
 */
/* :focus-within as well as :focus — Chromium moves focus into a date input's own picker
   shadow tree, at which point the host stops matching :focus while still being the page's
   activeElement, and the ring vanishes mid-interaction. */
.form-control:focus,
.form-select:focus,
.form-control:focus-within,
.form-select:focus-within,
.rg-booking-grid input:focus,
.rg-booking-grid input:focus-within,
.rg-booking-grid textarea:focus,
.rg-booking-grid select:focus {
    outline: 2px solid var(--rg-ruby);
    outline-offset: 1px;
    border-color: var(--rg-ruby);
    box-shadow: var(--rg-focus);
}

/*
 * Buttons need the ring stated at Bootstrap's own specificity.
 *
 * `.btn:focus` sets `outline: 0` and substitutes a box-shadow this palette renders
 * transparent, so a focused button showed nothing at all. `.btn:focus` is two classes deep,
 * which beats the generic `a:focus-visible` rule above — hence the repetition here.
 *
 * The ring is forest, not ruby: a ruby outline on a ruby button is invisible.
 */
.btn:focus,
.btn:focus-visible,
.btn-primary:focus,
.rg-hero-cta:focus,
.rg-rail-submit:focus,
.rg-sticky-book:focus {
    outline: 3px solid var(--rg-forest);
    outline-offset: 2px;
    box-shadow: 0 0 0 3px rgba(247, 244, 236, 0.9);
}

