/* ============================================================
   PEARL RIVERA — Tour Page Styles
   Layout: logo absolute top-left | main container fills middle | menu fixed bottom
   ============================================================ */

*,
*::before,
*::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    scroll-behavior: smooth;
    font-size: 16px;
}

body {
    font-family: var(--font-family);
    color: var(--color-text);
    background: var(--pr-0);
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    overflow-x: hidden;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

img {
    display: block;
    max-width: 100%;
    height: auto;
}

a {
    color: inherit;
    text-decoration: none;
}

/* ============================================================
   ZOOM CONTROLLER — SHARED (.prl-zoom-*)
   ------------------------------------------------------------
   A single compact pill used across all public zoomable views
   (ban-ngay, ban-do-vi-tri, tien-ich, tong-mat-bang,
   he-thong-duong-noi-khu). Layout:

       [ − ]  ←zoom out
       [ 100% ]  ← level display
       [ + ]  ←zoom in
       ─────  ← divider
       [ ↺ ]  ← reset

   Size: container ~40px wide, ~118px tall (28×28 buttons,
   14×14 icons). Right-edge-anchored by default; the parent
   pages position it as needed.
   ============================================================ */
.prl-zoom-controls {
    position: absolute;
    right: 14px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0;
    background: rgba(0, 0, 0, 0.22);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 10px;
    padding: 3px;
    z-index: 100;
    pointer-events: auto;
    touch-action: manipulation;
}

.prl-zoom-btn {
    width: 28px;
    height: 28px;
    border-radius: 6px;
    background: transparent;
    border: none;
    color: rgba(255, 255, 255, 0.65);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: auto;
    touch-action: manipulation;
    -webkit-tap-highlight-color: rgba(255, 255, 255, 0.12);
    transition:
        background 0.18s,
        color 0.18s;
}

.prl-zoom-btn:hover:not(:disabled) {
    background: rgba(255, 255, 255, 0.12);
    color: rgba(255, 255, 255, 0.95);
}

.prl-zoom-btn:active:not(:disabled) {
    background: rgba(255, 255, 255, 0.08);
    transform: scale(0.92);
}

.prl-zoom-btn:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}

.prl-zoom-btn:disabled:hover {
    background: transparent;
    color: rgba(255, 255, 255, 0.3);
}

.prl-zoom-level {
    min-width: 34px;
    text-align: center;
    font-family: var(--font-body, var(--font-family));
    font-size: 10px;
    font-weight: 500;
    color: rgba(255, 255, 255, 0.5);
    letter-spacing: 0.4px;
    padding: 2px 2px 1px;
    user-select: none;
}

.prl-zoom-divider {
    width: 14px;
    height: 1px;
    background: rgba(255, 255, 255, 0.12);
    margin: 2px auto;
}

@media (max-width: 768px) {
    .prl-zoom-controls {
        right: 10px;
        padding: 2px;
    }
    .prl-zoom-btn {
        width: 26px;
        height: 26px;
    }
    .prl-zoom-level {
        min-width: 30px;
        font-size: 9px;
    }
}

/* ----------------------------------------------------------
   LOGO
   Absolute, top-left, height=55px, logo-white.png
   ---------------------------------------------------------- */

.logo {
    position: fixed;
    top: 24px;
    left: 48px;
    z-index: 100;
    display: block;
    height: 55px;
    width: auto;
}

.logo img {
    height: 55px;
    width: auto;
    object-fit: contain;
}

/* ----------------------------------------------------------
   PAGE MAIN
   Fills remaining viewport height between logo and menu
   ---------------------------------------------------------- */

.page-main {
    flex: 1;
    width: 100%;
    position: relative;
    background: rgba(128, 128, 128, 0.08);
}

/* ----------------------------------------------------------
   MENU
   Fixed at bottom, full width
   Background handled by .menu__bg pseudo/child element
   ---------------------------------------------------------- */

.menu {
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    padding: 0 48px;
    min-height: 138px;
    z-index: 50;
    /* Promote the menu to its own GPU compositing layer. The zoom
       pages re-apply a transform to a huge image on every pan/zoom
       frame, and without this layer that transform would cascade
       into a repaint of the menu's background PNG too. Keeping the
       menu on its own layer means pan/zoom only repaints the image
       — the menu stays untouched and never appears to flicker. */
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
}

/* Background wave image — absolute, always 150px tall, bottom-aligned */
.menu__bg {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 150px;
    background: url("../images/menu-bg.png") no-repeat top center;
    background-size: cover;
    background-position: top center;
    pointer-events: none;
    z-index: -1;
}

/* Bottom row — grid container (desktop)
   Desktop: left | center | right — pills hidden
   ≤ 1600px: pills row shows, grid left/right hidden
*/
.menu__bottom {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: end;
    width: 100%;
    position: relative;
    z-index: 1;
}

/* Pills wrapper — hidden on desktop, visible on tablet/laptop */
.menu__pills {
    display: none;
    grid-column: 1 / -1;
}

/* Left — col 1 */
.menu__left {
    grid-column: 1;
    display: flex;
    align-items: flex-end;
    justify-content: flex-start;
    gap: 16px;
    padding-bottom: 20px;
}

/* Center — col 2 — logo flanked by Day / Night buttons */
.menu__center {
    grid-column: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    padding-bottom: 20px;
}

.menu__center-logo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    cursor: pointer;
    transition: opacity var(--transition-base);
}

.menu__center-logo:hover {
    opacity: 0.85;
}

.menu__center-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 50px;
    padding: 0 22px;
    border: none;
    border-radius: 100px;
    background: transparent;
    color: var(--pr-5);
    font-family: var(--font-family-domaine);
    font-size: var(--font-size-base);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    white-space: nowrap;
    cursor: pointer;
    transition:
        background var(--transition-base),
        color var(--transition-base),
        transform var(--transition-fast);
}

.menu__center-btn--day {
    background: var(--pr-0);
    color: var(--pr-5);
}

.menu__center-btn--day:hover,
.menu__center-btn--day.is-active {
    background: var(--pr-1);
    color: var(--pr-5);
}

.menu__center-btn--night {
    background: var(--pr-5);
    color: var(--pr-0);
}

.menu__center-btn--night:hover,
.menu__center-btn--night.is-active {
    background: var(--pr-6);
    color: var(--pr-0);
}

/* Center logo */
.menu__center img {
    display: block;
    height: 55px;
    width: auto;
    object-fit: contain;
}

/* Right — col 3 */
.menu__right {
    grid-column: 3;
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;
    gap: 16px;
    padding-bottom: 20px;
}

/* =============================================================
   MENU PILL
   Outline button: transparent bg, 1px outline, rounded 48px
   Text: white, uppercase, 18px, SVN-Century Gothic
   ---------------------------------------------------------- */

.menu-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 12px 24px;
    border-radius: 48px;
    outline: 1px solid var(--pr-0);
    outline-offset: -1px;
    font-size: 14px;
    font-family: var(--font-family);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--pr-0);
    white-space: nowrap;
    transition:
        background var(--transition-base),
        color var(--transition-base),
        transform var(--transition-fast);
}

.menu-pill:hover {
    background: var(--pr-0);
    color: var(--pr-5);
    transform: translateY(-2px);
}

/* =============================================================
   MENU PILL DROPDOWN
   ---------------------------------------------------------- */

.menu-pill-dropdown {
    position: relative;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
}

.menu-pill-dropdown > .menu-pill {
    cursor: pointer;
    background: none;
    border: none;
    padding: 12px 24px;
    border-radius: 48px;
    outline: 1px solid var(--pr-0);
    outline-offset: -1px;
    font-size: 14px;
    font-family: var(--font-family);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--pr-0);
    white-space: nowrap;
    transition:
        background var(--transition-base),
        color var(--transition-base),
        transform var(--transition-fast);
}

.menu-pill-dropdown__menu {
    position: absolute;
    bottom: calc(100% + 4px);
    left: 50%;
    transform: translateX(-50%) translateY(8px);
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 220px;
    opacity: 0;
    pointer-events: none;
    z-index: 10;
}

.menu-pill-dropdown::after {
    content: "";
    position: absolute;
    bottom: -4px;
    left: 50%;
    transform: translateX(-50%);
    width: 220px;
    height: 12px;
    background: transparent;
    pointer-events: none;
    z-index: -1;
}

@keyframes dropdownFadeIn {
    from {
        opacity: 0;
        transform: translateX(-50%) translateY(8px);
    }
    to {
        opacity: 1;
        transform: translateX(-50%) translateY(0);
    }
}

@keyframes dropdownFadeOut {
    from {
        opacity: 1;
        transform: translateX(-50%) translateY(0);
    }
    to {
        opacity: 0;
        transform: translateX(-50%) translateY(8px);
    }
}

.menu-pill-dropdown:hover > .menu-pill-dropdown__menu,
.menu-pill-dropdown.is-open > .menu-pill-dropdown__menu {
    animation: dropdownFadeIn 0.2s ease forwards;
    pointer-events: auto;
}

.menu-pill-dropdown:not(:hover) > .menu-pill-dropdown__menu {
    animation: dropdownFadeOut 1s ease forwards;
}

.menu-pill-dropdown.is-open > .menu-pill-dropdown__menu {
    animation: dropdownFadeIn 0.2s ease forwards;
    pointer-events: auto;
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

.menu-pill-dropdown__item {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 10px 20px;
    border-radius: 48px;
    background: var(--pr-4);
    color: var(--pr-0);
    font-size: 14px;
    font-family: var(--font-family);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    white-space: nowrap;
    text-align: center;
    opacity: 0.9;
    transition:
        background var(--transition-base),
        color var(--transition-base),
        opacity var(--transition-fast),
        transform var(--transition-fast);
}

.menu-pill-dropdown__item:hover {
    background: var(--pr-0);
    color: var(--pr-4);
    opacity: 1;
    transform: translateY(-2px);
}

/* Arrow indicator on parent pill */
.menu-pill-dropdown > .menu-pill::after {
    display: none;
}

/* ----------------------------------------------------------
   RESPONSIVE — ≤ 1600px
   Layout: pills row visible | grid left/right hidden
   ---------------------------------------------------------- */

@media (max-width: 1600px) {
    .main-container {
        padding-bottom: 300px;
    }

    .menu {
        position: fixed;
        bottom: 0;
        left: 0;
        flex-direction: column;
        align-items: center;
        gap: 8px;
        padding: 16px 24px 20px;
        min-height: 0;
        padding-bottom: 0;
    }

    .menu__bg {
        height: 175px;
    }

    .menu__bottom {
        grid-template-columns: 1fr;
        grid-template-rows: auto auto;
        justify-items: center;
    }

    /* Hide base grid left/right (direct children) — pills take over */
    .menu__bottom > .menu__left,
    .menu__bottom > .menu__right {
        display: none !important;
    }

    .menu__pills {
        grid-row: 2;
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        align-items: flex-end;
        flex-wrap: wrap;
        gap: 8px;
        width: 100%;
    }

    .menu__pills .menu__left,
    .menu__pills .menu__right {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
    }

    .menu__pills .menu__left {
        justify-content: flex-start;
    }

    .menu__pills .menu__right {
        justify-content: flex-end;
    }

    .menu__center {
        grid-column: 1;
        grid-row: 1;
        justify-content: center;
        padding-bottom: 8px;
        gap: 10px;
    }

    .menu__center-btn {
        height: 44px;
        padding: 0 16px;
        font-size: var(--font-size-sm);
    }

    .menu__center-logo-img {
        height: 48px;
    }

    .menu-pill {
        font-size: var(--font-size-base);
        padding: 10px 16px;
    }

    .page-main {
        padding: var(--space-10) var(--space-6);
    }

    .page-title {
        font-size: var(--font-size-xl);
    }

    .tien-ich-dropdowns {
        bottom: 185px;
    }
}

/* ----------------------------------------------------------
   RESPONSIVE — MOBILE (≤ 768px)
   ---------------------------------------------------------- */

@media (max-width: 768px) {
    .logo {
        left: 20px;
        top: 12px;
        height: 38px;
    }

    .logo img {
        height: 38px;
    }

    .page-main {
        min-height: calc(100vh - 38px - 197px);
    }

    .page-title {
        font-size: var(--font-size-lg);
    }
}

/* ----------------------------------------------------------
   RESPONSIVE — TABLET (≤ 1030px)
   ---------------------------------------------------------- */

@media (max-width: 1030px) {
    .page-main {
        padding-bottom: 300px;
    }

    .menu {
        position: fixed;
        bottom: 0;
        left: 0;
        flex-direction: column;
        align-items: center;
        gap: 8px;
        padding: 16px 24px 10px;
        min-height: 0;
    }

    .menu__bg {
        height: 160px;
    }

    .logo {
        left: 32px;
        top: 16px;
        height: 40px;
    }

    .logo img {
        height: 40px;
    }

    .menu__bottom {
        grid-template-columns: 1fr;
        grid-template-rows: auto auto;
        justify-items: center;
    }

    /* Hide base grid left/right — pills take over */
    .menu__bottom > .menu__left,
    .menu__bottom > .menu__right {
        display: none !important;
    }

    .menu__pills {
        grid-row: 2;
        display: flex;
        flex-direction: row;
        justify-content: center;
        align-items: flex-end;
        flex-wrap: wrap;
        gap: 8px;
        width: 100%;
    }

    .menu__pills .menu__left,
    .menu__pills .menu__right {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        flex: 1 1 100%;
        justify-content: center;
    }

    .menu__pills .menu__left {
        padding-bottom: 0;
        padding-top: 10px;
    }

    .menu__pills .menu__right {
        padding-bottom: 0;
    }

    .menu__center {
        grid-column: 1;
        grid-row: 1;
        justify-content: center;
        gap: 8px;
    }

    .menu__center-btn {
        height: 40px;
        padding: 0 12px;
        font-size: 14px;
    }

    .menu__center img {
        height: 40px;
    }

    .menu__center-logo-img {
        height: 44px;
    }

    .menu-pill {
        font-size: var(--font-size-sm);
        padding: 8px 14px;
    }

    .menu-pill-dropdown > .menu-pill {
        font-size: var(--font-size-sm);
        padding: 8px 14px;
    }

    .menu-pill-dropdown__item {
        font-size: var(--font-size-sm);
        padding: 8px 14px;
    }

    .page-main {
        padding: var(--space-8) var(--space-6);
        min-height: calc(100vh - 40px - 197px);
    }

    .page-title {
        font-size: var(--font-size-lg);
    }

    .viewer-nav-strip {
        bottom: 235px;
    }

    .viewer-nav-strip.is-expanded {
        width: auto;
        max-width: calc(100vw - 24px);
    }

    .viewer-toggle-fab {
        bottom: 150px;
    }

    .viewer-nav-strip.is-expanded ~ .viewer-toggle-fab {
        bottom: 210px;
    }
}

/* ----------------------------------------------------------
   PAGE MAIN & TITLE
   ---------------------------------------------------------- */

.page-main {
    width: 100%;
    min-height: calc(100vh - 55px - 150px);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: var(--space-16) var(--space-12) calc(var(--space-16) + 150px);
}

.page-title {
    font-family: var(--font-family-domaine);
    font-size: var(--font-size-2xl);
    font-weight: 400;
    color: var(--pr-5);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    opacity: 0.4;
}

/* Active pill highlight — same look as hover so the current page
   is indistinguishable from a hovered pill (i.e. permanently lit up). */
.menu-pill.is-active {
    background: var(--pr-0);
    color: var(--pr-5);
    transform: translateY(-2px);
}

/* Active dropdown item — same visual as regular active pill */
.menu-pill-dropdown__item.is-active {
    background: var(--pr-0);
    color: var(--pr-5);
}

/* Parent dropdown button inherits active state from any active child */
.menu-pill-dropdown:has(> .menu-pill.is-active) > .menu-pill,
.menu-pill-dropdown:has(> .menu-pill.is-active) > button,
.menu-pill-dropdown:has(> .menu-pill-dropdown__menu .is-active) > .menu-pill,
.menu-pill-dropdown:has(> .menu-pill-dropdown__menu .is-active) > button {
    background: var(--pr-0);
    color: var(--pr-5);
    transform: translateY(-2px);
}

/* ============================================================
   360° ROTATE VIEWER
   ============================================================ */

/* Full-page wrap */
.rotage-360-wrap {
    position: fixed;
    inset: 0;
    z-index: 10;
    overflow: hidden;
    background: #060f14;
}

/* Ban ngày dropdown — fixed, centered at top of screen, ABOVE the viewer.
   Anchored at top: 20px so the pill sits on the same baseline as the
   back button on the left. */
.ban-ngay-viewer-dropdown {
    position: fixed;
    top: 20px;
    left: 0;
    right: 0;
    display: flex;
    justify-content: center;
    padding-top: 0;
    z-index: 200;
    pointer-events: none;
}

.ban-ngay-viewer-dropdown .menu-pill-dropdown {
    pointer-events: auto;
    position: relative;
}

.ban-ngay-viewer-dropdown .menu-pill-dropdown::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 24px;
    pointer-events: auto;
    z-index: -1;
}

/* Bridge gap fills the space between the pill and the open menu so the
   dropdown stays open as the cursor travels from pill to items. */
.ban-ngay-viewer-dropdown .menu-pill-dropdown::after {
    content: "";
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    height: 12px;
    pointer-events: auto;
    z-index: 10;
}

.ban-ngay-viewer-dropdown .menu-pill {
    font-size: 14px;
    padding: 9px 16px;
    border-radius: 48px;
    outline: 1px solid var(--pr-0);
    outline-offset: -1px;
    background: rgba(0, 0, 0, 0.18);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1px solid rgba(255, 255, 255, 0.08);
    color: rgba(252, 249, 246, 0.85);
    display: flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
    cursor: pointer;
    transition:
        background var(--transition-base),
        color var(--transition-base);
}

.ban-ngay-viewer-dropdown .menu-pill:hover {
    background: rgba(0, 0, 0, 0.3);
    color: rgba(252, 249, 246, 1);
}

.ban-ngay-viewer-dropdown .menu-pill.is-active {
    background: var(--pr-0);
    color: var(--pr-5);
}

.ban-ngay-viewer-dropdown .dropdown-arrow {
    flex-shrink: 0;
    transition: transform 0.2s ease;
}

.ban-ngay-viewer-dropdown .menu-pill-dropdown.is-open .dropdown-arrow {
    transform: rotate(180deg);
}

.ban-ngay-viewer-dropdown .menu-pill-dropdown:not(.is-open) .dropdown-arrow {
    transform: rotate(0deg);
}

.ban-ngay-viewer-dropdown .menu-pill-dropdown__menu {
    position: absolute;
    top: calc(100% + 4px);
    bottom: auto;
    left: 50%;
    transform: translateX(-50%) translateY(0);
    width: 200px;
    max-height: 320px;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.3) transparent;
    gap: 4px;
    min-width: 0;
    opacity: 0;
    pointer-events: none;
    display: flex;
    flex-direction: column;
}

.ban-ngay-viewer-dropdown .menu-pill-dropdown__menu::-webkit-scrollbar {
    width: 4px;
}

.ban-ngay-viewer-dropdown .menu-pill-dropdown__menu::-webkit-scrollbar-track {
    background: transparent;
}

.ban-ngay-viewer-dropdown .menu-pill-dropdown__menu::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.3);
    border-radius: 999px;
}

.ban-ngay-viewer-dropdown .menu-pill-dropdown__menu .menu-pill-dropdown__item {
    display: flex;
    align-items: flex-start;
    justify-content: flex-start;
    padding: 7px 12px;
    border-radius: 8px;
    background: var(--pr-4);
    color: var(--pr-0);
    font-size: 13px;
    font-family: var(--font-family);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    white-space: normal;
    word-break: break-word;
    text-align: left;
    line-height: 1.4;
    transition:
        background var(--transition-base),
        color var(--transition-base),
        transform var(--transition-fast);
}

.ban-ngay-viewer-dropdown .menu-pill-dropdown__menu .menu-pill-dropdown__item:hover {
    background: var(--pr-1);
    color: var(--pr-5);
}

/* Active item — off-white background with brand brown text, matching the
   menu navigation pill hover treatment so the selected scene reads as
   "currently selected" while inactive items stay teal. */
.ban-ngay-viewer-dropdown .menu-pill-dropdown__menu .menu-pill-dropdown__item.is-active {
    background: var(--pr-0);
    color: var(--pr-5);
}

/* is-open shows the menu; hover on the button also shows it (click sets is-open) */
.ban-ngay-viewer-dropdown .menu-pill-dropdown.is-open > .menu-pill-dropdown__menu,
.ban-ngay-viewer-dropdown .menu-pill-dropdown:hover > .menu-pill-dropdown__menu {
    opacity: 1;
    pointer-events: auto;
    transform: translateX(-50%) translateY(4px);
    transition:
        opacity 0.15s ease,
        transform 0.15s ease;
}

/* Keep the menu open when hovering inside it; only hide when fully leaving */
.ban-ngay-viewer-dropdown .menu-pill-dropdown > .menu-pill-dropdown__menu:hover {
    opacity: 1;
    pointer-events: auto;
    transform: translateX(-50%) translateY(4px);
}

/* Closed state */
.ban-ngay-viewer-dropdown .menu-pill-dropdown > .menu-pill-dropdown__menu {
    opacity: 0;
    pointer-events: none;
    transform: translateX(-50%) translateY(-4px);
    transition:
        opacity 0.15s ease,
        transform 0.15s ease;
}

/* NIGHT MODE — hide the day-only ngoại khu dropdown entirely.
   The set of exterior scenes currently ships as daytime imagery
   (`assets/images/ngoai_khu_ban_ngay/nk_*.jpg`) — there is no
   night counterpart yet. Rather than render an unusable pill in
   "Hoàng hôn" mode (which would suggest scenes that don't exist),
   the JS flips `pr-mode-dem` on <body> when the night toggle is
   active and we collapse the dropdown out of the layout. */
body.pr-mode-dem .ban-ngay-viewer-dropdown {
    display: none;
}

/* Hide dropdown until the 360° viewer's first frame is decoded.
   JS removes .is-pre-load in _onAllLoaded() once hideLoading() runs. */
.ban-ngay-viewer-dropdown.is-pre-load {
    opacity: 0;
    pointer-events: none;
    transform: translateY(-6px);
    transition:
        opacity 400ms ease,
        transform 400ms ease;
}

.ban-ngay-viewer-dropdown {
    transition:
        opacity 400ms ease,
        transform 400ms ease;
}


/* ===== VIEWER ===== */
.pearl-viewer {
    width: 100vw;
    /* dvh tracks the live viewport — unlike 100vh it shrinks/grows when
       the mobile URL bar collapses, so the viewer always fills the
       actually-visible area instead of leaving a dark gap below. */
    height: 100vh; /* fallback for older browsers without dvh */
    height: 100dvh;
    position: relative;
    overflow: hidden;
    background: #060f14;
}

/* Gradient overlays */
.viewer-gradient {
    position: absolute;
    inset: 0;
    z-index: 12;
    pointer-events: none;
    background: linear-gradient(
        to bottom,
        rgba(226, 212, 186, 0.15) 0%,
        transparent 18%,
        transparent 55%,
        rgba(226, 212, 186, 0.35) 100%
    );
    pointer-events: none;
}
.viewer-vignette {
    position: absolute;
    inset: 0;
    z-index: 13;
    background: radial-gradient(
        ellipse 100% 100% at 50% 50%,
        transparent 50%,
        rgba(14, 139, 139, 0.07) 100%
    );
    pointer-events: none;
}

/* ===== 360 ROTATE VIEWER ===== */
.rotage-360-container {
    position: absolute;
    inset: 0;
    z-index: 10;
    overflow: hidden;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    visibility: hidden;
    opacity: 0;
    transition:
        opacity 300ms ease,
        visibility 0ms linear 300ms;
    /* Same dark teal as the panorama's sky/water tone so that any
       transient gap (e.g. during initial draw before the first frame
       paints, or when the URL bar collapses mid-frame on mobile) blends
       with the image instead of showing pure black. */
    background: #060f14;
}
.rotage-360-container.visible {
    visibility: visible;
    opacity: 1;
    transition:
        opacity 300ms ease,
        visibility 0ms linear 0ms;
}
.rotage-360-container:active {
    cursor: grabbing;
}
.rotage-360-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    pointer-events: none;
}
.rotage-360-crossfade {
    position: absolute;
    inset: 0;
    z-index: 5;
    background: #000;
    opacity: 0;
    pointer-events: none;
    transition: opacity 400ms ease;
}
.rotage-360-loading {
    position: absolute;
    inset: 0;
    z-index: 15;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 22px;
    background: rgba(14, 139, 139, 0.6);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    pointer-events: none;
}
.rotage-360-loading.hidden {
    display: none;
}
.rotage-360-logo {
    width: 72px;
    height: auto;
    animation: logoPulse 2s ease-in-out infinite;
}
@keyframes logoPulse {
    0%, 100% { transform: scale(1); opacity: 0.9; }
    50%       { transform: scale(1.08); opacity: 1; }
}
.rotage-360-progress {
    width: 180px;
    height: 3px;
    background: rgba(252, 249, 246, 0.15);
    border-radius: 2px;
    overflow: hidden;
}
.rotage-360-progress-bar {
    height: 100%;
    background: var(--pr-1);
    border-radius: 2px;
    transition: width 0.2s ease;
    width: 0%;
}
.rotage-360-drag-hint {
    position: absolute;
    bottom: 165px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 20px;
    background: rgba(0, 0, 0, 0.18);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 14px;
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    font-size: 11px;
    color: rgba(252, 249, 246, 0.8);
    letter-spacing: 1px;
    animation: hintFadeOut 3s ease 2s forwards;
    pointer-events: none;
    white-space: nowrap;
}
.rotage-360-drag-hint.hidden {
    display: none;
}
.rotage-360-drag-hint svg {
    color: rgba(252, 249, 246, 0.6);
    flex-shrink: 0;
}
@keyframes hintFadeOut {
    0% {
        opacity: 1;
    }
    80% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}
.rotage-360-cursor-icon {
    position: absolute;
    bottom: 160px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 20;
    pointer-events: none;
    animation: cursorBounce 1.5s ease-in-out infinite;
    opacity: 0;
    transition: opacity 0.3s ease;
}
.rotage-360-cursor-icon.visible {
    opacity: 1;
}
@keyframes cursorBounce {
    0%,
    100% {
        transform: translateX(-50%) translateX(-8px);
    }
    50% {
        transform: translateX(-50%) translateX(8px);
    }
}
.rotage-360-cursor-icon svg {
    color: rgba(252, 249, 246, 0.7);
    filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.5));
}

/* ===== RESPONSIVE ===== */

/* ----------------------------------------------------------
   UTILITIES & ACCESSIBILITY
   ---------------------------------------------------------- */

:focus-visible {
    outline: 2px solid var(--pr-3);
    outline-offset: 3px;
    border-radius: 4px;
}

/* ============================================================
   PEARL RIVERA — Map Page (ban-do-vi-tri)
   ============================================================ */

.map-page {
    position: fixed;
    inset: 0;
    overflow: hidden;
    background: #fff;
    z-index: 0;
}

.map-bg {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: bottom;
    z-index: 1;
    pointer-events: none;
}

.map-wave {
    position: absolute;
    bottom: 197px;
    left: 0;
    width: 100%;
    height: auto;
    z-index: 2;
    pointer-events: none;
}

.map-split {
    --shared-menu-height: 107px;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: calc(100dvh - var(--shared-menu-height) + 25px);
    z-index: 3;
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 0;
    padding: 0;
}

.map-pane {
    position: relative;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
    border-radius: 8px;
    background: rgba(0, 0, 0, 0.04);
}

/* Left pane: a 2fr-wide cell that hosts a centred, zoomable image.
   The pane itself is the zoom viewport (#mapViTriZoomContainer) —
   it fills the cell and centres the image via JS transform. The
   controls overlay (zoom in/out/reset) sits inside the pane on the
   left edge. */
.map-pane--left {
    overflow: hidden;
    height: 100%;
    background: transparent;
    border-radius: 0;
    box-shadow: none;
    outline: none;
    transition: none;
    /* The left pane has its own JS pinch/drag handler (tour.js
       mapViTriTouchStart/Move). Letting the browser also process
       these gestures races with the JS handler and produces the
       "sometimes scrolls, sometimes zooms" flakiness. Declaring
       touch-action: none lets JS own every touch on this pane. */
    touch-action: none;
    min-width: 0;
    min-height: 0;
}

.map-pane--left:hover {
    transform: none;
    box-shadow: none;
}

.map-pane__zoom {
    position: absolute;
    inset: 0;
    overflow: hidden;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    /* The JS pinch/drag handler in tour.js calls e.preventDefault()
       on touchmove. Without touch-action: none here, iOS treats the
       gesture as a scroll candidate and the JS handler either loses
       events or fires after a noticeable delay. */
    touch-action: none;
}

.map-pane--left .map-img {
    position: absolute;
    top: 0;
    left: 0;
    width: auto;
    height: auto;
    max-width: none;
    max-height: none;
    display: block;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(14, 65, 70, 0.12);
    transition: box-shadow 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
    transform-origin: 0 0;
    /* Seed with translate3d to guarantee GPU-layer promotion on iOS,
       so the image's pan/zoom transform doesn't cascade into a
       repaint of the fixed bottom menu. */
    transform: translate3d(0, 0, 0);
    will-change: transform;
    pointer-events: none;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
}

.map-pane--left:hover .map-img {
    box-shadow: 0 6px 18px rgba(14, 65, 70, 0.18);
}

/* Right pane: scrollable area for tall image. No chrome on the
   outer wrapper — modern styling lives on the image itself. */
.map-pane--right {
    overflow: hidden;
    height: 100%;
    background: transparent;
    border-radius: 0;
    box-shadow: none;
    outline: none;
    transition: none;
    /* min-width/min-height: 0 keep the grid cell from inflating the
       pane past its allocated space — without this the child
       .map-pane__scroll refuses to establish a scrollable height on
       Safari iOS and the right pane ends up static. */
    min-width: 0;
    min-height: 0;
}

.map-pane--right:hover {
    transform: none;
    box-shadow: none;
}

/* Zoom controls — left pane, vertical pill on the right edge. */
.map-pane__controls {
    right: 14px;
}

.map-pane__scroll {
    width: 100%;
    height: 100%;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: thin;
    scrollbar-color: var(--pr-3) transparent;
    /* Containment: when the user hits the top/bottom edge, don't
       rubber-band the page shell behind the split. */
    overscroll-behavior: contain;
    /* Legacy iOS momentum fallback (older WebViews). */
    -webkit-overflow-scrolling: touch;
    /* Only allow vertical pan — this stops two-finger horizontal
       gestures from accidentally hijacking scroll on the right pane. */
    touch-action: pan-y;
}

.map-pane__scroll::-webkit-scrollbar {
    width: 6px;
}

.map-pane__scroll::-webkit-scrollbar-track {
    background: transparent;
}

.map-pane__scroll::-webkit-scrollbar-thumb {
    background: var(--pr-3);
    border-radius: 999px;
}

.map-pane__scroll .map-img {
    width: 100%;
    height: auto;
    display: block;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(14, 65, 70, 0.12);
    transition: box-shadow 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
}

.map-pane__scroll:hover .map-img {
    box-shadow: 0 6px 18px rgba(14, 65, 70, 0.18);
}

.map-img--fit {
    object-fit: contain;
}

/* ----------------------------------------------------------
   TABLET/MOBILE (≤ 1030px) — stack vertically: left on top,
   right (scrollable) below. Map sits above fixed bottom menu.
   ---------------------------------------------------------- */
@media (max-width: 1030px) {
    .map-wave {
        bottom: 110px;
    }

    .map-split {
        --shared-menu-height: 110px;
        bottom: auto;
        height: calc(100dvh - var(--shared-menu-height) + 20px);
        grid-template-columns: 1fr;
        grid-template-rows: 1fr 1fr;
        gap: 0;
        padding: 0;
    }

    .map-pane--left {
        overflow: hidden;
        width: 100%;
        max-width: 100%;
        max-height: 100%;
        /* JS zoom handler still owns touch — see desktop rule above. */
        touch-action: none;
    }

    .map-pane--right {
        overflow: hidden;
        /* Same containment as desktop for the mobile split layout. */
        min-width: 0;
        min-height: 0;
    }

    .map-pane__scroll {
        /* On mobile the address-bar collapse/expand changes the actual
           visible viewport. 100% on the inner pane inherits a stable
           height from .map-pane--right (which already uses 100% from
           the grid track). The key fix here is the touch-action +
           overscroll-behavior declared in the base rule above — those
           were missing from the mobile block, which is why the right
           pane scroll felt intermittent. */
        overflow-y: auto;
        overflow-x: hidden;
        overscroll-behavior: contain;
        touch-action: pan-y;
        -webkit-overflow-scrolling: touch;
    }
}

/* ══════════════════════════════════════════════════════
   TỔNG MẶT BẰNG — FULL SCREEN ZOOMABLE IMAGE
   ══════════════════════════════════════════════════════ */
.tong-mat-bang-page {
    position: fixed;
    inset: 0;
    overflow: hidden;
    background: #fff;
    /* `contain: layout paint` scopes layout and paint to this
       element. The browser is allowed to composite the page
       independently from the rest of the document, so the image's
       pan/zoom transform inside won't force a re-paint of the
       fixed bottom menu. Much cheaper than `will-change: transform`
       and doesn't create a permanent GPU layer. */
    contain: layout paint;
}

.tong-mat-bang-bg {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: bottom;
    z-index: 1;
    pointer-events: none;
}

.tong-mat-bang-wave {
    position: absolute;
    bottom: 107px;
    left: 0;
    width: 100%;
    height: auto;
    z-index: 2;
    pointer-events: none;
}

.tong-mat-bang-zoom-container {
    position: absolute;
    inset: 0;
    bottom: 80px;
    overflow: hidden;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
    background: transparent;
    z-index: 3;
}

.page-main:has(.tong-mat-bang-page) {
    padding-top: 0;
}
.page-main:has(.tien-ich-page) {
    padding-top: 0;
}
.tong-mat-bang-zoom-container:active {
    cursor: grabbing;
}

.tong-mat-bang-zoom-img {
    position: absolute;
    top: 0;
    left: 0;
    width: auto;
    height: auto;
    max-width: none;
    max-height: none;
    transform-origin: 0 0;
    /* Seed with translate3d(0,0,0) so the browser promotes this element
       to its own GPU compositing layer on first paint. will-change alone
       is not always enough on iOS Safari — combine it with a 3D
       transform hint to guarantee layer promotion and stop the image's
       pan/zoom repaints from re-rasterising the fixed bottom menu
       (which was the main source of the mobile flicker). */
    transform: translate3d(0, 0, 0);
    will-change: transform;
    pointer-events: none;
    display: block;
    cursor: grab;
    /* Backface-visibility hidden reinforces the layer promotion on iOS */
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
}

/* Zone image layer — preloaded, opacity-toggled on hover for instant swap */
.tong-mat-bang-zone-img {
    position: absolute;
    top: 0;
    left: 0;
    width: auto;
    height: auto;
    max-width: none;
    max-height: none;
    transform-origin: 0 0;
    will-change: transform, opacity;
    pointer-events: none;
    display: block;
    opacity: 0;
    z-index: 1; /* above the main image, below the SVG overlays */
}

/* Zoom controls — handled by shared .prl-zoom-* (see top of file) */

@media (max-width: 768px) {
    .rotage-360-drag-hint {
        bottom: 240px;
    }
}

@media (max-width: 1500px) {
    .tong-mat-bang-wave {
        bottom: 45%;
    }
}

/* ================================================================
   TỔNG MẶT BẰNG — ADMIN POLYGON EDITOR
   Activate when URL has ?admin=1
   ================================================================ */

/* SVG overlays — same position/size as the image (top:0 left:0) */
.tmb-svg-overlay {
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: none;
    z-index: 6; /* lô polygons — on top so clicks pass through to this */
}

.tmb-svg-viewer {
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: none;
    z-index: 5; /* zone polygons — below, hover detects zone, click passes through */
}

.tmb-svg-overlay path,
.tmb-svg-viewer path {
    pointer-events: auto;
}

.tmb-svg-viewer path.zone-poly,
.tmb-svg-overlay path.zone-poly {
    pointer-events: none; /* zone polygons: no click at all — lô polygons below take priority */
}

body.tmb-admin-mode .tmb-svg-overlay {
    pointer-events: auto;
}

/* Admin mode: disable zoom drag */
body.tmb-admin-mode .tong-mat-bang-zoom-container {
    cursor: default;
    overflow: visible;
}

body.tmb-admin-mode .tong-mat-bang-zoom-img {
    cursor: crosshair;
}

body.tmb-admin-mode .tong-mat-bang-zoom-container:active {
    cursor: crosshair;
}

/* Viewer polygon hover effect */
.tmb-svg-viewer path {
    cursor: pointer;
    transition: fill 120ms ease;
}
.tmb-svg-viewer path.zone-poly {
    cursor: default;
}
.tmb-svg-viewer path:not(.zone-poly):not(.zone-hit):hover {
    fill: rgba(247, 166, 59, 0.25);
}
.tmb-svg-viewer path.zone-hit {
    cursor: default;
}
.tmb-svg-viewer path.zone-hit:hover {
    fill: transparent;
}

/* Hotspot overlay */
.tmb-hotspot-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 4;
}

/* Image hotspot overlay — positioned like tmbSvgViewer (natural px, viewBox, transform mirror) */
#tmbImageHotspotOverlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 6;
}

/* Dot hotspot overlay — same size as image overlay so % positions resolve. */
#tmbDotHotspotOverlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 7;
}

/* Dot-el: anchored at % within overlay; counter-scale keeps size constant when zoomed */
.tmb-img-hotspot {
    position: absolute;
    transform: scale(var(--tmb-img-hs-inv-scale, 1));
    transform-origin: center center;
    display: flex;
    align-items: center;
    justify-content: center;
}

.tmb-img-hotspot-img {
    width: 100px;
    height: 100px;
    object-fit: contain;
    filter: drop-shadow(0 2px 8px rgba(0,0,0,0.35));
    transition: transform 0.2s ease;
}

/* Pulsing ring animation for hotspot dots */
@keyframes tmbHsPulse {
    0%   { transform: scale(1);    opacity: 1; }
    50%  { transform: scale(1.07); opacity: 0.75; }
    100% { transform: scale(1);    opacity: 1; }
}

.tmb-img-hotspot-img {
    animation: tmbHsPulse 2.4s ease-in-out infinite;
    transition: transform 0.2s ease;
}

.tmb-img-hotspot:hover .tmb-img-hotspot-img {
    animation-play-state: paused;
    transform: scale(1.1);
}

.tmb-img-hotspot {
    pointer-events: none;
    box-shadow: 0 2px 10px rgba(0,0,0,0.15);
}

/* ================================================================
   Dot Hotspot — numbered dot (20px) with hover tooltip showing name
   Used for utility / amenity markers on tong-mat-bang viewer
   ================================================================ */

/* Dot hotspot overlay — JS syncs its bounds to image's rendered rect
   and copies the image's transform so the dots move with zoom/pan. */
/* size defined earlier to keep it in one place */

/* Dot hotspot container — 0×0 anchor at the % point. Children:
   - .tmb-dot-hotspot-dot: positioned at (0,0), centered via translate
   - .tmb-dot-hotspot-tooltip: positioned above the dot */
.tmb-dot-hotspot {
    position: absolute;
    width: 0;
    height: 0;
    pointer-events: auto;
    cursor: pointer;
}

/* The numbered dot — 20px circle, colored by data, pulse animation.
   The transform uses a CSS variable for the current scale so the
   hover state can multiply it without breaking the centering. */
.tmb-dot-hotspot-dot {
    --tmb-dot-hs-color: #00685D;
    --tmb-dot-hs-color-glow: rgba(0, 104, 93, 0.55);
    --tmb-dot-hs-current-scale: var(--tmb-dot-hs-inv-scale, 1);

    position: absolute;
    top: 0;
    left: 0;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--tmb-dot-hs-color);
    color: #fff;
    font-family: var(--font-family);
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1.5px solid #fff;
    box-shadow: 0 0 0 0 var(--tmb-dot-hs-color-glow);
    transform-origin: center center;
    transform: translate(-50%, -50%) scale(var(--tmb-dot-hs-current-scale));
    animation: tmbDotHotspotPulse 2s ease-in-out infinite;
    user-select: none;
    transition: border-color 0.2s ease;
}

.tmb-dot-hotspot:hover .tmb-dot-hotspot-dot,
.tmb-dot-hotspot.is-active .tmb-dot-hotspot-dot {
    animation-play-state: paused;
    --tmb-dot-hs-current-scale: calc(var(--tmb-dot-hs-inv-scale, 1) * 1.18);
}

/* Tooltip wrapper — sits at the wrapper's top-left (the % point).
   0 size so it doesn't add layout; the inner carries visuals.
   Stays unscaled so the dot anchor is stable. */
.tmb-dot-hotspot-tooltip {
    position: absolute;
    top: 0;
    left: 50%;
    width: 0;
    height: 0;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.18s ease;
    z-index: 1;
}

/* Tooltip inner — counter-scaled so text/padding stay constant
   when the image is zoomed. translateY uses pixels (not %) so the
   6px gap above the dot is always exactly 6px on screen.
   transform-origin: bottom center keeps the arrow aligned when scaled. */
.tmb-dot-hotspot-tooltip-inner {
    --tmb-tooltip-bg: #ffffff;
    --tmb-tooltip-fg: #0e1f2e;

    position: absolute;
    bottom: 0;
    left: 0;
    transform-origin: bottom center;
    transform: translate(-50%, calc(-100% - 6px)) scale(var(--tmb-dot-hs-inv-scale, 1));

    display: block;
    max-width: 180px;
    width: max-content;
    padding: 7px 16px;
    background: var(--tmb-tooltip-bg);
    color: var(--tmb-tooltip-fg);
    font-family: var(--font-family);
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: 0.01em;
    text-align: center;
    text-transform: uppercase;
    white-space: pre-line;
    border-radius: 8px;
    border: 1px solid rgba(14, 31, 46, 0.08);
    box-shadow:
        0 4px 14px rgba(14, 31, 46, 0.12),
        0 1px 2px rgba(14, 31, 46, 0.06);
    transition: transform 0.18s cubic-bezier(0.34, 1.36, 0.64, 1);
}

/* With-image variant: title on top, image below.
   Width becomes fixed 300px (per spec); height auto via img. */
.tmb-dot-hotspot-tooltip-inner--with-image {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    width: 300px;
    max-width: 300px;
    min-width: 0;
    padding: 10px 10px 8px;
    text-align: center;
    white-space: normal;
    word-break: break-word;
}

.tmb-dot-hotspot-tooltip-title {
    color: var(--tmb-tooltip-fg);
    font-family: var(--font-family);
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: 0.01em;
    text-align: center;
    text-transform: uppercase;
    white-space: pre-line;
    word-break: break-word;
}

.tmb-dot-hotspot-tooltip-img {
    display: block;
    width: 100%;
    height: auto;
    max-width: 100%;
    border-radius: 4px;
    object-fit: cover;
    user-select: none;
    -webkit-user-drag: none;
}

/* Arrow — small rounded notch using clip-path, no harsh triangle.
   Sized so it tucks under the tooltip near the dot anchor. */
.tmb-dot-hotspot-tooltip-inner::after {
    content: "";
    position: absolute;
    top: calc(100% - 1px);
    left: 50%;
    width: 10px;
    height: 6px;
    transform: translateX(-50%);
    background: var(--tmb-tooltip-bg);
    border-right: 1px solid rgba(14, 31, 46, 0.08);
    border-bottom: 1px solid rgba(14, 31, 46, 0.08);
    clip-path: polygon(0 0, 100% 0, 50% 100%);
}

.tmb-dot-hotspot:hover .tmb-dot-hotspot-tooltip,
.tmb-dot-hotspot.is-active .tmb-dot-hotspot-tooltip {
    opacity: 1;
}

.tmb-dot-hotspot:hover .tmb-dot-hotspot-tooltip-inner,
.tmb-dot-hotspot.is-active .tmb-dot-hotspot-tooltip-inner {
    transform: translate(-50%, calc(-100% - 10px)) scale(var(--tmb-dot-hs-inv-scale, 1));
}

/* Pulse animation — ring color comes from --tmb-dot-hs-color-glow
   (set per-hotspot from the data's color field). */
@keyframes tmbDotHotspotPulse {
    0% {
        box-shadow: 0 0 0 0 var(--tmb-dot-hs-color-glow);
    }
    50% {
        box-shadow: 0 0 0 8px transparent;
    }
    100% {
        box-shadow: 0 0 0 0 transparent;
    }
}

/* Lightbox */
.tmb-img-hs-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0);
    z-index: 99999;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.3s ease;
}

.tmb-img-hs-backdrop.is-visible {
    background: rgba(0,0,0,0.82);
}

.tmb-img-hs-box {
    max-width: 90vw;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    opacity: 0;
    transform: scale(0.88);
    transition: opacity 0.3s ease, transform 0.3s cubic-bezier(0.34,1.56,0.64,1);
}

.tmb-img-hs-backdrop.is-visible .tmb-img-hs-box {
    opacity: 1;
    transform: scale(1);
}

.tmb-img-hs-box img {
    max-width: 100%;
    max-height: calc(90vh - 48px);
    object-fit: contain;
    border-radius: 12px;
    box-shadow: 0 8px 40px rgba(0,0,0,0.5);
}

.tmb-img-hs-caption {
    margin-top: 12px;
    font-family: var(--font-family);
    font-size: 15px;
    font-weight: 600;
    color: #fff;
    text-align: center;
    text-shadow: 0 1px 4px rgba(0,0,0,0.5);
}

/* Tooltip portal */
.tmb-tooltip-portal {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 9999;
    pointer-events: none;
}

/* Tooltip */
.tmb-tooltip {
    position: fixed;
    background: #fff;
    border-radius: 14px;
    box-shadow:
        0 8px 32px rgba(0, 0, 0, 0.14),
        0 2px 8px rgba(0, 0, 0, 0.06);
    display: none;
    z-index: 9999;
    min-width: 168px;
    overflow: hidden;
    pointer-events: auto;
    opacity: 0;
}
.tmb-tooltip.show {
    display: block;
    animation: ttFadeIn 0.18s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
@keyframes ttFadeIn {
    from {
        opacity: 0;
        transform: translate(-50%, calc(-100% + 8px)) scale(0.92);
    }
    to {
        opacity: 1;
        transform: translate(-50%, -100%) scale(1);
    }
}
.tmb-tooltip .tt-inner {
    position: relative;
    overflow: hidden;
}
.tmb-tooltip .tt-header {
    background: linear-gradient(135deg, #0e8b8b 0%, #0aa0a0 100%);
    padding: 10px 12px 10px 14px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}
.tmb-tooltip .tt-label-main {
    font-family: var(--font-family);
    font-weight: 700;
    font-size: 13px;
    color: #fff;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    line-height: 1.2;
}
.tmb-tooltip .tt-close-btn {
    background: rgba(255, 255, 255, 0.18);
    border: 1px solid rgba(255, 255, 255, 0.3);
    color: rgba(255, 255, 255, 0.85);
    font-size: 0;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    flex-shrink: 0;
    transition:
        background 0.15s,
        color 0.15s,
        transform 0.15s;
}
.tmb-tooltip .tt-close-btn:hover {
    background: rgba(255, 255, 255, 0.28);
    color: #fff;
    transform: scale(1.1);
}
.tmb-tooltip .tt-body {
    background: #fff;
    padding: 10px 14px 6px;
}
.tmb-tooltip .tt-row {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-bottom: 7px;
    font-family: var(--font-family);
    font-size: 12px;
    line-height: 1;
}
.tmb-tooltip .tt-row:last-of-type {
    margin-bottom: 0;
}
.tmb-tooltip .tt-row-icon {
    color: #0e8b8b;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    width: 16px;
}
.tmb-tooltip .tt-row-label {
    color: #999;
    font-weight: 500;
    flex: 1;
    min-width: 0;
}
.tmb-tooltip .tt-row-value {
    font-weight: 700;
    color: #1a1a2e;
    font-size: 13px;
    text-align: right;
    white-space: nowrap;
}
.tmb-tooltip .tt-unit {
    font-size: 10px;
    vertical-align: super;
    font-weight: 600;
    color: #555;
}
.tmb-tooltip .tt-footer {
    padding: 8px 14px 12px;
    display: flex;
    justify-content: center;
}
.tmb-tooltip .tt-cta {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-family: var(--font-family);
    font-size: 12px;
    font-weight: 600;
    color: #fff;
    background: linear-gradient(135deg, #f7a63b 0%, #f0892b 100%);
    border-radius: 20px;
    padding: 7px 18px;
    text-decoration: none;
    cursor: pointer;
    transition:
        opacity 0.15s,
        transform 0.15s;
    box-shadow: 0 2px 8px rgba(247, 166, 59, 0.35);
}
.tmb-tooltip .tt-cta:hover {
    opacity: 0.9;
    transform: translateY(-1px);
}
.tmb-tooltip .tt-cta:active {
    transform: translateY(0);
}
.tmb-tooltip .tt-arrow {
    position: absolute;
    bottom: -7px;
    left: 50%;
    transform: translateX(-50%);
    width: 14px;
    height: 7px;
    overflow: visible;
}
.tmb-tooltip .tt-arrow::before {
    content: "";
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 14px;
    height: 14px;
    background: #fff;
    clip-path: polygon(50% 100%, 0% 0%, 100% 0%);
    box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.08);
}

/* ================================================================
   Polygon Info Modal
   ================================================================ */
.tmb-modal {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
}
.tmb-modal[hidden] {
    display: none;
}
.tmb-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(2px);
}
.tmb-modal-content {
    position: relative;
    background: #fff;
    border-radius: 10px;
    width: 360px;
    max-width: calc(100vw - 32px);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
    font-family: var(--font-family);
    overflow: hidden;
}
.tmb-modal-header {
    background: #0e8b8b;
    padding: 14px 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}
.tmb-modal-title {
    margin: 0;
    font-size: 15px;
    font-weight: 700;
    color: #fff;
}
.tmb-modal-close {
    background: none;
    border: none;
    color: rgba(255, 255, 255, 0.7);
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 4px;
    transition: background 0.15s;
}
.tmb-modal-close:hover {
    background: rgba(255, 255, 255, 0.15);
    color: #fff;
}
.tmb-modal-body {
    padding: 20px 20px 8px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}
.tmb-modal-field {
    display: flex;
    flex-direction: column;
    gap: 5px;
}
.tmb-modal-field label {
    font-size: 12px;
    font-weight: 600;
    color: #555;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.tmb-modal-field input {
    width: 100%;
    box-sizing: border-box;
    padding: 9px 12px;
    border: 1.5px solid #ddd;
    border-radius: 6px;
    font-size: 14px;
    font-family: var(--font-family);
    color: #222;
    background: #fafafa;
    transition:
        border-color 0.15s,
        background 0.15s;
    outline: none;
}
.tmb-modal-field input:focus {
    border-color: #0e8b8b;
    background: #fff;
}
.tmb-modal-footer {
    padding: 12px 20px 20px;
    display: flex;
    gap: 10px;
    justify-content: flex-end;
}
.tmb-modal-btn {
    padding: 9px 20px;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 600;
    font-family: var(--font-family);
    cursor: pointer;
    border: none;
    transition:
        background 0.15s,
        opacity 0.15s;
}
.tmb-modal-btn--cancel {
    background: #f0f0f0;
    color: #555;
}
.tmb-modal-btn--cancel:hover {
    background: #e4e4e4;
}
.tmb-modal-btn--save {
    background: #0e8b8b;
    color: #fff;
}
.tmb-modal-btn--save:hover {
    background: #0a6f6f;
}

/* Admin Toggle Button */
.tmb-admin-toggle[hidden] {
    display: none;
}
.tmb-admin-toggle {
    position: absolute;
    top: 12px;
    right: 76px;
    z-index: 100;
    background: rgba(255, 255, 255, 0.9);
    border: 1px solid rgba(0, 0, 0, 0.1);
    border-radius: 8px;
    padding: 8px 14px;
    cursor: pointer;
    font-family: var(--font-family);
    font-size: 13px;
    font-weight: 600;
    color: #333;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
    transition: all 0.2s ease;
    user-select: none;
    display: flex;
    align-items: center;
    gap: 8px;
}
.tmb-admin-toggle:hover {
    background: rgba(255, 255, 255, 1);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.tmb-admin-toggle.active {
    background: #ff9800;
    color: #fff;
    border-color: #ff9800;
}
.tmb-admin-toggle.active svg {
    stroke: #fff;
}

/* Admin Panel */
.tmb-admin-panel {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 280px;
    background: rgba(255, 255, 255, 0.97);
    border: 1px solid rgba(0, 0, 0, 0.1);
    border-radius: 12px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.18);
    z-index: 100;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.tmb-admin-panel[hidden] {
    display: none;
}

.tmb-admin-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 12px;
    border-bottom: 1px solid #e8e8e8;
    background: #fafafa;
}

.tmb-admin-title {
    font-family: var(--font-family);
    font-size: 13px;
    font-weight: 700;
    color: #333;
}

.tmb-admin-header-actions {
    display: flex;
    gap: 6px;
}

.tmb-admin-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-family: var(--font-family);
    font-size: 12px;
    font-weight: 600;
    padding: 5px 10px;
    border-radius: 6px;
    border: 1px solid rgba(0, 0, 0, 0.15);
    background: #fff;
    color: #333;
    cursor: pointer;
    transition: all 0.15s ease;
    white-space: nowrap;
}
.tmb-admin-btn:hover {
    background: #f0f0f0;
}
.tmb-admin-btn:active {
    transform: scale(0.97);
}
.tmb-admin-btn--sm {
    padding: 4px 8px;
    font-size: 11px;
}
.tmb-admin-btn--ghost {
    background: transparent;
    border-color: transparent;
    color: #666;
}
.tmb-admin-btn--ghost:hover {
    background: rgba(0, 0, 0, 0.05);
    color: #333;
}
.tmb-admin-btn--danger {
    color: #d32f2f;
    border-color: rgba(211, 47, 47, 0.3);
}
.tmb-admin-btn--danger:hover {
    background: #ffebee;
}

.tmb-admin-toolbar {
    padding: 10px 12px;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    border-bottom: 1px solid #e8e8e8;
}

.tmb-admin-tools {
    display: flex;
    gap: 4px;
}

.tmb-tool-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-family: var(--font-family);
    font-size: 12px;
    font-weight: 500;
    padding: 5px 10px;
    border-radius: 6px;
    border: 1px solid rgba(0, 0, 0, 0.15);
    background: #fff;
    color: #555;
    cursor: pointer;
    transition: all 0.15s ease;
    white-space: nowrap;
}
.tmb-tool-btn:hover {
    background: #f0f0f0;
    color: #333;
}
.tmb-tool-btn.active {
    background: #ff9800;
    color: #fff;
    border-color: #ff9800;
}

.tmb-admin-divider {
    width: 1px;
    height: 28px;
    background: #e0e0e0;
}

.tmb-admin-group {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.tmb-admin-label {
    font-family: var(--font-family);
    font-size: 10px;
    font-weight: 600;
    color: #888;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.tmb-color-picker-row {
    display: flex;
    align-items: center;
    gap: 6px;
}

.tmb-color-input {
    width: 28px;
    height: 24px;
    border: 1px solid rgba(0, 0, 0, 0.2);
    border-radius: 4px;
    padding: 0;
    cursor: pointer;
    background: none;
}

.tmb-color-hex {
    font-family: var(--font-family);
    font-size: 11px;
    color: #555;
    font-weight: 500;
}

.tmb-admin-footer {
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.tmb-polygon-list-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-family: var(--font-family);
    font-size: 11px;
    font-weight: 600;
    color: #888;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.tmb-polygon-count {
    background: #0e8b8b;
    color: #fff;
    border-radius: 10px;
    padding: 1px 7px;
    font-size: 10px;
    font-weight: 700;
}

.tmb-polygon-list {
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: #ccc transparent;
}
.tmb-polygon-list::-webkit-scrollbar {
    width: 4px;
}
.tmb-polygon-list::-webkit-scrollbar-thumb {
    background: #ccc;
    border-radius: 2px;
}

.tmb-polygon-list-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border-radius: 6px;
    cursor: pointer;
    transition: background 0.12s ease;
    border: 1px solid transparent;
}
.tmb-polygon-list-item:hover {
    background: #f5f5f5;
}
.tmb-polygon-list-item.selected {
    background: #fff8e1;
    border-color: #ff9800;
}
.tmb-polygon-list-item .tmb-poly-color-dot {
    width: 12px;
    height: 12px;
    border-radius: 3px;
    flex-shrink: 0;
    border: 1px solid rgba(0, 0, 0, 0.15);
}
.tmb-polygon-list-item .tmb-poly-label {
    font-family: var(--font-family);
    font-size: 12px;
    color: #333;
    font-weight: 500;
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.tmb-polygon-list-item .tmb-poly-delete {
    opacity: 0;
    background: none;
    border: none;
    color: #d32f2f;
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    padding: 2px;
    border-radius: 3px;
    transition: opacity 0.12s ease;
}
.tmb-polygon-list-item:hover .tmb-poly-delete {
    opacity: 1;
}
.tmb-polygon-list-item .tmb-poly-delete:hover {
    background: #ffebee;
}

.tmb-polygon-list-item .tmb-poly-edit {
    opacity: 0;
    background: none;
    border: none;
    color: #1565c0;
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    padding: 2px;
    border-radius: 3px;
    transition: opacity 0.12s ease;
    flex-shrink: 0;
}
.tmb-polygon-list-item:hover .tmb-poly-edit {
    opacity: 1;
}
.tmb-polygon-list-item .tmb-poly-edit:hover {
    background: #e3f2fd;
}

.tmb-footer-actions {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

/* Admin Help */
.tmb-admin-help {
    position: absolute;
    bottom: 16px;
    left: 50%;
    transform: translateX(-50%);
    background: rgba(0, 0, 0, 0.7);
    color: #fff;
    font-family: var(--font-family);
    font-size: 12px;
    padding: 8px 14px;
    border-radius: 8px;
    display: none;
    z-index: 100;
    white-space: nowrap;
    pointer-events: none;
    transition: background 0.3s ease;
}
.tmb-admin-help.success {
    background: rgba(76, 175, 80, 0.9);
}
.tmb-admin-help.info {
    background: rgba(33, 150, 243, 0.9);
}

/* Auto-clear checkbox */
.tmb-admin-auto-clear {
    position: absolute;
    bottom: 16px;
    right: 76px;
    background: rgba(0, 0, 0, 0.6);
    color: #fff;
    font-family: var(--font-family);
    font-size: 12px;
    padding: 6px 10px;
    border-radius: 6px;
    display: none;
    z-index: 100;
    cursor: pointer;
    user-select: none;
    transition: background 0.3s ease;
}
.tmb-admin-auto-clear:hover {
    background: rgba(0, 0, 0, 0.8);
}
.tmb-admin-auto-clear input[type="checkbox"] {
    margin-right: 6px;
    cursor: pointer;
}

/* Drawing preview: polygon points & lines on SVG */
.tmb-svg-overlay path {
    fill: rgba(247, 166, 59, 0.01);
    stroke: #ff9800;
    stroke-width: 2;
    stroke-opacity: 0;
    transition:
        stroke-opacity 120ms ease,
        fill 120ms ease;
    vector-effect: non-scaling-stroke;
}
.tmb-svg-overlay path:hover {
    stroke-opacity: 0;
    fill: rgba(247, 166, 59, 0.25);
}
body.tmb-admin-mode .tmb-svg-overlay path {
    cursor: crosshair;
    pointer-events: none;
}

/* Draggable vertex dots for selected polygon */
.tong-mat-bang-zoom-container .tmb-vertex-dot {
    fill: #f7a63b;
    stroke: #fff;
    stroke-width: 2;
    vector-effect: non-scaling-stroke;
    cursor: grab;
    transition: r 80ms ease;
}
.tong-mat-bang-zoom-container .tmb-vertex-dot:hover {
    r: 7;
    fill: #ff9800;
}

/* Live preview: polygon shape while drawing */
.tong-mat-bang-zoom-container .tmb-preview-poly {
    fill: rgba(247, 166, 59, 0.15);
    stroke: #f7a63b;
    stroke-width: 2;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
}

/* Live preview: vertex dots */
.tong-mat-bang-zoom-container .tmb-preview-dot {
    fill: #f7a63b;
    stroke: #fff;
    stroke-width: 1.5;
    vector-effect: non-scaling-stroke;
}

/* Live preview: dashed line to mouse */
.tong-mat-bang-zoom-container .tmb-preview {
    stroke: #ff9800;
    stroke-width: 1.5;
    stroke-dasharray: 5, 4;
    vector-effect: non-scaling-stroke;
}

/* Selected polygon */
.tmb-svg-overlay path.selected,
.tmb-svg-viewer path.selected {
    stroke-opacity: 1 !important;
    fill: rgba(247, 166, 59, 0.15) !important;
}

/* Admin mode cursor for image */
body.tmb-admin-mode .tmb-svg-overlay,
body.tmb-admin-mode .tong-mat-bang-zoom-container {
    cursor: crosshair;
}

/* Responsive admin panel */
@media (max-width: 768px) {
    .tmb-admin-toggle {
        top: 60px;
        right: 12px;
    }
    .tmb-admin-toggle span {
        display: none !important;
    }
    .tmb-admin-panel {
        left: 8px;
        right: 8px;
        width: auto;
        max-width: 320px;
    }
    .tmb-admin-help {
        font-size: 11px;
        padding: 6px 10px;
        bottom: 12px;
    }
    .tmb-admin-auto-clear {
        bottom: 12px;
        right: 12px;
    }
}

/* =============================================================
   TIỆN ÍCH — FULL SCREEN ZOOMABLE IMAGE
   ============================================================= */
.tien-ich-page {
    position: fixed;
    inset: 0;
    overflow: hidden;
    background: #fff;
}

.tien-ich-zoom-container {
    position: absolute;
    inset: 0;
    bottom: 80px;
    overflow: hidden;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
    background: transparent;
    z-index: 3;
}

.ti-hotspot-overlay {
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: none;
    z-index: 5;
}

.ti-hotspot-dot-el {
    position: absolute;
    transform: scale(var(--ti-inv-scale, 1));
    transform-origin: 0 0;
    pointer-events: none;
    width: 20px;
    height: 20px;
}

.ti-hotspot-dot {
    position: absolute;
    top: 0;
    left: 0;
    transform: translate(-50%, -50%);
    width: 9px;
    height: 9px;
    border-radius: 50%;
    box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.4);
    animation: tiHotspotPulse 2s ease-in-out infinite;
    transition: box-shadow 0.2s;
}

.ti-hotspot-dot-el:hover .ti-hotspot-dot {
    animation-play-state: paused;
    box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.15);
}

@keyframes tiHotspotPulse {
    0%   { box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.4); }
    50%  { box-shadow: 0 0 0 6px rgba(0, 0, 0, 0); }
    100% { box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.4); }
}

/* Vertical solid line — connects dot to label above */
.ti-hotspot-line {
    position: absolute;
    top: calc(4.5px - var(--ti-line-h, 50px));
    left: -1px;
    width: 0;
    height: var(--ti-line-h, 50px);
    border-left: 1px solid rgba(255, 255, 255, 0.6);
    pointer-events: none;
}

.ti-hotspot-label {
    position: absolute;
    top: calc(4.5px - var(--ti-line-h, 50px) - 2px);
    left: 0%;
    transform: translateX(-50%);
    background-color: var(--ti-color, #00685D);
    color: #fff;
    border-radius: 4px;
    padding: 3px 8px;
    white-space: normal;
    font-family: var(--font-body);
    font-size: 11px;
    font-weight: 600;
    line-height: 1.3;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
    overflow: hidden;
    pointer-events: none;
    width: max-content;

}

.ti-hotspot-label strong {
    font-weight: 700;
}

/* Primary hotspots (Bạch Ngọc / Huyền Ngọc / Thanh Ngọc) shown on the
   landing view. They are the entry points into each sub-zone, so we
   make them larger, give them their own distinct label style, and let
   them receive pointer events (the regular sub-zone dots stay
   non-interactive). */
.ti-hotspot-dot-el--primary {
    width: 56px;
    height: 56px;
    pointer-events: auto;
    cursor: pointer;
    /* Allow fast taps on mobile without the 300ms double-tap-zoom delay,
       but still let the parent viewer handle multi-finger pans/swipes. */
    touch-action: manipulation;
}

.ti-hotspot-dot-el--primary .ti-hotspot-dot {
    width: 18px;
    height: 18px;
    box-shadow:
        0 0 0 4px rgba(255, 255, 255, 0.85),
        0 0 0 0 rgba(0, 0, 0, 0.45);
}

.ti-hotspot-dot-el--primary:hover .ti-hotspot-dot,
.ti-hotspot-dot-el--primary:focus-visible .ti-hotspot-dot {
    animation-play-state: paused;
    box-shadow:
        0 0 0 5px rgba(255, 255, 255, 0.95),
        0 0 0 10px rgba(0, 0, 0, 0.18);
}

.ti-hotspot-dot-el--primary:focus-visible {
    outline: none;
}

.ti-hotspot-dot-el--primary .ti-hotspot-label {
    font-size: 12px;
    padding: 5px 12px;
    border-radius: 6px;
    box-shadow: 0 3px 12px rgba(0, 0, 0, 0.3);
    white-space: nowrap;
    /* Anchor the label above the dot, just like the regular sub-zone
       hotspots. Primary dots are 18px (vs 9px for sub-zone dots), so
       the centre offset becomes 9px instead of 4.5px. */
    top: calc(9px - var(--ti-line-h, 60px) - 2px);
    bottom: auto;
    left: 0%;
    transform: translateX(-50%);
    /* Make the whole label clickable, not just the dot. Sub-zone labels
       stay pointer-events: none so they don't fight the map pan/zoom. */
    pointer-events: auto;
    cursor: pointer;
    transition: opacity 0.2s ease, transform 0.2s ease;
}

.ti-hotspot-dot-el--primary .ti-hotspot-label:hover {
    opacity: 0.9;
    transform: translateX(-50%) scale(1.05);
}

.ti-hotspot-dot-el--primary .ti-hotspot-line {
    /* Same vertical anchor as the regular sub-zone hotspots, shifted
       down 4.5px because primary dots are 18px tall (tâm dot = 9px). */
    top: calc(9px - var(--ti-line-h, 60px));
    left: -1px;
    width: 0;
    height: var(--ti-line-h, 60px);
    border-left: 1px solid rgba(255, 255, 255, 0.6);
}

/* Back button — appears once the user has drilled into a sub-zone view.
   Hidden by default; JS toggles `.is-visible` when a primary filter is
   active. Style mirrors .ban-ngay-back-btn: brand teal pill (--pr-4),
   cream text, uppercase, chevron icon. Positioned top-left so it
   doesn't collide with the right-side zoom rail or the bottom-center
   dropdowns. The wrapper is `.tien-ich-page` (position: fixed inset:0)
   so the absolute coords anchor to the visible viewport. */
.ti-hotspot-back-btn {
    position: absolute;
    top: 20px;
    left: 20px;
    z-index: 50;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 9px 16px;
    border: none;
    border-radius: 48px;
    background: var(--pr-4);
    color: var(--pr-0);
    font-family: var(--font-family);
    font-size: 14px;
    font-weight: 500;
    line-height: 1;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    cursor: pointer;
    pointer-events: auto;
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    /* Kill the 300ms tap delay on mobile without breaking the
       parent's pan/pinch gestures elsewhere. */
    touch-action: manipulation;
    opacity: 0;
    transform: translateY(-6px);
    transition:
        opacity 0.22s ease,
        transform 0.22s ease,
        background 0.2s,
        color 0.2s;
    visibility: hidden;
}

.ti-hotspot-back-btn.is-visible {
    opacity: 1;
    transform: translateY(0);
    visibility: visible;
}

.ti-hotspot-back-btn:hover {
    background: var(--pr-3);
    color: var(--pr-0);
}

.ti-hotspot-back-btn:active {
    transform: translateY(0) scale(0.96);
}

.ti-hotspot-back-btn svg {
    flex-shrink: 0;
}

/* Mobile: collapse the pill into a circular icon-only button, matching
   the .ban-ngay-back-btn pattern (label hidden, square padding so
   border-radius 50% produces a true circle). */
@media (max-width: 768px) {
    .ti-hotspot-back-btn {
        padding: 9px;
        gap: 0;
        border-radius: 50%;
        align-items: center;
        justify-content: center;
    }

    .ti-hotspot-back-btn > svg {
        width: 20px;
        height: 20px;
        display: block;
    }

    .ti-hotspot-back-btn > span {
        display: none;
    }
}

.tien-ich-zoom-container:active {
    cursor: grabbing;
}

.img-overlay-spinner {
    width: 40px;
    height: 40px;
    border: 3px solid rgba(0, 0, 0, 0.1);
    border-top-color: var(--pr-1);
    border-radius: 50%;
    animation: imgSpinnerSpin 0.7s linear infinite;
}
@keyframes imgSpinnerSpin {
    to {
        transform: rotate(360deg);
    }
}

/* (Brand loader styles removed — page-transition SPA loader is now the
   single loading visual across the whole tour experience.) */

.tien-ich-zoom-img {
    position: absolute;
    top: 0;
    left: 0;
    width: auto;
    height: auto;
    max-width: none;
    max-height: none;
    transform-origin: 0 0;
    /* Seed with translate3d to guarantee GPU-layer promotion on iOS,
       isolating pan/zoom repaints from the fixed bottom menu. */
    transform: translate3d(0, 0, 0);
    will-change: transform;
    pointer-events: none;
    display: block;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
}

/* Zoom controls — handled by shared .prl-zoom-* (see top of file) */

@media (max-width: 768px) {
    .rotage-360-drag-hint {
        bottom: 240px;
    }
}

/* =============================================================
   360° VIEWER — MOBILE SAFETY
   ------------------------------------------------------------
   On tall portrait viewports (or when the mobile URL bar
   collapses/expands) the viewer MUST keep the panorama
   cover-fitted to the full visible area — no black gap
   below. dvh handles the live resize, svh handles the
   "smallest possible viewport" worst case (URL bar visible),
   and we explicitly forbid any background bleed-through.
   ============================================================= */
@supports (height: 100dvh) {
    .rotage-360-wrap,
    .pearl-viewer {
        height: 100dvh;
    }
}
@supports (height: 100svh) {
    .rotage-360-wrap,
    .pearl-viewer {
        min-height: 100svh;
    }
}
.rotage-360-wrap,
.pearl-viewer,
.rotage-360-container,
.rotage-360-canvas {
    background: #060f14;
}

/* =============================================================
   HỆ THỐNG ĐƯỜNG NỘI KHU — FULL SCREEN ZOOMABLE IMAGE
   ============================================================= */
.noi-khu-page {
    position: fixed;
    inset: 0;
    overflow: hidden;
    background: #fff;
}

.noi-khu-zoom-container {
    position: absolute;
    inset: 0;
    bottom: 80px;
    overflow: hidden;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
    background: transparent;
    z-index: 3;
}

.noi-khu-zoom-container:active {
    cursor: grabbing;
}

.noi-khu-zoom-container.is-admin {
    cursor: default;
    touch-action: auto;
    overflow: visible;
}

.noi-khu-zoom-img {
    position: absolute;
    top: 0;
    left: 0;
    width: auto;
    height: auto;
    max-width: none;
    max-height: none;
    transform-origin: 0 0;
    /* Seed with translate3d to guarantee GPU-layer promotion on iOS,
       isolating pan/zoom repaints from the fixed bottom menu. */
    transform: translate3d(0, 0, 0);
    will-change: transform;
    pointer-events: none;
    display: block;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
}

.noi-khu-zoom-img.is-admin {
    position: relative;
    width: auto;
    height: 100%;
    max-width: none;
    max-height: 100%;
    transform: none !important;
    margin: 0 auto;
    top: 0;
    left: 0;
}

/* Zoom controls — handled by shared .prl-zoom-* (see top of file) */

/* =============================================================
   BAN NGÀY NGOẠI KHU — FULL SCREEN ZOOMABLE IMAGE
   ============================================================= */
.ban-ngay-page {
    position: fixed;
    inset: 0;
    overflow: hidden;
    background: #060f14;
}


.ban-ngay-back-btn {
    position: fixed;
    top: 20px;
    left: 20px;
    z-index: 50;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 9px 16px;
    background: var(--pr-4);
    border: none;
    border-radius: 48px;
    color: var(--pr-0);
    font-family: var(--font-family);
    font-size: 14px;
    font-weight: 500;
    line-height: 1;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    cursor: pointer;
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    transition:
        background 0.2s,
        color 0.2s,
        transform 0.15s;
}
.ban-ngay-back-btn:hover {
    background: var(--pr-3);
    color: var(--pr-0);
}
.ban-ngay-back-btn:active {
    transform: scale(0.96);
}

.ban-ngay-zoom-container {
    position: absolute;
    inset: 0;
    overflow: hidden;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
    background: transparent;
    z-index: 3;
}
.ban-ngay-zoom-container:active {
    cursor: grabbing;
}

.ban-ngay-zoom-img {
    position: absolute;
    top: 0;
    left: 0;
    width: auto;
    height: auto;
    max-width: none;
    max-height: none;
    transform-origin: 0 0;
    /* Seed with translate3d to guarantee GPU-layer promotion on iOS,
       isolating pan/zoom repaints from the fixed bottom menu. */
    transform: translate3d(0, 0, 0);
    will-change: transform;
    pointer-events: none;
    display: block;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
}

.lqip-placeholder {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    filter: blur(20px);
    transform: scale(1.1);
    transition: opacity 0.5s ease;
    pointer-events: none;
    z-index: 1;
}

/* Zoom controls — handled by shared .prl-zoom-* (see top of file) */

/* =============================================================
   TIỆN ÍCH — DROPDOWN PILLS
   ============================================================= */
.tien-ich-dropdowns {
    position: fixed;
    bottom: 158px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: flex-end;
    gap: 10px;
    z-index: 40;
    padding: 0 16px;
}

.tien-ich-dropdowns .menu-pill-dropdown {
    position: relative;
}

.tien-ich-dropdowns .menu-pill-dropdown::before {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 24px;
    pointer-events: auto;
    z-index: -1;
}

/* Hidden when not hovered and not open */
.tien-ich-dropdowns .menu-pill-dropdown:hover > .menu-pill-dropdown__menu {
    animation: none;
    opacity: 1;
    transform: translateX(-50%) translateY(0);
    pointer-events: auto;
}

/* Override: keep hidden if .is-open is NOT present (e.g. just closed, hover still active) */
.tien-ich-dropdowns .menu-pill-dropdown:hover:not(.is-open) > .menu-pill-dropdown__menu {
    opacity: 0;
    pointer-events: none;
    transform: translateX(-50%) translateY(8px);
}

/* Explicit open state */
.tien-ich-dropdowns .menu-pill-dropdown.is-open > .menu-pill-dropdown__menu {
    animation: none;
    opacity: 1;
    transform: translateX(-50%) translateY(0);
    pointer-events: auto;
}

.tien-ich-dropdowns
    .menu-pill-dropdown:not(:hover)
    > .menu-pill-dropdown__menu:not(:hover) {
    animation: none;
    opacity: 0;
    pointer-events: none;
    transform: translateX(-50%) translateY(8px);
}

.tien-ich-dropdowns .menu-pill-dropdown > .menu-pill {
    font-size: 14px;
    padding: 9px 16px;
    border-radius: 48px;
    outline: 1px solid var(--pr-0);
    outline-offset: -1px;
    background: rgba(0, 0, 0, 0.18);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1px solid rgba(255, 255, 255, 0.08);
    color: rgba(252, 249, 246, 0.85);
    display: flex;
    align-items: center;
    gap: 6px;
}

.tien-ich-dropdowns .menu-pill-dropdown > .menu-pill:hover {
    background: rgba(0, 0, 0, 0.3);
    color: rgba(252, 249, 246, 1);
}

.tien-ich-dropdowns .menu-pill-dropdown.is-open > .menu-pill,
.tien-ich-dropdowns .menu-pill-dropdown > .menu-pill.is-active {
    background: var(--pr-0);
    color: var(--pr-5);
}

.tien-ich-dropdowns .dropdown-arrow {
    flex-shrink: 0;
    transition: transform 0.2s ease;
}

.tien-ich-dropdowns .menu-pill-dropdown:hover .dropdown-arrow {
    transform: rotate(180deg);
}

.tien-ich-dropdowns .menu-pill-dropdown.is-open .dropdown-arrow {
    transform: rotate(180deg);
}

.tien-ich-dropdowns .menu-pill-dropdown:hover:not(.is-open) .dropdown-arrow {
    transform: rotate(0deg);
}

.tien-ich-dropdowns .menu-pill-dropdown:not(:hover) .dropdown-arrow {
    transform: rotate(0deg);
}

.tien-ich-dropdowns .menu-pill-dropdown__menu {
    bottom: calc(100% + 2px);
    top: auto;
    width: 250px;
    max-height: 420px;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.3) transparent;
    gap: 4px;
}

.tien-ich-dropdowns .menu-pill-dropdown__menu::-webkit-scrollbar {
    width: 4px;
}

.tien-ich-dropdowns .menu-pill-dropdown__menu::-webkit-scrollbar-track {
    background: transparent;
}

.tien-ich-dropdowns .menu-pill-dropdown__menu::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.3);
    border-radius: 999px;
}

.tien-ich-dropdowns .menu-pill-dropdown__item {
    display: flex;
    align-items: flex-start;
    justify-content: flex-start;
    padding: 7px 12px;
    border-radius: 8px;
    background: var(--pr-4);
    color: var(--pr-0);
    font-size: 13px;
    font-family: var(--font-family);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    white-space: normal;
    word-break: break-word;
    text-align: left;
    line-height: 1.4;
    transition:
        background var(--transition-base),
        color var(--transition-base),
        transform var(--transition-fast);
}

/* Responsive — tablet */
@media (max-width: 1200px) {
    .tien-ich-dropdowns {
        bottom: 197px;
        gap: 8px;
        padding: 0 12px;
    }

    .tien-ich-dropdowns .menu-pill-dropdown > .menu-pill {
        font-size: 12px;
        padding: 8px 12px;
    }
}

/* Responsive — mobile (< 840px) */
@media (max-width: 840px) {
    .menu__center-btn {
        height: 36px;
        padding: 0 10px;
        font-size: 14px;
    }

    .menu__center-logo-img {
        height: 40px;
    }

    .tien-ich-dropdowns {
        bottom: 225px;
        flex-wrap: wrap;
        overflow-x: visible;
        justify-content: center;
        gap: 12px;
        padding: 0 12px;
        max-width: 100%;
        width: 100%;
    }

    .tien-ich-dropdowns .menu-pill-dropdown {
        flex: 1 1 calc(50% - 6px);
        max-width: calc(50% - 6px);
        min-width: calc(50% - 6px);
    }

    .tien-ich-dropdowns .menu-pill-dropdown > .menu-pill {
        font-size: 12px;
        padding: 7px 16px;
        width: 100%;
        justify-content: center;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* Dropdown: hidden by default on mobile, shown when .is-open */
    .menu-pill-dropdown > .menu-pill-dropdown__menu,
    .tien-ich-dropdowns .menu-pill-dropdown > .menu-pill-dropdown__menu {
        position: absolute;
        bottom: calc(100% + 0px);
        top: auto;
        left: 50%;
        transform: translateX(-50%) translateY(8px);
        width: 220px;
        z-index: 999;
        max-height: 280px;
        overflow-y: auto;
        opacity: 0;
        pointer-events: none;
        animation: none !important;
        padding-bottom: 7px;
    }

    .menu-pill-dropdown.is-open > .menu-pill-dropdown__menu,
    .tien-ich-dropdowns .menu-pill-dropdown.is-open > .menu-pill-dropdown__menu {
        opacity: 1;
        pointer-events: auto;
        transform: translateX(-50%) translateY(0);
        animation: none !important;
    }

    /* Dropdown arrow */
    .tien-ich-dropdowns .menu-pill-dropdown:hover .dropdown-arrow {
        transform: rotate(180deg);
    }

    .tien-ich-dropdowns .menu-pill-dropdown.is-open .dropdown-arrow {
        transform: rotate(180deg);
    }

    .tien-ich-dropdowns .menu-pill-dropdown:hover:not(.is-open) .dropdown-arrow {
        transform: rotate(0deg);
    }

    .tien-ich-dropdowns .menu-pill-dropdown:not(:hover) .dropdown-arrow {
        transform: rotate(0deg);
    }

    .tien-ich-dropdowns .menu-pill-dropdown::after {
        content: "";
        position: absolute;
        bottom: -6px;
        left: 50%;
        transform: translateX(-50%);
        width: 220px;
        height: 14px;
        background: transparent;
        pointer-events: none;
        z-index: -1;
    }

    .tien-ich-dropdowns .menu-pill-dropdown__item {
        font-size: 12px;
        padding: 7px 12px;
    }
}

/* ----------------------------------------------------------
   RESPONSIVE — PHONE (≤ 480px)
   Compact, 2-column pill grid; readable active state.
   Goal: fit the full shared-menu nav (6 pills + center logo +
   day/night toggle) into ~150–170px of vertical space and keep
   every label fully visible.
   ---------------------------------------------------------- */

@media (max-width: 480px) {
    .main-container {
        padding-bottom: 260px;
    }

    .menu {
        padding: 10px 14px 14px;
        gap: 6px;
    }

    .menu__bg {
        height: 165px;
    }

    /* Center row: tighter so the pill grid below it gets the space */
    .menu__center {
        gap: 6px;
        padding-bottom: 4px;
    }

    .menu__center-btn {
        height: 34px;
        padding: 0 12px;
        font-size: 12px;
        letter-spacing: 0.04em;
    }

    .menu__center img,
    .menu__center-logo-img {
        height: 36px;
    }

    /* Pill grid: items auto-size to their label.
       2 stacked rows (one per group: .menu__left + .menu__right),
       each centered horizontally with equal `gap: 6px` between items. */
    .menu__bottom {
        grid-template-columns: 1fr;
        grid-template-rows: auto auto;
        justify-items: stretch;
        row-gap: 6px;
    }

    .menu__pills {
        grid-row: 2;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        gap: 6px;
        width: 100%;
        padding: 0 4px;
    }

    /* Each group (.menu__left / .menu__right) is a centered row of pills.
       `justify-content: center` centers each row as a whole;
       `gap: 6px` keeps the spacing between pills perfectly even. */
    .menu__pills .menu__left,
    .menu__pills .menu__right {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        align-items: center;
        gap: 6px;
        flex: 0 0 auto;
        width: 100%;
    }

    /* Each pill auto-sizes to its label. `flex: 0 0 auto` keeps pills at
       their natural width so the group centers the row and `gap: 6px`
       distributes spacing evenly between items. */
    .menu__pills .menu__left > *,
    .menu__pills .menu__right > * {
        flex: 0 0 auto;
        justify-content: center;
    }

    /* Compact pills — content-width, no full-row stretch so gap stays even */
    .menu-pill {
        font-size: 12px;
        padding: 8px 12px;
        letter-spacing: 0.04em;
        white-space: nowrap;
    }

    .menu-pill-dropdown > .menu-pill {
        font-size: 12px;
        padding: 8px 12px;
        justify-content: center;
    }

    /* Active pill — same look as hover so the current page is permanently lit up */
    .menu-pill.is-active {
        background: var(--pr-0);
        color: var(--pr-5);
    }

    .menu-pill-dropdown:has(> .menu-pill.is-active) > .menu-pill,
    .menu-pill-dropdown:has(> .menu-pill.is-active) > button,
    .menu-pill-dropdown:has(> .menu-pill-dropdown__menu .is-active) > .menu-pill,
    .menu-pill-dropdown:has(> .menu-pill-dropdown__menu .is-active) > button {
        background: var(--pr-0);
        color: var(--pr-5);
    }

    /* Keep content above the new compact menu height */
    .map-split {
        --shared-menu-height: 175px;
        height: calc(100dvh - var(--shared-menu-height) + 16px);
    }

    .map-wave {
        bottom: 175px;
    }

    /* Dropdown panels open upward from the bottom row — push them above
       the safe area so they never get clipped by the phone's bottom edge */
    .menu-pill-dropdown__menu {
        bottom: calc(100% + 6px);
        left: 0;
        right: auto;
        width: max-content;
        max-width: 220px;
        max-height: 220px;
        overflow-y: auto;
    }

    .menu-pill-dropdown__item {
        font-size: 12px;
        padding: 8px 12px;
        white-space: normal;
        line-height: 1.35;
    }

    /* `tien-ich` page keeps its 4 inline dropdowns above the menu */
    .tien-ich-dropdowns {
        bottom: 200px;
        flex-wrap: wrap;
        overflow-x: visible;
        justify-content: center;
        gap: 8px;
        padding: 0 10px;
        max-width: 100%;
        width: 100%;
    }

    .tien-ich-dropdowns .menu-pill-dropdown {
        flex: 1 1 calc(50% - 4px);
        max-width: calc(50% - 4px);
        min-width: calc(50% - 4px);
    }

    .tien-ich-dropdowns .menu-pill-dropdown > .menu-pill {
        font-size: 12px;
        padding: 8px 12px;
        width: 100%;
        justify-content: center;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* Dropdown: hidden by default on phone, shown when .is-open */
    .menu-pill-dropdown > .menu-pill-dropdown__menu,
    .tien-ich-dropdowns .menu-pill-dropdown > .menu-pill-dropdown__menu {
        position: absolute;
        bottom: calc(100% + 0px);
        top: auto;
        left: 50%;
        transform: translateX(-50%) translateY(8px);
        width: 220px;
        z-index: 999;
        max-height: 280px;
        overflow-y: auto;
        opacity: 0;
        pointer-events: none;
        animation: none !important;
        padding-bottom: 7px;
    }

    .menu-pill-dropdown.is-open > .menu-pill-dropdown__menu,
    .tien-ich-dropdowns .menu-pill-dropdown.is-open > .menu-pill-dropdown__menu {
        opacity: 1;
        pointer-events: auto;
        transform: translateX(-50%) translateY(0);
        animation: none !important;
    }

    /* Dropdown arrow */
    .tien-ich-dropdowns .dropdown-arrow {
        transition: transform 0.2s ease;
    }

    .tien-ich-dropdowns .menu-pill-dropdown:hover .dropdown-arrow {
        transform: rotate(180deg);
    }

    .tien-ich-dropdowns .menu-pill-dropdown.is-open .dropdown-arrow {
        transform: rotate(180deg);
    }

    .tien-ich-dropdowns .menu-pill-dropdown:hover:not(.is-open) .dropdown-arrow {
        transform: rotate(0deg);
    }

    .tien-ich-dropdowns .menu-pill-dropdown:not(:hover) .dropdown-arrow {
        transform: rotate(0deg);
    }
}

/* =============================================================
   HỆ THỐNG ĐƯỜNG NỘI KHU — ADMIN DRAWING PANEL
   ============================================================= */

/* Static SVG paths (exported from admin tool)
   Must match the image's rendered position and dimensions exactly */
.nk-static-paths {
    position: absolute;
    pointer-events: none;
    z-index: 4;
    /* top/left/width/height are set dynamically by JS to match the image */
}

/* SVG Overlay */
.noi-khu-svg-overlay,
.noi-khu-svg-viewer {
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: none;
    z-index: 5;
    overflow: visible;
}
/* By default, no descendant of the viewer SVG should swallow taps —
   the viewer is decorative (animated route lines). Only the explicit
   interactive children opt back in (see individual cursor rules below).
   This keeps .prl-zoom-controls clickable on mobile even though the
   SVG extends past its container's bounds. */
.noi-khu-svg-viewer * {
    pointer-events: none;
}
.noi-khu-svg-overlay.is-drawing,
.noi-khu-svg-overlay.is-select-mode {
    pointer-events: auto;
}
/* In admin modes, re-enable hits on the editable handles / hitareas. */
.noi-khu-svg-overlay.is-drawing .nk-path-hitarea,
.noi-khu-svg-overlay.is-select-mode .nk-path-hitarea,
.noi-khu-svg-overlay.is-drawing .nk-handle,
.noi-khu-svg-overlay.is-select-mode .nk-handle,
.noi-khu-svg-overlay.is-drawing .nk-ctrl-pt,
.noi-khu-svg-overlay.is-select-mode .nk-ctrl-pt,
.noi-khu-svg-overlay.is-drawing .nk-drag-pt,
.noi-khu-svg-overlay.is-select-mode .nk-drag-pt {
    pointer-events: auto;
}
.noi-khu-svg-viewer {
    z-index: 4;
}
.noi-khu-svg-viewer .nk-viewer-path-line {
    pointer-events: none;
    animation: nk-path-run 20s linear infinite;
    /* Force thicker, zoom-independent stroke */
    stroke-width: 11;
    vector-effect: non-scaling-stroke;
}
@keyframes nk-path-run {
    /* Phase 1: Running light from start to end (~5s) */
    0% {
        stroke-dashoffset: var(--nk-path-peri, 8000);
        opacity: 1;
        filter: drop-shadow(0 0 4px var(--nk-path-color, #fedc32));
    }
    /* End of run — line fully drawn */
    25% {
        stroke-dashoffset: 0;
        opacity: 1;
        filter: drop-shadow(0 0 4px var(--nk-path-color, #fedc32));
    }
    /* Phase 2: Blink at end (~14.5s, ~3.6s per blink cycle) */
    26% {
        opacity: 0.55;
        filter: drop-shadow(0 0 2px var(--nk-path-color, #fedc32));
    }
    34% {
        opacity: 1;
        filter: drop-shadow(0 0 20px var(--nk-path-color, #fedc32)) brightness(1.6);
    }
    35% {
        opacity: 0.55;
        filter: drop-shadow(0 0 2px var(--nk-path-color, #fedc32));
    }
    43% {
        opacity: 1;
        filter: drop-shadow(0 0 20px var(--nk-path-color, #fedc32)) brightness(1.6);
    }
    44% {
        opacity: 0.55;
        filter: drop-shadow(0 0 2px var(--nk-path-color, #fedc32));
    }
    52% {
        opacity: 1;
        filter: drop-shadow(0 0 20px var(--nk-path-color, #fedc32)) brightness(1.6);
    }
    53% {
        opacity: 0.55;
        filter: drop-shadow(0 0 2px var(--nk-path-color, #fedc32));
    }
    61% {
        opacity: 1;
        filter: drop-shadow(0 0 20px var(--nk-path-color, #fedc32)) brightness(1.6);
    }
    62% {
        opacity: 0.55;
        filter: drop-shadow(0 0 2px var(--nk-path-color, #fedc32));
    }
    70% {
        opacity: 1;
        filter: drop-shadow(0 0 20px var(--nk-path-color, #fedc32)) brightness(1.6);
    }
    71% {
        opacity: 0.55;
        filter: drop-shadow(0 0 2px var(--nk-path-color, #fedc32));
    }
    79% {
        opacity: 1;
        filter: drop-shadow(0 0 20px var(--nk-path-color, #fedc32)) brightness(1.6);
    }
    /* Phase 3: Reset back to start */
    97% {
        stroke-dashoffset: 0;
        opacity: 1;
        filter: drop-shadow(0 0 4px var(--nk-path-color, #fedc32));
    }
    98% {
        stroke-dashoffset: var(--nk-path-peri, 8000);
        opacity: 1;
        filter: drop-shadow(0 0 4px var(--nk-path-color, #fedc32));
    }
    100% {
        stroke-dashoffset: var(--nk-path-peri, 8000);
        opacity: 1;
        filter: drop-shadow(0 0 4px var(--nk-path-color, #fedc32));
    }
}
.noi-khu-svg-viewer .nk-viewer-path-line:hover {
    animation-play-state: paused;
    opacity: 1;
}

/* SVG Overlay — bản đồ vị trí (đường đi viewer)
   Mirrors .noi-khu-svg-viewer for the LEFT pane of ban-do-vi-tri.html.
   The viewer SVG sits on top of the zoomable map image and inherits the
   same transform as #mapViTriZoomImg so routes pan/zoom together. */
.ban-do-vi-tri-svg-viewer {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 4;
    overflow: visible;
    pointer-events: none;
    transform-origin: 0 0;
}

/* Layer 1 — static base line (solid, no animation).
   Thick outer stroke acts as the road casing. */
.ban-do-vi-tri-svg-viewer .bdvt-viewer-path-bg {
    pointer-events: none;
    vector-effect: non-scaling-stroke;
    opacity: 0.85;
    filter: drop-shadow(0 0 3px var(--nk-path-color, #ffa502));
}

/* Layer 2 — thin dashed running light overlay (~2.5px), centered on the
   base path so it reads as a "lane marker" flowing along the route.
   JS sets stroke-width and stroke color on the run path. */
.ban-do-vi-tri-svg-viewer .bdvt-viewer-path-run {
    pointer-events: none;
    stroke-dasharray: var(--nk-dash, 8) var(--nk-gap, 14);
    stroke-dashoffset: 0;
    animation: bdvt-dash-run 1.5s linear infinite;
    vector-effect: non-scaling-stroke;
}

/* Layer 3 — short bright dash scrolling along the path, simulating
   moving headlights / traffic flow. JS sets --nk-flow-dash/--nk-flow-cycle
   dynamically based on getTotalLength() so the dash loops seamlessly
   along the entire path length. */
.ban-do-vi-tri-svg-viewer .bdvt-viewer-path-flow {
    pointer-events: none;
    stroke-dashoffset: var(--nk-flow-start, 90);
    animation: bdvt-flow-run var(--nk-flow-dur, 1.6s) linear infinite;
    vector-effect: non-scaling-stroke;
}

.ban-do-vi-tri-svg-viewer .bdvt-viewer-path-run:hover,
.ban-do-vi-tri-svg-viewer .bdvt-viewer-path-flow:hover {
    animation-play-state: paused;
}

/* Dashes flow forward: dash starts off-path (offset = dash+gap), ends at 0 */
@keyframes bdvt-dash-run {
    from { stroke-dashoffset: calc(var(--nk-dash, 8) + var(--nk-gap, 14)); }
    to   { stroke-dashoffset: 0; }
}

/* Flow layer — gradient-stroked dash (white→transparent→white)
   sweeps from off-path-before-start to off-path-after-end.
   JS sets --nk-flow-start (dash length) and --nk-flow-end (-path length). */
@keyframes bdvt-flow-run {
    from { stroke-dashoffset: var(--nk-flow-start, 90); }
    to   { stroke-dashoffset: var(--nk-flow-end, -1000); }
}

/* SVG Overlay — ban ngày ngoại khu (đường đi viewer)
   Mirrors .ban-do-vi-tri-svg-viewer for the ngoại khu zoomable images
   in ban-ngay-ngoai-khu.html. The viewer SVG sits on top of the
   zoomable image (#banNgayZoomImg) and inherits the same transform so
   routes pan/zoom together. Coordinate space matches the source
   nk_{N}.jpg pixel space (3840×2160) — no scaling is needed. */
.ban-ngay-nk-svg-viewer {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 4;
    overflow: visible;
    pointer-events: none;
    transform-origin: 0 0;
}

/* Layer 1 — static base line (solid, no animation). Acts as the road casing.
   White outer halo makes the orange stroke pop against bright ngoại khu
   daytime backgrounds (sky, foliage, concrete). The halo is rendered via
   filter: drop-shadow on a white-painted copy stacked below the orange
   stroke — see the JS render() function for the implementation. */
.ban-ngay-nk-svg-viewer .bnnk-viewer-path-bg {
    pointer-events: none;
    vector-effect: non-scaling-stroke;
    opacity: 0.92;
    filter: drop-shadow(0 0 2px var(--nk-path-color, #0e8b8b));
}

/* Layer 1b — white halo behind the colored stroke so routes stay readable
   on light backgrounds (asphalt, sky, foliage). Mirrors the same `d` as
   the bg layer but is drawn first (wider, white, slightly blurred). */
.ban-ngay-nk-svg-viewer .bnnk-viewer-path-halo {
    pointer-events: none;
    vector-effect: non-scaling-stroke;
    opacity: 0.8;
}

/* Layer 2 — thin dashed running light (~2.5px white) flowing along the path. */
.ban-ngay-nk-svg-viewer .bnnk-viewer-path-run {
    pointer-events: none;
    stroke-dasharray: var(--nk-dash, 8) var(--nk-gap, 14);
    stroke-dashoffset: 0;
    animation: bdvt-dash-run 1.5s linear infinite;
    vector-effect: non-scaling-stroke;
}

/* Layer 3 — short bright dash scrolling along the path (moving headlights /
   traffic flow). JS sets --nk-flow-dur based on getTotalLength() so the dash
   loops seamlessly along the entire path length. */
.ban-ngay-nk-svg-viewer .bnnk-viewer-path-flow {
    pointer-events: none;
    stroke-dashoffset: var(--nk-flow-start, 90);
    animation: bdvt-flow-run var(--nk-flow-dur, 1.6s) linear infinite;
    vector-effect: non-scaling-stroke;
}

.ban-ngay-nk-svg-viewer .bnnk-viewer-path-run:hover,
.ban-ngay-nk-svg-viewer .bnnk-viewer-path-flow:hover {
    animation-play-state: paused;
}

/* ================================================================
   BAN NGÀY NGOẠI KHU — HOTSPOTS (line + block)
   Mirrors the admin/quan-tri-duong-di.html hotspot pattern:
     - Overlay sized to image's NATURAL dimensions (px) so hotspot
       pixel positions from the JSON align with the source image.
     - Transform mirrors the image's pan/zoom so the overlay tracks
       the image at every zoom level.
     - Inner elements counter-scale via --bn-hs-inv-scale so the
       dot/label/line/block stay constant pixel size when zoomed.

   Coordinates: JSON stores (x, y) as % of image natural dims.
   JS converts to absolute px and positions elements there.
   ================================================================ */

/* Hotspot overlay — sized to natural px dimensions via JS so the
   hotspot pixel positions align with the source image. Transform
   mirrors the image's pan/zoom (see syncOverlay in tour.js). */
.ban-ngay-hotspot-overlay {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 5;
    pointer-events: none;
    transform-origin: 0 0;
}

/* ----- LINE kind ----- */

/* Dot-element: auto-sized container, anchored at the % point of the
   image via the parent's % left/top. Counter-scale applied via JS so
   the dot/line/label stay constant pixel size regardless of zoom.
   Mirrors .nk-hotspot-dot-el styling in he-thong-duong-noi-khu.html. */
.bn-hs-dot-el {
    position: absolute;
    pointer-events: all;
    cursor: pointer;
    transform: translate(-50%, -50%) scale(var(--bn-hs-inv-scale, 1));
    transform-origin: 0 0;
}

/* Vertical guide line — connects label above to the dot below.
   top/height use --bn-hs-line-h (set by JS per hotspot). Matches
   .nk-hotspot-line in he-thong-duong-noi-khu.html: always teal
   --pr-3 (the hotspot color stays on the dot/label only) with a
   pulsing glow that breathes in lockstep with the dot's
   hotspotPulse animation. */
.bn-hs-line-el {
    position: absolute;
    top: calc(0px - var(--bn-hs-line-h, 120px));
    left: 50%;
    transform: translateX(-50%);
    width: 1px;
    height: var(--bn-hs-line-h, 120px);
    background-color: transparent;
    background-image: linear-gradient(
        to bottom,
        var(--pr-0) 0,
        var(--pr-0) 6px,
        transparent 6px,
        transparent 12px
    );
    background-size: 1px 12px;
    background-repeat: repeat-y;
    opacity: 0.85;
    pointer-events: none;
    box-shadow: 0 0 6px rgba(252, 249, 246, 0.5);
    animation: bnHsLinePulse 2s ease-in-out infinite;
}

@keyframes bnHsLinePulse {
    0%,
    100% {
        box-shadow: 0 0 6px rgba(252, 249, 246, 0.5);
    }

    50% {
        box-shadow: 0 0 14px rgba(252, 249, 246, 0.9);
    }
}

@keyframes bnHsDotPulse {
    0% {
        box-shadow: 0 0 0 0 rgba(252, 249, 246, 0.4);
    }

    50% {
        box-shadow: 0 0 0 10px rgba(252, 249, 246, 0);
    }

    100% {
        box-shadow: 0 0 0 0 rgba(252, 249, 246, 0.4);
    }
}

/* Pulsing dot at the anchor point. Sized ~3/4 (15px) without the white
   border for a cleaner look. Uses --pr-0 kem nhạt with the matching
   bnHsDotPulse keyframes. Forced to --pr-0 (matching the line) so the
   per-hotspot `color` from hotspot-nk*.json stays on the label accent. */
.bn-hs-dot-el .bn-hs-dot {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background-color: var(--pr-0);
    box-shadow: 0 0 0 0 rgba(252, 249, 246, 0.4);
    animation: bnHsDotPulse 2s ease-in-out infinite;
    pointer-events: none;
}

/* Label box above the dot. Flush with the top of the line so the
   label sits at distance = --bn-hs-line-h above the anchor (matches
   the line's actual height). Mirrors .nk-hotspot-label: warm pr-0→
   pr-2 gradient background, --pr-4 text, uppercase, larger size for
   readability on bright ngoại khu backgrounds. The colour is opt-in
   via --bn-hs-color, otherwise the default gradient is used. */
.bn-hs-dot-el .bn-hs-label {
    position: absolute;
    bottom: var(--bn-hs-line-h, 120px);
    left: 50%;
    transform: translateX(-50%);
    padding: 4px 10px;
    background: linear-gradient(135deg, var(--pr-0) 0%, var(--pr-1) 30%, var(--pr-2) 50%, var(--pr-2) 70%, var(--pr-2) 100%);
    color: var(--pr-4);
    border-radius: 5px;
    font-family: var(--font-family);
    font-size: 14px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.65px;
    white-space: nowrap;
    text-align: center;
    line-height: 1.2;
    pointer-events: none;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
}

/* Selected / hover state — solid primary background, like
   .nk-hotspot-dot-el.is-selected. Applies to dot + label so both
   pop when the hotspot is active. */
.bn-hs-dot-el.is-selected .bn-hs-dot,
.bn-hs-dot-el:hover .bn-hs-dot {
    background-color: var(--color-primary);
    animation-play-state: paused;
    box-shadow:
        0 0 12px rgba(14, 139, 139, 0.25),
        0 2px 12px rgba(0, 0, 0, 0.15);
}
.bn-hs-dot-el.is-selected .bn-hs-label {
    border-color: var(--color-primary);
    box-shadow:
        0 0 12px rgba(14, 139, 139, 0.25),
        0 2px 12px rgba(0, 0, 0, 0.15);
}

/* logo-hs variant — replace the text label with the Pearl Rivera
   logo image. Position mirrors the text label (sits at
   --bn-hs-line-h above the dot, centered) so the line + dot stay
   in the same place; only the label content swaps. */
.bn-hs-dot-el.logo-hs .bn-hs-label {
    background: transparent;
    padding: 0;
    border-radius: 0;
    box-shadow: none;
}
.bn-hs-dot-el.logo-hs .bn-hs-label .bn-hs-logo {
    display: block;
    width: 80px;
    height: auto;
    pointer-events: none;
    user-select: none;
    -webkit-user-drag: none;
}

/* ----- BLOCK kind ----- */

/* A block hotspot is a rectangular pill centred on the anchor px point
   and rotated by `rotation` degrees. JS sets the full transform via
   inline style so we reset the CSS transform here (inline wins). */
.bn-hs-block-el {
    position: absolute;
    transform: none; /* JS overrides with inline style.transform */
    pointer-events: none;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 6px 16px;
    background: var(--bn-hs-color, #ff4757);
    color: #fff;
    border-radius: 4px;
    font-family: var(--font-family);
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    white-space: nowrap;
    line-height: 1.2;
    box-shadow:
        0 2px 10px rgba(0, 0, 0, 0.2),
        0 0 0 2px rgba(255, 255, 255, 0.85) inset;
}

/* Direction indicator (used by the `huong-di-hs` hotspot class on the
   noi-khu floorplan, e.g. "Hướng đi Mỹ Đình"). Breakthrough layout:
   the whole thing is a solid pr-5 pill with a large triangular tail
   tip on the leading end. The label sits INSIDE the pill (pr-1 on
   pr-5 for strong contrast) — visually the tag and the arrow are
   one single shape pointing in the direction of travel.

   The tip's side encodes direction:
     - data-direction="rtl" → tip on the LEFT  (via ::before)
     - data-direction="ltr" → tip on the RIGHT (via ::after)

   The trailing end (away from the tip) keeps a full pill rounding,
   while the leading end (where the tip joins) is squared off so the
   triangle reads as a clear arrowhead instead of a rounded blob. */
.bn-hs-block-el.huong-di-hs {
    background: var(--pr-5);
    color: var(--pr-1);
    border: none;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
    padding: 6px 20px;
    font-size: 12px;
}

/* Trailing-end rounding only (the end OPPOSITE the tip).
   rtl (tip left)  → round the RIGHT corners.
   ltr (tip right) → round the LEFT corners.
   Matches the .bn-hs-label dot-label rounding (5px) so block and
   dot labels read as the same component family on the floorplan. */
.bn-hs-block-el.huong-di-hs[data-direction="rtl"] {
    border-radius: 0 5px 5px 0;
}
.bn-hs-block-el.huong-di-hs[data-direction="ltr"] {
    border-radius: 5px 0 0 5px;
}

/* External arrow tip — a large triangle that extends well past the
   pill. Sized to ~38px tall / 22px wide so it clearly reads as an
   arrowhead against the pr-5 body. The tip's base sits flush with
   the pill's straight (un-rounded) leading edge.

   No border on the triangle — the pill's own box-shadow is enough
   to lift the whole tag off the map. */
.bn-hs-block-el.huong-di-hs[data-direction="rtl"]::before,
.bn-hs-block-el.huong-di-hs[data-direction="ltr"]::after {
    content: "";
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 0;
    height: 0;
    pointer-events: none;
}

/* Tip on the LEFT (rtl: e.g. "Hướng đi Mỹ Đình") */
.bn-hs-block-el.huong-di-hs[data-direction="rtl"]::before {
    left: -20px;
    border-top: 19px solid transparent;
    border-bottom: 19px solid transparent;
    border-right: 22px solid var(--pr-5);
}

/* Tip on the RIGHT (ltr) */
.bn-hs-block-el.huong-di-hs[data-direction="ltr"]::after {
    right: -20px;
    border-top: 19px solid transparent;
    border-bottom: 19px solid transparent;
    border-left: 22px solid var(--pr-5);
}

/* Road hotspot — modern 2-tone gradient using the project palette:
   pr-3 (teal #0e8b8b) → pr-4 (deep teal #1d6e72) at a 135° angle so the
   lighter tone sits at the top-left and the darker tone fades to the
   bottom-right. Text in pr-0 (warm white #fcf9f6) reads well on the
   teal background. Compact sizing overrides the base block
   (6px 16px / 15px / r4) so road labels don't dominate the map. */
/* Road hotspot block label — roughly 1.5× the dot hotspot label
   width (padding 5×15 vs label's 4×10) with font-size 2px larger
   (16px vs label's 14px) so road labels read as the primary tier
   above secondary-hs. */
.bn-hs-block-el.road-hs {
    background: linear-gradient(135deg, var(--pr-3) 0%, var(--pr-4) 100%);
    color: var(--pr-0);
    border: none;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
    padding: 5px 15px;
    font-size: 16px;
    border-radius: 5px;
    letter-spacing: 0.65px;
}

/* Secondary hotspot — low-emphasis block label matching the dot
   hotspot label size (padding/font/radius) so the two read as the
   same tier. Cream/brown pair (pr-5 background, pr-1 text) keeps it
   visually below the primary teal road labels. */
.bn-hs-block-el.secondary-hs {
    background: var(--pr-2);
    color: var(--pr-5);
    border: none;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
    padding: 4px 10px;
    font-size: 14px;
    border-radius: 5px;
    letter-spacing: 0.65px;
}

.noi-khu-svg-overlay .nk-path-line {
    cursor: crosshair;
    transition: filter 0.15s;
}
.noi-khu-svg-overlay .nk-path-line.is-selected {
    filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.9));
}
.noi-khu-svg-overlay .nk-handle {
    cursor: move;
}
.noi-khu-svg-overlay .nk-ctrl-pt {
    cursor: pointer;
    fill: rgba(255, 255, 255, 0.7);
    stroke: #333;
    stroke-width: 1.5;
}
.noi-khu-svg-overlay .nk-ctrl-pt:hover {
    fill: #fff;
    stroke: #000;
}
.noi-khu-svg-overlay .nk-path-hitarea {
    fill: none;
    stroke: transparent;
    stroke-width: 12;
    cursor: pointer;
}
.noi-khu-svg-overlay .nk-drag-pt {
    cursor: move;
}

/* Admin Toggle Button */
.nk-admin-toggle[hidden] {
    display: none;
}
.nk-admin-toggle {
    position: absolute;
    top: 12px;
    right: 22px;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 10px;
    color: rgba(255, 255, 255, 0.8);
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition:
        background 0.18s,
        color 0.18s,
        transform 0.12s;
}
.nk-admin-toggle:hover {
    background: rgba(0, 0, 0, 0.75);
    color: #fff;
    transform: scale(1.03);
}
.nk-admin-toggle:active {
    transform: scale(0.97);
}
.nk-admin-toggle.is-active {
    background: rgba(255, 255, 255, 0.15);
    border-color: rgba(255, 255, 255, 0.3);
    color: #fff;
}

/* Admin Panel */
.nk-admin-panel[hidden] {
    display: none;
}
.nk-admin-panel {
    position: absolute;
    top: 58px;
    right: 22px;
    z-index: 15;
    width: 380px;
    max-height: calc(100vh - 240px);
    background: rgba(14, 16, 22, 0.88);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 14px;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.15) transparent;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
    display: flex;
    flex-direction: column;
}

.nk-admin-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 12px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    background: rgba(255, 255, 255, 0.03);
}

.nk-admin-title {
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.9);
    letter-spacing: 0.3px;
}

.nk-admin-header-actions {
    display: flex;
    align-items: center;
    gap: 4px;
}

.nk-admin-btn {
    padding: 5px 12px;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 7px;
    color: rgba(255, 255, 255, 0.75);
    font-family: var(--font-body);
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition:
        background 0.15s,
        color 0.15s;
}
.nk-admin-btn:hover {
    background: rgba(255, 255, 255, 0.15);
    color: #fff;
}
.nk-admin-btn:active {
    transform: scale(0.96);
}
.nk-admin-btn--sm {
    padding: 4px 10px;
    font-size: 11px;
}
.nk-admin-btn--danger:hover {
    background: rgba(220, 50, 50, 0.25);
    border-color: rgba(220, 50, 50, 0.4);
    color: #ff8080;
}
.nk-admin-btn--ghost {
    background: transparent;
    border-color: rgba(255, 255, 255, 0.15);
    color: rgba(255, 255, 255, 0.4);
}
.nk-admin-btn--ghost:hover {
    background: rgba(255, 255, 255, 0.08);
    border-color: rgba(255, 255, 255, 0.3);
    color: rgba(255, 255, 255, 0.8);
}
.nk-admin-btn--icon {
    width: 28px;
    height: 28px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border-color: transparent;
    font-size: 13px;
    color: rgba(255, 255, 255, 0.4);
}
.nk-admin-btn--icon:hover {
    background: rgba(255, 255, 255, 0.08);
    border-color: rgba(255, 255, 255, 0.1);
    color: rgba(255, 255, 255, 0.8);
}

.nk-admin-toolbar {
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Tools row */
.nk-admin-tools {
    display: flex;
    gap: 4px;
}

.nk-tool-btn {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    padding: 8px 4px;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 9px;
    color: rgba(255, 255, 255, 0.5);
    cursor: pointer;
    transition:
        background 0.15s,
        color 0.15s,
        border-color 0.15s;
}
.nk-tool-btn svg {
    flex-shrink: 0;
}
.nk-tool-btn span {
    font-family: var(--font-body);
    font-size: 10px;
    font-weight: 500;
}
.nk-tool-btn:hover {
    background: rgba(255, 255, 255, 0.1);
    color: rgba(255, 255, 255, 0.85);
    border-color: rgba(255, 255, 255, 0.15);
}
.nk-tool-btn.active {
    background: rgba(255, 255, 255, 0.15);
    border-color: rgba(255, 255, 255, 0.3);
    color: #fff;
}

/* Props row */
.nk-admin-props {
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.nk-prop-group {
    display: flex;
    align-items: center;
    gap: 8px;
}

.nk-prop-label {
    font-family: var(--font-body);
    font-size: 10px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.4);
    text-transform: uppercase;
    letter-spacing: 0.8px;
    min-width: 38px;
}

/* Color swatches */
.nk-color-row {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.nk-color-swatch {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 2px solid rgba(255, 255, 255, 0.15);
    cursor: pointer;
    transition:
        transform 0.12s,
        border-color 0.12s,
        box-shadow 0.12s;
}
.nk-color-swatch:hover {
    transform: scale(1.18);
    border-color: rgba(255, 255, 255, 0.5);
}
.nk-color-swatch.active {
    border-color: #fff;
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3);
    transform: scale(1.12);
}

/* Stroke buttons */
.nk-stroke-row {
    display: flex;
    gap: 3px;
}
.nk-stroke-btn {
    width: 30px;
    height: 26px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 6px;
    color: rgba(255, 255, 255, 0.6);
    font-family: var(--font-body);
    font-size: 10px;
    font-weight: 600;
    cursor: pointer;
    transition:
        background 0.15s,
        color 0.15s,
        border-color 0.15s;
}
.nk-stroke-btn:hover {
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
}
.nk-stroke-btn.active {
    background: rgba(255, 255, 255, 0.15);
    border-color: rgba(255, 255, 255, 0.35);
    color: #fff;
}

/* Effect buttons */
.nk-effect-row {
    display: flex;
    gap: 3px;
}
.nk-effect-btn {
    height: 26px;
    padding: 0 8px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 6px;
    color: rgba(255, 255, 255, 0.6);
    font-family: var(--font-body);
    font-size: 10px;
    font-weight: 600;
    cursor: pointer;
    transition:
        background 0.15s,
        color 0.15s,
        border-color 0.15s;
}
.nk-effect-btn:hover {
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
}
.nk-effect-btn.active {
    background: rgba(255, 255, 255, 0.15);
    border-color: rgba(255, 255, 255, 0.35);
    color: #fff;
}

/* Footer — road list + undo */
.nk-admin-footer {
    display: flex;
    flex-direction: column;
    min-height: 0;
    gap: 6px;
}

.nk-road-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
}

.nk-road-tip {
    flex: 1;
    font-family: var(--font-body);
    font-size: 10px;
    color: rgba(255, 255, 255, 0.35);
    text-align: right;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.nk-road-list {
    display: flex;
    flex-direction: column;
    gap: 5px;
    max-height: 140px;
    min-height: 0;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.15) transparent;
}

.nk-road-item {
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.07);
    border-radius: 7px;
    overflow: hidden;
    cursor: pointer;
    transition:
        background 0.12s,
        border-color 0.12s;
}
.nk-road-item:hover {
    background: rgba(255, 255, 255, 0.07);
    border-color: rgba(255, 255, 255, 0.12);
}
.nk-road-item.is-current {
    border-color: rgba(255, 255, 255, 0.25);
    background: rgba(255, 255, 255, 0.07);
}
.nk-road-item.is-selected .nk-road-name {
    color: #fff;
}

.nk-road-head {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 5px 8px;
}

.nk-road-vis {
    background: none;
    border: none;
    color: rgba(255, 255, 255, 0.5);
    cursor: pointer;
    padding: 1px;
    display: flex;
    align-items: center;
    transition: color 0.12s;
    flex-shrink: 0;
}
.nk-road-vis:hover {
    color: #fff;
}
.nk-road-vis.is-hidden {
    color: rgba(255, 255, 255, 0.2);
}

.nk-road-color-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex-shrink: 0;
}

.nk-road-name {
    flex: 1;
    font-family: var(--font-body);
    font-size: 11px;
    font-weight: 500;
    color: rgba(255, 255, 255, 0.75);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.nk-road-name-input {
    flex: 1;
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 4px;
    color: #fff;
    font-family: var(--font-body);
    font-size: 11px;
    padding: 1px 5px;
    outline: none;
}

.nk-road-del {
    background: none;
    border: none;
    color: rgba(255, 255, 255, 0.3);
    font-size: 12px;
    cursor: pointer;
    padding: 1px 3px;
    line-height: 1;
    transition: color 0.12s;
    flex-shrink: 0;
}
.nk-road-del:hover {
    color: #ff6060;
}

.nk-road-paths {
    display: flex;
    flex-wrap: wrap;
    gap: 3px;
    padding: 0 8px 6px 26px;
}

.nk-path-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 7px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 5px;
    font-family: var(--font-body);
    font-size: 10px;
    color: rgba(255, 255, 255, 0.55);
    cursor: pointer;
    transition:
        background 0.12s,
        border-color 0.12s;
    user-select: none;
}
.nk-path-badge:hover {
    background: rgba(255, 255, 255, 0.12);
    border-color: rgba(255, 255, 255, 0.18);
}
.nk-path-badge.is-selected {
    background: rgba(255, 255, 255, 0.16);
    border-color: rgba(255, 255, 255, 0.32);
    color: #fff;
}
.nk-path-badge .nk-badge-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex-shrink: 0;
}

.nk-footer-actions {
    display: flex;
    gap: 4px;
    flex-shrink: 0;
    justify-content: flex-end;
}

/* SVG path effects via filter definitions */
.nk-svg-filters {
    position: absolute;
    width: 0;
    height: 0;
    overflow: hidden;
}

/* Hotspot overlay — JS syncs its bounds to image's rendered rect */
.nk-hotspot-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 6;
}

/* Dot-el: anchor at % within overlay (overlay has same transform as image).
   Inverse-scale the whole container so dot/label/line stay constant pixel
   size at any zoom. Logo image uses image-rendering hint to stay sharp. */
.nk-hotspot-dot-el {
    position: absolute;
    pointer-events: all;
    cursor: pointer;
    transform: scale(var(--inv-scale, 1));
    transform-origin: 0 0;
}

/* Admin: visible 20px anchor dot (dot-el itself IS the dot) */
body:not(.nk-viewer-mode) .nk-hotspot-dot-el {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-color: var(--pr-3);
    border: 2px solid #fff;
    box-shadow: 0 0 0 0 rgba(14, 139, 139, 0.4);
    animation: hotspotPulseAdmin 1.5s ease-in-out infinite;
    pointer-events: all;
    cursor: pointer;
}
@keyframes hotspotPulseAdmin {
    0% {
        box-shadow: 0 0 0 0 rgba(14, 139, 139, 0.5);
    }
    50% {
        box-shadow: 0 0 0 8px rgba(14, 139, 139, 0);
    }
    100% {
        box-shadow: 0 0 0 0 rgba(14, 139, 139, 0.5);
    }
}

/* Admin: always show label so user can see & drag hotspot */
body:not(.nk-viewer-mode) .nk-hotspot-label {
    display: block;
}

/* Viewer: show label with logo hotspot */
body.nk-viewer-mode .nk-hotspot-label {
    display: flex;
    justify-content: center;
    align-items: center;
}

/* 1. Label box — absolute at top, centered above the dot */
.nk-hotspot-label {
    position: absolute;
    bottom: 120px;
    z-index: 1;
    left: 50%;
    transform: translateX(-50%);
    padding: 5px 12px;
    background: linear-gradient(135deg, var(--pr-0) 0%, var(--pr-1) 30%, var(--pr-2) 50%, var(--pr-2) 70%, var(--pr-2) 100%);
    border: none;
    border-radius: 6px;
    color: var(--pr-4);
    font-family: var(--font-family);
    font-size: 17px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    white-space: nowrap;
    pointer-events: none;
    text-align: center;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
    margin-bottom: 4px;
}

/* 2. Vertical guide line — absolute below label */
.nk-hotspot-line {
    position: absolute;
    top: -120px;
    left: 50%;
    transform: translateX(-50%);
    width: 3px;
    height: 120px;
    background-color: var(--pr-3);
    opacity: 0.85;
    pointer-events: none;
    box-shadow: 0 0 6px rgba(14, 139, 139, 0.5);
}

/* 3. Hotspot dot — viewer mode only; admin mode uses dot-el as the dot itself */
.nk-hotspot-dot {
    display: none;
}

.nk-hotspot-dot-el.has-logo .nk-hotspot-label {
    width: 180px;
    background: linear-gradient(135deg, var(--pr-3) 0%, var(--pr-4) 100%);
    animation: logoLabelBlink 2s ease-in-out infinite;
}

@keyframes logoLabelBlink {
    0%, 100% {
        opacity: 1;
        transform: translateX(-50%);
    }
    50% {
        opacity: 0.95;
        transform: translateX(-50%);
    }
}

/* Logo hotspot in label (width 150px) */
body.nk-viewer-mode .nk-hotspot-label .nk-hotspot-logo {
    width: 150px;
    height: auto;
    object-fit: contain;
    image-rendering: -webkit-optimize-contrast;
    image-rendering: crisp-edges;
    -ms-interpolation-mode: nearest-neighbor;
    animation: logoBlink 2s ease-in-out infinite;
}

@keyframes logoBlink {
    0%, 100% {
        opacity: 1;
    }
    50% {
        opacity: 0.6;
    }
}

/* Viewer: dot at anchor point */
body.nk-viewer-mode .nk-hotspot-dot-el .nk-hotspot-dot {
    display: block;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 20px;
    height: 20px;
    background-color: var(--pr-3);
    border: 2px solid #fff;
    border-radius: 50%;
    box-shadow: 0 0 0 0 rgba(14, 139, 139, 0.4);
    animation: hotspotPulse 2s ease-in-out infinite;
    pointer-events: none;
}

@keyframes hotspotPulse {
    0% {
        box-shadow: 0 0 0 0 rgba(14, 139, 139, 0.4);
    }

    50% {
        box-shadow: 0 0 0 10px rgba(14, 139, 139, 0);
    }

    100% {
        box-shadow: 0 0 0 0 rgba(14, 139, 139, 0.4);
    }
}

/* Admin: selected state — primary border on label, highlight the dot-el (which IS the anchor) */
body:not(.nk-viewer-mode) .nk-hotspot-dot-el.is-selected {
    background-color: var(--color-primary);
    border-color: #fff;
    animation: hotspotPulseSelected 1.5s ease-in-out infinite;
}
.nk-hotspot-dot-el.is-selected .nk-hotspot-label {
    border-color: var(--color-primary);
    box-shadow:
        0 0 12px rgba(14, 139, 139, 0.25),
        0 2px 12px rgba(0, 0, 0, 0.15);
}

/* Viewer: selected dot */
body.nk-viewer-mode .nk-hotspot-dot-el.is-selected .nk-hotspot-dot {
    background-color: var(--color-primary);
    border-color: #fff;
}

@keyframes hotspotPulseSelected {
    0% {
        box-shadow: 0 0 0 0 rgba(14, 139, 139, 0.6);
    }
    50% {
        box-shadow: 0 0 0 14px rgba(14, 139, 139, 0);
    }
    100% {
        box-shadow: 0 0 0 0 rgba(14, 139, 139, 0.6);
    }
}

/* Admin: dragging state */
.nk-hotspot-dot-el.is-dragging {
    cursor: grabbing;
    z-index: 20;
}
.nk-hotspot-dot-el.is-dragging .nk-hotspot-label {
    border-color: var(--color-primary);
}

/* Admin: hide viewer-only class in non-viewer (admin mode) */
body:not(.nk-viewer-mode) .nk-hotspot-dot-el.is-viewer-only {
    display: none;
}

/* Hotspot list header */
.nk-hotspot-list-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 8px 2px;
    font-family: var(--font-body);
    font-size: 10px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.35);
    text-transform: uppercase;
    letter-spacing: 0.8px;
}

.nk-hotspot-item {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.07);
    border-radius: 7px;
    cursor: pointer;
    transition:
        background 0.12s,
        border-color 0.12s;
}
.nk-hotspot-item:hover {
    background: rgba(255, 255, 255, 0.07);
    border-color: rgba(255, 255, 255, 0.12);
}
.nk-hotspot-item.is-selected {
    border-color: rgba(255, 215, 0, 0.5);
    background: rgba(255, 215, 0, 0.08);
}

.nk-hotspot-pin {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #ffd700;
    flex-shrink: 0;
    box-shadow: 0 0 4px rgba(255, 215, 0, 0.6);
}

.nk-hotspot-name {
    flex: 1;
    font-family: var(--font-body);
    font-size: 11px;
    font-weight: 500;
    color: rgba(255, 255, 255, 0.75);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.nk-hotspot-name-input {
    flex: 1;
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 215, 0, 0.5);
    border-radius: 4px;
    color: #fff;
    font-family: var(--font-body);
    font-size: 11px;
    padding: 1px 5px;
    outline: none;
}

.nk-hotspot-del {
    background: none;
    border: none;
    color: rgba(255, 255, 255, 0.3);
    font-size: 12px;
    cursor: pointer;
    padding: 1px 3px;
    line-height: 1;
    transition: color 0.12s;
    flex-shrink: 0;
}
.nk-hotspot-del:hover {
    color: #ff6060;
}

/* ================================================================
   KRRPANO PAGE WRAPPER — for tien-ich-tour & san-pham-tour
   ================================================================ */
.krpano-wrap {
    position: fixed;
    inset: 0;
    z-index: 10;
    overflow: hidden;
    background: #060f14;
    pointer-events: none;
}

.krpano-wrap #krpanoPano,
.krpano-wrap #krpanoPano > div {
    width: 100% !important;
    height: 100% !important;
    pointer-events: auto;
}

/* Make krpano's internal layers sit below our fixed UI */
.krpano-wrap .krpano_object,
.krpano-wrap iframe {
    z-index: 1;
}

/* ================================================================
   KRrpano NAV — fixed top bar
   ================================================================ */
.krpano-nav {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 20;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    padding: 10px 20px;
    background: linear-gradient(
        to bottom,
        rgba(0, 0, 0, 0.55) 0%,
        transparent 100%
    );
    pointer-events: none;
}

.krpano-nav__left {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    pointer-events: auto;
}

.krpano-nav__scene-info {
    display: flex;
    align-items: center;
    gap: 12px;
}

.krpano-nav__scene-label {
    font-family: var(--font-family);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: rgba(255, 255, 255, 0.6);
}

.krpano-nav__scene-name {
    font-family: var(--font-family);
    font-size: 14px;
    font-weight: 400;
    color: var(--pr-1);
    letter-spacing: 0.02em;
}

.krpano-nav__divider {
    width: 1px;
    height: 16px;
    background: rgba(255, 255, 255, 0.3);
}

.krpano-nav__counter {
    font-family: var(--font-family);
    font-size: 12px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.7);
    letter-spacing: 0.05em;
}

/* Right controls */
.krpano-nav__controls {
    display: flex;
    align-items: center;
    gap: 8px;
    pointer-events: auto;
}

.krpano-nav__ctrl-btn {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.25);
    background: rgba(0, 0, 0, 0.35);
    color: rgba(255, 255, 255, 0.85);
    cursor: pointer;
    transition:
        background var(--transition-fast),
        border-color var(--transition-fast),
        color var(--transition-fast);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    /* Mobile: kill the ~300ms tap delay so taps dispatch `click` immediately.
       Without this, mobile Safari/Chrome hold the click for double-tap-to-zoom
       detection, making the top-bar buttons feel unresponsive. `manipulation`
       still allows the user to scroll the page (so the underlying krpano
       viewer isn't blocked) but skips the double-tap zoom heuristic. */
    touch-action: manipulation;
    -webkit-tap-highlight-color: rgba(255, 255, 255, 0.15);
}

.krpano-nav__ctrl-btn:hover {
    background: rgba(0, 0, 0, 0.6);
    border-color: rgba(255, 255, 255, 0.5);
    color: #fff;
}

.krpano-nav__ctrl-btn.is-active {
    background: rgba(14, 139, 139, 0.5);
    border-color: var(--pr-3);
    color: var(--pr-1);
}

/* Tooltip pill — matches the look of the viewer-toggle-fab tooltip,
   but trimmed for the smaller 40px circle buttons in the nav. */
.krpano-nav__ctrl-btn .krpano-ctrl-tooltip {
    position: absolute;
    top: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%) translateY(-4px);
    white-space: nowrap;
    padding: 6px 10px;
    border-radius: 8px;
    background: rgba(0, 0, 0, 0.72);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    color: rgba(255, 255, 255, 0.92);
    font-size: 12px;
    font-weight: 500;
    line-height: 1;
    letter-spacing: 0.01em;
    pointer-events: none;
    opacity: 0;
    transition:
        opacity 0.18s ease,
        transform 0.18s ease;
    z-index: 4;
}

.krpano-nav__ctrl-btn .krpano-ctrl-tooltip::after {
    content: "";
    position: absolute;
    top: -4px;
    left: 50%;
    transform: translateX(-50%);
    border: 4px solid transparent;
    border-bottom-color: rgba(0, 0, 0, 0.72);
}

.krpano-nav__ctrl-btn:hover .krpano-ctrl-tooltip,
.krpano-nav__ctrl-btn:focus-visible .krpano-ctrl-tooltip {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* ================================================================
   KRrpano NAV BACK LINK — "Trở về Tiện ích", shown inside nav bar
   only when the user navigated from tien-ich.html dropdown.
   ================================================================ */
.krpano-nav-back {
    display: none;
    align-items: center;
    gap: 6px;
    padding: 6px 14px 6px 10px;
    background: rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 100px;
    color: rgba(255, 255, 255, 0.9);
    font-family: var(--font-family);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.02em;
    text-decoration: none;
    cursor: pointer;
    transition:
        background 0.2s ease,
        color 0.2s ease,
        border-color 0.2s ease;
    /* Mobile: tap should fire `click` immediately (see .krpano-nav__ctrl-btn). */
    touch-action: manipulation;
    -webkit-tap-highlight-color: rgba(255, 255, 255, 0.15);
}

.krpano-nav-back.is-visible {
    display: flex;
}

.krpano-nav-back:hover {
    background: rgba(0, 0, 0, 0.7);
    color: #fff;
    border-color: rgba(255, 255, 255, 0.4);
}

.krpano-nav-back:active {
    opacity: 0.8;
}

.krpano-nav-back svg {
    flex-shrink: 0;
    transition: transform 0.18s ease;
}

.krpano-nav-back:hover svg {
    transform: translateX(-2px);
}

/* ================================================================
   Fullscreen overrides — when the document enters fullscreen the
   page chrome shifts up so the panorama is unobstructed:
   - thumb strip drops to just above the bottom edge
   - toggle FAB anchors to the very bottom
   - scene heading lifts above the strip
   ================================================================ */
:fullscreen .viewer-nav-strip,
:-webkit-full-screen .viewer-nav-strip {
    bottom: 40px;
}

:fullscreen .viewer-toggle-fab,
:-webkit-full-screen .viewer-toggle-fab {
    bottom: 8px;
}

:fullscreen .krpano-scene-heading,
:-webkit-full-screen .krpano-scene-heading {
    bottom: 150px;
}

/* ================================================================
   KRrpano SCENE HEADING — bottom-left overlay
   ================================================================ */
.krpano-scene-heading {
    position: fixed;
    bottom: 285px;
    left: 32px;
    z-index: 20;
    display: flex;
    align-items: flex-end;
    gap: 16px;
    pointer-events: none;
    animation: krpanoHeadingFadeIn 0.5s ease forwards;
}

@keyframes krpanoHeadingFadeIn {
    from {
        opacity: 0;
        transform: translateY(12px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.krpano-scene-heading__num {
    font-family: var(--font-family-domaine);
    font-size: 72px;
    font-weight: 400;
    line-height: 1;
    color: var(--pr-1);
    opacity: 0.15;
    user-select: none;
}

.krpano-scene-heading__text {
    padding-bottom: 4px;
}

.krpano-scene-heading__name {
    font-family: var(--font-family-domaine);
    font-size: 28px;
    font-weight: 400;
    line-height: 1.1;
    color: var(--pr-1);
    margin: 0;
    letter-spacing: 0.02em;
}

.krpano-scene-heading__tag {
    font-family: var(--font-family);
    font-size: 12px;
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: rgba(255, 255, 255, 0.5);
    margin: 4px 0 0;
}

/* Hide the bottom-left scene heading on medium and small screens —
   the floating UI (top bar, FAB, thumb strip) carries the scene name
   there, and the 72px numeral collides with the FAB. */
@media (max-width: 1024px) {
    .krpano-scene-heading {
        display: none !important;
    }
}


/* ================================================================
   MOBILE MENU ADJUSTMENT when in krpano mode
   ================================================================ */
body[data-page="tienichtour"] .menu,
body[data-page="sanphamtour"] .menu {
    /* krpano pages need a taller bottom bar clearance */
}

body[data-page="tienichtour"] .menu__bottom,
body[data-page="sanphamtour"] .menu__bottom {
    /* Keep the pill nav visible at the bottom */
}

/* ================================================================
   KRrpano VIGNETTE & GRADIENT OVERLAY
   ================================================================ */
.krpano-vignette {
    position: fixed;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background: radial-gradient(
        ellipse 100% 100% at 50% 50%,
        transparent 60%,
        rgba(0, 0, 0, 0.25) 100%
    );
}

/* ================================================================
   KRrpano KRpano skin override — hide default bottom bar on our pages
   ================================================================ */
body[data-page="tienichtour"] #pano div[style*="bottom"],
body[data-page="sanphamtour"] #pano div[style*="bottom"] {
    bottom: 0 !important;
}

/* Directly hide krpano skin layer elements */
body[data-page="tienichtour"] #krpanoPano layer[name="skin_layer"],
body[data-page="sanphamtour"] #krpanoPano layer[name="skin_layer"],
body[data-page="tienichtour"] #krpanoPano layer[name="skin_control_bar"],
body[data-page="sanphamtour"] #krpanoPano layer[name="skin_control_bar"],
body[data-page="tienichtour"] #krpanoPano layer[name="skin_btn_prev"],
body[data-page="sanphamtour"] #krpanoPano layer[name="skin_btn_prev"],
body[data-page="tienichtour"] #krpanoPano layer[name="skin_btn_next"],
body[data-page="sanphamtour"] #krpanoPano layer[name="skin_btn_next"],
body[data-page="tienichtour"] #krpanoPano layer[name="skin_btn_thumbs"],
body[data-page="sanphamtour"] #krpanoPano layer[name="skin_btn_thumbs"],
body[data-page="tienichtour"] #krpanoPano layer[name="skin_btn_show"],
body[data-page="sanphamtour"] #krpanoPano layer[name="skin_btn_show"] {
    visible = false !important;
}

/* Also hide via krpano JS once ready */
body[data-page="tienichtour"] .krpano-wrap,
body[data-page="sanphamtour"] .krpano-wrap {
    --krpano-skin-opacity: 0 !important;
}

/* ================================================================
   Viewer Nav Strip — collapsible scene navigator
   Aligned with Pearl Rivera brand language:
   - Translucent dark glass panel + soft blur (matches .prl-zoom-controls)
   - Brand teal `--pr-3` (#0e8b8b) for active scene accent
   - Brand cream `--pr-1` (#fff5e3) for active scene name
   - Domaine serif numerals for scene counter (matches krpano-scene-heading)
   - Bigger, more readable thumbnails with proper breathing room
   - Chevron FAB sits flush above the panel as a clean handle
   ================================================================ */

/* ------------------------------------------------------------------
   Viewer nav strip + floating toggle button

   - The strip stays at a fixed `bottom` whether expanded or collapsed,
     so it never collides with the bottom menu (which is 138px tall
     and sits above z-index 50).
   - The toggle is a separate FAB (`viewer-toggle-fab`) that floats
     above the strip's top edge. It is icon-only with no border or
     background, so it reads as a "handle" rather than a button.
   - When collapsed the strip shrinks to the FAB's width; when
     expanded it stretches to a full panel.
   ------------------------------------------------------------------ */
.viewer-nav-strip {
    position: fixed;
    bottom: 178px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 100;
    /* Collapsed: hidden, only the floating toggle button is visible. */
    width: 0;
    height: 0;
    padding: 0;
    border: none;
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    overflow: hidden;
    pointer-events: none;
    transition:
        width 0.45s cubic-bezier(0.34, 1.2, 0.64, 1),
        height 0.4s cubic-bezier(0.34, 1.2, 0.64, 1),
        padding 0.4s ease,
        border-color 0.35s ease,
        background 0.35s ease,
        opacity 0.3s ease;
    opacity: 0;
}

/* Expanded: full glass panel — same translucent surface as
   `.prl-zoom-controls` but wider so 5–6 thumbnails fit
   comfortably without crowding the arrow buttons. */
.viewer-nav-strip.is-expanded {
    width: auto;
    max-width: min(820px, calc(100vw - 32px));
    height: auto;
    padding: 0;
    background: rgba(8, 22, 26, 0.42);
    backdrop-filter: blur(20px) saturate(140%);
    -webkit-backdrop-filter: blur(20px) saturate(140%);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 18px;
    box-shadow:
        0 1px 0 rgba(255, 255, 255, 0.06) inset,
        0 12px 32px rgba(0, 0, 0, 0.35);
    overflow: visible;
    pointer-events: auto;
    opacity: 1;
}

/* Body — hidden in compact mode, fades in when expanded.
   Generous padding so the strip feels substantial and aligned with
   the brand's pill aesthetic (similar to .menu-pill vertical rhythm). */
.viewer-nav-strip__body {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0;
    opacity: 0;
    transform: translateY(-8px) scale(0.96);
    transform-origin: top center;
    max-height: 0;
    overflow: hidden;
    transition:
        opacity 0.28s ease,
        transform 0.32s cubic-bezier(0.34, 1.2, 0.64, 1),
        max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1),
        padding 0.3s ease;
    pointer-events: none;
}

.viewer-nav-strip.is-expanded .viewer-nav-strip__body {
    opacity: 1;
    transform: translateY(0) scale(1);
    max-height: 360px;
    pointer-events: auto;
    padding: 12px 14px;
}

/* Thin teal accent line at the top of the panel — visually ties the
   strip to the brand teal pill row below and signals "selected scene
   rail" without screaming. */
.viewer-nav-strip.is-expanded::before {
    content: "";
    position: absolute;
    top: -1px;
    left: 50%;
    transform: translateX(-50%);
    width: 56px;
    height: 2px;
    border-radius: 0 0 2px 2px;
    background: linear-gradient(
        90deg,
        transparent 0%,
        rgba(14, 139, 139, 0.65) 50%,
        transparent 100%
    );
    pointer-events: none;
}

/* Floating toggle (FAB) — bare icon button that toggles the strip.
   No border, no background, no backdrop — just the icon itself.
   Sits flush above the panel as a clean handle. */
.viewer-toggle-fab {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    bottom: 153px;
    z-index: 101;
    display: flex;
    align-items: center;
    justify-content: center;
    width: auto;
    height: auto;
    padding: 6px 14px;
    border: none;
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    color: rgba(255, 245, 227, 0.78);
    cursor: pointer;
    border-radius: 100px;
    transition:
        color 0.2s ease,
        transform 0.2s ease,
        background 0.25s ease;
    outline: none;
    -webkit-tap-highlight-color: transparent;
}

.viewer-toggle-fab:hover {
    color: var(--pr-1, #fff5e3);
    background: rgba(255, 255, 255, 0.06);
}

.viewer-toggle-fab:active {
    transform: translateX(-50%) scale(0.94);
}

.viewer-toggle-fab:focus-visible {
    box-shadow: 0 0 0 2px rgba(14, 139, 139, 0.45);
}

/* Chevron: points UP (▴) when collapsed, rotates 180° to point DOWN (▾)
   when the strip is expanded. Slightly thicker stroke for legibility on
   busy panoramas. */
.viewer-toggle-fab .toggle-chevron {
    display: block;
    transition: transform 0.4s cubic-bezier(0.34, 1.3, 0.64, 1);
    transform: rotate(0deg);
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.55));
}

.viewer-toggle-fab.is-expanded .toggle-chevron {
    transform: rotate(180deg);
}

/* Tooltip — small dark glass pill above the toggle icon. Visibility is
   JS-driven (`.is-visible`) so mobile taps can dismiss it cleanly and
   hover-only devices keep the original hover behaviour (see
   `viewer-nav-strip.js`). */
.viewer-toggle-fab__tooltip {
    position: absolute;
    bottom: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    white-space: nowrap;
    max-width: min(220px, calc(100vw - 32px));
    padding: 6px 10px;
    border-radius: 8px;
    background: rgba(0, 0, 0, 0.78);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    color: rgba(255, 255, 255, 0.92);
    font-family: var(--font-family);
    font-size: 12px;
    font-weight: 500;
    line-height: 1;
    letter-spacing: 0.01em;
    pointer-events: none;
    opacity: 0;
    transition:
        opacity 0.18s ease,
        transform 0.18s ease;
}

/* Hover-preview on devices with a real pointer. JS will toggle
   `.is-visible` for touch/keyboard interactions. */
@media (hover: hover) and (pointer: fine) {
    .viewer-toggle-fab:hover .viewer-toggle-fab__tooltip {
        opacity: 1;
        transform: translateX(-50%) translateY(0);
    }
}

.viewer-toggle-fab__tooltip.is-visible {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* Small arrow pointing down at the icon */
.viewer-toggle-fab__tooltip::after {
    content: "";
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 4px solid transparent;
    border-top-color: rgba(0, 0, 0, 0.78);
}

/* Nav arrow buttons — circle buttons matching `.prl-zoom-btn`
   proportions. Teal accent on hover matches the rest of the krpano UI. */
.nav-arrow-btn {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.12);
    color: rgba(255, 255, 255, 0.75);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition:
        background 0.2s ease,
        border-color 0.2s ease,
        color 0.2s ease,
        transform 0.15s ease;
}

.nav-arrow-btn:hover {
    background: rgba(14, 139, 139, 0.32);
    border-color: rgba(14, 139, 139, 0.7);
    color: var(--pr-1, #fff5e3);
}

.nav-arrow-btn:active {
    transform: scale(0.92);
}

.nav-arrow-btn:disabled {
    opacity: 0.28;
    cursor: not-allowed;
}

.nav-arrow-btn:disabled:hover {
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.12);
    color: rgba(255, 255, 255, 0.4);
}

.nav-arrow-btn svg {
    display: block;
}

/* Thumbnail strip — wider than before, more breathing room,
   gentler edge fade so the active card isn't clipped by the mask. */
.thumb-strip {
    display: flex;
    align-items: center;
    gap: 8px;
    overflow-x: auto;
    scroll-behavior: smooth;
    max-width: 70vw;
    padding: 4px 6px;
    scrollbar-width: none;
    -webkit-mask-image: linear-gradient(
        90deg,
        transparent 0,
        #000 24px,
        #000 calc(100% - 24px),
        transparent 100%
    );
    mask-image: linear-gradient(
        90deg,
        transparent 0,
        #000 24px,
        #000 calc(100% - 24px),
        transparent 100%
    );
}

.thumb-strip::-webkit-scrollbar {
    display: none;
}

/* Individual thumb card — larger, brand-aligned card with teal accent
   on active state and a soft cream glow on the active scene name. */
.thumb-item {
    position: relative;
    width: 116px;
    height: 72px;
    border-radius: 10px;
    overflow: hidden;
    cursor: pointer;
    flex-shrink: 0;
    border: 1px solid rgba(255, 255, 255, 0.1);
    transition:
        background 0.2s ease,
        transform 0.22s cubic-bezier(0.34, 1.3, 0.64, 1),
        border-color 0.2s ease,
        box-shadow 0.22s ease;
    background: rgba(255, 255, 255, 0.05);
}

.thumb-item::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
    z-index: 1;
    opacity: 0;
    background: linear-gradient(180deg, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0.6) 100%);
}

/* Only darken the bottom when the card is in placeholder mode
   (no real preview image) so the "Đang tải…" label stays readable. */
.thumb-item.is-placeholder::after {
    opacity: 1;
}

/* Custom hover tooltip — single shared element appended to
   document.body and positioned via JS on mouseenter.
   `position: fixed` is anchored to the viewport (no ancestor has
   `transform` between body and this element), so left/top set from
   `getBoundingClientRect()` map directly to viewport coordinates.
   Same dark-glass look as the FAB tooltip so the brand surface
   stays consistent. */
.thumb-tooltip {
    position: fixed;
    /* JS sets left/top in pixels on hover */
    transform: translate(-50%, -100%);
    white-space: nowrap;
    max-width: 220px;
    padding: 6px 10px;
    border-radius: 6px;
    background: rgba(0, 0, 0, 0.82);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    color: rgba(255, 245, 227, 0.95);
    font-family: var(--font-family);
    font-size: 12px;
    font-weight: 500;
    line-height: 1.2;
    letter-spacing: 0.01em;
    text-overflow: ellipsis;
    overflow: hidden;
    pointer-events: none;
    opacity: 0;
    z-index: 1000;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
    transition:
        opacity 0.18s ease,
        transform 0.18s ease;
}

.thumb-tooltip.is-visible {
    opacity: 1;
}

/* Small arrow pointing down at the thumb card.
   `border-top-color` creates a ▼ shape (filled top edge, the triangle's
   tip points down) that hangs below the tooltip and points at the
   card underneath. */
.thumb-tooltip::after {
    content: "";
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 4px solid transparent;
    border-top-color: rgba(0, 0, 0, 0.82);
}

.thumb-item:hover {
    background: rgba(255, 255, 255, 0.1);
    border-color: rgba(255, 255, 255, 0.28);
    transform: translateY(-2px);
}

/* Active card — brand teal ring + soft glow + lifted. Cream name label
   becomes the brand cream so the selected scene reads instantly. */
.thumb-item.active {
    background: rgba(14, 139, 139, 0.18);
    border-color: var(--pr-3, #0e8b8b);
    box-shadow:
        0 0 0 1px rgba(14, 139, 139, 0.45),
        0 6px 18px rgba(14, 139, 139, 0.28);
    transform: translateY(-2px);
}

.thumb-item.active::after {
    opacity: 0;
}

.thumb-item img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.45s ease, filter 0.3s ease;
    opacity: 1;
    z-index: 2;
}

.thumb-item .placeholder-bg {
    z-index: 1;
}

.thumb-item:hover img {
    transform: scale(1.06);
}

.thumb-item.active img {
    transform: scale(1.04);
}

/* Fallback placeholder when preview image fails to load */
.thumb-item.is-placeholder {
    background: transparent;
}

.thumb-item.is-placeholder .placeholder-icon {
    width: 24px;
    height: 24px;
    opacity: 0.75;
    position: relative;
    z-index: 2;
    color: rgba(255, 255, 255, 0.7);
}

.thumb-item.is-placeholder .placeholder-bg {
    position: absolute;
    inset: 0;
    z-index: 1;
    border-radius: inherit;
    background:
        linear-gradient(135deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.02)),
        linear-gradient(135deg, rgba(14, 139, 139, 0.32), rgba(8, 36, 36, 0.6));
    transition: opacity 0.4s ease;
    animation: placeholder-shimmer 1.6s ease-in-out infinite;
}

@keyframes placeholder-shimmer {
    0%, 100% { opacity: 0.55; }
    50%      { opacity: 1; }
}

.thumb-item.is-placeholder .thumb-name,
.thumb-item.is-placeholder .thumb-num {
    z-index: 3;
}

/* Scene number badge — top-left, brand-cream Domaine numeral.
   Larger and more prominent so users can scan the order at a glance. */
.thumb-num {
    position: absolute;
    top: 6px;
    left: 7px;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 100px;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    font-family: var(--font-family-domaine, Georgia, serif);
    font-size: 11px;
    font-weight: 500;
    line-height: 1;
    color: rgba(255, 245, 227, 0.92);
    pointer-events: none;
    z-index: 4;
    letter-spacing: 0.04em;
    transition:
        background 0.2s ease,
        color 0.2s ease;
}

.thumb-item.active .thumb-num {
    background: var(--pr-3, #0e8b8b);
    color: var(--pr-1, #fff5e3);
}

/* Scene name — bottom-left, slightly larger, brand cream when active.
   Bottom-anchored so the card reads top-to-bottom: number → image → name. */
.thumb-name {
    position: absolute;
    bottom: 5px;
    left: 5px;
    right: 5px;
    width: calc(100% - 10px);
    padding: 3px 6px;
    border-radius: 5px;
    background: linear-gradient(90deg, rgba(0, 0, 0, 0.68), rgba(0, 0, 0, 0.32));
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    font-family: var(--font-family);
    font-size: 10px;
    font-weight: 500;
    color: rgba(255, 255, 255, 0.95);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.85);
    overflow: hidden;
    pointer-events: none;
    z-index: 4;
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    box-sizing: border-box;
    transition:
        background 0.2s ease,
        color 0.2s ease;
}

.thumb-item.active .thumb-name {
    background: linear-gradient(90deg, rgba(14, 139, 139, 0.85), rgba(14, 139, 139, 0.5));
    color: var(--pr-1, #fff5e3);
}

.thumb-name-inner {
    white-space: nowrap;
    flex-shrink: 0;
}

.thumb-name-inner:nth-child(2) {
    display: none;
}

.thumb-item:hover .thumb-name {
    /* keep overflow hidden so marquee stays inside the thumb */
}

.thumb-item:hover .thumb-name-inner:nth-child(2) {
    display: inline-block;
}

.thumb-item:hover .thumb-name-inner:nth-child(1) {
    padding-right: 16px;
}

.thumb-item:hover .thumb-name-inner {
    animation: marquee-scroll 6s linear infinite;
}

@keyframes marquee-scroll {
    0%   { transform: translateX(0); }
    100% { transform: translateX(-50%); }
}

/* Mobile adjustments */
@media (max-width: 768px) {
    .nk-admin-panel {
        left: 8px;
        right: 8px;
        top: 54px;
        width: auto;
        max-height: calc(100vh - 158px);
    }
    .nk-admin-toggle {
        font-size: 12px;
        padding: 6px 10px;
    }
    .menu__bg {
        height: 185px;
    }

}
/* Mobile adjustments */
@media (max-width: 768px) {
    .krpano-nav {
        padding: 8px 14px;
    }

    .krpano-nav__scene-label,
    .krpano-nav__divider,
    .krpano-nav__counter {
        display: none;
    }

    /* Vertically center the remaining scene name with the controls row.
       .krpano-nav__scene-info is the direct flex child of .krpano-nav
       (no .krpano-nav__left wrapper on the san_pham page), so we size
       the info row itself to match the 36px controls. */
    .krpano-nav__scene-info {
        align-items: center;
        min-height: 36px;
    }

    .krpano-nav__scene-name {
        font-size: 12px;
    }

    .krpano-nav__ctrl-btn {
        width: 36px;
        height: 36px;
    }

    .krpano-scene-heading {
        bottom: 200px;
        left: 16px;
        gap: 10px;
    }

    .krpano-scene-heading__num {
        font-size: 48px;
    }

    .krpano-scene-heading__name {
        font-size: 20px;
    }

    .viewer-nav-strip {
        /* Mobile: lift the strip + toggle above the taller menu bar
           (which grows to 205px on phone widths). The strip just
           becomes narrower so it fits phone widths. */
        bottom: 240px;
    }

    .viewer-nav-strip.is-expanded {
        width: auto;
        max-width: calc(100vw - 24px);
    }

    .viewer-toggle-fab {
        bottom: 215px;
    }

    .thumb-strip {
        max-width: 50vw;
        gap: 6px;
    }

    .thumb-item {
        width: 88px;
        height: 58px;
    }

    .nav-arrow-btn {
        width: 34px;
        height: 34px;
    }
}

/* Standalone tour wrapper — used by content/* pages that host a tour
   inside a full-bleed iframe (san-pham-tour, tien-ich-tour, ...).
   Lives here so the SPA can re-inject the markup without re-defining
   the styles every time. */
.tour-iframe-wrap {
    position: fixed;
    inset: 0;
    z-index: 10;
    background: #060f14;
}
.tour-iframe-wrap iframe {
    width: 100%;
    height: 100%;
    border: none;
    display: block;
}

/* Polygon blink animation for mat-bang highlights */
@keyframes nk-poly-blink-stroke {
    0%, 100% { stroke-opacity: 0.6; }
    50% { stroke-opacity: 0.1; }
}
@keyframes nk-poly-blink-fill {
    0%, 100% { fill-opacity: 0.25; }
    50% { fill-opacity: 0.04; }
}
@keyframes nk-poly-blink-glow {
    0%, 100% { filter: drop-shadow(0 0 4px currentColor); }
    50% { filter: drop-shadow(0 0 1px currentColor); }
}
.nk-polygon-group {
    animation: nk-poly-blink-glow 2.5s ease-in-out infinite;
    cursor: pointer;
}
.nk-polygon-group .nk-poly-fill {
    animation: nk-poly-blink-fill 2.5s ease-in-out infinite;
}
.nk-polygon-group .nk-poly-stroke {
    animation: nk-poly-blink-stroke 2.5s ease-in-out infinite;
}
.nk-polygon-group .nk-poly-runner {
    animation: nk-poly-run 6s linear infinite;
    opacity: 0;
}
@keyframes nk-poly-run {
    0% {
        stroke-dashoffset: var(--nk-poly-peri, 1000);
        opacity: 0;
        filter: drop-shadow(0 0 4px var(--nk-poly-color, #ff9800));
    }
    5% {
        opacity: 1;
    }
    80% {
        opacity: 1;
    }
    100% {
        stroke-dashoffset: 0;
        opacity: 0;
        filter: drop-shadow(0 0 12px var(--nk-poly-color, #ff9800)) brightness(1.5);
    }
}
.nk-polygon-group:hover .nk-poly-runner {
    animation-play-state: paused;
    opacity: 1;
}
.nk-polygon-group[data-id="6"] .nk-poly-runner {
    animation-duration: 10s;
    stroke-opacity: 0.4;
}
.nk-polygon-group[data-id="6"] .nk-poly-fill {
    animation: nk-poly-blink-fill-soft 4s ease-in-out infinite;
}
@keyframes nk-poly-blink-fill-soft {
    0%, 100% { fill-opacity: 0.12; }
    50% { fill-opacity: 0.03; }
}
.nk-polygon-group[data-id="7"] .nk-poly-runner {
    animation-duration: 8s;
}
.nk-polygon-group[data-id="7"] {
    animation-duration: 4s;
}
.nk-polygon-group[data-id="7"] .nk-poly-fill,
.nk-polygon-group[data-id="7"] .nk-poly-stroke {
    animation-duration: 4s;
}
.nk-polygon-tooltip {
    position: absolute;
    background: rgba(0, 0, 0, 0.85);
    color: #fff;
    padding: 8px 12px;
    border-radius: 6px;
    font-size: 13px;
    pointer-events: none;
    white-space: nowrap;
    z-index: 100;
    border: 1px solid rgba(255,255,255,0.2);
}
.nk-polygon-tooltip strong {
    display: block;
    margin-bottom: 4px;
    font-size: 14px;
}
.nk-polygon-tooltip span {
    opacity: 0.8;
}

/* ================================================================
   PAGE TRANSITION LOADER
   Overlay shown while SPA fetches & swaps #page-main content.
   Matches the 360° loading style (pearl logo + thin progress bar).
   ================================================================ */
.page-transition {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 22px;
    background: rgba(14, 139, 139, 0.85);
    /* backdrop-filter intentionally omitted: a blur over the full
       viewport forces the browser to re-composite every element below
       (including the fixed bottom menu) on every animation frame, and
       on iOS Safari the cost is severe — visible as the menu and the
       zoom-page image "flickering" during navigation. A solid tinted
       background gives the same visual cue without the cost. */
    opacity: 0;
    visibility: hidden;
    transition: opacity 200ms ease, visibility 200ms ease;
    pointer-events: none;
    /* Promote to its own GPU layer so the fade-in/fade-out doesn't
       retrigger paint on the rest of the page. */
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
}
.page-transition.is-active {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}
.page-transition__logo {
    width: 72px;
    height: auto;
    animation: logoPulse 2s ease-in-out infinite;
}
.page-transition__bar {
    width: 180px;
    height: 3px;
    background: rgba(252, 249, 246, 0.15);
    border-radius: 2px;
    overflow: hidden;
}
.page-transition__bar-fill {
    height: 100%;
    width: 0%;
    background: var(--pr-1);
    border-radius: 2px;
    transition: width 250ms ease;
}
.page-transition.is-active .page-transition__bar-fill {
    width: 85%;
}

/* =============================================================
   MOBILE OVERRIDES — BAN NGÀY VIEWER (ngoại khu page)
   ----------------------------------------------------------
   On mobile the screen is cramped, so:
   1. The dropdown opens DOWNWARD instead of upward (overrides the
      default mobile rule that pushes every menu-pill-dropdown above
      the pill). The pill is anchored at top:20px, so opening up
      would clip items above the viewport.
   2. The back button collapses to a circle icon + tooltip; height
      is preserved via padding: 9px 12px to match the dropdown pill
      so both are visually aligned on the same baseline.
   3. Dropdown menu width is reduced on mobile for tight screens.
   ============================================================= */
@media (max-width: 768px) {
    .ban-ngay-viewer-dropdown .menu-pill-dropdown__menu {
        top: calc(100% + 4px);
        bottom: auto;
        transform: translateX(-50%) translateY(0);
        width: 160px;
    }

    .ban-ngay-viewer-dropdown .menu-pill-dropdown > .menu-pill-dropdown__menu {
        transform: translateX(-50%) translateY(-4px);
    }

    .ban-ngay-viewer-dropdown .menu-pill-dropdown.is-open > .menu-pill-dropdown__menu,
    .ban-ngay-viewer-dropdown .menu-pill-dropdown:hover > .menu-pill-dropdown__menu,
    .ban-ngay-viewer-dropdown .menu-pill-dropdown > .menu-pill-dropdown__menu:hover {
        transform: translateX(-50%) translateY(4px);
    }

    /* Back button: equal square box around the icon so border-radius
       50% produces a true circle. Inline SVG width/height attrs would
       otherwise make the content box wider than tall. */
    .ban-ngay-back-btn {
        padding: 9px;
        gap: 0;
        border-radius: 50%;
        position: relative;
        align-items: center;
        justify-content: center;
    }

    .ban-ngay-back-btn > svg {
        width: 20px;
        height: 20px;
        display: block;
    }

    .ban-ngay-back-btn__label {
        display: none;
    }

    /* Tooltip: appears below the button, arrow pointing up */
    .ban-ngay-back-btn [data-tooltip] {
        position: relative;
    }

    .ban-ngay-back-btn [data-tooltip]::after {
        content: attr(data-tooltip);
        position: absolute;
        top: calc(100% + 10px);
        left: 50%;
        transform: translateX(-50%);
        background: var(--pr-5);
        color: var(--pr-0);
        font-family: var(--font-family);
        font-size: 12px;
        font-weight: 400;
        white-space: nowrap;
        padding: 5px 10px;
        border-radius: 6px;
        pointer-events: none;
        opacity: 0;
        transition: opacity var(--transition-fast);
        z-index: 300;
    }

    /* Downward-pointing caret below tooltip text */
    .ban-ngay-back-btn [data-tooltip]::before {
        content: "";
        position: absolute;
        top: calc(100% + 3px);
        left: 50%;
        transform: translateX(-50%);
        border: 5px solid transparent;
        border-top-color: var(--pr-5);
        border-bottom: none;
        pointer-events: none;
        opacity: 0;
        transition: opacity var(--transition-fast);
        z-index: 301;
    }

    .ban-ngay-back-btn:hover [data-tooltip]::after,
    .ban-ngay-back-btn:hover [data-tooltip]::before {
        opacity: 1;
    }
}