/* Krua Bophut. Final site, built from the "Lantern" concept: night blue, teak and candle gold. */

/* ---------- Fonts (self-hosted, see fonts/make.py) ----------
   One family name per role. Latin and Thai faces share it and split by unicode-range, so an
   English page never downloads a Thai font and a Thai page gets Thai faces drawn to match. */
@font-face {
  font-family: "KB Serif"; font-style: normal; font-weight: 300 400; font-display: swap;
  src: url(fonts/fraunces-latin-340.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: "KB Serif"; font-style: italic; font-weight: 300 400; font-display: swap;
  src: url(fonts/fraunces-latin-340-italic.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;
}
/* Thai has no italic, so on the Thai page the italic styles are set upright (see "Thai" below). */
@font-face {
  font-family: "KB Serif"; font-style: normal; font-weight: 300 400; font-display: swap;
  src: url(fonts/noto-serif-thai-300.woff2) format("woff2");
  unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC;
}
/* Latin and Thai faces of one family must carry identical weight ranges: Chrome only falls through
   unicode-range segments within one weight match, so a 400-600 Figtree beside a 400-500 Plex left
   every Thai body line in the system face. Figtree is one variable file, declared twice. */
@font-face {
  font-family: "KB Sans"; font-style: normal; font-weight: 400 500; font-display: swap;
  src: url(fonts/figtree-latin-400-600.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: "KB Sans"; font-style: normal; font-weight: 501 700; font-display: swap;
  src: url(fonts/figtree-latin-400-600.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: "KB Sans"; font-style: normal; font-weight: 400 500; font-display: swap;
  src: url(fonts/plex-sans-thai-looped-400.woff2) format("woff2");
  unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC;
}
@font-face {
  font-family: "KB Sans"; font-style: normal; font-weight: 501 700; font-display: swap;
  src: url(fonts/plex-sans-thai-looped-600.woff2) format("woff2");
  unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC;
}

:root {
  --night: #090b10;
  --night-2: #0d121b;
  --teak: #130d09;
  --candle: #f1cd94;
  --candle-2: #dcb985;
  --ink: #e9e0d0;
  --ink-2: #c3b6a2;
  --hair: rgba(241, 205, 148, 0.18);
  --orange: #f37024;
  --orange-ink: #1c0d03;

  --serif: "KB Serif", "Iowan Old Style", Georgia, serif;
  --sans: "KB Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --thai-sys: system-ui, -apple-system, "Thonburi", "Leelawadee UI", "Noto Sans Thai", sans-serif;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-io: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-brush: cubic-bezier(0.45, 0.05, 0.25, 1);

  --gut: clamp(20px, 5vw, 72px);
  --maxw: 1200px;
  /* the one left edge: the 1200px column, or the gutter on narrower screens */
  --edge: max(var(--gut), calc((100vw - var(--maxw)) / 2));
  --col-gap: clamp(16px, 2.4vw, 32px);
  --sec: clamp(96px, 10vw, 152px);
  --bar-h: 64px;
}

*, *::before, *::after { box-sizing: border-box; }

html {
  background: var(--night);
  color: var(--ink);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: var(--bar-h);
}
/* No global smooth scrolling: Chrome would animate the restored position on reload or back.
   app.js smooth-scrolls the in-page links instead. */

body {
  margin: 0;
  background: var(--night);
  font-family: var(--sans);
  font-size: clamp(16px, 15px + 0.2vw, 18px);
  line-height: 1.7;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
}

img { display: block; max-width: 100%; height: auto; }
picture { display: contents; }
figure { margin: 0; }

a { color: inherit; text-decoration: none; -webkit-tap-highlight-color: transparent; }
:focus-visible { outline: 2px solid var(--candle); outline-offset: 4px; border-radius: 2px; }
[tabindex="-1"]:focus { outline: none; } /* section targets of in-page links */

h1, h2, h3, p, dl, dd { margin: 0; }

h2 {
  font-family: var(--serif);
  font-weight: 340;
  font-size: clamp(34px, 1.55rem + 2.3vw, 60px);
  line-height: 1.06;
  letter-spacing: -0.016em;
  color: var(--candle);
  text-wrap: balance;
}
h3 {
  display: flex; align-items: baseline; gap: 0.5em;
  font-family: var(--serif);
  font-weight: 340;
  font-size: clamp(28px, 1.3rem + 1.1vw, 40px);
  line-height: 1.12;
  letter-spacing: -0.01em;
  color: var(--candle);
  text-wrap: balance;
}
.num {
  flex: none;
  font-style: italic;
  font-size: 0.5em;
  line-height: 1;
  color: var(--candle-2);
  transform: translateY(-0.1em);
}
p { max-width: 34em; text-wrap: pretty; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* Thai text on the English page uses the system face, so no Thai web font is fetched. */
.th-sys, .lang [lang="th"] { font-family: var(--thai-sys); }

.skip {
  position: fixed; left: 16px; top: 12px; z-index: 100;
  padding: 12px 18px; background: var(--candle); color: var(--orange-ink);
  font-weight: 600; font-size: 15px; border-radius: 4px;
  transform: translateY(-160%);
  transition: transform 0.4s var(--ease-out);
}
.skip:focus-visible { transform: none; }

.wrap {
  width: 100%;
  max-width: calc(var(--maxw) + 2 * var(--gut));
  margin-inline: auto;
  padding-inline: var(--gut);
}
.grid12 {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--col-gap);
}

/* ---------- Buttons and links ---------- */

.actions { display: flex; flex-wrap: wrap; gap: 12px; }

.btn {
  position: relative;
  isolation: isolate;
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 52px; padding: 0 28px;
  font: 600 16px/1.1 var(--sans);
  letter-spacing: 0.015em;
  border-radius: 4px;
  overflow: hidden;
  transition: transform 0.55s var(--ease-out);
}
.btn::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  opacity: 0; transition: opacity 0.45s var(--ease-out);
}
.btn-primary { background: var(--orange); color: var(--orange-ink); }
.btn-primary::after { background: #fff; }
.btn-ghost { color: var(--candle); box-shadow: inset 0 0 0 1px rgba(241, 205, 148, 0.5); }
.btn-ghost::after { background: var(--candle); }
.btn-sm { min-height: 44px; padding: 0 18px; font-size: 15px; }

@media (hover: hover) {
  .btn:hover { transform: translateY(-2px); }
  .btn-primary:hover::after { opacity: 0.16; }
  .btn-ghost:hover::after { opacity: 0.1; }
}
.btn:active { transform: translateY(0); transition-duration: 0.15s; }

.lnk {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 5px;
  text-decoration-color: rgba(233, 224, 208, 0.38);
}
@media (hover: hover) {
  .lnk:hover { color: var(--candle); text-decoration-color: var(--candle); }
}

/* ---------- Logo: three stacked layers, boxes in px of the 1926x687 master (assets.json) ---------- */

.lp {
  position: absolute;
  left: calc(var(--l) / 19.26 * 1%);
  top: calc(var(--t) / 6.87 * 1%);
  width: calc(var(--w) / 19.26 * 1%);
  height: calc(var(--h) / 6.87 * 1%);
}
.lp-thai { --l: 33; --t: 6; --w: 646; --h: 215; }
.lp-word { --l: 6; --t: 194; --w: 1914; --h: 394; }
.lp-tag  { --l: 800; --t: 584; --w: 1112; --h: 97; }

.logo { width: var(--logo-w, 600px); }
.logo-art { position: relative; display: block; aspect-ratio: 1926 / 687; }
.logo-glow {
  position: absolute;
  left: -12%; top: -33.6%; width: 124%; height: 167.3%;
  max-width: none;
  opacity: 0.3;
  pointer-events: none;
}
.ll { --f: 0.36; overflow: hidden; }
.ll-m {
  position: absolute; left: 0; top: 0; height: 100%;
  width: calc(100% * (1 + var(--f)));
}
.ll-m img {
  position: absolute; left: 0; top: 0;
  width: calc(100% / (1 + var(--f)));
  height: 100%;
  max-width: none;
}

/* ---------- Header ----------
   Without JS it sits at the top of the hero and scrolls away, holding only the language link.
   With JS it is fixed: clear over the photo, then a solid night bar (nothing shows through)
   before any copy reaches it, and the small logo and Call to book join once the hero copy has gone. */

.bar {
  position: absolute; inset: 0 0 auto 0; z-index: 50;
  display: flex; align-items: center; gap: 12px;
  height: calc(var(--bar-h) + env(safe-area-inset-top));
  padding: env(safe-area-inset-top) max(var(--edge), env(safe-area-inset-right)) 0 max(var(--edge), env(safe-area-inset-left));
}
.bar-home { display: block; padding: 8px 0; margin-right: auto; }
.bar-home img { width: clamp(92px, 24vw, 112px); }
.bar-cta { white-space: nowrap; }
.bar-home, .bar-cta { visibility: hidden; opacity: 0; }
.lang {
  display: flex; align-items: center;
  margin-right: -6px;
  font-size: 15px; letter-spacing: 0.04em;
  color: var(--ink-2);
}
.lang a {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px; padding: 0 6px;
  text-decoration: underline 1px transparent;
  text-underline-offset: 6px;
}
/* The current language is marked by more than colour: candle gold and a fine underline. */
.lang a[aria-current="true"] { color: var(--candle); text-decoration-color: currentColor; }
.lang a:not([aria-current="true"]) { color: var(--ink-2); }
.lang span { opacity: 0.6; }
@media (hover: hover) { .lang a:not([aria-current="true"]):hover { color: var(--ink); } }
@media (max-width: 420px) {
  .bar { gap: 6px; }
  .bar .btn-sm { padding: 0 14px; }
}

/* The solid night is its own layer, so turning the bar solid only fades opacity. */
html.has-bar .bar { position: fixed; }
html.has-bar .bar::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--night);
  border-bottom: 1px solid var(--hair);
  opacity: 0;
  transition: opacity 0.35s var(--ease-out);
  pointer-events: none;
}
html.has-bar .bar.is-solid::before { opacity: 1; }
html.has-bar .bar-home, html.has-bar .bar-cta {
  transition: opacity 0.5s var(--ease-out), visibility 0s linear 0.5s;
}
html.has-bar .bar.is-brand .bar-home, html.has-bar .bar.is-brand .bar-cta {
  visibility: visible; opacity: 1;
  transition: opacity 0.6s var(--ease-out), visibility 0s;
}
/* While the Visit section's own buttons are on screen, the bar's Call to book steps aside. */
html.has-bar .bar.is-brand.is-quiet .bar-cta {
  visibility: hidden; opacity: 0;
  transition: opacity 0.4s var(--ease-out), visibility 0s linear 0.4s;
}

/* ---------- Hero ---------- */

.hero {
  --logo-w: min(84vw, 340px);
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  align-items: end;
  overflow: hidden;
  isolation: isolate;
  background: var(--night);
}
.hero-media {
  position: absolute; inset: 0; z-index: -2;
  overflow: hidden;
  background: var(--night);
}
.hero-media::before {
  /* blur-up placeholder, painted with the first frame */
  content: ""; position: absolute; inset: -40px;
  background: var(--lq) center / cover no-repeat;
  filter: blur(22px);
}
.hero-pic {
  position: absolute; inset: 0;
  display: block;
  opacity: 0;
  transition: opacity 2.6s var(--ease-io);
}
.hero-pic.is-on { opacity: 1; }
.hero-pic img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  transform-origin: 50% 40%;
}
.hero-shade {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(180deg, rgba(9, 11, 16, 0.86) 0%, rgba(9, 11, 16, 0.72) 7%, rgba(9, 11, 16, 0) 19%),
    linear-gradient(0deg, rgba(9, 11, 16, 1) 0%, rgba(9, 11, 16, 0.86) 22%, rgba(9, 11, 16, 0.5) 42%, rgba(9, 11, 16, 0) 62%);
}
.hero-copy {
  width: 100%;
  padding: 0 var(--gut) calc(clamp(32px, 6vh, 64px) + env(safe-area-inset-bottom));
}
.hero-line {
  margin-top: clamp(16px, 2.6vh, 26px);
  max-width: 22em;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 340;
  font-size: clamp(20px, 1.05rem + 0.5vw, 26px);
  line-height: 1.34;
  color: var(--candle);
}
.hero-hours {
  margin-top: 10px;
  font-size: 17px;
  letter-spacing: 0.03em;
  color: var(--ink);
}
.hero .actions { margin-top: clamp(20px, 3.2vh, 30px); }

/* Phones and portrait tablets: the house stands in the top of the screen and fades into the
   night where the name sits, so the logo is never laid over candles or signs. */
@media (max-aspect-ratio: 4/5) {
  .hero-media {
    bottom: auto;
    height: min(100%, 138vw);
    -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 56%, rgba(0, 0, 0, 0.45) 78%, transparent 100%);
    mask-image: linear-gradient(180deg, #000 0%, #000 56%, rgba(0, 0, 0, 0.45) 78%, transparent 100%);
  }
  .hero-media::before { background-image: var(--lq-p); }
  .hero-pic img { object-position: 50% 22%; transform-origin: 50% 20%; }
  /* The hall photo has pale napkins and a table edge low in the frame: a deeper night under the name. */
  .hero-pic + .hero-pic::after {
    content: ""; position: absolute; inset: 0; pointer-events: none;
    background: linear-gradient(0deg, rgba(9, 11, 16, 0.92) 0%, rgba(9, 11, 16, 0.85) 34%, rgba(9, 11, 16, 0) 62%);
  }
  .hero-shade {
    background:
      linear-gradient(180deg, rgba(9, 11, 16, 0.86) 0%, rgba(9, 11, 16, 0.72) 7%, rgba(9, 11, 16, 0) 19%),
      linear-gradient(0deg, rgba(9, 11, 16, 1) 0%, rgba(9, 11, 16, 0.92) 30%, rgba(9, 11, 16, 0.4) 44%, rgba(9, 11, 16, 0) 56%);
  }
}

@media (min-width: 900px) and (min-aspect-ratio: 801/1000) {
  /* The name sits on the page's column edge. The photo starts where the name ends and feathers
     into the night on its left, so the name stays on dark ground, away from the lamps. */
  .hero { --logo-w: clamp(400px, 35vw, 560px); }
  .hero-media {
    left: calc(var(--edge) + var(--logo-w) * 0.92);
    -webkit-mask-image: linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, 0.3) 22%, #000 46%);
    mask-image: linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, 0.3) 22%, #000 46%);
  }
  .hero-pic img { object-position: 38% 50%; transform-origin: 46% 45%; }
  .hero-shade {
    background:
      linear-gradient(180deg, rgba(9, 11, 16, 0.86) 0%, rgba(9, 11, 16, 0.72) 7%, rgba(9, 11, 16, 0) 19%),
      linear-gradient(0deg, rgba(9, 11, 16, 0.9) 0%, rgba(9, 11, 16, 0.4) 14%, rgba(9, 11, 16, 0) 34%);
  }
  .hero-copy {
    width: auto;
    max-width: calc(var(--logo-w) + var(--edge) + var(--gut));
    padding-left: var(--edge);
    padding-bottom: clamp(56px, 10vh, 112px);
  }
}

/* ---------- Frames: clean photo windows, no borders. Reveal + parallax live inside .px ---------- */

.frame {
  position: relative;
  overflow: hidden;
  background: #17110c;
}
.frame .px {
  position: absolute; left: 0; right: 0; top: -8%; bottom: -8%;
}
.frame .px img {
  width: 100%; height: 100%;
  object-fit: cover;
  max-width: none;
}
figcaption {
  margin-top: 14px;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 340;
  font-size: 17px;
  line-height: 1.45;
  color: var(--candle-2);
}

/* ---------- The house (story) ---------- */

.story { padding-block: clamp(80px, 9vw, 136px) var(--sec); background: var(--night); }
.story-text p { margin-top: clamp(22px, 2.6vw, 32px); }
.story-a { aspect-ratio: 4 / 5; margin: 36px calc(-1 * var(--gut)) 0; }
.story-b { aspect-ratio: 16 / 9; margin: 10px calc(-1 * var(--gut)) 0; }

@media (min-width: 900px) {
  .story-grid {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    grid-template-rows: auto auto;
    column-gap: var(--col-gap);
    row-gap: clamp(40px, 4.4vw, 64px);
  }
  .story-text { grid-column: 1 / span 5; grid-row: 1; align-self: start; padding-top: 6px; }
  .story-a { grid-column: 7 / span 6; grid-row: 1 / span 2; aspect-ratio: auto; min-height: 560px; margin: 0; align-self: stretch; }
  .story-b { grid-column: 1 / span 5; grid-row: 2; aspect-ratio: 3 / 2; margin: 0; align-self: end; }
}

/* ---------- Kitchen ---------- */

.kitchen {
  padding-block: 0 var(--sec);
  background: linear-gradient(180deg, var(--night) 0%, var(--teak) 22%, var(--teak) 100%);
}
.kitchen-text p { margin-top: clamp(20px, 2.4vw, 28px); }
.seafood { margin: 40px calc(-1 * var(--gut)) 0; }
.seafood-img { aspect-ratio: 9 / 5; }
.seafood figcaption { padding-inline: var(--gut); }
.plates {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 10px calc(-1 * var(--gut)) 0;
}
.plate-a { grid-column: 1 / -1; aspect-ratio: 3 / 2; }
.plate-b, .plate-c { aspect-ratio: 355 / 500; }
/* daylight food photos sit into the candlelit page under a soft edge vignette */
.plate .px::after, .seafood-img .px::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(125% 100% at 50% 50%, rgba(19, 13, 9, 0) 56%, rgba(19, 13, 9, 0.42) 100%);
}

@media (hover: hover) {
  .plate img, .seafood-img img { transition: transform 1.4s var(--ease-out); }
}

@media (min-width: 900px) {
  .kitchen-grid {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    column-gap: var(--col-gap);
    align-items: center;
  }
  .kitchen-text { grid-column: 1 / span 5; padding-bottom: 36px; }
  .seafood { grid-column: 7 / span 6; margin: 0; }
  .seafood figcaption { padding-inline: 0; }
  .plates {
    grid-column: 1 / -1;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    column-gap: var(--col-gap);
    margin: clamp(48px, 5vw, 72px) 0 0;
  }
  .plate-a { grid-column: 1 / span 6; }
  .plate-b { grid-column: 7 / span 3; aspect-ratio: auto; }
  .plate-c { grid-column: 10 / span 3; aspect-ratio: auto; }
}

/* ---------- Places: inside, the deck, the sand ---------- */

.places { background: linear-gradient(180deg, var(--teak) 0%, var(--night-2) 46%, var(--night) 100%); padding-top: 0; }
.place { padding-top: clamp(64px, 7vw, 104px); }
.place-big { aspect-ratio: 3 / 2; margin: 26px calc(-1 * var(--gut)) 0; }
.place-deck .place-big { aspect-ratio: 4 / 5; }
.place-text p { margin-top: 14px; }
.place-small { aspect-ratio: 16 / 9; margin: 10px calc(-1 * var(--gut)) 0; }

@media (min-width: 701px) {
  .place-deck .place-big { aspect-ratio: 3 / 2; }
}
@media (min-width: 900px) {
  .place-grid {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    grid-template-rows: auto auto;
    column-gap: var(--col-gap);
    row-gap: clamp(28px, 3vw, 40px);
  }
  .place-big { grid-row: 1 / span 2; align-self: center; margin: 0; }
  .place-text { grid-row: 1; align-self: end; }
  .place-small { grid-row: 2; align-self: start; aspect-ratio: 3 / 2; margin: 0; }
  .place-house .place-big { grid-column: 1 / span 7; }
  .place-house .place-text, .place-house .place-small { grid-column: 9 / span 4; }
  .place-deck .place-big { grid-column: 6 / span 7; }
  .place-deck .place-text, .place-deck .place-small { grid-column: 1 / span 4; }
}

/* ---------- Down on the sand: sunset, a dip through dusk, then moonlight ---------- */

.sand { position: relative; margin-top: clamp(72px, 8vw, 120px); }
.sand-stage {
  position: relative;
  height: 100vh;
  height: 100svh;
  min-height: 560px;
  overflow: hidden;
  isolation: isolate;
  background: var(--night);
}
.sand-pic { position: absolute; inset: 0; display: block; z-index: -2; }
.sand-pic img { width: 100%; height: 100%; object-fit: cover; max-width: none; }
.sand-sun img { object-position: 50% 50%; transform-origin: 50% 45%; }
/* The moon is near the top of its photo: keep the top edge, and push in downward so it stays in view. */
.sand-moon img { object-position: 50% 0%; transform-origin: 52% 0%; }
.sand-shade {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(180deg, rgba(9, 11, 16, 0.75) 0%, rgba(9, 11, 16, 0) 6%),
    linear-gradient(0deg, rgba(9, 11, 16, 1) 0%, rgba(9, 11, 16, 0.94) 38%, rgba(9, 11, 16, 0.55) 46%, rgba(9, 11, 16, 0) 54%);
}
@media (max-aspect-ratio: 4/5) {
  .sand-pic {
    bottom: auto;
    height: min(100%, 134vw);
    -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 60%, rgba(0, 0, 0, 0.4) 82%, transparent 100%);
    mask-image: linear-gradient(180deg, #000 0%, #000 60%, rgba(0, 0, 0, 0.4) 82%, transparent 100%);
  }
  .sand-sun img { object-position: 50% 35%; }
}
@media (min-aspect-ratio: 4/5) {
  /* The left scrim eases out over many stops, so it reads as evening light, not a box edge; a soft
     pool of night from the bottom-left corner keeps the copy at 7.8:1 or better at every step. */
  .sand-shade {
    background:
      linear-gradient(180deg, rgba(9, 11, 16, 0.7) 0%, rgba(9, 11, 16, 0) 6%),
      radial-gradient(120% 95% at 0% 100%, rgba(9, 11, 16, 0.78) 0%, rgba(9, 11, 16, 0.6) 38%, rgba(9, 11, 16, 0.25) 62%, rgba(9, 11, 16, 0) 82%),
      linear-gradient(0deg, rgba(9, 11, 16, 0.94) 0%, rgba(9, 11, 16, 0.55) 30%, rgba(9, 11, 16, 0) 52%),
      linear-gradient(90deg, rgba(9, 11, 16, 0.9) 0%, rgba(9, 11, 16, 0.78) 18%, rgba(9, 11, 16, 0.6) 30%, rgba(9, 11, 16, 0.34) 42%, rgba(9, 11, 16, 0.12) 54%, rgba(9, 11, 16, 0) 64%);
  }
}
.sand-copy {
  position: absolute;
  left: var(--edge);
  right: var(--gut);
  bottom: calc(clamp(36px, 8vh, 96px) + env(safe-area-inset-bottom));
  max-width: 560px;
}
.sand-lede { margin-top: 14px; color: var(--ink); }
.atmos {
  margin-top: clamp(18px, 3vh, 30px);
  font-family: var(--serif);
  font-style: italic;
  font-weight: 340;
  font-size: clamp(24px, 1.1rem + 1.1vw, 34px);
  line-height: 1.3;
  color: var(--candle);
}
.atmos span { display: block; }

/* With JS the stage pins below the bar for a walk down the beach; the evening runs with the scroll. */
html.js .sand { height: 260vh; height: 260svh; }
html.js .sand-stage {
  position: sticky;
  top: calc(var(--bar-h) + env(safe-area-inset-top));
  height: calc(100vh - var(--bar-h) - env(safe-area-inset-top));
  height: calc(100svh - var(--bar-h) - env(safe-area-inset-top));
}
html.js .sand-moon { opacity: 0; }
/* Two composited layers, only while the scene is near the screen (app.js toggles is-live). */
html.js .sand.is-live .sand-pic { will-change: opacity; }
@media (prefers-reduced-motion: no-preference) {
  html.js .sand.is-live .sand-pic img { will-change: transform; }
}
@media (max-aspect-ratio: 4/5) {
  html.js .sand { height: 240vh; height: 240svh; }
}

/* ---------- Visit ---------- */

.visit {
  padding-block: clamp(64px, 9vw, 136px) clamp(64px, 7vw, 104px);
  background: var(--night);
}
.visit-lede { margin-top: 20px; }
.visit .actions { margin-top: 30px; }
.facts { margin-top: 52px; border-top: 1px solid var(--hair); }
.fact {
  display: grid;
  grid-template-columns: 7.2em minmax(0, 1fr);
  gap: 16px;
  padding: 16px 0;
  border-bottom: 1px solid var(--hair);
}
.fact dt {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 340;
  color: var(--candle-2);
}
.fact dd { color: var(--ink); overflow-wrap: break-word; }
/* Links padded out to a 44px+ target without moving the text; stacked links touch, never overlap,
   and the focus ring is pulled inside the padding so it clears the label above. */
.fact dd .lnk { display: block; width: fit-content; padding: 10px 8px; margin: -10px -8px; }
.fact dd .lnk + .lnk { margin-top: 10px; }
.fact dd .lnk:focus-visible { outline-offset: -5px; }
@media (max-width: 520px) {
  .fact { grid-template-columns: 1fr; gap: 4px; padding: 14px 0 16px; }
}

.awards { display: grid; gap: 14px; margin-top: 44px; }
.award {
  display: flex; flex-direction: column; justify-content: center;
  min-height: 44px; padding: 4px 0;
  width: fit-content;
}
.award-name {
  font-family: var(--serif);
  font-weight: 340;
  font-size: clamp(20px, 1.05rem + 0.35vw, 23px);
  line-height: 1.25;
  color: var(--candle);
}
.award-by {
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: 3px;
  font-size: 15px; letter-spacing: 0.02em; color: var(--ink-2);
}
.award-by svg {
  width: 11px; height: 11px;
  fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round;
  transition: transform 0.55s var(--ease-out);
}
@media (hover: hover) {
  .award:hover .award-by svg { transform: translate(2px, -2px); }
  .award:hover .award-by { color: var(--ink); }
}

@media (min-width: 900px) {
  .visit-grid {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    grid-template-rows: auto 1fr;
    column-gap: var(--col-gap);
  }
  .visit-main { grid-column: 1 / span 5; grid-row: 1; }
  .facts { grid-column: 7 / span 6; grid-row: 1 / span 2; margin-top: 8px; align-self: start; }
  .awards { grid-column: 1 / span 5; grid-row: 2; align-self: end; margin-top: 48px; }
}

/* ---------- Footer ---------- */

.foot {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  padding: 26px var(--edge) calc(30px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--hair);
  background: var(--night);
}
.foot-home { display: block; padding: 6px 0; }
.foot-home img { width: 104px; }
.foot-note { font-size: 15px; letter-spacing: 0.02em; color: var(--ink-2); }

/* ---------- Thai ---------- */

html[lang="th"] body { line-height: 1.8; }
html[lang="th"] h2 { line-height: 1.3; letter-spacing: 0; font-size: clamp(30px, 1.4rem + 2vw, 52px); }
html[lang="th"] h3 { line-height: 1.35; letter-spacing: 0; font-size: clamp(26px, 1.2rem + 1vw, 36px); }
html[lang="th"] .hero-line { line-height: 1.55; }
html[lang="th"] .atmos { line-height: 1.5; font-size: clamp(22px, 1rem + 1vw, 30px); }
html[lang="th"] figcaption, html[lang="th"] .fact dt { line-height: 1.6; }
html[lang="th"] .btn { letter-spacing: 0; }
html[lang="th"] .hero-line, html[lang="th"] .atmos, html[lang="th"] figcaption,
html[lang="th"] .fact dt, html[lang="th"] .num { font-style: normal; }
html.i18n-wait [data-i18n], html.i18n-wait [data-i18n-html] { visibility: hidden; }

/* =================================================================
   Motion. Everything above is the resting state, visible without JS.
   Initial "before" states only apply once html.js is set.
   ================================================================= */

/* Hero photo: blur-up, then a slow push-in. */
html.js .hero-pic img { opacity: 0; transition: opacity 0.8s var(--ease-out); }
html.js .hero-pic img.is-loaded { opacity: 1; }

@media (prefers-reduced-motion: no-preference) {
  html.js .hero-pic img { animation: kenburns 28s var(--ease-io) infinite alternate both; }
  html.js .hero-pic + .hero-pic img { animation-duration: 32s; animation-direction: alternate-reverse; }
  html.js .hero-pic + .hero-pic:not(.is-on) img,
  html.js .hero.is-off .hero-pic img,
  html.js .hero.is-off .logo-glow { animation-play-state: paused; }
}
@keyframes kenburns {
  from { transform: scale(1.02) translate3d(0, 0, 0); }
  to   { transform: scale(1.1) translate3d(-1.2%, -0.8%, 0); }
}

/* Logo: a dry-brush mask sweeps right while the image counter-moves, so the letters stay put. */
html.js .ll-m {
  -webkit-mask-image: url(img/brush.png);
  mask-image: url(img/brush.png);
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  transform: translate3d(-100%, 0, 0);
}
html.js .ll-m img { transform: translate3d(calc((1 + var(--f)) * 100%), 0, 0); }
html.js .hero.is-in .ll-m,
html.js .hero.is-in .ll-m img {
  transform: translate3d(0, 0, 0);
  transition: transform var(--dur) var(--ease-brush) var(--delay);
}
html.js .hero.is-done .ll-m { -webkit-mask-image: none; mask-image: none; }
html.js .logo-glow { opacity: 0; }
html.js .hero.is-in .logo-glow {
  opacity: 0.3;
  transition: opacity 1.6s var(--ease-io) 0.7s;
}
@media (prefers-reduced-motion: no-preference) {
  html.js .hero.is-done .logo-glow { animation: candle 8s ease-in-out infinite; }
}
@keyframes candle {
  0%, 100% { opacity: 0.3; }
  20% { opacity: 0.26; }
  38% { opacity: 0.34; }
  55% { opacity: 0.27; }
  74% { opacity: 0.35; }
}

/* Hero copy: after the name, in by ~1.6s. */
html.js [data-reveal="hero"] {
  opacity: 0;
  transform: translate3d(0, 14px, 0);
  filter: blur(4px);
}
html.js .hero.is-in [data-reveal="hero"] {
  opacity: 1; transform: none; filter: blur(0);
  transition: opacity 0.66s var(--ease-out) var(--d, 0ms), transform 0.8s var(--ease-out) var(--d, 0ms), filter 0.66s var(--ease-out) var(--d, 0ms);
}

/* Words light up one by one, like lamps along a path. */
.w { display: inline-block; }
html.js [data-split] .w {
  opacity: 0;
  transform: translate3d(0, 0.4em, 0);
  filter: blur(6px);
}
html.js [data-split].is-in .w {
  opacity: 1;
  transform: none;
  filter: blur(0);
  transition:
    opacity 0.95s var(--ease-out),
    transform 1.2s var(--ease-out),
    filter 1s var(--ease-out);
  transition-delay: calc(var(--d, 0ms) + var(--i, 0) * 50ms);
}

/* Blocks rise gently. */
html.js [data-reveal]:not(.frame):not([data-reveal="hero"]) {
  opacity: 0;
  transform: translate3d(0, 22px, 0);
}
html.js [data-reveal].is-in:not(.frame):not([data-reveal="hero"]) {
  opacity: 1;
  transform: none;
  transition: opacity 1s var(--ease-out) var(--d, 0ms), transform 1.2s var(--ease-out) var(--d, 0ms);
}

/* Photos unveil from below (or from the side) and their lamps come up. */
html.js .frame[data-reveal] { background: transparent; }
html.js .frame[data-reveal] > .px { clip-path: inset(100% 0 0 0); }
html.js .frame[data-reveal="side"] > .px { clip-path: inset(0 100% 0 0); }
html.js .frame[data-reveal] img { transform: scale(1.14); filter: brightness(0.45) saturate(0.75); }
html.js .frame[data-reveal].is-in > .px {
  clip-path: inset(0 0 0 0);
  transition: clip-path 1.15s var(--ease-io) var(--d, 0ms);
}
html.js .frame[data-reveal].is-in img {
  transform: none;
  filter: none;
  transition: transform 1.6s var(--ease-out) var(--d, 0ms), filter 1.4s var(--ease-out) var(--d, 0ms);
}
@media (hover: hover) {
  html.js .plate.is-in:hover img,
  html.js .seafood-img.is-in:hover img,
  .plate:hover img, .seafood-img:hover img {
    transform: scale(1.04);
    transition: transform 1.4s var(--ease-out) 0ms;
  }
}

/* Parallax layers are promoted only while near the screen (app.js toggles is-live). */
.px.is-live { will-change: transform; }

/* Atmosphere lines arrive one by one as the evening turns (driven by the scroll). */
html.js .atmos span {
  opacity: 0;
  transform: translate3d(0, 0.45em, 0);
  filter: blur(5px);
  transition: opacity 0.9s var(--ease-out), transform 1.1s var(--ease-out), filter 0.9s var(--ease-out);
}
html.js .atmos span.is-in { opacity: 1; transform: none; filter: blur(0); }

/* Reduced motion: nothing moves. The hero copy is simply there; elsewhere, crossfades only. */
@media (prefers-reduced-motion: reduce) {
  html.js .ll-m, html.js .ll-m img { transform: none !important; -webkit-mask-image: none; mask-image: none; }
  html.js .ll { opacity: 0; }
  html.js .hero.is-in .ll { opacity: 1; transition: opacity 0.6s var(--ease-io); }
  html.js [data-reveal="hero"] { opacity: 1 !important; transform: none !important; filter: none !important; transition: none !important; }
  html.js [data-split] .w,
  html.js [data-reveal]:not(.frame),
  html.js .atmos span { transform: none !important; filter: none !important; }
  html.js .frame[data-reveal] > .px { clip-path: none !important; }
  html.js .frame[data-reveal] { opacity: 0; }
  html.js .frame[data-reveal].is-in { opacity: 1; transition: opacity 1.1s var(--ease-io) var(--d, 0ms); }
  html.js .frame[data-reveal] img { transform: none !important; filter: none !important; }
  .btn, .award-by svg { transition: none; }
  .btn:hover, .plate:hover img, .seafood-img:hover img { transform: none !important; }
}
