/* Highway New Time · map3d.css · the home page's 3D map hero (DESIGN_SYSTEM.md 3.21). Loaded by index.html only, after hnt.css.
   Port of the approved prototype lab/3d-map/template.html. Every rule is scoped to #m3d (the stage) or #m3d-dock (the phone
   bar), plus the <html> state classes that map3d.js sets: ready, m3d-open, m3d-nogl, m3d-arriving, m3d-shot.
   Colours are the hnt.css tokens; the four lab-only tokens live on this scope. Map materials (fills, edges, shadows)
   are part of the 3D drawing, not interface colours. The owner-approved exceptions to DESIGN_SYSTEM sections 1 and 7
   (3D and parallax motion, solid brass buttons, text shadows over the map, the photo background with its slideshow,
   round tags) are listed in section 3.21.
   Sizes follow the lab in px so the hero matches the approved prototype at every width. */

#m3d,#m3d-dock{
  --sand-45:rgba(230,220,198,.45);
  --sand-60:rgba(230,220,198,.6);
  --brass-hi:#c19a52;
  --drawer:cubic-bezier(.32,.72,0,1);
  --sheet:min(440px,92vw);
  /* a tight dark halo for text that sits on the map or the photographs (WCAG: the halo is the text's background) */
  --halo:0 0 1px rgba(10,18,32,1),0 0 2px rgba(10,18,32,1),0 0 4px rgba(10,18,32,.95),0 1px 10px rgba(10,18,32,.9);
  --halo-l:0 0 2px rgba(10,18,32,1),0 0 4px rgba(10,18,32,1),0 0 8px rgba(10,18,32,.9),0 1px 18px rgba(10,18,32,.85);
}

/* ---------- stage: starts under the site header (72 px), fills the rest of the first screen ---------- */
#m3d{position:relative;isolation:isolate;overflow:hidden;padding:0;margin-block-end:calc(var(--section)/2);
  height:calc(100vh - 72px);height:calc(100svh - 72px);min-height:568px;max-height:1028px;
  background:radial-gradient(90% 75% at 50% 56%,#16273f 0%,var(--navy) 55%,#0b1524 100%)}
#m3d button{text-align:inherit}

/* ---------- background: the tag destinations' photos (map3d.js rotates them), under a navy scrim ----------
   Each slide drifts slowly (11 s, paused with the slideshow); a new one fades in over the last. The scrim keeps the
   headline (top band) and the tags (bottom band) readable and lets the photo show around the map. */
#m3d .bg{position:absolute;inset:0;z-index:0;overflow:hidden;pointer-events:none;background:var(--navy-2)}
#m3d .bg .sl{position:absolute;inset:0;width:100%;height:100%;max-width:none;object-fit:cover;opacity:0;transition:opacity 1.4s var(--ease);
  filter:saturate(1.06) contrast(1.03);animation:m3d-drift 11s linear both;will-change:opacity,transform}
/* grade: a touch more colour, never less (owner 2026-10-05, after the phone screenshot: "手机上的图片要更醒目") */
#m3d .bg .sl.on{opacity:1}
#m3d .bg.paused .sl{animation-play-state:paused}
#m3d .bg.still .sl{animation:none;transform:scale(1.04)}
@keyframes m3d-drift{from{transform:scale(1.03) translate3d(var(--kx0,0),var(--ky0,0),0)}to{transform:scale(1.11) translate3d(var(--kx1,0),var(--ky1,0),0)}}
/* phones: the portrait crop is 1:1 at 2x, so the drift stays small (at most 1.05) and nothing is blown up much */
@keyframes m3d-drift-m{from{transform:scale(1) translate3d(0,0,0)}to{transform:scale(1.05) translate3d(var(--kx1,0),var(--ky1,0),0)}}
#m3d .scrim{position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(680px 250px at 50% 130px,rgba(10,18,32,.5),rgba(10,18,32,0) 100%),
    linear-gradient(to bottom,rgba(10,18,32,.9) 0,rgba(10,18,32,.8) 215px,rgba(10,18,32,.5) 320px,rgba(10,18,32,.15) max(44%,380px),rgba(10,18,32,.15) 62%,rgba(10,18,32,.36) 74%,rgba(10,18,32,.9) 100%)}
/* the top band follows the headline in px (it does not grow with the stage); the lower bands are shares of the stage.
   Round 8 (owner: "not so plain dark"): the middle band, where no interface text sits on the photo, is .15 instead of .3-.36;
   the text bands above and below are unchanged, and the map labels keep their own dark bands and halos. */
#m3d .gl{position:absolute;inset:0;width:100%;height:100%;display:block;touch-action:pan-y;opacity:0;transition:opacity 1.2s var(--ease)}
.ready #m3d .gl{opacity:1}

/* static map: shown until the 3D map is drawn, and instead of it without WebGL (?gl=0, Save-Data, low memory, context lost) */
#m3d .poster{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;pointer-events:none;transition:opacity 1s var(--ease);
  padding:clamp(148px,calc(30vh - 72px),198px) 0 clamp(96px,14vh,132px)}
#m3d .poster svg{display:block;height:100%;width:auto;max-width:82vw;transform:perspective(1500px) rotateX(32deg);opacity:.97;filter:drop-shadow(0 4px 0 #5e4a24) drop-shadow(0 10px 28px rgba(3,8,16,.7))}
#m3d .poster path{fill:#18263d;stroke:rgba(230,220,198,.1);stroke-width:.12;stroke-linejoin:round}
#m3d .poster path.r{fill:#2e4a73}
#m3d .poster .ins rect{fill:#0c1626;stroke:rgba(230,220,198,.42);stroke-width:.12}
#m3d .poster .ins path{fill:#1b2f4b;stroke:none}
#m3d .poster .ins circle{fill:var(--sand)}
.ready #m3d .poster{opacity:0}
.m3d-nogl #m3d .poster{opacity:1}
.m3d-nogl.m3d-open #m3d .poster{inset-inline-end:var(--sheet);padding-top:28px}
.m3d-nogl #m3d .gl,.m3d-nogl #m3d .labels,.m3d-nogl #m3d .ring,.m3d-nogl #m3d .mini{display:none}

/* ---------- buttons: the DS .cta (brass border), and the solid brass variant used only in this hero ---------- */
#m3d .cta,#m3d-dock{display:inline-flex;align-items:center;justify-content:center;gap:.5em;min-height:52px;padding:0 26px;border:1px solid var(--brass);color:var(--sand);white-space:nowrap;
  transition:background-color .35s var(--ease),color .35s var(--ease)}
#m3d .cta:hover{background:var(--brass);color:var(--navy)}
#m3d .cta.solid,#m3d-dock{background:var(--brass);border-color:var(--brass);color:var(--navy);font-weight:400}
#m3d .cta.solid:hover,#m3d-dock:hover{background:var(--brass-hi);border-color:var(--brass-hi);color:var(--navy)}

/* ---------- headline: centred above the map ---------- */
#m3d .intro{position:absolute;z-index:10;top:clamp(8px,2.4vh,28px);left:50%;transform:translateX(-50%);width:min(940px,92vw);max-width:none;text-align:center;
  font-size:inherit;font-weight:400;line-height:inherit;transition:opacity .6s var(--ease),transform .6s var(--ease);text-shadow:0 1px 18px rgba(10,18,32,.7)}
#m3d .intro .cta{text-shadow:none}
.m3d-open #m3d .intro{opacity:0;pointer-events:none;transform:translate(-50%,-12px);visibility:hidden;transition:opacity .6s var(--ease),transform .6s var(--ease),visibility 0s linear .6s}
#m3d .eyebrow{margin:0;font-size:12.5px;line-height:inherit;letter-spacing:.16em;text-transform:uppercase;color:var(--brass-hi);text-wrap:wrap}
html[lang="ar"] #m3d .eyebrow{letter-spacing:normal;text-transform:none;font-size:13.5px}
html[lang="zh"] #m3d .eyebrow{letter-spacing:.06em;font-size:13.5px}
#m3d h1{font-weight:300;font-size:clamp(40px,4.6vw,66px);line-height:1.08;letter-spacing:-.005em;margin-top:10px;text-wrap:wrap}
#m3d h1 .ln{display:inline-block}
html[lang="ar"] #m3d h1{line-height:1.3;letter-spacing:0}
html[lang="zh"] #m3d h1{line-height:1.25;letter-spacing:.04em;font-feature-settings:"halt"}
html[lang="zh"] #m3d h1 .sp{display:none}   /* no space between the two clauses; "halt" sets the comma half-width (the site loads Noto Serif SC) */
#m3d .lead{max-width:64ch;margin:14px auto 0;font-size:clamp(17px,1.3vw,19.5px);line-height:1.55;color:var(--sand-70);font-weight:300;text-wrap:balance}
#m3d .lead .s{display:none}
/* the hero's WhatsApp button: .cta-d on desktop (data-src m3d_hero_d), .cta-m on phones (m3d_hero_m, watched by the dock) */
#m3d .intro .cta-m{display:none}
#m3d .intro .cta-d{margin-top:18px;min-height:48px;padding:0 24px;font-size:15.5px}

/* ---------- map overlays: greetings, hotspots, leader lines, route cities, Dubai, inset label, province tip ---------- */
#m3d .labels,#m3d .ring{position:absolute;inset:0;pointer-events:none;z-index:5}
html:not(.ready) #m3d .labels{visibility:hidden}   /* labels are created before the first frame places them */
#m3d .ring span{position:absolute;left:0;top:0;white-space:nowrap;font-size:13.5px;color:var(--sand);will-change:transform,opacity;font-weight:300;opacity:0;text-shadow:0 1px 8px rgba(10,18,32,.95),0 0 3px rgba(10,18,32,.9)}
#m3d .ring span.me{color:var(--brass-hi);font-weight:400;font-size:24px;letter-spacing:.02em;text-shadow:var(--halo-l)}
#m3d .origin{position:absolute;left:0;top:0;display:flex;align-items:center;gap:9px;font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:var(--brass-hi);white-space:nowrap;transition:opacity .6s var(--ease);font-family:var(--en);text-shadow:var(--halo)}
html[lang="ar"] #m3d .origin{font-family:var(--ar);letter-spacing:0;font-size:14px}
html[lang="zh"] #m3d .origin{font-family:var(--zh);letter-spacing:.08em;font-size:13px}
#m3d .origin i{width:8px;height:8px;border-radius:50%;background:var(--brass-hi);box-shadow:0 0 0 5px rgba(193,154,82,.16);flex:none}
#m3d .origin.left{flex-direction:row-reverse}
.m3d-arriving #m3d .hot,.m3d-arriving #m3d .origin,.m3d-arriving #m3d .inset-label{opacity:0}
#m3d .hot{position:absolute;left:0;top:0;pointer-events:auto;display:flex;align-items:center;gap:10px;min-height:44px;padding:0 4px;text-shadow:var(--halo);
  font-size:15px;line-height:1.3;color:var(--sand);white-space:nowrap;transition:opacity .4s var(--ease),color .3s var(--ease);text-align:start}
#m3d .hot.flip{flex-direction:row-reverse;text-align:end}
#m3d .hot i{width:9px;height:9px;border-radius:50%;background:var(--brass-hi);box-shadow:0 0 0 4px rgba(193,154,82,.18);flex:none}
#m3d .hot small{display:block;font-size:12.5px;color:var(--sand)}
#m3d .hot:hover,#m3d .hot.on{color:#fff}
#m3d .hot.off{opacity:0;pointer-events:none}
#m3d .hot .sn{display:none}
#m3d .hot.compact small{display:none}
#m3d .hot.nodot i{visibility:hidden}
#m3d .hot.dotonly>span{display:none}   /* no place near its city for the label: the dot alone (still opens the region) */
#m3d .ld{position:absolute;left:0;top:0;height:1px;background:rgba(193,154,82,.7);transform-origin:0 50%;opacity:0;pointer-events:none;transition:opacity .4s var(--ease)}
.m3d-arriving #m3d .ld{opacity:0!important}
#m3d .city{position:absolute;left:0;top:0;font-size:13px;color:var(--sand);white-space:nowrap;padding:2px 4px;text-shadow:var(--halo);transition:opacity .5s var(--ease)}
html[lang="en"] #m3d .city{font-size:11.5px;letter-spacing:.12em;text-transform:uppercase}
#m3d .city.hidden{opacity:0}
#m3d .inset-label{position:absolute;left:0;top:0;font-size:12px;color:var(--sand);white-space:nowrap;text-align:center;line-height:1.35;text-shadow:var(--halo)}
/* text on the map or the photographs: a soft, borderless dark band behind it (feathered on all four sides, so no box shows), with the halo */
#m3d .hot>span,#m3d .origin>span,#m3d .now .nw{position:relative}
#m3d .hot>span::before,#m3d .origin>span::before,#m3d .now .nw::before,#m3d .city::before,#m3d .ring span.me::before,#m3d .inset-label::before,#m3d .mini-l::before{
  content:"";position:absolute;z-index:-1;inset:-9px -18px;pointer-events:none;
  background:linear-gradient(to right,rgba(10,18,32,0),rgba(10,18,32,.74) 18px,rgba(10,18,32,.74) calc(100% - 18px),rgba(10,18,32,0));
  -webkit-mask-image:linear-gradient(to bottom,transparent,#000 9px,#000 calc(100% - 9px),transparent);mask-image:linear-gradient(to bottom,transparent,#000 9px,#000 calc(100% - 9px),transparent)}
#m3d .mini-l{position:relative}
/* the brass "welcome" is darker than sand: a denser band behind it (round 8: 3.35:1 on Zhangjiajie's bright cliffs at 360 x 640) */
#m3d .ring span.me::before{background:linear-gradient(to right,rgba(10,18,32,0),rgba(10,18,32,.9) 18px,rgba(10,18,32,.9) calc(100% - 18px),rgba(10,18,32,0))}

/* the province under the mouse: its name (and tagline once provinces.js is in), placed clear of Taiwan, Hainan and the inset */
#m3d .pname{position:absolute;z-index:6;left:0;top:0;max-width:260px;padding:7px 11px;background:rgba(10,18,32,.92);border:1px solid rgba(193,154,82,.5);
  color:var(--sand);font-size:15px;line-height:1.3;pointer-events:none;opacity:0;transition:opacity .15s var(--ease);text-shadow:none}
#m3d .pname.show{opacity:1}
#m3d .pname b{display:block;font-weight:400}
#m3d .pname small{display:block;margin-top:2px;font-size:12.5px;color:var(--sand-70)}
#m3d .pname small:empty{display:none}

/* ---------- fixed South China Sea Islands inset, shown in region views (placed by map3d.js) ---------- */
#m3d .mini{position:absolute;z-index:6;inset-inline-start:var(--pad);bottom:104px;width:96px;opacity:0;pointer-events:none;transition:opacity .6s var(--ease);text-align:center}
.m3d-open #m3d .mini{opacity:1}
.m3d-zoom #m3d .mini{opacity:1}
/* ---------- the visitor's own zoom (2026-10-06; map3d.js): the buttons, and the zoomed map's window ----------
   The buttons sit under the headline's button at the end side (--zc-top, set by map3d.js). While the map is zoomed
   (html.m3d-zoom) the canvas is masked to its window (--zt to --zb, 12 px feathers: ZF in map3d.js), one finger moves the
   map instead of the page, and the photo caption is put away. Labels stay scrollable but never start a page zoom. */
#m3d .zc{position:absolute;z-index:9;top:var(--zc-top,40%);inset-inline-end:var(--pad);display:flex;gap:1px;border-radius:999px;overflow:hidden;
  background:rgba(230,220,198,.26);border:1px solid rgba(230,220,198,.3);transition:opacity .4s var(--ease),visibility 0s linear 0s}
#m3d .zc[hidden],#m3d .zc button[hidden]{display:none}
#m3d .zc button{display:grid;place-items:center;width:44px;height:42px;color:var(--sand);background:rgba(10,18,32,.74);transition:color .3s var(--ease),background-color .3s var(--ease)}
#m3d .zc button:disabled{color:rgba(230,220,198,.36);cursor:default}
#m3d .zc button:not(:disabled):active{background:rgba(10,18,32,.92);color:var(--brass-hi)}
#m3d .zc button:focus-visible{outline:2px solid var(--brass-hi);outline-offset:-3px}
#m3d .zc svg{width:15px;height:15px}
html:not(.ready) #m3d .zc,.m3d-arriving #m3d .zc,.m3d-open #m3d .zc,.m3d-nogl #m3d .zc{opacity:0;visibility:hidden;pointer-events:none;transition:opacity .3s var(--ease),visibility 0s linear .3s}
.m3d-zoom #m3d .gl{touch-action:none;
  -webkit-mask-image:linear-gradient(to bottom,transparent var(--zt,0px),#000 calc(var(--zt,0px) + 12px),#000 calc(var(--zb,100%) - 12px),transparent var(--zb,100%));
  mask-image:linear-gradient(to bottom,transparent var(--zt,0px),#000 calc(var(--zt,0px) + 12px),#000 calc(var(--zb,100%) - 12px),transparent var(--zb,100%))}
.m3d-zoom #m3d .now{opacity:0;visibility:hidden;pointer-events:none;transition:opacity .3s var(--ease),visibility 0s linear .3s}
#m3d .hot{touch-action:pan-y}
.m3d-zoom #m3d .hot{touch-action:none}
#m3d .mini svg{display:block;width:100%;max-width:none;height:auto}
#m3d .mini rect{fill:rgba(12,22,38,.9);stroke:rgba(230,220,198,.42);stroke-width:.008}
#m3d .mini path{fill:#22365a}
#m3d .mini circle{fill:var(--sand)}
#m3d .mini-l{display:block;margin-top:4px;font-size:11.5px;line-height:1.35;color:var(--sand);text-shadow:var(--halo)}

/* ---------- tags row (generated: parts/_map3d_tags.html), centred under the map; it scrolls when it does not fit ----------
   Each tag: a round thumbnail from assets/map3d/tags.webp (one cell per tag, --n cells) and its label in the page language
   (all three are in the markup; .ml shows the one that matches <html lang>). The tag of the current background photo
   carries a brass edge and a progress line; "All provinces" stays at the end, outside the scrolling part. */
#m3d .ml>[lang]{display:none}
html[lang="en"] #m3d .ml>[lang="en"],html[lang="ar"] #m3d .ml>[lang="ar"],html[lang="zh"] #m3d .ml>[lang="zh"]{display:inline}
#m3d .tags{position:absolute;z-index:10;bottom:clamp(14px,3vh,30px);left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:8px;
  width:max-content;max-width:calc(100% - 2 * var(--pad));transition:opacity .5s var(--ease)}
#m3d .tg-row{--fl:0px;--fr:0px;display:flex;gap:8px;min-width:0;overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none;padding:3px 2px;scroll-padding-inline:44px;
  -webkit-mask-image:linear-gradient(to right,transparent 0,#000 var(--fl),#000 calc(100% - var(--fr)),transparent 100%);
  mask-image:linear-gradient(to right,transparent 0,#000 var(--fl),#000 calc(100% - var(--fr)),transparent 100%)}
#m3d .tg-row::-webkit-scrollbar{display:none}
html[dir="ltr"] #m3d .tg-row.fs,html[dir="rtl"] #m3d .tg-row.fe{--fl:40px}
html[dir="ltr"] #m3d .tg-row.fe,html[dir="rtl"] #m3d .tg-row.fs{--fr:40px}
#m3d .tg{position:relative;flex:none;display:inline-flex;align-items:center;gap:9px;min-height:44px;padding-block:4px;padding-inline:4px 16px;border-radius:22px;
  background:rgba(10,18,32,.7);border:1px solid rgba(230,220,198,.22);color:var(--sand);font-size:14.5px;line-height:1.2;white-space:nowrap;
  transition:background-color .3s var(--ease),border-color .3s var(--ease),color .3s var(--ease)}
#m3d .tg:hover{background:rgba(10,18,32,.9);border-color:rgba(193,154,82,.8);color:#fff}
#m3d .tg:focus-visible{outline-offset:-5px}   /* inside the tag: the scrolling row would clip the global 4 px outer ring */
#m3d .tg .th{width:34px;height:34px;border-radius:50%;flex:none;background:var(--navy-2) url(../map3d/tags.webp) no-repeat;background-size:calc(var(--n,12) * 100%) 100%;
  box-shadow:0 0 0 1px rgba(230,220,198,.28);transition:box-shadow .3s var(--ease)}
#m3d .tg.cur{border-color:rgba(193,154,82,.9);background:rgba(10,18,32,.84)}
#m3d .tg.cur .th{box-shadow:0 0 0 2px var(--brass-hi)}
#m3d .tg::after{content:"";position:absolute;inset-inline:24px 20px;bottom:3px;height:2px;border-radius:1px;background:var(--brass-hi);opacity:0;
  transform:scaleX(0);transform-origin:left center}
html[dir="rtl"] #m3d .tg::after{transform-origin:right center}
#m3d .tg.cur::after{opacity:1;animation:m3d-prog 7s linear forwards}
#m3d .tags.paused .tg.cur::after{animation-play-state:paused}
#m3d .tags.still .tg::after{display:none}
@keyframes m3d-prog{from{transform:scaleX(0)}to{transform:scaleX(1)}}
#m3d .tsc,#m3d .tsf{display:none}
@media (hover:hover) and (min-width:821px){
  #m3d .tsc{position:absolute;z-index:2;top:50%;inset-inline-start:-6px;display:grid;place-items:center;width:34px;height:34px;margin-top:-17px;border-radius:50%;
    background:rgba(10,18,32,.9);border:1px solid rgba(193,154,82,.7);color:var(--sand);opacity:0;pointer-events:none;transition:opacity .3s var(--ease)}
  #m3d .tsc.on{opacity:1;pointer-events:auto}
  /* .tsf: a navy fade under each arrow (map3d.js puts it beside the arrow), reaching into the row, so a clipped label fades
     out before the arrow instead of running into it (round 8) */
  #m3d .tsf{position:absolute;z-index:1;top:0;bottom:0;width:60px;pointer-events:none;opacity:0;transition:opacity .3s var(--ease)}
  #m3d .tsf.on{opacity:1}
  #m3d .tsf.prev{inset-inline-start:-6px}
  html[dir="ltr"] #m3d .tsf.prev,html[dir="rtl"] #m3d .tsf.next{background:linear-gradient(to right,rgba(10,18,32,.9) 50%,rgba(10,18,32,0))}
  html[dir="ltr"] #m3d .tsf.next,html[dir="rtl"] #m3d .tsf.prev{background:linear-gradient(to left,rgba(10,18,32,.9) 50%,rgba(10,18,32,0))}
  #m3d .tsc.next{inset-inline-start:auto}
  #m3d .tsc svg{width:7px;height:12px}
  #m3d .tsc.next svg,html[dir="rtl"] #m3d .tsc.prev svg{transform:scaleX(-1)}
  html[dir="rtl"] #m3d .tsc.next svg{transform:none}
}
#m3d .tg.all{gap:9px;padding-inline:14px 16px;border-color:rgba(193,154,82,.7)}
#m3d .tg.all .ic{width:15px;height:15px;flex:none;color:var(--brass-hi)}
#m3d .tg.all .sh{display:none}
#m3d .tg.all[aria-expanded="true"]{background:var(--sand);color:var(--navy);border-color:var(--sand)}
#m3d .tg.all[aria-expanded="true"] .ic{color:var(--navy)}
.m3d-open #m3d .tags{left:calc((100% - var(--sheet)) / 2);max-width:calc(100% - var(--sheet) - 2 * var(--pad))}
html[dir="rtl"].m3d-open #m3d .tags{left:calc(var(--sheet) + (100% - var(--sheet)) / 2)}

/* ---------- the background photo's caption: its place (opens the province), its credit, a pause button ----------
   Physically on the left, above the tags: the map's west side, far from Taiwan, Hainan and the inset (map3d.js hides it
   should it ever touch them). Hidden while a sheet is open: the sheet shows the same photo with its credit. */
#m3d .now{position:absolute;z-index:10;left:var(--pad);bottom:calc(clamp(14px,3vh,30px) + 56px);display:flex;align-items:center;gap:8px;
  max-width:min(440px,calc(100% - 2 * var(--pad)));transition:opacity .4s var(--ease),visibility 0s linear 0s}
#m3d .now[hidden]{display:none}
.m3d-open #m3d .now,#m3d .now.clash{opacity:0;visibility:hidden;pointer-events:none;transition:opacity .3s var(--ease),visibility 0s linear .3s}
#m3d .now .pp{flex:none;display:grid;place-items:center;width:44px;height:44px;border-radius:50%;color:var(--sand);background:rgba(10,18,32,.66);border:1px solid rgba(230,220,198,.26);
  transition:border-color .3s var(--ease)}
#m3d .now .pp:hover{border-color:var(--brass-hi)}
#m3d .now .pp[hidden]{display:none}
#m3d .now .pp svg{width:11px;height:11px}
#m3d .now .pp .i-play,#m3d .now .pp.play .i-pause{display:none}
#m3d .now .pp.play .i-play{display:inline}
#m3d .now .nw{display:flex;flex-direction:column;align-items:flex-start;min-width:0;text-shadow:var(--halo)}
#m3d .now .nt{display:inline-flex;align-items:center;min-height:30px;font-size:15.5px;line-height:1.3;color:var(--sand);text-decoration:underline;text-decoration-color:transparent;text-underline-offset:4px;
  transition:text-decoration-color .3s var(--ease)}
#m3d .now .nt:hover{text-decoration-color:var(--brass-hi)}
#m3d .now .nc{margin-top:3px;font-size:11.5px;line-height:1.35;color:var(--sand-70)}
#m3d .now .nc a{display:inline-block;padding-block:4px;margin-block:-4px;text-decoration:underline;text-underline-offset:2px}
/* touch screens of any width (iPad landscape): the place's button 44 px tall and the licence link 8 px under it, so a thumb
   aimed at the place does not open creativecommons.org (round 2 review) */
@media (pointer:coarse){
  #m3d .now .nt{min-height:44px}
  #m3d .now .nc{margin-top:12px}   /* the link's 4 px padding: its box starts 8 px under the place's button */
}

/* ---------- journey sheet: a drawer on the end side (desktop), a bottom sheet (phones) ---------- */
#m3d .sheet{position:absolute;z-index:25;top:0;bottom:0;inset-inline-end:0;width:var(--sheet);background:var(--navy-2);border-inline-start:1px solid var(--line);
  transform:translateX(102%);transition:transform .45s var(--drawer),visibility 0s linear .45s;overflow-y:auto;overscroll-behavior:contain;padding:22px 30px 0;visibility:hidden;scroll-padding-bottom:120px}
html[dir="rtl"] #m3d .sheet{transform:translateX(-102%)}
.m3d-open #m3d .sheet,html[dir="rtl"].m3d-open #m3d .sheet{transform:none;visibility:visible;transition:transform .45s var(--drawer),visibility 0s}
#m3d .sheet .top{display:flex;align-items:flex-start;justify-content:space-between;gap:16px}
#m3d .sheet .close{min-height:44px;min-width:44px;font-size:14px;color:var(--sand-70);display:inline-flex;align-items:center;gap:8px;flex:none}
#m3d .sheet .close:hover{color:var(--sand)}
#m3d .sheet .close svg{display:block;width:14px;height:14px}
#m3d .sheet .s-eye{font-size:13.5px;color:var(--sand-70);padding-top:12px}
#m3d .sheet h2{font-weight:300;font-size:clamp(28px,2.3vw,34px);line-height:1.15;margin-top:2px;text-wrap:wrap}
html[lang="ar"] #m3d .sheet h2{line-height:1.4}
#m3d .sheet h2 .alt{display:block;font-size:.52em;color:var(--sand-70);margin-top:4px;text-align:left;text-align:-webkit-match-parent;text-align:match-parent}
/* 3D card: layered tilt — photo (with depth parallax), light sweep and caption at different depths */
#m3d .card3d{margin-top:18px;perspective:900px}
#m3d .card3d .tilt{position:relative;aspect-ratio:4/3;transform-style:preserve-3d;will-change:transform}
#m3d .card3d .ph{position:absolute;inset:0;overflow:hidden;background:var(--navy-2);transform:translateZ(0)}
#m3d .card3d .ph img{position:absolute;inset:-6%;width:112%;height:112%;max-width:none;object-fit:cover;filter:saturate(.95) contrast(1.05) brightness(.97);
  transition:opacity .6s var(--ease);animation:m3d-kb 18s ease-in-out infinite alternate}
#m3d .card3d .ph::after{content:"";position:absolute;inset:0;background:linear-gradient(to top,rgba(10,18,32,.45),transparent 40%);mix-blend-mode:normal;opacity:1}
#m3d .card3d .glare{position:absolute;inset:0;pointer-events:none;background:radial-gradient(60% 60% at var(--gx,30%) var(--gy,20%),rgba(255,240,210,.16),transparent 70%);
  transform:translateZ(1px);mix-blend-mode:screen}
#m3d .card3d .cap{position:absolute;inset-inline-start:14px;bottom:14px;transform:translateZ(46px);font-size:13px;padding:5px 10px;background:rgba(10,18,32,.8);border:1px solid var(--line);color:var(--sand)}
@keyframes m3d-kb{from{transform:scale(1) translate3d(0,0,0)}to{transform:scale(1.06) translate3d(-1.2%,-.8%,0)}}
#m3d .thumbs{display:flex;gap:6px;margin-top:10px}
#m3d .thumbs button{width:58px;height:44px;overflow:hidden;opacity:.55;border:1px solid transparent;transition:opacity .3s var(--ease)}
#m3d .thumbs button[aria-pressed="true"]{opacity:1;border-color:var(--brass)}
#m3d .thumbs img{display:block;width:100%;height:100%;max-width:none;object-fit:cover}
#m3d .credit{margin-top:6px;font-size:12px;color:var(--sand-60)}
#m3d .credit a{text-decoration:underline;text-underline-offset:3px}
#m3d .sel{margin-top:20px}
#m3d .sel .jt{font-weight:400;font-size:22px;line-height:1.3;text-wrap:wrap}
#m3d .sel .m{margin-top:6px;font-size:14.5px;color:var(--sand-70);font-variant-numeric:tabular-nums}
#m3d .sel .desc{margin-top:12px;max-width:none;font-size:16px;color:var(--sand-70);font-weight:300}
#m3d .sel ul{list-style:none;margin-top:10px}
#m3d .sel li{position:relative;padding-inline-start:18px;margin-top:6px;font-size:15px;color:var(--sand-70);line-height:1.5}
#m3d .sel li::before{content:"";position:absolute;inset-inline-start:0;top:.75em;width:7px;height:1px;background:var(--brass)}
#m3d .sel .price{margin-top:10px;font-size:19px;line-height:1.35;color:var(--sand);font-variant-numeric:tabular-nums}
#m3d .sel .note{margin-top:4px;font-size:14px;line-height:1.5;color:var(--sand-70)}
/* "Read the itinerary": a text link here, not the DS .more button */
#m3d .sel .more{display:inline-flex;align-items:center;justify-content:flex-start;gap:0;max-width:none;min-height:44px;margin-top:10px;padding:0;border:0;
  font-size:inherit;line-height:inherit;white-space:normal;text-align:start;color:var(--sand);
  text-decoration:underline;text-decoration-color:var(--brass);text-underline-offset:5px;text-decoration-thickness:1px}
#m3d .sel .more:hover{background:none;color:#fff}
#m3d .act{position:sticky;bottom:0;z-index:2;margin:22px -30px 0;padding:16px 30px 20px;background:linear-gradient(to top,var(--navy-2) 80%,rgba(10,18,32,0))}
#m3d .act::before{content:"";position:absolute;inset-inline:0;bottom:100%;height:30px;pointer-events:none;background:linear-gradient(to top,var(--navy-2),rgba(10,18,32,0))}
#m3d .act .cta{width:100%}
#m3d .act-n{margin-top:7px;font-size:12.5px;line-height:1.4;color:var(--sand-60);text-align:center}
#m3d .grab{display:none}
#m3d .act:empty{display:none}
/* province sheet: description, three highlights, best season, then our journeys there (if any) */
#m3d .sheet .back{display:inline-flex;align-items:center;gap:8px;min-height:44px;margin-top:2px;font-size:14px;color:var(--sand-70)}
#m3d .sheet .back[hidden]{display:none}
#m3d .sheet .back:hover{color:var(--sand)}
#m3d .sheet .back svg{width:7px;height:12px}
html[dir="rtl"] #m3d .sheet .back svg{transform:scaleX(-1)}
#m3d .sheet.noph .card3d .ph>*,#m3d .sheet.noph .credit,#m3d .sheet.noph .cap{opacity:0!important}
#m3d .pv{margin-top:18px}
#m3d .pv .desc{font-size:16px;line-height:1.6;color:var(--sand-70);font-weight:300}
#m3d .pv .vh{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
#m3d .pv .hl{list-style:none;display:flex;flex-wrap:wrap;gap:6px;margin-top:14px}
#m3d .pv .hl li{padding:5px 12px;border:1px solid rgba(230,220,198,.22);border-radius:16px;font-size:14px;line-height:1.4;color:var(--sand)}
#m3d .pv .season{margin-top:16px;font-size:15px;line-height:1.45;color:var(--sand)}
#m3d .pv .season .k{display:block;font-size:12.5px;color:var(--sand-60);margin-bottom:2px}
#m3d .pv .nr{margin-top:14px;font-size:14px;line-height:1.5;color:var(--sand-70)}
#m3d .sel .jh{font-weight:400;font-size:13.5px;line-height:1.4;color:var(--sand-70);padding-top:20px;margin-bottom:8px;border-top:1px solid var(--line)}
#m3d .sel .cta:not(.solid){display:flex;width:100%;margin-top:10px;min-height:46px;padding:0 18px;font-size:15px}
/* the list of every province: our journeys first, then the 34 units in two columns, each with a round thumbnail */
#m3d .sheet[data-mode="list"] .card3d,#m3d .sheet[data-mode="list"] .thumbs,#m3d .sheet[data-mode="list"] .credit{display:none}
#m3d .lst h3{margin-top:22px;font-weight:400;font-size:13.5px;line-height:1.4;color:var(--sand-70)}
#m3d .lst h3:first-child{margin-top:16px}
#m3d .lst .pl{list-style:none;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:0 16px;margin-top:6px;padding-bottom:28px}
#m3d .lst .pl button{display:flex;align-items:center;gap:10px;width:100%;min-height:54px;padding:6px 0;border-bottom:1px solid var(--line);text-align:start}
#m3d .lst .pl .th{width:38px;height:38px;flex:none;border-radius:50%;background:var(--navy) url(../map3d/provinces.webp) no-repeat;background-size:3400% 100%;
  box-shadow:0 0 0 1px rgba(230,220,198,.2)}
#m3d .lst .pl .th.none{background-image:none}
#m3d .lst .pl .tx{display:flex;flex-direction:column;min-width:0}
#m3d .lst .pl .t{font-size:15px;line-height:1.3;color:var(--sand)}
#m3d .lst .pl .m{font-size:12px;line-height:1.35;color:var(--sand-60);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#m3d .lst .pl button:hover .t{text-decoration:underline;text-underline-offset:4px;text-decoration-color:var(--brass)}
#m3d .others{margin-top:28px}
#m3d .others h3{font-weight:400;font-size:13.5px;line-height:inherit;color:var(--sand-70);text-wrap:wrap}
#m3d .jl{list-style:none;margin-top:8px;border-top:1px solid var(--line)}
#m3d .jl button{display:block;width:100%;padding:12px 0;border-bottom:1px solid var(--line);line-height:1.4}
#m3d .jl .t{display:block;font-size:16px;color:var(--sand)}
#m3d .jl .m{display:block;font-size:13px;color:var(--sand-60);margin-top:2px;font-variant-numeric:tabular-nums}
#m3d .jl button:hover .t{text-decoration:underline;text-underline-offset:4px;text-decoration-color:var(--brass)}

/* ---------- phone WhatsApp bar: outside the stage, under the open site menu (z-index 20) ---------- */
#m3d-dock{display:none}

/* ---------- phones ---------- */
@media (max-width:820px){
  #m3d{min-height:560px;max-height:none}
  #m3d .intro{top:4px}
  #m3d .eyebrow{font-size:11px;letter-spacing:.12em}
  html[lang="ar"] #m3d .eyebrow,html[lang="zh"] #m3d .eyebrow{font-size:12.5px}
  html[lang="en"] #m3d .eyebrow{font-size:10.5px;letter-spacing:.06em}
  #m3d h1{font-size:clamp(32px,9vw,42px);margin-top:4px}
  /* Chinese: the two clauses on one line even before Noto Serif SC arrives (full-width comma), so the photo band does not
     jump when the font loads (round 2 of 2026-10-05: at 390 px the line broke in two and the band lost 40 px) */
  html[lang="zh"] #m3d h1{font-size:clamp(26px,8.6vw,38px)}
  /* the headline block as short as the tokens allow (round 2: Arabic and Chinese ran 13 px taller than English, which the
     photo band lost on 375 x 635): the eyebrow at the UI line height, the one-line h1 at the display line height */
  #m3d .eyebrow{line-height:var(--lh-ui)}
  html[lang="ar"] #m3d h1,html[lang="zh"] #m3d h1{line-height:var(--lh-display)}
  #m3d .lead{font-size:15px;margin-top:8px;max-width:34ch;line-height:1.5}
  #m3d .lead .l{display:none}
  #m3d .lead .s{display:inline}
  #m3d .origin{display:none}
  #m3d .intro .cta-m{display:inline-flex;margin-top:14px;min-height:48px;padding:0 22px;font-size:15.5px}
  #m3d .intro .cta-d{display:none}
  /* Photos first (owner 2026-10-05, "手机上的图片要更醒目"): the navy only where text sits (the headline block, whose
     lead ends at --ib, set by map3d.js; and the caption and photo cards at the foot), clear in between; the map is
     smaller and lower (map3d.js bands(): a photo band under the button) and lets the photo through (.gl opacity) */
  #m3d .scrim{background:linear-gradient(to bottom,rgba(10,18,32,.88) 0,rgba(10,18,32,.8) var(--ib,150px),rgba(10,18,32,.32) calc(var(--ib,150px) + 34px),
    rgba(10,18,32,0) calc(var(--ib,150px) + 66px),rgba(10,18,32,0) calc(var(--mt,60%) - 10px),rgba(10,18,32,.24) calc(var(--mt,60%) + 60px),rgba(10,18,32,.5) calc(100% - 170px),rgba(10,18,32,.9) 100%)}
  /* portrait slides are sized and placed by HNT_M3D_FIT (parts/_map3d.html): their subject in the photo band, the photo
     covering the stage (round 2: no more shifting a stage-high box up, which left a navy strip at the foot) */
  #m3d .bg .sl{animation-name:m3d-drift-m}
  #m3d .bg.fit .sl{transition:opacity 1.4s var(--ease),top .6s var(--ease),left .6s var(--ease),width .6s var(--ease),height .6s var(--ease)}
  #m3d .bg.still .sl{transform:none}
  #m3d .intro .eyebrow,#m3d .intro .lead{text-shadow:var(--halo)}
  .ready:not(.m3d-open) #m3d .gl{opacity:var(--gl-o,.8)}
  .ready.m3d-zoom:not(.m3d-open) #m3d .gl{opacity:.93}   /* a zoomed map is read, not looked through */
  #m3d .poster{padding:var(--mt,calc(var(--ib,150px) + 180px)) 0 var(--mb,150px)}   /* the static map: the same bands as the 3D one */
  #m3d .poster svg{height:auto;width:86vw;max-width:none;max-height:100%;transform:perspective(900px) rotateX(28deg);opacity:.8}
  /* the tags as photo cards (owner 2026-10-05): a 114 x 86 photo (assets/map3d/tagcards.webp, 240 x 180 cells, same
     background-position as the round thumbnails) with the label under it, two lines at most; the row scrolls sideways
     (at 375 px two cards and a third's edge show, so the row reads as scrollable) */
  #m3d .tags{left:0;transform:none;width:100%;max-width:none;bottom:0;gap:8px;align-items:stretch;padding-block:8px calc(10px + env(safe-area-inset-bottom,0px));padding-inline:0 12px;
    background:linear-gradient(to top,rgba(10,18,32,.9) 50%,rgba(10,18,32,0))}
  #m3d .tg-row{flex:1;padding-inline:12px 2px;gap:8px}
  #m3d .tg{flex-direction:column;align-items:stretch;gap:0;width:116px;min-height:0;padding:0;border-radius:10px;overflow:hidden;font-size:13px;white-space:normal;
    background:rgba(10,18,32,.78)}
  #m3d .tg .th{width:114px;height:86px;border-radius:0;box-shadow:none;background-image:url(../map3d/tagcards.webp)}
  #m3d .tg[data-tag] .ml{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;height:2.6em;margin:6px 8px 7px;line-height:1.3;text-align:start}
  html[lang="ar"] #m3d .tg[data-tag] .ml{font-size:13.5px;line-height:1.35;height:2.7em}
  #m3d .tg.cur{border-color:var(--brass-hi);box-shadow:inset 0 0 0 1px var(--brass-hi)}
  #m3d .tg.cur .th{box-shadow:none}
  #m3d .tg::after{inset-inline:8px;bottom:3px}
  #m3d .tg.all{width:58px;flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:0 6px;text-align:center}
  #m3d .tg.all .ic{width:20px;height:20px}
  #m3d .tg.all .lg{display:none}
  #m3d .tg.all .sh{display:inline}
  .m3d-open #m3d .tags,html[dir="rtl"].m3d-open #m3d .tags{left:0;max-width:none;opacity:0;pointer-events:none;visibility:hidden}
  #m3d .now{left:12px;bottom:calc(160px + env(safe-area-inset-bottom,0px));max-width:calc(100% - 24px)}   /* over the photo cards */
  #m3d .zc{inset-inline-end:12px}
  #m3d .now .nt{min-height:44px;font-size:14.5px}
  #m3d .now .nc{margin-top:12px;font-size:11px}
  .m3d-nogl.m3d-open #m3d .poster{inset-inline-end:0;bottom:58svh;padding:6px 0 8px}
  #m3d .hot small{display:none;font-size:11.5px}
  #m3d .hot .n{display:none}
  #m3d .hot .sn{display:inline}
  #m3d .hot{font-size:13.5px;gap:8px}
  #m3d .ring span.me{font-size:20px}
  #m3d .sheet{top:auto;height:58svh;width:100%;inset-inline:0;border-inline-start:0;border-top:1px solid var(--line);transform:translateY(102%)!important;padding:0 20px}
  #m3d .grab{display:block;position:sticky;top:0;z-index:3;height:22px;margin:0 -20px;background:var(--navy-2);touch-action:none;cursor:grab}
  #m3d .grab::after{content:"";position:absolute;inset-inline:0;top:9px;width:38px;height:4px;margin-inline:auto;border-radius:2px;background:var(--sand-45)}
  #m3d .card3d .tilt{aspect-ratio:16/9}
  #m3d .card3d{margin-top:10px}
  #m3d .act{margin:18px -20px 0;padding:12px 20px 14px}
  #m3d .sheet h2{font-size:26px}
  .m3d-open #m3d .sheet{transform:none!important}
  #m3d .mini{inset-inline-start:auto;inset-inline-end:12px;bottom:calc(58svh + 10px);width:max-content;max-width:112px}
  #m3d .mini svg{width:48px;margin-inline:auto}   /* the label may be wider than the plate: two short lines, not five */
  #m3d .lst .pl{gap:0 12px}
  #m3d .lst .pl .th{width:34px;height:34px}
  #m3d .mini-l{font-size:10.5px}
  /* the overview's inset label under the plate: "南海诸岛" and, in English and Arabic, the translation as a second line (round 2
     of 2026-10-05: smaller, so its room under the map, HNT_M3D_BANDS ir, stays small; a narrower dark band, which map3d.js
     keeps clear of Taiwan and Hainan; one long English line reached Hainan in round 8, hence the width cap) */
  #m3d .inset-label{white-space:normal;width:max-content;max-width:132px;font-size:10.5px;line-height:1.3}
  #m3d .inset-label::before{inset:-5px -8px;background:linear-gradient(to right,rgba(10,18,32,0),rgba(10,18,32,.78) 8px,rgba(10,18,32,.78) calc(100% - 8px),rgba(10,18,32,0));
    -webkit-mask-image:linear-gradient(to bottom,transparent,#000 5px,#000 calc(100% - 5px),transparent);mask-image:linear-gradient(to bottom,transparent,#000 5px,#000 calc(100% - 5px),transparent)}
  #m3d-dock{display:flex;position:fixed;z-index:15;inset-inline:16px;bottom:calc(12px + env(safe-area-inset-bottom));min-height:50px;font-size:15.5px;
    box-shadow:0 8px 24px rgba(0,0,0,.35);transform:translateY(160%);visibility:hidden;transition:transform .45s var(--ease),visibility 0s linear .45s}
  #m3d-dock.show{transform:none;visibility:visible;transition:transform .45s var(--ease),visibility 0s}
  /* room under the footer's last line for the bar (home page only: this file is not loaded elsewhere) */
  html:not(.hero-classic) .footer{padding-block-end:calc(96px + env(safe-area-inset-bottom))}
}
/* shorter phones (and in-app browsers, whose bars take height): smaller cards with the label over the photo's foot, so the
   map keeps its band (map3d.js bands()). Viewport under 772 px high (stage under 700): 102 x 77; under 672: 90 x 68. */
@media (max-width:820px) and (max-height:771px){
  #m3d h1{margin-top:2px}
  #m3d .lead{font-size:14px;line-height:1.45;max-width:none;margin-top:6px}
  #m3d .intro .cta-m{margin-top:10px;min-height:44px}
  #m3d .tg{display:grid;width:104px}
  #m3d .tg .th{grid-area:1/1;width:102px;height:77px}
  #m3d .tg[data-tag] .ml{grid-area:1/1;align-self:end;height:auto;max-height:none;margin:0;padding:16px 7px 6px;font-size:12.5px;line-height:1.25;
    background:linear-gradient(to top,rgba(10,18,32,.94) 45%,rgba(10,18,32,.6) 75%,rgba(10,18,32,0))}
  html[lang="ar"] #m3d .tg[data-tag] .ml{font-size:13px;line-height:1.3;height:auto}
  #m3d .tg.all{width:52px}
  #m3d .now{bottom:calc(104px + env(safe-area-inset-bottom,0px))}
}
@media (max-width:820px) and (max-height:671px){
  #m3d .tg{width:92px}
  #m3d .tg .th{width:90px;height:68px}
  #m3d .now{bottom:calc(95px + env(safe-area-inset-bottom,0px))}
}

/* ---------- screenshot mode and reduced motion ---------- */
html.m3d-shot #m3d *,html.m3d-shot #m3d-dock{transition:none!important;animation:none!important}
@media (prefers-reduced-motion:reduce){
  #m3d *,#m3d-dock{animation:none!important;transition-property:opacity,visibility,color,background-color,border-color!important}
}
