:root {
  --ink: #111827;
  --muted: #6B7280;
  --rule: #E8E6E2;
  --field: #DBD5C6;
  --sage: #2E6A5C;
  --sage-wash: #EFF2EE;
  --sand: #B9844F;
  --sand-wash: #FBF1E8;
  --sand-ink: #8A5A2E;
  --thai: "Anuphan", system-ui, sans-serif;
  --head: "Noto Sans Thai", system-ui, sans-serif;
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: #fff;
  color: var(--ink);
  font-family: var(--thai);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; height: auto; }
h1, h2, h3, p, ol, ul { margin: 0; }
ol, ul { padding: 0; list-style: none; }

.muted { color: var(--muted); font-size: 14px; line-height: 20px; }
.fine { color: var(--muted); font-size: 13px; line-height: 18px; text-align: center; }
.cap { display: block; color: var(--muted); font-size: 12px; line-height: 16px; }

/* Nav */
.nav {
  position: sticky; top: 0; z-index: 10;
  display: flex; align-items: center; justify-content: space-between;
  padding: 22px 64px;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--rule);
}
.brand { display: flex; align-items: center; gap: 10px; color: var(--ink); }
.brand span { font-family: "Source Serif 4", serif; font-size: 27px; line-height: 30px; letter-spacing: -0.005em; }
.brand-sm span { font-size: 22px; line-height: 26px; }
.nav-links { display: flex; gap: 36px; font-size: 15px; line-height: 22px; }
.nav-links a { position: relative; }
.nav-links a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -4px; height: 1px;
  background: var(--ink); transform: scaleX(0); transform-origin: left;
  transition: transform 200ms var(--ease-out);
}
.nav-end { display: flex; align-items: center; gap: 20px; }
.nav-end .muted { font-size: 15px; }

/* Buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  height: 54px; padding: 0 30px; border-radius: 8px;
  font-size: 16px; font-weight: 600; line-height: 22px;
  transition: transform 160ms var(--ease-out), background-color 160ms ease, border-color 160ms ease;
}
.btn:active { transform: scale(0.97); }
.btn-dark { background: #000; color: #fff; }
.btn-line { border: 1px solid var(--rule); font-weight: 500; }
.btn-sm { height: 40px; padding: 0 18px; font-size: 14px; line-height: 20px; }
.btn-block { width: 100%; height: 52px; }
.btn:focus-visible, .chip:focus-visible, .field:focus-within { outline: 2px solid var(--sage); outline-offset: 2px; }

/* Type */
h1 {
  font-family: var(--head); font-weight: 600;
  font-size: 56px; line-height: 78px; letter-spacing: -0.01em; text-align: center;
}
.h-lg { font-family: var(--head); font-weight: 600; font-size: 44px; line-height: 60px; text-align: center; }
.h-md { font-family: var(--head); font-weight: 600; font-size: 40px; line-height: 56px; }
.h-sm { font-family: var(--head); font-weight: 600; font-size: 28px; line-height: 40px; text-align: center; }
.body { color: var(--muted); font-size: 17px; line-height: 30px; }
.narrow { max-width: 560px; text-align: center; }
.label { font-size: 13px; font-weight: 500; letter-spacing: 0.1em; line-height: 16px; }
.sand-text { color: var(--sand); }
.sage-text { color: var(--sage); }

/* Hero */
.hero {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 22px;
  padding: 72px 24px 0;
}
.kicker { color: var(--muted); font-size: 13px; letter-spacing: 0.1em; line-height: 16px; }
.lede { max-width: 600px; color: var(--muted); font-size: 18px; line-height: 33px; text-align: center; }
.cta-row { display: flex; gap: 14px; padding-top: 10px; flex-wrap: wrap; justify-content: center; }
.facts { display: flex; align-items: center; gap: 14px; color: var(--muted); font-size: 14px; line-height: 20px; flex-wrap: wrap; justify-content: center; }
.facts li + li::before {
  content: ""; display: inline-block; width: 3px; height: 3px; margin-right: 14px;
  border-radius: 50%; background: #C9C6BF; vertical-align: middle;
}
.hero-stage { position: relative; width: 880px; max-width: 100%; }
.hero-art { width: 100%; height: 520px; object-fit: contain; }

/* Watercolour bloom: the cluster seeps outward from its base like pigment on wet paper. */
@property --bloom {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 180%;
}
.hero-art {
  -webkit-mask-image: radial-gradient(ellipse 60% 55% at 50% 72%, #000 var(--bloom), transparent calc(var(--bloom) + 30%));
          mask-image: radial-gradient(ellipse 60% 55% at 50% 72%, #000 var(--bloom), transparent calc(var(--bloom) + 30%));
  animation: bloom 1800ms cubic-bezier(0.33, 1, 0.68, 1) 300ms both;
}
@keyframes bloom {
  from { --bloom: -30%; filter: blur(6px); }
  60% { filter: blur(0); }
  to { --bloom: 180%; filter: blur(0); }
}

/* WebGL bloom (bloom.js) paints the hero while the water spreads, then hands back to the image. */
.gl-bloom .hero-art { animation: none; -webkit-mask-image: none; mask-image: none; opacity: 0; }
.gl-bloom .hero-stage.bloomed .hero-art { opacity: 1; }
.hero-bloom { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
/* Glint: a band of light that follows the cursor across the crystals, masked to the stones
   so it never touches the paper. app.js moves it; it is brightest at the cursor's height. */
.glint {
  position: absolute; inset: 0; overflow: hidden; pointer-events: none;
  -webkit-mask: url("assets/hero-mask.png") center / contain no-repeat;
          mask: url("assets/hero-mask.png") center / contain no-repeat;
}
.glint i {
  position: absolute; top: 0; left: 0; width: 24%; height: 100%;
  background: linear-gradient(105deg, transparent 30%, rgba(255, 255, 255, 0.25) 44%, rgba(255, 255, 255, 0.85) 50%, rgba(255, 255, 255, 0.25) 56%, transparent 70%);
  -webkit-mask-image: radial-gradient(ellipse 80% 45% at 50% var(--gy, 50%), #000 35%, transparent 100%);
          mask-image: radial-gradient(ellipse 80% 45% at 50% var(--gy, 50%), #000 35%, transparent 100%);
  opacity: 0;
  transition: opacity 450ms ease; /* leaving: the light fades slowly */
}
.glint.on i { opacity: 1; transition: opacity 200ms var(--ease-out); }

/* Hero entrance: pure CSS so it never waits on JS. Children cascade 60ms apart. */
.hero > .rise {
  animation: rise 560ms var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * 60ms);
}
@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
}

/* Floating stones: `scale` pops them in, `transform` bobs, and drag owns `translate` + `rotate`.
   Separate transform properties compose, so none of the three fight each other.
   Pop fills backwards only, which hands `scale` back to the grab state once it finishes. */
.float {
  position: absolute; z-index: 2; object-fit: contain;
  cursor: grab; touch-action: none; user-select: none; -webkit-user-drag: none;
  animation:
    pop 640ms var(--ease-out) backwards,
    bob 7s ease-in-out infinite;
  animation-delay: calc(240ms + var(--i, 0) * 80ms), calc(var(--b, 0) * -1s);
  transition: scale 200ms var(--ease-out), filter 200ms ease;
}
.float.paused { animation-play-state: running, paused; }
/* Held: bob stops so the stone sits still under the pointer, and it lifts off the page. */
.float.held {
  cursor: grabbing; z-index: 5;
  scale: 1.08;
  filter: drop-shadow(0 12px 14px rgba(17, 24, 39, 0.18));
  animation-play-state: paused;
}
.f-rose { width: 92px; left: calc(50% - 470px); top: 130px; --i: 0; --b: 0; }
.f-jade { width: 54px; left: calc(50% - 390px); top: 250px; --i: 1; --b: 2; animation-duration: 640ms, 8s; }
.f-amethyst { width: 96px; left: calc(50% + 390px); top: 170px; --i: 2; --b: 4; }
.f-jade2 { width: 64px; left: calc(50% - 420px); top: 60px; --b: 1; }
.f-rose2 { width: 80px; left: calc(50% + 340px); top: 110px; --b: 3; animation-duration: 640ms, 8.5s; }
/* The LINE-section stones sit far below the fold; their pop is replaced by the reveal. */
.line .float { animation: bob 7s ease-in-out infinite; animation-delay: calc(var(--b, 0) * -1s); }
.line .float.paused { animation-play-state: paused; }
@keyframes pop {
  from { opacity: 0; scale: 0.92; }
}
@keyframes bob {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50% { transform: translateY(-10px) rotate(4deg); }
}

/* Sections */
.honest, .steps, .intent, .line {
  display: flex; flex-direction: column; align-items: center; gap: 18px; padding-inline: 24px;
}
.honest { padding-top: 40px; padding-bottom: 120px; }
.honest .body { max-width: 780px; text-align: center; }
.steps { padding-top: 40px; padding-bottom: 140px; }

.step-grid { display: grid; grid-template-columns: repeat(3, 384px); gap: 24px; padding-top: 34px; }
.card {
  display: flex; flex-direction: column; gap: 12px;
  padding: 30px 32px 34px; border: 1px solid var(--rule); border-radius: 14px;
  transition: border-color 200ms ease;
}
.icon { display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: 50%; }
.icon.sage { background: var(--sage-wash); }
.icon.sand { background: var(--sand-wash); }
.step-no { padding-top: 8px; color: var(--muted); font-size: 13px; line-height: 18px; }
.card h3 { font-family: var(--head); font-weight: 600; font-size: 20px; line-height: 30px; }
.card p { color: var(--muted); font-size: 15px; line-height: 26px; }

/* Birthday */
.birthday {
  display: flex; align-items: center; justify-content: center; gap: 96px;
  padding: 40px 24px 160px;
}
.sphere { position: relative; width: 480px; height: 480px; flex-shrink: 0; }
.sphere img, .sphere canvas { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
/* The WebGL layer sits over the still painting and only fades in once it has drawn a frame. */
.sphere canvas { opacity: 0; transition: opacity 400ms ease; }
.sphere.live canvas { opacity: 1; }
.bd-copy { display: flex; flex-direction: column; gap: 16px; width: 520px; flex-shrink: 0; }
.field-label { padding-top: 12px; margin-bottom: -6px; font-size: 15px; font-weight: 500; line-height: 22px; }
.field {
  position: relative;
  display: flex; align-items: center; gap: 12px;
  height: 54px; padding: 0 18px;
  border: 1px solid var(--field); border-radius: 10px; background: #fff;
  font-size: 17px; line-height: 24px; cursor: pointer;
  transition: border-color 160ms ease;
}
.field input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; border: 0;
}
.readout { display: flex; border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); }
.cell {
  flex: 1 1 0; display: flex; align-items: center; justify-content: center; gap: 12px;
  padding-block: 18px;
}
.cell + .cell { border-left: 1px solid var(--rule); }
.cell strong { display: block; font-size: 16px; font-weight: 500; line-height: 24px; }
.swatch { width: 18px; height: 18px; border-radius: 50%; background: #E8A1B8; flex-shrink: 0; transition: background-color 300ms ease; }
.stones { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.pill {
  display: inline-block;
  padding: 8px 16px; border-radius: 999px; background: var(--sand-wash);
  color: var(--sand-ink); font-size: 14px; font-weight: 500; line-height: 20px;
}

/* Value swap: dip instantly, then settle back in. Transitions retarget if the user changes again mid-way. */
.swap {
  transition: opacity 220ms var(--ease-out), filter 220ms var(--ease-out), transform 220ms var(--ease-out);
}
.swap.is-swapping {
  opacity: 0; filter: blur(2px); transform: translateY(3px);
  transition: none;
}

/* Intent */
.intent { padding-top: 20px; }
.chips { display: flex; gap: 12px; padding-top: 24px; flex-wrap: wrap; justify-content: center; }
.chip {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 13px 22px; border: 1px solid var(--rule); border-radius: 999px;
  background: #fff; color: var(--ink);
  font: 15px/20px var(--thai); cursor: pointer;
  transition: border-color 160ms ease, background-color 160ms ease, transform 160ms var(--ease-out);
}
.chip i { width: 10px; height: 10px; border-radius: 50%; background: var(--c); flex-shrink: 0; transition: transform 200ms var(--ease-out); }
.chip:active { transform: scale(0.97); }
.chip[aria-pressed="true"] { border-color: var(--ink); background: #F7F6F3; }
.chip[aria-pressed="true"] i { transform: scale(1.3); }
.pick-note { min-height: 20px; text-align: center; }

/* Stone row: five clipped copies of one image, one stone each, so a chip can lift its stone. */
.row-art {
  position: relative;
  width: min(548px, 100%);
  aspect-ratio: 1376 / 768;
}
/* Nothing moves: the whole row dims, and a feathered copy of each picked stone sits on top at full strength.
   Soft mask edges keep the shared watercolour wash from showing a hard seam between stones. */
.row-art img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  transition: opacity 260ms var(--ease-out);
}
.row-art img[data-key] {
  opacity: 0;
  -webkit-mask-image: linear-gradient(to right, transparent calc(var(--l) - 3%), #000 calc(var(--l) + 1%), #000 calc(var(--r) - 1%), transparent calc(var(--r) + 3%));
          mask-image: linear-gradient(to right, transparent calc(var(--l) - 3%), #000 calc(var(--l) + 1%), #000 calc(var(--r) - 1%), transparent calc(var(--r) + 3%));
}
.row-art img[data-key="love"] { --l: 0%; --r: 26.9%; }
.row-art img[data-key="work"] { --l: 26.9%; --r: 43.3%; }
.row-art img[data-key="money"] { --l: 43.3%; --r: 58.5%; }
.row-art img[data-key="protect"] { --l: 58.5%; --r: 74.7%; }
.row-art img[data-key="calm"] { --l: 74.7%; --r: 100%; }
.row-art.has-pick .row-base { opacity: 0.3; }
.row-art img.on { opacity: 1; }

/* Custom offer */
.custom { display: flex; align-items: center; justify-content: center; gap: 120px; padding: 100px 24px 140px; }
.custom-copy { display: flex; flex-direction: column; gap: 16px; width: 520px; flex-shrink: 0; }
.offer {
  display: flex; flex-direction: column; gap: 22px; width: 400px; flex-shrink: 0;
  padding: 34px 34px 30px; border: 1px solid var(--rule); border-radius: 18px;
}
.offer h3 { margin-bottom: 6px; font-family: var(--head); font-weight: 600; font-size: 22px; line-height: 32px; }
.checks { display: flex; flex-direction: column; gap: 14px; font-size: 15px; line-height: 22px; }
.checks li { display: flex; align-items: center; gap: 12px; }
.checks li::before {
  content: ""; width: 18px; height: 18px; flex-shrink: 0;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 18'%3E%3Cpath d='M4 9.5l3 3 7-7' fill='none' stroke='%232E6A5C' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* LINE */
.line { position: relative; padding-top: 140px; padding-bottom: 40px; }

/* Footer */
.foot { display: flex; flex-direction: column; gap: 28px; margin-top: 40px; padding: 56px 64px 40px; border-top: 1px solid var(--rule); }
.foot-top { display: flex; justify-content: space-between; gap: 40px; }
.foot-brand { display: flex; flex-direction: column; gap: 10px; width: 320px; }
.foot-cols { display: flex; gap: 64px; }
.foot-cols div { display: flex; flex-direction: column; gap: 10px; width: 160px; font-size: 14px; line-height: 20px; }
.foot-cols .cap { font-size: 13px; line-height: 18px; }
.foot-legal { padding-top: 22px; border-top: 1px solid var(--rule); color: var(--muted); font-size: 13px; line-height: 18px; }

/* Hover only where a real pointer exists; on touch, a tap would leave it stuck. */
@media (hover: hover) and (pointer: fine) {
  .nav-links a:hover::after { transform: scaleX(1); }
  .btn-dark:hover { background: #1f2329; }
  .btn-line:hover { border-color: #c9c6bf; }
  .card:hover { border-color: #d4d0c8; }
  .field:hover { border-color: #c4bca8; }
  .chip:hover { border-color: #c9c6bf; }
  .foot-cols a:hover { text-decoration: underline; text-underline-offset: 3px; }
  .float:hover:not(.held) { scale: 1.04; }
}

/* Scroll reveal. Content stays visible without JS; only below-the-fold blocks start hidden. */
.js .reveal { transition: opacity 520ms var(--ease-out), transform 520ms var(--ease-out); }
.js .reveal:not(.in) { opacity: 0; transform: translateY(10px); }

/* Responsive */
@media (max-width: 1280px) {
  .step-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); max-width: 1200px; width: 100%; }
  .birthday, .custom { gap: 56px; }
  .sphere { width: 400px; height: 400px; }
}
@media (max-width: 960px) {
  .nav { padding: 16px 20px; }
  .nav-links, .nav-end .muted { display: none; }
  h1 { font-size: 40px; line-height: 58px; }
  .h-lg { font-size: 32px; line-height: 46px; }
  .h-md { font-size: 30px; line-height: 44px; }
  .h-sm { font-size: 22px; line-height: 34px; }
  .lede { font-size: 16px; line-height: 29px; }
  .body { font-size: 16px; line-height: 28px; }
  .hero { padding-top: 76px; }
  .hero-art { height: auto; }
  .f-rose { width: 48px; left: 5%; top: 14px; }
  .f-jade { display: none; }
  .f-amethyst { width: 50px; left: auto; right: 5%; top: 10px; }
  .f-jade2 { width: 40px; left: 6%; top: 36px; }
  .f-rose2 { width: 48px; left: auto; right: 6%; top: 30px; }
  .step-grid { grid-template-columns: 1fr; max-width: 440px; }
  .birthday, .custom { flex-direction: column; gap: 32px; padding-bottom: 96px; }
  .sphere { width: 260px; height: 260px; }
  .bd-copy, .custom-copy { width: 100%; max-width: 440px; }
  .offer { width: 100%; max-width: 440px; padding: 28px 24px 24px; }
  .custom { padding-top: 72px; }
  .cell { flex-direction: column; gap: 6px; text-align: center; padding-block: 14px; }
  .line { padding-top: 96px; }
  .foot { padding: 40px 20px 32px; }
  .foot-top { flex-direction: column; }
  .foot-cols { flex-wrap: wrap; gap: 28px; }
  .foot-cols div { width: 140px; }
}
@media (max-width: 480px) {
  .cta-row { width: 100%; flex-direction: column; }
  .cta-row .btn { width: 100%; }
  .facts { flex-direction: column; gap: 4px; }
  .facts li + li::before { display: none; }
}

/* Reduced motion: keep fades that explain change, drop everything that moves. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .hero > .rise { animation-name: fade; }
  .hero-art { animation: fade 600ms ease both; -webkit-mask-image: none; mask-image: none; }
  .glint { display: none; }
  .float, .line .float { animation: fade 400ms ease both; }
  @keyframes fade { from { opacity: 0; } }
  .js .reveal:not(.in) { transform: none; }
  .swap.is-swapping { filter: none; transform: none; }
  .btn:active, .chip:active { transform: none; }
}
