/* page-shell.css — the Norton Park page on top of the editor's multi-mood shell (V4XShell, root index.html
   of the export). Loaded AFTER site.css, so equal-specificity rules here win. Replaces inline.css of the
   23/09 build (retired/inline.css). The runtime chrome INSIDE the scene iframes (minimap, hotspot pins,
   plan tooltip) is skinned by site/viewer-skin.css, not here. Sections:
     1. layering          scene iframes (shell) < page UI < transition FX < intro gates
     2. intro reveal      of the scene iframe in front
     3. mood bar          N moods (NP_BOOT_CFG.moods; site.js sets --n)
     4. floors panel      on phones (#10, unchanged from the 23/09 build)
     5. device fixes      of the 24/09 device matrix: tour bar under ☰ on phones held upright, touch
                          targets, the Mặt cắt button remembering a floor across a mood switch
   Brand tokens (--edge, --glass, --map-w, --f-sub …) come from site.css :root. */

/* ---------- 1. layering ----------
   The shell's scene iframes (.v4xsh-frame, z 0–2) and its cover (#v4xsh-cover z 9, the veil of a switch
   to a scene that is still loading) sit UNDER the page. .stage (the page UI, z 20) lets clicks, drags
   and pinches through to the scene; only the real controls (.ui > *, the touch unit card with its button, an
   open popup) take them back. The shell's transition FX (#v4xsh-fx: seed, rings, flash) plays ABOVE the UI,
   like the page's own seed drop did; the intro gates (#introGate 200, #sceneBridge 205, #seedLoad 230) stay
   above everything.
   The DESKTOP unit card follows the cursor 22 px off and must not take the mouse (site.css): a quick move that
   lands on it froze the hover under the card (measured 26/09: 2 units per floor never reached by a 34 px
   pointer grid; the Lot B card is taller, 7 rows). Only the touch sheet (.touch, "Mở tour 360" button) does. */
.stage{z-index:20;pointer-events:none}
#unitCard.touch{pointer-events:auto}
body:not(.ui-off) #pop.open{pointer-events:auto}
#bg[hidden]{display:none}
#v4xsh-fx{z-index:80}
/* the viewer died (bridge › fallbackToStill): the still image of the page shows instead */
body.v4d-dead .v4xsh-frame,body.v4d-dead #v4xsh-cover,body.v4d-dead #v4xsh-fx{display:none!important}
/* the static mock's own masterplan panel — replaced by each scene's runtime minimap (viewer-skin.css) */
#blStack{display:none!important}
/* the shell paints #0b0d11 under the scenes; the page's dark matches the intro gate */
html,body{background:#07080b}

/* ---------- 2. intro reveal ----------
   The scene fades in from dark and settles 1.045 → 1 while the last video frame pushes out
   (site.css › v4dSceneIn). transform + opacity of the iframe only: compositor work. */
body.intro-reveal .v4xsh-frame.is-front{animation:v4dSceneIn 4s cubic-bezier(.45,.05,.2,1) both}
@media (prefers-reduced-motion:reduce){body.intro-reveal .v4xsh-frame.is-front{animation:v4dUiIn .4s linear both}}

/* ---------- 3. mood bar: N moods ----------
   site.css sized the bar for three moods (Sáng · Trưa · Chiều). The moods shown come from the export
   (a node without a source is hidden; Trưa had none until 02/10/2026), so the thumb is 1/n of the
   track and the bar keeps the same width per mood. */
#mood .thumb{width:calc((100% - 8px) / var(--n,3))}
@media (min-width:741px){
  #mood{width:calc(var(--mood-w) * (var(--n,3) + 1) / 4)}
}
@media (max-width:740px){
  /* phone upright: the bar stands vertical under the compass, 44 px per mood */
  #mood,#mood .seg{height:calc(8px + 44px * var(--n,3))}
  #mood .thumb{width:auto;height:calc((100% - 8px) / var(--n,3))}
}
body.mood-busy #mood .seg{cursor:progress}
/* Rest after a switch on a one-scene device (owner 13/10/2026; v4d-bridge.js › moodCoolStart, site.js › moodCoolNudge): the whole
   bar dims (owner chose B over "only the other moods dim") until the new scene has loaded; it takes no tap meanwhile */
#mood .seg{transition:opacity .25s}
body.mood-cool #mood .seg{cursor:progress;opacity:.45}
body.mood-cool #mood .hint{opacity:0!important}   /* "kéo ngang · click để chuyển mood" would be wrong meanwhile */

/* ---------- 9. thanh tour: chỉ bước tour (chủ dự án 02/10/2026) ----------
   Bỏ nhãn dưới thanh ("Tour tự động" / "Khu vực"); ô số luôn là bước tour X / Y (site.js › TOUR_AREA_MODE = false: không
   còn chế độ Khu, không còn cú cuộn số); tour dừng thì thanh rõ hẳn. Cảnh 3D dừng vì có lớp phủ — popup (bản đồ vị trí, tour
   gợi ý thiết kế, View 180°…), mặt cắt tầng (máy tính lẫn điện thoại), sân khấu căn — thì thanh tour cùng ♫ và ▶/⏸ ẩn
   hẳn, không nằm đè lên lớp phủ; popup cao sát mép trên như cũ (chủ dự án, tin nhắn thứ hai cùng ngày). */
#tour .cap{display:none}
#tour.paused{opacity:1}
body:is(.pop-open,.np-unit-open,.np-slice-desk,.np-slice-mobile) #tour,body:has(#pop.open) #tour,body:has(#floors.open) #tour{
  opacity:0!important;visibility:hidden;pointer-events:none!important;transition:opacity .18s,visibility 0s .18s}

/* ---------- 4. floors panel on phones (#10) ----------
   The static demo turned the 19-floor list into a 2-column grid up to 38 vh — plus legend and exit
   button it hid most of the floor plan on a phone. Now: one row "Chọn tầng · Thoát", a strip of floor
   chips that scrolls sideways (site.js keeps the selected chip centred), and the unit-type legend as
   one wrapping line. ≈130 px in portrait, ≈90 px in landscape. */
@media (max-width:740px), (max-height:520px) and (orientation:landscape){
  #floors{display:grid;grid-template-columns:1fr auto;grid-template-areas:"h4 exit" "list list" "ov ov";
    column-gap:8px;row-gap:6px;align-items:center;padding:8px 10px 10px;top:auto;width:auto}
  #floors h4{grid-area:h4;margin:0 2px}
  #floors .exit{grid-area:exit;margin:0;width:auto;padding:6px 12px;font-size:11px;min-height:34px}
  #floors .list{grid-area:list;display:flex;flex-direction:row-reverse;gap:6px;max-height:none;
    overflow-x:auto;overflow-y:hidden;padding:2px 0;scroll-snap-type:x proximity;overscroll-behavior-x:contain;
    -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 12px,#000 calc(100% - 12px),transparent 100%);
    mask-image:linear-gradient(90deg,transparent 0,#000 12px,#000 calc(100% - 12px),transparent 100%)}
  #floors.has-ov .list{max-height:none}
  #floors .list button{flex:none;min-width:58px;min-height:40px;padding:0 10px;text-align:center;
    scroll-snap-align:center;white-space:nowrap}
  #floors .ov{grid-area:ov;margin:0;padding-top:6px;display:flex;flex-wrap:wrap;align-items:center;gap:4px 10px}
  #floors .ov-head{width:auto;padding:4px 6px;min-height:34px}
  #floors .ov-key{display:flex;flex-wrap:wrap;gap:2px 8px;margin:0;flex:1 1 auto}
  #floors .ov-key div{padding:2px 4px}
  #floors .ov-key button{width:auto;margin:0;padding:2px 6px}   /* nút lọc loại căn (28/09/2026) trong dải một hàng */
  #floors .ov-key span{margin-left:4px}
}
@media (max-width:740px){
  #floors{left:var(--edge-l);right:var(--edge-r);bottom:calc(var(--edge-b) + 60px)}
}
@media (max-height:520px) and (orientation:landscape){
  #floors{left:var(--edge);right:calc(var(--edge) + var(--btn) + 12px);bottom:var(--edge);
    transform:translateY(8px);grid-template-columns:auto 1fr auto;grid-template-areas:"h4 list exit" "ov ov ov";
    column-gap:10px;row-gap:4px;padding:6px 10px}
  #floors.open{transform:none}
  #floors h4{white-space:nowrap}
  #floors .ov{padding-top:4px;border-top:0;flex-wrap:nowrap;overflow:hidden}
  #floors .ov-key{flex-wrap:nowrap;overflow:hidden;white-space:nowrap}
  /* the strip sits where the mood bar lives — step it aside while it is open (the runtime minimap of the
     scene steps aside through viewer-skin.css › html.np-floors-open) */
  body:has(#floors.open) #mood{opacity:0;pointer-events:none;transition:opacity .2s}
}

/* ---------- 5. device fixes (device matrix 24/09) ---------- */
/* #1 — phone held upright: the room between the minimap button and ☰ is only ~258 px (~212 px on a 344 px
   cover screen). Since 30/09/2026 the Tour | Khu switch is gone (the middle group of the bar changes role by
   itself, site.css › "nhóm giữa ‹ n / tổng ›"), so the bar is [▶][‹ n / tổng ›][x1] again, ~218 px (~206 px
   on the cover screen); only the music button floats above it (section 6). The bar is its containing block. */
@media (max-width:740px){
  #tour .bar{position:relative}
}
/* #4 — touch targets ≥ 44 px without changing the drawing: transparent hit areas around the small
   controls (the mood bar is 38 px in a low landscape window). */
#mood .seg::before{content:"";position:absolute;inset:-4px}
/* Mặt cắt remembers the floor being cut when the mood changed (owner's rule 24/09/2026: the cut never
   crosses by itself; the button opens that floor): a small bronze dot on the button until it is used. */
/* a child element (site.js adds <i class="np-armed">): the button's ::after is its tooltip and its ::before
   the touch hit area below */
.np-armed{display:none;position:absolute;top:6px;right:6px;width:8px;height:8px;border-radius:50%;z-index:1;
  background:#C39B77;box-shadow:0 0 0 2px rgba(31,34,25,.85),0 0 8px rgba(195,155,119,.8);pointer-events:none}
.is-armed > .np-armed{display:block}
.sh-it[data-act="floors"]{position:relative}
/* #4 on touch screens: the round buttons are 42 px (741–900 px wide) or 38 px (phone held landscape) —
   a transparent ring of 3 px brings the target to 44–48 px; neighbours stay apart (gap ≥ 6 px) */
@media (pointer:coarse){
  #rail .btn::before,#corner .btn::before,#menuFab::before{content:"";position:absolute;inset:-3px;border-radius:50%}
}
/* phone held landscape: 38 px buttons, 6 px apart — a 4 px ring (measured 42 → 44+ effective; the rounded
   hit region loses about a pixel per side) */
@media (pointer:coarse) and (max-height:540px){
  #rail .btn::before,#corner .btn::before{inset:-4px}
}

/* ---------- 6. nút nhạc nền trong thanh tour (chủ dự án 28/09/2026) ----------
   Ô cuối của thanh tour, sau vạch ngăn, cùng cỡ các nút tròn của thanh (--t-btn); đang phát = sóng nhạc + viền vàng, đã tắt =
   loa gạch chéo. Là một phần của thanh tour: mờ khi thanh nghỉ, ẩn khi popup mở / phím H / mặt cắt trên điện thoại (không có
   luật nào kéo nó lên trên). Dòng gợi ý mỗi lần vào (.np-bgm-hint) nằm trong #tour nên cũng ẩn / hiện theo thanh.
   Điện thoại, máy gập, iPad (chủ dự án 02/10/2026: "không thích icon BGM ở chính giữa và nằm ở một hàng riêng"): ♫ THAY CHỖ nút
   tốc độ x1 / x1.5 / x3 — nút tốc độ và vạch ngăn ẩn, ♫ là ô cuối của thanh. Máy tính giữ [x1] | [♫]. Trước 02/10 điện thoại dọc
   có ♫ nổi riêng phía trên thanh, canh giữa. */
#tour .bar .np-bgm-div{width:1px;height:22px;flex:none;margin:0 3px;background:rgba(255,255,255,.3)}
#tour .bar .np-bgm svg{width:calc(var(--t-ico) + 3px);height:calc(var(--t-ico) + 3px);
  filter:drop-shadow(0 1px 3px rgba(0,0,0,.8)) drop-shadow(0 0 6px rgba(0,0,0,.45))}
#tour .bar .np-bgm.on{box-shadow:inset 0 0 0 1.5px rgba(226,192,143,.95);background:rgba(255,255,255,.1)}
#tour .bar .np-bgm:not(.on) svg{opacity:.82}
#tour.np-bgm-hinting{opacity:1}
@media (max-width:740px), (pointer:coarse){
  #tour .bar .speed,#tour .bar .np-bgm-div{display:none}
}
#tour .np-bgm-hint{position:absolute;z-index:2;width:max-content;max-width:min(300px,80vw);padding:8px 11px;border-radius:10px;
  background:rgba(18,21,27,.9);color:#fef0e1;font:500 12.5px/1.45 var(--f-body,system-ui);text-align:left;letter-spacing:0;
  text-transform:none;box-shadow:0 6px 20px rgba(0,0,0,.35);pointer-events:none;animation:npBgmHint .25s ease-out}
#tour .np-bgm-hint b{color:#e2c08f;font-weight:700}
#tour .np-bgm-hint kbd{display:inline-block;min-width:16px;padding:0 4px;margin:0 2px;border-radius:4px;border:1px solid rgba(254,240,225,.45);
  font:600 11px/16px var(--f-body,system-ui);text-align:center}
#tour .np-bgm-hint::after{content:"";position:absolute;left:var(--ax,50%);width:10px;height:10px;margin-left:-5px;background:inherit;transform:rotate(45deg)}
#tour .np-bgm-hint.up::after{top:-5px}
#tour .np-bgm-hint.down::after{bottom:-5px}
@keyframes npBgmHint{from{opacity:0;transform:translateY(4px)}}
@media (prefers-reduced-motion:reduce){#tour .np-bgm-hint{animation:none}}

/* Phones: the open "Sơ đồ" sheet lies inside the viewer iframe, under the page's mood bar — the bar steps aside while the
   sheet is open (v4d-bridge.js › mmSyncMoodBar; VPS hot fix 04/10/2026 20:11, owner's Android photo) */
@media (max-width:740px),(max-height:540px) and (orientation:landscape){
  body.np-mm-open #mood{opacity:0;visibility:hidden;pointer-events:none;transition:opacity .18s,visibility 0s .18s}
}
/* A phone on its side: the sheet takes the left two thirds from the top, so the compass (top centre) lay over "Mở rộng" /
   "Thu gọn" and the logo over the sheet's title (measured 04/10/2026 at 844×390) — they step aside with the mood bar */
@media (max-height:540px) and (orientation:landscape){
  body.np-mm-open #compass,body.np-mm-open #logo{opacity:0;visibility:hidden;pointer-events:none;transition:opacity .18s,visibility 0s .18s}
}

/* One scene in memory — in-app browsers and phones (owner 08/10/2026, option C; boot.js › NP_BOOT.one, html.np-one): a mood switch removes the scene in front
   and loads the next one under the shell's cover (viz4d-editor/server.py › swapOne), 5–15 s on a phone. The cover then says
   "Đang chuyển cảnh…" over the progress of that load, in the look of the intro's loading block (site.css › .ig-load):
   pulsing dot, spaced capitals, a 2 px cream bar with its percentage. The page UI (z 20+) stays above it. */
html.np-one #v4xsh-cover{background:#07080b;color:#e6cba0;gap:16px}
html.np-one #v4xsh-cover .wt{font:600 11px/1.4 var(--f-sub,system-ui);letter-spacing:.24em;text-transform:uppercase;
  opacity:1;color:rgba(238,242,247,.85);text-shadow:0 1px 4px rgba(0,0,0,.7);white-space:nowrap}
html.np-one #v4xsh-cover .wt::before{content:'';display:inline-block;width:7px;height:7px;margin:0 10px 1px 0;border-radius:50%;
  vertical-align:middle;background:#e6cba0;box-shadow:0 0 10px rgba(230,203,160,.9);animation:igPulse 1.15s ease-in-out infinite}
html.np-one #v4xsh-cover .pg{width:min(300px,calc(100vw - 64px));gap:12px}
html.np-one #v4xsh-cover .pb{background:rgba(238,242,247,.22);box-shadow:0 1px 6px rgba(0,0,0,.35)}
html.np-one #v4xsh-cover .pb i{background:#e6cba0;box-shadow:0 0 8px rgba(230,203,160,.85)}
html.np-one #v4xsh-cover .pc{font:600 12px/1 var(--f-sub,system-ui);letter-spacing:.04em;opacity:1;color:#e6cba0;
  text-shadow:0 1px 4px rgba(0,0,0,.7)}
@media (prefers-reduced-motion:reduce){html.np-one #v4xsh-cover .wt::before{animation:none}}
/* the NEXT mood's own picture behind the text (v4d-bridge.js › oneCoverPicture, owner 08/10/2026 ~21:30): its 640×360 thumbnail,
   blurred, darkened and slightly enlarged (the blurred edge stays off screen), fading in once loaded — the wait reads as a passage
   into that mood's light. A layer under the text: transform / opacity only, the blur is drawn once. */
html.np-one #v4xsh-cover::before{content:'';position:absolute;inset:-48px;background:var(--np-one-bg,none) center/cover no-repeat;
  filter:blur(18px) saturate(1.08) brightness(.58);transform:scale(1.06);opacity:0;transition:opacity .7s ease;pointer-events:none}
html.np-one #v4xsh-cover.np-one-bg::before{opacity:1}
html.np-one #v4xsh-cover .wt,html.np-one #v4xsh-cover .pg{z-index:1}
/* One-scene switch: the page UI stays visible over the cover but takes no tap until the new mood is in (body.mood-busy, site.js
   runMood) — its scene is gone meanwhile (v4d-bridge.js › releaseFront), a tap would act on nothing (review 08/10/2026 evening) */
html.np-one body.mood-busy .ui *{pointer-events:none!important}
/* EVERY screen size (owner 08/10/2026 ~22:00, a Note 20 photo): the compass, logo, tour bar and mood bar step aside while the OPEN
   "Sơ đồ" lies under them (v4d-bridge.js › mmOverlap) — the map is inside the scene's iframe, no z-index can lift it over them;
   its fold / expand buttons stay reachable, everything comes back once it is folded */
body.np-mm-over-compass #compass,body.np-mm-over-logo #logo,body.np-mm-over-tour #tour,body.np-mm-over-mood #mood{
  opacity:0;visibility:hidden;pointer-events:none;transition:opacity .18s,visibility 0s .18s}
/* "Đang dựng mặt cắt…" (F, phones only — v4d-bridge.js › cutWait): covers the scene from the first tap on Mặt cắt until the floor
   plan is built and splats draw again (5–20 s on a phone link, the old step's picture + raw splats meanwhile). z 50: above the
   scene and the page UI (.stage 20), BELOW the phone's floor bar / exit button (slice-mobile.css 51–53) and #floors (64), so the
   floor list and × stay usable; below popups and the intro gates. */
#npCutWait{position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;background:#07080b;
  opacity:0;visibility:hidden;pointer-events:none;transition:opacity .45s ease,visibility 0s .45s}
#npCutWait.is-on{opacity:1;visibility:visible;transition:opacity .12s ease}
#npCutWait .wt{font:600 11px/1.4 var(--f-sub,system-ui);letter-spacing:.24em;text-transform:uppercase;color:rgba(238,242,247,.85);
  text-shadow:0 1px 4px rgba(0,0,0,.7);white-space:nowrap}
#npCutWait .wt::before{content:'';display:inline-block;width:7px;height:7px;margin:0 10px 1px 0;border-radius:50%;vertical-align:middle;
  background:#e6cba0;box-shadow:0 0 10px rgba(230,203,160,.9);animation:igPulse 1.15s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){#npCutWait .wt::before{animation:none}}
