/* ==========================================================================
   teedinrimnam.com
   A curated property site: editorial, quiet, image-led. Light theme only —
   property is looked at, not read in the dark.
   ========================================================================== */

:root {
  --paper:        #faf8f4;
  --paper-2:      #f2eee7;
  --card:         #ffffff;
  --ink:          #16140f;
  --ink-2:        #4a453c;
  --ink-3:        #857d70;
  --rule:         #e2dcd1;
  --accent:       #2f4739;   /* deep green — restrained, not corporate blue */
  --accent-soft:  #e8ece8;
  --sale:         #2f4739;
  --rent:         #7a5c33;
  --line-green:   #06c755;

  --serif: Georgia, "Iowan Old Style", "Times New Roman", serif;
  --sans:  "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
           "Leelawadee UI", "Noto Sans Thai", Tahoma, sans-serif;

  --wrap: 1180px;
  --r: 3px;
}

/* Thai reads better in the sans stack at a slightly larger size. */
html[data-lang="th"] {
  --serif: "Leelawadee UI", "Noto Sans Thai", Tahoma, Georgia, serif;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

html[data-lang="th"] body { line-height: 1.9; }

img { max-width: 100%; display: block; }

a { color: inherit; text-decoration: none; }

h1, h2, h3, h4 {
  font-family: var(--serif);
  font-weight: 400;
  letter-spacing: -0.01em;
  margin: 0;
  line-height: 1.2;
}

html[data-lang="th"] h1,
html[data-lang="th"] h2,
html[data-lang="th"] h3 { line-height: 1.45; }

p { margin: 0 0 1em; }

.wrap {
  max-width: var(--wrap);
  margin: 0 auto;
  padding-inline: 24px;
}

.muted { color: var(--ink-3); }

ul.plain { list-style: none; margin: 0; padding: 0; }

/* ------------------------------------------------------------ demo notice -- */

.demo-bar {
  background: var(--ink);
  color: #d9d2c4;
  font-size: 12px;
  letter-spacing: 0.04em;
  text-align: center;
  padding: 7px 16px;
}

/* ----------------------------------------------------------------- header -- */

.site-header {
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
  position: sticky;
  top: 0;
  z-index: 20;
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding-block: 18px;
}

.brand { display: block; }

.brand-mark {
  font-family: var(--serif);
  font-size: 25px;
  letter-spacing: 0.02em;
  display: block;
  line-height: 1.1;
}

.brand-sub {
  display: block;
  font-size: 12px;
  color: var(--ink-3);
  margin-top: 3px;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 26px;
  font-size: 14px;
}

/* Thai has no spaces between words, so a narrow column will break a label
   like ที่ดินริมน้ำ down the middle. Nav labels never wrap. */
.site-nav a { padding-block: 4px; border-bottom: 1px solid transparent; white-space: nowrap; }
.site-nav a:hover { border-bottom-color: var(--ink); }

.nav-end { display: contents; }

/* The menu button and its scrim only exist below the nav breakpoint. */
.nav-checkbox { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.nav-button,
.nav-scrim { display: none; }

.lang-toggle {
  border: 1px solid var(--rule) !important;
  border-radius: var(--r);
  padding: 5px 12px !important;
  font-size: 13px;
}
.lang-toggle:hover { background: var(--ink); color: var(--paper); }

/* ------------------------------------------------------------------- hero -- */

/* The hero carries a photograph behind the type.
   
   TWO CROPS, not one. The band the photograph fills is a completely different
   shape at each end of the range: about 4.5:1 on a 1920px desktop and about
   1.1:1 on a 390px phone. A single file cannot serve both — `cover` would throw
   away 47% of the height on the desktop or 53% of the width on the phone.
   
   So: a 3.2:1 crop for anything tablet-width and up, and a 1.3:1 crop below
   that. The browser downloads only the one its media query matches.
   
   The gradient wash on top is what makes the type legible. Text over a bare
   photograph is readable or not depending on which part of the photograph it
   lands on, and that changes with every viewport width. */
.hero {
  position: relative;
  border-bottom: 1px solid var(--rule);
  background:
    linear-gradient(100deg,
      rgba(242, 238, 231, 0.97) 0%,
      rgba(242, 238, 231, 0.94) 38%,
      rgba(242, 238, 231, 0.72) 68%,
      rgba(242, 238, 231, 0.58) 100%),
    url("img/site/hero-wide.jpg") center / cover no-repeat,
    var(--paper-2);
}

@media (max-width: 860px) {
  /* Narrow crop, and the wash turns vertical and nearly solid: at this width
     the type sits over the middle of the frame rather than beside it. */
  .hero {
    background:
      linear-gradient(180deg,
        rgba(242, 238, 231, 0.95) 0%,
        rgba(242, 238, 231, 0.88) 60%,
        rgba(242, 238, 231, 0.92) 100%),
      url("img/site/hero-narrow.jpg") center / cover no-repeat,
      var(--paper-2);
  }
}

.hero-inner { padding-block: 86px 78px; }

.hero-title {
  font-size: clamp(34px, 5.4vw, 60px);
  margin-bottom: 22px;
  max-width: 16ch;
}

.hero-body {
  font-size: 18px;
  color: var(--ink-2);
  max-width: 62ch;
  margin-bottom: 30px;
}

.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; }

/* --------------------------------------------------------------- sections -- */

.section { padding-block: 68px; }
.section-tight { padding-top: 12px; }

.section-alt {
  background: var(--paper-2);
  border-block: 1px solid var(--rule);
}

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 30px;
  flex-wrap: wrap;
}

.section-head h2 { font-size: clamp(24px, 3vw, 33px); }

.section-link { font-size: 14px; color: var(--ink-2); }
.section-link:hover { color: var(--ink); }

.page-title { font-size: clamp(28px, 4vw, 42px); margin-bottom: 26px; }

.lede {
  font-size: 17px;
  color: var(--ink-2);
  max-width: 62ch;
  margin-bottom: 34px;
}

/* --------------------------------------------------------------- buttons -- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 22px;
  border-radius: var(--r);
  font-size: 14.5px;
  font-family: var(--sans);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
  text-align: center;
}

.btn-primary { background: var(--accent); color: #fff; }
.btn-primary:hover { background: #24382c; }

.btn-outline { border-color: var(--ink); color: var(--ink); background: transparent; }
.btn-outline:hover { background: var(--ink); color: var(--paper); }

.btn-quiet { border-color: var(--rule); color: var(--ink-2); background: transparent; }
.btn-quiet:hover { border-color: var(--ink-3); color: var(--ink); }

.btn-line { background: var(--line-green); color: #05340f; font-weight: 600; }
.btn-line:hover { filter: brightness(0.94); }

/* --------------------------------------------------------------- filters -- */

.filters {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 20px;
}

.filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: flex-end;
}

.field { display: flex; flex-direction: column; gap: 5px; min-width: 140px; }
.field-grow { flex: 1 1 220px; }
.field-price { min-width: 200px; }

.field-label {
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
}

html[data-lang="th"] .field-label { text-transform: none; letter-spacing: 0; font-size: 12.5px; }

.field input,
.field select,
.sort select {
  font-family: var(--sans);
  font-size: 14.5px;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 10px 11px;
  width: 100%;
  min-height: 42px;
}

.field input:focus,
.field select:focus,
.sort select:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}

.price-inputs { display: flex; gap: 8px; }

.field-actions { flex-direction: row; gap: 10px; align-items: stretch; }
.field-actions .btn { white-space: nowrap; }

/* ----------------------------------------------------------------- cards -- */

/* Three across at full width, stepping down to two and one.

   Three rather than four: a property card is carrying a photograph, and at
   four across the image is small enough that the thing being sold stops being
   legible. Twelve per page divides evenly by 3, 2 and 1, so the last row is
   never left with a single stranded card at any width.

   minmax(0, 1fr) rather than a pixel minimum: Thai is written without spaces,
   so a long title can look to the browser like one unbreakable word and push a
   column wider than the screen. */
.grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 28px;
}

@media (max-width: 980px) { .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; } }
@media (max-width: 620px) { .grid { grid-template-columns: 1fr; } }

.card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  overflow: hidden;
  transition: border-color .18s, transform .18s;
}

.card:hover { border-color: var(--ink-3); transform: translateY(-2px); }

.card-media { position: relative; aspect-ratio: 4 / 3; overflow: hidden; background: var(--paper-2); }
.card-media img { width: 100%; height: 100%; object-fit: cover; }

.badge {
  position: absolute;
  top: 12px;
  left: 12px;
  background: rgba(255,255,255,.94);
  color: var(--ink);
  font-size: 11.5px;
  letter-spacing: 0.05em;
  padding: 5px 10px;
  border-radius: var(--r);
}

.badge-sale { border-left: 3px solid var(--sale); }
.badge-rent { border-left: 3px solid var(--rent); }

/* The waterfront mark. Opposite corner from the sale/rent badge, which is also
   absolutely positioned at top-left — both at once would stack on top of each
   other. Reversed colours so it reads as a claim about the property rather
   than another status label. */
.badge-water {
  left: auto;
  right: 12px;
  background: var(--accent);
  color: #fff;
  border-left: 0;
  font-weight: 600;
}

/* Thai has no spaces, so "ติดน้ำ · แม่น้ำ" can wrap mid-word in a narrow card. */
.badge-water { white-space: nowrap; }

.card-body { padding: 18px 18px 20px; }

.card-zone {
  font-size: 11.5px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 7px;
}

html[data-lang="th"] .card-zone { text-transform: none; letter-spacing: 0; font-size: 13px; }

.card-title {
  font-size: 19px;
  margin-bottom: 12px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.card-price { font-size: 20px; font-family: var(--serif); margin-bottom: 10px; }

/* Georgia has no baht sign, so the browser substitutes it from another face
   and the glyph sits too close to the first digit. A little room fixes it. */
.cur { margin-right: 0.08em; }

.card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  font-size: 13.5px;
  color: var(--ink-2);
  padding-bottom: 12px;
  border-bottom: 1px solid var(--rule);
}

.card-pps { font-size: 12.5px; color: var(--ink-3); padding-top: 11px; }
.card-pps strong { color: var(--ink-2); font-weight: 600; }

/* ----------------------------------------------------------------- zones -- */

.zone-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr));
  gap: 20px;
}

.zone-card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 22px;
  display: flex;
  flex-direction: column;
  gap: 9px;
  transition: border-color .18s;
}

.zone-card:hover { border-color: var(--ink); }
.zone-card h3 { font-size: 20px; }
.zone-card p { font-size: 14px; color: var(--ink-2); margin: 0; flex: 1; }
.zone-count { font-size: 12.5px; color: var(--ink-3); }
.zone-empty { opacity: .58; }

/* ------------------------------------------------------------------- why -- */

.why-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: 34px;
}

.why h3 { font-size: 20px; margin-bottom: 9px; }
.why p { font-size: 15px; color: var(--ink-2); margin: 0; }

/* --------------------------------------------------------------- results -- */

.results-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: 26px;
}

.results-count { font-size: 14px; color: var(--ink-2); }

.sort { display: flex; flex-direction: column; gap: 5px; min-width: 200px; }

.empty {
  text-align: center;
  padding: 70px 20px;
  border: 1px dashed var(--rule);
  border-radius: var(--r);
}

.empty h1, .empty h2 { font-size: 27px; margin-bottom: 10px; }
.empty p { color: var(--ink-2); max-width: 46ch; margin-inline: auto; margin-bottom: 22px; }

.pager { display: flex; gap: 8px; justify-content: center; margin-top: 44px; }

.pager-item {
  min-width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  font-size: 14px;
}

.pager-item:hover { border-color: var(--ink); }
.pager-item.is-current { background: var(--ink); color: var(--paper); border-color: var(--ink); }

/* ---------------------------------------------------------------- detail -- */

.detail-top { padding-block: 22px 6px; }

.back-link { font-size: 14px; color: var(--ink-2); }
.back-link:hover { color: var(--ink); }

.gallery { padding-bottom: 8px; }

/* One large photograph and a 2x2 block of four beside it.
   Five visible; the rest stay in the DOM for the lightbox and for crawlers,
   hidden by :nth-child below rather than dropped from the markup. */
.gallery-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  grid-template-rows: repeat(2, 1fr);
  gap: 8px;
  height: min(60vh, 520px);
}

.gallery-item {
  margin: 0;
  overflow: hidden;
  border-radius: var(--r);
  background: var(--paper-2);
  position: relative;
}

.gallery-item img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transition: transform .45s ease;
}

.gallery-item:hover img { transform: scale(1.04); }

.gallery-lead { grid-column: 1; grid-row: 1 / span 2; }

/* Only the first five occupy the grid. */
.gallery-item:nth-child(n + 6) { display: none; }

/* "+5 more" sits on the last visible tile and opens the full set. */
.gallery-more {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  gap: 4px;
  background: rgba(16, 22, 28, .58);
  color: #fff;
  font-weight: 600;
  font-size: .95rem;
  letter-spacing: .01em;
  border: 0;
  width: 100%;
  cursor: pointer;
  transition: background .2s ease;
}

.gallery-more:hover { background: rgba(16, 22, 28, .7); }
.gallery-more span { display: block; }
.gallery-more .gallery-more-n { font-size: 1.5rem; line-height: 1; }

.detail-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 56px;
  padding-block: 48px 68px;
  align-items: start;
}

.detail-head {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

.detail-head .badge { position: static; border: 1px solid var(--rule); }

.detail-zone { font-size: 13.5px; color: var(--ink-2); }
.detail-ref { font-size: 12.5px; color: var(--ink-3); margin-left: auto; }

.detail-title { font-size: clamp(27px, 3.6vw, 40px); margin-bottom: 10px; }

.detail-address { color: var(--ink-2); font-size: 15.5px; margin-bottom: 26px; }

.price-block {
  border-block: 1px solid var(--rule);
  padding-block: 22px;
  margin-bottom: 34px;
}

.price-main { font-family: var(--serif); font-size: clamp(28px, 4vw, 38px); line-height: 1.1; }
.price-sub { font-size: 14px; color: var(--ink-3); margin-top: 9px; }
.price-sub strong { color: var(--ink); font-weight: 600; margin-left: 4px; }

/* the comparison block */

.market {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 24px;
  margin-bottom: 38px;
}

.market-title { font-size: 20px; margin-bottom: 14px; }

.market-verdict {
  display: inline-block;
  font-size: 14.5px;
  padding: 7px 13px;
  border-radius: var(--r);
  margin-bottom: 20px;
}

.market-verdict.is-below { background: var(--accent-soft); color: var(--accent); }
.market-verdict.is-above { background: #f6ece2; color: var(--rent); }
.market-verdict.is-flat  { background: var(--paper-2); color: var(--ink-2); }

.bars { display: flex; flex-direction: column; gap: 13px; }

.bar-row {
  display: grid;
  grid-template-columns: 150px minmax(0, 1fr) 110px;
  align-items: center;
  gap: 14px;
  font-size: 13.5px;
}

.bar-label { color: var(--ink-2); }

.bar-track { background: var(--paper-2); border-radius: 2px; height: 11px; overflow: hidden; }

.bar-fill { display: block; height: 100%; border-radius: 2px; }
.bar-this { background: var(--accent); }
.bar-avg  { background: #c4bcab; }

.bar-value { text-align: right; color: var(--ink); font-variant-numeric: tabular-nums; }

.market-note { font-size: 12.5px; color: var(--ink-3); margin: 18px 0 0; }

.prose h2, .features h2 { font-size: 22px; margin-bottom: 14px; }
.prose p { font-size: 16.5px; color: var(--ink-2); max-width: 68ch; }
.prose { margin-bottom: 38px; }

.specs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(180px, 100%), 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  overflow: hidden;
  margin-bottom: 38px;
}

.spec { background: var(--card); padding: 16px 18px; }
.spec dt { font-size: 11.5px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 5px; }
html[data-lang="th"] .spec dt { text-transform: none; letter-spacing: 0; font-size: 13px; }
.spec dd { margin: 0; font-size: 15.5px; }

.feature-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(190px, 100%), 1fr));
  gap: 9px 18px;
  font-size: 15px;
  color: var(--ink-2);
}

.feature-list li::before { content: "— "; color: var(--ink-3); }

/* contact */

.detail-side { position: sticky; top: 96px; }

.contact-card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 11px;
}

.contact-card h2 { font-size: 21px; }
.contact-card p { font-size: 14px; margin: 0; }

.agent { border-block: 1px solid var(--rule); padding-block: 15px; margin-block: 4px; }
.agent-label { font-size: 11.5px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 5px; }
html[data-lang="th"] .agent-label { text-transform: none; letter-spacing: 0; font-size: 13px; }
.agent-name { font-family: var(--serif); font-size: 18px; }
/* The agent's name in the contact card is a link, and on a touch screen a
   20px-tall line is a poor thing to aim at. */
.agent-name a { display: inline-block; padding-block: 8px; }
.agent-role { font-size: 13.5px; }

/* ---------------------------------------------------------------- footer -- */

.site-footer {
  border-top: 1px solid var(--rule);
  background: var(--paper-2);
  padding-block: 52px 26px;
  margin-top: 10px;
}

.footer-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: 40px;
}

.footer-brand { margin-bottom: 8px; }
.footer-grid h4 { font-family: var(--sans); font-size: 12px; letter-spacing: 0.07em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 12px; }
html[data-lang="th"] .footer-grid h4 { text-transform: none; letter-spacing: 0; font-size: 13.5px; }
.footer-grid p, .footer-grid li { font-size: 14px; }
.footer-grid li { margin-bottom: 5px; }
.footer-grid a:hover { color: var(--ink); text-decoration: underline; }

.footer-social { margin-top: 14px; display: flex; flex-wrap: wrap; gap: 8px; }
.footer-social a {
  font-size: 13px;
  padding: 4px 11px;
  border: 1px solid var(--line);
  border-radius: 999px;
  white-space: nowrap;
}
.footer-social a:hover { border-color: var(--ink-3); text-decoration: none; }

.footer-legal {
  margin-top: 40px;
  padding-top: 20px;
  border-top: 1px solid var(--rule);
  font-size: 12.5px;
}

/* -------------------------------------------------- intrinsic-width guard --

   Thai is written without spaces, so a whole sentence can look to the browser
   like one unbreakable word. In a grid track that is sized to its contents,
   that forces the column wider than the screen and the page scrolls sideways.
   Telling every card it may be narrower than its contents fixes it at the
   root — the text then wraps normally inside whatever width it is given. */

.grid > *,
.article-list > *,
.cat-grid > *,
.agent-grid > *,
.specs > *,
.feature-list > *,
.card-body,
.article-body,
.agent-card-body { min-width: 0; }

/* A button carrying an email address must not push the page wider than the
   phone it is on. */
.btn { max-width: 100%; overflow-wrap: anywhere; }

/* ------------------------------------------------------------ responsive -- */

/* Laptops. The English labels are wider than the Thai ones, so the nav has to
   give up some of its spacing here or it will not survive a 1280px laptop. */
@media (max-width: 1340px) {
  .site-nav { gap: 16px; font-size: 13.5px; }
  .site-nav a { padding-block: 3px; }
}

/* ---- The menu breakpoint.
   Set by the labels rather than by any device. Eight nav items plus a language
   toggle and a sign-in button need 1132px in English — "Waterfront
   condominiums" is a wide thing to write — and a nav that wraps onto two lines
   or clips its last button looks broken rather than responsive. So the whole
   nav becomes a panel behind one button below this width, which is what every
   iPad, every phone and any half-width desktop window will see. The Thai
   labels would survive down to about 1000px, but one breakpoint that both
   languages share is worth more than 200px of menu bar. */
@media (max-width: 1220px) {
  .header-inner { padding-block: 14px; gap: 14px; }

  .brand { position: relative; z-index: 2; }

  .nav-button {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    position: relative;
    z-index: 2;
    min-height: 44px;
    padding: 9px 15px;
    border: 1px solid var(--rule);
    border-radius: var(--r);
    background: var(--paper);
    font-size: 14.5px;
    cursor: pointer;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
  }

  .nav-burger { display: grid; gap: 4px; width: 17px; }
  .nav-burger i { display: block; height: 1.5px; background: var(--ink); border-radius: 2px; }

  .nav-checkbox:checked ~ .nav-button {
    background: var(--ink);
    border-color: var(--ink);
    color: var(--paper);
  }
  .nav-checkbox:checked ~ .nav-button .nav-burger i { background: var(--paper); }
  .nav-checkbox:focus-visible ~ .nav-button { outline: 2px solid var(--accent); outline-offset: 2px; }

  /* The panel. Hidden outright rather than merely transparent, so its links
     are out of the tab order and out of the accessibility tree when closed. */
  .site-nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 2;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
    box-shadow: 0 16px 30px rgba(22, 20, 15, 0.10);
    max-height: calc(100dvh - 68px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  .nav-checkbox:checked ~ .site-nav { display: flex; }

  .site-nav a {
    display: flex;
    align-items: center;
    min-height: 50px;
    padding: 12px 24px;
    font-size: 16px;
    border-bottom: 1px solid var(--rule);
  }
  .site-nav a:hover { border-bottom-color: var(--rule); background: var(--paper-2); }

  .nav-end {
    display: flex;
    gap: 10px;
    padding: 14px 24px 18px;
  }
  .nav-end a {
    flex: 1;
    justify-content: center;
    min-height: 46px;
    border: 1px solid var(--rule) !important;
    border-radius: var(--r);
    padding: 10px 14px !important;
  }
  .nav-end .nav-signin { background: var(--accent); color: #fff; border-color: var(--accent) !important; }

  .nav-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 1;
    background: rgba(22, 20, 15, 0.34);
    opacity: 0;
    visibility: hidden;
    transition: opacity .18s;
  }
  .nav-checkbox:checked ~ .nav-scrim { opacity: 1; visibility: visible; }
}

/* ---- Tablet. One narrower column of reading, two of cards. */
@media (max-width: 940px) {
  .detail-body { grid-template-columns: 1fr; gap: 36px; }
  .detail-side { position: static; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .hero-inner { padding-block: 66px 58px; }
  .grid { grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr)); gap: 24px; }
  .article-list { grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr)); gap: 26px; }
}

/* ---- Phone. */
@media (max-width: 720px) {
  .wrap { padding-inline: 18px; }
  .site-nav a, .nav-end { padding-inline: 18px; }

  .hero-inner { padding-block: 46px 42px; }
  .section { padding-block: 44px; }

  /* Every photograph, swiped sideways — better than hiding all but the first,
     which is what this used to do. */
  .gallery-grid {
    display: flex;
    grid-template-columns: none;
    grid-template-rows: none;
    height: auto;
    gap: 8px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* Bleed to the screen edges: a carousel that stops short of them reads as
       a mistake, and the padding is what tells you to keep swiping. */
    margin-inline: -18px;
    padding-inline: 18px;
  }
  .gallery-grid::-webkit-scrollbar { display: none; }
  .gallery-item {
    flex: 0 0 86%;
    aspect-ratio: 4 / 3;
    scroll-snap-align: center;
  }
  .gallery-item:not(.gallery-lead) { display: block; }
  .gallery-lead { grid-row: auto; }

  .bar-row { grid-template-columns: 1fr; gap: 5px; }
  .bar-value { text-align: left; }

  .field { min-width: 100%; }
  .field-actions { flex-direction: column; }
  /* 16px or larger, or iOS Safari zooms the page in on focus and leaves it
     there. This is the single most common reason a site "breaks" on iPhone. */
  .field input,
  .field select,
  .sort select { font-size: 16px; min-height: 46px; }

  .btn { min-height: 46px; }

  .specs { grid-template-columns: repeat(auto-fill, minmax(min(140px, 100%), 1fr)); }
  .spec { padding: 13px 14px; }
  .feature-list { grid-template-columns: 1fr 1fr; }

  .footer-grid { grid-template-columns: 1fr; gap: 30px; }
  .footer-legal { flex-direction: column; align-items: flex-start; gap: 10px; }
  .detail-ref { margin-left: 0; width: 100%; }
  .detail-head { flex-wrap: wrap; }
}

/* ---- Small phones (iPhone SE and the like). */
@media (max-width: 400px) {
  .brand-mark { font-size: 22px; }
  .nav-button-text { display: none; }
  .nav-button { padding: 9px 12px; }
  .feature-list { grid-template-columns: 1fr; }
  .grid, .article-list { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------- articles -- */

.article-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
  gap: 34px;
}

.article-card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: border-color .18s;
}
.article-card:hover { border-color: var(--ink-3); }

.article-media { display: block; aspect-ratio: 16 / 9; overflow: hidden; background: var(--paper-2); }
.article-media img { width: 100%; height: 100%; object-fit: cover; }

.article-body { padding: 20px; display: flex; flex-direction: column; gap: 10px; flex: 1; }

.article-meta {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  font-size: 12.5px;
  color: var(--ink-3);
}

.article-title { font-size: 21px; line-height: 1.3; }
.article-title a:hover { text-decoration: underline; }

.article-summary { font-size: 15px; color: var(--ink-2); margin: 0; flex: 1; }

/* one article */

.article-page { max-width: 720px; padding-block: 10px 70px; }

.article-head { margin-bottom: 30px; }
.article-h1 { font-size: clamp(29px, 4.4vw, 44px); margin: 12px 0 16px; }
.article-lede { font-size: 18.5px; color: var(--ink-2); margin: 0; }

.article-cover { margin: 0 0 36px; border-radius: var(--r); overflow: hidden; }
.article-cover img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }

.article-prose { font-size: 17.5px; color: var(--ink-2); }
.article-prose h2 { font-size: 26px; color: var(--ink); margin: 46px 0 14px; }
.article-prose h3 { font-size: 20px; color: var(--ink); margin: 34px 0 10px; }
.article-prose p { margin: 0 0 1.15em; }
.article-prose ul, .article-prose ol { margin: 0 0 1.3em; padding-left: 1.3em; }
.article-prose li { margin-bottom: .5em; }
.article-prose strong { color: var(--ink); font-weight: 600; }
.article-prose a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.article-prose hr { border: 0; border-top: 1px solid var(--rule); margin: 38px 0; }

.article-prose blockquote {
  margin: 0 0 1.3em;
  padding: 2px 0 2px 22px;
  border-left: 3px solid var(--rule);
  color: var(--ink-3);
  font-style: italic;
}

.article-tags { display: flex; flex-wrap: wrap; gap: 8px; margin: 34px 0 0; }
.tag {
  font-size: 12.5px;
  color: var(--ink-3);
  border: 1px solid var(--rule);
  border-radius: 20px;
  padding: 4px 12px;
}

.article-cta {
  margin-top: 44px;
  padding: 26px;
  background: var(--paper-2);
  border: 1px solid var(--rule);
  border-radius: var(--r);
}
.article-cta h2 { font-size: 21px; margin-bottom: 8px; }
.article-cta p { font-size: 15px; }
.article-cta-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 16px; }

/* ------------------------------------------------------------------ faq -- */

.faq { display: grid; gap: 26px; max-width: 760px; }
.faq-q { font-size: 19px; margin-bottom: 7px; }
.faq-a { font-size: 16px; color: var(--ink-2); margin: 0; }

@media (max-width: 720px) {
  .article-h1 { font-size: 28px; }
  .article-prose { font-size: 16.5px; }
  .article-prose h2 { font-size: 22px; margin-top: 34px; }
}

/* ------------------------------------------------------- area groupings -- */

.zone-group { margin-bottom: 40px; }
.zone-group:last-child { margin-bottom: 0; }

.zone-group-title {
  font-size: 15px;
  font-family: var(--sans);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-bottom: 10px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--rule);
}
html[data-lang="th"] .zone-group-title { text-transform: none; letter-spacing: 0; font-size: 16px; }

.zone-card h4 { font-size: 19px; font-family: var(--serif); font-weight: 400; }

/* frontage, the number that separates two plots of equal size */
.card-frontage { color: var(--accent); font-weight: 600; }
.price-note { font-size: 12.5px; color: var(--ink-3); margin: 10px 0 0; max-width: 52ch; }

/* footer sign-in */
.footer-legal { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.footer-signin { border-bottom: 1px solid var(--rule); }
.footer-signin:hover { color: var(--ink); border-bottom-color: var(--ink); }

/* ------------------------------------------------- the four categories -- */

.cat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
  gap: 16px;
}

.cat-card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 22px 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  transition: border-color .18s, transform .18s;
}
.cat-card:hover { border-color: var(--ink); transform: translateY(-2px); }
.cat-card h3 { font-size: 21px; }
.cat-card p { font-size: 14px; color: var(--ink-2); margin: 0; }

/* sign-in, in the header where people look for it */
.nav-signin {
  border: 1px solid var(--accent) !important;
  color: var(--accent);
  border-radius: var(--r);
  padding: 5px 14px !important;
  font-size: 13px;
}
.nav-signin:hover { background: var(--accent); color: #fff; }

/* ---------------------------------------------------------------- agents -- */

.agent-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
  gap: 26px;
}

.agent-card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: border-color .18s;
}
.agent-card:hover { border-color: var(--ink-3); }

.agent-photo { display: block; aspect-ratio: 1; overflow: hidden; background: var(--paper-2); }
.agent-photo img { width: 100%; height: 100%; object-fit: cover; }

.agent-photo-blank {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--serif);
  font-size: 54px;
}

.agent-card-body { padding: 18px; display: flex; flex-direction: column; gap: 6px; flex: 1; }
.agent-card-name { font-size: 21px; }
.agent-card-name a:hover { text-decoration: underline; }
.agent-card-title { font-size: 14px; margin: 0; }
.agent-card-count { font-size: 13px; color: var(--ink-3); margin: 0; }
.agent-card-links { display: flex; flex-direction: column; gap: 3px; font-size: 14px; margin: 6px 0; }
.agent-card-links a { color: var(--accent); }
.agent-card-links a:hover { text-decoration: underline; }

/* one agent */

.agent-head { display: flex; gap: 32px; align-items: flex-start; flex-wrap: wrap; }
.agent-photo-lg { width: 190px; flex: none; border-radius: var(--r); }
.agent-head-body { flex: 1; min-width: 260px; }
.agent-h1 { font-size: clamp(28px, 4vw, 40px); margin-bottom: 6px; }
.agent-h1-title { font-size: 17px; color: var(--ink-2); margin-bottom: 8px; }
.agent-head-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 18px; }

@media (max-width: 600px) {
  .agent-photo-lg { width: 120px; }
  .agent-head { gap: 20px; }
  .agent-head-body { min-width: 0; }

  /* A square portrait the full width of a phone pushes the name below the
     fold. Sideways instead: face left, name and contact beside it. */
  .agent-card { flex-direction: row; align-items: stretch; }
  .agent-photo { width: 118px; flex: none; aspect-ratio: auto; }
  .agent-card-body { padding: 15px; min-width: 0; }
  .agent-card-name { font-size: 18px; }
  .agent-card-links { gap: 2px; font-size: 13.5px; }
  .agent-card-links a { overflow-wrap: anywhere; }
}

/* pool toggle in the filter bar */
.field-toggle { min-width: 150px; justify-content: flex-end; }
.toggle { display: flex; align-items: center; gap: 8px; min-height: 42px; font-size: 14.5px; }
.toggle input { width: 17px; height: 17px; accent-color: var(--accent); }
.card-pool { color: var(--accent); font-weight: 600; }

/* --------------------------------------------------------------- lightbox --
   Full-screen photograph viewer. Created by app.js, so none of this applies
   unless the script ran; without it every photograph is still in the grid. */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 20px;
  background: rgba(12, 16, 20, .94);
}

/* `display: grid` above beats the hidden ATTRIBUTE, so without this the
   overlay is permanently on screen: invisible against the page but covering
   it, swallowing every click — which is why the close button appeared dead.
   A plain [hidden] selector loses to the class selector; this one wins. */
.lightbox[hidden] { display: none; }

.lightbox-stage {
  margin: 0;
  grid-column: 2;
  display: grid;
  place-items: center;
  max-height: 88vh;
}

.lightbox-stage img {
  max-width: 100%;
  max-height: 88vh;
  object-fit: contain;
  border-radius: 4px;
}

.lightbox-nav,
.lightbox-close {
  background: rgba(255, 255, 255, .12);
  color: #fff;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  line-height: 1;
  transition: background .2s ease;
}

.lightbox-nav { width: 48px; height: 48px; font-size: 2rem; }
.lightbox-nav:hover,
.lightbox-close:hover { background: rgba(255, 255, 255, .26); }

.lightbox-close {
  position: absolute;
  top: 18px; right: 18px;
  width: 42px; height: 42px;
  font-size: 1.6rem;
  /* Above the photograph, which can otherwise reach the same corner. */
  z-index: 2;
}

.lightbox-count {
  position: absolute;
  bottom: 18px; left: 50%;
  transform: translateX(-50%);
  margin: 0;
  color: rgba(255, 255, 255, .8);
  font-size: .9rem;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 720px) {
  /* The arrows would cover the photograph on a narrow screen; swipe and the
     close button do the same job with the whole width left for the image. */
  .lightbox { grid-template-columns: 1fr; padding: 12px; }
  .lightbox-nav { display: none; }
  .lightbox-stage { grid-column: 1; }
}

/* ------------------------------------------------------------------ video --
   A 16:9 box that keeps its shape at any width, so the player never letterboxes
   itself or pushes the page sideways on a phone. */

.video { padding-block: 26px 6px; }

.video-frame {
  position: relative;
  aspect-ratio: 16 / 9;
  max-width: 100%;
  border-radius: var(--r);
  overflow: hidden;
  background: #000;
}

.video-frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}


/* ----------------------------------------------------------------- brand --
   The logo mark beside the wordmark, same artwork as the favicon. */

.brand { display: flex; align-items: center; gap: 11px; }
.brand-logo { width: 44px; height: 44px; flex: 0 0 auto; }
.brand-words { display: block; }

.footer-brand-row { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.footer-brand-row .brand-logo { width: 34px; height: 34px; }
.footer-brand-row .footer-brand { margin: 0; }

@media (max-width: 520px) {
  .brand-logo { width: 36px; height: 36px; }
}

/* ------------------------------------------------------- nav dropdown --
   "All properties" carries the ways of narrowing it: the four waterfront
   categories, then sale and rent.

   Opens on hover AND on focus-within, so it is reachable from the keyboard.
   No JavaScript: a menu that only works once a script has loaded is a menu
   that sometimes does not work. */

.nav-group { position: relative; display: flex; align-items: center; }

.nav-group-top {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
}

.nav-caret { font-size: 9px; line-height: 1; transform: translateY(1px); color: var(--ink-3); }

.nav-sub {
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 190px;
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  box-shadow: 0 14px 30px rgba(22, 20, 15, .12);
  padding: 6px;
  /* Hidden by opacity rather than display:none so it can animate, and made
     inert with visibility so a keyboard cannot tab into a closed menu. */
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity .16s ease, transform .16s ease, visibility .16s;
  z-index: 30;
}

/* A small bridge across the gap, or the menu closes as the pointer travels
   from the parent down to the first item. */
.nav-group::after {
  content: "";
  position: absolute;
  top: 100%; left: 0; right: 0;
  height: 10px;
}

.nav-group:hover .nav-sub,
.nav-group:focus-within .nav-sub {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.nav-sub a {
  padding: 8px 12px;
  border-bottom: 0 !important;
  border-radius: 2px;
  white-space: nowrap;
}

.nav-sub a:hover { background: var(--accent-soft); }

.nav-sub-rule {
  display: block;
  height: 1px;
  background: var(--rule);
  margin: 5px 8px;
}

@media (max-width: 1220px) {
  /* The whole nav is already a stacked panel here, so the submenu just sits
     inline and indented. Nothing hovers on a touch screen. */
  .nav-group { display: block; }
  .nav-caret { display: none; }

  .nav-sub {
    position: static;
    opacity: 1;
    visibility: visible;
    transform: none;
    border: 0;
    box-shadow: none;
    background: transparent;
    padding: 0;
    min-width: 0;
  }

  .nav-sub a { padding-left: 34px; }
  .nav-sub-rule { display: none; }
  .nav-group::after { display: none; }
}

/* -------------------------------------------------------------- spotlight --
   Two featured properties above the main grid on /properties, rotated daily.
   Wider cards than the 3-up grid below, so the pair reads as a selection
   rather than as the first two of a list. */

.spotlight { margin-bottom: 44px; }

.spotlight-head { margin-bottom: 18px; }
.spotlight-head h2 { font-size: clamp(21px, 2.4vw, 27px); }
.spotlight-head p { margin: 4px 0 0; font-size: 14px; }

.grid-spotlight { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px; }

.spotlight-next {
  font-size: clamp(21px, 2.4vw, 27px);
  margin-bottom: 18px;
  padding-top: 8px;
  border-top: 1px solid var(--rule);
}

@media (max-width: 760px) {
  .grid-spotlight { grid-template-columns: 1fr; }
}

/* Breadcrumb trail. Replaces a single "back" link, which only helped someone
   who arrived from the page it pointed at — anyone landing from search had no
   route up the site. */
.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-size: 13.5px;
  color: var(--ink-3);
}
.crumbs a { color: var(--ink-2); border-bottom: 1px solid transparent; }
.crumbs a:hover { border-bottom-color: var(--ink-2); }
.crumbs span { color: var(--ink-3); }

/* A listing without a stated price still needs something in the line where the
   price per unit would be — an empty band under the price reads as a rendering
   fault rather than as information that has not arrived yet. */
.card-pps-ask { color: var(--ink-3); font-style: italic; }

/* Last-updated stamp on a listing. A listing with no date reads as possibly
   sold and forgotten. */
.detail-updated { color: var(--ink-3); font-size: 13px; }

/* "New" for the first week. Green rather than the sale/rent greys, because it
   is a claim about freshness rather than another status label.
   
   Both this and the waterfront mark want the top-right corner, so the two are
   laid out as a column there instead of each being positioned by hand. The
   earlier attempt used `.badge-water ~ .badge-new`, which could never match:
   the "New" badge comes FIRST in the markup, and ~ only looks forwards. It
   also left a 46px gap above the badge on any card with no waterfront mark
   to sit under. */
.card-badges {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
}

.card-badges .badge { position: static; }

.badge-new {
  background: #4c7a12;
  color: #fff;
  border-left: 0;
  font-weight: 600;
}

/* ==========================================================================
   Motion
   --------------------------------------------------------------------------
   Two kinds: an entrance for the hero, and a reveal for everything that
   arrives on scroll. Both are opacity + transform only, so nothing here can
   move the layout or cost anything in Core Web Vitals.

   Everything is off by default in the markup sense: the reveal styles only
   apply once app.js adds .js-motion to <html>. Without JavaScript the page
   renders complete and static, which is the same bargain the rest of the
   file makes.
   ========================================================================== */

@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

/* --- Hero ---------------------------------------------------------------
   Plays on load rather than on scroll: it is already in view. The stagger is
   small — the eye should register order, not wait through a sequence. */

.js-motion .hero-title,
.js-motion .hero-body,
.js-motion .hero-actions {
  animation: rise .7s cubic-bezier(.22, .61, .36, 1) backwards;
}
.js-motion .hero-title   { animation-delay: .05s; }
.js-motion .hero-body    { animation-delay: .17s; }
.js-motion .hero-actions { animation-delay: .29s; }

/* --- Scroll reveal ------------------------------------------------------
   app.js tags candidates with .reveal and unsets it with .is-in once they
   cross into view. --i is the position within a row, which turns a grid into
   a short cascade instead of four things appearing at once. */

.js-motion .reveal {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity .62s cubic-bezier(.22, .61, .36, 1),
    transform .62s cubic-bezier(.22, .61, .36, 1);
  transition-delay: calc(var(--i, 0) * 70ms);
}

.js-motion .reveal.is-in {
  opacity: 1;
  transform: none;
}

/* --- Card cover ---------------------------------------------------------
   The card already lifts on hover; this gives the photograph the same slow
   scale the gallery uses, so the two read as one idea. .card-media must clip
   or the image grows past its corner. */

.card-media { overflow: hidden; }

.card-media img {
  transition: transform .55s cubic-bezier(.22, .61, .36, 1);
}
.card:hover .card-media img { transform: scale(1.035); }

/* --- Buttons ------------------------------------------------------------ */

.btn {
  transition: background .18s, color .18s, border-color .18s, transform .18s;
}
.btn:hover  { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

/* --- Opting out ---------------------------------------------------------
   Anyone who has asked their system for less motion gets the page as it was
   before any of the above: everything visible, nothing moving. The reveal
   rules must be neutralised explicitly, since an element left at opacity 0
   with its transition removed would never appear at all. */

@media (prefers-reduced-motion: reduce) {
  .js-motion .hero-title,
  .js-motion .hero-body,
  .js-motion .hero-actions {
    animation: none;
  }

  .js-motion .reveal,
  .js-motion .reveal.is-in {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .card:hover .card-media img,
  .btn:hover,
  .btn:active {
    transform: none;
  }

  .gallery-item:hover img { transform: none; }
}
