/* Kaif, preview D: premium beach café. Sand to sea, calm and slow. */

/* Latin subsets (Latin-1 plus curly quotes, en dash, ellipsis). Playfair is a static 400 cut of the variable font. */
@font-face { font-family: "Playfair Display"; src: url("fonts/playfair-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Prompt"; src: url("fonts/prompt-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Prompt"; src: url("fonts/prompt-500.woff2") format("woff2"); font-weight: 500; font-display: swap; }
/* The baht sign for the menu prices (0.6 KB): the Latin subsets above have none. Its own name keeps it to the menu. */
@font-face { font-family: "Prompt Baht"; src: url("fonts/prompt-baht-400.woff2") format("woff2"); font-weight: 400; font-display: swap; unicode-range: U+0E3F; }

:root {
  /* Sand: the brand cream, and the warmer sand sampled from the beach photos */
  --sand: #F4EDE1;
  --sand-warm: #EFE3CE;
  --shell: #FBF7EF;
  /* Water: the printed menus' mint tints, then the bench upholstery, softened */
  --foam: #EAF1EB;
  --mint: #BBDAD4;
  --seafoam: #C8E0DA;
  --sea: #AED4D6;
  /* Teal leads the accents: the tufted benches, from their highlights down to their shadows */
  --teal: #1F6B6B;
  --teal-deep: #174F50;
  --teal-night: #1D4A4B;
  /* Ink: wrought-iron black with the teal still in it (the select chevron repeats it as %231B2E30) */
  --ink: #1B2E30;
  --muted: #3B5557;
  --kicker: var(--teal);
  --line: #5F8787;
  --earth: #8A4A22; /* rattan and wood brown, used for form errors */
  --shade: 14 38 40; /* the deep teal shade laid over photos where text sits: rgb(var(--shade) / a) */
  --focus: var(--ink);

  /* Spacing scale */
  --s0: .35rem; /* label, hint and error gaps */
  --s1: .5rem;
  --s2: 1rem;
  --s3: 1.5rem;
  --s4: 2.25rem;
  --s5: clamp(2.25rem, 4.4vw, 4rem);
  --section: clamp(3.25rem, 6.2vw, 5.75rem);
  --section-end: clamp(2.25rem, 4vw, 3.5rem); /* a section breathes in at the top and arrives at the bottom */
  --gutter: clamp(1.25rem, 4.4vw, 4rem); /* same curve as --s5 on purpose, with a smaller floor */
  --wrap: 1280px;
  --edge: max(var(--gutter), (100% - var(--wrap)) / 2); /* the one pair of outer margins */
  --shore: clamp(20px, 2.6vw, 38px);
  --pad-card: clamp(1.5rem, 3.2vw, 2.75rem);
  --header-h: 5rem; /* room kept clear under the fixed header for anchors and focus */
  --tap: 44px;

  /* Type steps */
  --t-kicker: .8125rem;
  --t-small: .875rem;
  --t-body: 1rem;
  --t-lead: 1.125rem;
  --t-dish: clamp(1.25rem, 1.6vw, 1.5rem); /* stays a clear step under h3 on phones */
  --t-h3: clamp(1.6rem, 2.3vw, 2rem);
  --t-h2: clamp(2rem, 3.5vw, 3rem);
  --t-h1: clamp(2.9rem, 6.2vw, 5.6rem);
  --t-h1-portrait: clamp(2.3rem, 11.6vw, 4.2rem);
  --measure: 34em;

  /* Radii */
  --radius-focus: 4px;
  --radius-field: 12px;
  --radius-photo: 22px;
  --radius-card: 28px;
  --radius-pill: 999px;

  /* Motion: one calm curve, five durations. Answers are quick, arrivals are slow. */
  --calm: cubic-bezier(.22, 1, .36, 1);
  --dur-tap: .35s;     /* hover, press, focus, tab selection */
  --dur-state: .6s;    /* header bar, logo swap, a new menu tab */
  --dur-reveal: .9s;   /* text and photos arriving as you scroll */
  --dur-welcome: 1.5s; /* the hero welcome */
  --dur-draw: 1.4s;    /* the wave line under the booking thank-you */

  --serif: "Playfair Display", Georgia, "Times New Roman", serif;
  --sans: "Prompt", "Helvetica Neue", Arial, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: var(--header-h); -webkit-text-size-adjust: 100%; }
body { margin: 0; font: 400 var(--t-body)/1.7 var(--sans); color: var(--ink); background: var(--sand); -webkit-font-smoothing: antialiased; }
img { max-width: 100%; height: auto; display: block; }
h1, h2, h3, h4, p, dl, dd, ul, figure { margin: 0; }
ul { padding: 0; list-style: none; }
a { color: inherit; }
[hidden] { display: none !important; }
::selection { background: var(--mint); color: var(--ink); }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; border-radius: var(--radius-focus); }
.defs { position: absolute; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.skip { position: absolute; left: var(--s2); top: -4rem; z-index: 100; padding: var(--s1) var(--s2); border-radius: var(--radius-pill); background: var(--ink); color: var(--shell); }
.skip:focus { top: var(--s2); }

.wrap { width: min(100% - 2 * var(--gutter), var(--wrap)); margin-inline: auto; }

h1, h2, h3 { font-family: var(--serif); font-weight: 400; letter-spacing: -.01em; text-wrap: balance; }
h2 { font-size: var(--t-h2); line-height: 1.12; }
h3 { font-size: var(--t-h3); line-height: 1.2; }
.kicker { font: 500 var(--t-kicker)/1.4 var(--sans); letter-spacing: .16em; text-transform: uppercase; color: var(--kicker); }
.lead { font-size: var(--t-lead); }
p { text-wrap: pretty; }

.btn { display: inline-block; padding: .8em 1.6em; border: 1px solid transparent; border-radius: var(--radius-pill); background: var(--teal); color: var(--shell); font: 500 var(--t-body)/1.4 var(--sans); text-decoration: none; cursor: pointer; transition: background-color var(--dur-tap) var(--calm), color var(--dur-tap) var(--calm), transform var(--dur-tap) var(--calm); }
.btn:hover { background: var(--teal-deep); }
.btn:active { transform: scale(.98); }
.btn[disabled] { opacity: .6; cursor: default; }
.btn-cream { background: var(--shell); color: var(--ink); }
.btn-cream:hover { background: var(--mint); }
.btn-ghost { background: none; border-color: currentColor; color: inherit; }
.btn-ghost:hover { background: color-mix(in srgb, var(--shell) 16%, transparent); }
.btn-sm { padding: .4em 1.15em; }
.text-link { padding: 0; border: 0; background: none; font: inherit; color: inherit; cursor: pointer; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .35em; transition: text-decoration-color var(--dur-tap) var(--calm); }
.text-link:hover { text-decoration-color: transparent; }

/* Tones: the page walks from sand into the water */
.tone-sand { --bg: var(--sand); }
.tone-foam { --bg: var(--foam); }
.tone-seafoam { --bg: var(--seafoam); --kicker: var(--teal-deep); }
.tone-sea { --bg: var(--sea); --kicker: var(--teal-deep); }
.tone-night { --bg: var(--teal-night); --focus: var(--shell); }
main > section, .site-footer { position: relative; background-color: var(--bg); overflow-x: clip; }
.intro, .menu, .roast, .visit { padding-block: var(--section) var(--section-end); }
.menu { padding-top: clamp(2.75rem, 5vw, 4.5rem); }
/* Fine grain so the cream reads as sand, not paper. Dry sand and wet sand only.
   The grain is neutral grey laid over the tone, so it adds light and dark specks without shifting the colour. */
.tone-sand, .tone-foam { background-image: url("img/grain.svg"); background-size: 220px; background-blend-mode: overlay; }

/* Shore: a slow, shallow wave edge where one tone meets the next */
.shore { position: absolute; left: 0; right: 0; bottom: calc(100% - 1px); z-index: 3; height: var(--shore); overflow: hidden; color: var(--bg); pointer-events: none; }
.shore svg { position: absolute; left: 0; top: 0; width: 200%; height: 100%; fill: currentColor; }
.shore-back { opacity: .5; animation: drift 52s linear infinite; }
.shore-front { animation: drift 34s linear infinite; }
.shore .crest { fill: none; stroke: var(--shell); stroke-width: 1.5; stroke-opacity: .75; vector-effect: non-scaling-stroke; }
.shore-flip { top: -1px; bottom: auto; transform: scaleY(-1); color: var(--foam); }
.js .shore:not(.is-in) svg { animation-play-state: paused; }
@keyframes drift { to { transform: translateX(-50%); } }

/* Header: a plain clear bar over the hero photo, a soft cream bar once the page moves.
   The padding never changes; only colour moves, so nothing relays out. */
.site-header { --focus: currentColor; position: absolute; inset: 0 0 auto; z-index: 50; display: flex; align-items: center; justify-content: space-between; gap: var(--s2); padding: .75rem var(--edge); color: var(--shell); transition: background-color var(--dur-state) var(--calm), color var(--dur-state) var(--calm); }
.js .site-header { position: fixed; }
.brand { position: relative; display: block; height: 46px; aspect-ratio: 148 / 92; }
.brand img { position: absolute; inset: 0; width: 100%; height: 100%; transition: opacity var(--dur-state) var(--calm); }
.brand-dark { opacity: 0; }
.site-header ul { display: flex; align-items: center; gap: clamp(.9rem, 2.4vw, 2.25rem); }
.site-header a { text-decoration: none; }
.site-header nav a:not(.btn) { display: block; padding: .4em 0; white-space: nowrap; }
.site-header.is-scrolled { background: var(--sand); color: var(--ink); }
.is-scrolled .brand-light { opacity: 0; }
.is-scrolled .brand-dark { opacity: 1; }
.site-header.is-scrolled .nav-book { background: var(--teal); color: var(--shell); }
.site-header.is-scrolled .nav-book:hover { background: var(--teal-deep); }

/* Hero: the palm photo, "Welcome to Kaïf" centred over it, and the information small in the bottom-left corner.
   The rules are scoped by data-hero="2" on <html>, as they were built in the preview. */
.hero { --focus: var(--shell); color: var(--shell); background: var(--teal-night); }
.hero-stage { position: relative; container-type: inline-size; height: 100vh; height: 100svh; min-height: 36rem; display: flex; align-items: flex-end; overflow: hidden; overflow: clip; }
.hero-media, .hero-cut { position: absolute; inset: 0; will-change: transform; }
.hero-media picture, .hero-media img, .hero-media video, .hero-cut picture, .hero-cut img { display: block; width: 100%; height: 100%; }
.hero-media img, .hero-media video, .hero-cut img { object-fit: cover; object-position: 50% 100%; color: transparent; }
/* The drift as the hero scrolls away. Where the browser can tie an animation to the scroll position it runs on the
   compositor, exactly in step with the page; elsewhere main.js moves it. A length, not a percentage, so it stays there. */
@supports (animation-timeline: view()) {
  :is([data-hero="2"], [data-hero="3"]) :is(.hero-media, .hero-cut) { animation: hero-drift linear both; animation-timeline: view(0px); animation-range: exit 0% exit 100%; } /* 0px: measured from the real top edge, not the 5rem kept clear for anchors */
}
@keyframes hero-drift { to { transform: translate3d(0, max(28svh, 10.08rem), 0); } }
/* The teal shade: under the header, and under the small copy. Never under the big word. */
.hero-stage { --shade-foot: radial-gradient(ellipse 40rem 50% at 0 100%, rgb(var(--shade) / .88), rgb(var(--shade) / .7) 40%, rgb(var(--shade) / 0)); }
.hero-stage::before { content: ""; position: absolute; inset: 0; z-index: 3; background: linear-gradient(rgb(var(--shade) / .72), rgb(var(--shade) / .52) min(3.5rem, 12%), rgb(var(--shade) / .18) min(5.5rem, 19%), rgb(var(--shade) / 0) min(7.5rem, 26%)), var(--shade-foot); pointer-events: none; }
.hero-copy { position: relative; z-index: 5; margin: 0 var(--edge); padding-bottom: calc(var(--shore) + var(--s4)); max-width: 40rem; }
.hero-copy > *, .hero-word { animation: arrive var(--dur-welcome) var(--calm) both; }
.hero-copy > :nth-child(2) { animation-delay: .1s; }
.hero-copy > :nth-child(4) { animation-delay: .2s; }
.hero-copy > :nth-child(5) { animation-delay: .3s; }
@keyframes arrive { from { opacity: 0; transform: translateY(14px); } }
.hero .kicker { color: inherit; }
/* The h1 is read out; the lockup below is what is seen. */
.hero h1 { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.hero-meta { margin-top: var(--s2); font-size: var(--t-lead); }
.hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); margin-top: var(--s3); }

/* The display lockup: a quiet "Welcome to" and the name set as large as the screen allows. */
@font-face { font-family: "Kaif Display"; src: url("fonts/playfair-900i-kaif.woff2") format("woff2"); font-weight: 900; font-style: italic; font-display: block; }
.hero-word { position: absolute; z-index: 1; font-family: var(--serif); pointer-events: none; user-select: none; }
.w-a { display: block; font-size: clamp(1.7rem, 3.4vw, 3.25rem); line-height: 1.1; letter-spacing: -.01em; }
.w-b { display: block; font-family: "Kaif Display", var(--serif); font-weight: 900; }

/* Weather: one quiet line of what the bay is doing. Its room is always kept, so nothing jumps when it arrives or stays away. */
.weather { display: grid; grid-template-columns: auto auto minmax(0, 1fr); align-items: center; gap: .65rem; width: fit-content; max-width: 100%; min-height: 3.5rem; margin-bottom: var(--s3); padding: .45rem 1.1rem .45rem .7rem; border-radius: var(--radius-card); background: rgb(var(--shade) / .72); font-size: var(--t-small); line-height: 1.4; text-align: left; visibility: hidden; opacity: 0; transition: opacity var(--dur-reveal) var(--calm); }
.weather.is-on { visibility: visible; opacity: 1; }
/* The glyph is two or three stacked drawings. Only whole drawings move, so the compositor animates them and the page does not repaint. */
.wx-glyph { position: relative; display: block; width: 2.1rem; height: 2.1rem; }
.wx-glyph svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.wx-temp { font-size: 1.25rem; font-weight: 500; line-height: 1; }
.wx-text { text-wrap: balance; }
.wx-fill { fill: currentColor; fill-opacity: .22; }
.wx-glow { animation: wx-glow 5s ease-in-out infinite; }
.wx-drift { animation: wx-drift 9s ease-in-out infinite; }
.wx-fall { animation: wx-fall 2.6s linear infinite; }
.wx-flash { animation: wx-flash 6s linear infinite; }
.wx-sink { animation: wx-sink 7s ease-in-out infinite alternate; }
.wx-glyph svg + svg + svg { animation-delay: -1.3s; }
.js .hero:not(.is-in) .wx-glyph svg { animation-play-state: paused; }
@keyframes wx-glow { 50% { opacity: .45; } }
@keyframes wx-drift { 50% { transform: translateX(1.5px); } }
@keyframes wx-fall { from { opacity: 0; transform: translateY(-3px); } 25%, 60% { opacity: 1; } to { opacity: 0; transform: translateY(4px); } }
@keyframes wx-flash { 0%, 84%, 100% { opacity: .4; } 88%, 93% { opacity: 1; } 90% { opacity: .5; } }
@keyframes wx-sink { to { transform: translateY(2.5px); } }

/* Heroes 2 and 3: the name stands in the middle of the screen, and the information keeps to the bottom-left corner, small. */
:is([data-hero="2"], [data-hero="3"]) .hero-word { inset: 0; display: grid; place-content: center; justify-items: center; text-align: center; }
:is([data-hero="2"], [data-hero="3"]) .hero-copy { max-width: 26rem; margin: 0 var(--gutter); padding-bottom: calc(var(--shore) + var(--s2)); }
:is([data-hero="2"], [data-hero="3"]) .weather { gap: .45rem; min-height: 2.75rem; margin-bottom: .7rem; padding: .25rem .85rem .25rem .5rem; font-size: var(--t-kicker); line-height: 1.35; }
:is([data-hero="2"], [data-hero="3"]) .wx-glyph { width: 1.5rem; height: 1.5rem; }
:is([data-hero="2"], [data-hero="3"]) .wx-temp { font-size: var(--t-body); }
:is([data-hero="2"], [data-hero="3"]) .hero .kicker { font-size: .75rem; }
:is([data-hero="2"], [data-hero="3"]) .hero-meta { margin-top: .35rem; font-size: var(--t-small); line-height: 1.55; }
:is([data-hero="2"], [data-hero="3"]) .hero-actions { gap: .5rem; margin-top: .85rem; }
:is([data-hero="2"], [data-hero="3"]) .hero-actions .btn { padding: .5em 1.15em; font-size: var(--t-small); }
@media (max-width: 640px) {
  /* Small to look at, still a full thumb to press. */
  :is([data-hero="2"], [data-hero="3"]) .hero-actions .btn { display: inline-flex; align-items: center; min-height: var(--tap); }
}

/* Hero 2, the palms: "Welcome to" and the name in italic, centred over the photo. A sand tide draws back on load. */
[data-hero="2"] :is(.hero-media, .hero-cut) img { object-position: 50% 78%; }
[data-hero="2"] .w-b { font-style: italic; font-size: min(26vw, 44svh); line-height: .9; letter-spacing: -.02em; }
.hero-tide { position: absolute; inset: 0; z-index: 6; pointer-events: none; }
.hero-tide > div { position: absolute; inset: 0; background: var(--sand); animation: recede 2s var(--calm) .3s both; }
.hero-tide .tide-back { opacity: .5; animation-duration: 2.7s; }
.hero-tide svg { position: absolute; left: 0; bottom: calc(100% - 1px); width: 200%; height: clamp(34px, 5vw, 72px); fill: var(--sand); }
@keyframes recede { to { transform: translateY(calc(100% + 80px)); visibility: hidden; } }
[data-hero="2"] .hero-word { animation-delay: .7s; }
[data-hero="2"] .hero-copy > * { animation-delay: .9s; }
[data-hero="2"] .hero-copy > :nth-child(4) { animation-delay: 1s; }
[data-hero="2"] .hero-copy > :nth-child(5) { animation-delay: 1.1s; }
/* Portrait screens: the word spans the width and the copy sits at the foot. */
@media (orientation: portrait) {
  .hero-stage { --shade-foot: linear-gradient(to top, rgb(var(--shade) / .88), rgb(var(--shade) / .76) min(10rem, 26%), rgb(var(--shade) / 0) min(19rem, 46%)); }
  [data-hero="2"] :is(.hero-media, .hero-cut) img { object-position: 78% 100%; }
  [data-hero="2"] .w-b { font-size: min(37vw, 22svh); }
}
/* Short portrait phones: tighten the copy so the word keeps its room. */
@media (orientation: portrait) and (max-height: 700px) {
  .hero-meta { font-size: var(--t-body); }
  .weather { margin-bottom: var(--s2); }
}
/* Landscape phones: the whole welcome, buttons included, fits on the first screen. */
@media (orientation: landscape) and (max-height: 500px) {
  .hero-stage { min-height: 0; }
  .hero-meta { margin-top: var(--s1); font-size: var(--t-body); }
  .hero-actions { margin-top: var(--s2); }
  .hero-copy { padding-bottom: calc(var(--shore) + var(--s2)); }
  .weather { margin-bottom: var(--s1); }
  .site-header { padding-block: var(--s1); }
  .brand { height: 36px; }
  [data-hero="2"] .w-b { font-size: min(18vw, 42svh); }
  :is([data-hero="2"], [data-hero="3"]) .hero-copy { max-width: 15rem; }
}
/* The narrowest phones: the place line leaves the hero (the weather line names it). */
@media (max-width: 359px) {
  .hero .kicker { display: none; }
}
/* Owner, 14 Nov: in hero 2 the word sits over the palms, softened so the trees show through. */
/* The 72% is in the colour, not opacity: Safari paints faded text into a layer cut at the text box, which clips the italic f. */
[data-hero="2"] .w-b { color: color-mix(in srgb, var(--shell) 72%, transparent); }

/* Hero 4: hero 1's sand sheet laid over hero 2.
   "Kaïf" is cut out of the sheet in the lockup's italic, the palms show through, and scrolling opens the sheet
   from inside the "a" until hero 2 is all there is. .has-veil is set in the head only with JS on and motion allowed. */
.hero-veil { display: none; }
.has-veil .hero-stage { --word-r: 2.301; --word-w: min(100cqw - 2 * var(--gutter), (max(100svh, 36rem) - 28rem) * var(--word-r)); --word-h: calc(var(--word-w) / var(--word-r)); --word-x: calc((100cqw - var(--word-w)) / 2); --word-y: calc((max(100svh, 36rem) - 10rem - var(--word-h)) / 2 + 1.75rem); }
@media (prefers-reduced-motion: no-preference) {
  .has-veil .hero { height: calc(100svh + 70vh); }
  .has-veil .hero-stage { position: sticky; top: 0; }
  .has-veil .hero-veil { display: block; position: absolute; inset: 0; z-index: 4; pointer-events: none; will-change: transform, opacity; transform-origin: calc(var(--word-x) + .47 * var(--word-w)) calc(var(--word-y) + .6 * var(--word-h)); }
}
/* A soft teal shade seen only through the letters, so they hold their shape against the sand. */
.hero-veil::before { content: ""; position: absolute; inset: 0; background: rgb(var(--shade) / .3); }
/* "Welcome to" in ink above the cut-out, so the sheet reads as the same lockup that waits underneath. */
.veil-welcome { position: absolute; left: 0; right: 0; top: calc(var(--word-y) - 3.6rem); margin: 0; font: 400 clamp(1.7rem, 3.4vw, 3.25rem)/1.1 var(--serif); letter-spacing: -.01em; text-align: center; color: var(--ink); }
.veil-sand { position: absolute; inset: 0; background: var(--sand); /* plain sand: a grain blend under a mask is redrawn every frame on iPhones */
  -webkit-mask: url("img/kaif-word-i.svg") var(--word-x) var(--word-y) / var(--word-w) var(--word-h) no-repeat, linear-gradient(#000 0 0); mask: url("img/kaif-word-i.svg") var(--word-x) var(--word-y) / var(--word-w) var(--word-h) no-repeat, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude; }
/* The sand tide is not needed under the sheet, and the lockup waits for the sheet to open (main.js fades it in). */
.has-veil .hero-tide { display: none; }
.has-veil .hero-word { animation: none; }
.veil-shut .hero-word { opacity: 0; }
/* While the sheet is shut, the corner block and the header read in ink on the sand; they turn cream as it opens. */
.has-veil .hero-copy, .has-veil .hero-copy .btn { transition: color var(--dur-state) var(--calm), background-color var(--dur-state) var(--calm), border-color var(--dur-state) var(--calm); }
.has-veil .weather { transition: opacity var(--dur-reveal) var(--calm), color var(--dur-state) var(--calm), background-color var(--dur-state) var(--calm), box-shadow var(--dur-state) var(--calm); }
.veil-shut .weather { background: var(--shell); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--teal) 30%, transparent); }
.veil-shut .hero { --focus: var(--ink); color: var(--ink); }
.veil-shut .hero .btn-cream { background: var(--teal); color: var(--shell); }
.veil-shut .hero .btn-cream:hover { background: var(--teal-deep); }
.veil-shut .hero .btn-ghost:hover { background: color-mix(in srgb, var(--teal) 10%, transparent); }
.veil-shut .site-header:not(.is-scrolled) { color: var(--ink); }
.veil-shut .site-header:not(.is-scrolled) .brand-light { opacity: 0; }
.veil-shut .site-header:not(.is-scrolled) .brand-dark { opacity: 1; }
.veil-shut .site-header:not(.is-scrolled) .nav-book { background: var(--teal); color: var(--shell); }

/* Fades as things come into view: quick enough to read through, still soft */
.js .reveal { opacity: 0; transform: translateY(14px); transition: opacity var(--dur-reveal) var(--calm), transform var(--dur-reveal) var(--calm); }
.js .reveal.is-in { opacity: 1; transform: none; }

.photo img { width: 100%; border-radius: var(--radius-photo); background: var(--sand-warm); color: transparent; }
.blob { position: absolute; z-index: -1; overflow: visible; }

/* Intro */
.intro-grid { display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); gap: var(--s5); align-items: center; }
.intro-copy p { margin-top: var(--s3); max-width: var(--measure); font-size: var(--t-lead); color: var(--muted); }
.intro-photos { position: relative; isolation: isolate; display: grid; grid-template-columns: 5fr 7fr; gap: var(--s3); align-items: end; }
.intro-photo-a { order: 2; }
.intro-photo-b { order: 1; }
.intro-photo-a img { aspect-ratio: 4 / 5; object-fit: cover; object-position: 50% 60%; }
.intro-photo-b img { aspect-ratio: 4 / 5; object-fit: cover; }
.intro-photos .blob { width: 86%; left: -12%; top: 6%; fill: var(--sand-warm); }

/* Menu */
.menu-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--s1) var(--s4); }
.menu-note { font-size: var(--t-small); color: var(--muted); }
.menu-index { margin: var(--s2) 0 var(--s3); }
.menu-index ul, .menu-index [role="tablist"] { display: flex; flex-wrap: wrap; gap: var(--s1); margin-left: -1.1em; }
.menu-index a, .menu-index [role="tab"] { display: block; padding: .5em 1.1em; border: 0; border-radius: var(--radius-pill); background: none; font: 400 var(--t-body)/1.4 var(--sans); color: var(--muted); text-decoration: none; white-space: nowrap; cursor: pointer; transition: background-color var(--dur-tap) var(--calm), color var(--dur-tap) var(--calm); }
.menu-index a:hover, .menu-index [role="tab"]:hover { background: color-mix(in srgb, var(--mint) 50%, transparent); color: var(--ink); }
.menu-index [aria-selected="true"], .menu-index [aria-selected="true"]:hover { background: var(--mint); color: var(--ink); }
.menu-grid { display: grid; grid-template-columns: minmax(0, 1fr) clamp(250px, 26vw, 350px); gap: var(--s5); align-items: start; }
.menu-panels { display: grid; gap: var(--s5); }
/* The menu fade: headings and dishes rise one after another, 60ms apart, when a tab opens or the list is filtered. */
.menu-panel.is-entering .rise { animation: rise .5s cubic-bezier(.21, .47, .32, .98) calc(80ms + var(--i, 0) * 60ms) both; }
@keyframes rise { from { opacity: 0; transform: translateY(15px); } }
.menu-panel h3 { margin-bottom: var(--s3); }
/* With tabs, the selected tab already names the panel: keep the heading for screen readers only. */
.js .menu-panel h3 { position: absolute; width: 1px; height: 1px; margin: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* Each tab holds its groups: a small serif heading with a thin rule, then compact rows, as on Kaif's earlier menu. */
.menu-group { margin-bottom: var(--s2); }
.menu-group:last-of-type { margin-bottom: 0; }
.group-title { font: 400 1.3rem/1.3 var(--serif); letter-spacing: -.005em; }
.group-title span { display: block; padding-bottom: .4rem; margin-bottom: .8rem; border-bottom: 1px solid color-mix(in srgb, var(--teal) 30%, transparent); }
.dishes { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s2); }
.dishes dt { font-weight: 500; line-height: 1.45; }
.dishes dd { line-height: 1.6; color: var(--muted); }
.menu-panel .dishes { gap: .8rem; }
.menu-panel dd { font-size: .9375rem; line-height: 1.5; }
/* Prices (Thai baht, VAT included) sit at the right of the dish name in Bench Teal, with the baht sign. */
.menu-panel dt { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s2); }
.menu-panel .price { font-family: "Prompt Baht", var(--sans); font-weight: 400; color: var(--teal); white-space: nowrap; }
/* Quiet lines inside a tab: a note at the top, the trimmings, a small label beside a dish name. */
.menu-tabnote { margin-bottom: var(--s2); font-size: .9375rem; line-height: 1.5; color: var(--muted); }
.menu-text { font-size: .9375rem; line-height: 1.5; color: var(--muted); }
.menu-text + .menu-text { margin-top: .6rem; }
.menu-text .text-link { font-size: var(--t-body); color: var(--ink); }
/* Two columns: the groups flow down then across, like a printed menu, so nothing leaves a hole. */
@media (min-width: 641px) {
  .menu-panel { columns: 2; column-gap: var(--s5); }
  .menu-panel h3 { column-span: all; }
  .menu-panel .dishes { display: block; }
  .menu-panel .dishes > div { break-inside: avoid; padding-bottom: .8rem; }
  /* A heading never sits alone at the foot of a column: its box reaches down over the first dish below it. */
  .group-title { break-inside: avoid; padding-bottom: 4rem; margin-bottom: -4rem; }
}
.v { margin-left: .2em; font-size: var(--t-kicker); letter-spacing: .06em; color: var(--kicker); }
.menu-more { margin-top: var(--s2); }
.menu-photos { position: relative; isolation: isolate; display: grid; gap: var(--s3); }
.menu-photo-b { width: 74%; margin-left: -10%; }
.menu-photos img { aspect-ratio: 3 / 4; object-fit: cover; }
.menu-photo-a img { object-position: 50% 40%; } /* sign and menu shelf */
.menu-photos figcaption { margin-top: var(--s1); font-size: var(--t-small); color: var(--muted); }
.menu-photos .blob { width: 120%; right: -34%; top: 30%; fill: var(--mint); opacity: .55; transform: rotate(70deg); }
.menu-roast { margin-top: var(--s3); max-width: 60ch; }
/* Wide screens, with the tabs: the photo column takes its height from the dish list beside it, never the other way round,
   and one photo fills it (the açaí bowl with Breakfast, the palms with the other tabs; main.js sets data-show). */
@media (min-width: 901px) {
  .js .menu-grid { align-items: stretch; }
  .js .menu-aside { position: relative; min-height: 16rem; }
  .js .menu-photos { position: absolute; inset: 0; display: flex; flex-direction: column; }
  .js .menu-photos figure { flex: 1; display: flex; flex-direction: column; width: auto; min-height: 0; margin: 0; }
  .js .menu-photos picture { position: relative; flex: 1; min-height: 0; }
  .js .menu-photos img { position: absolute; inset: 0; height: 100%; aspect-ratio: auto; }
  .js .menu-photos[data-show="a"] .menu-photo-b, .js .menu-photos[data-show="b"] .menu-photo-a { display: none; }
  /* The blob sits centred behind the one photo, so it stays whole above the section edge. */
  .js .menu-photos .blob { width: 80%; right: -24%; top: 50%; margin-top: -33%; }
}

/* Vegetarian chip: one calm pill under the tabs, with a count beside it. */
.menu-filter { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s2); margin-top: var(--s2); font-size: var(--t-small); color: var(--muted); }
.chip { display: inline-flex; align-items: center; gap: .45em; padding: .45em 1.1em .45em .8em; border: 1px solid color-mix(in srgb, var(--teal) 30%, transparent); border-radius: var(--radius-pill); background: none; font: 400 var(--t-body)/1.4 var(--sans); color: var(--ink); cursor: pointer; transition: background-color var(--dur-tap) var(--calm), border-color var(--dur-tap) var(--calm), transform var(--dur-tap) var(--calm); }
.chip:hover { background: color-mix(in srgb, var(--mint) 50%, transparent); }
.chip:active { transform: scale(.98); }
.chip[aria-pressed="true"] { border-color: transparent; background: var(--mint); }
/* The (V) mark turns into a tick when the chip is on, so the state never rests on colour alone. */
.chip-mark { display: inline-grid; place-items: center; min-width: 1.7em; font-size: var(--t-kicker); letter-spacing: .06em; color: var(--kicker); }
.chip-mark > * { grid-area: 1 / 1; transition: opacity var(--dur-tap) var(--calm), transform var(--dur-tap) var(--calm); }
.chip-mark svg { width: 1em; height: .85em; fill: none; stroke: var(--ink); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; opacity: 0; transform: scale(.6); }
.chip[aria-pressed="true"] .chip-mark span { opacity: 0; transform: scale(.6); }
.chip[aria-pressed="true"] .chip-mark svg { opacity: 1; transform: none; }
.is-veg .not-v { display: none; }

/* Mural band */
.band { position: relative; height: clamp(230px, 44vh, 440px); overflow: hidden; overflow: clip; background: var(--teal-night); }
.band-media { position: absolute; inset: -14% 0; will-change: transform; }
.band-media picture, .band-media img { display: block; width: 100%; height: 100%; }
.band-media img { object-fit: cover; object-position: 50% 62%; color: transparent; }

/* Sunday roast and booking: the roast menu straight on the water, the booking form the one raised card */
.roast-head { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--s3) var(--s5); align-items: start; }
.roast-lead { max-width: 58ch; }
.roast-lead .lead { font: 400 var(--t-dish)/1.3 var(--serif); letter-spacing: -.005em; }
.roast-lead p + p { margin-top: var(--s1); }
.roast-jump { display: none; }
.roast-grid { position: relative; isolation: isolate; display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--s5); align-items: start; margin-top: var(--s5); }
.roast-card { padding-top: calc(var(--pad-card) + 1px); }
.book-card { padding: var(--pad-card); border: 1px solid color-mix(in srgb, var(--teal) 30%, transparent); border-radius: var(--radius-card); background: var(--shell); }
.roast-dishes { gap: var(--s2); margin-top: var(--s3); }
.roast-dishes dt { font: 400 var(--t-dish)/1.25 var(--serif); letter-spacing: -.005em; }
.roast-extras { display: grid; gap: var(--s3); margin-top: var(--s4); }
.roast-extras p { margin-top: var(--s1); line-height: 1.6; color: var(--muted); }
.blob-a { width: 30%; right: -7%; top: -9%; fill: var(--sea); opacity: .8; transform: rotate(-24deg); }

/* Booking form (the preview stand-in for the Symphony widget, which will load into .book-embed) */
.book-note { max-width: 60ch; margin: var(--s2) 0 var(--s3); color: var(--muted); }
.field { margin-bottom: var(--s2); }
.field-row { display: grid; grid-template-columns: 1.6fr 1fr 1fr; gap: 0 var(--s2); }
.field-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--s2); }
label { display: block; margin-bottom: var(--s0); font-weight: 500; font-size: var(--t-small); }
.optional { font-weight: 400; color: var(--muted); }
input, select, textarea { display: block; width: 100%; padding: .7rem .95rem; border: 1px solid var(--line); border-radius: var(--radius-field); background-color: var(--sand); color: var(--ink); font: 400 var(--t-body)/1.5 var(--sans); transition: border-color var(--dur-tap) var(--calm), box-shadow var(--dur-tap) var(--calm); }
select { appearance: none; padding-right: 2.4rem; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%231B2E30' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right .95rem center; background-size: .7rem; }
textarea { resize: vertical; min-height: 4.5rem; }
input:focus-visible, select:focus-visible, textarea:focus-visible { outline-offset: 2px; border-radius: var(--radius-field); }
[aria-invalid="true"] { border-color: var(--earth); box-shadow: inset 0 0 0 1px var(--earth); }
.error { margin-top: var(--s0); font-size: var(--t-small); line-height: 1.45; color: var(--earth); }
.hint { margin-top: var(--s0); font-size: var(--t-small); color: var(--muted); }
.guests-hint { margin: calc(-1 * var(--s1)) 0 var(--s2); }
.closed-note { margin-bottom: var(--s2); font-size: var(--t-small); }
.form-foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); margin-top: var(--s3); }
.alt { font-size: var(--t-small); }
.alt a { text-underline-offset: .35em; }
.confirm:focus { outline: none; }
.confirm-title { font: 400 var(--t-h3)/1.2 var(--serif); letter-spacing: -.01em; }
.confirm p { margin-top: var(--s2); }
.confirm-note { font-size: var(--t-small); color: var(--muted); }
/* Delight: the shore's crest drawn once, like a wave running up the sand. */
.confirm-wave { display: block; width: 9rem; height: .9rem; margin-top: var(--s2); overflow: visible; fill: none; stroke: var(--teal); stroke-width: 2; stroke-linecap: round; }
.confirm-wave use { vector-effect: non-scaling-stroke; stroke-dasharray: .5 1; stroke-dashoffset: 0; }
.confirm:not([hidden]) .confirm-wave use { animation: draw var(--dur-draw) var(--calm) .2s both; }
@keyframes draw { from { stroke-dashoffset: .5; } }

/* Visit and photos: details on one side, a small mosaic on the other */
.visit-grid { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--s5); align-items: center; }
.visit-facts { display: grid; gap: var(--s3); margin-top: var(--s4); }
.visit-facts dt { font-weight: 500; }
.visit-facts .text-link { display: inline-block; margin-top: var(--s1); }
.mosaic { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: var(--s2); }
.mosaic li, .mosaic picture { display: flex; width: 100%; }
.mosaic img { height: 100%; aspect-ratio: 1; object-fit: cover; }
.mosaic-main { grid-row: span 2; }
.mosaic-main img { aspect-ratio: auto; }

/* Footer */
.site-footer { padding: var(--s5) 0 var(--s3); color: var(--shell); }
.footer-inner { display: grid; grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr)); gap: var(--s3) var(--s4); align-items: start; font-size: .9375rem; line-height: 1.6; }
.footer-logo { width: 96px; height: auto; margin: 0 0 var(--s2); }
.footer-brand p { max-width: 26ch; opacity: .85; }
.footer-head { margin: 0 0 var(--s1); font: 500 .75rem/1.4 var(--sans); letter-spacing: .14em; text-transform: uppercase; opacity: .7; }
.footer-col p + p { margin-top: var(--s1); }
.footer-col a, .footer-brand a { color: inherit; text-decoration: none; }
.footer-col a:hover { text-decoration: underline; text-underline-offset: .3em; }
.footer-nav { list-style: none; margin: 0; padding: 0; display: grid; gap: .35rem; }
.footer-small { grid-column: 1 / -1; margin-top: var(--s2); padding-top: var(--s2); border-top: 1px solid color-mix(in srgb, var(--shell) 18%, transparent); font-size: .8125rem; opacity: .7; }
@media (max-width: 900px) { .footer-inner { grid-template-columns: repeat(3, minmax(0, 1fr)); } .footer-brand { grid-column: 1 / -1; } }
@media (max-width: 480px) { .footer-inner { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

@media (max-width: 900px) {
  .intro-grid, .roast-head, .roast-grid, .visit-grid, .menu-grid { grid-template-columns: minmax(0, 1fr); }
  .intro-photos { max-width: 36rem; }
  .menu-photos { grid-template-columns: 1fr 1fr; gap: var(--s2); }
  .menu-photo-b { width: auto; margin: var(--s4) 0 0; }
  .menu-photos .blob { width: 70%; right: -16%; top: 20%; }
  .blob-a { display: none; }
  .roast-jump { display: block; }
  .roast-card { padding-top: 0; }
  /* Menu tabs: one row that scrolls sideways, fading at the edge to show there is more. */
  .menu-index [role="tablist"] { position: relative; flex-wrap: nowrap; gap: .25rem; overflow-x: auto; scroll-snap-type: x proximity; scrollbar-width: none; margin-inline: calc(-1 * var(--gutter)); padding-inline: var(--gutter) 3rem; mask-image: linear-gradient(90deg, var(--ink) calc(100% - 3rem), transparent); }
  .menu-index [role="tablist"]::-webkit-scrollbar { display: none; }
  .menu-index [role="tab"] { flex: none; scroll-snap-align: start; scroll-margin-inline: var(--gutter); }
}
@media (min-width: 901px) {
  .menu-roast { display: none; }
}
@media (max-width: 640px) {
  .brand { height: var(--tap); }
  .site-header a { font-size: var(--t-small); }
  .site-header ul { gap: .75rem; }
  /* "Sunday roast" reads "Roast" in the phone header; screen readers still hear "Sunday roast". */
  .nav-full { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .nav-short { display: inline; }
  .shore-back { display: none; } /* at 20px tall the second wave layer can't be seen; skip painting it */
  .field-pair { grid-template-columns: 1fr; }
  .field-row { grid-template-columns: 1fr 1fr; }
  .field-row .field:first-child { grid-column: 1 / -1; }
  .mosaic { grid-template-columns: 1fr 1fr; }
  .mosaic-main { grid-column: 1 / -1; grid-row: auto; }
  .mosaic-main img { aspect-ratio: 5 / 4; }
  /* Long menu sections show their first dishes, with a button for the rest (set up in main.js). */
  .menu-panels:not(.is-veg) .is-folded .more { display: none; }
  .is-veg .menu-more { display: none; } /* the vegetarian list is short enough to show whole */
  .chip { min-height: var(--tap); }
  /* Thumb-sized targets: grow the hit area, not the look. */
  .site-header nav a, .menu-index [role="tab"] { display: flex; align-items: center; justify-content: center; min-width: var(--tap); min-height: var(--tap); }
  .site-header .nav-book { padding-inline: .9em; }
  /* The two hero buttons share one row, which makes the room the weather line needs. */
  .hero-actions { gap: .6rem; }
  .hero-actions .btn { padding-inline: 1.15em; font-size: .9375rem; }
  .text-link, .alt a, .footer-nav a { display: inline-block; padding-block: 11px; margin-block: -11px; }
  .footer-nav a { min-width: var(--tap); }
  .menu-panel .menu-more { margin-top: calc(var(--s2) - 11px); }
  .visit-facts .text-link { margin-top: calc(var(--s1) - 11px); }
  .footer-nav { gap: var(--s2) var(--s4); }
}
@media (min-width: 641px) {
  .menu-more { display: none; }
}
@media (min-width: 641px) {
  .nav-short { display: none; }
}
@media (max-width: 380px) {
  .site-header { gap: var(--s1); }
  .site-header ul { gap: .5rem; }
  .site-header li:nth-child(3) { display: none; } /* "Visit" is in the footer, and the last section */
  .hero-actions .btn { padding-inline: .9em; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition-duration: .01ms !important; }
  .js .reveal { opacity: 1; transform: none; }
  .hero-tide { display: none; } /* with no animation the sand tide would never draw back */
}

/* Guest reviews, after the old site's card layout */
.reviews { padding-block: var(--section) var(--section-end); }
.reviews-head { text-align: center; }
.reviews-head h2 { margin-top: var(--s1); }
.reviews-score { margin-top: var(--s2); color: var(--muted); display: inline-flex; align-items: center; gap: .4em; }
.stars { display: inline-flex; gap: 2px; color: var(--teal); vertical-align: -0.1em; }
.star { width: .8em; height: .8em; fill: currentColor; }
.review-grid { list-style: none; margin: var(--s4) 0 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); }
.review { display: flex; flex-direction: column; gap: var(--s2); padding: var(--s3); background: var(--shell); border: 1px solid color-mix(in oklab, var(--ink) 9%, transparent); border-radius: 18px; }
.review-head { display: flex; align-items: center; gap: .75rem; }
.avatar { flex: none; display: grid; place-items: center; width: 2.25rem; height: 2.25rem; border-radius: 50%; background: var(--mint); color: var(--teal-deep); font: 400 1rem/1 var(--serif); }
.review-who { display: flex; flex-direction: column; line-height: 1.3; min-width: 0; }
.review-name { font-weight: 500; }
.review-meta { font-size: .8125rem; color: var(--muted); }
.review-tag { margin-left: auto; padding: .2rem .6rem; border-radius: 999px; background: var(--foam); font-size: .8125rem; color: var(--muted); }
.review blockquote { margin: 0; flex: 1; }
.review blockquote p { font-size: .9375rem; line-height: 1.6; color: var(--ink); }
.review-scores { display: flex; flex-wrap: wrap; justify-content: flex-start; gap: .3rem .9rem; padding-top: var(--s2); border-top: 1px solid color-mix(in oklab, var(--ink) 8%, transparent); font-size: .75rem; color: var(--muted); white-space: nowrap; }
.review-scores > span { display: inline-flex; align-items: center; gap: .3em; }
.review-scores .stars { gap: 1px; }
.reviews-more { margin-top: var(--s3); text-align: center; }
@media (max-width: 1000px) { .review-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .review-grid { grid-template-columns: minmax(0, 1fr); } .review:nth-child(n+4) { display: none; } }
.roast-quote { margin: var(--s3) 0 0; max-width: 52ch; }
.roast-quote blockquote p { font-family: var(--serif, "Playfair Display", serif); font-size: 1.125rem; line-height: 1.5; }
@media (max-width: 900px) { .quotes { grid-template-columns: minmax(0, 1fr); gap: var(--s3); } }
.roast-quote + .roast-jump { margin-top: var(--s3); }

/* The little map: the bay to the north, the sand, and Kaif on the shore. Drawn from the page's own wave, not to scale. */
.map { position: relative; display: block; max-width: 26rem; aspect-ratio: 5 / 2; margin-top: var(--s2); overflow: hidden; border-radius: var(--radius-photo); background: var(--seafoam); text-decoration: none; }
.map:focus-visible { border-radius: var(--radius-photo); }
.map svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.map-water { fill: none; stroke: var(--shell); stroke-width: 1.5; stroke-opacity: .8; vector-effect: non-scaling-stroke; }
.map-land { fill: var(--sand); }
.map-pin { fill: var(--teal); }
.map-eye { fill: var(--shell); }
.map-ring { fill: var(--teal); opacity: 0; transform-box: fill-box; transform-origin: center; }
.map.is-in .map-ring { animation: ripple 3.2s var(--calm) infinite; }
.map text { font: 400 21px var(--serif); fill: var(--ink); }
.map-north { fill: none; stroke: var(--teal-deep); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.map .kicker { position: absolute; left: 1.1rem; top: .9rem; }
.map-go { position: absolute; right: .8rem; bottom: .7rem; }
.map:hover .map-go { background: var(--teal-deep); }
@keyframes ripple { from { opacity: .5; transform: scale(1); } to { opacity: 0; transform: scale(2.8); } }
@media (max-width: 359px) { .review { padding: var(--s2); } }
/* Roast prices */
.roast-dishes dt { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.roast-dishes .price { flex: none; font: 500 1rem/1.2 var(--sans, "Prompt", sans-serif); color: var(--teal); }
.fav { margin-left: .5em; font: 500 .75rem/1 var(--sans, "Prompt", sans-serif); letter-spacing: .12em; text-transform: uppercase; color: var(--teal); vertical-align: .25em; }

.quotes blockquote, .roast-quote blockquote { margin: 0; }
/* Owner: lift the welcome lockup a little, for more room above the corner block */
[data-hero="2"] .hero-word { padding-bottom: 14svh; }
@media (min-width: 641px) and (max-height: 800px) { [data-hero="2"] .w-b { font-size: min(26vw, 38svh); } [data-hero="2"] .hero-word { padding-bottom: 18svh; } }
@media (max-width: 640px) { [data-hero="2"] .hero-word { padding-bottom: 16svh; } }

/* Owner: "Sunday roasts are back" as a big call to action filling the left column */
.roast-cta h2 { margin-top: var(--s1); font-size: clamp(3rem, 6.4vw, 6rem); line-height: .98; letter-spacing: -.025em; }
.roast-cta h2 span { display: block; color: var(--teal); }
.roast-cta-btn { margin-top: var(--s3); }
@media (max-width: 900px) { .roast-cta h2 { font-size: clamp(2.6rem, 11vw, 4rem); } }

/* Phone booking pill: slim, bottom centre, only between the welcome and the booking card (main.js decides when). */
.book-pill { display: none; }
@media (max-width: 900px) {
  html { scroll-padding-bottom: 4.5rem; } /* a focused link never hides behind the pill */
  .book-pill { --focus: var(--shell); position: fixed; left: calc(50% - (2.75rem + var(--s2)) / 2); bottom: calc(var(--s2) + env(safe-area-inset-bottom, 0px)); z-index: 40; display: flex; align-items: center; border: 1px solid color-mix(in srgb, var(--shell) 55%, transparent); border-radius: var(--radius-pill); background: var(--teal); color: var(--shell); white-space: nowrap; opacity: 0; visibility: hidden; pointer-events: none; transform: translate(-50%, 12px); transition: opacity var(--dur-state) var(--calm), transform var(--dur-state) var(--calm), visibility 0s var(--dur-state); }
  .book-pill.is-on { opacity: 1; visibility: visible; pointer-events: auto; transform: translate(-50%, 0); transition-delay: 0s; }
  .book-pill a { display: flex; align-items: center; min-height: var(--tap); padding: 0 .35em 0 1.4em; font-weight: 500; text-decoration: none; }
  .book-pill button { display: grid; place-items: center; width: var(--tap); height: var(--tap); padding: 0; border: 0; border-radius: 50%; background: none; color: inherit; cursor: pointer; }
  .book-pill svg { width: .65rem; height: .65rem; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linecap: round; opacity: .85; }
  .book-pill :focus-visible { outline-offset: -5px; border-radius: var(--radius-pill); }

}

/* Back to the top */
.to-top { position: fixed; right: calc(var(--s2) + env(safe-area-inset-right, 0px)); bottom: calc(var(--s2) + env(safe-area-inset-bottom, 0px)); z-index: 41; display: grid; place-items: center; width: 2.75rem; height: 2.75rem; padding: 0; border: 1px solid color-mix(in srgb, var(--teal) 35%, transparent); border-radius: 50%; background: color-mix(in srgb, var(--shell) 92%, transparent); color: var(--teal); cursor: pointer; opacity: 0; visibility: hidden; transform: translateY(10px); transition: opacity var(--dur-state) var(--calm), transform var(--dur-state) var(--calm), visibility 0s var(--dur-state), background-color var(--dur-tap) var(--calm); }
.to-top.is-on { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }
.to-top:hover { background: var(--teal); color: var(--shell); }
.to-top svg { width: 1rem; height: 1rem; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
@media (min-width: 901px) { .to-top { right: calc(var(--s3) + env(safe-area-inset-right, 0px)); bottom: var(--s3); } }

/* Scrollbar in the Kaïf colours */
html { scrollbar-color: color-mix(in srgb, var(--teal) 55%, var(--sand)) var(--sand); scrollbar-width: thin; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--sand); }
::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--teal) 55%, var(--sand)); border: 2px solid var(--sand); border-radius: 999px; }
::-webkit-scrollbar-thumb:hover { background: var(--teal); }
#roast .roast-dishes .price, #roast .fav { color: var(--teal-deep); }

address { font-style: normal; }

/* Safari clips the italic f overhang when opacity makes a layer; give the glyph room (even padding keeps it centred). */
[data-hero="2"] .w-b { padding-inline: .3em; }

/* Band 5: a day at Kaïf, five photos from 8am to 8pm, on the menu's foam.
   Plain layout (no JS, or reduced motion): all five side by side. */
.band-day { padding-block: var(--s3) calc(var(--section-end) + var(--shore)); }
.band-day-row { margin-top: var(--s3); padding-inline: var(--edge); }
.band-day-track { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--s2); align-items: end; margin: 0; padding: 0; list-style: none; }
.band-day-track img { aspect-ratio: 4 / 5; object-fit: cover; }
.band-day-track figcaption { margin-bottom: var(--s1); font-size: var(--t-small); line-height: 1.5; } /* the time comes first, so each card can be read as soon as the row arrives */
.band-day-time { display: block; font: 400 var(--t-dish)/1.25 var(--serif); font-variant-numeric: lining-nums; letter-spacing: -.005em; }
/* Phones and tablets: a row to swipe, snapping card by card, with the next card peeking in. */
@media (max-width: 900px) {
  .band-day-row { overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scroll-padding-inline: var(--gutter); scrollbar-width: none; }
  .band-day-row::-webkit-scrollbar { display: none; }
  .band-day-track { display: flex; width: max-content; }
  .band-day-track > li { flex: none; width: min(68vw, 300px); scroll-snap-align: start; }
}
.band-day-row:focus-visible { outline-offset: -2px; } /* a full-width row: keep the ring on screen */

/* Design review fixes, 14 Nov */
/* Short portrait phones: the lockup takes the room above the corner block, so the two never meet. */
@media (orientation: portrait) and (max-height: 600px) {
  .hero-stage { flex-direction: column; align-items: stretch; }
  [data-hero="2"] .hero-word { position: relative; inset: auto; flex: 1 1 auto; min-height: 0; padding: var(--header-h) 0 0; }
  [data-hero="2"] .hero-copy { flex: none; }
  [data-hero="2"] .w-b { font-size: min(34vw, 19svh); }
}
/* Landscape phones: keep the word clear of the corner block. */
@media (orientation: landscape) and (max-height: 500px) { [data-hero="2"] .hero-word { padding-left: 16rem; padding-bottom: 6svh; } }
.hero-meta { text-wrap: balance; }
@media (min-width: 901px) {
  .roast-head { align-items: end; } /* lead and quote sit on the headline's last line */
  .book-card { position: sticky; top: calc(var(--header-h) + var(--s2)); } /* the card travels beside the roast list */
  .js .menu-photos figure { flex: none; position: sticky; top: calc(var(--header-h) + var(--s2)); height: min(100%, calc(100svh - var(--header-h) - 2 * var(--s2))); }
}
/* Touch screens wider than phones still get 44px targets. */
@media (pointer: coarse) and (min-width: 641px) {
  .site-header nav a, .menu-index [role="tab"], .chip, .hero-actions .btn { display: inline-flex; align-items: center; justify-content: center; min-width: var(--tap); min-height: var(--tap); }
  .text-link, .footer-col a { display: inline-block; padding-block: 11px; margin-block: -11px; }
}
.intro-copy p + p { margin-top: var(--s2); font-size: var(--t-body); }
@media (max-width: 480px) { .footer-inner > .footer-col:nth-child(2) { grid-column: 1 / -1; } }
.visit-photo img { aspect-ratio: 5 / 4; object-fit: cover; object-position: 50% 78%; }

/* A fixed, full-height hero photo. The page scrolls up over it; the photo moves a little (parallax). */
.hero-media[data-fixed-hero] { position: fixed; inset: 0 0 auto; height: calc(100lvh + 60vh + 2px); z-index: 0; background: var(--teal-night); animation: none; will-change: transform; }
/* The parallax, run by the browser itself: the photo moves at a fifth of the scroll for the first three screens. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .hero-media[data-fixed-hero] { animation: photo-sink linear both; animation-timeline: scroll(root); animation-range: 0 300vh; }
  }
}
@keyframes photo-sink { to { transform: translate3d(0, -60vh, 0); } }
.hero { background: transparent; z-index: 1; }
main > section:not(.hero), .site-footer { z-index: 1; }

/* Once the sheet has opened, the second lockup is just the name. */
.has-veil .w-a { visibility: hidden; }

/* No section colours at all. The fixed palm photo is the page's background, under one even teal tint
   that deepens as the hero scrolls away (main.js sets --past from 0 to 1). Text is white over it. */
:root { --tint: .8; }
.hero-media[data-fixed-hero]::after { content: ""; position: absolute; inset: 0; background: rgb(29 74 75 / var(--tint)); opacity: var(--past, 0); } /* --teal-night */
main > section:not(.hero), .site-footer { background: none; }
.shore, .shore-flip, .hero-tide { display: none; }
main > section:not(.hero), .site-footer {
  --ink: var(--shell); --muted: var(--shell); --kicker: var(--shell);
  --teal: var(--shell); --teal-deep: var(--shell); --line: color-mix(in srgb, var(--shell) 40%, transparent); --focus: var(--shell);
  color: var(--shell);
}
/* Cards, buttons and selected tabs keep their own colours, with dark text on them. */
main > section:not(.hero) :is(.review, .book-card, .map, .btn, .chip[aria-pressed="true"], .menu-index [aria-selected="true"], input, select, textarea),
.site-footer .btn {
  --ink: #1B2E30; --muted: #3B5557; --kicker: #1F6B6B; --teal: #1F6B6B; --teal-deep: #174F50; --line: #5F8787; --focus: #1B2E30;
}
main > section:not(.hero) :is(.review, .book-card, .map) { color: var(--ink); }
.site-header.is-scrolled { background: rgb(var(--shade)); color: var(--shell); }
.site-header.is-scrolled .brand-light { opacity: 1; } .site-header.is-scrolled .brand-dark { opacity: 0; }

/* The hero's own shade softens at its foot and fades as the page tint takes over, so there is no hard line between them. */
.hero-stage::before { will-change: opacity; -webkit-mask: linear-gradient(#000 calc(100% - 7rem), transparent); mask: linear-gradient(#000 calc(100% - 7rem), transparent); opacity: calc(1 - var(--past, 0)); }

/* The soft round shapes were drawn for cream sections; on the tinted photo they read as faint water, not cream discs. */
main > section:not(.hero) .blob { fill: var(--shell); opacity: .08; }
/* Contrast: white on the 60% tint is about 4.4:1 at the brightest cloud. A soft shade behind section text lifts it past 4.5:1 there
   without a visible halo. Mint stays for the large "are back" only, where 3:1 is enough. */
main > section:not(.hero), .site-footer { text-shadow: 0 0 1.2em rgb(var(--shade) / .55); }
main > section:not(.hero) :is(.review, .book-card, .map, .btn, .chip, .menu-index [role="tab"], input, select, textarea, .photo) { text-shadow: none; }
#roast-title span { color: var(--mint); }

/* The opening, run by the browser itself where it can (smooth on iPhones): over the 70vh hold the sheet grows a little
   from inside the "a" and fades, then the name comes up. main.js only switches the ink/cream colours at the halfway mark. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .has-veil .hero-veil { animation: veil-open linear both; animation-timeline: scroll(root); animation-range: 0 70vh; }
    .has-veil .hero-word { animation: word-in linear both; animation-timeline: scroll(root); animation-range: 0 70vh; }
  }
}
@keyframes veil-open { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.5); opacity: 1; } 70% { transform: scale(2.5); opacity: 0; visibility: visible; } 100% { transform: scale(2.5); opacity: 0; visibility: hidden; } }
@keyframes word-in { 0%, 70% { opacity: 0; } 95%, 100% { opacity: 1; } }

/* Design review 2 fixes (15 Nov). */
/* Focus rings sit on the photo, so they are cream; only inside the cream cards are they ink. */
main > section:not(.hero) :is(.btn, .chip[aria-pressed="true"], .menu-index [aria-selected="true"], .map), .site-footer .btn { --focus: var(--shell); }
main > section:not(.hero) :is(.review, .book-card) { --focus: #1B2E30; }
.to-top { --focus: var(--shell); }
.veil-shut .site-header:not(.is-scrolled) .nav-book { --focus: var(--ink); }
/* Footer small text was faded for a solid footer; on the photo it needs full strength. */
.site-footer :is(.footer-head, .footer-small, .footer-brand p) { opacity: 1; }
/* Leftovers from the cream page. */
main > section:not(.hero) :is(.menu-index [role="tab"], .chip):hover { --ink: #1B2E30; --kicker: #1F6B6B; background: var(--mint); color: var(--ink); text-shadow: none; }
::selection { background: var(--mint); color: #1B2E30; text-shadow: none; }
html { scrollbar-color: color-mix(in srgb, var(--shell) 40%, rgb(var(--shade))) rgb(var(--shade)); }
::-webkit-scrollbar-track { background: rgb(var(--shade)); }
::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--shell) 40%, rgb(var(--shade))); border-color: rgb(var(--shade)); }
main > section:not(.hero) .blob { display: none; }

/* The pill covered dishes on tablets and landscape phones; there the header's Book button is always in reach. */
@media (min-width: 600px), (max-height: 500px) { .book-pill { display: none; } }
