/* Aspen Beckett — "Paper & Ink", with a frosted night window for the opening scene.
   Clean, modern light page and ink; colours live in the palette blocks below. One serif (Instrument Serif) for display,
   one sans (Instrument Sans) for everything else. Motion is short and decisive. */
:root{
  --paper:#FBFBF9; --paper-2:#F4F4F2; --paper-3:#EDEDEA; --paper-rgb:251,251,249;
  --ink:#1C1B1B; --ink-soft:rgba(28,27,27,.72); --stone:#6A6A6A; --rule:rgba(28,27,27,.13); --ink-hover:#333131;
  --night:#0B1220; --frost:#CBD5DF; --ivory:#F5F1EA;
  --serif:'Instrument Serif','Times New Roman',serif;
  --sans:'Instrument Sans','Helvetica Neue',Arial,system-ui,sans-serif;
  --ease:cubic-bezier(.25,.1,.25,1); --out:cubic-bezier(.16,1,.3,1);
  --gutter:clamp(16px,4.5vw,64px);
  --gutter-l:max(var(--gutter),env(safe-area-inset-left,0px));    /* the side gutters never sit under a notch or a rounded corner (landscape iPhone) */
  --gutter-r:max(var(--gutter),env(safe-area-inset-right,0px));
  --wrap:1160px;   /* ONE content width: headings, intro, glance, gallery, favourites, rates, notes all share this left edge (a look can widen it) */
}
/* palettes: index.html sets the default on <html data-palette>; ?palette=name previews another */
html[data-palette="white"]{
  --paper:#FBFBF9; --paper-2:#F4F4F2; --paper-3:#EDEDEA; --paper-rgb:251,251,249;
  --ink:#1C1B1B; --ink-soft:rgba(28,27,27,.72); --stone:#6A6A6A; --rule:rgba(28,27,27,.13); --ink-hover:#333131;
}
html[data-palette="green"]{
  --paper:#FAFAF8; --paper-2:#F1F1EE; --paper-3:#E6E6E2; --paper-rgb:250,250,248;
  --ink:#0F1412; --ink-soft:rgba(15,20,18,.72); --stone:#626663; --rule:rgba(15,20,18,.13); --ink-hover:#272E2A; --accent:#1A6A5A;
}
html[data-palette="mocha"]{
  --paper:#F8F7F3; --paper-2:#EFEDE7; --paper-3:#E6E2DA; --paper-rgb:248,247,243;
  --ink:#151412; --ink-soft:rgba(21,20,18,.72); --stone:#68625A; --rule:rgba(21,20,18,.13); --ink-hover:#2F2C28; --accent:#5A4A3E;
}
*,*::before,*::after{box-sizing:border-box}
[hidden]{display:none!important}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-top:76px}
body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--sans);font-size:16px;line-height:1.65;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;overflow-x:hidden}
body.is-gated{overflow:hidden}
img{max-width:100%;display:block}
a{color:inherit}
button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}
::selection{background:var(--ink);color:var(--paper)}
:focus-visible{outline:1px solid currentColor;outline-offset:4px}
.sr{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.skip{position:fixed;left:16px;top:-60px;z-index:200;background:var(--ink);color:var(--paper);padding:10px 16px;font-size:12px;letter-spacing:.14em;text-transform:uppercase}
.skip:focus{top:16px}
em{font-style:normal}
/* highlighted words, per palette (em .wi = per-word reveal spans) */
html[data-palette="white"] em{font-style:italic;font-synthesis:none;color:var(--ink)}
html[data-palette="white"] em .w{padding-inline:.2em .1em;margin-inline:-.2em -.1em}
html[data-palette="white"] .gifts em{color:var(--ink)}
html[data-palette="white"] .hero em{color:inherit}
html[data-palette="green"] em{font-style:normal;color:var(--accent)}
html[data-palette="green"] .hero em{color:inherit}
html[data-palette="green"] ::selection{background:var(--accent);color:var(--paper)}
html[data-palette="mocha"] em{font-style:italic;font-synthesis:none;color:var(--accent)}
html[data-palette="mocha"] em .w{padding-inline:.14em .1em;margin-inline:-.14em -.1em}
html[data-palette="mocha"] .gifts em{color:var(--ink)}
html[data-palette="mocha"] .hero em{color:inherit}
.hint{font-family:var(--sans);font-style:normal;font-size:max(.38em,12.5px);letter-spacing:.04em;color:var(--stone);border-bottom:1px dotted currentColor;vertical-align:middle;line-height:1.5}
.hero .hint{color:var(--frost)}

/* ---------- type ---------- */
.eyebrow{font-family:var(--sans);font-weight:500;font-size:11px;letter-spacing:.26em;text-transform:uppercase;color:var(--stone);margin:0 0 1.5rem}
.display{font-family:var(--serif);font-weight:400;font-size:clamp(2.7rem,6.2vw,5.8rem);line-height:1;letter-spacing:-.018em;margin:0}
.section{position:relative;padding:clamp(88px,12vw,176px) var(--gutter-r) clamp(88px,12vw,176px) var(--gutter-l)}
.section + .section{border-top:1px solid var(--rule)}
.section__head{max-width:var(--wrap);margin:0 auto clamp(44px,6vw,84px)}
.section__note{font-size:15px;color:var(--ink-soft);max-width:34rem;margin:1.4rem 0 0}

/* reveals: quick, settled, no wobble */
[data-split] .w{display:inline-block;overflow:hidden;vertical-align:top;padding-bottom:.1em;margin-bottom:-.1em}
[data-split] .wi{display:inline-block;transform:translateY(102%);transition:transform .8s var(--out);transition-delay:calc(var(--i) * 30ms)}
[data-split].in .wi{transform:none}
.reveal{opacity:0;transform:translateY(16px);transition:opacity .7s var(--ease),transform .8s var(--out)}
.reveal.in{opacity:1;transform:none}

/* ---------- buttons: sharp, quiet ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.6em;min-height:52px;padding:0 30px;border:1px solid transparent;
  font-family:var(--sans);font-size:11.5px;font-weight:500;letter-spacing:.22em;text-transform:uppercase;text-decoration:none;
  transition:background-color .25s var(--ease),color .25s var(--ease),border-color .25s var(--ease),transform .4s var(--out)}
.btn--solid{background:var(--ink);color:var(--paper)}
.btn--solid:hover{background:var(--ink-hover)}
.btn--ghost{border-color:var(--rule);min-height:44px;padding:0 22px}
.btn--ghost:hover{border-color:var(--ink)}
.btn--text{padding:0 8px;color:var(--stone)} .btn--text:hover{color:var(--ink)}
.hero .btn--solid{background:var(--ivory);color:var(--night)}
.hero .btn--solid:hover{background:#fff}
.hero .btn--text{color:rgba(245,241,234,.62)} .hero .btn--text:hover{color:var(--ivory)}

/* ---------- signature (her logo) ---------- */
.sig{display:block;color:var(--ink)}
.sig svg{display:block;width:100%;height:auto;overflow:visible}
.sig--hero{color:var(--ivory);width:min(78vw,720px,62svh);margin:0 auto;filter:drop-shadow(0 0 24px rgba(203,213,223,.16))}
.sig--nav{width:112px}
.sig--letter{width:min(230px,56vw)}
.sig--foot{width:min(360px,64vw);margin:0 auto 44px}
.sig--veil{width:min(340px,64vw);margin:0 auto 18px}
.sig--sent{width:200px;margin:0 auto 14px}
.sig[data-sig-write]{position:relative}
.sig--hero.sheen::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(100deg,transparent 38%,rgba(255,255,255,.9) 50%,transparent 62%) no-repeat;background-size:300% 100%;background-position:120% 0;
  -webkit-mask:url(assets/signature.svg) center/100% 100% no-repeat;mask:url(assets/signature.svg) center/100% 100% no-repeat;animation:sheen 1.8s var(--out) forwards}
@keyframes sheen{to{background-position:-20% 0}}

/* ---------- film grain: opening scene only ---------- */
.grain{position:absolute;inset:0;z-index:1;pointer-events:none;opacity:.08;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}

/* ---------- cursor: a single ring that inverts over light and dark ---------- */
.cursor{position:fixed;inset:0;pointer-events:none;z-index:150;display:none;mix-blend-mode:difference}
.has-cursor .cursor{display:block}
.has-cursor,.has-cursor a,.has-cursor button,.has-cursor label,.has-cursor summary{cursor:none}
.has-cursor input,.has-cursor textarea,.has-cursor select{cursor:text}
.cursor__ring,.cursor__dot{position:absolute;left:0;top:0;border-radius:50%;will-change:transform}
.cursor__ring{width:34px;height:34px;margin:-17px 0 0 -17px;border:1px solid #fff;transition:width .3s var(--out),height .3s var(--out),margin .3s var(--out)}
.cursor__dot{width:4px;height:4px;margin:-2px 0 0 -2px;background:#fff}
.cursor__label{display:none}
.cursor.is-hover .cursor__ring{width:52px;height:52px;margin:-26px 0 0 -26px}
.cursor.is-label .cursor__ring{width:72px;height:72px;margin:-36px 0 0 -36px}

/* ---------- privacy veil ---------- */
.veil{position:fixed;inset:0;z-index:180;display:grid;place-items:center;background:rgba(var(--paper-rgb),.7);
  -webkit-backdrop-filter:blur(30px);backdrop-filter:blur(30px);opacity:0;visibility:hidden;transition:opacity .25s,visibility 0s .25s}
.veil.on{opacity:1;visibility:visible;transition:opacity .15s}
.veil p{font-size:11px;letter-spacing:.26em;text-transform:uppercase;color:var(--stone);text-align:center;margin:0}

/* ---------- nav ---------- */
.nav{position:fixed;inset:0 0 auto 0;z-index:100;display:flex;align-items:center;justify-content:space-between;gap:24px;
  height:72px;padding:0 var(--gutter-r) 0 var(--gutter-l);color:var(--ink);transition:transform .45s var(--out),color .3s var(--ease)}
.nav::before{content:"";position:absolute;inset:0;background:rgba(var(--paper-rgb),.88);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
  border-bottom:1px solid var(--rule);opacity:0;transition:opacity .3s var(--ease);pointer-events:none}
.nav.scrolled::before{opacity:1}
body[data-theme="night"] .nav{color:var(--ivory)}
body[data-theme="night"] .nav::before{opacity:0}
.is-gated .nav,.nav.hide{transform:translateY(-110%)}
.nav__logo{position:relative;display:block;color:inherit}
.nav__logo .sig{color:inherit}
.nav__links{position:relative;display:flex;gap:clamp(18px,2.6vw,38px)}
.nav__links a,.nav__burger b{font-size:11px;font-weight:500;letter-spacing:.22em;text-transform:uppercase;text-decoration:none;color:inherit;opacity:.72;transition:opacity .2s;white-space:nowrap}
.nav__links a{position:relative;padding:6px 0}
.nav__links a::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;background:currentColor;transform:scaleX(0);transform-origin:right;transition:transform .35s var(--out)}
.nav__links a:hover{opacity:1}
.nav__links a:hover::after{transform:scaleX(1);transform-origin:left}
.nav__right{position:relative;display:flex;align-items:center;gap:20px}
.nav__cta{color:inherit;border-color:currentColor}
.lang{display:inline-flex;align-items:center;gap:8px;font-size:11px;font-weight:500;letter-spacing:.2em}
.lang i{width:1px;height:11px;background:currentColor;opacity:.3}
.lang span{opacity:.6;transition:opacity .2s}
html[lang="en"] .lang [data-lang="en"],html[lang="fr"] .lang [data-lang="fr"]{opacity:1}
.nav__burger{display:none;align-items:center;gap:10px;padding:13px 0 13px 14px;margin:-13px 0 -13px -14px}   /* 44px tall hit area, same look */
.nav__burger span{display:block;width:22px;height:1px;background:currentColor;transition:transform .35s var(--out)}
.nav__burger span+span{margin-left:-32px;transform:translateY(4px)}
.nav__burger span:first-child{transform:translateY(-3px)}
.menu-open .nav__burger span:first-child{transform:rotate(45deg)}
.menu-open .nav__burger span+span{transform:rotate(-45deg)}
body.menu-open .nav{color:var(--ink)}
.menu{position:fixed;inset:0;z-index:95;background:var(--paper);display:grid;place-items:center;opacity:0;visibility:hidden;transition:opacity .35s var(--ease),visibility 0s .35s}
.menu-open .menu{opacity:1;visibility:visible;transition:opacity .35s var(--ease)}
.menu nav{display:flex;flex-direction:column;align-items:center;gap:10px}
.menu a{font-family:var(--serif);font-size:clamp(2.4rem,10vw,3.4rem);line-height:1.15;color:var(--ink);text-decoration:none;opacity:0;transform:translateY(14px);
  transition:opacity .45s var(--ease),transform .6s var(--out);transition-delay:calc(.05s + var(--i) * 45ms)}
.menu-open .menu a{opacity:1;transform:none}
.menu-open{overflow:hidden}

/* ---------- opening scene: the frosted night window ---------- */
.hero{position:relative;min-height:100svh;display:grid;place-items:center;overflow:hidden;background:var(--night);color:var(--ivory);isolation:isolate}
.hero__frost{position:absolute;inset:0;width:100%;height:100%;z-index:0;touch-action:pan-y}
/* her photo under the frost (hero-frost.js sizes it and shows it once the frost has drawn; hidden for every other look) */
.hero__stage{position:absolute;z-index:0;left:0;top:0;width:100%;height:100%;opacity:0;pointer-events:none;contain:layout style}
.hero__stage.on{opacity:1}
.hero__stage img{display:block;width:100%;height:100%;user-select:none;-webkit-user-drag:none}
.hero__spark{position:absolute;inset:0;pointer-events:none}
.hero__fallback{position:absolute;inset:0;z-index:-1;background:radial-gradient(120% 80% at 50% 35%,#1a2a45 0%,#0c1424 55%,#060a12 100%),url(assets/texture-band.jpg) center/cover}
.hero::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;background:radial-gradient(90% 70% at 50% 45%,transparent 40%,rgba(5,8,15,.6) 100%)}
.hero__inner{position:relative;z-index:2;width:100%;max-width:960px;padding:clamp(76px,11svh,120px) var(--gutter-r) clamp(96px,14svh,140px) var(--gutter-l);text-align:center;pointer-events:none}
.hero__inner a,.hero__inner button{pointer-events:auto}
.hero__eyebrow{color:var(--frost);opacity:0;transform:translateY(10px);transition:opacity .9s var(--ease) .1s,transform 1s var(--out) .1s}
.hero__sig{margin:0 0 clamp(14px,3svh,32px);font-weight:400}
.is-entered .hero__eyebrow,.is-gated.sig-done .hero__eyebrow{opacity:.85;transform:none}
.gate{max-width:500px;margin:0 auto;transition:opacity .5s var(--ease),transform .6s var(--out),visibility 0s .6s}
.gate__title{font-size:11px;font-weight:500;letter-spacing:.3em;text-transform:uppercase;color:var(--frost);margin:0 0 12px}
.gate__text{font-size:14px;line-height:1.75;color:rgba(245,241,234,.72);margin:0 0 26px}
.gate__actions{display:flex;justify-content:center;align-items:center;gap:14px;margin-bottom:24px}
.gate .lang{color:var(--frost)}
.gate > *{opacity:0;transform:translateY(10px);transition:opacity .6s var(--ease),transform .7s var(--out)}
.sig-done .gate > *{opacity:1;transform:none}
.sig-done .gate > *:nth-child(2){transition-delay:.06s}
.sig-done .gate > *:nth-child(3){transition-delay:.12s}
.sig-done .gate > *:nth-child(4){transition-delay:.18s}
.is-entered .gate{opacity:0;transform:translateY(-8px);visibility:hidden;position:absolute;left:0;right:0}
.hero__after{display:none}
.is-entered .hero__after{display:block}
.hero__tagline{font-family:var(--serif);font-size:clamp(1.7rem,3.3vw,2.7rem);line-height:1.15;margin:0 0 16px;color:var(--ivory)}
.hero__sub{font-size:15px;line-height:1.75;color:rgba(245,241,234,.74);max-width:30rem;margin:0 auto 34px;opacity:0;transform:translateY(10px);transition:opacity .8s var(--ease) .35s,transform .9s var(--out) .35s}
.hero__after .btn{opacity:0;transform:translateY(10px);transition:opacity .8s var(--ease) .5s,transform .9s var(--out) .5s,background-color .25s}
.hero-in .hero__sub,.hero-in .hero__after .btn{opacity:1;transform:none}
.status{display:flex;width:max-content;align-items:center;gap:10px;margin:24px auto 0;font-size:10.5px;font-weight:500;letter-spacing:.26em;text-transform:uppercase;color:var(--frost);opacity:0;transition:opacity .8s var(--ease) .7s}
.hero-in .status{opacity:.75}
.status i{position:relative;width:6px;height:6px}
.status i::before,.status i::after{content:"";position:absolute;inset:0;border-radius:50%}
.status i::after{background:var(--frost)}   /* the dot */
.status i::before{background:rgb(203,213,223);opacity:0;animation:pulse 2.6s infinite}   /* the ring that spreads from it: a disc under the dot, scaled up and faded out (transform + opacity: the compositor does it, no repaint every frame) */
@keyframes pulse{0%{transform:scale(1);opacity:.5}70%,100%{transform:scale(4);opacity:0}}   /* the dot is 6px: scale 4 = the old 9px spread */
/* the endless animations stop while they cannot be seen (app.js adds .off when their host leaves the screen, .tab-hidden when the tab is hidden) */
.status i.off::before,.hero__scroll i.off,.leaf--orn.off,.tab-hidden .status i::before,.tab-hidden .hero__scroll i,.tab-hidden .leaf--orn{animation-play-state:paused}
.hero__hint{position:absolute;z-index:2;left:0;right:0;bottom:88px;text-align:center;margin:0;font-size:10.5px;font-weight:500;letter-spacing:.28em;text-transform:uppercase;color:var(--frost);opacity:0;transition:opacity 1s var(--ease) 1s;pointer-events:none}
.hero-in .hero__hint{opacity:.5}
.hero.no-frost .hero__hint{display:none}   /* no WebGL (or the context was lost): nothing can be wiped, so no "clear the frost" line */
.hint--touch{display:none}
@media (hover:none){.hint--fine{display:none}.hint--touch{display:inline}}
.hero__scroll{position:absolute;z-index:2;left:50%;bottom:26px;width:1px;height:44px;background:rgba(203,213,223,.2);overflow:hidden;opacity:0;transition:opacity .8s 1.2s}
.hero-in .hero__scroll{opacity:1}
.hero__scroll i{position:absolute;inset:0;background:var(--ivory);transform:translateY(-100%);animation:drip 2.2s var(--ease) infinite}
@keyframes drip{0%{transform:translateY(-100%)}60%,100%{transform:translateY(100%)}}

/* ---------- photo frames ---------- */
.frame{position:relative;margin:0;overflow:hidden;background:var(--paper-3)}
.frame__art{position:absolute;inset:-5%;background-size:cover;background-position:center;transition:transform 1.1s var(--out)}
.frame__art:not([style*="url"]){background:linear-gradient(160deg,var(--paper-2) 0%,var(--paper-3) 100%)}
.frame:hover .frame__art{transform:scale(1.03)}
.frame__frost{display:none}
.frame__label{position:absolute;left:18px;right:18px;bottom:16px;display:flex;gap:12px;align-items:baseline;font-size:12px;line-height:1.5;color:var(--stone)}
.frame__label b{font-weight:500;letter-spacing:.18em;color:var(--ink)}
.frame.has-photo .frame__label{display:none}
.frame--portrait{aspect-ratio:4/5}

/* ---------- introduction ---------- */
.intro{padding-top:clamp(96px,13vw,180px)}
.intro__grid{max-width:var(--wrap);margin:0 auto;display:grid;grid-template-columns:minmax(0,5fr) minmax(0,6fr);gap:clamp(40px,7vw,112px);align-items:center}
.intro__grid.no-portrait{grid-template-columns:1fr;max-width:780px}
.letter{font-family:var(--serif);font-size:clamp(1.3rem,1.7vw,1.55rem);line-height:1.5;color:var(--ink-soft);margin-top:2rem;max-width:33rem}
.letter p{margin:0 0 1em}
.letter__sign{margin-top:1rem}
.glance{max-width:var(--wrap);margin:clamp(64px,9vw,128px) auto 0;display:grid;grid-template-columns:repeat(var(--cols,6),1fr);gap:1px;background:var(--rule);border-top:1px solid var(--rule);border-bottom:1px solid var(--rule)}
.glance div{padding:24px 10px;text-align:center;background:var(--paper)}
.glance dt{font-size:10.5px;font-weight:500;letter-spacing:.24em;text-transform:uppercase;color:var(--stone);margin-bottom:6px}
.glance dd{margin:0;font-family:var(--serif);font-size:1.45rem;line-height:1.2}

/* ---------- gallery: editorial, photo-led ---------- */
.editorial{max-width:var(--wrap);margin:0 auto;display:grid;grid-template-columns:repeat(12,1fr);column-gap:clamp(12px,2vw,28px);row-gap:clamp(36px,6vw,96px);align-items:start}
.editorial .frame[data-ed="0"]{grid-column:1/span 7;aspect-ratio:4/5}
.editorial .frame[data-ed="1"]{grid-column:9/span 4;aspect-ratio:3/4;align-self:end}
.editorial .frame[data-ed="2"]{grid-column:2/span 4;aspect-ratio:3/4}
.editorial .frame[data-ed="3"]{grid-column:7/span 6;aspect-ratio:4/5;margin-top:clamp(40px,10vw,160px)}
.editorial .frame[data-ed="4"]{grid-column:1/span 5;aspect-ratio:4/5}
.editorial .frame[data-ed="5"]{grid-column:7/span 5;aspect-ratio:3/4;margin-top:clamp(30px,7vw,110px)}
.editorial .frame[data-ed="solo"]{grid-column:3/span 8;aspect-ratio:4/5}
/* photos arrive with a slow curtain wipe */
.frame.curtain{background:transparent}
.frame.curtain .frame__art{clip-path:inset(100% 0 0 0);transition:clip-path 1.25s cubic-bezier(.77,0,.18,1),transform 1.7s var(--out)}
.frame.curtain.in .frame__art{clip-path:inset(0 0 0 0)}
.frame.curtain .frame__label{opacity:0;transition:opacity .6s var(--ease) .7s}
.frame.curtain.in .frame__label{opacity:1}
.editorial .frame.curtain .frame__art{transform:scale(1.16)}
.editorial .frame.curtain.in .frame__art{transform:scale(1)}
.editorial .frame.curtain.in:hover .frame__art{transform:scale(1.03);transition:clip-path 1.25s cubic-bezier(.77,0,.18,1),transform 1s var(--out)}

/* ---------- kind words ---------- */
.words{text-align:center}
.words__list{display:grid;max-width:980px;margin:0 auto}
.words__quote{grid-area:1/1;margin:0;opacity:0;transform:translateY(8px);transition:opacity .9s var(--ease),transform 1s var(--out);pointer-events:none}
.words__quote.on{opacity:1;transform:none;pointer-events:auto}
.words__quote p{font-family:var(--serif);font-size:clamp(1.9rem,4vw,3.4rem);line-height:1.15;letter-spacing:-.01em;margin:0 0 1.6rem}
.words__quote footer{font-size:11px;font-weight:500;letter-spacing:.26em;text-transform:uppercase;color:var(--stone)}

.leaf{fill:none;stroke:var(--ink);stroke-width:2;stroke-linecap:round}
.leaf--orn{width:30px;height:30px;margin:0 auto 24px;display:block;transform-origin:50% 90%;animation:quake 5s ease-in-out infinite}
@keyframes quake{0%,70%,100%{transform:rotate(0)}74%{transform:rotate(7deg)}78%{transform:rotate(-6deg)}82%{transform:rotate(4deg)}86%{transform:rotate(-2deg)}}

/* ---------- favourites: a compact row ---------- */
.favs{padding-top:clamp(64px,8vw,112px);padding-bottom:clamp(64px,8vw,112px)}
.favs .section__head{margin-bottom:clamp(28px,4vw,48px)}
.favs .display{font-size:clamp(2rem,3.8vw,3.2rem)}
.favs__grid{max-width:var(--wrap);margin:0 auto;padding:0;list-style:none;display:grid;grid-template-columns:repeat(6,1fr);gap:28px 20px}
.fav__icon{display:block;width:26px;height:26px;margin:0 0 12px;fill:none;stroke:var(--ink);stroke-width:1.3;stroke-linecap:round;stroke-linejoin:round;opacity:.85;transition:transform .5s var(--out)}
.fav:hover .fav__icon{transform:translateY(-3px) rotate(-4deg)}
.fav h3{font-family:var(--serif);font-weight:400;font-size:1.18rem;line-height:1.2;margin:0 0 4px}
.fav p{margin:0;font-size:13px;line-height:1.5;color:var(--stone)}
.gifts{max-width:var(--wrap);margin:clamp(32px,4vw,48px) auto 0;padding-top:22px;border-top:1px solid var(--rule);font-family:var(--serif);font-size:clamp(1.1rem,1.5vw,1.3rem);line-height:1.45;color:var(--ink-soft);text-align:center}

/* ---------- engagements ---------- */
.rates__list{max-width:var(--wrap);margin:0 auto;padding:0;list-style:none;counter-reset:r;border-top:1px solid var(--rule)}
.rates__list li{display:flex;align-items:baseline;gap:18px;padding:24px 0;border-bottom:1px solid var(--rule);counter-increment:r}
.rates__list li::before{content:counter(r,decimal-leading-zero);font-size:11px;font-weight:500;letter-spacing:.18em;color:var(--stone);width:32px;flex:none}
.r__name{font-family:var(--serif);font-size:clamp(1.55rem,2.6vw,2.2rem);line-height:1.12}
.r__name small{display:block;font-family:var(--sans);font-size:14px;color:var(--stone);margin-top:6px;line-height:1.5}
.r__dur{font-size:11px;font-weight:500;letter-spacing:.2em;text-transform:uppercase;color:var(--stone);white-space:nowrap}
.r__line{flex:1;height:1px;align-self:center;background:repeating-linear-gradient(90deg,var(--rule) 0 2px,transparent 2px 7px);transform:scaleX(0);transform-origin:left;transition:transform 1s var(--out)}
.rates__list li.in .r__line{transform:none}
.r__val{font-family:var(--serif);font-size:clamp(1.35rem,2vw,1.75rem);white-space:nowrap}
.rates__notes{max-width:var(--wrap);margin:40px auto 0;display:grid;grid-template-columns:1fr 1fr;gap:24px 64px}
.rates__notes p{margin:0;font-size:15px;line-height:1.75;color:var(--ink-soft)}
.rates__notes b{display:block;font-size:10.5px;font-weight:500;letter-spacing:.26em;text-transform:uppercase;color:var(--stone);margin-bottom:6px}

/* ---------- etiquette ---------- */
.acc{max-width:880px;margin:0 auto;border-top:1px solid var(--rule)}
.acc details{border-bottom:1px solid var(--rule)}
.acc summary{list-style:none;display:flex;justify-content:space-between;align-items:center;gap:20px;padding:26px 0;font-family:var(--serif);font-size:clamp(1.45rem,2.4vw,2rem);line-height:1.15;cursor:pointer}
.acc summary::-webkit-details-marker{display:none}
.acc summary i{position:relative;width:14px;height:14px;flex:none}
.acc summary i::before,.acc summary i::after{content:"";position:absolute;left:0;right:0;top:50%;height:1px;background:var(--ink);transition:transform .35s var(--out)}
.acc summary i::after{transform:rotate(90deg)}
.acc details[open] summary i::after{transform:rotate(0)}
.acc__body p{margin:0 0 26px;max-width:44rem;font-size:15.5px;line-height:1.8;color:var(--ink-soft)}

/* ---------- form ---------- */
.form{max-width:720px;margin:0 auto}
.form__steps{display:flex;justify-content:space-between;margin:0 0 12px;padding:0;list-style:none;font-size:10.5px;font-weight:500;letter-spacing:.22em;text-transform:uppercase;color:var(--stone)}
.form__steps li{opacity:1;transition:opacity .25s,color .25s}
.form__steps li.on{opacity:1;color:var(--ink)}
.form__track{height:1px;background:var(--rule);margin-bottom:40px;overflow:hidden}
.form__track i{display:block;height:100%;width:25%;background:var(--ink);transition:width .5s var(--out)}
.step{border:0;margin:0;padding:0;display:none}
.step.on{display:block;animation:stepIn .45s var(--out)}
@keyframes stepIn{from{opacity:0;transform:translateX(14px)}to{opacity:1;transform:none}}
.field{display:block;margin-bottom:24px}
.field > span{display:block;font-size:10.5px;font-weight:500;letter-spacing:.22em;text-transform:uppercase;color:var(--stone);margin-bottom:6px}
.field small{text-transform:none;letter-spacing:.02em}
.field input,.field select,.field textarea{width:100%;background:transparent;border:0;border-bottom:1px solid var(--rule);color:var(--ink);font-family:var(--serif);font-size:1.4rem;padding:8px 0 10px;border-radius:0;transition:border-color .2s;-webkit-appearance:none;appearance:none}
.field select{background-image:linear-gradient(45deg,transparent 50%,var(--ink) 50%),linear-gradient(135deg,var(--ink) 50%,transparent 50%);background-position:calc(100% - 11px) 55%,calc(100% - 6px) 55%;background-size:5px 5px;background-repeat:no-repeat}
.field textarea{resize:vertical;font-size:1.25rem;line-height:1.55}
.field input:focus,.field select:focus,.field textarea:focus{outline:0;border-bottom-color:var(--ink)}
.field input[type="date"],.field input[type="time"]{color-scheme:light}
.field.bad input,.field.bad select,.field.bad textarea{border-bottom-color:var(--err,#a5432f)}
.field__row{display:grid;grid-template-columns:2fr 1fr;gap:24px}
.field__help{font-size:14px;color:var(--stone);margin:0 0 16px}
/* small guidance under (or inside) a field: where to meet, which days are listed, what to write in the notes */
.field__hint{display:block;margin:0 0 24px;font-size:14px;line-height:1.6;color:var(--stone);text-transform:none;letter-spacing:0;font-weight:400;text-wrap:pretty}
.field > .field__hint{margin:0 0 8px}
.field:has(+ .field__hint:not([hidden])){margin-bottom:8px}
.field__row:has(+ .field__hint:not([hidden])) > .field{margin-bottom:8px}
.field__hint:has(+ .f-switch:not([hidden])){margin-bottom:0}
.field select{text-overflow:ellipsis;padding-right:24px}
#f-city{font-size:clamp(1.05rem,4.6vw,1.4rem)}   /* on a 320px phone the longest hotel options (about 285px of text) are still cut with an ellipsis; the hint under the field says the same */
#f-datesel,#f-duration{font-size:clamp(1.05rem,5.8vw,1.4rem)}   /* the date and length labels fit on a phone from 320px up (full size from about 386px) */
.field select:disabled{color:var(--stone);cursor:default}
.f-switch{display:inline-flex;justify-content:flex-start;min-height:44px;margin:0 0 20px;padding:0;font-size:14px;font-weight:400;letter-spacing:0;text-transform:none;text-decoration:underline;text-underline-offset:4px;text-align:left}
.choices{display:grid;gap:8px;margin-bottom:26px}
.choice{display:flex;align-items:center;gap:14px;padding:15px 18px;border:1px solid var(--rule);cursor:pointer;transition:border-color .2s,background-color .2s}
.choice input{accent-color:var(--ink)}
.choice:has(input:checked){border-color:var(--ink);background:var(--paper-2)}
.choice span{font-family:var(--serif);font-size:1.25rem}
.check{display:flex;gap:12px;align-items:flex-start;font-size:14px;color:var(--ink-soft);cursor:pointer}
.check input{margin-top:4px;accent-color:var(--ink)}
.form__nav{display:flex;justify-content:space-between;align-items:center;margin-top:32px}
.form__nav [data-next],.form__nav [data-submit]{margin-left:auto}
.form__error{min-height:1.4em;margin:16px 0 0;font-size:13px;color:var(--err,#a5432f)}
.sent{max-width:620px;margin:0 auto;text-align:center}
.sent .display{font-size:clamp(2.4rem,5vw,3.6rem);margin-bottom:12px}
.sent p:not(.display){font-size:15px;color:var(--ink-soft)}
.sent__actions{display:flex;justify-content:center;gap:14px;margin-top:24px}

/* ---------- footer ---------- */
.foot{padding:clamp(76px,9vw,128px) var(--gutter-r) 36px var(--gutter-l);text-align:center;border-top:1px solid var(--rule)}
.foot__cols{max-width:1100px;margin:0 auto;display:grid;grid-template-columns:repeat(3,1fr);gap:26px;font-size:13px;line-height:1.85;color:var(--stone)}
.foot__cols p{margin:0}
.foot__cols a{text-decoration:none;font-weight:500;letter-spacing:.2em;text-transform:uppercase;font-size:11px;color:var(--ink)}
.foot kbd{font-family:var(--sans);font-size:11px;border:1px solid var(--rule);padding:1px 6px}
.foot__copy{margin:52px 0 0;font-size:10.5px;font-weight:500;letter-spacing:.22em;text-transform:uppercase;color:var(--stone)}

/* ---------- lightbox ---------- */
.lightbox{border:0;padding:0;background:transparent;color:var(--ivory);width:min(94vw,1280px);max-width:none;max-height:none;overflow:visible}   /* big: the photo is limited by the screen height, not by a 700px box */
.lightbox::backdrop{background:rgba(12,11,10,.9)}
.lightbox__art{width:100%;height:min(82vh,calc(94vw * 1.5));height:min(82svh,calc(94vw * 1.5));margin:0 auto;background-size:contain;background-repeat:no-repeat;background-position:center bottom}   /* the photo sits on the bottom of its box, so the caption is always right under it */
.lightbox[style*="--a"] .lightbox__art{width:min(100%,calc(82vh * var(--a)));width:min(100%,calc(82svh * var(--a)));height:auto;aspect-ratio:var(--a)}   /* when the page passes the photo's shape (--a), the box is exactly that shape */
.lightbox__art:not([style*="url"]){height:auto;aspect-ratio:4/5;width:min(100%,calc(82svh * .8))}
.lightbox__art:not([style*="url"]){background:linear-gradient(160deg,var(--paper-2) 0%,var(--paper-3) 100%)}
/* Oct 20: the twinkle layer (sparkle.js) is a canvas inside the picture's box: it needs a positioned parent, and it never prints */
.lightbox__art{position:relative}
.sparkle{pointer-events:none}
@media print{.sparkle{display:none !important}}
.lightbox__label{font-size:12px;letter-spacing:.14em;text-align:center;color:rgba(245,241,234,.75);margin:12px 0 0}
.lightbox__label:empty{display:none}
.lightbox__close{position:fixed;top:8px;right:max(8px,env(safe-area-inset-right));width:48px;height:48px;display:grid;place-items:center;font-size:32px;line-height:1;color:var(--ivory)}   /* a 48px target; the cross stays where it was */
.lightbox[open]{animation:lbIn .35s var(--out)}
@keyframes lbIn{from{opacity:0;transform:scale(.985)}to{opacity:1;transform:none}}

/* ---------- responsive ---------- */
@media (max-width:980px){
  .nav__links,.nav__cta,.nav__right > .lang{display:none}
  .nav__burger{display:inline-flex}
  .intro__grid{grid-template-columns:1fr}
  .intro__portrait{max-width:460px;width:100%;margin:0 auto}
  .glance{grid-template-columns:repeat(min(3,var(--cols,6)),1fr)}
  .favs__grid{grid-template-columns:repeat(3,1fr)}
  .rates__notes{grid-template-columns:1fr}
  .foot__cols{grid-template-columns:1fr}
}
@media (max-width:600px){
  .glance{grid-template-columns:repeat(min(2,var(--cols,6)),1fr)}
  .favs__grid{grid-template-columns:1fr 1fr;gap:24px 16px}
  .editorial{grid-template-columns:1fr;row-gap:28px}
  .editorial .frame{grid-column:auto!important;grid-row:auto!important;margin-top:0!important;width:88%}
  .editorial .frame:nth-child(even){justify-self:end;width:74%}
  .rates__list li{flex-wrap:wrap;gap:4px 14px}
  .rates__list li::before{width:100%}
  .r__line{display:none}
  .r__val{margin-left:auto}
  .field__row{grid-template-columns:1fr}
  .form__steps li:not(.on){display:none}
  .gate__actions{flex-direction:column;gap:4px}
  .hero__hint{bottom:80px}
  .hero__eyebrow{font-size:10px;letter-spacing:.18em}
}

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion:reduce){
  html:not(.motion) *,html:not(.motion) *::before,html:not(.motion) *::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;transition-delay:0s!important;scroll-behavior:auto!important}
  html:not(.motion) [data-split] .wi{transform:none}
  html:not(.motion) .reveal{opacity:1;transform:none}
  html:not(.motion) .frame.curtain .frame__art{clip-path:none}
  html:not(.motion) .frame.curtain .frame__label{opacity:1}
}

/* ---------- Oct 11: the incall space + availability & booking ---------- */
.incall .section__head,.avail .section__head{margin-bottom:0}
.incall__body{max-width:40rem}
.avail__cal{max-width:960px;margin:clamp(32px,5vw,56px) auto 0;padding:0}
.avail__cal img{display:block;width:100%;height:auto;border-radius:var(--cal-radius,6px);box-shadow:var(--cal-shadow,0 18px 50px rgba(0,0,0,.28))}   /* a look can set a softer shadow */
.avail__actions{display:flex;flex-wrap:wrap;gap:14px 22px;justify-content:center;margin-top:clamp(28px,4vw,44px)}
@media (max-width:600px){
  .glance[data-n="8"]{grid-template-columns:repeat(2,1fr)}
  .avail__cal{margin-left:calc(var(--gutter-l) * -1);margin-right:calc(var(--gutter-r) * -1)}   /* the calendar runs edge to edge on a phone, so its small type is as large as it can be */
  .avail__cal img{border-radius:0}
}
.avail__tip{margin-top:12px;text-align:center;font-size:12.5px;letter-spacing:.04em;color:var(--stone)}

/* Oct 11: no prices yet -> no "On request" on every row (one note under the list says it) */
.rates__list.no-prices .r__line,.rates__list.no-prices .r__val{display:none}
/* phone menu: the private gallery link sits a little apart, then a language switch */
.menu .menu__private{font-size:clamp(1.6rem,6vw,2.1rem)!important;opacity:.85;margin-top:14px;padding-block:8px}
.menu .lang--menu{margin-top:14px;padding:16px 0;font:500 12px/1 var(--sans);letter-spacing:.2em;text-transform:uppercase;color:var(--cream,#fff)}
.menu .lang--menu span{color:var(--cream,#fff)}
.menu .lang--menu i{background:var(--jade,currentColor)}

/* ---------- Oct 11: her month, drawn in the site's own style (tokens only, so it follows every look) ----------
   One marker everywhere (legend, grid, phone list): filled dot = available all day, half dot = part of the day,
   dashed ring = pre-booked pop-ins, faint ring = unavailable */
.cal{max-width:1060px;margin:clamp(32px,5vw,56px) auto 0;text-align:left;--dot:9px}
.cal__head{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:14px 28px;padding-bottom:18px}
.cal__month{margin:0;font:400 clamp(2rem,3.6vw,2.9rem)/1 var(--serif);letter-spacing:-.02em;color:var(--ink)}
.cal__month em{font-style:italic;color:var(--accent)}
.cal__legend{display:flex;flex-wrap:wrap;gap:8px 22px;margin:0;padding:0;list-style:none;font-size:12.5px;color:var(--stone)}
.cal__legend li{display:flex;align-items:center;gap:9px}
.cal__legend li::before,.cal__lab::before,.cal__list li::before{content:"";flex:none;display:inline-block;width:var(--dot);height:var(--dot);box-sizing:border-box;border-radius:50%;border:1px solid var(--accent);background:transparent}
.cal .is-open::before,.cal .is-open .cal__lab::before{background:var(--accent)}
.cal .is-part::before,.cal .is-part .cal__lab::before{background:linear-gradient(90deg,var(--accent) 50%,transparent 50%)}
.cal .is-popin::before,.cal .is-popin .cal__lab::before{border-style:dashed}
.cal .is-off::before,.cal .is-off .cal__lab::before{border-color:var(--stone);opacity:.55}
.cal__grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:1px;background:var(--rule);border:1px solid var(--rule)}
.cal__dow{padding:12px 6px;background:var(--paper);text-align:center;font:600 10.5px/1 var(--sans);letter-spacing:.2em;text-transform:uppercase;color:var(--stone)}
.cal__pad{background:var(--paper)}
.cal__day{display:flex;flex-direction:column;gap:8px;min-height:clamp(84px,9vw,104px);padding:11px 11px 12px;background:var(--paper)}
.cal__num{font:400 1.2rem/1 var(--serif);color:var(--ink)}
.cal__lab{display:flex;align-items:baseline;gap:7px;font:italic 400 clamp(.86rem,1.1vw,1rem)/1.2 var(--serif);color:var(--ink-soft)}
.cal__lab::before{transform:translateY(-1px)}
.cal__day.is-open{background:var(--paper-2)}
.cal__day.is-open .cal__lab{color:var(--accent)}
.cal__day.is-popin .cal__lab{color:var(--stone)}
.cal__day.is-off .cal__lab{align-items:center;font:600 9.5px/1.3 var(--sans);font-style:normal;letter-spacing:.16em;text-transform:uppercase;color:var(--stone)}
.cal__day.is-past > *{opacity:.35}
.cal__day.is-today{box-shadow:inset 0 0 0 2px var(--accent)}
.cal__list{display:none;margin:4px 0 0;padding:0;list-style:none}
.cal__list li{display:flex;align-items:center;gap:12px;padding:14px 0;border-top:1px solid var(--rule)}
.cal__list li:last-child{border-bottom:1px solid var(--rule)}
.cal__when{font:400 1.1rem/1.2 var(--serif);color:var(--ink);white-space:nowrap}
.cal__what{margin-left:auto;text-align:right;font-size:14px;color:var(--ink-soft)}
.cal__list li.is-open .cal__what{color:var(--accent)}
.cal__list li.is-off .cal__when,.cal__list li.is-off .cal__what{color:var(--stone)}
@media (max-width:930px){   /* below this the day cells are too narrow for "Unavailable" (it spilled across the cell border at 700-830px), so the month becomes the list */
  .cal__grid{display:none}
  .cal__list{display:block}
  .cal__legend{font-size:12px;gap:8px 16px}
}

/* =====================================================================================================================
   Oct 13 polish pass (layout, wraps, tap targets). Everything here is look-neutral: it uses the page's own tokens, so the
   default look (atelier, blush) and ?palette=noir both follow it.
   ===================================================================================================================== */

/* ---------- no lone last words ---------- */
/* "balance" evens out short blocks (browsers balance up to about six lines and leave longer ones alone); "pretty" is the gentler fix for long ones */
.hero__tagline,.hero__sub,.hero__eyebrow,.gifts,.fav p,.btn,.letter p,.incall__body p,.section__note,.r__name small,.field__help,.gate__text,.sent p:not(.display),.acc__body p,.rates__notes p{text-wrap:balance}
.foot__cols p{text-wrap:pretty}

/* ---------- navigation ---------- */
/* Six links in two languages need more room than 980px gives (French crowds first), so the menu button takes over up to 1220px.
   Above that the links share the bar evenly; from 1340px there is room for them to sit exactly on the page's own centre line. */
@media (max-width:1220px){
  .nav__links,.nav__cta,.nav__right > .lang{display:none}
  .nav__burger{display:inline-flex}
}
@media (min-width:1340px){
  .nav{display:grid;grid-template-columns:minmax(max-content,1fr) auto minmax(max-content,1fr)}
  .nav__logo{justify-self:start}
  .nav__right{justify-self:end}
}
/* the "Private gallery" link: same type as its neighbours, set apart by a hairline */
.nav__links .nav__private,.nav__links a[href^="/p/"]{margin-left:clamp(4px,.6vw,10px)}
.nav__links .nav__private::before,.nav__links a[href^="/p/"]::before{content:"";position:absolute;left:calc(clamp(18px,2.6vw,38px) / -2 - clamp(4px,.6vw,10px) / 2);top:50%;width:1px;height:12px;background:currentColor;opacity:.35;transform:translateY(-50%)}
/* over the opening scene the Contact button keeps its outline on hover (the generic ghost hover would turn it ink-dark on a dark photo) */
body[data-theme="night"] .nav__cta:hover{border-color:currentColor;background:rgba(255,255,255,.14)}

/* ---------- quick exit for touch screens (a phone has no Esc key); desktops keep the Esc-Esc shortcut. index.html has two: #qx on the page and #qx-lb inside the photo viewer (class .qx; .qexit is accepted too) ---------- */
.qx,.qexit{position:fixed;right:max(12px,env(safe-area-inset-right));bottom:max(12px,env(safe-area-inset-bottom));z-index:99;display:inline-flex;align-items:center;justify-content:center;gap:.6em;
  min-height:44px;min-width:44px;padding:0 18px;border:1px solid rgba(255,255,255,.4);border-radius:0;background:var(--band,var(--wine-deep,#4A302B));background:color-mix(in srgb,var(--band,var(--wine-deep,#4A302B)) 90%,transparent);
  color:var(--cream,#FBF1EC);font:600 10.5px/1 var(--sans);letter-spacing:.24em;text-transform:uppercase;text-decoration:none;white-space:nowrap;
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);box-shadow:0 8px 22px -10px rgba(26,16,15,.55);-webkit-tap-highlight-color:transparent}
.qx:active,.qexit:active{background:var(--band,var(--wine-deep,#2A1B1A))}
.qx:focus-visible,.qexit:focus-visible{outline:2px solid var(--jade,#F3C9CD);outline-offset:3px}
@media (hover:hover) and (pointer:fine){.qx,.qexit{display:none}}
body.is-gated .qx,body.is-gated .qexit{display:none}   /* the age gate has its own Leave button */

/* ---------- the opening scene on screens of different heights ---------- */
/* The "move / touch to clear the frost" line is pinned near the bottom of the scene, so the block above it keeps clear of it
   (the status line used to be covered at 721-780px tall). On a short screen there is no room for it at all, so it steps aside. */
@media (min-height:701px){.hero__inner{padding-bottom:clamp(132px,14svh,150px)}}
@media (max-height:700px){.hero__hint{display:none}}

/* The age gate must always be reachable: the page cannot scroll while it is up, so on a short screen the scene tightens up
   instead (a small phone upright, then a phone on its side, where the gate and the signature sit side by side). */
@media (max-height:620px){
  .hero__inner{padding-top:64px;padding-bottom:80px}
  .hero__eyebrow{margin-bottom:12px}
  .hero__sig{margin-bottom:10px}
  .sig--hero{width:min(78vw,720px,34svh)}
  .gate__title{margin-bottom:8px}
  .gate__text{font-size:13px;line-height:1.6;margin-bottom:16px}
  .gate__actions{flex-direction:row;gap:12px;margin-bottom:10px}
}
@media (orientation:landscape) and (max-height:520px){
  .hero__inner{max-width:900px;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);column-gap:clamp(24px,5vw,56px);align-items:center;padding:56px var(--gutter-r) 50px var(--gutter-l)}   /* 50px below: the last line (the status) stays above the fixed Leave button */
  .hero__eyebrow{grid-column:1;grid-row:1;margin:0 0 10px;align-self:end}
  .hero__sig{grid-column:1;grid-row:2;margin:0;align-self:start}
  .sig--hero{width:min(100%,340px,56svh)}
  .gate,.hero__after{grid-column:2;grid-row:1 / span 2}
  .gate__title{margin-bottom:8px}
  .gate__text{font-size:13px;line-height:1.6;margin-bottom:14px}
  .gate__actions{flex-direction:row;gap:12px;margin-bottom:8px}
  .hero__tagline{font-size:clamp(1.35rem,3.2vw,1.75rem);margin-bottom:8px}
  .hero__sub{font-size:13.5px;line-height:1.5;margin-bottom:14px}
  .hero__after .btn{min-height:44px}
  .status{margin-top:10px}
  .hero__scroll{display:none}
}

/* Oct 20: small phones upright. The fixed "Leave" button sits in the bottom-right corner, so the status line rises above it (the
   French one is longer), the hero words clear the signature above them, and the thank-you buttons stop short of it. */
@media (hover:none) and (max-height:700px) and (orientation:portrait){
  .hero__sub{margin-bottom:22px}
  .status{margin-top:12px}
  .qx{padding:0 14px;letter-spacing:.18em}
}
@media (hover:none) and (max-height:620px) and (orientation:portrait){.is-entered .hero__inner{padding-top:72px}}   /* the first line clears the signature in the top bar */
@media (hover:none) and (max-height:560px) and (orientation:portrait){   /* the shortest phones (Safari toolbars showing): the same words in a little less height, so the status line stays clear of the corner button */
  .sig--hero{width:min(78vw,720px,28svh)}
  .hero__inner{padding-bottom:68px}
  .is-entered .hero__inner{padding-top:70px}
  .hero__sub{font-size:14px;line-height:1.6;margin-bottom:16px}
  .hero__tagline{margin-bottom:10px}
}
@media (hover:none){html{scroll-padding-bottom:72px}}
@media (hover:none) and (max-width:600px){.sent{padding-bottom:112px}}

/* ---------- rates: an odd number of notes starts with a full-width one, so a note never sits orphaned beside a hole ---------- */
.rates__notes > p:first-child:nth-last-child(odd){grid-column:1 / -1}

/* ---------- footer: the third column is a tidy stack (Contact / Private gallery / EN | FR) ----------
   The " · " separators are plain text between the links, so they are zeroed rather than left to wrap (and stranded at a line end). */
.foot__cols p:has(.lang--foot){font-size:0;line-height:0;display:flex;flex-direction:column;align-items:center}
.foot__cols p:has(.lang--foot) .sep{display:none}
.foot__cols p:has(.lang--foot) > a{font-size:11px;line-height:1.7;padding:3px 0;text-align:center;text-wrap:balance}
.foot__cols p:has(.lang--foot) > a[href^="/p/"]{letter-spacing:.15em}   /* the long one: a touch tighter, so it sits on one line from about 1000px up */
.foot__cols p:has(.lang--foot) > .lang--foot{font-size:11px;line-height:1.7;padding:6px 0}
@media (min-width:981px){.foot__cols{grid-template-columns:1fr 1fr 1.45fr}}
@media (max-width:980px),(pointer:coarse){
  .foot__cols p:has(.lang--foot) > a,.foot__cols p:has(.lang--foot) > .lang--foot{display:flex;align-items:center;justify-content:center;min-height:44px;min-width:44px;padding:0 14px}
}
/* the language switch on the age gate: a 44px target that costs no layout room */
.lang--gate{padding:13px 18px;margin:-13px -18px}

/* ---------- phones ---------- */
@media (max-width:600px){
  .hero__eyebrow{font-size:clamp(9px,2.55vw,10px);letter-spacing:.1em}   /* "Private companion · Ottawa · English & français" fits on one line on any phone; the French needs 350px+, else it wraps in balance */
}
@media (max-width:340px){
  .hero__after .btn{letter-spacing:.14em;padding-inline:20px}   /* the French call to action fits on one line at 320 */
}

/* Oct 13: an unticked required box is marked like a bad field (colour + an icon, never colour alone) */
.choice.bad{border-color:var(--err,#a5432f)}
.choice.bad > span,.check.bad > span{color:var(--err,#a5432f)}
.choice.bad > span::before,.check.bad > span::before{content:"!";display:inline-grid;place-items:center;width:15px;height:15px;margin-right:9px;border-radius:50%;background:var(--err,#a5432f);color:#fff;font:700 10px/1 var(--sans);letter-spacing:0;vertical-align:2px}
.check.bad{outline:1px solid var(--err,#a5432f);outline-offset:6px}
/* long copy: avoid one-word last lines (balance does nothing on blocks this long) */
.letter p,.incall__body p,.acc__body p,.section__note,.rates__notes p{text-wrap:pretty}
