/* Olio Homestay — site styles
   Tokens follow .claude/skills/editorial-motion-site (source rhythm) and brand/README.md (colours).
   One typeface, one weight. Hierarchy by size, case, letterspacing and colour only. */

:root {
  --paper: #FDFCFA;           /* page: warm white */
  --ink: #1E1C1A;
  --body: #3E3A36;
  --muted: #7A756D;
  --muted-on-ink: #8A847B;
  --rule: #E3DED6;
  --slot: #F5F2ED;           /* placeholder: a whisper off the paper, not a grey box */
  --slot-ink: #2A2724;
  --tint: #F0EBE3;            /* the brand's paper cream, used for the restaurant section */
  --slot-tint: #E7E1D8;      /* the same whisper on the cream sections */

  --frame: 40px;              /* all four edges */
  --title-to-eyebrow: 30px;
  --caption-to-image: 25px;
  --gutter: 50px;             /* between images */

  --font: "Cormorant Garamond", Georgia, "Times New Roman", serif;
}

@media (max-width: 900px) {
  :root { --frame: 20px; --gutter: 16px; --caption-to-image: 14px; --title-to-eyebrow: 22px; }
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; background: var(--paper); }
.fonts-loading body { visibility: hidden; }   /* removed by the head script once the font is ready */
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-weight: 400;
  font-size: 18px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
@media (max-width: 900px) { body { font-size: 17px; } }

a { color: inherit; text-decoration: none; }
a:hover { color: var(--muted); }
h1, h2, h3, p, figure { margin: 0; font-weight: 400; }
img, video { display: block; max-width: 100%; }

/* ---------- type ---------- */
.eyebrow {
  font-size: 12px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--muted);
}
.on-ink .eyebrow { color: var(--muted-on-ink); }
.title { font-size: clamp(46px, 5.3vw, 76px); line-height: 1.05; letter-spacing: -0.005em; }
.heading { font-size: clamp(36px, 3.9vw, 56px); line-height: 1.1; }
.subheading { font-size: clamp(22px, 1.8vw, 26px); line-height: 1.2; }
.lede { font-size: clamp(19px, 1.7vw, 24px); line-height: 1.6; max-width: 820px; }
.body { color: var(--body); font-size: 17px; line-height: 1.6; }
.price { font-size: 17px; }
@media (max-width: 900px) { .body { font-size: 16px; } }
.tagline { font-size: clamp(30px, 2.8vw, 40px); font-style: italic; line-height: 1.2; }

.link {
  font-size: 13px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--muted);
}
.link-primary { color: var(--ink); border-bottom: 1px solid var(--ink); padding-bottom: 3px; }
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  border: 1px solid var(--ink);
  padding: 12px 30px;
  font-size: 13px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ink);
  /* the same rule serves <a> and <button>: no browser fill, no system font, no radius */
  background: transparent;
  font-family: inherit;
  line-height: 1.2;
  border-radius: 0;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
.btn:hover { background: var(--ink); color: var(--paper); }
.btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

/* ---------- layout ---------- */
/* The frame is 40px at normal widths. On very wide screens the padding grows instead, so content
   is held to a centred 100rem column while section backgrounds still run edge to edge. */
.frame { padding-left: max(var(--frame), calc((100% - 100rem) / 2)); padding-right: max(var(--frame), calc((100% - 100rem) / 2)); }
/* On a tablet, once the two-column layouts have stacked, the reading sections hold their content to a centred
   640px column (the intro copy's measure) the same way, so a 4:3 photo or a table doesn't run the width of the
   page. The hero strip and the ink story keep the full width on purpose; a phone narrower than the column is unaffected. */
@media (max-width: 900px) {
  .rooms, .garden, .details, .restaurant, .closing {
    padding-left: max(var(--frame), calc((100% - 640px) / 2));
    padding-right: max(var(--frame), calc((100% - 640px) / 2));
  }
}
.section { padding-top: 140px; padding-bottom: 140px; }
@media (max-width: 900px) { .section { padding-top: 72px; padding-bottom: 72px; } }
.on-ink { background: var(--ink); color: var(--paper); }
.on-tint { background: var(--tint); }

.stack { display: flex; flex-direction: column; }
.row { display: flex; align-items: center; justify-content: space-between; gap: 24px; }
.two-col { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gutter); }
@media (max-width: 900px) { .two-col { grid-template-columns: 1fr; gap: 40px; } }

/* ---------- header ---------- */
.site-header { display: flex; align-items: center; justify-content: space-between; }
.wordmark { display: flex; align-items: center; gap: 14px; }
.wordmark img { width: 44px; height: 44px; }
.wordmark span { font-size: 15px; letter-spacing: 0.34em; text-transform: uppercase; white-space: nowrap; }
.site-nav { display: flex; align-items: center; gap: 40px; }
.site-nav .link { white-space: nowrap; }
@media (max-width: 900px) {
  .wordmark img { width: 36px; height: 36px; }
  .wordmark span { font-size: 12px; letter-spacing: 0.24em; }
  .site-nav { gap: 20px; }
  .site-nav .link { font-size: 11px; letter-spacing: 0.2em; }
  .site-nav .link:not(.link-primary) { display: none; }
}

/* ---------- hero ---------- */
.hero {
  min-height: 100vh;
  min-height: 100svh;
  padding-top: var(--frame);
  padding-bottom: var(--frame);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 40px;
}
.hero-heading { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--title-to-eyebrow); }

/* typewriter: the fixed part never moves; the animated phrase reserves the width of its longest variant */
.tw-anim { display: inline-block; text-align: left; white-space: nowrap; transition: min-width 0.45s ease; }
@media (max-width: 900px) { .tw-anim { display: inline; white-space: normal; min-width: 0 !important; } }
.tw-caret { display: none; margin-left: 0.04em; }
.title.is-typewriter .tw-caret { display: inline; animation: caret-blink 1s steps(1, end) infinite; }
.title.is-typewriter.is-typing .tw-caret { animation: none; opacity: 1; }
@keyframes caret-blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }

.gallery { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--gutter); }
.gallery-item { display: flex; flex-direction: column; gap: var(--caption-to-image); }
.gallery-item .num { position: relative; font-size: 12px; letter-spacing: 0.2em; color: var(--muted); }
.gallery-item .num::after {         /* progress line for the active clip (sequential autoplay); scales rather than resizes, so it never triggers layout */
  content: ""; position: absolute; left: 0; bottom: -8px; height: 1px; width: 100%;
  background: var(--ink); opacity: 0; transform: scaleX(0); transform-origin: 0 50%;
}
.gallery-item.is-active .num::after { opacity: 1; transform: scaleX(1); transition: transform var(--clip-duration, 4s) linear; }
.gallery-item.is-active.is-paused .num::after { transform: scaleX(var(--progress, 0)); transition: none; }   /* held while a hero item is hovered */
.gallery-item.is-active.is-manual .num::after { transform: scaleX(1); transition: none; }   /* the clip a phone visitor scrolled to; it loops */
.gallery .slot { aspect-ratio: 3 / 4; }
/* Hover zoom on the hero row: the whole item (number and picture) lifts on a white card with a white
   border, growing from its own bottom edge, centred, over its neighbours, without moving anything else.
   The scale (--hover-scale, set by motion.js) makes it at most twice its size and at most 460px tall,
   so it is a closer look on a narrow page and a modest lift on a wide one. */
@media (hover: hover) and (min-width: 901px) {
  /* Only transform and opacity animate, so the hover stays on the GPU: the item scales as its own layer
     (will-change), and the page-coloured card behind it is a pseudo-element that fades in. */
  .gallery-item { position: relative; isolation: isolate; transform-origin: 50% 100%; will-change: transform;
    transition: transform 0.55s cubic-bezier(0.2, 0.7, 0.2, 1); }
  .gallery-item::before { content: ""; position: absolute; inset: -6px; background: var(--paper); opacity: 0; z-index: -1;
    transition: opacity 0.35s ease; pointer-events: none; }
  .gallery-item:hover { transform: scale(var(--hover-scale, 1.25)); z-index: 3; }
  .gallery-item:hover::before { opacity: 1; }
  .gallery-item:first-child { transform-origin: 0 100%; }      /* the end items grow inward, so nothing leaves the screen */
  .gallery-item:last-child { transform-origin: 100% 100%; }
}
@media (max-width: 900px) {
  .gallery { display: flex; gap: var(--gutter); overflow-x: auto; scroll-snap-type: x mandatory; margin-right: calc(-1 * var(--frame)); padding-right: var(--frame); scrollbar-width: none; }
  .gallery::-webkit-scrollbar { display: none; }
  .gallery-item { flex: 0 0 210px; scroll-snap-align: start; }
}

/* ---------- image slots. The .slot-placeholder brief markup is only for a slot that has no visual yet; every slot in index.html has one now, so none is present there. ---------- */
.slot { position: relative; width: 100%; background: var(--slot); overflow: hidden; }
/* Entrance: a veil in the slot's own colour sits over the picture and fades off once the
   picture has decoded (motion.js adds .is-ready). The hero row lifts left to right. */
.slot::after { content: ""; position: absolute; inset: 0; background: inherit; z-index: 3; pointer-events: none; opacity: 1; transition: opacity 0.9s cubic-bezier(0.22, 0.61, 0.36, 1); }
.slot.is-ready::after { opacity: 0; }
.gallery-item:nth-child(2) .slot::after { transition-delay: 90ms; }
.gallery-item:nth-child(3) .slot::after { transition-delay: 180ms; }
.gallery-item:nth-child(4) .slot::after { transition-delay: 270ms; }
.gallery-item:nth-child(5) .slot::after { transition-delay: 360ms; }
.slot-ink { background: var(--slot-ink); }
.slot-tint { background: var(--slot-tint); }
.slot-4x3 { aspect-ratio: 4 / 3; }
.slot-3x4 { aspect-ratio: 3 / 4; }
.slot-16x9 { aspect-ratio: 16 / 9; }
.slot video, .slot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.slot video { display: none; }
.slot.has-media video { display: block; }
.slot.has-media .slot-placeholder { display: none; }
.slot .slot-poster { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 2; pointer-events: none; }   /* stays on top until the video has painted a frame */
.slot .slot-poster { transition: opacity 0.4s ease; }   /* the frames match; the fade hides any last hair of browser colour difference */
.slot.is-painted .slot-poster { opacity: 0; }
.slot-placeholder {
  position: absolute; inset: 0; padding: 16px;
  display: flex; flex-direction: column; justify-content: space-between;
}
.slot-id { font-size: 11px; letter-spacing: 0.28em; text-transform: uppercase; color: var(--muted); }
.slot-subject { font-size: 17px; line-height: 1.35; color: #5C5852; }
.slot-motion { font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); line-height: 1.5; }
.slot-ink .slot-subject { color: #B9B2A8; }
.slot-ink .slot-id, .slot-ink .slot-motion { color: var(--muted-on-ink); }
@media (max-width: 900px) { .slot-placeholder { padding: 12px; } .slot-subject { font-size: 15px; } }

/* Placeholder-only light sweep, scrubbed by scroll (stands in for the flat-lay video) */
.slot-sweep::before {
  content: ""; position: absolute; inset: -40%;
  background: radial-gradient(closest-side, rgba(255, 250, 240, 0.55), rgba(255, 250, 240, 0) 70%);
  transform: translate(calc(var(--sweep, 0) * -60%), -20%);
  pointer-events: none;
}
.slot.has-video.slot-sweep::before { display: none; }   /* keep the sweep over a still; drop it once the clip exists */
.slot.has-media.slot-sweep::before { mix-blend-mode: soft-light; opacity: 0.9; }

/* ---------- story ---------- */
.story { display: flex; flex-direction: column; gap: 32px; padding-top: 110px; padding-bottom: 110px; }
.story .eyebrow { margin-top: -8px; }
@media (max-width: 900px) { .story { gap: 24px; padding-top: 64px; padding-bottom: 64px; } }
.wipe .wipe-char { color: var(--muted-on-ink); transition: color 120ms linear; }
.wipe .wipe-char.is-on { color: var(--paper); }
.on-ink-body.wipe .wipe-char { color: #5F5A53; }            /* the smaller paragraph reveals to its own softer tone, not to white */
.on-ink-body.wipe .wipe-char.is-on { color: #B9B2A8; }
.wipe .wipe-word { white-space: nowrap; }

/* ---------- rooms ---------- */
.rooms { display: flex; flex-direction: column; gap: 80px; }
.rooms-heading { display: flex; flex-direction: column; gap: var(--title-to-eyebrow); }
.room { display: flex; flex-direction: column; gap: var(--caption-to-image); }
.room-text { display: flex; flex-direction: column; gap: 18px; padding-top: 10px; }
.room .row { align-items: baseline; flex-wrap: wrap; row-gap: 6px; }
/* The price takes its whole line, so the availability link sits under it at its own width, never squeezed beside it */
.room .row .price { flex-basis: 100%; }
.room .row .link { margin-top: 8px; }
/* Wander spans the width: picture on the left, text beside it; the three others sit in a row beneath */
/* The picture takes the larger column but is capped at 620px and centred in it, as the garden picture is in
   its half, so on a wide screen it sits in white space instead of running the width of the page; the text sits
   level with it. Below the cap the picture fills its column and the layout is the plain two-column one. */
.room-wide { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: var(--gutter); align-items: center; }
.room-wide .room-gallery { width: min(100%, 620px); margin: 0 auto; }
.room-wide .room-text { max-width: 560px; padding-top: 0; }
.three-col { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gutter); }
@media (max-width: 900px) {
  .rooms { gap: 40px; }
  .room-wide { grid-template-columns: 1fr; gap: var(--caption-to-image); }
  .room-wide .room-text { max-width: none; padding-top: 10px; }
  .three-col { grid-template-columns: 1fr; gap: 40px; }
}

/* ---------- room galleries ----------
   Main image with a column of thumbnails on its right. The current thumbnail carries the
   same thin progress line as the hero numbers; it stops once someone chooses a photo. */
.room-gallery { display: grid; grid-template-columns: minmax(0, 1fr) 72px; gap: 14px; align-items: stretch; }
.gallery-main { position: relative; height: 0; padding-bottom: 75%; overflow: hidden; background: var(--slot); }   /* 4:3 by padding, which every iOS honours */
.gallery-main .slot { position: absolute; inset: 0; opacity: 0; transition: opacity 0.9s ease; }
.gallery-main .slot.is-current { opacity: 1; z-index: 1; }
.gallery-main .slot:first-child:not(.is-current) ~ .slot.is-current, .gallery-main .slot.is-current { opacity: 1; }
.gallery-main .slot:first-child { opacity: 1; }   /* first photo shows even before scripts run; later photos fade over it */
.gallery-main .slot:first-child:not(.is-current) { opacity: 0; }
.gallery-thumbs { display: flex; flex-direction: column; gap: 10px; margin: 0; padding: 0; min-height: 0; }   /* the column shares the main image's height; thumbs split it equally */
.thumb { position: relative; display: block; width: 100%; flex: 1 1 0; min-height: 0; padding: 0; border: 0; background: var(--slot); cursor: pointer; opacity: 0.45; transition: opacity 0.4s ease; }
.thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.thumb:hover, .thumb:focus-visible { opacity: 0.8; outline: none; }
.thumb.is-current { opacity: 1; }
.thumb::after { content: ""; position: absolute; left: 0; bottom: -5px; height: 1px; width: 100%; background: var(--ink); opacity: 0; transform: scaleX(0); transform-origin: 0 50%; }
.thumb.is-current.is-timed::after { opacity: 1; transform: scaleX(1); transition: transform var(--interval, 4.5s) linear; }
.thumb.is-current.is-manual::after { opacity: 1; transform: scaleX(1); transition: none; }
@media (max-width: 900px) {
  .room-gallery { grid-template-columns: 1fr; gap: 12px; }
  .gallery-thumbs { flex-direction: row; flex-wrap: wrap; }   /* more than five wrap to a second row of the same size */
  /* Every thumbnail is sized as one of five across, so a room with two photos gets the same small
     squares as a room with five, rather than two big ones. */
  .thumb { flex: 0 0 auto; width: calc((100% - 40px) / 5); aspect-ratio: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .gallery-main .slot { transition: none; }
  .thumb.is-current.is-timed::after { transition: none; }
}

/* staggered fade-up */
.fade-up { opacity: 0; transform: translateY(24px); transition: opacity 0.8s ease-out, transform 0.8s ease-out; }
.fade-up.is-in { opacity: 1; transform: translateY(0); }

/* ---------- garden and restaurant (mirror-image two-column sections) ---------- */
.restaurant, .garden { align-items: center; }
/* The picture keeps its half of the section but is capped in size and centred in that space, so it doesn't balloon on wide screens. */
.garden .scrub-window, .restaurant .scrub-window { width: min(100%, 590px); margin: 0 auto; }
@media (max-width: 900px) {
  .garden .scrub-window { order: 2; }   /* text first on a phone, then the picture */
  .garden .scrub-window, .restaurant .scrub-window { width: 100%; }   /* the section column already sets the measure */
}
.restaurant-text { display: flex; flex-direction: column; gap: var(--title-to-eyebrow); max-width: 560px; }
.restaurant-links { display: flex; gap: 40px; flex-wrap: wrap; }
.scrub-window { position: relative; overflow: hidden; }   /* fixed at 65% of the media height, media translates inside */
.scrub-window .slot { will-change: transform; }

/* ---------- location · facilities · prices ---------- */
.details { display: flex; flex-direction: column; gap: 90px; }
.detail { display: flex; flex-direction: column; gap: 18px; align-items: flex-start; }
.detail .eyebrow { margin-bottom: 8px; }
.detail-row { display: grid; grid-template-columns: 1.15fr 1fr; gap: var(--gutter); }
.detail-prices { border-left: 1px solid var(--rule); padding-left: var(--gutter); }
/* The facilities column is shorter than the price table: its eyebrow stays level with "Prices", the icon grid centres in the space below */
.detail-row .facilities { margin-top: auto; margin-bottom: auto; }

.facilities { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 44px 24px; width: 100%; }
.facilities li { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 12px; font-size: 15px; line-height: 1.35; color: var(--body); }
.facilities svg { width: 28px; height: 28px; fill: none; stroke: var(--ink); stroke-width: 1.25; stroke-linecap: round; stroke-linejoin: round; }   /* Lucide icons, MIT, inlined */
.facilities span { opacity: var(--ink-text, 1); }

/* Ink draw: the section's rules are painted as backgrounds so their length can follow scroll (--draw), and text follows (--ink-text). */
.prices { border-collapse: collapse; width: 100%; font-size: 17px; color: var(--body); }
.prices th { font-size: 11px; letter-spacing: 0.26em; text-transform: uppercase; font-weight: 400; color: var(--muted); text-align: left; padding: 12px 14px; }
.prices thead tr { background: linear-gradient(var(--tint), var(--tint)) no-repeat left top / var(--draw, 100%) 100%; }
.prices td { padding: 12px 14px; vertical-align: baseline; background: linear-gradient(var(--rule), var(--rule)) no-repeat left bottom / var(--draw, 100%) 1px; }
.prices th:last-child, .prices td:last-child { text-align: right; white-space: nowrap; }
.prices td:last-child { color: var(--ink); }
.prices th, .prices td { color: inherit; }
.prices tr > * { opacity: var(--ink-text, 1); }
.prices th { color: var(--muted); }
.prices .muted { color: var(--muted); font-size: 15px; margin-left: 6px; }
.notes { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; font-size: 15px; line-height: 1.5; color: var(--body); opacity: var(--ink-text, 1); }
.notes li::before { content: "·"; color: var(--muted); margin-right: 10px; }
.detail-prices { background: linear-gradient(var(--rule), var(--rule)) no-repeat left top / 1px var(--draw, 100%); border-left: 0; }

.rooms-intro { max-width: 640px; }
.on-ink-body { color: #B9B2A8; max-width: 820px; }
@media (max-width: 900px) {
  .details { gap: 56px; }
  .detail-row { grid-template-columns: 1fr; gap: 56px; }
  .detail-prices { padding-left: 0; padding-top: 40px; background: linear-gradient(var(--rule), var(--rule)) no-repeat left top / var(--draw, 100%) 1px; }
  .facilities { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 28px 12px; }
}

/* ---------- closing ---------- */
.closing { padding-top: 140px; padding-bottom: 60px; display: flex; flex-direction: column; gap: 90px; }
@media (max-width: 900px) { .closing { padding-top: 72px; gap: 56px; } }
.scale-stage { display: flex; justify-content: center; }
.scale-stage .slot { will-change: clip-path; }   /* the reveal window is set by motion.js as a clip-path inset; the picture itself never scales */
/* Matches the photo's aspect so nothing is cropped at full size, and never taller than 90% of the visible screen (svh excludes mobile browser bars). */
.scale-stage .closing-slot { width: min(100%, 820px, calc(90vh * 3 / 4)); width: min(100%, 820px, calc(90svh * 3 / 4)); aspect-ratio: 3 / 4; }
.closing-cta { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 36px; }
.closing-note { font-size: 17px; color: var(--muted); }

.site-footer { display: flex; justify-content: space-between; align-items: flex-end; gap: 24px; border-top: 1px solid var(--rule); padding-top: 32px; }
.site-footer .contact { display: flex; flex-direction: column; gap: 10px; font-size: 15px; line-height: 1.5; color: var(--body); }
.site-footer .links { display: flex; gap: 36px; flex-wrap: wrap; }
.site-footer .links .link { font-size: 12px; letter-spacing: 0.28em; }
@media (max-width: 900px) { .site-footer { flex-direction: column; align-items: flex-start; } }

/* ---------- booking page ---------- */
.book { min-height: 100vh; min-height: 100svh; padding-top: var(--frame); padding-bottom: var(--frame); display: flex; flex-direction: column; justify-content: space-between; gap: 60px; }
.book-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 120px; align-items: start; }
@media (max-width: 900px) { .book-grid { grid-template-columns: 1fr; gap: 48px; } }
.book-intro { display: flex; flex-direction: column; gap: var(--title-to-eyebrow); max-width: 520px; }
.book-form { display: flex; flex-direction: column; gap: 34px; }
.field { display: flex; flex-direction: column; gap: 10px; }
.field label { font-size: 12px; letter-spacing: 0.28em; text-transform: uppercase; color: var(--muted); }
.field input, .field select, .field textarea {
  width: 100%; min-height: 48px; border: 0; border-bottom: 1px solid #A39D93; border-radius: 0;
  background: transparent; font: inherit; color: var(--ink); padding: 8px 0; outline: none;
}
.field textarea { min-height: 72px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus { border-bottom-color: var(--ink); }
.field ::placeholder { color: #A39D93; }
.book-actions { display: flex; align-items: center; gap: 30px; flex-wrap: wrap; padding-top: 6px; }
.book-footer { display: flex; justify-content: flex-end; font-size: 12px; letter-spacing: 0.28em; text-transform: uppercase; color: var(--muted); }

/* ---------- accessibility ---------- */
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .fade-up { opacity: 1; transform: none; transition: none; }
  .wipe .wipe-char { color: var(--paper); transition: none; }
  .gallery-item.is-active .num::after { transition: none; }
  .scrub-window .slot { transform: none !important; }
  .scale-stage .slot { clip-path: none !important; }
  .slot::after { transition: none; }
}

/* ---------- languages ----------
   Thai and Chinese pages are generated by scripts/i18n.py; see .claude/skills/localize.
   Cormorant has no Thai or Chinese glyphs, so each page adds a face after it: Latin (room
   names, numbers, "Olio Homestay") stays in Cormorant, the rest falls through.
   Chinese follows what premium Chinese brands do (The PuLi, Aranya, Fnji; researched
   2026-09-28): a light sans for the text, never a regular-weight Song serif, which reads
   heavy and official. Only the Light (300) weight is loaded, so that is what renders. The
   hero line alone is set in a kai, LXGW WenKai Light, loaded on the Chinese home page only. */
:root:lang(th) { --font: "Cormorant Garamond", "Noto Serif Thai", Georgia, serif; }
:root:lang(zh) { --font: "Cormorant Garamond", "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif; }
:root:lang(zh) .hero .title { font-family: "Cormorant Garamond", "LXGW WenKai", "Noto Sans SC", "PingFang SC", sans-serif; }
/* Wide tracking is a device for Latin capitals. On Thai it pulls vowels and tone marks away
   from their consonants, and Chinese has no capitals to space; both get a light touch. */
:root:lang(th) body *:not(.wordmark *) { letter-spacing: 0.02em; }
:root:lang(zh) body *:not(.wordmark *) { letter-spacing: 0.08em; }
:root:lang(zh) .title, :root:lang(zh) .heading, :root:lang(zh) .subheading, :root:lang(zh) .lede { letter-spacing: 0.02em; }
/* Thai stacks marks above and below the line; tight display leading clips them. */
:root:lang(th) .title { line-height: 1.35; }
:root:lang(th) .heading, :root:lang(th) .subheading { line-height: 1.35; }
:root:lang(th) .body, :root:lang(th) .lede { line-height: 1.75; }

.lang { position: relative; }
.lang summary {
  list-style: none; cursor: pointer; white-space: nowrap;
  font-size: 13px; letter-spacing: 0.26em; text-transform: uppercase; color: var(--muted);
}
.lang summary::-webkit-details-marker { display: none; }
.lang summary::after {
  content: ""; display: inline-block; width: 5px; height: 5px; margin-left: 8px;
  border-right: 1px solid currentColor; border-bottom: 1px solid currentColor;
  transform: translateY(-3px) rotate(45deg);
}
.lang summary:hover { color: var(--ink); }
.lang summary:focus-visible, .lang a:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.lang ul {
  position: absolute; right: -18px; top: calc(100% + 14px); z-index: 30;
  margin: 0; padding: 10px 0; list-style: none; min-width: 132px;
  background: var(--paper); box-shadow: 0 10px 30px rgba(30, 28, 26, 0.10);
}
.lang li a { display: block; padding: 7px 18px; font-size: 16px; letter-spacing: 0.04em; color: var(--ink); }
.lang li a[aria-current] { color: var(--muted); }
.lang li a:hover { color: var(--muted); }
@media (max-width: 900px) {
  .lang summary { font-size: 11px; letter-spacing: 0.2em; }
  .lang ul { right: -8px; }
}
/* The first-visit suggestion, in the visitor's own language, under the picker. */
.lang-nudge {
  position: absolute; right: -18px; top: calc(100% + 14px); z-index: 29; white-space: nowrap;
  padding: 10px 18px; background: var(--paper); box-shadow: 0 10px 30px rgba(30, 28, 26, 0.10);
  font-size: 16px; letter-spacing: 0.02em; color: var(--ink);
  opacity: 0; transform: translateY(-4px); transition: opacity 400ms ease, transform 400ms ease;
  pointer-events: none;
}
.lang-nudge.is-on { opacity: 1; transform: none; pointer-events: auto; }
.site-nav { position: relative; }
.lang[open] + .lang-nudge { display: none; }
@media (max-width: 900px) { .lang-nudge { right: -8px; font-size: 15px; } }
@media (prefers-reduced-motion: reduce) { .lang-nudge { transition: none; } }
