@charset "UTF-8";
/* ==========================================================================
   Kim Bangkok Property — design system
   Light mode only. One spacing scale, one type scale, one palette.
   Tokens derived from resource/design-reference.png.
   ========================================================================== */

/* --- fonts: self-hosted, thai + latin subsets only ----------------------- */
@font-face{font-family:"Prompt";font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/prompt-500-thai.woff2) format("woff2");unicode-range:U+02D7,U+0303,U+0331,U+0E01-0E5B,U+200C-200D,U+25CC}
@font-face{font-family:"Prompt";font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/prompt-500-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Prompt";font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/prompt-600-thai.woff2) format("woff2");unicode-range:U+02D7,U+0303,U+0331,U+0E01-0E5B,U+200C-200D,U+25CC}
@font-face{font-family:"Prompt";font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/prompt-600-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Prompt";font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/prompt-700-thai.woff2) format("woff2");unicode-range:U+02D7,U+0303,U+0331,U+0E01-0E5B,U+200C-200D,U+25CC}
@font-face{font-family:"Prompt";font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/prompt-700-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Sarabun";font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/sarabun-400-thai.woff2) format("woff2");unicode-range:U+02D7,U+0303,U+0331,U+0E01-0E5B,U+200C-200D,U+25CC}
@font-face{font-family:"Sarabun";font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/sarabun-400-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Sarabun";font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/sarabun-500-thai.woff2) format("woff2");unicode-range:U+02D7,U+0303,U+0331,U+0E01-0E5B,U+200C-200D,U+25CC}
@font-face{font-family:"Sarabun";font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/sarabun-500-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Sarabun";font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/sarabun-600-thai.woff2) format("woff2");unicode-range:U+02D7,U+0303,U+0331,U+0E01-0E5B,U+200C-200D,U+25CC}
@font-face{font-family:"Sarabun";font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/sarabun-600-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}

/* --- tokens -------------------------------------------------------------- */
:root{
  /* palette */
  --navy:#0E2A47; --navy-700:#16395D; --navy-500:#2B5480; --navy-050:#EDF2F8;
  --gold:#C8A44B; --gold-600:#AD8A34; --gold-050:#FBF6E9;
  --ink:#1B2733; --body:#465565; --muted:#6C7A8A; --faint:#9AA7B4;
  --bg:#FFFFFF; --bg-alt:#F8F6F2; --bg-tint:#F2F5F9;
  --line:#E2E7EE; --line-strong:#CBD4DF;
  --line-green:#06C755; --wechat-green:#07C160;
  --ok:#1B8A4B; --warn:#B4762A;

  /* type scale (fluid) */
  --f-xs:.8125rem; --f-sm:.9375rem; --f-base:1.0625rem;
  --f-lg:clamp(1.125rem,.35vw + 1.05rem,1.25rem);
  --f-h4:clamp(1.1875rem,.5vw + 1.08rem,1.375rem);
  --f-h3:clamp(1.3125rem,.9vw + 1.12rem,1.625rem);
  --f-h2:clamp(1.5rem,1.7vw + 1.15rem,2.125rem);
  --f-h1:clamp(1.875rem,3vw + 1.2rem,3rem);
  --f-display:clamp(2.125rem,4vw + 1.25rem,3.5rem);

  /* spacing scale */
  --s1:.25rem; --s2:.5rem; --s3:.75rem; --s4:1rem; --s5:1.5rem;
  --s6:2rem; --s7:2.5rem; --s8:3rem; --s9:4rem; --s10:5rem; --s11:7rem;

  /* shape + depth */
  --r-sm:6px; --r:10px; --r-lg:16px; --r-pill:999px;
  --sh-sm:0 1px 2px rgba(14,42,71,.06),0 1px 3px rgba(14,42,71,.05);
  --sh:0 2px 6px rgba(14,42,71,.07),0 8px 20px rgba(14,42,71,.06);
  --sh-lg:0 8px 24px rgba(14,42,71,.10),0 24px 48px rgba(14,42,71,.08);

  --wrap:1200px; --wrap-narrow:760px;
  --header-h:64px;
  --ease:cubic-bezier(.2,.7,.3,1);
  --dur:.22s;
}

/* --- reset --------------------------------------------------------------- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  margin:0;background:var(--bg);color:var(--body);
  font-family:"Sarabun",system-ui,-apple-system,"Segoe UI",sans-serif;
  font-size:var(--f-base);line-height:1.75;
  -webkit-font-smoothing:antialiased;overflow-x:clip;
}
h1,h2,h3,h4,h5,h6{
  font-family:"Prompt",system-ui,sans-serif;color:var(--navy);
  margin:0 0 var(--s4);line-height:1.25;font-weight:600;text-wrap:balance;
}
h1{font-size:var(--f-h1);font-weight:700;letter-spacing:-.02em}
h2{font-size:var(--f-h2);font-weight:700;letter-spacing:-.01em}
h3{font-size:var(--f-h3)}
h4{font-size:var(--f-h4)}
p{margin:0 0 var(--s4)}
p:last-child{margin-bottom:0}
a{color:var(--navy-500);text-underline-offset:.18em;text-decoration-thickness:1px}
a:hover{color:var(--navy)}
img{max-width:100%;height:auto;display:block}
ul,ol{margin:0 0 var(--s4);padding-left:1.35em}
li{margin-bottom:var(--s2)}
li:last-child{margin-bottom:0}
strong,b{font-weight:600;color:var(--ink)}
small{font-size:var(--f-sm)}
hr{border:0;border-top:1px solid var(--line);margin:var(--s7) 0}
table{border-collapse:collapse;width:100%}
button{font:inherit;color:inherit}

:focus-visible{outline:3px solid var(--gold);outline-offset:2px;border-radius:2px}
::selection{background:var(--gold-050);color:var(--navy)}

/* Chinese: Sarabun/Prompt carry no CJK glyphs, and CJK does not wrap on spaces. */
:lang(zh){
  font-family:"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Noto Sans SC","Source Han Sans SC",system-ui,sans-serif;
  line-height:1.85;
}
:lang(zh) h1,:lang(zh) h2,:lang(zh) h3,:lang(zh) h4,:lang(zh) h5,:lang(zh) h6{
  font-family:"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Noto Sans SC",system-ui,sans-serif;
  letter-spacing:0;line-height:1.4;
}
:lang(zh) .btn{overflow-wrap:anywhere;word-break:break-word}

.skip{position:absolute;left:-9999px;top:0;z-index:200;background:var(--navy);color:#fff;padding:var(--s3) var(--s4);border-radius:0 0 var(--r) 0}
.skip:focus{left:0}
.vh{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* --- layout -------------------------------------------------------------- */
.container{width:100%;max-width:var(--wrap);margin-inline:auto;padding-inline:var(--s4)}
.container--narrow{max-width:var(--wrap-narrow)}
.section{padding-block:clamp(2.5rem,6vw,var(--s10))}
.section--alt{background:var(--bg-alt)}
.section--tint{background:var(--bg-tint)}
.section--navy{background:var(--navy);color:#C9D6E4}
.section--navy h2,.section--navy h3{color:#fff}
.section__head{max-width:70ch;margin-bottom:var(--s6)}
.eyebrow{
  font-family:"Prompt",sans-serif;font-size:var(--f-xs);font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--gold-600);
  margin:0 0 var(--s2);display:flex;align-items:center;gap:var(--s3);
}
.eyebrow::before{content:"";width:28px;height:2px;background:var(--gold);flex:none}
.lede{font-size:var(--f-lg);color:var(--body)}
.grid{display:grid;gap:var(--s5)}
.grid--2{grid-template-columns:1fr}
.grid--3{grid-template-columns:1fr}
.grid--4{grid-template-columns:1fr}
.prose>*+h2{margin-top:var(--s8)}
.prose>*+h3{margin-top:var(--s6)}
.prose{max-width:74ch}

/* --- buttons ------------------------------------------------------------- */
/* Content-sized, wrap-allowed, never nowrap or ellipsis: long Thai and Chinese
   CTA labels must be able to grow without spilling out of the button. */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s2);
  padding:var(--s3) var(--s5);min-height:48px;max-width:100%;
  font-family:"Prompt",sans-serif;font-size:var(--f-sm);font-weight:600;line-height:1.35;
  text-align:center;text-decoration:none;border:1px solid transparent;border-radius:var(--r-sm);
  cursor:pointer;transition:background var(--dur) var(--ease),color var(--dur) var(--ease),
    border-color var(--dur) var(--ease),transform var(--dur) var(--ease);
  overflow-wrap:break-word;
}
.btn:hover{transform:translateY(-1px)}
.btn:active{transform:translateY(0)}
.btn .icon{width:20px;height:20px;flex:none}
.btn--line{background:var(--line-green);color:#fff}
.btn--line:hover{background:#05b34d;color:#fff}
.btn--wechat{background:var(--wechat-green);color:#fff}
.btn--wechat:hover{background:#06ad56;color:#fff}
.btn--phone{background:transparent;color:var(--navy);border-color:var(--line-strong)}
.btn--phone:hover{background:var(--navy-050);color:var(--navy);border-color:var(--navy-500)}
.btn--navy{background:var(--navy);color:#fff}
.btn--navy:hover{background:var(--navy-700);color:#fff}
.btn--gold{background:var(--gold);color:#26200C}
.btn--gold:hover{background:var(--gold-600);color:#fff}
.btn--ghost{background:#fff;color:var(--navy);border-color:var(--line-strong)}
.btn--ghost:hover{background:var(--bg-alt);color:var(--navy)}
.btn--sm{min-height:44px;padding:var(--s2) var(--s4);font-size:var(--f-xs)}
.btn--block{display:flex;width:100%}
.section--navy .btn--phone{color:#fff;border-color:rgba(255,255,255,.35)}
.section--navy .btn--phone:hover{background:rgba(255,255,255,.1);color:#fff}

.ctaset{display:flex;flex-wrap:wrap;gap:var(--s3);align-items:stretch}
.ctaset .btn{flex:1 1 auto;min-width:0}
@media (min-width:480px){.ctaset .btn{flex:0 1 auto}}
.cta-note{font-size:var(--f-sm);color:var(--muted);margin-top:var(--s3)}

/* --- header -------------------------------------------------------------- */
.site-header{
  position:sticky;top:0;z-index:100;background:rgba(255,255,255,.96);
  border-bottom:1px solid var(--line);
}
/* The blur lives on a pseudo-element, NOT on .site-header itself: a filter or
   backdrop-filter turns its element into the containing block for every
   position:fixed descendant, which would trap the full-screen .navpanel inside
   the 72px header box and clip the whole menu away. */
.site-header::before{content:"";position:absolute;inset:0;z-index:-1;
  backdrop-filter:saturate(180%) blur(10px)}
.header__bar{display:flex;align-items:center;gap:var(--s2);min-height:var(--header-h);
  max-width:var(--wrap);margin-inline:auto;padding-inline:var(--s3);position:relative}
.brand{display:flex;align-items:center;justify-content:center;gap:var(--s2);text-decoration:none;flex:none;margin-right:auto;min-height:44px;min-width:44px}
.brand__mark{width:30px;height:30px;flex:none;display:block;object-fit:contain}
.brand__name{display:none;font-family:"Prompt",sans-serif;font-weight:700;font-size:1rem;color:var(--navy);line-height:1.1;letter-spacing:-.01em}
.brand__sub{display:block;font-family:"Prompt",sans-serif;font-size:.5625rem;font-weight:500;letter-spacing:.16em;text-transform:uppercase;color:var(--gold-600)}

.nav{display:none}
.nav__list{display:flex;align-items:center;gap:var(--s1);list-style:none;margin:0;padding:0}
/* static, not relative: the mega panels anchor to .header__bar so they can never
   be pushed off a viewport edge by whichever <li> happens to own them. */
.nav__list>li{margin:0;position:static}
.nav__top{
  display:inline-flex;align-items:center;gap:var(--s1);background:none;border:0;
  padding:var(--s2) var(--s3);border-radius:var(--r-sm);cursor:pointer;
  font-family:"Prompt",sans-serif;font-size:var(--f-sm);font-weight:500;color:var(--ink);text-decoration:none;
}
.nav__top:hover{background:var(--navy-050);color:var(--navy)}
.nav__top svg{width:11px;height:11px;transition:transform var(--dur) var(--ease)}
.nav__list>li:hover .nav__top svg,.nav__top[aria-expanded="true"] svg{transform:rotate(180deg)}

/* Mega panel opens on hover AND focus-within so it works without JS. */
/* Anchored to .header__bar (max-width:var(--wrap), centred) so a panel can never
   spill off a viewport edge, but positioned per-item: main.js writes --mega-x so
   each panel's left edge sits under its own trigger, clamped inside the bar. A
   dropdown parked at the far right of the header, three items away from the
   button that opened it, is what this replaces. Without JS the fallback is the
   bar's left edge — still on the correct side of the header. */
.mega{
  position:absolute;top:calc(100% + 6px);left:var(--mega-x,0px);translate:none;
  width:min(940px,100%);max-height:min(72vh,640px);overflow-y:auto;overscroll-behavior:contain;
  background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--sh-lg);
  padding:var(--s5);opacity:0;visibility:hidden;transform:translateY(-6px);
  transition:opacity var(--dur) var(--ease),transform var(--dur) var(--ease),visibility var(--dur);
}
.mega--right{width:min(560px,100%)}
.nav__list>li:hover>.mega,.nav__list>li:focus-within>.mega,.nav__top[aria-expanded="true"]+.mega{
  opacity:1;visibility:visible;transform:translateY(0)
}
.mega__cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:var(--s5)}
.mega__col{min-width:0}
.mega__title{
  display:block;font-family:"Prompt",sans-serif;font-size:var(--f-xs);font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;color:var(--navy);
  padding-bottom:var(--s2);margin-bottom:var(--s2);border-bottom:1px solid var(--line);text-decoration:none;
}
a.mega__title:hover{color:var(--gold-600)}
.mega__count{color:var(--faint);font-weight:500;letter-spacing:0;text-transform:none}
.mega__list{list-style:none;margin:0;padding:0}
.mega__list li{margin:0}
.mega__list a{
  display:block;padding:var(--s2) var(--s2);border-radius:var(--r-sm);
  font-size:var(--f-sm);color:var(--body);text-decoration:none;line-height:1.4;
}
.mega__list a:hover{background:var(--navy-050);color:var(--navy)}
.mega__list .sub{display:block;font-size:var(--f-xs);color:var(--faint)}
.mega__note{font-size:var(--f-xs);color:var(--muted);margin-top:var(--s2)}

/* language switcher — a real <a>, the only crawl path into the /zh/ tree */
.lang{display:flex;align-items:center;gap:2px;flex:none;
  border:1px solid var(--line-strong);border-radius:var(--r-pill);padding:2px;background:#fff}
.footer__list a{display:inline-block;min-height:44px;padding-block:.7rem}
.lang a,.lang span{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:44px;min-height:44px;padding:0 var(--s2);border-radius:var(--r-pill);
  font-family:"Prompt",sans-serif;font-size:var(--f-xs);font-weight:600;text-decoration:none;line-height:1;
}
.lang span{background:var(--navy);color:#fff}
.lang a{color:var(--muted)}
.lang a:hover{background:var(--navy-050);color:var(--navy)}

.header__cta{display:flex;align-items:center;gap:var(--s2);flex:none}
/* Icon-only chat CTAs on mobile — full 44px targets, aria-label carries the name */
.header__cta .btn{padding:0;width:44px;height:44px;min-height:44px}
.header__cta .btn span{display:none}
.header__cta .btn--phone{display:none}

.burger{
  display:inline-flex;align-items:center;justify-content:center;
  width:44px;height:44px;flex:none;background:none;border:1px solid var(--line-strong);
  border-radius:var(--r-sm);cursor:pointer;color:var(--navy);order:-1;
}
.burger:hover{background:var(--navy-050)}
.burger svg{width:20px;height:20px}
.burger .ic-x{display:none}
.burger[aria-expanded="true"] .ic-menu{display:none}
.burger[aria-expanded="true"] .ic-x{display:block}

/* --- mobile nav panel ---------------------------------------------------- */
/* Visible in normal flow without JS; .js hides it so a no-JS visitor still gets
   a working (long) nav rather than an unreachable one. */
.navpanel{border-top:1px solid var(--line);background:#fff}
.js .navpanel{
  position:fixed;inset:var(--header-h) 0 0;z-index:99;overflow-y:auto;overscroll-behavior:contain;
  padding:var(--s4) var(--s4) var(--s9);display:none;
}
.js .navpanel.is-open{display:block}
.navpanel__lang{display:flex;justify-content:center;margin-bottom:var(--s4)}
.navpanel details{border-bottom:1px solid var(--line)}
.navpanel summary{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  min-height:52px;padding:var(--s3) var(--s2);cursor:pointer;list-style:none;
  font-family:"Prompt",sans-serif;font-weight:600;font-size:var(--f-base);color:var(--navy);
}
.navpanel summary::-webkit-details-marker{display:none}
.navpanel summary::after{content:"";width:9px;height:9px;flex:none;margin-right:var(--s2);
  border-right:2px solid var(--faint);border-bottom:2px solid var(--faint);
  transform:rotate(45deg);transition:transform var(--dur) var(--ease)}
.navpanel details[open]>summary::after{transform:rotate(-135deg)}
.navpanel details details{border-bottom:0;border-top:1px solid var(--line);margin-left:var(--s3)}
.navpanel details details summary{font-size:var(--f-sm);font-weight:500;min-height:48px}
.navpanel__links{list-style:none;margin:0 0 var(--s3);padding:0}
.navpanel__links li{margin:0}
.navpanel__links a{
  display:block;min-height:48px;padding:var(--s3) var(--s3);
  font-size:var(--f-sm);color:var(--body);text-decoration:none;border-radius:var(--r-sm);
}
.navpanel__links a:hover{background:var(--navy-050);color:var(--navy)}
.navpanel__solo{
  display:flex;align-items:center;min-height:52px;padding:var(--s3) var(--s2);
  font-family:"Prompt",sans-serif;font-weight:600;color:var(--navy);text-decoration:none;
  border-bottom:1px solid var(--line);
}
.navpanel__cta{display:grid;gap:var(--s3);margin-top:var(--s5)}
/* On a wide tablet the panel is the full viewport — keep its rows readable
   rather than stretching a 12-word link across 1000px. */
@media (min-width:640px){.js .navpanel>*{max-width:640px;margin-inline:auto}}

/* --- hero ---------------------------------------------------------------- */
/* Desktop: full-bleed background image with the subject on the right and a
   left-to-right scrim so the navy headline stays readable (matches
   resource/design-reference.png). Mobile: stacked — the scrim needed to make
   text readable over the photo would hide the subject entirely, so the image
   gets its own band above the copy. */
.hero{position:relative;background:var(--bg-alt);overflow:hidden;isolation:isolate}
.hero__inner{display:grid;gap:var(--s6);align-items:center;
  padding-block:clamp(2rem,5vw,var(--s9))}
.hero h1{font-size:var(--f-display);margin-bottom:var(--s4)}
.hero__lede{font-size:var(--f-lg);max-width:52ch;margin-bottom:var(--s5)}
.hero__media{position:relative;border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--sh-lg)}
.hero__media img{width:100%;aspect-ratio:4/3;object-fit:cover}

/* full-bleed variant */
.hero--bleed .hero__bg{position:absolute;inset:0;z-index:-1;display:none}
.hero--bleed .hero__bg img{width:100%;height:100%;object-fit:cover;object-position:78% center}
.hero--bleed .hero__bg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(90deg,
    rgba(248,246,242,.97) 0%,
    rgba(248,246,242,.94) 32%,
    rgba(248,246,242,.72) 48%,
    rgba(248,246,242,.15) 62%,
    rgba(248,246,242,0) 74%)}
.hero--bleed .hero__copy{min-width:0}
/* The copy column is a fixed 600px but the scrim fades on viewport percentages,
   so at the narrow end of the bleed range the transparent phone button reaches
   past the scrim onto the dark suit and its navy label disappears. Opaque fill,
   applied at every width rather than patched into one band. */
.hero--bleed .btn--phone{background:#fff}

.statband{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:var(--s3);
  background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--s5);box-shadow:var(--sh);margin-top:var(--s6)}
.stat{display:flex;flex-direction:column;gap:2px;text-align:left;min-width:0}
.stat__n{font-family:"Prompt",sans-serif;font-size:var(--f-h3);font-weight:700;color:var(--navy);line-height:1.1}
.stat__l{font-size:var(--f-xs);color:var(--muted);letter-spacing:.02em}

/* --- cards --------------------------------------------------------------- */
.card{background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);
  overflow:hidden;box-shadow:var(--sh-sm);display:flex;flex-direction:column;
  transition:box-shadow var(--dur) var(--ease),transform var(--dur) var(--ease)}
.card:hover{box-shadow:var(--sh);transform:translateY(-2px)}
.card__media{position:relative;background:var(--bg-tint)}
.card__media img{width:100%;aspect-ratio:4/3;object-fit:cover}
.card__badge{position:absolute;top:var(--s3);left:var(--s3);
  background:var(--navy);color:#fff;font-family:"Prompt",sans-serif;font-size:var(--f-xs);
  font-weight:600;padding:var(--s1) var(--s3);border-radius:var(--r-pill)}
.card__badge--gold{background:var(--gold);color:#26200C}
.card__body{padding:var(--s5);display:flex;flex-direction:column;gap:var(--s2);flex:1}
.card__title{font-size:var(--f-h4);margin:0}
/* Card headings are primary tap targets, not inline prose links — WCAG's inline
   exception does not apply, so they carry the full 44px height. */
.card__title a{display:inline-block;min-height:44px;padding-block:.55rem;color:var(--navy);text-decoration:none}
.card__title a:hover{color:var(--gold-600)}
.card__meta{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);font-size:var(--f-sm);color:var(--muted);margin:0}
.card__meta span{display:inline-flex;align-items:center;gap:var(--s1)}
.card__price{font-family:"Prompt",sans-serif;font-size:var(--f-lg);font-weight:700;color:var(--gold-600);margin:0}
.card__hook{font-size:var(--f-sm);color:var(--body);margin:0}
.card__foot{margin-top:auto;padding-top:var(--s3)}
/* Standalone links inside a card body (e.g. "nearby area →") are tap targets too. */
.card__body>a:not(.btn),.card__link{display:inline-block;min-height:44px;padding-block:.6rem}

/* --- unit table + deep-linkable unit panels ------------------------------ */
.tablewrap{overflow-x:auto;-webkit-overflow-scrolling:touch;border:1px solid var(--line);
  border-radius:var(--r-lg);background:#fff}
.utable{min-width:640px;font-size:var(--f-sm)}
.utable th,.utable td{padding:var(--s3) var(--s4);text-align:left;border-bottom:1px solid var(--line);vertical-align:middle}
.utable thead th{background:var(--bg-tint);font-family:"Prompt",sans-serif;font-weight:600;
  color:var(--navy);font-size:var(--f-xs);letter-spacing:.04em;text-transform:uppercase;white-space:nowrap}
.utable tbody tr:last-child td{border-bottom:0}
.utable tbody tr:hover{background:var(--navy-050)}
.utable .num{font-variant-numeric:tabular-nums;white-space:nowrap}
.utable .price{font-weight:700;color:var(--gold-600);font-family:"Prompt",sans-serif}

/* Full detail is in the HTML on load and visible in flow; .js collapses it. */
.unit{scroll-margin-top:calc(var(--header-h) + var(--s4));
  border:1px solid var(--line);border-radius:var(--r-lg);background:#fff;
  margin-bottom:var(--s4);overflow:hidden}
.unit__head{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s3);
  padding:var(--s4) var(--s5);background:var(--bg-tint);border-bottom:1px solid var(--line)}
.unit__code{font-family:"Prompt",sans-serif;font-weight:700;color:var(--navy);font-size:var(--f-lg);margin:0}
.unit__price{font-family:"Prompt",sans-serif;font-weight:700;color:var(--gold-600);margin-left:auto;font-size:var(--f-lg)}
.unit__body{padding:var(--s5)}
.js .unit__body{display:none}
.js .unit.is-open .unit__body{display:block}
.unit:target{border-color:var(--gold);box-shadow:0 0 0 3px var(--gold-050)}
.js .unit:target .unit__body{display:block}
.unit__toggle{display:none;background:none;border:0;cursor:pointer;padding:var(--s2);
  min-height:44px;min-width:44px;color:var(--navy-500);font-family:"Prompt",sans-serif;font-size:var(--f-sm)}
.js .unit__toggle{display:inline-flex;align-items:center;gap:var(--s1)}
.unit__specs{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:var(--s3);list-style:none;margin:0 0 var(--s5);padding:0}
.unit__specs li{display:flex;flex-direction:column;gap:2px;margin:0;
  padding:var(--s3);background:var(--bg-alt);border-radius:var(--r-sm)}
.unit__specs dt,.unit__specs .k{font-size:var(--f-xs);color:var(--muted)}
.unit__specs dd,.unit__specs .v{margin:0;font-weight:600;color:var(--ink);font-size:var(--f-sm)}
.gallery{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:var(--s3);margin-bottom:var(--s5)}
.gallery img{width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:var(--r-sm);background:var(--bg-tint)}

/* --- inline WeChat section (no modal anywhere on this site) --------------- */
.wechat{scroll-margin-top:calc(var(--header-h) + var(--s4))}
.wechat__inner{display:grid;gap:var(--s6);align-items:center;
  background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);
  padding:clamp(1.5rem,4vw,var(--s8));box-shadow:var(--sh)}
.wechat__ids{background:var(--bg-alt);border:1px solid var(--line);border-radius:var(--r);padding:var(--s5)}
.wechat__idlabel{font-family:"Prompt",sans-serif;font-size:var(--f-xs);font-weight:600;letter-spacing:.12em;
  text-transform:uppercase;color:var(--gold-600);margin:0 0 var(--s2)}
.wechat__id+.wechat__idlabel{margin-top:var(--s5)}
.wechat__id{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s3);
  background:#fff;border:1px solid var(--line);border-radius:var(--r);
  padding:var(--s3) var(--s4);margin:0}
.wechat__id code{font-family:"Prompt",sans-serif;font-size:var(--f-lg);font-weight:700;
  color:var(--navy);letter-spacing:.04em}
.btn-copy{
  margin-left:auto;min-height:44px;padding:var(--s2) var(--s4);
  background:var(--navy);color:#fff;border:0;border-radius:var(--r-sm);cursor:pointer;
  font-family:"Prompt",sans-serif;font-size:var(--f-sm);font-weight:600;
}
.btn-copy:hover{background:var(--navy-700)}
.wechat__steps{counter-reset:s;list-style:none;padding:0;margin:0 0 var(--s4)}
.wechat__steps li{counter-increment:s;position:relative;padding-left:2.25rem;margin-bottom:var(--s3);font-size:var(--f-sm)}
.wechat__steps li::before{content:counter(s);position:absolute;left:0;top:.1em;
  width:1.6rem;height:1.6rem;display:grid;place-items:center;border-radius:50%;
  background:var(--wechat-green);color:#fff;font-family:"Prompt",sans-serif;font-size:var(--f-xs);font-weight:700}
.wechat__status{min-height:1.5em;font-size:var(--f-sm);color:var(--ok);font-weight:600;margin:0}
:target.wechat .wechat__inner{border-color:var(--wechat-green);box-shadow:0 0 0 3px rgba(7,193,96,.15)}

/* --- FAQ ----------------------------------------------------------------- */
/* Open by default; <details open> keeps every answer visible without JS. */
.faq{display:grid;gap:var(--s3)}
.faq details{border:1px solid var(--line);border-radius:var(--r);background:#fff;overflow:hidden}
.faq summary{cursor:pointer;list-style:none;padding:var(--s4) var(--s5);
  display:flex;align-items:flex-start;gap:var(--s3);background:var(--bg-alt)}
.faq summary::-webkit-details-marker{display:none}
.faq summary h3{margin:0;font-size:var(--f-h4);flex:1}
.faq summary::after{content:"";flex:none;width:9px;height:9px;margin-top:.55em;
  border-right:2px solid var(--faint);border-bottom:2px solid var(--faint);
  transform:rotate(-135deg);transition:transform var(--dur) var(--ease)}
.faq details:not([open]) summary::after{transform:rotate(45deg)}
.faq__a{padding:var(--s5)}
.faq__a>*:last-child{margin-bottom:0}

/* --- CTA band, notices, footer ------------------------------------------- */
.ctaband{background:var(--navy);color:#C9D6E4;border-radius:var(--r-lg);
  padding:clamp(1.5rem,4vw,var(--s8));text-align:center}
.ctaband h2{color:#fff;margin-bottom:var(--s3)}
.ctaband p{max-width:56ch;margin-inline:auto;margin-bottom:var(--s5)}
.ctaband .ctaset{justify-content:center}

.notice{display:flex;gap:var(--s3);align-items:flex-start;
  background:var(--gold-050);border:1px solid #EFE2BE;border-left:3px solid var(--gold);
  border-radius:var(--r-sm);padding:var(--s4);font-size:var(--f-sm);color:#5C4A18}
.notice p:last-child{margin-bottom:0}

.site-footer{background:var(--navy);color:#9FB3C8;padding-block:var(--s8) var(--s6);margin-top:var(--s9)}
.site-footer h2,.site-footer h3{color:#fff;font-size:var(--f-sm);letter-spacing:.1em;
  text-transform:uppercase;margin-bottom:var(--s4)}
.footer__grid{display:grid;gap:var(--s6);margin-bottom:var(--s7)}
.footer__list{list-style:none;margin:0;padding:0}
.footer__list li{margin-bottom:var(--s2)}
.footer__list a{color:#9FB3C8;text-decoration:none}
.footer__list a:hover{color:#fff;text-decoration:underline}
.footer__contact a{display:inline-flex;align-items:center;gap:var(--s2);
  min-height:44px;color:#fff;text-decoration:none;font-weight:600}
.footer__contact a:hover{color:var(--gold)}
.footer__bottom{border-top:1px solid rgba(255,255,255,.12);padding-top:var(--s5);
  display:flex;flex-wrap:wrap;gap:var(--s3) var(--s5);align-items:center;
  font-size:var(--f-xs);color:#7A8FA6}
.footer__bottom a{color:#7A8FA6}
.footer__legal{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);list-style:none;margin:0;padding:0}
.footer__legal li{margin:0}
.footer__legal a{display:inline-block;min-height:44px;padding-block:.7rem}
/* Consent withdrawal: a button because it acts, but it sits among the legal
   links and must not read as anything more prominent than they do. */
.footer__consent{display:inline-block;min-height:44px;padding:.7rem 0;
  background:none;border:0;cursor:pointer;font:inherit;color:#7A8FA6;text-decoration:underline}
.footer__consent:hover{color:#fff}

/* --- sticky chat --------------------------------------------------------- */
.chat{position:fixed;right:var(--s4);bottom:var(--s4);z-index:95;
  display:flex;flex-direction:column;align-items:flex-end;gap:var(--s3)}
.chat__list{display:flex;flex-direction:column;align-items:flex-end;gap:var(--s3)}
.js .chat__list{display:none}
.js .chat.is-open .chat__list{display:flex}
.chat__item{display:inline-flex;align-items:center;gap:var(--s2);text-decoration:none;
  background:#fff;border:1px solid var(--line);border-radius:var(--r-pill);
  padding:var(--s2) var(--s4) var(--s2) var(--s2);box-shadow:var(--sh);
  font-family:"Prompt",sans-serif;font-size:var(--f-sm);font-weight:600;color:var(--navy);
  min-height:48px;max-width:min(78vw,320px)}
.chat__item:hover{color:var(--navy);border-color:var(--line-strong);transform:translateY(-1px)}
.chat__ico{width:36px;height:36px;flex:none;border-radius:50%;display:grid;place-items:center;color:#fff}
.chat__ico svg{width:20px;height:20px}
.chat__ico--line{background:var(--line-green)}
.chat__ico--wechat{background:var(--wechat-green)}
.chat__ico--phone{background:var(--navy)}
.chat__toggle{display:inline-flex;align-items:center;gap:var(--s2);
  background:var(--navy);color:#fff;border:0;border-radius:var(--r-pill);
  padding:var(--s2) var(--s5) var(--s2) var(--s2);min-height:56px;cursor:pointer;
  box-shadow:var(--sh-lg);font-family:"Prompt",sans-serif;font-weight:600;font-size:var(--f-sm);
  max-width:min(80vw,320px)}
.chat__toggle:hover{background:var(--navy-700)}
.chat__toggle .chat__ico{background:var(--gold);color:#26200C}
.chat__toggle .ic-x{display:none}
.chat.is-open .chat__toggle .ic-chat{display:none}
.chat.is-open .chat__toggle .ic-x{display:block}

/* --- cookie consent ------------------------------------------------------ */
.cookie{position:fixed;left:var(--s4);right:var(--s4);bottom:var(--s4);z-index:110;
  background:#fff;border:1px solid var(--line-strong);border-radius:var(--r-lg);
  box-shadow:var(--sh-lg);padding:var(--s5);max-width:520px;display:none}
.cookie.is-shown{display:block}
.cookie p{font-size:var(--f-sm);margin-bottom:var(--s4)}
.cookie__actions{display:flex;flex-wrap:wrap;gap:var(--s3)}
.cookie__actions .btn{flex:1 1 auto}

/* --- 404 ----------------------------------------------------------------- */
.e404{text-align:center;padding-block:var(--s9)}
.e404 .ctaset{justify-content:center}
.e404__links{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));
  gap:var(--s3);margin-top:var(--s7);text-align:left}
.e404__links a{display:block;padding:var(--s4);background:#fff;border:1px solid var(--line);
  border-radius:var(--r);text-decoration:none;color:var(--navy);font-weight:600;min-height:48px}
.e404__links a:hover{border-color:var(--navy-500);background:var(--navy-050)}

/* --- breakpoints --------------------------------------------------------- */
@media (min-width:480px){
  .header__bar{gap:var(--s3);padding-inline:var(--s4)}
}
@media (min-width:640px){
  .brand__name{display:block}
}
@media (min-width:480px){
  .grid--2,.grid--3,.grid--4{grid-template-columns:repeat(2,1fr)}
  .cookie__actions .btn{flex:0 1 auto}
}
@media (min-width:768px){
  :root{--header-h:72px}
  .wechat__inner{grid-template-columns:minmax(280px,.85fr) 1fr}
  .grid--3{grid-template-columns:repeat(3,1fr)}
  .grid--4{grid-template-columns:repeat(2,1fr)}
  .wechat__inner{grid-template-columns:auto 1fr;gap:var(--s8)}
  .footer__grid{grid-template-columns:repeat(2,1fr)}
  .header__cta .btn{width:auto;padding:var(--s2) var(--s4)}
  .header__cta .btn span{display:inline}
}
/* The hero has its own breakpoint: below 783px it stacks — copy, then the photo
   in its own band underneath — and from 783px up it is the full-bleed layout.
   ONE set of declarations for that whole range, no per-band tweaks to the
   scrim, the crop or the column width, so 800px and 1400px differ only in how
   much of the same picture is on screen. */
@media (min-width:783px){
  .hero__inner{grid-template-columns:1.05fr .95fr;gap:var(--s8)}
  .hero--bleed .hero__bg{display:block}
  .hero--bleed .hero__media{display:none}
  .hero--bleed .hero__inner{grid-template-columns:minmax(0,600px);min-height:min(78vh,680px);
    align-content:center;padding-block:var(--s9)}
}
@media (min-width:1100px){
  .burger{display:none}
  .navpanel{display:none!important}
  .nav{display:block}
  .grid--4{grid-template-columns:repeat(4,1fr)}
  .footer__grid{grid-template-columns:1.4fr 1fr 1fr 1fr}
  .header__cta .btn--phone{display:inline-flex}
}
@media (min-width:1280px){
  .container{padding-inline:var(--s5)}
}

/* --- motion preferences -------------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important;
  }
  .btn:hover,.card:hover,.chat__item:hover{transform:none}
}

/* --- print --------------------------------------------------------------- */
@media print{
  .site-header,.chat,.cookie,.navpanel,.ctaband{display:none!important}
  body{color:#000}
  .js .unit__body{display:block!important}
}

/* footer text-only service-area list (never links down — nav does that) */
.footer__areas{color:#9FB3C8;margin:0}
.footer__note{font-size:var(--f-xs);color:#7A8FA6;max-width:70ch}
@media (min-width:768px){.footer__grid{grid-template-columns:1.5fr 1fr 1fr}}
@media (min-width:1024px){.footer__grid{grid-template-columns:1.6fr 1fr 1fr}}

/* Wide comparison tables: the 640px base min-width is too narrow for the
   8-column cross-building tables on the unit-size pages. */
.utable--wide{min-width:900px}
/* Group header row inside a unit table (e.g. price bands) */
.utable__group td,.utable__group th{background:var(--navy-050);font-weight:700;color:var(--navy)}

/* Table-cell links are real tap targets (project names, unit codes), not inline
   prose links — the WCAG inline exception does not apply. Give them the full
   44px and trim the cell padding so rows don't balloon. */
.utable td{padding-block:var(--s2)}
.utable td a{display:inline-block;min-height:44px;padding-block:.7rem}

/* Placeholder building images: labelled until real project photography arrives.
   An AI-generated facade must never read as a photograph of the actual building. */
.img-note{margin:var(--s2) 0 0;font-size:var(--f-xs);color:var(--muted);line-height:1.4}
.hero__media .img-note{position:absolute;left:0;right:0;bottom:0;margin:0;
  background:rgba(14,42,71,.78);color:#fff;padding:var(--s2) var(--s3);backdrop-filter:blur(2px)}

/* --- listing cards + detail modal ---------------------------------------- */
/* Marketplace-style card grid. Full detail stays in the HTML on load (inside
   .listing-modal) so it is crawlable and works with JS off — JS only turns it
   into an overlay. Deep links (#unit-M04348) still open the right unit. */
.listings{padding-block:clamp(2rem,5vw,var(--s9))}
.listing-grid{display:grid;gap:var(--s5);grid-template-columns:1fr}
.listing-card{background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);
  overflow:hidden;box-shadow:var(--sh-sm);display:flex;flex-direction:column;
  transition:box-shadow var(--dur) var(--ease),transform var(--dur) var(--ease)}
.listing-card:hover{box-shadow:var(--sh);transform:translateY(-2px)}
.listing-card__media{position:relative;background:var(--bg-tint)}
.listing-card__media img{width:100%;aspect-ratio:4/3;object-fit:cover}
.listing-card__tag{position:absolute;top:var(--s3);left:var(--s3);
  background:var(--navy);color:#fff;font-family:"Prompt",sans-serif;font-size:var(--f-xs);
  font-weight:600;padding:var(--s1) var(--s3);border-radius:var(--r-pill)}
.listing-card__body{padding:var(--s5);display:flex;flex-direction:column;gap:var(--s3);flex:1}
.listing-card__price{font-family:"Prompt",sans-serif;font-size:var(--f-h4);font-weight:700;
  color:var(--gold-600);margin:0;line-height:1.2}
.listing-card__psm{font-size:var(--f-xs);color:var(--muted);font-weight:500}
.listing-card__title{font-family:"Prompt",sans-serif;font-size:var(--f-base);font-weight:600;
  color:var(--navy);margin:0}
.listing-card__meta{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);margin:0;
  font-size:var(--f-sm);color:var(--body);list-style:none;padding:0}
.listing-card__meta li{display:inline-flex;align-items:center;gap:var(--s1);margin:0}
.listing-card__meta svg{width:16px;height:16px;flex:none;color:var(--faint)}
.listing-card__foot{margin-top:auto;padding-top:var(--s3);display:grid;gap:var(--s2)}

/* the detail overlay */
.listing-modal{scroll-margin-top:calc(var(--header-h) + var(--s4));
  border:1px solid var(--line);border-radius:var(--r-lg);background:#fff;
  margin-bottom:var(--s5);overflow:hidden}
.js .listing-modal{display:none;position:fixed;inset:0;z-index:120;margin:0;border:0;
  border-radius:0;overflow-y:auto;overscroll-behavior:contain;background:rgba(14,42,71,.55);
  padding:0;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}
.js .listing-modal.is-open{display:block}
.js .listing-modal__inner{background:#fff;max-width:840px;margin:clamp(0px,4vh,64px) auto;
  border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--sh-lg);
  animation:modal-in var(--dur) var(--ease)}
@keyframes modal-in{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
.listing-modal__head{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s3);
  padding:var(--s4) var(--s5);background:var(--bg-tint);border-bottom:1px solid var(--line);
  position:sticky;top:0;z-index:1}
.listing-modal__code{font-family:"Prompt",sans-serif;font-weight:700;color:var(--navy);
  font-size:var(--f-lg);margin:0}
.listing-modal__price{font-family:"Prompt",sans-serif;font-weight:700;color:var(--gold-600);
  margin-left:auto;font-size:var(--f-lg)}
.listing-modal__close{display:none;flex:none;width:44px;height:44px;border:1px solid var(--line-strong);
  border-radius:var(--r-sm);background:#fff;cursor:pointer;color:var(--navy);
  align-items:center;justify-content:center}
.js .listing-modal__close{display:inline-flex}
.listing-modal__close:hover{background:var(--navy-050)}
.listing-modal__close svg{width:20px;height:20px}
.listing-modal__body{padding:var(--s5)}
.listing-modal__body>*:last-child{margin-bottom:0}

@media (min-width:640px){.listing-grid{grid-template-columns:repeat(2,1fr)}}
@media (min-width:1024px){.listing-grid{grid-template-columns:repeat(3,1fr)}}
@media (prefers-reduced-motion:reduce){.js .listing-modal__inner{animation:none}}

/* Grid and flex children default to min-width:auto, so a 640px-min-width table
   inside one stretches the track instead of scrolling — the scroll container
   only works if it is allowed to shrink below its content. */
.grid>*,.hero__inner>*,.wechat__inner>*{min-width:0}
.tablewrap{min-width:0;max-width:100%}

/* ==========================================================================
   Round 2 fixes
   ========================================================================== */

/* Hero: the subject's head was being cropped by object-fit:cover centering.
   Anchor to the top so the full head always shows. */
.hero--bleed .hero__bg img{object-position:78% top}
.hero--bleed .hero__media img{object-position:center top}

/* Stat band: every band on the site holds 4 or 5 stats. It goes one row when it
   fits and 2-up when it doesn't — never 3-up, which left the 4th stat alone in
   an empty row. With 5 stats the odd one out spans the full width so the wrap
   reads as deliberate. The 1px gap over a line-coloured background draws the
   dividers automatically however it lands. */
.statband{grid-template-columns:repeat(2,1fr);
  gap:1px;padding:1px;background:var(--line);overflow:hidden}
.statband>.stat:last-child:nth-child(odd){grid-column:1/-1}
@media (min-width:768px){
  .statband{grid-template-columns:repeat(auto-fit,minmax(132px,1fr))}
  .statband>.stat:last-child:nth-child(odd){grid-column:auto}
}
.stat{padding:var(--s4);background:#fff;border:0}
/* A plain (non-bleed) hero splits its row into two proportional columns, so its
   stat band sits in ~50% of the container and hits the 3-up state ~330px before
   every other band on the site. The bleed hero on the homepage is exempt: its
   copy column is a fixed 600px, wide enough for four across at 768 already. */
@media (max-width:1099.98px){
  .hero:not(.hero--bleed) .statband{grid-template-columns:repeat(2,1fr)}
  .hero:not(.hero--bleed) .statband>.stat:last-child:nth-child(odd){grid-column:1/-1}
}

/* Portrait images (the About photo) are 3:4 — forcing 4:3 cut the head off. */
.hero__media--portrait img{aspect-ratio:3/4;object-position:center top}

/* Phone CTA on the navy CTA band was navy-on-navy and effectively invisible. */
.ctaband .btn--phone,.section--navy .btn--phone{color:#fff;border-color:rgba(255,255,255,.45)}
.ctaband .btn--phone:hover,.section--navy .btn--phone:hover{background:rgba(255,255,255,.12);color:#fff;border-color:#fff}

/* Inline brand/utility icons had no size outside .btn, so they rendered at
   intrinsic size (huge) in the footer. */
.icon{width:1.25em;height:1.25em;flex:none}
.footer__contact a{gap:var(--s3);line-height:1.4;margin-bottom:var(--s2)}
.footer__contact svg,.footer__contact .icon{width:20px;height:20px;flex:none}

/* Copy-to-clipboard confirmation toast, centred on screen. */
.toast{position:fixed;left:50%;top:50%;translate:-50% -50%;z-index:200;
  background:var(--navy);color:#fff;padding:var(--s4) var(--s6);border-radius:var(--r-lg);
  box-shadow:var(--sh-lg);font-family:"Prompt",sans-serif;font-weight:600;
  font-size:var(--f-base);text-align:center;max-width:min(90vw,420px);
  display:flex;align-items:center;gap:var(--s3);opacity:0;pointer-events:none;
  transition:opacity var(--dur) var(--ease),translate var(--dur) var(--ease)}
.toast.is-shown{opacity:1;translate:-50% -50%}
.toast__ico{flex:none;width:28px;height:28px;border-radius:50%;background:var(--ok);
  display:grid;place-items:center}
.toast__ico svg{width:16px;height:16px;color:#fff}
.toast code{font-family:"Prompt",sans-serif;font-weight:700;color:var(--gold)}
@media (prefers-reduced-motion:reduce){.toast{transition:none}}

/* ==========================================================================
   Listing card v2 — marketplace style with a swipeable image carousel
   ========================================================================== */
.listing-card{cursor:pointer;position:relative}
.listing-card:focus-within{outline:3px solid var(--gold);outline-offset:2px}

/* carousel */
.lc-gal{position:relative;background:var(--bg-tint);overflow:hidden;touch-action:pan-y}
.lc-gal__track{display:flex;transition:transform var(--dur) var(--ease);will-change:transform}
.lc-gal__track>img{flex:0 0 100%;width:100%;aspect-ratio:4/3;object-fit:cover;user-select:none;-webkit-user-drag:none}
.lc-gal.is-dragging .lc-gal__track{transition:none}
.lc-gal__nav{position:absolute;top:50%;translate:0 -50%;z-index:2;
  width:38px;height:38px;border:0;border-radius:50%;cursor:pointer;
  background:rgba(255,255,255,.82);color:var(--navy);display:none;
  align-items:center;justify-content:center;box-shadow:var(--sh-sm);
  -webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}
.lc-gal__nav:hover{background:#fff}
.lc-gal__nav svg{width:18px;height:18px}
.lc-gal__nav--prev{left:10px}
.lc-gal__nav--next{right:10px}
.lc-gal:hover .lc-gal__nav,.lc-gal__nav:focus-visible{display:inline-flex}
@media (hover:none){.lc-gal__nav{display:inline-flex}}
.lc-gal__dots{position:absolute;left:50%;bottom:10px;translate:-50% 0;z-index:2;
  display:flex;gap:6px;padding:5px 9px;border-radius:var(--r-pill);background:rgba(14,42,71,.45)}
.lc-gal__dots span{width:6px;height:6px;border-radius:50%;background:rgba(255,255,255,.55)}
.lc-gal__dots span.is-on{background:#fff}
.lc-gal__count{position:absolute;left:10px;bottom:10px;z-index:2;
  display:inline-flex;align-items:center;gap:5px;padding:4px 9px;border-radius:var(--r-pill);
  background:rgba(14,42,71,.6);color:#fff;font-size:var(--f-xs);font-weight:600}
.lc-gal__count svg{width:13px;height:13px}

/* card body */
.listing-card__tags{display:flex;gap:var(--s2);flex-wrap:wrap;margin:0}
.tag{font-family:"Prompt",sans-serif;font-size:var(--f-xs);font-weight:600;
  padding:3px var(--s3);border-radius:var(--r-sm);line-height:1.6}
.tag--sale{background:var(--line-green);color:#fff}
.tag--type{background:#E9F8EF;color:#1B8A4B}
.listing-card__name{display:flex;align-items:center;gap:var(--s2);font-size:var(--f-sm);color:var(--muted);margin:0}
.listing-card__name svg{width:15px;height:15px;flex:none}
.listing-card__psm{display:block;font-size:var(--f-sm);color:var(--muted);font-weight:500;margin-top:2px}
.listing-card__title{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}

/* ==========================================================================
   Listing modal v2 — hero gallery grid, spec cards, sticky CTA bar
   ========================================================================== */
.js .listing-modal__inner{max-width:960px;display:flex;flex-direction:column;
  max-height:calc(100vh - clamp(0px,8vh,128px))}
.listing-modal__scroll{overflow-y:auto;-webkit-overflow-scrolling:touch;flex:1}
.lm-head{padding:var(--s5) var(--s5) 0}
.lm-project{font-family:"Prompt",sans-serif;font-weight:700;color:var(--navy);font-size:var(--f-h4);margin:0 0 var(--s2)}
.lm-facts{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s5);list-style:none;padding:0;margin:0 0 var(--s4);
  font-size:var(--f-sm);color:var(--body)}
.lm-facts li{display:inline-flex;align-items:center;gap:var(--s2);margin:0}
.lm-facts svg{width:17px;height:17px;color:var(--faint);flex:none}

/* Gallery grid. Mobile: one lead image, then a row of three thumbs, the last
   of which carries the "show all" overlay. Desktop: 1 large + 2 stacked, and
   the fourth cell drops out. Both overlays are in the markup; CSS picks. */
.lm-gal{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s2);padding:0 var(--s5)}
.lm-gal__cell:first-child{grid-column:1/-1}
.lm-gal__cell:first-child img{aspect-ratio:4/3}
.lm-gal__cell:not(:first-child) img{aspect-ratio:1}
.lm-gal__cell:nth-child(3) .lm-gal__more{display:none}
.lm-gal__cell{position:relative;border-radius:var(--r);overflow:hidden;background:var(--bg-tint);
  cursor:zoom-in;border:0;padding:0;display:block;width:100%}
.lm-gal__cell img{width:100%;height:100%;object-fit:cover;aspect-ratio:4/3}
.lm-gal__more{position:absolute;inset:0;background:rgba(14,42,71,.55);color:#fff;
  display:flex;align-items:center;justify-content:center;gap:var(--s2);
  font-family:"Prompt",sans-serif;font-weight:600;font-size:var(--f-sm)}
.lm-gal__more svg{width:20px;height:20px}
.lm-gal__count{position:absolute;left:var(--s3);bottom:var(--s3);
  display:inline-flex;align-items:center;gap:5px;padding:4px 10px;border-radius:var(--r-sm);
  background:rgba(255,255,255,.9);color:var(--navy);font-size:var(--f-xs);font-weight:700}
.lm-gal__count svg{width:14px;height:14px}
@media (min-width:768px){
  .lm-gal{grid-template-columns:2fr 1fr;grid-template-rows:1fr 1fr}
  .lm-gal__cell:first-child{grid-column:1;grid-row:1/3}
  .lm-gal__cell:nth-child(4){display:none}
  .lm-gal__cell img,.lm-gal__cell:not(:first-child) img{aspect-ratio:auto;height:100%}
  .lm-gal__cell:first-child img{aspect-ratio:4/3}
  .lm-gal__cell:nth-child(3) .lm-gal__more{display:flex}
}
.lm-body{padding:var(--s5)}
.lm-price{font-family:"Prompt",sans-serif;font-weight:700;color:var(--navy);
  font-size:clamp(1.5rem,1vw + 1.3rem,2rem);margin:0 0 var(--s2);line-height:1.15}
.lm-price small{font-family:"Sarabun",sans-serif;font-size:var(--f-sm);font-weight:500;color:var(--muted)}
.lm-specs{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--s3);margin:var(--s5) 0;list-style:none;padding:0}
.lm-specs li{display:flex;align-items:center;gap:var(--s3);margin:0;
  background:var(--bg-alt);border-radius:var(--r);padding:var(--s3) var(--s4)}
.lm-specs__ico{flex:none;width:36px;height:36px;border-radius:var(--r-sm);background:#fff;
  border:1px solid var(--line);display:grid;place-items:center;color:var(--navy-500)}
.lm-specs__ico svg{width:18px;height:18px}
.lm-specs .k{display:block;font-size:var(--f-xs);color:var(--muted)}
.lm-specs .v{display:block;font-weight:700;color:var(--ink);font-family:"Prompt",sans-serif}
@media (min-width:640px){.lm-specs{grid-template-columns:repeat(4,1fr)}}

/* sticky CTA bar */
.lm-cta{position:sticky;bottom:0;z-index:2;background:#fff;border-top:1px solid var(--line);
  padding:var(--s3) var(--s4);display:flex;gap:var(--s2);justify-content:center;flex-wrap:nowrap}
.lm-cta .btn{flex:0 1 auto;min-height:48px;padding:var(--s2) var(--s5)}
@media (max-width:639px){
  .lm-cta{padding:var(--s2)}
  .lm-cta .btn{flex:1 1 0;padding:var(--s2) var(--s2);font-size:var(--f-xs);min-width:0}
  .lm-cta .btn .full{display:none}
}
@media (min-width:640px){.lm-cta .btn .short{display:none}}

/* ==========================================================================
   Lightbox
   ========================================================================== */
.lightbox{position:fixed;inset:0;z-index:200;background:#000;display:none;
  flex-direction:column;touch-action:pan-y}
.lightbox.is-open{display:flex}
.lightbox__bar{display:flex;align-items:center;gap:var(--s4);padding:var(--s3) var(--s4);color:#fff;flex:none}
.lightbox__counter{font-family:"Prompt",sans-serif;font-size:var(--f-sm);font-weight:600}
.lightbox__close{margin-left:auto;width:44px;height:44px;border:0;background:none;color:#fff;
  cursor:pointer;display:grid;place-items:center;border-radius:var(--r-sm)}
.lightbox__close:hover{background:rgba(255,255,255,.14)}
.lightbox__close svg{width:22px;height:22px}
.lightbox__stage{flex:1;position:relative;display:flex;align-items:center;justify-content:center;
  overflow:hidden;min-height:0}
.lightbox__track{display:flex;height:100%;width:100%;transition:transform var(--dur) var(--ease)}
.lightbox.is-dragging .lightbox__track{transition:none}
.lightbox__track figure{flex:0 0 100%;margin:0;display:flex;align-items:center;justify-content:center;padding:0 var(--s4)}
.lightbox__track img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;
  user-select:none;-webkit-user-drag:none}
.lightbox__nav{position:absolute;top:50%;translate:0 -50%;z-index:2;width:48px;height:48px;
  border:0;border-radius:50%;background:rgba(255,255,255,.12);color:#fff;cursor:pointer;
  display:grid;place-items:center}
.lightbox__nav:hover{background:rgba(255,255,255,.25)}
.lightbox__nav svg{width:24px;height:24px}
.lightbox__nav--prev{left:var(--s3)}
.lightbox__nav--next{right:var(--s3)}
.lightbox__thumbs{flex:none;display:flex;gap:var(--s2);padding:var(--s3);overflow-x:auto;
  background:#0a0a0a;scrollbar-width:thin}
.lightbox__thumbs button{flex:0 0 auto;width:104px;height:74px;border:2px solid transparent;
  border-radius:var(--r-sm);overflow:hidden;background:none;padding:0;cursor:pointer;opacity:.55}
.lightbox__thumbs button.is-on{border-color:var(--line-green);opacity:1}
.lightbox__thumbs img{width:100%;height:100%;object-fit:cover}
@media (max-width:639px){.lightbox__thumbs button{width:76px;height:56px}}
@media (prefers-reduced-motion:reduce){
  .lc-gal__track,.lightbox__track{transition:none}
}

/* Listings-first pages: the page H1, lede and stats sit inside the listings
   section instead of a separate hero, kept deliberately compact so the cards
   stay near the top of the fold. */
.listings__intro{margin-bottom:var(--s6);max-width:78ch}
.listings__intro h1{font-size:clamp(1.4rem,1.4vw + 1.05rem,1.9rem);margin-bottom:var(--s3)}
.listings__intro .listings__lede{font-size:var(--f-base);color:var(--body);max-width:70ch;margin-bottom:var(--s4)}
.listings__intro .statband{margin-top:0;box-shadow:none;background:var(--bg-alt)}
.listings__intro .stat__n{font-size:var(--f-h4)}
.listings__intro .stat{padding:var(--s3) var(--s4)}

/* Modal headings: the dialog owns its own hierarchy — h1 (page) → h2 (listing)
   → h3 (sections inside). Sized down so it reads as a card title, not a banner. */
.lm-title{font-size:var(--f-h4);margin:var(--s4) 0 var(--s3);letter-spacing:0}
.lm-subhead{font-size:var(--f-h4);margin-top:var(--s5)}

/* Listing detail body */
.lm-prose{margin-bottom:var(--s4)}
.lm-prose>*:last-child{margin-bottom:0}
.lm-about{margin-bottom:var(--s4)}
.lm-kv{display:grid;grid-template-columns:1fr;gap:0;margin:0 0 var(--s5);
  border:1px solid var(--line);border-radius:var(--r);overflow:hidden}
.lm-kv>div{display:flex;gap:var(--s4);padding:var(--s3) var(--s4);border-top:1px solid var(--line)}
.lm-kv>div:first-child{border-top:0}
.lm-kv dt{flex:0 0 40%;color:var(--muted);font-size:var(--f-sm);margin:0}
.lm-kv dd{margin:0;font-weight:600;color:var(--ink);font-size:var(--f-sm);min-width:0;overflow-wrap:anywhere}
@media (min-width:640px){.lm-kv dt{flex-basis:30%}}
.lm-facs{display:grid;grid-template-columns:1fr;gap:0;list-style:none;padding:0;margin:0 0 var(--s5)}
.lm-facs li{display:flex;align-items:center;gap:var(--s3);margin:0;
  padding:var(--s3) 0;border-bottom:1px solid var(--line);font-size:var(--f-sm)}
.lm-facs li:last-child{border-bottom:0}
.lm-facs svg{width:17px;height:17px;color:var(--ok);flex:none}
@media (min-width:640px){.lm-facs{grid-template-columns:repeat(2,1fr);column-gap:var(--s6)}}
.lm-near{display:grid;grid-template-columns:1fr;gap:var(--s4);margin-bottom:var(--s5)}
.lm-near__cat{font-family:"Prompt",sans-serif;font-size:var(--f-xs);font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;color:var(--gold-600);margin:0 0 var(--s2)}
.lm-near ul{list-style:none;padding:0;margin:0}
.lm-near li{display:flex;justify-content:space-between;gap:var(--s4);margin:0;
  padding:var(--s2) 0;border-bottom:1px solid var(--line);font-size:var(--f-sm)}
.lm-near li:last-child{border-bottom:0}
.lm-near__d{color:var(--muted);white-space:nowrap;font-variant-numeric:tabular-nums}
@media (min-width:640px){.lm-near{grid-template-columns:repeat(2,1fr);column-gap:var(--s6)}}

/* --- faceted listing section (homepage §all-units) ------------------------ */
/* Every card is in the HTML on load and visible without JS; the filter and the
   "load more" step only toggle [hidden] over markup that is already there.
   Nothing here writes to the URL — parameterised copies of the homepage would
   be duplicate content on the most important page on the site. */
.facets{
  position:sticky;top:var(--header-h);z-index:20;
  display:none;gap:var(--s2);align-items:center;
  flex-wrap:nowrap;overflow-x:auto;overscroll-behavior-x:contain;
  scrollbar-width:none;-ms-overflow-style:none;
  margin:0 calc(var(--s4) * -1) var(--s4);padding:var(--s3) var(--s4);
  background:var(--bg-alt);border-bottom:1px solid transparent;
}
.facets::-webkit-scrollbar{display:none}
/* sticky only inside its own section: position:sticky releases at the end of
   its containing block, which here is the section's .container */
.facets.is-stuck{border-bottom-color:var(--line);box-shadow:0 6px 16px -12px rgba(14,42,71,.5)}
@media (min-width:768px){.facets{flex-wrap:wrap;overflow-x:visible}}

.facet{
  display:inline-flex;align-items:center;gap:var(--s2);flex:none;
  min-height:44px;padding:0 var(--s4);border-radius:var(--r-pill);
  background:#fff;border:1px solid var(--line-strong);cursor:pointer;
  font-family:"Prompt",sans-serif;font-size:var(--f-sm);font-weight:500;
  color:var(--body);white-space:nowrap;
  transition:background var(--dur) var(--ease),color var(--dur) var(--ease),border-color var(--dur) var(--ease);
}
.facet:hover{background:var(--navy-050);color:var(--navy);border-color:var(--navy-100,var(--line-strong))}
.facet.is-on{background:var(--navy);border-color:var(--navy);color:#fff}
.facet__n{font-size:var(--f-xs);color:var(--faint);font-variant-numeric:tabular-nums}
.facet.is-on .facet__n{color:rgba(255,255,255,.72)}

/* The filter, the counter and "load more" only do something with JS. Without
   it all 51 cards are already in flow, so hide the controls rather than ship
   dead ones. */
.js .facets{display:flex}
.allunits__status{display:none;font-size:var(--f-sm);color:var(--muted);margin:0 0 var(--s4)}
.js .allunits__status{display:block}
.js .allunits__status[hidden]{display:none}
.allunits__empty{
  background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--s6);text-align:center;color:var(--body);margin:0}
.allunits__more{display:none;margin:var(--s6) 0 0;text-align:center}
.js .allunits__more{display:block}
.js .allunits__more[hidden]{display:none}
/* [hidden] loses to the component's own display: rule without this */
.listing-grid .listing-card[hidden]{display:none}
