/* ═══════════════════════════════
   TOKENS
═══════════════════════════════ */
:root {
  --white:    #FFFFFF;
  --off:      #F7F5F1;
  --light:    #EEE9E1;
  --rule:     #E4DDD4;
  --charcoal: #1C1C1C;
  --panel-dark: #1A1A1A;
  --ink-deep: #0D0D0D;
  --body:     #3D3D3D;
  --muted:    #6B6B6B;
  --gold:     #C9A84C;
  --gold-dk:  #A8893C;
  --gold-lt:  #DFC07A;
  --gold-bg:  #FBF7EE;
  /* Darker gold for TEXT on light/off-white grounds — --gold itself is
     ~2.3:1 on white (fails WCAG AA); this reads ~4.9:1. Decorative fills,
     borders and dark-background text keep using --gold/--gold-lt. */
  --gold-text:#8A6B22;
  /* Error red for form failure states (fetch/submit errors) and required-
     field markers. ~5.6:1 on white/--off — passes WCAG AA for normal text. */
  --err-text: #B3261E;
  --err-bg:   #FDEDEC;
  --err-border:#F3C9C6;
  --ease:     cubic-bezier(.22,.68,0,1.1);
  --r-sm:     10px;
  --r-md:     16px;
  --r-lg:     24px;
  --r-xl:     32px;
  --ff-d:     'Work Sans', system-ui, sans-serif;
  --ff-b:     'Work Sans', system-ui, sans-serif;
}

/* Italic gold <em> emphasis (headings site-wide) visually crowds into
   whatever CJK character follows it with no gap -- italic's slant makes the
   glyph's right edge overhang, and Chinese has no natural word-spacing to
   fall back on the way English does. Scoped by :lang() so English em usage
   (already spaced by real word breaks) is untouched. Covers every current
   and future zh-tw/zh-cn <em>, not just the instances found today. */
:lang(zh-tw) em,:lang(zh-cn) em{margin-right:.12em}

/* CJK fonts have no true italic glyphs — browsers fake it with a synthetic
   slant transform, which just looks like distorted/sheared characters
   rather than a real italic face the way it does for Latin script. Every
   h1/h2/h3 em{font-style:italic} rule across this file (dozens of them,
   scoped per heading class) gets neutralized here for zh-tw/zh-cn/ko
   instead of hunting each one down — !important is deliberate, needed to
   beat those rules' higher selector specificity. Covers every current and
   future zh-tw/zh-cn/ko <em>, not just the instances found today. Applies
   to ko too: Noto Sans KR has the same no-true-italic gap as the Chinese
   fonts above, and Hangul fares no better under a synthetic slant. */
:lang(zh-tw) em,:lang(zh-cn) em,:lang(ko) em{font-style:normal!important}

/* Default CJK line-breaking treats every character as its own break
   opportunity, with no concept of the 2-4 character compound words
   Chinese is actually written in (設計, 持有, 國際學校...) — the browser
   will happily split "設" onto one line and "計" onto the next whenever a
   line happens to run out of room there. keep-all tells it not to break
   between CJK characters at all (only at real word/punctuation
   boundaries, same as English); overflow-wrap is the safety net for the
   rare case where a single unbreakable run is still too wide for its
   box. Scoped to the root element (word-break inherits) so it covers
   every zh-tw/zh-cn element site-wide, not just headings. */
html:lang(zh-tw),html:lang(zh-cn){word-break:keep-all;overflow-wrap:break-word}

/* Chinese punctuation (，。、) was rendering vertically centered instead of
   hugging the baseline. Root-caused by directly measuring actual ink
   pixels (not just layout boxes) for Google's Noto Sans SC vs Noto Sans
   TC side by side: SC renders 、，。at the correct low/baseline position
   (~63-98% down the character height); TC renders the exact same
   characters centered (~31-66%) -- this is a real, measurable difference
   between the two font cuts, not environment noise. mypvip.com's old
   site sidesteps this entirely: it loads Noto Sans SC and uses it on
   EVERY page, including its zh-tw ones -- it never loads a
   Traditional-specific font at all. Matching that proven pattern here:
   Noto Sans SC for both locales (see base.njk's <link>), scoped via
   these custom properties so Latin/numeral glyphs still render in Work
   Sans exactly as before -- only the CJK fallback changes. */
html:lang(zh-cn),html:lang(zh-tw){--ff-b:'Work Sans','Noto Sans SC',sans-serif;--ff-d:'Work Sans','Noto Sans SC',sans-serif}

/* Same fallback-font problem as zh-cn/zh-tw above, Korean's own font
   (Noto Sans KR, see base.njk's <link>) instead of Noto Sans SC. Korean is
   NOT given the word-break:keep-all treatment above -- unlike Chinese,
   Korean text already has spaces between words, so the default break
   behavior already wraps correctly; keep-all would only be needed for a
   script with no word-spacing at all. */
html:lang(ko){--ff-b:'Work Sans','Noto Sans KR',sans-serif;--ff-d:'Work Sans','Noto Sans KR',sans-serif}

/* keep-all's tradeoff: a heading/paragraph's longest unbreakable CJK run
   can now be wider than plain per-character breaking ever produced.
   Flex and grid items default to min-width:auto (their content's
   min-content size) -- harmless before, since free per-character
   breaking kept CJK min-content tiny, but now that can exceed a
   column's available width and force the item (and the viewport)
   wider than intended instead of wrapping, e.g. .page-hero-left,
   .intro-stmt-text. Rather than chasing down every affected container
   individually, this resets it site-wide for zh-tw/zh-cn -- safe even
   for elements that don't need it, since min-width:0 only matters when
   a flex/grid algorithm would otherwise be forced to keep an item at
   its content width; anything with an explicit width or flex-shrink:0
   (icons, badges, buttons) is unaffected either way. */
:lang(zh-tw),:lang(zh-cn){min-width:0}

/* Inline SVG icons inside icon badges (partials/icons.njk), replacing emoji */
.why-icon svg,.map-icon svg,.req-icon svg,.elig-icon svg,.priv-icon svg,.dual-badge-icon svg,.docs-card-icon svg,.fc-cover-icon svg{
  width:20px;height:20px;stroke:var(--gold-text);fill:none;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;flex-shrink:0
}
.map-icon svg{width:16px;height:16px}
.rs-icon svg,.wp-icon svg{width:13px;height:13px;stroke:var(--gold-text);fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}

/* ═══════════════════════════════
   BASE
═══════════════════════════════ */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;font-size:19px}
body{background:var(--white);color:var(--charcoal);font-family:var(--ff-b);line-height:1.6;overflow-x:hidden;-webkit-font-smoothing:antialiased}
img{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
ul{list-style:none}
button{font-family:var(--ff-b);cursor:pointer;border:none;background:none}

/* Branded focus ring for pill/CTA buttons — box-shadow reads cleanly on
   border-radius:50px shapes, unlike the browser's default square outline. */
.btn-primary:focus-visible,.btn-ghost:focus-visible,.btn-gold-pill:focus-visible,
.btn-outline-dark:focus-visible,.btn-gold-cta:focus-visible,.btn-white-outline:focus-visible,
.nav-cta:focus-visible,.form-submit:focus-visible,
.cta-sidebar a:focus-visible,.register-sticky a.rs-btn:focus-visible,
.tier-tab:focus-visible,.filter-btn:focus-visible,.faq-cat-btn:focus-visible,
.mm2h-tier-btn:focus-visible,.subtab:focus-visible,.faq-q:focus-visible,
.nav-drop-btn:focus-visible,.ben-card:focus-visible{
  outline:none;box-shadow:0 0 0 3px var(--gold-bg),0 0 0 5px var(--gold);
}

/* ═══════════════════════════════
   UTILS
═══════════════════════════════ */
.eyebrow{font-family:var(--ff-b);font-size:.63rem;letter-spacing:.18em;text-transform:uppercase;color:var(--gold-text);margin-bottom:.9rem;display:block}
.pad{padding:5.5rem 6vw}

.reveal{opacity:0;transform:translateY(18px);transition:opacity .65s var(--ease),transform .65s var(--ease)}
.reveal.in{opacity:1;transform:none}
.d1{transition-delay:.08s}.d2{transition-delay:.16s}.d3{transition-delay:.24s}
.d4{transition-delay:.32s}.d5{transition-delay:.40s}

/* ═══════════════════════════════
   NAV
═══════════════════════════════ */
#nav{
  position:fixed;top:0;left:0;right:0;z-index:200;
  display:flex;align-items:center;justify-content:space-between;
  height:96px;padding:0 6vw;
  border-bottom:1px solid var(--rule);
  box-shadow:0 2px 20px rgba(0,0,0,.05);
}
/* Blur lives on a pseudo-element, not #nav itself: backdrop-filter on #nav would make it
   a containing block for its position:fixed .nav-links mobile menu, breaking inset:0 so the
   menu only fills the navbar's own (short) box instead of the full screen. */
#nav::before{
  content:'';position:absolute;inset:0;z-index:-1;
  background:rgba(255,255,255,.97);
  backdrop-filter:blur(14px);
}
.nav-logo{font-family:var(--ff-d);font-size:1.5rem;font-weight:600;letter-spacing:.03em;color:var(--charcoal);display:flex;align-items:center;gap:.55rem}
.nav-logo span{color:var(--gold)}
.nav-logo-img{height:80px;width:auto;display:block}
.nav-links{display:flex;align-items:center;gap:2.2rem}
.nav-links>a,.nav-drop-btn{font-size:1rem;font-weight:500;color:var(--muted);transition:color .2s;background:none;border:none;cursor:pointer;padding:0;font-family:var(--ff-b)}
.nav-links>a:hover,.nav-drop-btn:hover{color:var(--charcoal)}
.nav-links a.current{color:var(--gold-text)}
.nav-lang-icon{display:inline-flex;margin-right:.35rem;vertical-align:-3px}
.nav-lang-icon svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.nav-lang-menu{min-width:160px}
.nav-lang-menu a.current{color:var(--gold-dk);font-weight:600;background:var(--gold-bg)}
.nav-dropdown{position:relative}
.nav-drop-menu{
  display:none;position:absolute;top:calc(100% + .8rem);left:50%;transform:translateX(-50%);
  background:var(--white);border:1px solid var(--rule);border-radius:var(--r-md);
  padding:.5rem 0;min-width:210px;
  box-shadow:0 12px 40px rgba(0,0,0,.1);z-index:300;
}
.nav-drop-menu a{display:block;padding:.6rem 1.2rem;font-size:.8rem;color:var(--body);transition:background .15s,color .15s}
.nav-drop-menu a:hover{background:var(--gold-bg);color:var(--gold-dk)}
.nav-drop-menu.open{display:block}
.nav-drop-group-label{display:block;margin-top:.5rem;padding:.55rem 1.2rem .3rem;font-family:var(--ff-b);font-size:.72rem;font-weight:600;letter-spacing:.02em;text-transform:uppercase;color:var(--gold-text);background:var(--gold-bg);border-top:1px solid var(--rule)}
.nav-drop-menu>.nav-drop-group-label:first-child{margin-top:-.5rem;border-top:none;border-top-left-radius:var(--r-md);border-top-right-radius:var(--r-md)}
.nav-cta{background:var(--gold)!important;color:#131313!important;padding:.9rem 2.1rem!important;border-radius:50px;font-size:.95rem!important;font-weight:700!important;letter-spacing:.02em;box-shadow:0 8px 20px rgba(201,168,76,.35);transition:background .2s,transform .15s!important}
.nav-cta:hover{background:var(--gold-dk)!important;transform:translateY(-1px)}
.nav-cta:active{background:var(--gold-dk)!important;transform:scale(.96)!important}
.nav-mob{display:none;flex-direction:column;gap:6px;padding:12px;cursor:pointer;position:relative;z-index:201}
.nav-mob span{display:block;width:24px;height:2px;border-radius:2px;background:var(--charcoal);transition:transform .25s ease,opacity .2s ease}
#nav.scrolled .nav-mob span{background:var(--charcoal)}
/* Open state: bars 1 and 3 rotate into an X, bar 2 fades out. transform/
   opacity only (no layout properties), so this never triggers reflow.
   translateY(8px)/(-8px) = gap(6px)+height(2px), converging both bars on
   the middle bar's center line. Was previously stuck looking identical
   whether the mobile menu was open or closed (design-critique P3). */
.nav-mob--open span:nth-child(1){transform:translateY(8px) rotate(45deg)}
.nav-mob--open span:nth-child(2){opacity:0}
.nav-mob--open span:nth-child(3){transform:translateY(-8px) rotate(-45deg)}

/* ═══════════════════════════════
   HERO
═══════════════════════════════ */
.hero{
  position:relative;min-height:100vh;
  display:flex;flex-direction:column;justify-content:flex-end;
  padding:0 6vw;overflow:hidden;
  background:var(--charcoal) url('/assets/img/hero-klcc-original.jpg') center/cover no-repeat;
}
.hero-overlay{
  position:absolute;inset:0;z-index:1;
  background:
    linear-gradient(to bottom,rgba(14,22,32,.45) 0%,rgba(14,22,32,.72) 55%,rgba(14,22,32,.9) 100%),
    linear-gradient(110deg,rgba(14,22,32,.7) 0%,transparent 60%);
}

.hero-content{position:relative;z-index:3;padding:7.5rem 0 4.5rem;max-width:680px}
.hero-h1{
  /* Matches .page-hero h1 (used on every other page's hero) — was
     clamp(2.5rem,4.9vw,4.4rem), oversized relative to the rest of the
     site and disproportionate to the hero-desc/actions beneath it. */
  font-family:var(--ff-d);font-size:clamp(2.4rem,4.6vw,3.8rem);
  font-weight:300;line-height:1.08;color:#fff;
  margin-bottom:1.3rem;
  animation:fadeUp .8s .2s var(--ease) both;
}
.hero-h1 em{font-style:italic;color:var(--gold-lt)}
.hero-h1 strong{font-weight:600}
.hero-desc{
  font-size:1.03rem;color:rgba(255,255,255,.6);line-height:1.75;
  max-width:480px;margin-bottom:2.2rem;
  animation:fadeUp .8s .3s var(--ease) both;
}
.hero-actions{
  display:flex;align-items:center;gap:1.1rem;flex-wrap:wrap;
  animation:fadeUp .8s .5s var(--ease) both;
}
.btn-primary{
  background:var(--gold);color:#131313;
  font-size:.83rem;font-weight:600;letter-spacing:.04em;
  padding:.85rem 2rem;border-radius:50px;
  display:inline-flex;align-items:center;gap:.5rem;
  border:none;cursor:pointer;
  transition:background .2s,transform .15s,box-shadow .2s;
}
.btn-primary:hover{background:var(--gold-dk);transform:translateY(-2px);box-shadow:0 8px 24px rgba(201,168,76,.3)}
.btn-primary:active{background:var(--gold-dk);transform:scale(.96)}
.btn-ghost{
  font-size:.82rem;font-weight:500;color:rgba(255,255,255,.6);
  padding:.85rem 1.6rem;border-radius:50px;
  border:1.5px solid rgba(255,255,255,.2);
  transition:color .2s,border-color .2s,transform .15s;cursor:pointer;background:none;
}
.btn-ghost:hover{color:#fff;border-color:rgba(201,168,76,.5)}
.btn-ghost:active{color:#fff;border-color:rgba(201,168,76,.5);transform:scale(.96)}

/* stat strip */
.hero-strip{
  position:relative;z-index:3;
  display:flex;
  background:rgba(14,22,32,.75);backdrop-filter:blur(14px);
  border-top:1px solid rgba(255,255,255,.07);
  border-radius:var(--r-lg) var(--r-lg) 0 0;
  margin:0 -6vw;overflow:hidden;
}
.hs-item{flex:1;padding:1.3rem 0;text-align:center;border-right:1px solid rgba(255,255,255,.07)}
.hs-item:last-child{border-right:none}
.hs-v{font-family:var(--ff-d);font-size:2rem;font-weight:700;color:var(--gold);line-height:1}
.hs-l{font-family:var(--ff-b);font-weight:600;font-size:.64rem;letter-spacing:.04em;text-transform:uppercase;color:rgba(255,255,255,.35);margin-top:4px}

@keyframes fadeUp{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:none}}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}

/* ═══════════════════════════════
   TRUST BAR
═══════════════════════════════ */
.trust-bar{
  background:var(--off);border-bottom:1px solid var(--rule);
  padding:1.4rem 6vw;
  display:flex;align-items:center;overflow-x:auto;scrollbar-width:none;
}
.trust-bar::-webkit-scrollbar{display:none}
.t-item{
  display:flex;align-items:center;gap:.55rem;
  font-size:.75rem;font-weight:500;color:var(--muted);
  letter-spacing:.02em;white-space:nowrap;
  padding:0 2rem;border-right:1px solid var(--rule);flex-shrink:0;
}
.t-item:first-child{padding-left:0}
.t-item:last-child{border-right:none}
.t-check{
  width:18px;height:18px;border-radius:50%;
  background:var(--gold-bg);border:1px solid rgba(201,168,76,.3);
  display:flex;align-items:center;justify-content:center;
  color:var(--gold-text);font-size:.65rem;font-weight:700;flex-shrink:0;
}

/* ═══════════════════════════════
   PROGRAMME SECTION WRAPPER
═══════════════════════════════ */
.programmes{background:var(--white);padding:5.5rem 6vw}
.prog-section-header{text-align:center;margin-bottom:3.5rem}
.prog-section-header h2{
  font-size:clamp(1.9rem,3.5vw,3rem);color:var(--charcoal);
}
.prog-section-header h2 em{color:var(--gold-dk)}
.prog-section-header p{font-size:1.18rem;color:var(--muted);margin-top:.7rem;max-width:510px;margin-left:auto;margin-right:auto;line-height:1.75}

/* ═══════════════════════════════
   PVIP INTRO BLOCK
═══════════════════════════════ */
.pvip-block{
  display:grid;grid-template-columns:1fr 1fr;
  gap:0;border-radius:var(--r-xl);overflow:hidden;
  background:var(--charcoal);margin-bottom:2rem;
  box-shadow:0 20px 60px rgba(0,0,0,.12);
}
.pvip-img{
  position:relative;overflow:hidden;min-height:500px;
}
.pvip-img img{
  width:100%;height:100%;object-fit:cover;
  filter:brightness(.75) saturate(.85);
  transition:transform .6s var(--ease);
}
.pvip-block:hover .pvip-img img{transform:scale(1.04)}
.pvip-img-overlay{
  position:absolute;inset:0;
  background:linear-gradient(to right,transparent 60%,rgba(28,28,28,.85));
}
.pvip-content{
  padding:3.2rem 3rem;display:flex;flex-direction:column;justify-content:center;
  background:var(--charcoal);min-width:0;
}
.pvip-content .eyebrow{color:rgba(201,168,76,.8)}
.pvip-content h3{
  font-family:var(--ff-d);font-size:clamp(2rem,3vw,2.8rem);
  font-weight:300;color:#fff;line-height:1.1;margin-bottom:1rem;
}
/* zh-tw/zh-cn add a "（PVIP）" suffix the EN heading doesn't have (spelling
   out the acronym alongside 尊榮高級簽證/尊荣高级签证 for clarity), making
   this string too long to fit one line at the EN-tuned size. Smaller cap
   only -- the 3vw scaling and 2rem floor stay the same, so it still shrinks
   normally on narrower screens. (Root font-size is 19px here, not the
   browser default 16px -- 2.1rem is ~39.9px, not ~33.6px.) */
:lang(zh-tw) .pvip-content h3,:lang(zh-cn) .pvip-content h3{font-size:clamp(2rem,3vw,2rem)}
.pvip-content h3 em{font-style:italic;color:var(--gold-lt)}
.pvip-content p{
  font-size:.87rem;color:rgba(255,255,255,.55);
  line-height:1.75;margin-bottom:1.8rem;
}
.pvip-stats{
  display:flex;margin-bottom:1.8rem;
}
.pstat{flex:1;min-width:0;padding:0 1.1rem;text-align:center;border-left:1px solid rgba(255,255,255,.15)}
.pstat:first-child{border-left:none;padding-left:0}
.pstat-v{font-family:var(--ff-d);font-size:2.6rem;font-weight:700;color:var(--gold);line-height:1}
.pstat-l{font-family:var(--ff-b);font-size:.66rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:rgba(255,255,255,.6);margin-top:5px}
.pvip-feats{display:flex;flex-direction:column;gap:.85rem;margin-bottom:2rem}
.pvip-feat{
  display:flex;align-items:flex-start;gap:.8rem;
  font-size:1.15rem;font-weight:500;color:rgba(255,255,255,.85);line-height:1.55;
}
.pvip-feat::before{content:'✓';color:var(--gold);font-weight:900;font-size:.95rem;flex-shrink:0;width:1.6rem;height:1.6rem;display:flex;align-items:center;justify-content:center;background:rgba(201,168,76,.15);border-radius:50%;margin-top:0}
.btn-gold-pill{
  display:inline-flex;align-items:center;gap:.5rem;
  background:var(--gold);color:#131313;
  font-size:.8rem;font-weight:600;letter-spacing:.04em;
  padding:.8rem 1.8rem;border-radius:50px;
  border:none;cursor:pointer;align-self:flex-start;
  transition:background .2s,transform .15s;
}
.btn-gold-pill:hover{background:var(--gold-dk);transform:translateY(-1px)}
.btn-gold-pill:active{background:var(--gold-dk);transform:scale(.96)}

/* ═══════════════════════════════
   MM2H INTRO BLOCK (image right)
═══════════════════════════════ */
.mm2h-block{
  display:grid;grid-template-columns:1fr 1fr;
  gap:0;border-radius:var(--r-xl);overflow:hidden;
  background:var(--off);
  box-shadow:0 20px 60px rgba(0,0,0,.08);
}
.mm2h-content{
  padding:3.2rem 3rem;display:flex;flex-direction:column;justify-content:center;
  background:var(--off);min-width:0;
}
.mm2h-content h3{
  font-family:var(--ff-d);font-size:clamp(2rem,3vw,2.8rem);
  font-weight:300;color:var(--charcoal);line-height:1.1;margin-bottom:1rem;
}
.mm2h-content h3 em{font-style:italic;color:var(--gold-dk)}
.mm2h-content p{
  font-size:.87rem;color:var(--body);line-height:1.75;margin-bottom:1.8rem;
}
.mm2h-stats{
  display:flex;margin-bottom:1.8rem;
}
.mstat{flex:1;min-width:0;padding:0 1.1rem;text-align:center;border-left:1px solid var(--rule)}
.mstat:first-child{border-left:none;padding-left:0}
.mstat-v{font-family:var(--ff-d);font-size:2.6rem;font-weight:700;color:var(--gold-dk);line-height:1;white-space:nowrap}
.mstat-l{font-family:var(--ff-b);font-size:.66rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--muted);margin-top:5px}
.mm2h-feats{display:flex;flex-direction:column;gap:.85rem;margin-bottom:2rem}
.mm2h-feat{
  display:flex;align-items:flex-start;gap:.8rem;
  font-size:1.15rem;font-weight:500;color:var(--charcoal);line-height:1.55;
}
.mm2h-feat::before{content:'✓';color:var(--gold-text);font-weight:900;font-size:.95rem;flex-shrink:0;width:1.6rem;height:1.6rem;display:flex;align-items:center;justify-content:center;background:rgba(201,168,76,.15);border-radius:50%;margin-top:0}
.btn-outline-dark{
  display:inline-flex;align-items:center;gap:.5rem;
  border:2px solid var(--charcoal);color:var(--charcoal);
  font-size:.8rem;font-weight:600;letter-spacing:.04em;
  padding:.8rem 1.8rem;border-radius:50px;
  background:none;cursor:pointer;align-self:flex-start;
  transition:background .2s,color .2s,transform .15s;
}
.btn-outline-dark:hover{background:var(--charcoal);color:#fff}
.btn-outline-dark:active{background:var(--charcoal);color:#fff;transform:scale(.96)}
.mm2h-img{position:relative;overflow:hidden;min-height:500px}
.mm2h-img img{
  width:100%;height:100%;object-fit:cover;
  filter:brightness(.8) saturate(.9);
  transition:transform .6s var(--ease);
}
.mm2h-block:hover .mm2h-img img{transform:scale(1.04)}

/* ═══════════════════════════════
   COMPANY INTRO
═══════════════════════════════ */
.intro{background:var(--off)}
.intro-inner{
  display:grid;grid-template-columns:1.15fr .85fr;
  gap:4vw;align-items:center;
}
.intro-h2{
  font-family:var(--ff-d);font-size:clamp(1.9rem,3vw,2.8rem);
  font-weight:300;color:var(--charcoal);line-height:1.1;margin-bottom:1.1rem;
}
.intro-h2 em{font-style:italic;color:var(--gold-dk)}
.intro-p{font-size:1.2rem;color:var(--body);line-height:1.85;margin-bottom:.9rem}
.intro-right{display:flex;flex-direction:column;gap:1px;border-radius:var(--r-lg);overflow:hidden;background:var(--rule)}
.intro-stats-row{display:grid;grid-template-columns:repeat(3,1fr);gap:1px}
.intro-stat{
  background:var(--white);padding:1.6rem 1.2rem;
  transition:background .25s;
}
.intro-stat:hover{background:var(--gold-bg)}
.intro-stat-v{
  font-family:var(--ff-d);font-size:2.2rem;font-weight:700;
  color:var(--gold-dk);line-height:1;margin-bottom:.4rem;
}
.intro-stat-l{font-size:.78rem;color:var(--body);line-height:1.4}
.intro-stat-l strong{display:block;font-weight:600;font-size:.82rem;color:var(--charcoal);margin-bottom:.2rem}
.dual-badge{
  background:var(--gold);color:#131313;padding:1.4rem 1.8rem;
  display:flex;align-items:center;gap:.9rem;
}
.dual-badge-icon{font-size:1.3rem;flex-shrink:0}
.dual-badge-t{font-size:.82rem;line-height:1.5}
.dual-badge-t strong{display:block;font-size:.87rem;font-weight:600;margin-bottom:.2rem}

/* ═══════════════════════════════
   WHY MALAYSIA
═══════════════════════════════ */
.why{background:var(--white)}
.why-header{margin-bottom:3rem}
.why-header h2{
  font-size:clamp(1.9rem,3.2vw,2.8rem);color:var(--charcoal);
}
.why-header h2 em{color:var(--gold-dk)}
.why-header p{font-size:1.18rem;color:var(--muted);margin-top:.7rem;max-width:570px;line-height:1.75}

/* Not 6 uniform equal tiles: "Accredited Hospitals" (first card, the one
   with the most concrete, checkable content — real named hospitals) spans
   2 columns as a wide banner; the other 5 stay their normal single-column
   size, auto-flowing into the remaining cells (row1 col3, then row2 and
   row3 — 5 cards don't fill row3's last cell, which is fine: an empty grid
   cell just shows page background, unlike the first version of this layout
   (a 2x2 "feature tile"), which measured out at 615px tall for content that
   only needed ~340px — centering or anchoring that content still left an
   obvious dead zone no matter how it was arranged inside the box. A WIDE
   card lets the same content use width instead of needing to fill height,
   so it naturally lands close to a normal card's height with no box to
   fight. Card must be first in DOM order for auto-placement to reserve its
   2-column cell before any other item claims it — not an nth-child pin, so
   no specificity fight with the mobile layout either. */
.why-grid{
  /* align-items:start, not the grid default (stretch): row 1 pairs the
     taglist-bearing first card against a plain one, and later rows mix
     short/long descriptions too -- stretch forced every shorter card to
     match its row's tallest, leaving a large dead gap below the short
     card's own content. Sizing each card to its own content instead reads
     as an intentional light masonry rhythm, not a bug. */
  display:grid;grid-template-columns:repeat(3,1fr);gap:1.4rem;align-items:start;
}
@media(min-width:1025px){
  /* First card (hospitals + a taglist row on top of the usual title+desc)
     runs noticeably taller than every plain card -- it used to share row 1
     with just card 2, which either stretched card 2 to match (dead space
     inside it) or, once that stretch was removed, left card 2 looking
     small and orphaned with a visible gap below it before row 2 (measured
     ~115px). Giving it the full width instead means it's never paired
     against a shorter card at all -- same fix already applied to the last
     card below, extended to the other card whose content genuinely runs
     longer than the rest. Units: 3(first, full row)+1+1+1+1+2(last)=9,
     exactly 3 full rows -- last card spans 2 so its row (with the 5th
     card) fills evenly instead of leaving a lone card next to a gap. */
  .why-grid .why-card:first-child{grid-column:1/-1}
  .why-grid .why-card:first-child p{max-width:60ch}
  .why-grid .why-card:last-child{grid-column:span 2}
  .why-grid .why-card:last-child p{max-width:60ch}
}
.why-card{
  background:var(--off);border-radius:var(--r-md);
  padding:2.3rem 2.1rem;
  box-shadow:0 1px 2px rgba(0,0,0,.04);
  transition:transform .3s var(--ease),box-shadow .3s var(--ease);
  display:flex;flex-direction:column;
}
.why-card:hover{transform:translateY(-6px);box-shadow:0 20px 40px rgba(0,0,0,.1)}
.why-card.dark{background:var(--charcoal);box-shadow:none}
.why-card.dark:hover{box-shadow:0 20px 44px rgba(0,0,0,.35)}
.why-card-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.4rem}
.why-card-icon{position:relative;width:52px;height:52px;color:var(--gold-text)}
.why-seal-ring{position:absolute;inset:0;width:100%;height:100%}
.why-seal-glyph{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}
.why-seal-glyph svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.why-card-num{
  display:flex;align-items:center;gap:.6rem;
  font-family:var(--ff-d);font-weight:300;font-size:1.9rem;line-height:1;
  color:rgba(28,28,28,.13);
}
.why-card-num::before{content:'';display:block;width:20px;height:1px;background:currentColor}
.why-card.dark .why-card-icon{color:var(--gold-lt)}
.why-card.dark .why-card-num{color:rgba(255,255,255,.16)}
.why-card h3{font-size:1.05rem;font-weight:600;color:var(--charcoal);margin-bottom:.6rem}
.why-card.dark h3{color:#fff}
.why-card p{font-size:1.05rem;color:var(--body);line-height:1.7}
.why-card.dark p{color:rgba(255,255,255,.6)}
/* Feature card: bigger icon/type for weight, no width cap on the paragraph
   (was 32ch for the old tall 2x2 shape — at this card's real ~2x width the
   same sentence wraps to 1-2 lines instead of 3-4, which is most of why this
   version's height lands close to a normal single-column card's instead of
   needing 615px to fill). Hospital tags stay in normal flow at the bottom,
   no margin-top:auto needed — nothing to push down anymore. */
.why-card-feature .why-card-icon{width:68px;height:68px}
.why-card-feature .why-card-num{font-size:2.6rem}
.why-card-feature h3{font-size:1.55rem;margin-bottom:.9rem}
.why-card-feature p{font-size:1.2rem;max-width:60ch}
.why-card-taglist{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:1.6rem}
.why-card-taglist span{font-family:var(--ff-b);font-size:.7rem;font-weight:600;letter-spacing:.02em;color:rgba(255,255,255,.75);background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.14);border-radius:50px;padding:.4rem .9rem}
@media(max-width:1024px){
  .why-grid{grid-template-columns:repeat(2,1fr)}
  .why-card-feature .why-card-icon{width:52px;height:52px}
  .why-card-feature .why-card-num{font-size:1.9rem}
  .why-card-feature h3{font-size:1.05rem;margin-bottom:.6rem}
  .why-card-feature p{font-size:1.05rem;max-width:none}
}
@media(max-width:640px){.why-grid{grid-template-columns:1fr}}
@media(max-width:640px){.intro-stats-row{grid-template-columns:1fr}}

/* ═══════════════════════════════
   HOW IT WORKS
═══════════════════════════════ */
.process{background:var(--off)}
.process-header{text-align:center;margin-bottom:3.5rem}
.process-header h2{
  font-size:clamp(1.9rem,3vw,2.8rem);color:var(--charcoal);
}
.process-header h2 em{color:var(--gold-dk)}
.process-header p{font-size:1.15rem;color:var(--muted);margin-top:.7rem;max-width:460px;margin-left:auto;margin-right:auto}

/* Base timeline card — light, always fully visible (no scroll-progressive dimming).
   This is what MM2H/Employment Pass/Digital Nomad/APEC actually use. Tokenized
   (not hardcoded) so it automatically goes dark+cream on PVIP via theme-dark-premium,
   the same trick used for .features above. */
.timeline-wrap{
  max-width:700px;margin:0 auto;background:var(--white);border:1px solid var(--rule);
  border-radius:var(--r-xl);padding:3rem 2.5rem;position:relative;overflow:hidden;
  box-shadow:0 14px 50px rgba(0,0,0,.04);
}
/* Homepage-only KLCC watermark (see .tl-klcc-mark in index.njk). Path data
   traced from a real Petronas Towers photo via automated silhouette
   extraction (see the git history / earlier notes for sourcing), not
   hand-guessed, so the stepped taper and skybridge position are the real
   building's. Solid fill + one element-level opacity (not fill:rgba(...)
   per shape) — the strut triangle overlaps each tower's base, and per-shape
   alpha double-blends there, leaving a visible seam; compositing the whole
   mark as one flat layer first avoids it.
   Reuses the site's existing .reveal/IntersectionObserver fade+rise (same
   one the section header uses) rather than a bespoke scroll-threshold
   system: a multi-landmark version of this that revealed one mark per step
   was tried and reverted — it needed a large reserved dead-space band at
   the card's bottom to avoid colliding with the step text, and once
   scrolling settled, the payoff was three small icons floating over a
   mostly-empty band rather than one clean watermark. This gets the same
   "appears as you scroll to it" motion at zero structural cost: no
   reserved space, because the mark just fades in at its normal corner spot
   as the whole section enters view.
   `.tl-klcc-mark.reveal.in` (specificity 0,0,3,0) intentionally outweighs
   the generic `.reveal.in{opacity:1}` (0,0,2,0) — a plain fade to opacity 1
   would make this far too loud for a background watermark; this keeps the
   motion but ends at the mark's own low target opacity instead. */
.tl-klcc-mark{
  /* .timeline-wrap's height is intrinsic (sized by its content, not set),
     so percentage height can't resolve against it reliably — sized as a
     fixed px instead, picked to clear half of the card's real measured
     desktop height (~382px) with margin. */
  position:absolute;right:2px;bottom:-3px;height:210px;width:auto;
  fill:#C9A84C;pointer-events:none;z-index:0;
  filter:drop-shadow(0 8px 12px rgba(0,0,0,.4)) drop-shadow(0 2px 3px rgba(0,0,0,.45));
}
.tl-klcc-mark.reveal{opacity:0;transform:translateY(16px)}
.tl-klcc-mark.reveal.in{opacity:.11;transform:none}
/* PVIP-only: Menara Kuala Lumpur watermark, same photo-traced treatment —
   reference photo "Menara Kuala Lumpur (Kuala Lumpur Tower) (18972745702)",
   Wikimedia Commons. Real proportions are far more slender than the twin
   towers (the actual tower is a thin needle with a bulbous saucer pod, not
   a stepped block), which is exactly what makes it read as a different
   landmark now instead of a re-skinned copy of the KLCC mark. PVIP's card
   is dark (theme-dark-premium), so the same treatment as the homepage's
   dark card applies here too. */
.tl-menara-mark{
  /* PVIP's card runs taller than the homepage's (longer step copy), so this
     needs a bigger fixed height to clear half of ITS real measured desktop
     height (~511px) with margin. Solid fill + element opacity for the same
     reason as the other two marks (consistent technique, even though this
     one's a single non-overlapping path).
     Opacity bumped from .11 to .2 and nudged in from the edge (14px→28px):
     at .11 the shape all but disappeared against the dark card — it's a
     much thinner silhouette than the twin towers or the hibiscus (a single
     slender needle vs. two wide towers or a full flower), so the same
     opacity that reads fine on those reads as barely-there here. Nudging
     off right:14px also clears the card's own rounded bottom-right corner,
     which was clipping a sliver of the tower's base at that position. */
  position:absolute;right:28px;bottom:-3px;height:280px;width:auto;
  fill:#C9A84C;opacity:.2;pointer-events:none;z-index:0;
  filter:drop-shadow(0 8px 12px rgba(0,0,0,.45)) drop-shadow(0 2px 3px rgba(0,0,0,.5));
}
/* MM2H-only: Bunga Raya (hibiscus, Malaysia's national flower) watermark —
   traced from the site's own logo mark (see the SVG comment in mm2h.njk for
   how). Several petal/star/dot shapes overlap each other, so the colour is
   applied once via `opacity` on the whole element rather than per-shape
   `fill:rgba(...)` — the latter double-blends wherever two shapes overlap,
   leaving visible seams; a solid fill + one element-level opacity composites
   the whole mark as a single flat layer first, so overlaps stay invisible.
   MM2H's card stays the plain light/white card (unlike homepage/PVIP's dark
   cards), so this uses a higher opacity and a lighter shadow — matches the
   gold radial glows already used elsewhere on light cards (e.g.
   .req-box::before). Sized to clear half of MM2H's own measured desktop
   card height (~490px), same convention as the other two landmarks. */
.tl-hibiscus-mark{
  position:absolute;right:10px;bottom:-4px;height:250px;width:auto;
  fill:#C9A84C;opacity:.16;pointer-events:none;z-index:0;
  filter:drop-shadow(0 8px 12px rgba(28,28,28,.14)) drop-shadow(0 2px 3px rgba(28,28,28,.1));
}
.tl-track{display:flex;flex-direction:column;position:relative}
.tl-item{display:flex;gap:1.3rem;position:relative;padding-bottom:2.2rem}
.tl-item:last-child{padding-bottom:0}
.tl-line{position:absolute;left:27px;top:56px;bottom:0;width:2px;background:var(--rule)}
/* Scroll-linked progress: same box as .tl-line so it fills the identical
   length, but grown via scaleY instead of a measured height so it needs
   no JS math beyond a 0–1 progress value. main.js sets --tl-progress on
   the .tl-track as it scrolls through view; scaleY(0) is invisible until
   then, so nothing to gate behind prefers-reduced-motion (it's 1:1 with
   the user's own scroll input, not an independent animation). Hidden in
   the desktop zigzag layout below, which draws its own progress line. */
.tl-line-fill{
  position:absolute;left:27px;top:56px;bottom:0;width:2px;background:var(--gold-dk);
  transform-origin:top;transform:scaleY(var(--tl-progress,0));transition:transform .1s linear;
}
/* --gold-text, not --gold-dk: this base rule is MM2H's actual rendered color
   (its timeline stays the plain light card, per the comment below — nothing
   overrides it there), 3.11:1 on --gold-bg on mobile, below the 4.5:1 AA
   floor (Lighthouse a11y audit, mobile). Homepage's #process and the zigzag
   active/inactive states already override this with their own colors, so
   raising the fallback here only helps wherever it's still in effect. */
.tl-dot{
  width:56px;height:56px;border-radius:50%;flex-shrink:0;
  background:var(--gold-bg);border:1.5px solid rgba(201,168,76,.3);
  display:flex;align-items:center;justify-content:center;
  font-family:var(--ff-b);font-size:.72rem;color:var(--gold-text);position:relative;z-index:2;
}
.tl-body{flex:1;padding-top:.3rem}
.tl-title{font-size:1rem;font-weight:600;color:var(--charcoal);margin-bottom:.4rem}
.tl-desc{font-size:.82rem;color:var(--muted);line-height:1.6;max-width:460px}

/* Homepage-only: dark card. #process exists only on the homepage's timeline
   section — MM2H and PVIP use the same .zigzag layout/pin mechanics (see the
   min-width:900px block below, all class-scoped, no #process dependency)
   but keep their OWN card color untouched by this block: MM2H stays the
   plain light card (nothing overrides var(--white) there), and PVIP's base
   .timeline-wrap is already dark via its own body.theme-dark-premium token
   swap further down this file.
   :where(#process) rather than plain #process: an ID selector outweighs
   any number of classes, so a bare #process here would beat the zigzag
   block's class-only overrides below (max-width:1180px, the active-dot
   gold fill, etc) even though those come later and are meant to win —
   :where() keeps the exact same scoping with zero specificity, so normal
   class-vs-class cascade rules decide instead. */
:where(#process) .timeline-wrap{max-width:680px;background:var(--charcoal);border:1px solid rgba(201,168,76,.15);box-shadow:none}
:where(#process) .tl-line{background:rgba(201,168,76,.14)}
:where(#process) .tl-line-fill{background:var(--gold-lt)}
:where(#process) .tl-dot{background:rgba(201,168,76,.1);border-color:rgba(201,168,76,.35);color:var(--gold-lt)}
:where(#process) .tl-title{color:#fff}
:where(#process) .tl-desc{color:rgba(255,255,255,.55)}

/* Structural — shared by every page that renders a .timeline-wrap.zigzag
   (homepage, MM2H, PVIP), so these are class-scoped rather than tied to the
   homepage's #process id. Hides the zigzag SVG by default; the landscape
   media query below turns it on. */
.tl-zigzag-path{display:none}

/* Pin the timeline in view while its own internal scroll room (set below, desktop
   only, height computed in JS to match real content) drives the progress bar —
   mobile gets no extra height, so this is a no-op there and the section just
   scrolls normally with the rest of the page. */
.tl-pin-inner{display:flex;align-items:center;justify-content:center}

/* Desktop/landscape-only zigzag: 5-6 steps in a single horizontal band
   (alternating up/down) instead of one long vertical scroll, connected by a
   zigzag line matching the step order. Falls back to the standard vertical
   .tl-track below 900px (no room for a 5-6 column zigzag) AND on portrait
   screens regardless of width (iPad Pro portrait: 1024x1366, and similar):
   a horizontal zigzag doesn't fit a portrait canvas any better than it fits
   a narrow phone, and reusing the same vertical layout + scroll-fill line
   mobile already uses is simpler and more robust than trying to make the
   pin+scrub effect behave on an odd aspect ratio it wasn't built for. */
@media(min-width:900px) and (orientation:landscape){
  .tl-pin-outer{position:relative}
  /* top offset clears the fixed nav (--nav-h set by JS); .tl-pin-outer's own
     height is also set by JS from measured content, not guessed here. */
  .tl-pin-inner{position:sticky;top:calc(var(--nav-h, 90px) + 1.5rem)}
  /* Padding trimmed from 4.5rem/2.5rem: on a shorter (but still landscape)
     browser window this is the difference between the card fitting below
     the nav — and getting the interactive pin — or not (see pinDisabled()
     in main.js, which measures this exact height). */
  .timeline-wrap.zigzag{max-width:1360px;padding:2.5rem 2rem 1.25rem}
  /* Scroll-linked progress: JS drives these via classes as the pinned section
     is scrubbed — desktop only, since the JS that toggles .active never runs
     below 900px (no pin/zigzag there), so these must stay inside this query. */
  .zigzag .tl-dot{transition:all .4s var(--ease)}
  .zigzag .tl-item:not(.active) .tl-dot{background:rgba(201,168,76,.04);border-color:rgba(201,168,76,.16);color:rgba(201,168,76,.4)}
  /* Fixed dark text, not var(--charcoal): that token is PVIP's light cream
     foreground colour (theme-dark-premium inverts it), which would put
     low-contrast light text on this gold-filled dot on that page — the
     number needs to read dark against gold on every page, not just the
     ones where --charcoal happens to still mean "dark". */
  .zigzag .tl-item.active .tl-dot{background:var(--gold);border-color:var(--gold);color:#1C1C1C;box-shadow:0 0 0 8px rgba(201,168,76,.13)}
  .zigzag .tl-body{transition:opacity .4s var(--ease),transform .4s var(--ease)}
  .zigzag .tl-item:not(.active) .tl-body{opacity:0;transform:translateY(16px);pointer-events:none}
  /* Delayed on the way in only, so the text visibly follows the line reaching
     the dot rather than popping in at the same instant; no delay on the way out. */
  .zigzag .tl-item.active .tl-body{opacity:1;transform:none;transition-delay:.12s}
  .zigzag .tl-line,.zigzag .tl-line-fill{display:none}
  .tl-zigzag-path{display:block;position:absolute;inset:0;width:100%;height:100%}
  .tl-zigzag-path path{fill:none;stroke-linecap:round}
  .tl-zigzag-path-bg{stroke:rgba(201,168,76,.16);stroke-width:1.5}
  .tl-zigzag-path-fg{stroke:var(--gold);stroke-width:2}
  .zigzag .tl-track{flex-direction:row;align-items:flex-start;gap:.6rem;position:relative}
  .zigzag .tl-item{
    flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;text-align:center;
    gap:0;padding-bottom:0;
  }
  .zigzag .tl-item.down{margin-top:4rem}
  .zigzag .tl-body{padding-top:.7rem;display:flex;flex-direction:column;align-items:center}
  .zigzag .tl-title{min-height:3rem}
  .zigzag .tl-desc{max-width:34ch}
  /* html:lang(zh-tw)/zh-cn sets word-break:keep-all site-wide (0732f98) so
     compound words like 設計/持有 don't split mid-word -- correct for prose,
     but it also stops these short step descriptions from breaking at all
     until they hit a punctuation boundary. With align-items:center, an
     unbreakable run's shrink-to-fit width can exceed this item's own
     ~200px flex column, spilling text into neighbouring columns (measured:
     item 3's .tl-desc was 312px wide against a 200px column). Scoped back
     to normal here only -- safe since these are short step labels, not
     the compound-word-sensitive prose keep-all exists for. */
  .zigzag .tl-title,.zigzag .tl-desc{word-break:normal}
}

/* ═══════════════════════════════
   SOCIAL PROOF
═══════════════════════════════ */
.proof{background:var(--white)}
.proof-inner{display:grid;grid-template-columns:1fr 1.4fr;gap:5vw;align-items:start}
.proof-left h2{
  font-family:var(--ff-d);font-size:clamp(1.9rem,3vw,2.8rem);
  font-weight:300;color:var(--charcoal);line-height:1.1;margin-bottom:2rem;
}
.proof-left h2 em{font-style:italic;color:var(--gold-dk)}
.google-rating-link{display:inline-flex;align-items:center;gap:.4rem;margin:-1.2rem 0 1.8rem;font-size:.85rem;font-weight:600;color:var(--gold-dk);text-decoration:none;letter-spacing:.01em}
.google-rating-link:hover{text-decoration:underline}
.pnums{display:flex;flex-direction:column;gap:0}
.pn{
  display:flex;align-items:flex-start;gap:1rem;
  padding:1.3rem 0;border-bottom:1px solid var(--rule);
}
.pn:last-child{border-bottom:none}
/* width (not min-width) so every row's number box is the same size regardless
   of digit count -- "300+" renders ~127px at this font-size/weight, well past
   the old min-width:72px floor, so each row's box was sizing to its own
   content and .pn-l's left edge drifted by row (measured 205-239px across
   the three rows before this fix). Pre-existing on English too, not a
   Chinese-specific bug -- just more visually obvious there. */
.pn-v{font-family:var(--ff-d);font-size:2.7rem;font-weight:700;color:var(--gold-dk);line-height:1;flex-shrink:0;width:132px}
.pn-l{font-size:.82rem;color:var(--body);padding-top:.35rem;line-height:1.45}
.pn-l strong{display:block;font-weight:600;font-size:.86rem;color:var(--charcoal);margin-bottom:.1rem}
/* CJK glyphs carry more built-in vertical padding than this Latin-tuned
   font's numerals, so .pn-l's flex-start + padding-top:.35rem (correct for
   English) reads as visibly un-aligned on zh-tw/zh-cn -- the label sits
   noticeably below the stat number's top edge. align-items:center sidesteps
   the metric mismatch instead of chasing a magic-number offset per script. */
:lang(zh-tw) .pn,:lang(zh-cn) .pn{align-items:center}
.testis{position:relative;min-height:300px}
.testi-set{
  display:grid;grid-template-columns:1fr;gap:1rem;
  position:absolute;inset:0;
  opacity:0;transform:translateY(16px);
  transition:opacity .55s var(--ease),transform .55s var(--ease);
  pointer-events:none;
}
.testi-set.active{
  opacity:1;transform:none;position:relative;pointer-events:all;
}
.testi{
  background:var(--off);
  border:1px solid var(--rule);border-left:3px solid rgba(201,168,76,.3);
  border-radius:var(--r-lg);padding:1.5rem 1.6rem;
  transition:background .25s;
}
.testi:hover{background:var(--gold-bg)}
.testi.pending{border-left-style:dashed;border-left-color:var(--muted)}
.testi-q{
  font-family:var(--ff-d);font-size:1rem;font-style:italic;
  font-weight:300;color:var(--charcoal);line-height:1.55;margin-bottom:.85rem;
  /* Cap each quote so 3 stacked cards still fit roughly one screen even
     when a review runs long (e.g. multi-paragraph Chinese testimonials) —
     the full original text stays readable via internal scroll instead of
     being cut with an ellipsis. Short quotes never hit this height, so
     English/short cards render identically to before. */
  max-height:7.75rem;overflow-y:auto;padding-right:.4rem;
}
.testi-q::-webkit-scrollbar{width:4px}
.testi-q::-webkit-scrollbar-thumb{background:rgba(201,168,76,.4);border-radius:10px}
.testi-q::-webkit-scrollbar-track{background:transparent}
.testi-q::before{content:'\201C';color:var(--gold-dk);font-size:1.4rem;line-height:0;vertical-align:-.28em;margin-right:.1rem}
.testi.pending .testi-q{color:var(--muted)}
.testi-meta{display:flex;align-items:center;gap:.7rem}
.testi-av{
  width:32px;height:32px;border-radius:50%;
  background:var(--gold-bg);border:1px solid rgba(201,168,76,.2);
  display:flex;align-items:center;justify-content:center;
  font-family:var(--ff-d);font-size:.85rem;color:var(--gold-text);flex-shrink:0;
}
.testi-name{font-size:.8rem;font-weight:600;color:var(--charcoal)}
.testi-from{font-size:1rem;color:var(--muted)}
.testi-tag{
  margin-left:auto;font-family:var(--ff-b);font-size:.6rem; /* was .52rem = 9.88px, below the 11px accessibility floor */
  letter-spacing:.09em;text-transform:uppercase;
  background:var(--gold-bg);border:1px solid rgba(201,168,76,.25);
  color:var(--gold-text);padding:.18rem .5rem;border-radius:50px;
}
.testi-tag.pending{background:var(--light);border-color:var(--rule);color:var(--muted)}
.testi-dots{display:flex;gap:.45rem;margin-top:1.4rem}
.t-dot{
  width:7px;height:7px;border-radius:50%;background:var(--rule);
  cursor:pointer;border:none;padding:0;transition:all .3s;
}
.t-dot.active{background:var(--gold);width:22px;border-radius:5px}

/* ═══════════════════════════════
   CONTACT FORM + MAP
═══════════════════════════════ */
.contact-block{background:var(--off)}
.contact-header{text-align:center;margin-bottom:3rem}
.contact-header h2{
  font-size:clamp(1.9rem,3.2vw,2.8rem);color:var(--charcoal);
}
.contact-header h2 em{color:var(--gold-dk)}
.contact-header p{font-size:1.16rem;color:var(--muted);margin-top:.7rem;max-width:530px;margin-left:auto;margin-right:auto;line-height:1.75}
.contact-grid{display:grid;grid-template-columns:1.1fr 1fr;gap:1.5rem;align-items:start}
.form-card{
  background:var(--white);border:1px solid var(--rule);
  border-radius:var(--r-xl);padding:2.4rem;
}
.form-row{display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1.1rem}
.form-field{display:flex;flex-direction:column;gap:.4rem}
.form-field.full{grid-column:1/-1}
.form-field label{font-size:.78rem;font-weight:500;color:var(--charcoal)}
.required-mark{color:var(--err-text)}
.form-field input,.form-field select,.form-field textarea{
  border:1px solid var(--rule);border-radius:var(--r-sm);
  padding:.7rem .9rem;font-size:.85rem;font-family:var(--ff-b);
  color:var(--charcoal);background:var(--white);
  transition:border-color .2s,box-shadow .2s;outline:none;
}
.form-field input:focus,.form-field select:focus,.form-field textarea:focus{
  border-color:var(--gold);box-shadow:0 0 0 3px rgba(201,168,76,.12);
}
/* Only flags a field once it has real (but invalid) content — pairing
   :invalid with :not(:placeholder-shown) excludes empty untouched required
   fields, which are also :invalid but shouldn't read as an error yet. */
.form-field input:invalid:not(:placeholder-shown){
  border-color:var(--err-text);box-shadow:0 0 0 3px rgba(179,38,30,.1);
}
.form-field textarea{resize:vertical;min-height:80px;font-family:var(--ff-b)}
.form-submit{
  width:100%;margin-top:.6rem;
  background:var(--gold);color:#131313;
  font-size:.86rem;font-weight:600;letter-spacing:.04em;
  padding:.9rem;border-radius:50px;border:none;cursor:pointer;
  transition:background .2s,transform .15s;
}
.form-submit:hover{background:var(--gold-dk);transform:translateY(-1px)}
.form-submit:disabled{opacity:.6;cursor:default;transform:none}
.form-note{font-size:1.04rem;color:var(--muted);text-align:center;margin-top:.9rem;line-height:1.65}

.form-success{text-align:center}
.form-success-icon{
  width:56px;height:56px;border-radius:50%;margin:0 auto 1.2rem;
  background:var(--gold-bg);border:1px solid rgba(201,168,76,.2);
  display:flex;align-items:center;justify-content:center;
  font-size:1.6rem;color:var(--gold-text);
}
.form-success .form-step-title{margin-bottom:.6rem}
.form-success .form-step-sub{margin-bottom:0}

.form-error{text-align:center}
.form-error-icon{
  width:56px;height:56px;border-radius:50%;margin:0 auto 1.2rem;
  background:var(--err-bg);border:1px solid var(--err-border);
  display:flex;align-items:center;justify-content:center;
  font-size:1.6rem;font-weight:700;color:var(--err-text);
}
.form-error .form-step-title{margin-bottom:.6rem}
.form-error .form-step-sub{margin-bottom:1.4rem}
.form-error-actions{display:flex;gap:.8rem;justify-content:center;flex-wrap:wrap}
.form-error-actions .form-submit{width:auto;padding:.9rem 1.8rem}
.form-error-actions .btn-outline-dark{padding:.9rem 1.8rem}
@media(max-width:600px){.form-error-actions{flex-direction:column}.form-error-actions .form-submit,.form-error-actions .btn-outline-dark{width:100%;text-align:center}}

/* Four-step contact form: steps 1-3 (goal, financial fit, property plan) are
   short, step 4 (fields) is tall. min-height keeps the card from visibly
   shrinking next to the map on the earlier, shorter steps. */
.form-card{min-height:560px;display:flex;flex-direction:column;justify-content:center}
.form-step-label{
  display:block;font-family:var(--ff-b);font-size:.62rem;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:var(--gold-text);margin-bottom:.6rem;
}
.form-step-title{font-size:1.4rem;color:var(--charcoal);margin-bottom:.6rem}
.form-step-sub{font-size:.82rem;color:var(--muted);line-height:1.6;margin-bottom:1.4rem}
.form-step-sub em{font-style:normal;color:var(--gold-text)}
/* Homepage's old 4-step-quiz teaser card is now a partners showcase —
   same .form-card shell (the quiz itself moved to /free-consultation/,
   linked from CTAs elsewhere on the page/site, not from this card). */
.partners-eyebrow{font-family:var(--ff-b);font-size:.62rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--gold-text);margin-bottom:.6rem;display:block}
/* Only 2 partners exist today, and this card borrows its height from the
   (naturally tall — map embed + address rows) map-card next to it via
   .form-card's own min-height:560px. A thin row of small logos left most
   of that height empty — sized up (bigger logo, a name label under each)
   instead of boxing them in cards, so the space fills without reading as
   two empty tiles waiting for content. A plain rule between them (not a
   border/background per item) keeps the two readable as a pair.
   justify-content:flex-start (overriding .form-card's own centering,
   which is right for the 4-step quiz shell this card reuses but pinning
   this card's eyebrow/title to the top read better) plus the bigger
   logo/margin below still leaves a similar amount of dead space overall,
   just moved from "all above the content" to "a smaller amount below
   it" -- closer to how the naturally-tall map-card fills the same row. */
.partners-card{justify-content:flex-start}
.partners-row{display:flex;align-items:center;gap:2.2rem;flex-wrap:wrap;margin-top:4rem}
/* Hovering/tapping a logo swaps the map-card on the right (id="partnerMapEmbed"
   etc.) to that partner's own office details — see partnerData in main.js.
   Defaults to MYPVIP (.partner-active on load); mouseleave/blur reverts to
   whichever partner was last clicked/tapped, not always back to MYPVIP, so a
   touch-device choice sticks instead of springing back immediately. */
.partner-item{
  position:relative;cursor:pointer;
  display:flex;flex-direction:column;align-items:center;gap:1.1rem;
}
.partners-divider{width:1px;align-self:stretch;background:var(--rule);flex-shrink:0}
/* Once the row runs out of width and the two items wrap into a vertical
   stack (narrow phones), a vertical rule between them reads as a stray
   line rather than a divider — drop it there. */
@media(max-width:600px){.partners-divider{display:none}}
.partner-item-logo{height:90px;width:auto;max-width:100%;display:block;filter:grayscale(1);opacity:.7;transition:filter .2s,opacity .2s}
.partner-item.partner-active .partner-item-logo,
.partner-item:hover .partner-item-logo,
.partner-item:focus-visible .partner-item-logo{filter:grayscale(0);opacity:1}
.partner-item-name{font-family:var(--ff-b);font-size:.8rem;font-weight:600;letter-spacing:.03em;color:var(--muted);text-align:center;transition:color .2s}
.partner-item.partner-active .partner-item-name,
.partner-item:hover .partner-item-name,
.partner-item:focus-visible .partner-item-name{color:var(--gold-text)}
.goal-options{display:flex;flex-direction:column;gap:.7rem;margin-bottom:1.6rem}
.goal-opt{
  text-align:left;width:100%;border:1px solid var(--rule);background:var(--white);
  border-radius:var(--r-sm);padding:.9rem 1.1rem;font-size:.9rem;font-weight:500;
  color:var(--charcoal);cursor:pointer;transition:border-color .2s,background .2s,transform .15s;
}
.goal-opt:hover{border-color:var(--gold);background:var(--gold-bg);transform:translateY(-1px)}
.goal-opt small{display:block;font-size:.74rem;font-weight:400;color:var(--muted);margin-top:.2rem}
.form-back{
  background:none;border:none;cursor:pointer;padding:0;margin-bottom:.9rem;
  font-size:.8rem;font-weight:600;color:var(--muted);transition:color .2s;display:block;
}
.form-back:hover{color:var(--gold-text)}

/* Programme-of-interest multi-select: native checkboxes visually hidden,
   their <span> styled as toggle pills so it reads consistently with .goal-opt. */
.programme-pills{display:flex;flex-wrap:wrap;gap:.6rem}
.pill-check{cursor:pointer}
.pill-check input{position:absolute;opacity:0;width:0;height:0}
.pill-check span{
  display:inline-block;border:1px solid var(--rule);background:var(--white);
  border-radius:50px;padding:.5rem 1rem;font-size:.8rem;font-weight:500;
  color:var(--charcoal);transition:border-color .2s,background .2s,color .2s;
}
.pill-check:hover span{border-color:var(--gold)}
.pill-check input:checked + span{
  background:var(--gold);border-color:var(--gold);color:#131313;font-weight:600;
}
.pill-check input:focus-visible + span{box-shadow:0 0 0 3px rgba(201,168,76,.3)}

.map-card{
  border-radius:var(--r-xl);overflow:hidden;
  border:1px solid var(--rule);background:var(--white);
  display:flex;flex-direction:column;
}
.map-embed{position:relative;width:100%;height:300px;background:var(--light)}
.map-embed iframe{width:100%;height:100%;border:0;display:block}
.map-details{padding:1.6rem 1.8rem;flex:1;display:flex;flex-direction:column;gap:1.1rem}
.map-row{display:flex;align-items:flex-start;gap:.9rem}
.map-row[hidden]{display:none}
.map-icon{
  width:36px;height:36px;border-radius:50%;flex-shrink:0;
  background:var(--gold-bg);border:1px solid rgba(201,168,76,.2);
  display:flex;align-items:center;justify-content:center;font-size:.9rem;color:var(--gold-text);
}
.map-row-title{font-size:.82rem;font-weight:600;color:var(--charcoal);margin-bottom:.15rem}
.map-row-sub{font-size:.78rem;color:var(--muted);line-height:1.5}
.map-links{display:flex;flex-wrap:wrap;gap:.4rem 1.4rem;margin-top:.3rem}
.map-directions{
  display:inline-flex;align-items:center;gap:.5rem;
  font-size:.78rem;font-weight:600;color:var(--gold-text);
  border-bottom:1px solid rgba(201,168,76,.3);padding-bottom:2px;
  align-self:flex-start;margin-top:0;
}
.map-directions[hidden]{display:none}

/* ═══════════════════════════════
   FOOTER
═══════════════════════════════ */
footer{background:var(--off);border-top:1px solid var(--rule);padding:4rem 6vw 2rem}
.footer-top{display:grid;grid-template-columns:2fr 1fr 1fr;gap:3rem;margin-bottom:2.5rem}
.footer-logo{font-family:var(--ff-d);font-size:1.5rem;font-weight:600;color:var(--charcoal);margin-bottom:.9rem;display:flex;align-items:center;gap:.55rem}.footer-logo span{color:var(--gold)}
.footer-logo-img{height:72px;width:auto;display:block}

.footer-brand p{font-size:.95rem;color:var(--muted);line-height:1.7;max-width:300px;margin-bottom:1.2rem}
.footer-social{display:flex;gap:.5rem}
.footer-social a{
  width:30px;height:30px;border-radius:50%;
  border:1px solid var(--rule);background:var(--white);
  display:flex;align-items:center;justify-content:center;
  color:var(--muted);
  transition:border-color .2s,color .2s,background .2s;
}
.footer-social a svg{width:15px;height:15px;display:block}
.footer-social a:hover{border-color:var(--gold);color:var(--gold-text);background:var(--gold-bg)}
.footer-col h3{font-family:var(--ff-b);font-size:.75rem;letter-spacing:.14em;text-transform:uppercase;color:var(--charcoal);margin-bottom:.9rem}
.footer-col ul{display:flex;flex-direction:column;gap:.55rem}
.footer-col ul a{font-size:.8rem;color:var(--muted);transition:color .2s}
.footer-col ul a:hover{color:var(--gold-text)}
/* Government/licensing credential strip (MYPVIP, Visa Premium Malaysia,
   the Malaysian coat of arms, Imigresen Malaysia, MOTAC, and MM2H) --
   one flattened image pulled from the old live site rather than
   recreated, since these are official government marks. */
.footer-credentials{border-top:1px solid var(--rule);padding-top:1.8rem;margin-top:2.5rem;text-align:left}
.footer-credentials-img{width:550px;max-width:100%;height:auto}
.footer-bottom{padding-top:1.5rem;display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:1rem}
.footer-bottom p{font-size:1rem;color:var(--muted);line-height:1.7}
.footer-lic{font-family:var(--ff-b);font-size:.6rem;color:var(--gold-text);letter-spacing:.06em;text-align:right}

/* ═══════════════════════════════
   RESPONSIVE
═══════════════════════════════ */
@media(max-width:1024px){
  .pvip-block,.mm2h-block{grid-template-columns:1fr}
  .pvip-img,.mm2h-img{min-height:320px;order:-1}
  .pvip-img-overlay{background:linear-gradient(to bottom,transparent 60%,rgba(28,28,28,.85))}
  .intro-inner{grid-template-columns:1fr;gap:3rem}
  .proof-inner{grid-template-columns:1fr;gap:3rem}
  .footer-top{grid-template-columns:1fr 1fr;gap:2rem}
  .contact-grid{grid-template-columns:1fr}
  .map-embed{height:260px}
  /* Nav switches to the hamburger menu here, not at 768px: the full desktop nav
     (logo + Visas dropdown + About Us + News & Blog + CTA) starts wrapping onto two
     lines below ~900px, so iPad-portrait widths (768-1024px) need the mobile menu too. */
  #nav{padding:.9rem 5vw}
  .nav-links{display:none}
  .nav-mob{display:flex}
  /* The desktop dropdown floats as an absolutely-centered panel relative to its
     trigger button — inside the full-screen mobile menu that overflows off the
     left edge and can visually collide with the always-visible CTA. Make it
     flow inline in the vertical list instead. */
  .nav-dropdown{position:static;width:100%}
  .nav-drop-menu{
    position:static;transform:none;left:auto;top:auto;
    width:100%;min-width:0;margin-top:.8rem;
    box-shadow:none;
  }
}
@media(max-width:768px){
  .pad{padding:3.5rem 5vw}
  .programmes{padding:3.5rem 5vw}
  .hero-content{padding:8rem 0 3.5rem}
  /* Was display:none — hid all 5 credibility stats from mobile visitors
     entirely. Then tried horizontal-scroll (flex-shrink:0 items, like
     .trust-bar below the hero) — but unlike .trust-bar's small badge
     items, these are the primary trust numbers right under the fold, and
     a manually-scrolled row with no scroll-snap kept resting mid-item,
     showing a card sliced in half at each viewport edge. Wrap into a
     2-column grid instead: all stats readable at once, nothing hidden,
     nothing to scroll or crop. With 6 items this divides evenly into 3
     full rows — no odd-item-out closing row needed (that hack applied
     when there were 5; remove it if the count ever goes odd again). */
  .hero-strip{display:grid;grid-template-columns:1fr 1fr}
  .hs-item{padding:1.1rem .4rem}
  .hs-item:nth-child(-n+4){border-bottom:1px solid rgba(255,255,255,.07)}
  .hs-item:nth-child(2n){border-right:none}
  .footer-top{grid-template-columns:1fr}
  .footer-bottom{flex-direction:column}
  /* .hero-stat-card is flex-shrink:0 so it sits at a fixed size next to the
     hero text on desktop. Once it wraps onto its own row on mobile that
     stops constraining it and it sizes to its longest label's natural
     one-line width instead — fine for PVIP's short "Years Residency" but
     S-MM2H's "Years Max Residency (5+5, Renewable)" is long enough to run
     past the viewport edge. Let it size to the row like everything else. */
  .page-hero-inner{gap:1.6rem}
  .hero-stat-card{flex-shrink:1;width:100%}
  /* .req-box's 3rem/2.6rem desktop padding was never reduced for mobile,
     so on a narrow phone it squeezed the single-column card grid down to
     an uncomfortably narrow, heavily left/right-margined strip and pushed
     some card text (e.g. "RM 1,000,000") right to the edge of overflow. */
  .req-box{padding:2rem 1.2rem}
  /* Mobile-only trim: the desktop card was built for a wide two-column
     read, so on a phone the decorative image + full-size feature list
     stacked to several screens of scroll. Shrink the image, tighten the
     feature rows, and give the stats row breathing room on its right
     edge so the fixed WhatsApp button (.wa-widget, bottom-right) never
     sits on top of the third stat's label. */
  .pvip-img,.mm2h-img{min-height:200px}
  .pvip-content,.mm2h-content{padding:1.8rem 1.6rem 2.1rem}
  .form-card{padding:1.6rem 1.3rem}
  .btn-primary,.btn-ghost{font-size:.78rem;padding:.75rem 1.5rem}
  .pvip-stats,.mm2h-stats{margin-bottom:1.4rem}
  .pstat,.mstat{padding:0 .6rem}
  .pstat-v,.mstat-v{font-size:1.5rem}
  .pstat-l,.mstat-l{font-size:.56rem}
  .pvip-feats,.mm2h-feats{gap:.6rem;margin-bottom:1.5rem}
  .pvip-feat,.mm2h-feat{font-size:.92rem;line-height:1.5}
  .pvip-feat::before,.mm2h-feat::before{width:1.3rem;height:1.3rem;font-size:.72rem;margin-top:1px}
  .btn-gold-pill,.btn-outline-dark{align-self:stretch;justify-content:center}
}
@media(max-width:400px){
  /* Below ~400px, three nowrap stat values (esp. "5–20yr") no longer fit
     three-across even at a reduced font-size without either shrinking the
     numbers out of proportion or colliding into each other. Reflow to a
     2-up row with the third stat spanning full width beneath, on its own
     divider, so every value keeps its full size and clear space. */
  .pvip-stats,.mm2h-stats{flex-wrap:wrap;row-gap:.9rem}
  .pstat,.mstat{flex:0 1 50%}
  .pstat:nth-child(3),.mstat:nth-child(3){flex-basis:100%;border-left:none;padding-left:0;margin-top:.3rem;padding-top:.9rem}
  .pstat:nth-child(3){border-top:1px solid rgba(255,255,255,.15)}
  .mstat:nth-child(3){border-top:1px solid var(--rule)}
}
@media(max-width:520px){
  .form-row{grid-template-columns:1fr}
}
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition-duration:.01ms!important}
  .reveal{opacity:1!important;transform:none!important}
  .tl-body{opacity:1!important;transform:none!important}
}
/* Bolded sitewide on purpose — many visitors (incl. older applicants) read
   the thin display serif more easily at heavier weight. Keep this. */
h1,h2,h3,h4,h5,h6{font-weight:700!important}
.eyebrow{font-weight:700!important}

/* ═══════════════════════════════════════════════════════════
   INNER "PROGRAMME DETAIL" PAGE COMPONENTS
   Shared by /pvip/, /mm2h/, /employment-pass/, /digital-nomad/, /apec/
   These read from the same tokens above, so they're light-themed by
   default. .theme-dark-premium (bottom of file) overrides tokens for
   the one page (PVIP) that uses the dark "premium" treatment.
═══════════════════════════════════════════════════════════ */

/* Page hero — always a dark photo band regardless of page theme */
.page-hero{position:relative;padding:9.5rem 6vw 4.5rem;background:var(--ink-deep);overflow:hidden}
.page-hero-bg{position:absolute;inset:0;opacity:.5;background-size:cover;background-position:center}
.page-hero-overlay{position:absolute;inset:0;background:linear-gradient(120deg,rgba(13,13,13,.85) 0%,rgba(13,13,13,.68) 55%,rgba(13,13,13,.45) 100%)}
.page-hero-inner{position:relative;z-index:2;display:flex;justify-content:space-between;align-items:flex-end;gap:3rem;flex-wrap:wrap}
.page-hero-left{max-width:640px}
/* .35 -> .5: measured 3.19:1 on the dark-hero background (#1C1C1C), below the
   4.5:1 AA floor. */
.breadcrumb{font-family:var(--ff-b);font-size:.78rem;letter-spacing:.01em;color:rgba(255,255,255,.5);margin-bottom:1.2rem}
/* Underlined, not just a lighter shade: this link sits next to breadcrumb text
   in several different color contexts (dark hero here, light-hero and
   .article-header/.article-hero overrides elsewhere), so relying on a single
   "is it 3:1 apart from the text beside it" color tune would need re-solving
   per context. An underline distinguishes it by a non-color means everywhere
   at once (Lighthouse a11y: link-in-text-block). */
.breadcrumb a{color:rgba(255,255,255,.5);text-decoration:underline;text-underline-offset:2px;transition:color .2s}
.breadcrumb a:hover{color:var(--gold)}
.page-hero h1{font-family:var(--ff-d);font-size:clamp(2.4rem,4.6vw,3.8rem);font-weight:300;color:#fff;line-height:1.1;margin-bottom:1.1rem}
.page-hero h1 em{font-style:italic;color:var(--gold-lt)}
/* News' own light-hero variant (see news.njk's comment on .page-hero) inherited
   this dark-hero em color by default — 1.61:1 on its off-white background,
   nowhere near the 3:1 floor for large text (Lighthouse a11y audit).
   --gold-text is the site's accessible-on-light gold everywhere else. */
.page-hero.light h1 em{color:var(--gold-text)}
.page-hero p{font-size:1.25rem;color:rgba(255,255,255,.5);line-height:1.8;max-width:580px;margin-bottom:1.8rem}
.hero-btns{display:flex;gap:.8rem;flex-wrap:wrap}
.btn-gold-cta{background:var(--gold);color:#131313;font-size:.82rem;font-weight:600;letter-spacing:.04em;padding:.85rem 1.9rem;border-radius:50px;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:.5rem;transition:background .2s,transform .15s,box-shadow .2s}
.btn-gold-cta:hover{background:var(--gold-dk);transform:translateY(-1px);box-shadow:0 8px 24px rgba(201,168,76,.3)}
.btn-gold-cta:active{background:var(--gold-dk);transform:scale(.96)}
.btn-white-outline{border:1.5px solid rgba(255,255,255,.25);color:rgba(255,255,255,.8);font-size:.82rem;font-weight:500;letter-spacing:.04em;padding:.85rem 1.7rem;border-radius:50px;background:none;cursor:pointer;transition:border-color .2s,color .2s,transform .15s}
.btn-white-outline:hover{border-color:rgba(255,255,255,.6);color:#fff}
.btn-white-outline:active{border-color:rgba(255,255,255,.6);color:#fff;transform:scale(.96)}
.hero-stat-card{background:rgba(255,255,255,.07);border:1px solid rgba(201,168,76,.25);border-radius:var(--r-lg);padding:1.4rem 1.8rem;backdrop-filter:blur(10px);text-align:center;flex-shrink:0}
.hsc-num{font-family:var(--ff-d);font-size:2.6rem;font-weight:700;color:var(--gold-dk);line-height:1}
.hsc-label{font-family:var(--ff-b);font-size:.6rem;letter-spacing:.1em;text-transform:uppercase;color:rgba(255,255,255,.45);margin-top:.4rem}

/* Authority strip (same pattern as homepage trust-bar, renamed for these pages) */
.authority-strip{background:var(--off);border-bottom:1px solid var(--rule);padding:1.3rem 6vw;display:flex;align-items:center;overflow-x:auto;scrollbar-width:none}
.authority-strip::-webkit-scrollbar{display:none}
.a-item{display:flex;align-items:center;gap:.5rem;font-size:.73rem;font-weight:500;color:var(--muted);white-space:nowrap;padding:0 1.7rem;border-right:1px solid var(--rule);flex-shrink:0}
.a-item:first-child{padding-left:0}
.a-item:last-child{border-right:none}
.a-check{width:17px;height:17px;border-radius:50%;background:var(--gold-bg);border:1px solid rgba(201,168,76,.3);display:flex;align-items:center;justify-content:center;color:var(--gold-text);font-size:.6rem;font-weight:700;flex-shrink:0}

/* Auto-scrolling trust-bar/authority-strip — two states, set by JS (see
   main.js) depending on whether the row's items already fit the container:
    - .marquee-fits: nothing to scroll to, so instead of faking motion with a
      transform (which would need artificially-doubled content and risks
      clipping an item at the edge — tried and reverted, see
      feedback_mypvip_marquee_decision memory), a staggered glow sweeps
      across each item's checkmark. Purely decorative, zero clipping risk,
      since nothing ever leaves the visible area.
    - .marquee-overflow: content genuinely overflows; main.js auto-advances
      the row's real scrollLeft one item at a time (not a CSS transform), so
      it plays nicely with native touch/trackpad scrolling instead of
      animating independently of it. The edge mask below is just a "there's
      more" hint, not a clipping fix — the auto-advance itself never rests
      mid-item. */
.trust-bar.marquee-overflow,.authority-strip.marquee-overflow{
  -webkit-mask-image:linear-gradient(to right,transparent,#000 4%,#000 96%,transparent);
  mask-image:linear-gradient(to right,transparent,#000 4%,#000 96%,transparent);
}
/* Only the fits state can safely center -- centering an overflowing row
   would hide equal amounts of content off BOTH edges, so scrollLeft:0
   wouldn't show the true first item and a user's scroll would never reach
   a real start/end. */
.trust-bar.marquee-fits,.authority-strip.marquee-fits{justify-content:center}
@keyframes item-glow{0%,100%{box-shadow:0 0 0 0 rgba(201,168,76,0)}50%{box-shadow:0 0 0 4px rgba(201,168,76,.25)}}
.marquee-fits .t-check,.marquee-fits .a-check{animation:item-glow 3.6s ease-in-out infinite}
.marquee-fits .t-item:nth-child(1) .t-check,.marquee-fits .a-item:nth-child(1) .a-check{animation-delay:0s}
.marquee-fits .t-item:nth-child(2) .t-check,.marquee-fits .a-item:nth-child(2) .a-check{animation-delay:.5s}
.marquee-fits .t-item:nth-child(3) .t-check,.marquee-fits .a-item:nth-child(3) .a-check{animation-delay:1s}
.marquee-fits .t-item:nth-child(4) .t-check,.marquee-fits .a-item:nth-child(4) .a-check{animation-delay:1.5s}
.marquee-fits .t-item:nth-child(5) .t-check,.marquee-fits .a-item:nth-child(5) .a-check{animation-delay:2s}
.marquee-fits .t-item:nth-child(6) .t-check,.marquee-fits .a-item:nth-child(6) .a-check{animation-delay:2.5s}

/* Intro statement */
.intro-stmt{background:var(--white)}
.intro-stmt-inner{max-width:1240px;margin:0 auto;display:grid;grid-template-columns:1.15fr .85fr;gap:3.5rem;align-items:center}
.intro-stmt-text{max-width:640px}
.intro-stmt-img{border-radius:var(--r-xl);overflow:hidden;box-shadow:0 24px 64px rgba(0,0,0,.12)}
/* S-MM2H reuses one Kuching photo for both the hero backdrop and this card
   (no second real photo available yet — see HANDOFF.md). The hero shows it
   wide and washed-out as a backdrop; this crops tight on the waterfront
   mosque instead of repeating the hero's centered full-skyline framing, so
   the two don't read as the identical shot pasted twice. Swap for a second
   real Kuching/Sarawak photo when one is sourced. */
.intro-stmt-img img{width:100%;height:100%;object-fit:cover;object-position:18% 42%;display:block;aspect-ratio:4/5}
.intro-stmt p.intro-stmt-lead{font-family:var(--ff-d);font-size:clamp(1.5rem,2.3vw,2rem);font-weight:300;color:var(--charcoal);line-height:1.35}
.intro-stmt p.intro-stmt-lead em{font-style:italic;color:var(--gold-dk)}
.intro-stmt p{font-size:1.2rem;color:var(--body);line-height:1.85;margin-top:1.2rem}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.intro-note{margin-top:1.6rem;padding:1.1rem 1.4rem;background:var(--gold-bg);border:1px solid rgba(201,168,76,.3);border-radius:var(--r-sm);font-size:.82rem;color:var(--body);line-height:1.6}
.intro-note strong{color:var(--charcoal)}
@media(max-width:900px){
  .intro-stmt-inner{grid-template-columns:1fr}
  .intro-stmt-text{max-width:none}
  .intro-stmt-img{order:-1;aspect-ratio:16/9}
  .intro-stmt-img img{aspect-ratio:16/9}
}

/* Requirements grid — base is the plain light card treatment (used by MM2H,
   Employment Pass, Digital Nomad, APEC). PVIP additionally wraps this in a
   dark .req-box panel further below, which restyles the same classes by
   ancestor scoping rather than fighting over the bare selectors. */
.requirements{background:var(--off)}

/* Shared base for the 17 "eyebrow+h2+p" section-header classes below — font-size, color,
   margin-bottom and max-width stay per-class since those genuinely differ. */
:is(.prog-section-header,.why-header,.process-header,.contact-header,.req-header,.ct-header,.feat-header,.fees-header,.faq-header,.tiers-header,.section-header,.mm2h-calc-header,.docs-header,.certs-header,.team-header,.priv-header,.partners-header) h2{font-family:var(--ff-d);font-weight:300;line-height:1.1}
:is(.prog-section-header,.why-header,.process-header,.contact-header,.req-header,.ct-header,.feat-header,.fees-header,.faq-header,.tiers-header,.section-header,.mm2h-calc-header,.docs-header,.certs-header,.team-header,.priv-header,.partners-header) h2 em{font-style:italic}
.req-header{text-align:center;margin-bottom:2.6rem;position:relative}
.req-header h2{font-size:clamp(1.9rem,3.2vw,2.8rem);color:var(--charcoal)}
.req-header h2 em{color:var(--gold-dk)}
.req-header p{font-size:1.15rem;color:var(--muted);margin-top:.7rem;max-width:580px;margin-left:auto;margin-right:auto;line-height:1.75}
.req-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1.2rem}
.req-card{min-width:0;background:var(--white);border:1px solid var(--rule);border-radius:var(--r-lg);padding:1.7rem 1.5rem;transition:border-color .25s,transform .25s,box-shadow .25s;scroll-margin-top:calc(var(--nav-h, 90px) + 1.5rem)}
.req-card:hover{border-color:rgba(201,168,76,.35);transform:translateY(-4px);box-shadow:0 14px 36px rgba(201,168,76,.1)}
.req-icon{width:44px;height:44px;border-radius:50%;margin-bottom:1rem;background:var(--gold-bg);border:1px solid rgba(201,168,76,.2);display:flex;align-items:center;justify-content:center;font-size:1.1rem}
.req-card h3{font-size:.88rem;font-weight:600;color:var(--charcoal);margin-bottom:.5rem}
.req-metric{font-family:var(--ff-d);font-size:1.5rem;font-weight:600;color:var(--gold-dk);line-height:1.15;margin-bottom:.5rem;display:block}
.req-card p{font-size:1.1rem;color:var(--body);line-height:1.75}
@media(max-width:1024px){.req-grid{grid-template-columns:1fr 1fr}}
@media(max-width:768px){.req-grid{grid-template-columns:1fr}}

/* Employment Pass — Professional Visit Pass tab: 3 cards on desktop, same responsive
   collapse as the base .req-grid (needs its own breakpoints since equal-specificity
   rules are resolved by source order, not just by width match). */
.pvp-grid{grid-template-columns:repeat(3,1fr)}
@media(max-width:1024px){.pvp-grid{grid-template-columns:1fr 1fr}}
@media(max-width:768px){.pvp-grid{grid-template-columns:1fr}}

/* PVIP-only: dark boxed panel wrapping the same req-header/req-grid/req-card markup */
.req-box{background:var(--panel-dark);border-radius:var(--r-xl);padding:3rem 2.6rem;box-shadow:0 24px 64px rgba(0,0,0,.45);position:relative;overflow:hidden}
.req-box::before{content:'';position:absolute;top:-30%;right:-8%;width:480px;height:480px;border-radius:50%;background:radial-gradient(ellipse,rgba(201,168,76,.08) 0%,transparent 68%);pointer-events:none}
.req-box .req-header .eyebrow{color:rgba(201,168,76,.8)}
.req-box .req-header h2{color:#fff}
.req-box .req-header h2 em{color:var(--gold-lt)}
.req-box .req-header p{color:rgba(255,255,255,.6)}
.req-box .req-grid{grid-template-columns:repeat(3,1fr);gap:1px;background:rgba(201,168,76,.12);border-radius:var(--r-lg);overflow:hidden}
.req-box .req-card{background:rgba(255,255,255,.06);border:none;border-radius:0;padding:1.9rem 1.7rem;transition:background .25s}
.req-box .req-card:hover{background:rgba(201,168,76,.1);transform:none;box-shadow:none}
.req-box .req-icon{background:rgba(201,168,76,.1);border-color:rgba(201,168,76,.25)}
.req-box .req-card h3{color:#fff}
.req-box .req-metric{color:var(--gold)}
.req-box .req-card p{color:rgba(255,255,255,.58)}
@media(max-width:1024px){.req-box .req-grid{grid-template-columns:1fr 1fr}}
@media(max-width:768px){.req-box .req-grid{grid-template-columns:1fr}}

/* "Agreement paper" requirements card — opt-in via .req-doc on .req-grid,
   used on MM2H/S-MM2H's qualifying-criteria sections (not Employment Pass's
   PVP grid, which keeps the plain .req-icon treatment). PVIP does NOT use
   this light/paper treatment — see the dark override block below; both the
   deckled clip-path edge and the paper-on-dark-desk concept were tried and
   dropped after review, in favour of keeping PVIP's cards dark to match the
   rest of its "premium" theme. History in design-requirements-seal.html. */
.req-doc .req-card{
  background:#fff;border:1px solid #1C1C1C;border-radius:6px;
  padding:1.9rem 1.7rem;position:relative;transition:border-color .25s;
  transform:none;box-shadow:none;
}
.req-doc .req-card:hover{border-color:#A8893C;transform:none;box-shadow:none}
.req-doc .req-card::after{content:'';position:absolute;inset:5px;border:1px solid rgba(28,28,28,.12);border-radius:3px;pointer-events:none}
.req-doc .req-card h3{color:#1C1C1C}
.req-doc .req-card p{color:#3D3D3D}
.req-doc .req-metric{
  font-family:'DM Mono',monospace;font-weight:500;font-size:1.25rem;
  color:#A8893C;line-height:1.3;display:inline-block;
  padding-bottom:.3rem;margin-bottom:1rem;border-bottom:1px solid rgba(28,28,28,.2);
}
.req-seal{
  /* var(--gold-text), not --gold-dk: the ring/number sit directly on white
     .req-doc cards, and --gold-dk (#A8893C) only clears ~3.3:1 there — below
     the 4.5:1 AA floor. --gold-text (#8A6B22) is this site's existing
     accessible-on-light gold token (already used for eyebrows etc), ~5:1. */
  display:inline-flex;width:42px;height:42px;color:var(--gold-text);margin-bottom:1.1rem;
  transition:transform .4s cubic-bezier(.22,.68,0,1.1),color .3s;
}

/* PVIP only: dark card instead of the light/paper treatment above, so the
   requirements grid matches the rest of the page's dark "premium" theme
   instead of standing out as a bright block. This is the same "endorsement
   seal on dark glass" look validated earlier in design-lab.html, now
   overriding .req-doc specifically for PVIP's .req-box context (higher
   specificity than the light rules above, so it wins without fighting
   source order). */
.req-box .req-doc{gap:1.3rem;background:none;border-radius:0;overflow:visible}
.req-box .req-doc .req-card{
  background:rgba(255,255,255,.06);border-color:rgba(201,168,76,.25);
}
.req-box .req-doc .req-card:hover{background:rgba(201,168,76,.1);border-color:rgba(201,168,76,.4)}
.req-box .req-doc .req-card::after{border-color:rgba(201,168,76,.15)}
.req-box .req-doc .req-card h3{color:#fff}
.req-box .req-doc .req-card p{color:rgba(255,255,255,.58)}
.req-box .req-doc .req-metric{color:var(--gold);border-bottom-color:rgba(255,255,255,.2)}
.req-box .req-doc .req-seal{color:var(--gold)}
.req-box .req-doc .req-card:hover .req-seal{color:#fff}
/* No filter/drop-shadow here on purpose: a "letterpress" drop-shadow was
   tried and pulled out again — it forces the browser to rasterize the SVG
   (thin 1px/2.2px strokes at 42px) instead of rendering it as crisp vector
   lines, which read as blurry once you looked closely. Plain currentColor
   strokes stay sharp at any zoom/DPI. */
.req-seal svg{width:100%;height:100%;display:block}
.req-doc .req-card:hover .req-seal{color:#1C1C1C}
@media (prefers-reduced-motion: no-preference){
  .req-doc .req-card:hover .req-seal{transform:rotate(8deg) scale(1.06)}
}

/* Comparison table.
   Flat colour, not layered translucent gold/white washes: the box's corner
   radial glow, the wrap's white tint, and the highlighted column's own
   gold-tinted background used to all stack in the top-left corner into a
   muddy warm cast instead of reading as "dark table, one clean accent."
   Header is now a bottom rule instead of a filled bar, and the PVIP column
   is distinguished by text colour/weight alone — no background wash, so it
   doesn't visually claim "PVIP wins every row" on the one row where both
   columns actually tie ("Education & healthcare access": Applicable/Applicable).
   Full before/after in design-compare-table.html. */
.compare-tbl{background:var(--off)}
.ct-box{background:var(--panel-dark);border-radius:var(--r-xl);padding:3rem 2.6rem;box-shadow:0 24px 64px rgba(0,0,0,.45);position:relative}
.ct-header{text-align:center;margin-bottom:2.4rem}
.ct-header .eyebrow{color:rgba(201,168,76,.8)}
.ct-header h2{font-size:clamp(1.9rem,3.2vw,2.8rem);color:#fff}
.ct-header h2 em{color:var(--gold-lt)}
.ct-header p{font-size:1.15rem;color:rgba(255,255,255,.6);margin-top:.7rem;max-width:590px;margin-left:auto;margin-right:auto;line-height:1.75}
/* Synthesis line above the table — the critique's own note that a Persuade-
   mode comparison table should move the visitor toward a decision, not just
   hand them a spreadsheet. "6 of 9" is a plain count of this table's own
   rows below, not a separate claim. */
.ct-insight{font-size:1.05rem;font-weight:600;color:var(--gold-lt);margin-top:1rem;max-width:590px;margin-left:auto;margin-right:auto;line-height:1.6}
.ct-wrap{border-radius:var(--r-lg);overflow:hidden;background:rgba(255,255,255,.03)}
.ct-table{width:100%;border-collapse:collapse}
.ct-table thead th{background:none;border-bottom:2px solid rgba(201,168,76,.35);color:#fff;font-size:.78rem;font-weight:600;letter-spacing:.03em;padding:1.1rem 1.4rem;text-align:left}
.ct-table thead th:first-child{color:rgba(255,255,255,.55);font-weight:500}
.ct-table thead th.col-hl{color:var(--gold-lt)}
.ct-table tbody tr{border-bottom:1px solid rgba(255,255,255,.09)}
.ct-table tbody tr:last-child{border-bottom:none}
.ct-table tbody tr:nth-child(even){background:rgba(255,255,255,.03)}
.ct-table td{padding:1rem 1.4rem;font-size:1.1rem;color:rgba(255,255,255,.65);vertical-align:top;background:none}
.ct-table td:first-child{font-weight:600;color:#fff;white-space:nowrap}
.ct-table td.col-hl{color:var(--gold-lt);font-weight:600;background:none}
/* Cross-links back to the matching /pvip/#requirements card — critique fix
   for "no way to jump back to a specific requirement from later sections"
   (comparison table, fee calculator). Reused by .calc-table below. */
.ct-req-link{color:inherit;text-decoration:underline;text-decoration-style:dotted;text-decoration-color:rgba(255,255,255,.35);text-underline-offset:3px;transition:color .2s,text-decoration-color .2s}
.ct-req-link:hover{color:var(--gold-lt);text-decoration-color:var(--gold-lt)}
.ct-note{margin-top:1.3rem;padding:1rem 1.4rem;background:rgba(201,168,76,.08);border:1px solid rgba(201,168,76,.25);border-radius:var(--r-sm);font-size:.78rem;color:rgba(255,255,255,.65);line-height:1.6;position:relative}
.ct-note strong{color:#fff!important}
@media(max-width:1024px){.ct-table{font-size:.78rem}}
@media(max-width:768px){
  .ct-box{padding:1.8rem 1.1rem}
  .ct-wrap{overflow-x:visible}
  .ct-table thead{display:none}
  .ct-table,.ct-table tbody,.ct-table tr,.ct-table td{display:block;width:100%}
  .ct-table tbody tr{margin-bottom:1rem;border:1px solid rgba(255,255,255,.1);border-radius:var(--r-md);overflow:hidden;background:rgba(255,255,255,.03)!important}
  .ct-table tbody tr:last-child{margin-bottom:0}
  .ct-table td{padding:.75rem 1.1rem!important;white-space:normal!important;display:flex;justify-content:space-between;align-items:baseline;gap:1rem;border-bottom:1px solid rgba(255,255,255,.08);background:none!important}
  .ct-table td:last-child{border-bottom:none}
  .ct-table td:first-child{background:rgba(255,255,255,.04)!important;color:#fff;font-size:1rem;font-weight:700;display:block}
}

/* Features — hover/tap reveal photo grid.
   Tokenized (not hardcoded dark) so it's light on MM2H/Employment Pass/etc.
   and automatically dark on PVIP via body.theme-dark-premium's token swap —
   the ben-card photo/overlay itself is already dark regardless, by design. */
.features.pad{background:var(--off);padding-top:3.5rem;padding-bottom:3.5rem}
.feat-header{text-align:center;margin-bottom:1.8rem}
.feat-header h2{font-size:clamp(1.9rem,3.2vw,2.8rem);color:var(--charcoal)}
.feat-header h2 em{color:var(--gold-dk)}
.feat-header p{font-size:1.15rem;color:var(--muted);margin-top:.7rem;max-width:550px;margin-left:auto;margin-right:auto;line-height:1.75}
.ben-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1.2rem}
.ben-grid.ben-grid-3col{grid-template-columns:repeat(3,1fr)}
.ben-card{position:relative;border-radius:var(--r-lg);overflow:hidden;aspect-ratio:4/3;box-shadow:0 8px 32px rgba(0,0,0,.35);transition:transform .35s var(--ease),box-shadow .35s var(--ease)}
.ben-card:hover{transform:translateY(-6px);box-shadow:0 20px 50px rgba(0,0,0,.5)}
.ben-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .6s var(--ease)}
.ben-card:hover .ben-img{transform:scale(1.06)}
.ben-overlay{position:absolute;inset:0;background:linear-gradient(to top,rgba(10,8,6,.95) 0%,rgba(10,8,6,.55) 45%,rgba(10,8,6,.15) 100%);transition:background .35s}
.ben-card:hover .ben-overlay{background:linear-gradient(to top,rgba(10,8,6,.98) 0%,rgba(10,8,6,.65) 50%,rgba(10,8,6,.2) 100%)}
.ben-credit{position:absolute;top:1.2rem;right:1.2rem;max-width:60%;font-size:.52rem;line-height:1.35;text-align:right;color:rgba(255,255,255,.4);text-shadow:0 1px 3px rgba(0,0,0,.7);opacity:0;transition:opacity .3s}
.ben-credit a{color:inherit;text-decoration:underline}
.ben-card:hover .ben-credit,.ben-card.active .ben-credit{opacity:1}
.ben-content{position:absolute;bottom:0;left:0;right:0;padding:1.5rem 1.4rem}
/* Was a pill badge (rounded bg + border) — flattened to plain text, chrome
   removed but kept the pill's own font-size/letter-spacing (.57rem/.08em)
   rather than switching to the sitewide .eyebrow's larger/more-tracked
   values, since that read too big next to the title once the pill box was gone. */
.ben-tag{display:block;font-family:var(--ff-b);font-size:.57rem;letter-spacing:.08em;text-transform:uppercase;color:var(--gold-lt);margin-bottom:.55rem}
.ben-title{font-family:var(--ff-d);font-size:1.1rem;font-weight:600;color:#fff;line-height:1.25;margin-bottom:.4rem}
.ben-desc{font-size:.85rem;color:rgba(255,255,255,.6);line-height:1.6;max-height:0;overflow-y:auto;opacity:0;scrollbar-width:none;-ms-overflow-style:none;transition:max-height .35s var(--ease),opacity .3s}
.ben-desc::-webkit-scrollbar{display:none;width:0;height:0}
.ben-card:hover .ben-desc,.ben-card.active .ben-desc{max-height:160px;opacity:1}
@media(max-width:1024px){.ben-grid,.ben-grid.ben-grid-3col{grid-template-columns:repeat(2,1fr)}}
@media(max-width:768px){
  .ben-card{aspect-ratio:auto;min-height:340px}
  .ben-card.active{transform:translateY(-4px);box-shadow:0 20px 50px rgba(0,0,0,.5)}
  .ben-card.active .ben-img{transform:scale(1.06)}
  .ben-card.active .ben-overlay{background:linear-gradient(to top,rgba(10,8,6,.97) 0%,rgba(10,8,6,.75) 55%,rgba(10,8,6,.25) 100%)}
  .ben-content{max-height:100%;overflow-y:auto;-webkit-overflow-scrolling:touch;padding-bottom:1.1rem;scrollbar-width:none;-ms-overflow-style:none}
  .ben-content::-webkit-scrollbar{display:none;width:0;height:0}
}
@media(max-width:480px){.ben-grid,.ben-grid.ben-grid-3col{grid-template-columns:1fr}.ben-card{min-height:300px}}

/* Fee calculator */
.fees{background:var(--white)}
/* Capped and centered, unlike the section it sits in — .fees itself is full-bleed
   (just .pad's 6vw), so an unbounded fee-box read as ~340px of empty dark panel on
   each side at desktop widths with only .calc-wrap's 680px actually holding content.
   1120px keeps the panel a deliberate object instead of a full-bleed backdrop. */
.fee-box{background:var(--panel-dark);border-radius:var(--r-xl);padding:3rem 2.6rem;box-shadow:0 24px 64px rgba(0,0,0,.45);position:relative;overflow:hidden;max-width:1120px;margin:0 auto}
.fee-box::before{content:'';position:absolute;top:-30%;right:-8%;width:480px;height:480px;border-radius:50%;background:radial-gradient(ellipse,rgba(201,168,76,.08) 0%,transparent 68%);pointer-events:none}
.fees-header{text-align:center;margin-bottom:2.5rem;position:relative}
.fees-header .eyebrow{color:rgba(201,168,76,.8)}
.fees-header h3{font-size:clamp(1.8rem,3vw,2.6rem);color:#fff}
.fees-header h3 em{color:var(--gold-lt)}
.fees-header p{color:rgba(255,255,255,.6)!important}
/* No longer width-capped on its own — .fee-box now does that job — so the reclaimed
   width goes to .calc-grid below instead of sitting empty around a narrow column. */
.calc-wrap{margin:0 auto;background:rgba(255,255,255,.06);border-radius:var(--r-lg);padding:2.2rem 2.4rem;position:relative}
.calc-slider-row{display:flex;align-items:center;gap:1.2rem;margin-bottom:1.8rem}
.calc-slider-label{font-size:.82rem;color:rgba(255,255,255,.7);min-width:110px;font-weight:500}
.calc-slider-row input[type="range"]{flex:1;height:36px;padding:0;margin:0;background:transparent;outline:none;-webkit-appearance:none;appearance:none;touch-action:pan-y}
.calc-slider-row input[type="range"]::-webkit-slider-runnable-track{height:4px;border-radius:2px;background:rgba(255,255,255,.2)}
.calc-slider-row input[type="range"]::-moz-range-track{height:4px;border-radius:2px;background:rgba(255,255,255,.2)}
.calc-slider-row input[type="range"]::-webkit-slider-thumb{-webkit-appearance:none;width:26px;height:26px;border-radius:50%;background:var(--gold);cursor:pointer;border:3px solid var(--charcoal);box-shadow:0 0 0 1px var(--gold);margin-top:-11px}
.calc-slider-row input[type="range"]::-moz-range-thumb{width:26px;height:26px;border-radius:50%;background:var(--gold);cursor:pointer;border:3px solid var(--charcoal);box-shadow:0 0 0 1px var(--gold)}
.calc-slider-out{font-family:var(--ff-d);font-size:1.3rem;color:var(--gold-dk);min-width:24px;text-align:right;font-weight:600}
/* Quick-glance totals (left) beside the full itemization (right) — a checkout-style
   split, so both "what do I owe" and "how was that worked out" sit in view together
   in the width .fee-box now has, instead of one long stack the reader scrolls through. */
.calc-grid{display:grid;grid-template-columns:1fr 1.3fr;gap:2.5rem;align-items:start}
/* The 3 cards used to be much shorter than the 6-row table beside them, leaving the
   left column trailing into empty panel once the reader scrolled past them — fixed
   by folding the note + verified badge into this same sticky block instead of
   padding the gap with decoration, so real content fills it. Same idea as
   .topics-sidebar/.article-sidebar elsewhere: pin the summary while the longer
   itemization scrolls beside it. Desktop-grid only — the ≤860px stack below turns
   this off, where sticky would float the block over the table instead of beside it. */
.calc-summary{display:flex;flex-direction:column;gap:.8rem;position:sticky;top:calc(var(--nav-h, 90px) + 1.5rem)}
.calc-card{background:rgba(255,255,255,.08);border-radius:var(--r-md);padding:1rem 1.1rem;display:flex;align-items:center;justify-content:space-between;gap:1rem}
.calc-card.highlight{background:var(--gold);border:none}
.calc-card-label{font-size:.7rem;color:rgba(255,255,255,.55)}
.calc-card.highlight .calc-card-label{color:rgba(28,28,28,.7)}
.calc-card-val{font-family:var(--ff-d);font-size:1.4rem;font-weight:600;color:#fff;white-space:nowrap}
/* Hardcoded, not var(--charcoal): this chip is always gold, on every theme
   including PVIP's dark-premium body, which redefines --charcoal to a light
   cream for its own dark-background text — that redefinition was leaking
   into this gold highlight card too, dropping the total to ~2:1 contrast. */
.calc-card.highlight .calc-card-val{color:#1C1C1C}
.calc-table{width:100%;font-size:1.08rem;border-collapse:collapse}
.calc-table tr{border-top:1px solid rgba(255,255,255,.1)}
.calc-table tr:first-child{border-top:none}
.calc-table td{padding:.6rem 0;color:rgba(255,255,255,.65)}
.calc-table td:last-child{text-align:right}
.calc-table tr.grand td{color:#fff;font-weight:600;padding-top:.8rem}
/* Sits in .calc-summary now, alongside the cards it explains — sized down from the
   old full-width note (.95rem) since this column is narrower and the note is
   secondary to the cards' numbers, not the main act. */
.calc-note{font-size:.8rem;color:rgba(255,255,255,.42);margin:0;line-height:1.6}
.calc-note-highlight{color:var(--gold-lt);font-weight:600}
/* Same seal() mark as PVIP's own document checklist (.req-box .req-doc .req-seal),
   so this reads as the site's existing "verified" language, not a new badge system.
   Compact single row — whatever's left in the column after the cards and note is
   the smallest amount of space it has to work with. */
.calc-verified{display:flex;align-items:center;gap:.55rem}
.calc-verified .req-seal{width:24px;height:24px;color:var(--gold);margin-bottom:0;flex-shrink:0}
.calc-verified span{font-size:.66rem;color:rgba(255,255,255,.4);letter-spacing:.01em}
.calc-verified strong{color:rgba(255,255,255,.75);font-weight:600}
/* .calc-summary's cards are already a single-width flex column, so unlike the old
   3-across grid they need no per-breakpoint column juggling — only the two-column
   summary/detail split has to give way, once it's too tight for both sides to read. */
@media(max-width:860px){.calc-grid{grid-template-columns:1fr;gap:1.6rem}.calc-summary{position:static}}
@media(max-width:768px){
  .fee-box{padding:2.2rem 1.2rem}
  .calc-wrap{padding:1.5rem 1.1rem}
  .calc-slider-row{flex-direction:column;align-items:stretch;gap:.7rem}
  .calc-slider-label{min-width:0}
  .calc-slider-out{align-self:flex-end;font-size:1.5rem}
  .calc-card{padding:.9rem .95rem}
  .calc-card-label{font-size:.72rem}
  .calc-card-val{font-size:1.15rem}
  .calc-table{font-size:.95rem}
}

/* FAQ categorized accordion */
.faq{background:var(--white)}
.faq-header{text-align:center;margin-bottom:2.5rem}
.faq-header h2{font-size:clamp(1.9rem,3.2vw,2.8rem);color:var(--charcoal)}
.faq-header h2 em{color:var(--gold-dk)}
.faq-cats{display:flex;justify-content:center;gap:.6rem;margin-bottom:2rem;flex-wrap:wrap}
.faq-cat-btn{font-family:var(--ff-b);font-weight:600;font-size:.78rem;letter-spacing:.01em;padding:.55rem 1.2rem;border-radius:50px;border:1px solid var(--rule);color:var(--muted);background:var(--off);cursor:pointer;transition:all .2s}
.faq-cat-btn.active{background:var(--gold);color:#131313;border-color:var(--gold)}
.faq-cat-btn:hover:not(.active){border-color:rgba(201,168,76,.4);color:var(--gold-dk)}
.faq-list{max-width:760px;margin:0 auto;display:none;flex-direction:column;gap:.7rem}
.faq-list.active{display:flex}
.faq-item{background:var(--white);border:1px solid var(--rule);border-radius:var(--r-md);overflow:hidden;transition:border-color .25s,box-shadow .25s}
.faq-item:hover{border-color:rgba(201,168,76,.35)}
.faq-item.open{border-color:rgba(201,168,76,.5);box-shadow:0 12px 32px rgba(201,168,76,.1)}
.faq-q{width:100%;text-align:left;padding:1.25rem 1.5rem;display:flex;align-items:center;justify-content:space-between;cursor:pointer;font-size:1.02rem;font-weight:600;color:var(--charcoal);gap:1.2rem;transition:color .2s}
.faq-q:hover{color:var(--gold-dk)}
.faq-q-icon{width:28px;height:28px;border-radius:50%;background:var(--gold-bg);color:var(--gold-dk);display:flex;align-items:center;justify-content:center;font-size:1.05rem;font-weight:400;flex-shrink:0;transition:transform .35s var(--ease),background .3s,color .3s}
.faq-item.open .faq-q-icon{transform:rotate(135deg);background:var(--charcoal);color:#fff}
.faq-a{max-height:0;overflow:hidden;transition:max-height .35s var(--ease)}
.faq-item.open .faq-a{max-height:1200px}
.faq-a-inner{padding:0 1.5rem 1.35rem;font-size:1.05rem;color:var(--body);line-height:1.85}
.faq-a-inner ul{margin-top:.5rem;padding-left:1.2rem;list-style:disc}
.faq-a-inner li{margin-bottom:.3rem}

/* Bottom CTA band (dark, same across all inner pages) */
.cta-block{background:var(--ink-deep);border-top:1px solid rgba(201,168,76,.15);padding:5rem 6vw;text-align:center;position:relative;overflow:hidden}
.cta-block::before{content:'';position:absolute;top:-30%;left:-8%;width:500px;height:500px;border-radius:50%;background:radial-gradient(ellipse,rgba(201,168,76,.08) 0%,transparent 68%);pointer-events:none}
.cta-block .eyebrow{color:rgba(201,168,76,.8)}
.cta-block h2{font-family:var(--ff-d);font-size:clamp(2rem,3.5vw,3.2rem);font-weight:300;color:#fff;line-height:1.1;margin-bottom:1rem;position:relative}
.cta-block h2 em{font-style:italic;color:var(--gold-lt)}
.cta-block p{font-size:1.2rem;color:rgba(255,255,255,.5);max-width:520px;margin:0 auto 2rem;line-height:1.75;position:relative}
.cta-btns{display:flex;justify-content:center;gap:.9rem;flex-wrap:wrap;position:relative}

/* ═══════════════════════════════════════════════════════════
   MM2H-ONLY COMPONENTS — tiered comparison table, its own fee
   calculator (namespaced mm2h-*, distinct from PVIP's calc-*), and
   the required-documents checklist. Only used on /mm2h/.
═══════════════════════════════════════════════════════════ */
.tiers{background:var(--white)}
.tiers-header{text-align:center;margin-bottom:2.4rem}
.tiers-header h2{font-size:clamp(1.9rem,3.2vw,2.8rem);color:var(--charcoal)}
.tiers-header h2 em{color:var(--gold-dk)}
.tiers-header p{font-size:1.15rem;color:var(--muted);margin-top:.7rem;max-width:640px;margin-left:auto;margin-right:auto;line-height:1.75}
.tiers-insight{font-size:1.05rem;font-weight:600;color:var(--gold-text);margin-top:1rem;max-width:640px;margin-left:auto;margin-right:auto;line-height:1.6}
.tier-tabs{display:flex;justify-content:center;gap:.6rem;margin-bottom:2rem;flex-wrap:wrap}
.tier-tab{font-family:var(--ff-b);font-weight:600;font-size:.78rem;letter-spacing:.01em;padding:.6rem 1.3rem;border-radius:50px;border:1px solid var(--rule);color:var(--muted);background:var(--white);cursor:pointer;transition:all .2s}
.tier-tab.active{background:var(--charcoal);color:#fff;border-color:var(--charcoal)}
.tier-tab:hover:not(.active){border-color:rgba(201,168,76,.4);color:var(--gold-dk)}
/* Visible by default — see main.js's js-ready comment. Every pass type/tier's
   content is reachable by scroll even if the script that drives the tabs
   never runs; JS marking <html class="js-ready"> is what re-enables the
   tabbed, one-panel-at-a-time behavior below. */
.tier-panel{display:block}
.tier-panel.active{animation:tierFadeIn .4s var(--ease)}
.js-ready .tier-panel:not(.active){display:none}
@keyframes tierFadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

.tier-wrap{border:1px solid var(--rule);border-radius:var(--r-lg);overflow-x:auto;overflow-y:visible;box-shadow:0 14px 50px rgba(0,0,0,.05)}
.tier-table{width:100%;border-collapse:collapse;min-width:620px;font-variant-numeric:tabular-nums}
.tier-table thead th{position:sticky;top:0;z-index:2;background:var(--charcoal);color:#fff;font-size:.76rem;font-weight:600;letter-spacing:.02em;padding:1rem 1.2rem;text-align:left;white-space:nowrap}
.tier-table thead th:first-child{color:rgba(255,255,255,.5);font-weight:500}
.tier-table tbody tr{border-bottom:1px solid var(--rule);transition:background-color .15s}
.tier-table tbody tr:last-child{border-bottom:none}
.tier-table tbody tr:not(.tier-group):hover{background:var(--gold-bg)}
.tier-table td{padding:.95rem 1.2rem;font-size:1.08rem;color:var(--body);vertical-align:top}
/* Opt these cells back out of the sitewide zh-tw/zh-cn keep-all rule
   (line ~64): MM2H's SEZ deposit cell mixes two age brackets with a ／
   separator, and keep-all's bigger unbreakable chunks stranded the ／
   alone on its own line instead of the compact, evenly-wrapped original.
   Reverted to normal per-character breaking for this table specifically. */
:lang(zh-tw) .tier-table td,:lang(zh-cn) .tier-table td{word-break:normal}
.tier-table td:first-child{font-weight:600;color:var(--charcoal);white-space:nowrap}
.tier-table td.hl{color:var(--charcoal);font-weight:500;background:var(--gold-bg)}
/* --gold-text, not --gold-dk: measured 3.05:1 on --off, below the 4.5:1 AA
   floor (Lighthouse a11y audit) — same fix as .req-seal's text elsewhere. */
.tier-table tr.tier-group td{background:var(--off);color:var(--gold-text);font-family:var(--ff-b);font-size:.62rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;padding:.55rem 1.2rem}
.tier-table tr.tier-group:hover{background:var(--off)}
.tier-table tr.tier-group:hover td{background:var(--off)}
.tier-note{margin-top:1.3rem;padding:1rem 1.4rem;background:var(--gold-bg);border:1px solid rgba(201,168,76,.3);border-radius:var(--r-sm);font-size:.78rem;color:var(--body);line-height:1.6}
.pass-intro{font-size:.88rem;color:var(--body);line-height:1.8;max-width:760px;margin:0 auto 2.5rem}

/* Eligibility category cards (Digital Nomad) */
.elig-card{background:var(--white);border:1px solid var(--charcoal);border-radius:6px;padding:2.2rem 2rem;position:relative;transition:border-color .25s}
.elig-card::after{content:'';position:absolute;inset:5px;border:1px solid var(--rule);border-radius:3px;pointer-events:none}
.elig-card:hover{border-color:var(--gold-dk)}
.elig-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.3rem;position:relative}
.elig-icon{width:52px;height:52px;border-radius:50%;background:var(--gold-bg);border:1px solid rgba(201,168,76,.25);display:flex;align-items:center;justify-content:center;font-size:1.35rem;flex-shrink:0}
.elig-seal{width:46px;height:46px;color:var(--gold-dk);flex-shrink:0}
.elig-seal svg{width:100%;height:100%;display:block}
@media (prefers-reduced-motion: no-preference){
  .elig-seal{transition:transform .4s cubic-bezier(.22,.68,0,1.1),color .3s}
  .elig-card:hover .elig-seal{transform:rotate(8deg) scale(1.06);color:var(--charcoal)}
}
.elig-card h3{font-family:var(--ff-d);font-size:1.35rem;font-weight:600;color:var(--charcoal);margin-bottom:1.1rem}
.elig-metric{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:.3rem 1rem;background:var(--gold-bg);border:1px solid rgba(201,168,76,.2);border-radius:var(--r-md);padding:.9rem 1.1rem;margin-bottom:1.4rem}
.elig-metric-label{font-size:.72rem;color:var(--muted);letter-spacing:.02em}
/* white-space:nowrap keeps the number itself from ever line-breaking
   mid-digit (e.g. "60,00" / "0") -- but that only stays safe if the
   label+value pair always has room to negotiate their layout; relying on
   flex-wrap alone to rescue a too-narrow row is exactly the fragile
   pattern that's overflowed elsewhere on this site (word-break/keep-all
   fixes earlier this session). Stacking label above value below 480px
   removes the horizontal contest entirely -- the value gets the full
   card width to itself, comfortably more than "美金60,000" ever needs. */
.elig-metric-value{font-family:var(--ff-d);font-size:1.15rem;font-weight:600;color:var(--gold-dk);white-space:nowrap}
@media(max-width:480px){.elig-metric{flex-direction:column;align-items:flex-start;gap:.35rem}}
.elig-list{display:flex;flex-direction:column;gap:.65rem}
/* Was display:flex with the bullet as a sibling flex item -- the text
   itself is a bare text node, which becomes an anonymous flex item with
   the flex default min-width:auto. That default can't be reached with a
   selector (it's not a real element) to reset to min-width:0, so on a
   long unbroken run (e.g. "业务发展及其他非信息科技领域的资深职位", no
   punctuation for word-break:keep-all to break at) the item claimed its
   full intrinsic width and overflowed the card by 160px+ instead of
   wrapping at all -- confirmed via measurement, not visual guess.
   Plain block flow + an absolutely-positioned bullet avoids the flex
   intrinsic-sizing issue entirely: the text now wraps against the li's
   actual width like normal text, engaging overflow-wrap's fallback
   break correctly when keep-all has nowhere else to break. */
.elig-list li{list-style:none;position:relative;padding-left:1.05rem;font-size:.98rem;color:var(--body);line-height:1.55}
.elig-list li::before{content:'';position:absolute;left:0;top:.6em;width:6px;height:6px;border-radius:50%;background:var(--gold)}

/* Digital Nomad eligibility grid: 2 cards on desktop, same responsive collapse as the
   base .req-grid (own breakpoints needed — see .pvp-grid comment above for why). */
.elig-grid{grid-template-columns:1fr 1fr}
@media(max-width:1024px){.elig-grid{grid-template-columns:1fr 1fr}}
@media(max-width:768px){.elig-grid{grid-template-columns:1fr}}

/* Generic centered section header — eyebrow + h2 + intro paragraph.
   Used directly (not wrapped in req-header/tiers-header/etc) on simpler
   inner pages: Employment Pass, Digital Nomad, APEC. */
.section-header{text-align:center;margin-bottom:3rem}
.section-header h2{font-size:clamp(1.9rem,3.2vw,2.8rem);color:var(--charcoal)}
.section-header h2 em{color:var(--gold-dk)}
.section-header p{font-size:1.15rem;color:var(--muted);margin-top:.7rem;max-width:590px;margin-left:auto;margin-right:auto;line-height:1.75}

/* Labuan two-column feature-list cards (Employment Pass only).
   "Agreement paper" treatment reused here — same recipe as .req-doc
   .req-card (black border, inset double-frame, flat gold border on
   hover instead of lift) — but written directly against .labuan-card
   since this component isn't built on .req-card's h3+p markup, so the
   .req-doc selector can't reach it. */
.labuan-grid{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem}
.labuan-card{
  background:var(--white);border:1px solid #1C1C1C;border-radius:6px;
  padding:2rem;position:relative;transition:border-color .25s;
}
.labuan-card:hover{border-color:#A8893C}
.labuan-card::after{content:'';position:absolute;inset:5px;border:1px solid rgba(28,28,28,.12);border-radius:3px;pointer-events:none}
.labuan-card h3{font-family:var(--ff-d);font-size:1.2rem;font-weight:400;color:var(--charcoal);margin-bottom:1.2rem;padding-bottom:.8rem;border-bottom:1px solid var(--rule)}
.labuan-card h3 em{font-style:italic;color:var(--gold-text)}
.labuan-list{display:flex;flex-direction:column;gap:.7rem}
.labuan-row{display:flex;align-items:flex-start;gap:.8rem;font-size:.82rem;color:var(--body);line-height:1.5}
.labuan-row .req-seal{width:22px;height:22px;margin-bottom:0;margin-top:.1rem;flex-shrink:0;color:var(--gold-text)}
.labuan-row strong{color:var(--charcoal)}
.labuan-sub{font-size:1.05rem;color:var(--muted);margin-top:.2rem}
@media(max-width:768px){.labuan-grid{grid-template-columns:1fr}}
@media(max-width:768px){
  .tier-wrap{overflow-x:visible;border:none;box-shadow:none;border-radius:0}
  .tier-table{min-width:0}
  .tier-table thead{display:none}
  .tier-table,.tier-table tbody,.tier-table tr,.tier-table td{display:block;width:100%}
  .tier-table tbody tr{margin-bottom:1rem;border:1px solid var(--rule);border-radius:var(--r-md);overflow:hidden;background:var(--white)!important;box-shadow:0 8px 24px rgba(0,0,0,.05)}
  .tier-table tbody tr:last-child{margin-bottom:0}
  .tier-table td{padding:.75rem 1.1rem!important;white-space:normal!important;display:flex;justify-content:space-between;align-items:baseline;gap:1rem;border-bottom:1px solid var(--rule);background:none!important;font-size:1rem}
  .tier-table td:last-child{border-bottom:none}
  /* --gold-text: 3.11:1 on --gold-bg, below the 4.5:1 AA floor (Lighthouse
     a11y audit, mobile-only rule — desktop's .tier-table never triggered it). */
  .tier-table td:first-child{background:var(--gold-bg)!important;color:var(--gold-text);font-size:.95rem;font-weight:700;display:block}
  /* Label above value (not side-by-side) so a long label like "Special
     Economic Zone" can never squeeze the value column into overflow —
     side-by-side forced the label's flex-shrink:0 pseudo-element to keep
     its full width regardless of how little room that left for the value,
     which then clipped mid-word against the card's overflow:hidden. */
  .tier-table td:not(:first-child){display:flex;flex-direction:column;align-items:flex-start;gap:.3rem;text-align:left}
  .tier-table td:not(:first-child)::before{content:attr(data-label);font-size:.62rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
  .tier-table tr.tier-group{margin-bottom:.6rem!important;border:none!important;box-shadow:none!important;background:none!important}
  .tier-table tr.tier-group td{display:block!important;padding:0 .2rem!important;background:none!important}
}

/* Mobile tier picker (MM2H's 4-tier table only) — the stacked-card layout
   above still shows all 4 tiers' values inside every criterion's card, so
   comparing "just Gold" means tracking which position is Gold across 10
   separate cards (design-critique P2, previously deferred — see git
   history). This narrows the same cards to one tier's value at a time via
   setMobileTier() in main.js, which toggles a data-tier attribute on
   .tier-wrap; no separate markup or data, so it can never drift from the
   full desktop table. "All" (no attribute) is the default, matching
   today's unfiltered view for anyone who doesn't touch the picker. */
.tier-mobile-picker{display:none}
@media(max-width:768px){
  .tier-mobile-picker{display:flex;flex-wrap:wrap;gap:.5rem;margin-bottom:1rem}
  /* Order matters here over :not() — equal-specificity rules, later one
     wins, so "hide everything" first, then "except these" after. A
     :not([data-label*="All Tiers"]) on the hide rule looks equivalent but
     actually outweighs the show rules below (their :not() argument counts
     toward specificity too), which silently re-hid the very cells these
     were meant to reveal. */
  .tier-wrap[data-tier] td[data-label]{display:none}
  .tier-wrap[data-tier] td[data-label="All Tiers"]{display:flex}
  .tier-wrap[data-tier="sez"] td[data-label*="Special Economic Zone"]{display:flex}
  .tier-wrap[data-tier="silver"] td[data-label*="Silver"]{display:flex}
  .tier-wrap[data-tier="gold"] td[data-label*="Gold"]{display:flex}
  .tier-wrap[data-tier="platinum"] td[data-label*="Platinum"]{display:flex}
}

/* Employment Pass's EP I/II/III table only (.tier-table-compare): 3 narrow
   columns instead of full stacking, so a visitor can still compare all three
   categories per criterion at a glance — the one thing this table exists
   for, per the critique that flagged the shared stacked-card treatment as a
   real loss here. Not applied to the shared .tier-table rules above: MM2H's
   4-tier table and S-MM2H's 1-column table keep the standard stacked layout,
   which fits their column count/content length better than 3-across would.
   No background wash on the EP I (.hl) column here either — same "don't
   imply a tied row is a win" restraint the desktop table already keeps
   (.tier-table td{background:none!important} above still applies). */
@media(max-width:768px){
  .tier-table-compare tbody tr{display:grid;grid-template-columns:repeat(3,1fr);gap:0}
  .tier-table-compare td:first-child{grid-column:1/-1}
  .tier-table-compare td:not(:first-child){
    padding:.65rem .5rem!important;
    font-size:.76rem;
    border-top:1px solid var(--rule);
    border-right:1px solid var(--rule);
    border-bottom:none;
  }
  .tier-table-compare td:not(:first-child):last-child{border-right:none}
  .tier-table-compare td:not(:first-child)::before{font-size:.56rem}
}

/* MM2H fee calculator */
.mm2h-calc{background:var(--white)}
.mm2h-calc-header{text-align:center;margin-bottom:2.8rem}
.mm2h-calc-header h3{font-size:clamp(1.8rem,3vw,2.6rem);color:var(--charcoal)}
.mm2h-calc-header h3 em{color:var(--gold-dk)}
.mm2h-calc-header p{font-size:1.15rem;color:var(--muted);margin-top:.7rem;max-width:570px;margin-left:auto;margin-right:auto;line-height:1.75}
/* Widened from 740px to fit .mm2h-grid's two columns (same reasoning as PVIP's
   .fee-box: give the panel the width the layout inside it actually needs). */
.mm2h-calc-wrap{max-width:1100px;margin:0 auto;background:var(--white);border:1px solid var(--rule);border-radius:var(--r-xl);padding:2.4rem 2.6rem;box-shadow:0 14px 50px rgba(0,0,0,.05)}
/* flex-wrap, not a fixed 2-column grid: #mm2hAgeRow is JS-hidden outside the SEZ
   tier (style.display toggled in mm2h.njk), so a grid track would leave a gap in
   its place — flex just lets "Select tier" reclaim the row when it's the only child. */
.mm2h-tier-cols{display:flex;flex-wrap:wrap;gap:1.8rem 3rem;margin-bottom:1.8rem}
.mm2h-tier-row{margin-bottom:0}
.mm2h-tier-label{font-size:.8rem;font-weight:600;color:var(--charcoal);margin-bottom:.7rem;display:block}
.mm2h-tier-btns{display:flex;gap:.55rem;flex-wrap:wrap}
.mm2h-tier-btn{font-family:var(--ff-b);font-weight:600;font-size:.76rem;letter-spacing:.01em;padding:.55rem 1.2rem;border-radius:50px;cursor:pointer;border:1px solid var(--rule);background:var(--off);color:var(--muted);transition:all .2s}
.mm2h-tier-btn.active{background:var(--charcoal);color:#fff;border-color:var(--charcoal)}
.mm2h-tier-btn:hover:not(.active){border-color:rgba(201,168,76,.4);color:var(--gold-dk)}
.mm2h-slider-row{display:flex;align-items:center;gap:1.2rem;margin-bottom:.6rem}
.mm2h-slider-label{font-size:.82rem;color:var(--body);min-width:110px;font-weight:500}
/* Real-world anchor for the max-15 slider, so testing extreme values still
   gives a signal on whether that count is realistic. */
.mm2h-slider-hint{font-size:.7rem;color:var(--muted);line-height:1.5;margin-bottom:1.8rem}
.mm2h-slider-row input[type="range"]{flex:1;height:36px;padding:0;margin:0;background:transparent;outline:none;-webkit-appearance:none;appearance:none;touch-action:pan-y}
.mm2h-slider-row input[type="range"]::-webkit-slider-runnable-track{height:4px;border-radius:2px;background:var(--rule)}
.mm2h-slider-row input[type="range"]::-moz-range-track{height:4px;border-radius:2px;background:var(--rule)}
.mm2h-slider-row input[type="range"]::-webkit-slider-thumb{-webkit-appearance:none;width:26px;height:26px;border-radius:50%;background:var(--gold);cursor:pointer;border:3px solid var(--white);box-shadow:0 0 0 1px var(--gold);margin-top:-11px}
.mm2h-slider-row input[type="range"]::-moz-range-thumb{width:26px;height:26px;border-radius:50%;background:var(--gold);cursor:pointer;border:3px solid var(--white);box-shadow:0 0 0 1px var(--gold)}
.mm2h-slider-out{font-family:var(--ff-d);font-size:1.3rem;color:var(--gold-dk);min-width:24px;text-align:right;font-weight:600}
/* Same checkout-style split as PVIP's .calc-grid: quick-glance cards + note pinned
   on the left (.mm2h-summary, sticky) beside the full itemization on the right
   (.mm2h-detail), instead of one long stack. Desktop-grid only — ≤860px stacks. */
.mm2h-grid{display:grid;grid-template-columns:1fr 1.3fr;gap:2.5rem;align-items:start;margin-bottom:1.8rem}
.mm2h-summary{display:flex;flex-direction:column;gap:1rem;position:sticky;top:calc(var(--nav-h, 90px) + 1.5rem)}
.mm2h-cards{display:flex;flex-direction:column;gap:.8rem}
.mm2h-card{background:var(--off);border-radius:var(--r-md);padding:1rem 1.1rem;border:1px solid var(--rule);display:flex;align-items:center;justify-content:space-between;gap:1rem}
.mm2h-card.highlight{background:var(--gold);border-color:var(--gold)}
.mm2h-card-label{font-size:.7rem;color:var(--muted)}
/* .78, not .65 — measured 3.64:1 on the gold card, below the 4.5:1 AA floor
   (Lighthouse a11y audit). .78 clears ~4.9:1 while staying visibly lighter
   than the value text below it. */
.mm2h-card.highlight .mm2h-card-label{color:rgba(28,28,28,.78)}
.mm2h-card-val{font-family:var(--ff-d);font-size:1.35rem;font-weight:600;color:var(--charcoal);white-space:nowrap}
.mm2h-card.highlight .mm2h-card-val{color:var(--charcoal)}
/* Same seal() mark as PVIP's .calc-verified — req-seal's own default color
   (--gold-text) is already the accessible-on-white choice, so no override needed
   here the way PVIP's dark panel needed one. */
.mm2h-verified{display:flex;align-items:center;gap:.55rem}
.mm2h-verified .req-seal{width:24px;height:24px;margin-bottom:0;flex-shrink:0}
.mm2h-verified span{font-size:.66rem;color:var(--muted);letter-spacing:.01em}
.mm2h-verified strong{color:var(--charcoal);font-weight:600}
.mm2h-table{width:100%;font-size:1.08rem;border-collapse:collapse}
.mm2h-table tr{border-top:1px solid var(--rule)}
.mm2h-table tr:first-child{border-top:none}
.mm2h-table td{padding:.6rem 0;color:var(--body)}
.mm2h-table td:last-child{text-align:right;font-weight:500;color:var(--charcoal)}
.mm2h-table tr.grand{border-top:2px solid var(--rule)}
.mm2h-table tr.grand td{color:var(--charcoal);font-weight:600;padding-top:.8rem;font-size:.85rem}
.mm2h-table tr.sub td{color:var(--muted);font-size:.75rem}
/* .8rem, not .95rem — sits in the narrower .mm2h-summary column now (see PVIP's
   .calc-note for the same reasoning), secondary to the cards' numbers above it. */
.mm2h-calc-note{font-size:.8rem;color:var(--muted);margin-top:0;line-height:1.6}
.mm2h-calc-note p{margin-bottom:.6rem}
.mm2h-calc-note p:last-child{margin-bottom:0;margin-top:.6rem}
.mm2h-calc-note ul{padding-left:1.2rem;margin-bottom:.6rem}
.mm2h-calc-note li{margin-bottom:.3rem}
/* .mm2h-cards is already a single-width flex column (see .mm2h-summary), so unlike
   the old 3-across grid it needs no per-breakpoint column juggling here — only the
   two-column summary/detail split has to give way, once it's too tight for both
   sides to read. */
@media(max-width:860px){.mm2h-grid{grid-template-columns:1fr;gap:1.6rem}.mm2h-summary{position:static}}
@media(max-width:768px){
  .mm2h-calc-wrap{padding:1.5rem 1.1rem}
  .mm2h-tier-btns{gap:.45rem}
  .mm2h-tier-btn{padding:.5rem .9rem;font-size:.72rem}
  .mm2h-slider-row{flex-direction:column;align-items:stretch;gap:.7rem}
  .mm2h-slider-label{min-width:0}
  .mm2h-slider-out{align-self:flex-end;font-size:1.5rem}
  .mm2h-card{padding:.9rem .95rem}
  .mm2h-card-label{font-size:.72rem}
  .mm2h-card-val{font-size:1.15rem}
  .mm2h-table{font-size:.95rem}
  .mm2h-table tr{display:flex;flex-direction:column;align-items:flex-start;padding:.65rem 0;gap:.2rem}
  .mm2h-table td{display:block;width:100%;padding:0;white-space:normal!important;word-break:break-word;text-align:left!important}
  .mm2h-table td:first-child{color:var(--muted);font-size:.8rem}
  .mm2h-table td:last-child{font-weight:600;color:var(--charcoal);font-size:1rem}
  .mm2h-table tr.grand{padding-top:.9rem}
  /* --gold-text: 3.32:1 on white, below the 4.5:1 AA floor (Lighthouse a11y
     audit, mobile-only rule — desktop's .mm2h-table uses --charcoal here). */
  .mm2h-table tr.grand td:last-child{font-size:1.05rem;color:var(--gold-text)}
  .mm2h-table tr.sub td{font-size:.75rem}
  .mm2h-table tr.sub td:last-child{font-weight:500;color:var(--muted)}
}
@media(max-width:480px){.mm2h-calc-wrap{padding:1.2rem .9rem}}

/* Required documents checklist */
.docs{background:var(--off)}
.docs-header{text-align:center;margin-bottom:2.5rem}
.docs-header h2{font-size:clamp(1.8rem,3vw,2.6rem);color:var(--charcoal)}
.docs-header h2 em{color:var(--gold-dk)}
.docs-header p{font-size:1.15rem;color:var(--muted);margin-top:.7rem;max-width:550px;margin-left:auto;margin-right:auto;line-height:1.75}
.docs-grid{max-width:700px;margin:0 auto;display:flex;flex-direction:column;gap:.7rem}
.doc-row{background:var(--white);border:1px solid var(--rule);border-radius:var(--r-md);padding:1rem 1.3rem;display:flex;align-items:center;gap:1rem;transition:border-color .2s,background .2s}
.doc-row:hover{border-color:rgba(201,168,76,.3);background:var(--gold-bg)}
/* .req-seal reused here at row scale instead of the old bare .doc-check
   circle — one visual system for "verified requirement" instead of two;
   see .req-seal's own comment above for why no filter/drop-shadow. */
.docs-grid .doc-row .req-seal{width:26px;height:26px;margin-bottom:0;flex-shrink:0;color:var(--gold-text)}
.doc-name{font-size:.84rem;font-weight:600;color:var(--charcoal)}
.doc-who{font-family:var(--ff-b);font-size:.6rem;letter-spacing:.05em;text-transform:uppercase;color:var(--gold-dk);margin-left:auto;flex-shrink:0;padding-left:1rem}
.doc-detail{font-size:1.05rem;color:var(--muted);margin-top:.15rem}
@media(max-width:768px){.doc-row{flex-wrap:wrap}.doc-who{padding-left:0;margin-left:0}}

/* Grouped-by-audience variant — was a flat list/grid of 7 equal-weight
   items where a visitor had to scan everything to find what applies to
   them. Regrouped into the 5 real audiences (all applicants / main
   applicant / 18+ / spouse / children); the group label replaces each
   item's repeated .doc-who tag, so this is shorter than 7 items as well
   as easier to scan for "what does MY situation need". */
/* Flexbox + justify-content:center, not CSS grid — 5 groups doesn't divide
   evenly into fixed columns, so a 3-col grid leaves the last row's spare
   column empty (a blank track hanging off the right, worse the wider the
   screen). Flex-wrap lets each row size to its own item count and center
   itself instead. align-items:stretch matches every card in a row to the
   row's tallest (fixes the uneven-bottoms look flex-start was giving
   short 1-doc cards next to the denser 2-doc ones) — each card then
   top-anchors its own content (below) rather than centering it, so that
   extra height reads as trailing space under a shorter card instead of
   floating its label away from the top. */
.docs-groups{display:flex;flex-wrap:wrap;justify-content:center;align-items:stretch;gap:1.1rem;max-width:960px;margin:0 auto}
/* No max-width cap: .docs-break (below) puts the 2 dense groups on their
   own row above the 3 short ones, and a capped width left that 2-card row
   narrower than the 3-card row beneath it — centered or not, the two rows
   never lined up. Uncapped, flex-grow fills each row edge to edge instead,
   so both rows span the same width and stay centered as one block.
   justify-content:flex-start (not center) matters for the same reason at
   the card level: align-items:stretch (above) matches this card's height
   to its taller row sibling, and centering its content inside that extra
   height would float the label away from the top instead of anchoring
   the checklist where a reader expects it. */
.docs-group{
  flex:1 1 280px;background:var(--white);border:1px solid var(--rule);
  border-radius:var(--r-lg);padding:1.6rem 1.4rem;
  display:flex;flex-direction:column;justify-content:flex-start;
}
/* Forces a line break after the 2 dense groups (all applicants/main
   applicant) so the 3 short one-doc groups (18+/spouse/children) wrap
   together onto their own row — same height as each other instead of
   sitting next to a taller 2-doc card. A 0-height, 100%-width flex
   item is the standard way to force a break without hardcoding when
   wrapping happens at different container widths. */
.docs-break{flex-basis:100%;width:0;height:0}
.docs-group-label{
  font-family:var(--ff-b);font-size:.66rem;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--gold-dk);margin-bottom:1.1rem;
}
/* flex-wrap:nowrap overrides the plain .doc-row's mobile flex-wrap:wrap
   (below) — that rule exists to let a .doc-who tag drop under the row on
   narrow phones, but this compact variant has no .doc-who (the group
   label replaces it, per the comment above) and was wrapping its icon
   onto its own line above the text instead, for no reason. */
.docs-group .doc-row{background:none;border:none;padding:0;display:flex;align-items:flex-start;gap:.7rem;flex-wrap:nowrap}
.docs-group .doc-row:hover{background:none}
.docs-group .doc-row + .doc-row{margin-top:.9rem}
.docs-group .req-seal{width:22px;height:22px;margin-top:.1rem;flex-shrink:0}
.docs-group .doc-detail{font-size:.92rem;margin-top:.1rem}
/* ═══════════════════════════════════════════════════════════
   DARK "PREMIUM" THEME — applied via <body class="theme-dark-premium">
   Currently used on /pvip/ only. Same component markup/classes above,
   just different token values, so nothing else has to change per-page.
═══════════════════════════════════════════════════════════ */
body.theme-dark-premium{
  --white:    #131313;
  --off:      #1A1A1A;
  --light:    #222222;
  --rule:     rgba(201,168,76,.15);
  --charcoal: #F2EDE4;
  --body:     #B0A898;
  /* #6A6A6A (near-identical to the light theme's pre-fix value) only gave ~3.2:1
     against this theme's dark --off — needs to go lighter here, not darker. */
  --muted:    #8A8A8A;
  --gold-dk:  #DFC07A;
  --gold-lt:  #EDD898;
  --gold-bg:  rgba(201,168,76,.1);
  /* This theme's --off/--white are dark, so the light-ground-only
     --gold-text darkening doesn't apply here — restore full brightness. */
  --gold-text:#C9A84C;
  /* PVIP-only accent: MM2H's hero em (--gold-lt) and PVIP's hero-stat-card num
     (--gold-dk) happened to resolve to the identical #DFC07A, so the two pages'
     heroes read as the same product with different words. This deeper, redder
     copper is still gold-family (doesn't fight the site's palette) but reads as
     a distinct, more premium mark at a glance — used only on hero elements
     that visually "sign" the page, not spread across body text. */
  --premium-copper: #C9834A;
}
body.theme-dark-premium .footer-social a{color:rgba(242,237,228,.5)}
/* :not(.active) is load-bearing: without it, this rule's added "body" type
   selector out-specifies plain .faq-cat-btn.active{color:#131313} (both are
   2 classes, but this one also has an element selector), silently turning
   the active tab's intended dark text into translucent cream on gold. */
body.theme-dark-premium .faq-cat-btn:not(.active){color:rgba(242,237,228,.6)}
/* Hero signature: distinct accent color + an angled top-left corner on the
   stat card (vs. MM2H's uniformly rounded one) so PVIP's hero reads as its
   own mark at a glance, not a reskinned copy of MM2H's. */
body.theme-dark-premium .page-hero h1 em{color:var(--premium-copper)}
body.theme-dark-premium .hero-stat-card{border-color:rgba(201,131,74,.35);border-radius:2px var(--r-lg) var(--r-lg) var(--r-lg)}
body.theme-dark-premium .hsc-num{color:var(--premium-copper)}

/* ═══════════════════════════════════════════════════════════
   APEC-ONLY COMPONENTS — member-economy flag grid, two-column
   document requirement cards. (Tab switching reuses .tier-tab/
   .tier-panel/switchTierTab() — same pattern as MM2H and Employment Pass.)
═══════════════════════════════════════════════════════════ */
.country-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:.9rem}
.country-pill{background:var(--white);border:1px solid var(--rule);border-radius:var(--r-md);padding:.85rem 1rem;font-family:var(--ff-b);font-size:.78rem;font-weight:600;letter-spacing:.02em;color:var(--charcoal);text-align:left;display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:.8rem;transition:border-color .25s,transform .25s,box-shadow .25s,background .25s;position:relative}
.country-pill:hover{border-color:rgba(201,168,76,.45);background:var(--gold-bg);color:var(--gold-dk);transform:translateY(-3px);box-shadow:0 10px 26px rgba(201,168,76,.14)}
.country-pill.transitional{border-style:dashed}
.country-pill.transitional::after{content:'†';position:absolute;top:.6rem;right:.7rem;font-family:var(--ff-b);font-size:.7rem;color:var(--muted)}
.country-code{font-weight:700;color:var(--gold-text)}
.country-name{font-weight:500;color:inherit}
.flag-icon{width:32px;height:23px;object-fit:cover;border-radius:4px;box-shadow:0 0 0 1px rgba(0,0,0,.08),0 3px 8px rgba(0,0,0,.1);flex-shrink:0}
.member-legend{display:flex;align-items:center;justify-content:center;gap:1.5rem;margin-top:1.4rem;font-size:.74rem;color:var(--muted);flex-wrap:wrap}
.legend-item{display:flex;align-items:center;gap:.45rem}
.legend-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0;border:1px solid var(--rule)}
.legend-dot.full{background:var(--off)}
.legend-dot.trans{background:transparent;border-style:dashed}
@media(max-width:1024px){.country-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:480px){.country-grid{grid-template-columns:1fr}}

/* APEC transitional-members panel: only 2 countries, so it's pinned to 2 columns on
   desktop instead of inheriting the 3-column default — own breakpoints needed (see
   .pvp-grid comment near the NAV section for why equal-specificity rules need this). */
.country-grid-2{grid-template-columns:repeat(2,1fr)}
@media(max-width:480px){.country-grid-2{grid-template-columns:1fr}}

/* Two-column document requirement cards (APEC) */
.docs-grid.two-col{max-width:none;margin:0;display:grid;grid-template-columns:1fr 1fr;gap:1.5rem}
/* "Agreement paper" treatment — same recipe as .req-doc .req-card and
   .labuan-card (black border, inset double-frame, flat gold border on
   hover instead of lift, tighter 6px radius over the sitewide default). */
.docs-card{
  background:var(--white);border:1px solid #1C1C1C;border-radius:6px;
  padding:2.2rem 2rem;position:relative;transition:border-color .25s;
}
.docs-card:hover{border-color:#A8893C}
.docs-card::after{content:'';position:absolute;inset:5px;border:1px solid rgba(28,28,28,.12);border-radius:3px;pointer-events:none}
.docs-card-header{display:flex;align-items:center;gap:.9rem;margin-bottom:1.6rem;padding-bottom:1.2rem;border-bottom:1px solid var(--rule)}
/* Same Malaysia flag on both cards, on purpose — both columns are Malaysian
   passport holders (per each card's own subtitle), just at different
   locations. The flag marks nationality, not location, so it's correct
   (and consistent) on both rather than inventing a second, mismatched icon
   for "overseas" with no single country to depict. */
.docs-card-icon{width:40px;height:40px;border-radius:50%;flex-shrink:0;background:var(--gold-bg);border:1px solid rgba(201,168,76,.2);display:flex;align-items:center;justify-content:center;font-size:1rem;overflow:hidden}
.docs-card-icon img{width:24px;height:17px;object-fit:cover;border-radius:2px}
.docs-card-title{font-size:1rem;font-weight:600;color:var(--charcoal)}
.docs-card-sub{font-size:.84rem;color:var(--muted);margin-top:.1rem}
.doc-list{display:flex;flex-direction:column;gap:.7rem}
/* flex-wrap:nowrap overrides the plain .doc-row's mobile flex-wrap:wrap
   (further up) — that rule exists to let a .doc-who tag drop under the
   row on narrow phones, but this card variant has no .doc-who and was
   wrapping its icon onto its own line above the text instead, for no
   reason (same class of bug already fixed for .docs-group .doc-row). */
.docs-card .doc-row{display:flex;align-items:flex-start;gap:.8rem;font-size:.8rem;color:var(--body);line-height:1.5;background:none;border:none;padding:0;border-radius:0;flex-wrap:nowrap}
.docs-card .doc-row:hover{background:none;border-color:transparent}
.docs-card .doc-row .req-seal{width:20px;height:20px;margin-bottom:0;margin-top:.1rem;flex-shrink:0;color:var(--gold-text)}
.doc-extra{margin-top:.35rem;padding-left:1rem;border-left:2px solid var(--rule);font-size:.74rem;color:var(--muted);line-height:1.5}
.doc-extra li{margin-bottom:.15rem}
.docs-card .doc-row.unique{background:var(--gold-bg);border-radius:var(--r-sm);padding:.55rem .7rem}
@media(max-width:1024px){.docs-grid.two-col{grid-template-columns:1fr}}

/* ═══════════════════════════════════════════════════════════
   ABOUT US-ONLY COMPONENTS
═══════════════════════════════════════════════════════════ */
/* Who We Are intro photo block */
.who-inner{display:grid;grid-template-columns:1fr 1fr;gap:5vw;align-items:center}
.who-h2{font-family:var(--ff-d);font-size:clamp(1.9rem,3.2vw,2.8rem);font-weight:300;color:var(--charcoal);line-height:1.12;margin-bottom:1.1rem}
.who-h2 em{font-style:italic;color:var(--gold-dk)}
.who-p{font-size:1.2rem;color:var(--body);line-height:1.85;margin-bottom:1rem}
.who-p:last-of-type{margin-bottom:0}
.who-license-note{margin-top:1.8rem;padding:1.1rem 1.5rem;background:var(--gold-bg);border:1px solid rgba(201,168,76,.3);border-radius:var(--r-sm);font-size:.8rem;color:var(--body);line-height:1.6;display:flex;gap:.8rem;align-items:flex-start}
.who-license-note .mini-seal{width:22px;height:22px;flex-shrink:0;margin-top:.15rem;color:var(--gold-dk)}
.who-license-note .mini-seal svg{width:100%;height:100%}
.who-license-note strong{color:var(--charcoal)}
.who-img-block{position:relative;border-radius:var(--r-xl);overflow:hidden;min-height:440px;box-shadow:0 20px 60px rgba(0,0,0,.12)}
.who-img-block img{width:100%;height:100%;object-fit:cover;filter:brightness(.85) saturate(.9)}
.who-img-badge{position:absolute;bottom:1.6rem;left:1.6rem;right:1.6rem;background:rgba(28,28,28,.85);backdrop-filter:blur(10px);border-radius:var(--r-md);padding:1.2rem 1.4rem;display:flex;align-items:center;gap:1rem}
.wib-num{font-family:var(--ff-d);font-size:2.4rem;font-weight:700;color:var(--gold-dk);line-height:1}
.wib-text{font-size:.78rem;color:rgba(255,255,255,.7);line-height:1.4}
.wib-text strong{display:block;color:#fff;font-size:.84rem;font-weight:600;margin-bottom:.1rem}
@media(max-width:1024px){.who-inner{grid-template-columns:1fr;gap:3rem}.who-img-block{order:-1;min-height:320px}}

/* Government appointment certificates */
.certs-header{text-align:center;margin-bottom:2.8rem}
.certs-header h2{font-size:clamp(1.8rem,3vw,2.6rem);color:var(--charcoal)}
.certs-header h2 em{color:var(--gold-dk)}
.certs-header p{font-size:1.15rem;color:var(--muted);margin-top:.6rem;max-width:550px;margin-left:auto;margin-right:auto;line-height:1.7}
.certs-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:1.4rem}
/* Was three nested boxes (card > image-wrap > image, all near-identical
   off-white/bordered/rounded) reading as muddy double-borders around real
   government certificates. One frame now, using the site's "agreement
   paper" recipe (black border, inset mat-line, flat gold hover) — a fitting
   reuse since these genuinely are paper documents. The inset ::after line
   does the "matting" job the old .cert-image-wrap box existed for, so the
   image needs no box of its own and no separate drop-shadow. */
.cert-card{
  background:var(--off);border:1px solid #1C1C1C;border-radius:6px;
  padding:1.6rem 1.6rem 2rem;text-align:center;position:relative;
  transition:border-color .25s;
}
.cert-card:hover{border-color:#A8893C}
.cert-card::after{content:'';position:absolute;inset:5px;border:1px solid rgba(28,28,28,.12);border-radius:3px;pointer-events:none}
.cert-image{display:block;margin:0 auto 1.4rem;max-width:100%;max-height:480px;width:auto;height:auto;border-radius:2px}
.cert-card h3{font-size:.95rem;font-weight:600;color:var(--charcoal);margin-bottom:.5rem}
.cert-card p{font-size:1.1rem;color:var(--muted);line-height:1.75}
@media(max-width:1024px){.certs-grid{grid-template-columns:1fr}}

/* CEO personal message */
.ceo-message{background:var(--charcoal);position:relative;overflow:hidden}
.ceo-message::before{content:'';position:absolute;top:-30%;right:-8%;width:580px;height:580px;border-radius:50%;background:radial-gradient(ellipse,rgba(201,168,76,.09) 0%,transparent 68%);pointer-events:none}
.ceo-inner{display:grid;grid-template-columns:.85fr 1.4fr;gap:4vw;align-items:start;position:relative}
.ceo-photo-block{text-align:center}
.ceo-photo{width:330px;height:330px;border-radius:50%;margin:0 auto 1.2rem;background:rgba(201,168,76,.1);border:2px solid rgba(201,168,76,.3);display:block;object-fit:cover;object-position:center top}
.ceo-name{font-size:1.1rem;font-weight:600;color:#fff;margin-bottom:.2rem}
.ceo-title{font-family:var(--ff-b);font-size:.68rem;letter-spacing:.1em;text-transform:uppercase;color:rgba(201,168,76,.7)}
.ceo-text .eyebrow{color:rgba(201,168,76,.8)}
.ceo-text h2{font-family:var(--ff-d);font-size:clamp(1.8rem,3vw,2.6rem);font-weight:300;color:#fff;line-height:1.15;margin-bottom:1.3rem}
.ceo-text h2 em{font-style:italic;color:var(--gold-lt)}
.ceo-text p{font-size:1.2rem;color:rgba(255,255,255,.55);line-height:1.85;margin-bottom:1rem}
.ceo-text p:last-of-type{margin-bottom:0}
.ceo-signature{margin-top:1.6rem;padding-top:1.4rem;border-top:1px solid rgba(255,255,255,.1)}
.ceo-signature-name{font-family:var(--ff-d);font-size:1.3rem;font-style:italic;color:var(--gold-lt)}
.ceo-signature-title{font-size:.75rem;color:rgba(255,255,255,.4);margin-top:.2rem}
@media(max-width:1024px){
  .ceo-photo{width:260px;height:260px}
}
@media(max-width:768px){
  .ceo-inner{grid-template-columns:1fr;gap:2.5rem}
  .ceo-photo-block{text-align:left;display:flex;align-items:center;gap:1.2rem}
  .ceo-photo{margin:0;width:180px;height:180px}
}
@media(max-width:520px){.ceo-photo-block{flex-direction:column;text-align:center}.ceo-photo{margin:0 auto 1rem}}

/* Leadership team — static wrapping grid. Was a horizontal scroll-snap row;
   switched because all 6 people are equally "the team" and the scroll hid
   Justin Chan and Yu Juin Foo behind a fade with no indication more existed. */
.team{background:var(--off);position:relative}
.team-header{text-align:center;margin-bottom:3rem}
.team-header h2{font-size:clamp(1.9rem,3.2vw,2.8rem);color:var(--charcoal)}
.team-header h2 em{color:var(--gold-dk)}
.team-header p{font-size:1.15rem;color:var(--muted);margin-top:.7rem;max-width:530px;margin-left:auto;margin-right:auto;line-height:1.75}
.team-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:1.1rem}
.team-card{background:var(--white);border:1px solid var(--rule);border-radius:var(--r-lg);padding:1.8rem 1.2rem;text-align:center;transition:border-color .25s,transform .25s,box-shadow .25s}
.team-card:hover{border-color:rgba(201,168,76,.3);transform:translateY(-3px);box-shadow:0 10px 28px rgba(201,168,76,.08)}
/* Wrapper does the circular clipping; the img inside is free to scale/shift
   for a tighter crop (see about-us.njk) without growing the circle itself —
   object-position alone can't "zoom," only choose which part of the already-
   cover-scaled image shows. */
.team-avatar{width:150px;height:150px;border-radius:50%;margin:0 auto 1rem;background:var(--gold-bg);border:1px solid rgba(201,168,76,.25);overflow:hidden}
.team-avatar img{width:100%;height:100%;display:block;object-fit:cover;object-position:center top}
.team-name{font-size:.88rem;font-weight:600;color:var(--charcoal);margin-bottom:.25rem}
.team-role{font-family:var(--ff-b);font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;color:var(--gold-text)}

/* Client privileges */
.priv-header{text-align:center;margin-bottom:3rem}
.priv-header h2{font-size:clamp(1.9rem,3.2vw,2.8rem);color:var(--charcoal)}
.priv-header h2 em{color:var(--gold-dk)}
.priv-header p{font-size:1.15rem;color:var(--muted);margin-top:.7rem;max-width:550px;margin-left:auto;margin-right:auto;line-height:1.75}
.priv-pills{display:flex;justify-content:center;gap:.7rem;margin-bottom:3rem;flex-wrap:wrap}
.priv-pill{font-family:var(--ff-b);font-size:.68rem;letter-spacing:.06em;background:var(--gold-bg);border:1px solid rgba(201,168,76,.25);color:var(--gold-dk);padding:.45rem 1.2rem;border-radius:50px}
.priv-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1.4rem}
/* Same structure as the homepage's .why-card: seal-ring + meaningful glyph
   (not a generic checkmark — these three items aren't a checklist, so the
   real icon carries more information) plus a faint corner number for the
   same soft, non-prescriptive rhythm .why-card uses on its own 01-06.
   .why-card-top/.why-card-icon/.why-seal-ring/.why-seal-glyph/.why-card-num
   are reused directly (defined once, ~line 380) rather than duplicated. */
.priv-card{
  background:var(--off);border-radius:var(--r-md);
  padding:2.2rem 1.8rem;
  box-shadow:0 1px 2px rgba(0,0,0,.04);
  transition:transform .3s var(--ease),box-shadow .3s var(--ease);
}
.priv-card:hover{transform:translateY(-6px);box-shadow:0 20px 40px rgba(0,0,0,.1)}
.priv-card h3{font-size:1rem;font-weight:600;color:var(--charcoal);margin-bottom:.5rem}
.priv-card p{font-size:1.12rem;color:var(--body);line-height:1.75}
@media(max-width:1024px){.priv-grid{grid-template-columns:1fr}}

/* Business partner logos */
.partners-header{text-align:center;margin-bottom:2.5rem}
.partners-header h2{font-size:clamp(1.8rem,3vw,2.6rem);color:var(--charcoal)}
.partners-header h2 em{color:var(--gold-dk)}
.partner-cat{margin-bottom:2.2rem}
.partner-cat:last-child{margin-bottom:0}
.partner-cat-label{font-family:var(--ff-b);font-size:.65rem;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);margin-bottom:1rem;display:block;text-align:center}
.partner-logos{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:1.8rem 2.4rem}
.partner-logo{font-family:var(--ff-b);font-size:.7rem;letter-spacing:.06em;padding:.5rem;color:var(--muted);transition:transform .2s;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.6rem;min-height:5rem}
.partner-logo:hover{transform:translateY(-2px)}
.partner-logo img{height:64px;width:auto;max-width:260px;object-fit:contain;display:block;image-rendering:-webkit-optimize-contrast}
.partner-logo-name{font-size:.72rem;letter-spacing:.05em;color:var(--muted);text-align:center}
@media(max-width:768px){
  .partner-logos{display:grid;grid-template-columns:repeat(2,1fr);gap:.5rem;justify-items:center;align-items:center}
  .partner-logo{min-height:4.4rem;width:100%}
  .partner-logo img{height:44px;max-width:80%}
  .partner-cat{margin-bottom:1.6rem}
  /* An odd logo count leaves the grid's last row with a single tile stuck
     in the left column and a dead gap beside it. Span it across both
     columns instead so a lone leftover centers itself like the flex
     layout above 768px already does automatically. Self-correcting if a
     partner is ever added/removed: only fires when last-child's own
     position is odd, i.e. it really is alone in its row. */
  .partner-logo:last-child:nth-child(odd){grid-column:1 / -1}
}

/* ═══════════════════════════════════════════════════════════
   NEWS & BLOG — shared listing-page components
═══════════════════════════════════════════════════════════ */
.subtab-nav{background:var(--white);border-bottom:1px solid var(--rule);padding:0 6vw;display:flex;align-items:center;position:sticky;top:64px;z-index:100}
.subtab{font-family:var(--ff-b);font-size:.7rem;letter-spacing:.09em;text-transform:uppercase;padding:1.1rem 1.5rem;color:var(--muted);border-bottom:2px solid transparent;transition:color .2s,border-color .2s;display:flex;align-items:center;gap:.45rem;white-space:nowrap}
.subtab:hover{color:var(--charcoal)}
/* --gold-text on the text, --gold stays on the border (decorative, no contrast
   rule applies there): measured 3.32:1 on white, below the 4.5:1 AA floor. */
.subtab.active{color:var(--gold-text);border-bottom-color:var(--gold);font-weight:600}
.filter-bar{background:var(--off);padding:1.2rem 6vw;display:flex;align-items:center;gap:.6rem;flex-wrap:wrap;border-bottom:1px solid var(--rule)}
.filter-btn{font-family:var(--ff-b);font-weight:600;font-size:.74rem;letter-spacing:.01em;padding:.4rem 1rem;border-radius:50px;border:1px solid var(--rule);background:var(--white);color:var(--muted);cursor:pointer;transition:all .2s}
.filter-btn.active{background:var(--charcoal);color:#fff;border-color:var(--charcoal)}
.filter-btn:hover:not(.active){border-color:rgba(201,168,76,.4);color:var(--gold-dk)}
.filter-search{position:relative;margin-left:auto;flex:1 1 180px;min-width:160px;max-width:260px}
.filter-search svg{position:absolute;left:.9rem;top:50%;transform:translateY(-50%);width:14px;height:14px;stroke:var(--muted);pointer-events:none}
.filter-search input{width:100%;font-family:var(--ff-b);font-size:.78rem;color:var(--charcoal);background:var(--white);border:1px solid var(--rule);border-radius:50px;padding:.5rem 1rem .5rem 2.1rem;outline:none;transition:border-color .2s}
.filter-search input::placeholder{color:var(--muted)}
.filter-search input:focus{border-color:rgba(201,168,76,.4)}
.filter-search input::-webkit-search-cancel-button{cursor:pointer}
@media(max-width:600px){.filter-search{margin-left:0;max-width:none;flex-basis:100%}}
.article-meta{display:flex;align-items:center;gap:.7rem;font-size:1.04rem;color:var(--muted)}
.meta-dot{width:3px;height:3px;border-radius:50%;background:var(--rule)}
.grid-header{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:2rem}
.grid-header h3{font-family:var(--ff-d);font-size:1.5rem;font-weight:300;color:var(--charcoal)}
.grid-header h3 em{font-style:italic;color:var(--gold-dk)}

/* Blog: hero post + card grid + sidebar */
.hero-post{background:var(--white);padding:3.5rem 6vw}
.hero-post-card{display:grid;grid-template-columns:1.1fr 1fr;gap:3.5rem;align-items:center;max-width:1100px}
.hero-post-img{border-radius:var(--r-xl);overflow:hidden;position:relative;aspect-ratio:16/10}
.hero-post-img img{width:100%;height:100%;object-fit:cover;transition:transform .6s var(--ease)}
.hero-post-card:hover .hero-post-img img{transform:scale(1.04)}
/* --gold-text: measured 3.11:1 on --gold-bg, below the 4.5:1 AA floor. */
.blog-cat{display:inline-flex;font-family:var(--ff-b);font-weight:600;font-size:.68rem;letter-spacing:.03em;text-transform:uppercase;background:var(--gold-bg);border:1px solid rgba(201,168,76,.3);color:var(--gold-text);padding:.25rem .7rem;border-radius:50px;margin-bottom:.9rem}
.hero-post-content h2{font-family:var(--ff-d);font-size:clamp(1.7rem,2.8vw,2.4rem);font-weight:300;color:var(--charcoal);line-height:1.2;margin-bottom:.9rem}
.hero-post-content h2 em{font-style:italic;color:var(--gold-dk)}
.hero-post-content p{font-size:1.2rem;color:var(--body);line-height:1.8;margin-bottom:1.2rem}
/* --gold-text: measured 3.32:1 on white, below the 4.5:1 AA floor. */
.read-link{display:inline-flex;align-items:center;gap:.4rem;font-size:.8rem;font-weight:600;color:var(--gold-text);margin-top:1.2rem;transition:gap .2s}
.read-link:hover{gap:.7rem}
.blog-grid-wrap{background:var(--off);padding:3.5rem 6vw}
.blog-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1.3rem}
.blog-card{position:relative;background:var(--white);border:1px solid var(--rule);border-radius:var(--r-lg);overflow:hidden;display:flex;flex-direction:column;transition:border-color .25s,transform .25s,box-shadow .25s}
.blog-card:hover{border-color:rgba(201,168,76,.3);transform:translateY(-4px);box-shadow:0 14px 36px rgba(201,168,76,.08)}
.blog-card.hidden{display:none}
.blog-card-img{height:200px;overflow:hidden;position:relative;background:var(--light)}
/* Same third-party-thumbnail tint as .card-img img — see that rule's comment. */
.blog-card-img img{width:100%;height:100%;object-fit:cover;filter:brightness(.86) saturate(.85);transition:transform .5s var(--ease),filter .5s var(--ease)}
.blog-card:hover .blog-card-img img{transform:scale(1.05);filter:brightness(1) saturate(1)}
.blog-card-body{padding:1.5rem;flex:1;display:flex;flex-direction:column}
.blog-card-cat{display:inline-block;font-family:var(--ff-b);font-weight:600;font-size:.66rem;letter-spacing:.02em;text-transform:uppercase;background:var(--gold-bg);border:1px solid rgba(201,168,76,.2);color:var(--gold-dk);padding:.2rem .55rem;border-radius:50px;margin-bottom:.7rem}
.blog-card-title{font-family:var(--ff-d);font-size:1.08rem;font-weight:400;color:var(--charcoal);line-height:1.3;margin-bottom:.6rem;flex:1}
.blog-card-excerpt{font-size:.78rem;color:var(--muted);line-height:1.6;margin-bottom:1rem;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.blog-card-meta{font-family:var(--ff-b);font-size:.72rem;letter-spacing:.01em;color:var(--muted);display:flex;align-items:center;gap:.5rem;margin-top:auto;padding-top:.9rem;border-top:1px solid var(--rule)}
.read-min{color:var(--gold-dk)}
.blog-layout{display:grid;grid-template-columns:1fr 280px;gap:2.5rem;align-items:start}
.topics-sidebar{position:sticky;top:120px}
.topics-card{background:var(--white);border:1px solid var(--rule);border-radius:var(--r-lg);padding:1.5rem}
/* Matches both tags: the article layouts (news.njk/blog-post.njk) use h3 now —
   fixed a heading-order skip, h2 straight to h4 (Lighthouse a11y audit) — but
   blog.njk's own index-page sidebar and webinar.njk still use h4 correctly for
   their own heading context, untested and unchanged. */
.topics-card h3,.topics-card h4{font-family:var(--ff-b);font-size:.65rem;letter-spacing:.12em;text-transform:uppercase;color:var(--charcoal);margin-bottom:1.1rem}
.topic-list{display:flex;flex-direction:column;gap:.4rem}
.topic-item{width:100%;text-align:left;display:flex;align-items:center;justify-content:space-between;padding:.5rem .6rem;border-radius:var(--r-sm);cursor:pointer;transition:background .2s;font-size:.8rem;color:var(--body)}
.topic-item:hover{background:var(--gold-bg);color:var(--gold-dk)}
.topic-count{font-family:var(--ff-b);font-size:.62rem;color:var(--muted);background:var(--off);border-radius:50px;padding:.1rem .5rem}
.cta-sidebar{background:var(--charcoal);border-radius:var(--r-lg);padding:1.6rem;margin-top:1.2rem;text-align:center}
.cta-sidebar h3,.cta-sidebar h4{font-family:var(--ff-d);font-size:1.2rem;font-weight:300;color:#fff;margin-bottom:.6rem}
.cta-sidebar h3 em,.cta-sidebar h4 em{font-style:italic;color:var(--gold-lt)}
/* .45 -> .5: measured 4.43:1 on --charcoal, just short of the 4.5:1 AA floor
   (Lighthouse a11y audit on an article page). */
.cta-sidebar p{font-size:1.08rem;color:rgba(255,255,255,.5);line-height:1.65;margin-bottom:1.1rem}
.cta-sidebar a{display:block;background:var(--gold);color:#131313;font-size:.78rem;font-weight:600;padding:.75rem 1.2rem;border-radius:50px;transition:background .2s}
.cta-sidebar a:hover{background:var(--gold-dk)}
@media(max-width:1100px){.blog-layout{grid-template-columns:1fr}.topics-sidebar{position:static}.blog-grid{grid-template-columns:1fr 1fr}}
@media(max-width:768px){.hero-post-card{grid-template-columns:1fr;gap:2rem}.blog-grid{grid-template-columns:1fr}}

/* News: featured article + card grid */
.featured{background:var(--white);padding:3.5rem 6vw}
.featured-card{display:grid;grid-template-columns:1fr 1fr;gap:0;border-radius:var(--r-xl);overflow:hidden;background:var(--charcoal);box-shadow:0 20px 60px rgba(0,0,0,.12)}
.featured-img{position:relative;min-height:360px;overflow:hidden}
.featured-img img{width:100%;height:100%;object-fit:cover;filter:brightness(.75) saturate(.85);transition:transform .6s var(--ease)}
.featured-card:hover .featured-img img{transform:scale(1.04)}
.featured-img-overlay{position:absolute;inset:0;background:linear-gradient(to right,transparent 60%,rgba(28,28,28,.85))}
.featured-content{padding:2.8rem 2.6rem;display:flex;flex-direction:column;justify-content:center}
.news-cat{display:inline-flex;font-family:var(--ff-b);font-weight:600;font-size:.68rem;letter-spacing:.03em;text-transform:uppercase;background:rgba(201,168,76,.15);border:1px solid rgba(201,168,76,.3);color:var(--gold-text);padding:.25rem .7rem;border-radius:50px;margin-bottom:.9rem;align-self:flex-start}
.featured-content h2{font-family:var(--ff-d);font-size:clamp(1.6rem,2.5vw,2.2rem);font-weight:300;color:#fff;line-height:1.2;margin-bottom:.8rem}
.featured-content h2 em{font-style:italic;color:var(--gold-lt)}
.featured-content p{font-size:1.16rem;color:rgba(255,255,255,.5);line-height:1.75;margin-bottom:1.5rem}
.featured .article-meta{color:rgba(255,255,255,.38)}
.featured .meta-dot{background:rgba(255,255,255,.25)}
.read-more{display:inline-flex;align-items:center;gap:.4rem;font-size:.8rem;font-weight:600;color:var(--gold-text);margin-top:1.2rem;transition:gap .2s}
.read-more:hover{gap:.7rem}
.article-grid-wrap{background:var(--off);padding:3.5rem 6vw}
.article-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1.3rem}
.article-card{position:relative;background:var(--white);border:1px solid var(--rule);border-radius:var(--r-lg);overflow:hidden;transition:border-color .25s,transform .25s,box-shadow .25s;display:flex;flex-direction:column}
.article-card:hover{border-color:rgba(201,168,76,.3);transform:translateY(-4px);box-shadow:0 14px 36px rgba(201,168,76,.08)}
.article-card.hidden{display:none}
.card-img{position:relative;height:180px;overflow:hidden;background:var(--light)}
/* Thumbnails are pulled from third-party og:image tags (scripts/fetch-news.js) —
   wire photos and, often, an outlet's own headline graphic baked into the pixels.
   Tint/desaturate every one the same way .featured-img already does above, so a
   grid of mismatched sources reads as one product and any baked-in caption text
   recedes behind our own card-cat badge and card-title instead of competing. */
.card-img img{width:100%;height:100%;object-fit:cover;filter:brightness(.86) saturate(.85);transition:transform .5s var(--ease),filter .5s var(--ease)}
.article-card:hover .card-img img{transform:scale(1.05);filter:brightness(1) saturate(1)}
.card-img::after{content:'';position:absolute;inset:0;background:linear-gradient(180deg,rgba(20,18,15,.4) 0%,rgba(20,18,15,0) 42%,rgba(20,18,15,0) 100%);pointer-events:none}
.card-body{padding:1.4rem;flex:1;display:flex;flex-direction:column}
.card-cat{display:inline-block;font-family:var(--ff-b);font-weight:600;font-size:.66rem;letter-spacing:.02em;text-transform:uppercase;background:var(--gold-bg);border:1px solid rgba(201,168,76,.2);color:var(--gold-dk);padding:.2rem .55rem;border-radius:50px;margin-bottom:.7rem}
.card-img .card-cat{position:absolute;top:.8rem;left:.8rem;z-index:2;margin-bottom:0;background:rgba(20,18,15,.68);border-color:rgba(255,255,255,.28);color:#fff;backdrop-filter:blur(3px)}
.card-title{font-family:var(--ff-d);font-size:1.05rem;font-weight:400;color:var(--charcoal);line-height:1.3;margin-bottom:.6rem;flex:1}
.card-excerpt{font-size:.78rem;color:var(--muted);line-height:1.6;margin-bottom:1rem;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.card-meta{font-family:var(--ff-b);font-size:.72rem;letter-spacing:.01em;color:var(--muted);display:flex;align-items:center;gap:.4rem;margin-top:auto}
.card-meta svg{width:12px;height:12px;stroke:var(--muted);fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;flex-shrink:0}
/* Announcements past a year old shouldn't read at the same weight as this
   week's — see the isStale filter in .eleventy.js. */
.card-meta.stale,.article-meta.stale{opacity:.55}
@media(max-width:1024px){.featured-card{grid-template-columns:1fr}.featured-img{min-height:260px;order:-1}.featured-img-overlay{background:linear-gradient(to bottom,transparent 60%,rgba(28,28,28,.85))}.article-grid{grid-template-columns:1fr 1fr}}
@media(max-width:768px){.article-grid{grid-template-columns:1fr}}

/* News/Blog pagination */
.page-nav{display:flex;align-items:center;justify-content:center;gap:1.6rem;margin-top:2.8rem}
/* --gold-text: measured 3.32:1 on white, below the 4.5:1 AA floor. */
.page-nav-btn{font-family:var(--ff-b);font-size:.82rem;font-weight:600;color:var(--gold-text);background:var(--white);padding:.65rem 1.3rem;border:1px solid var(--rule);border-radius:50px;cursor:pointer;transition:border-color .2s,background .2s}
.page-nav-btn:hover{border-color:rgba(201,168,76,.4);background:var(--gold-bg)}
.page-nav-btn:disabled{opacity:.35;cursor:not-allowed;background:var(--white)}
.page-nav-btn:disabled:hover{border-color:var(--rule);background:var(--white)}
.page-nav.single-page{display:none}
.page-nav-count{font-family:var(--ff-b);font-size:.7rem;color:var(--muted);letter-spacing:.03em}

/* News/Blog article detail page */
.article-body-wrap{background:var(--white);padding:3rem 6vw 4rem}
.article-body{max-width:760px;margin:0 auto;font-size:1.02rem;line-height:1.85;color:var(--body)}
.article-hero-img{width:100%;border-radius:var(--r-lg);margin-bottom:2rem;object-fit:cover;max-height:460px}
.article-body p{margin-bottom:1.3rem}
.article-body h2,.article-body h3,.article-body h4{font-family:var(--ff-d);color:var(--charcoal);font-weight:500;line-height:1.3;margin:2rem 0 1rem}
.article-body ul,.article-body ol{margin:0 0 1.3rem 1.3rem}
.article-body li{margin-bottom:.4rem}
.article-body a{color:var(--gold-dk);text-decoration:underline}
.article-body blockquote{border-left:2px solid var(--rule);padding-left:1.2rem;color:var(--muted);font-style:italic;margin:1.5rem 0}
.article-body img{max-width:100%;border-radius:var(--r-md);margin:1.2rem 0}
.article-body iframe{max-width:100%;border-radius:var(--r-md);margin:1.2rem 0}
.article-body address{font-style:normal}

/* ============================================================
   Per-type article detail pages: News / Blog / Webinar
   Shared header + sidebar pattern, distinct hero per type.
   ============================================================ */
/* --gold-text: measured 3.11:1 on --gold-bg, below the 4.5:1 AA floor
   (Lighthouse a11y audit on an article page). */
.news-tag,.article-cat{display:inline-flex;align-items:center;gap:.35rem;font-family:var(--ff-b);font-weight:600;font-size:.7rem;letter-spacing:.02em;text-transform:uppercase;padding:.3rem .8rem;border-radius:50px;margin-bottom:1.1rem;background:var(--gold-bg);border:1px solid rgba(201,168,76,.3);color:var(--gold-text)}
.article-cat.webinar-cat{background:#EFF3FF;border-color:#C6D6FA;color:#4A63C9}
.article-meta-row{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap;font-family:var(--ff-b);font-size:.82rem;color:var(--muted);padding-bottom:1.8rem;border-bottom:1px solid var(--rule)}
.article-meta-row .meta-dot{width:3px;height:3px;border-radius:50%;background:var(--rule)}
.share-row{display:flex;gap:.5rem;margin-left:auto}
.share-btn{width:30px;height:30px;border-radius:50%;border:1px solid var(--rule);display:flex;align-items:center;justify-content:center;font-size:.68rem;color:var(--muted);transition:border-color .2s,color .2s,background .2s;background:none;padding:0;font-family:inherit;cursor:pointer}
.share-btn:hover{border-color:var(--gold);color:var(--gold-dk);background:var(--gold-bg)}
.share-btn.copied{border-color:var(--gold);color:var(--gold-dk);background:var(--gold-bg)}

/* News/webinar simple header (no dek, no featured image bleed) */
.article-header{max-width:1160px;margin:0 auto;padding:8rem 6vw 0}
.article-header h1{font-family:var(--ff-d);font-size:clamp(2rem,4vw,2.9rem);font-weight:600;color:var(--charcoal);line-height:1.22;margin-bottom:1.1rem;max-width:760px}
.article-header .breadcrumb,.article-hero .breadcrumb{color:var(--muted)}
.article-header .breadcrumb a,.article-hero .breadcrumb a{color:var(--body)}
.article-header .breadcrumb a:hover,.article-hero .breadcrumb a:hover{color:var(--gold-text)}

/* Blog hero (dek + author block, feature image bleeds below) */
.article-hero{position:relative;padding:8.5rem 6vw 0;background:var(--off);overflow:hidden}
.article-hero-inner{position:relative;z-index:2;max-width:820px;margin:0 auto;padding-bottom:3rem}
.article-hero h1{font-family:var(--ff-d);font-size:clamp(2.4rem,4.6vw,3.6rem);font-weight:300;color:var(--charcoal);line-height:1.14;margin-bottom:1.3rem;max-width:760px}
.article-hero h1 em{font-style:italic;color:var(--gold-dk)}
.article-hero .dek{font-size:1.1rem;color:var(--body);line-height:1.75;max-width:640px;margin-bottom:1.8rem}
.article-hero .article-meta-row{justify-content:space-between;padding-top:1.6rem;border-top:1px solid var(--rule);border-bottom:none;padding-bottom:0}
.author-block{display:flex;align-items:center;gap:.7rem}
.author-avatar{width:38px;height:38px;border-radius:50%;background:var(--charcoal);color:var(--gold-lt);display:flex;align-items:center;justify-content:center;font-family:var(--ff-d);font-size:.95rem;font-weight:600;flex-shrink:0}
.author-name{font-size:.85rem;font-weight:600;color:var(--charcoal)}
.author-sub{font-family:var(--ff-b);font-size:.76rem;color:var(--muted);letter-spacing:.01em}
.article-feature-img{max-width:1000px;margin:0 auto;padding:0 6vw 3.5rem}
.article-feature-img .img-frame{aspect-ratio:16/8;border-radius:var(--r-xl);box-shadow:0 24px 60px rgba(0,0,0,.1)}
.img-caption{font-family:var(--ff-b);font-size:.68rem;color:var(--muted);text-align:center;margin-top:.9rem}

/* Shared two-column layout */
.article-wrap{background:var(--white);padding:0 6vw 5rem}
.article-layout{display:grid;grid-template-columns:1fr 280px;gap:3.5rem;max-width:1160px;margin:0 auto;align-items:start;padding-top:2.2rem}
/* Unnamed wrapper around the article body: a wide prose table (even one
   already wrapped in .table-scroll) still forces this grid item to its
   min-content width unless it's told it's allowed to shrink, which blew
   the whole article column out past the viewport on mobile. */
.article-layout>div:first-child{min-width:0}
.article-sidebar{position:sticky;top:140px;display:flex;flex-direction:column;gap:1.3rem}

.news-img,.poster-hero-wrap{margin-bottom:2rem}
.news-img .img-frame{aspect-ratio:16/9;border-radius:var(--r-lg)}

/* Full-bleed hero image frame: shows the whole photo (never cropped) via
   object-fit:contain, with a blurred/darkened copy of the same photo filling
   the backdrop so there's no flat letterbox bars on non-matching aspect ratios. */
.img-frame{position:relative;overflow:hidden;background-size:cover;background-position:center}
.img-frame::before{content:'';position:absolute;inset:-15%;background-image:inherit;background-size:cover;background-position:center;filter:blur(35px) brightness(.65) saturate(1.15);transform:scale(1.1)}
.img-frame img{position:relative;z-index:1;width:100%;height:100%;object-fit:contain;display:block}
.poster-hero{border-radius:var(--r-xl);overflow:hidden;box-shadow:0 20px 50px rgba(0,0,0,.12);border:1px solid var(--rule);max-width:380px;aspect-ratio:4/5;margin:0 auto 2rem;background:var(--off);display:flex;align-items:center;justify-content:center}
.poster-hero img{width:100%;height:100%;object-fit:contain}

.prose{max-width:100%;font-size:1.08rem;color:var(--body);line-height:1.8;overflow-wrap:anywhere}
.prose > * + *{margin-top:1.25rem}
.prose h2{font-family:var(--ff-d);font-size:1.9rem;font-weight:700;color:var(--charcoal);line-height:1.3;margin-top:2.4rem}
.prose h3{font-family:var(--ff-d);font-size:1.4rem;font-weight:500;color:var(--charcoal);line-height:1.3;margin-top:2rem}
.prose ul{list-style:disc;padding-left:1.3rem;margin-top:1rem}
.prose ol{list-style:decimal;padding-left:1.3rem;margin-top:1rem}
.prose li{margin-top:.5rem}
.prose li::marker{color:var(--gold-dk);font-weight:600}
/* --gold-text on the text itself; the underline stroke stays the lighter gold
   since it's decorative, not the thing being read — measured 3.32:1 on white,
   below the 4.5:1 AA floor (Lighthouse a11y audit on an article page). */
.prose a{color:var(--gold-text);text-decoration:underline;text-decoration-color:rgba(201,168,76,.4)}
.prose strong,.prose b{color:var(--charcoal);font-weight:600}
.prose h4{font-family:var(--ff-d);font-size:1.4rem;font-weight:500;color:var(--charcoal);line-height:1.3;margin-top:2rem}
.prose blockquote{border:1px solid rgba(201,168,76,.25);background:var(--gold-bg);padding:1.2rem 1.5rem;border-radius:var(--r-md);font-family:var(--ff-d);font-size:1.15rem;font-style:italic;color:var(--charcoal);line-height:1.6}
.prose blockquote p{margin-top:0}
.prose blockquote p+p{margin-top:.8rem}
.prose blockquote cite{display:block;margin-top:.6rem;font-family:var(--ff-b);font-size:.68rem;font-style:normal;letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}
.prose img{border-radius:var(--r-lg);width:100%;margin-top:1.6rem}
.prose iframe{width:100%;aspect-ratio:16/9;height:auto;border:0;border-radius:var(--r-lg);margin-top:1.6rem}
.prose table{width:100%;border-collapse:collapse;margin-top:1.6rem;font-size:.95rem}
.prose table caption{caption-side:top;text-align:left;font-family:var(--ff-b);font-size:.7rem;letter-spacing:.05em;text-transform:uppercase;color:var(--muted);margin-bottom:.6rem}
.prose th,.prose td{border:1px solid var(--rule);padding:.7rem 1rem;text-align:left;vertical-align:top}
.prose th{background:var(--off);font-family:var(--ff-b);font-size:.7rem;letter-spacing:.04em;text-transform:uppercase;color:var(--charcoal);font-weight:600}
.prose tbody tr:nth-child(even){background:var(--off)}
.prose .table-scroll{overflow-x:auto;margin-top:1.6rem}
.prose .table-scroll table{margin-top:0}

/* CMS content blocks (partials/prose.njk) */
.content-block-img{margin-top:1.6rem}
.content-block-img .img-frame{border-radius:var(--r-lg);aspect-ratio:16/9}
.content-block-img .img-frame img{margin-top:0;border-radius:0}
.content-block-img figcaption{margin-top:.6rem;font-family:var(--ff-b);font-size:.72rem;color:var(--muted);text-align:center}
.callout{border-radius:var(--r-md);padding:1.1rem 1.4rem;border:1px solid rgba(201,168,76,.3);background:var(--gold-bg)}
.callout-title{display:block;font-family:var(--ff-d);font-weight:600;color:var(--charcoal);margin-bottom:.3rem}
.callout p{margin-top:0}
.callout p+p{margin-top:.6rem}
.callout-note{background:#EAF2FA;border-color:#4A83B4}
.callout-warning{background:#FBEDEA;border-color:#C0523A}
.pull-stat{display:flex;gap:2rem;background:var(--off);border:1px solid var(--rule);border-radius:var(--r-lg);padding:1.8rem 2rem;margin-top:2rem;flex-wrap:wrap}
.pull-stat div{flex:1;min-width:140px}
.pull-stat .num{font-family:var(--ff-d);font-size:2.2rem;font-weight:600;color:var(--gold-dk);line-height:1}
.pull-stat .lbl{font-family:var(--ff-b);font-size:.64rem;letter-spacing:.05em;text-transform:uppercase;color:var(--muted);margin-top:.5rem}
.source-box{background:var(--off);border:1px solid var(--rule);border-radius:var(--r-md);padding:1.1rem 1.4rem;margin-top:1.6rem;font-size:.85rem;color:var(--body)}
.source-box b{color:var(--charcoal)}

.tag-row{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:2.2rem;padding-top:1.6rem;border-top:1px solid var(--rule)}
.tag{font-family:var(--ff-b);font-weight:600;font-size:.72rem;padding:.32rem .85rem;border-radius:50px;background:var(--off);border:1px solid var(--rule);color:var(--body)}
.author-card{max-width:100%;margin-top:2.5rem;background:var(--off);border-radius:var(--r-lg);padding:1.8rem;display:flex;gap:1.2rem;align-items:flex-start}
.author-card .author-avatar{width:52px;height:52px;font-size:1.2rem}
/* h2, not h5: this post body has no h2 subsections of its own, so h1 -> h5
   skipped four levels (Lighthouse a11y audit on a blog-post page). h2 is the
   correct next level after the h1 title. */
.author-card h2{font-family:var(--ff-d);font-size:1.15rem;font-weight:600;color:var(--charcoal);margin-bottom:.3rem}
.author-card p{font-size:.85rem;color:var(--muted);line-height:1.6}

/* Webinar register / ended card */
.register-sticky{background:var(--charcoal);border-radius:var(--r-lg);padding:1.5rem;position:relative;overflow:hidden}
.register-sticky::before{content:'';position:absolute;top:-30%;right:-15%;width:200px;height:200px;border-radius:50%;background:radial-gradient(ellipse,rgba(201,168,76,.14) 0%,transparent 70%)}
.rs-row{position:relative;display:flex;align-items:flex-start;gap:.6rem;margin-bottom:.8rem}
.rs-row:last-child{margin-bottom:0}
.rs-icon{width:26px;height:26px;border-radius:50%;background:rgba(201,168,76,.15);border:1px solid rgba(201,168,76,.35);display:flex;align-items:center;justify-content:center;font-size:.7rem;flex-shrink:0}
.rs-label{font-family:var(--ff-b);font-size:.56rem;letter-spacing:.05em;text-transform:uppercase;color:rgba(255,255,255,.4)}
.rs-value{font-size:.82rem;color:#fff;font-weight:500}
.register-sticky a.rs-btn{position:relative;display:block;background:var(--gold);color:#131313;font-size:.78rem;font-weight:600;padding:.75rem 1rem;border-radius:50px;text-align:center;margin-top:1rem;transition:background .2s}
.register-sticky a.rs-btn:hover{background:var(--gold-dk)}
.seats-note{position:relative;font-family:var(--ff-b);font-size:.6rem;color:rgba(255,255,255,.4);text-align:center;margin-top:.7rem}
.rs-ended-badge{position:relative;display:inline-flex;align-items:center;gap:.35rem;font-family:var(--ff-b);font-weight:600;font-size:.72rem;letter-spacing:.02em;text-transform:uppercase;color:var(--gold-lt);background:rgba(201,168,76,.14);border:1px solid rgba(201,168,76,.35);padding:.32rem .75rem;border-radius:50px;margin-bottom:1.1rem}
.rs-ended-title{position:relative;font-family:var(--ff-d);font-size:1.2rem;font-weight:300;color:#fff;line-height:1.35;margin-bottom:.7rem}
.rs-ended-title em{font-style:italic;color:var(--gold-lt)}
.rs-ended-note{position:relative;font-size:.82rem;color:rgba(255,255,255,.55);line-height:1.6;margin-bottom:0}

/* Webinar reminder popup — site-wide */
.wp-overlay{position:fixed;inset:0;display:none;align-items:center;justify-content:center;padding:5vw;background:rgba(28,28,28,.72);backdrop-filter:blur(3px);z-index:1000}
.wp-overlay:not([hidden]){display:flex;animation:fadeIn .25s var(--ease) both}
.wp-modal{position:relative;background:var(--white);border-radius:var(--r-lg);max-width:420px;width:100%;overflow:hidden;box-shadow:0 24px 70px rgba(0,0,0,.28);animation:fadeUp .35s .05s var(--ease) both}
.wp-image{display:block;width:100%;aspect-ratio:16/9;object-fit:cover}
.wp-body{padding:2.2rem}
.wp-close{position:absolute;top:1rem;right:1rem;width:30px;height:30px;border-radius:50%;background:rgba(255,255,255,.9);color:var(--muted);font-size:.85rem;display:flex;align-items:center;justify-content:center;transition:background .2s,color .2s;backdrop-filter:blur(4px)}
.wp-close:hover{background:var(--white);color:var(--charcoal)}
.wp-badge{display:inline-flex;align-items:center;gap:.35rem;font-family:var(--ff-b);font-weight:600;font-size:.7rem;letter-spacing:.02em;text-transform:uppercase;padding:.3rem .8rem;border-radius:50px;margin-bottom:1rem;background:var(--gold-bg);border:1px solid rgba(201,168,76,.3);color:var(--gold-dk)}
.wp-title{display:block;font-family:var(--ff-d);font-size:1.5rem;font-weight:600;line-height:1.3;color:var(--charcoal);margin-bottom:1.2rem;transition:color .2s}
.wp-title:hover{color:var(--gold-dk)}
.wp-row{display:flex;align-items:flex-start;gap:.6rem;margin-bottom:.8rem}
.wp-row:last-of-type{margin-bottom:1.4rem}
.wp-icon{width:26px;height:26px;border-radius:50%;background:var(--gold-bg);border:1px solid rgba(201,168,76,.3);display:flex;align-items:center;justify-content:center;font-size:.7rem;flex-shrink:0}
.wp-label{font-family:var(--ff-b);font-size:.6rem;letter-spacing:.05em;text-transform:uppercase;color:var(--muted)} /* was .56rem = 10.64px, below the 11px accessibility floor */
.wp-value{font-size:.82rem;color:var(--charcoal);font-weight:500}
.wp-cta{display:flex;justify-content:center;width:100%}

/* WhatsApp widget — site-wide, matches apply.mypvip.com's floating button.
   Fixed bottom-right on every page, so it permanently occupies that corner
   of the viewport at whatever content happens to scroll underneath. The
   tooltip used to render open at all times, turning a 56px circle into a
   ~230px pill+circle footprint over page content for no interaction benefit;
   it now only appears on hover/focus, same as any other icon-button label. */
.wa-widget{position:fixed;right:1.4rem;bottom:1.4rem;z-index:400;display:flex;align-items:center;gap:.7rem}
.wa-tooltip{background:rgba(255,255,255,.9);backdrop-filter:blur(6px);padding:.55rem 1rem;border-radius:50px;font-size:.82rem;font-weight:500;color:#1C1C1C;box-shadow:0 8px 24px rgba(0,0,0,.14);white-space:nowrap;opacity:0;transform:translateX(6px);pointer-events:none;transition:opacity .2s var(--ease),transform .2s var(--ease)}
.wa-widget:hover .wa-tooltip,.wa-widget:focus-within .wa-tooltip{opacity:1;transform:translateX(0)}
.wa-btn{width:56px;height:56px;flex-shrink:0;border-radius:50%;background:#25D366;color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 12px 28px -8px rgba(37,211,102,.6);transition:transform .2s}
.wa-btn:hover{transform:scale(1.08)}
@media(max-width:640px){.wa-tooltip{display:none}.wa-widget{right:1rem;bottom:1rem}.wa-btn{width:48px;height:48px}}

/* More news / related articles — full width below layout */
.more-news,.related-wrap{background:var(--off);padding:4rem 6vw;border-top:1px solid var(--rule)}
.more-news-header,.related-header{max-width:1160px;margin:0 auto 1.6rem}
.more-news-header h3,.related-header h3{font-family:var(--ff-d);font-size:1.6rem;font-weight:300}
.more-news-header h3 em,.related-header h3 em{font-style:italic;color:var(--gold-dk)}
.more-news-list{max-width:1160px;margin:0 auto;display:flex;flex-direction:column}
.news-row{display:flex;align-items:center;gap:1.3rem;padding:1.1rem 0;border-bottom:1px solid var(--rule)}
.news-row:last-child{border-bottom:none}
.news-row-img{width:96px;height:70px;border-radius:var(--r-sm);overflow:hidden;flex-shrink:0;background:var(--light)}
.news-row-img img{width:100%;height:100%;object-fit:cover}
.news-row-body{flex:1;min-width:0}
.news-row-tag{font-family:var(--ff-b);font-weight:600;font-size:.68rem;letter-spacing:.02em;text-transform:uppercase;color:var(--gold-dk);display:block;margin-bottom:.3rem}
.news-row-title{font-size:.94rem;font-weight:600;color:var(--charcoal);line-height:1.35}
.news-row-date{font-family:var(--ff-b);font-size:.74rem;color:var(--muted);white-space:nowrap;flex-shrink:0}
.related-grid{max-width:1160px;margin:0 auto;display:grid;grid-template-columns:repeat(3,1fr);gap:1.3rem}

@media(max-width:1100px){.article-layout{grid-template-columns:1fr}.article-sidebar{position:static;display:flex;flex-direction:row;flex-wrap:wrap;min-width:0}.article-sidebar>*{flex:1;min-width:240px}.related-grid{grid-template-columns:1fr 1fr}}
@media(max-width:768px){.article-header{padding:7.5rem 5vw 0}.article-hero{padding:7.5rem 5vw 0}.article-meta-row{flex-wrap:wrap}.share-row{margin-left:0}.news-row{flex-wrap:wrap}.news-row-date{margin-left:auto}.related-grid{grid-template-columns:1fr}.poster-hero{max-width:220px}}

/* ═══════════════════════════════════════════════════════════
   FREE CONSULTATION PAGE (/free-consultation/)
   6-step wizard reusing .form-card/.form-step/.goal-opt from the old
   homepage quiz, plus both the PVIP and MM2H calculators verbatim
   (only one shown at a time, decided by computeRecommendation() in
   main.js). Card is wider (960px vs. the homepage's ~600px) than the
   old quiz card specifically so the calculators' own 2-column layout
   (.calc-grid/.mm2h-grid, designed for a full-width page section) has
   room to breathe instead of being squeezed into a narrow sidebar.
═══════════════════════════════════════════════════════════ */
.fc-wizard{background:var(--off)}
.fc-wizard-wrap{max-width:1200px;margin:0 auto}
/* Button/slider steps (1,2,3,4) stay narrow and centered even though the
   card itself is wide — only step 5 (calculator) and step 6 (2-col
   contact fields) actually need the fuller width. */
.fc-narrow{max-width:560px;margin:0 auto}
/* Tag used to be its own 2rem heading line above a second headline
   sentence repeating the same programme name — cut to one inline line
   ("PVIP looks like your strongest fit.") plus tighter gaps throughout,
   so this whole block + the toggle below fit in one screen instead of
   pushing the calculator halfway down the next scroll. */
.fc-recommend{text-align:center;margin-bottom:1rem}
.fc-recommend-tag{font-family:var(--ff-d);font-weight:700;color:var(--gold-dk)}
.fc-recommend-headline{font-size:1.05rem;color:var(--charcoal);line-height:1.5;max-width:560px;margin:0 auto .7rem}
.fc-recommend-reasons{list-style:none;text-align:left;max-width:560px;margin:0 auto;display:flex;flex-direction:column;gap:.45rem}
.fc-recommend-reasons li{display:flex;gap:.7rem;font-size:.88rem;color:var(--body);line-height:1.45}
.fc-recommend-reasons li::before{content:"\2713";flex-shrink:0;color:var(--gold-dk);font-weight:700}

/* Lets a visitor peek at the other programme's calculator even though one
   is recommended — both embeds are pre-filled the moment step 5 loads,
   this just toggles which is visible. */
.fc-calc-toggle{display:flex;gap:.6rem;justify-content:center;margin-bottom:1.1rem}
.fc-calc-toggle-btn{
  border:1px solid var(--rule);background:var(--white);border-radius:50px;
  padding:.6rem 1.4rem;font-size:.85rem;font-weight:600;color:var(--muted);
  cursor:pointer;transition:border-color .2s,background .2s,color .2s;
}
.fc-calc-toggle-btn:hover{border-color:var(--gold)}
.fc-calc-toggle-btn.active{border-color:var(--gold);background:var(--gold-bg);color:var(--gold-dk)}
.fc-calc-toggle-btn.recommended::after{
  content:"Recommended";display:block;font-size:.6rem;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--gold-text);margin-top:.15rem;
}
.fc-calc-embed{margin-top:1.8rem}
/* Step 3's own dependants slider reuses .calc-slider-row/-label from the
   PVIP calculator, but that calculator lives on a dark panel — its label
   is white-on-transparent and invisible against this step's white
   .form-card. Scoped override, not a change to the shared class (the
   two calculator embeds below still need the original white label). */
.fc-slider-onlight .calc-slider-label{color:var(--charcoal)}
/* Track color was rgba(255,255,255,.2) for the calculator's dark
   background — invisible (white-on-white) on this step's white card. */
.fc-slider-onlight input[type="range"]::-webkit-slider-runnable-track{background:var(--rule)}
.fc-slider-onlight input[type="range"]::-moz-range-track{background:var(--rule)}
@media(max-width:600px){.fc-wizard-wrap .form-card{padding:1.6rem 1.3rem}}

/* Short steps (goal/income buttons) used to float vertically centered in
   a tall 560px-min-height card — that sizing was for the old homepage
   quiz sitting next to a map, which this page doesn't do. Card sizes to
   its content and top-aligns instead. */
.fc-wizard-wrap .form-card{min-height:0;justify-content:flex-start}
/* The 960px card width exists for steps 5/6 (calculator's 2-col grid,
   contact form's 2-col fields) — every other step only holds a ~560px
   narrow column, so the full-width card left a huge empty strip beside
   the content. Card defaults to a width that hugs the narrow content;
   goToFcStep() in main.js adds .fc-wide only for steps 5/6. */
.fc-wizard-wrap .form-card{max-width:680px;margin:0 auto}
.fc-wizard-wrap .form-card.fc-wide{max-width:960px}
/* Step 5's calculator (.fee-box/.mm2h-calc-wrap) wants ~1120px on its
   source pages (/pvip/, /mm2h/) — squeezed into the 960px card its
   labels wrapped ("Participation fees" onto 2 lines). Widen just this
   step so it gets the room it was actually designed for. */
.fc-wizard-wrap .form-card.fc-xwide{max-width:1200px}

/* Cover screen (fcStep0) — plain, matches the wizard's own .form-card
   instead of a dark photo hero. See the WIZARD comment in
   free-consultation.njk for why this page diverges from .page-hero. */
.fc-cover-crumb{color:var(--muted);margin-bottom:1.4rem}
.fc-cover-crumb a{color:var(--body)}
.fc-cover-crumb a:hover{color:var(--gold-text)}
.fc-cover-title{font-size:clamp(1.9rem,3.2vw,2.6rem);color:var(--charcoal);margin-bottom:.9rem}
.fc-cover-title em{font-style:italic;color:var(--gold-dk)}
.fc-cover-sub{font-size:1rem;color:var(--muted);line-height:1.75;margin-bottom:1.8rem}
.fc-cover-list-label{font-size:.72rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--gold-text);margin-bottom:.9rem}
.fc-cover-list{list-style:none;display:flex;flex-direction:column;gap:.7rem;margin-bottom:2rem}
.fc-cover-list li{display:flex;align-items:center;gap:.7rem;font-size:.92rem;color:var(--body)}

/* Progress stepper — replaces the old plain "Step X of 6" text label.
   Circles connect via .fc-stepper-line; goToFcStep() in main.js toggles
   .done/.active on each .fc-stepper-item as the visitor advances. Hidden
   on the cover screen (fcStep0), shown for steps 1-6. */
.fc-stepper{list-style:none;display:flex;align-items:flex-start;margin-bottom:2.2rem}
.fc-stepper[hidden]{display:none}
.fc-stepper-item{position:relative;display:flex;flex-direction:column;align-items:center;flex-shrink:0}
.fc-stepper-circle{
  width:26px;height:26px;border-radius:50%;border:2px solid var(--rule);
  display:flex;align-items:center;justify-content:center;background:var(--white);
  color:var(--gold-dk);transition:border-color .25s,background .25s;
}
.fc-stepper-circle svg{display:none;width:13px;height:13px;stroke:currentColor;fill:none;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
.fc-stepper-item.active .fc-stepper-circle{border-color:var(--gold);background:var(--gold)}
.fc-stepper-item.done .fc-stepper-circle{border-color:var(--gold);background:var(--gold-bg)}
.fc-stepper-item.done .fc-stepper-circle svg{display:block}
/* Only the active step's label is shown visually (matches the reference
   pattern); inactive labels stay in the DOM, visually clipped, so screen
   readers can still read every step name. */
.fc-stepper-label{
  position:absolute;width:1px;height:1px;padding:0;margin:0;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0;
  font-size:.68rem;color:var(--charcoal);font-weight:600;top:34px;
}
.fc-stepper-item.active .fc-stepper-label{
  position:static;width:auto;height:auto;overflow:visible;clip:auto;margin-top:.5rem;white-space:nowrap;
}
.fc-stepper-line{flex:1;height:2px;background:var(--rule);margin:12px .35rem 0;transition:background .25s}
.fc-stepper-line.done{background:var(--gold)}
@media(max-width:600px){
  .fc-stepper-circle{width:20px;height:20px}
  .fc-stepper-circle svg{width:10px;height:10px}
  .fc-stepper-line{margin-top:9px}
  .fc-stepper-item.active .fc-stepper-label{font-size:.6rem}
}

/* ===== Page-section side nav (visa-programme pages, partials/side-nav.njk) =====
   Mobile-first: base rules below are the <1600px drawer (default CLOSED).
   The >=1600px override further down replaces it with a slim rail docked in
   the page's own side margin, default OPEN. The toggle button always just
   flips whichever class is the "non-default" one for the current breakpoint
   (.side-nav--open on mobile, .side-nav--closed on desktop) — see main.js.
   The panel sizes itself to its own content (width:max-content, height:auto,
   each capped with a max- limit + scroll fallback) instead of a hardcoded
   box, so it never shows dead space past the last link. Because the size is
   therefore content-dependent, neither the toggle tab's `left` nor <main>'s
   push-over margin can be a fixed CSS number either — main.js measures the
   panel's real rendered width on load, on toggle, and on resize, and writes
   it to the --side-nav-actual-w custom property (also setting the toggle's
   `left` inline) so both track wherever the panel's edge actually lands. */
.side-nav-toggle{
  position:fixed;left:0;top:50%;transform:translateY(-50%);z-index:240;
  display:flex;align-items:center;justify-content:center;
  width:32px;height:56px;border:1px solid var(--rule);border-left:none;
  border-radius:0 var(--r-sm) var(--r-sm) 0;
  background:var(--white);color:var(--gold-text);
  box-shadow:2px 0 12px rgba(0,0,0,.08);cursor:pointer;
  transition:left .3s var(--ease);
}
/* Icon direction is one rule for every breakpoint: closed = arrow points
   away from the panel, outward toward the space it'll expand into; open =
   arrow points back at the panel, inward toward where it'll collapse to. */
.side-nav-toggle svg{transition:transform .3s var(--ease)}
.side-nav-toggle--open svg{transform:rotate(180deg)}

.side-nav-backdrop{
  position:fixed;inset:0;z-index:220;
  /* Dark + blurred, not just dimmed: a plain 40% tint left large hero
     headings legible right up to the drawer's edge, so a word straddling
     that edge read as sliced in half (opaque behind the panel, ghosted
     past it). Strong enough that nothing behind it is legible removes the
     artifact instead of tuning around it. */
  background:rgba(10,9,7,.72);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  opacity:0;pointer-events:none;transition:opacity .3s var(--ease);
}
.side-nav--open .side-nav-backdrop{opacity:1;pointer-events:auto}

.side-nav-panel{
  position:fixed;top:50%;left:0;z-index:230;
  width:max-content;max-width:min(80vw,300px);
  max-height:calc(100vh - 4rem);overflow-y:auto;
  background:var(--white);box-shadow:8px 0 32px rgba(0,0,0,.15);
  border-radius:0 var(--r-lg) var(--r-lg) 0;
  padding:2rem 1.75rem;
  transform:translate(-100%,-50%);transition:transform .3s var(--ease);
}
.side-nav--open .side-nav-panel{transform:translate(0,-50%)}

.side-nav-title{
  font-family:var(--ff-b);font-size:.63rem;letter-spacing:.18em;text-transform:uppercase;
  color:var(--gold-text);display:block;padding:0 .6rem;margin-bottom:1rem;
}
.side-nav-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.15rem}
.side-nav-list a{
  display:block;padding:.6rem .6rem;border-radius:var(--r-sm);
  font-family:var(--ff-b);font-size:.72rem;font-weight:600;line-height:1.4;
  letter-spacing:.06em;text-transform:uppercase;color:var(--muted);
}
.side-nav-list a:hover{background:var(--gold-bg);color:var(--charcoal)}
.side-nav-list a.active{color:var(--gold-text);background:var(--gold-bg)}

@media(min-width:1600px){
  .side-nav-backdrop{display:none}
  /* "Sits in the margin, no overlay" turned out not to have real free
     margin to sit in at this breakpoint — hero/heading content runs close
     to the edge on these pages (confirmed visually at 1800px: a
     floating-in-the-gutter version overlapped the H1). Reserving actual
     layout space by pushing <main> over, instead of assuming pre-existing
     whitespace, is what actually guarantees zero overlap. #sideNav and
     <main> are siblings under <body> (see base.njk) so ~ reaches it. */
  /* Animating margin-left (a layout property) is normally avoided in favor
     of transform — but transform doesn't reserve space, and reserving real
     space is the entire point of this rule (see the comment above). This
     only ever fires once, on a toggle click, not on scroll or anything
     frequent, so the reflow cost is a non-issue in practice. --side-nav-actual-w
     is written by main.js from the panel's real offsetWidth — it varies by
     page since each page's nav labels are a different length. */
  #sideNav ~ main{margin-left:calc(var(--side-nav-actual-w,190px) + 22px);transition:margin-left .3s var(--ease)}
  #sideNav.side-nav--closed ~ main{margin-left:0}
  .side-nav-panel{
    top:96px;left:0;max-height:calc(100vh - 96px - 2rem);width:max-content;max-width:260px;
    transform:none;
    background:var(--white);box-shadow:4px 0 24px rgba(0,0,0,.06);
    border:1px solid var(--rule);border-left:none;border-radius:0 var(--r-lg) var(--r-lg) 0;
    padding:1.75rem 1.25rem;
    transition:opacity .3s var(--ease),transform .3s var(--ease);
  }
  .side-nav--closed .side-nav-panel{transform:translateX(-100%);opacity:0;pointer-events:none}
  .side-nav-list a{font-size:.68rem;padding:.5rem .55rem}
}

/* ══ 404 PAGE ═══════════════════════════════════════════════
   Same dark/gold treatment as .cta-block (deepest section on the site)
   so a lost visitor still reads this as MYPVIP, not a broken host. */
.notfound{background:var(--ink-deep);min-height:70vh;display:flex;align-items:center;justify-content:center;text-align:center;padding:6rem 6vw;position:relative;overflow:hidden}
.notfound::before{content:'';position:absolute;top:-30%;left:-8%;width:500px;height:500px;border-radius:50%;background:radial-gradient(ellipse,rgba(201,168,76,.08) 0%,transparent 68%);pointer-events:none}
.notfound-inner{position:relative;max-width:560px}
.notfound-num{font-family:var(--ff-d);font-size:clamp(4rem,10vw,7rem);font-weight:300;color:var(--gold-lt);line-height:1;margin-bottom:.5rem}
.notfound h1{font-family:var(--ff-d);font-size:clamp(1.6rem,3vw,2.4rem);font-weight:300;color:#fff;line-height:1.2;margin-bottom:1rem}
.notfound h1 em{font-style:italic;color:var(--gold-lt)}
.notfound p{font-size:1.05rem;color:rgba(255,255,255,.55);line-height:1.75;margin-bottom:2.2rem}
.notfound-btns{display:flex;justify-content:center;gap:.9rem;flex-wrap:wrap}
