/* ==========================================================================
   THE MURNANS , house style
   The Bear & the Tiger · Brooklyn, New York
   --------------------------------------------------------------------------
   1. Tokens          5. Reveal system     9.  Timeline
   2. Reset & base    6. Nav & footer      10. Tables & drinks
   3. Typography      7. Hero & pour       11. The day
   4. Layout          8. Home sections     12. Lightbox, cursor, motion
   ========================================================================== */

/* 1 ── TOKENS ──────────────────────────────────────────────────────────── */

/* Palette sampled straight out of the Bear & Tiger artwork: dusty blue ground,
   cream, khaki, butter-gold sparkles, dusty rose mat, and heavy black ink. */

:root {
  /* Dawn , warm cream, the default */
  --paper:        #F7F0E0;
  --paper-2:      #EFE4CB;
  --paper-3:      #E2D4B4;
  --ink:          #14110D;
  --ink-2:        #4B443A;
  --ink-3:        #6E6455;

  /* their blue */
  --blue:         #5E9BB4;
  --blue-deep:    #3D7B95;

  --sage-600:     #4E7A62;
  --sage-500:     #7FA08A;
  --sage-300:     #B3CDB8;

  --glacier:      #C3DEE8;

  --khaki:        #B49C6C;
  --gold:         #F0CE84;
  --rose:         #DCC0BE;
  --coral:        #E2604F;

  --wine:         #7A2436;
  --wine-2:       #A03A50;
  --wine-3:       #C1687C;

  --brass:        #B8913F;   /* decorative: rules, stars, hairlines */
  --brass-ink:    #7E611F;   /* the same gold, dark enough to read small */
  --brass-2:      #F0D89C;

  /* the four colors the maps color states in, no two neighbours alike */
  --quilt-1:      #5E9BB4;
  --quilt-2:      #F0CE84;
  --quilt-3:      #7FA08A;
  --quilt-4:      #D88A7E;

  --line:         color-mix(in srgb, var(--ink) 16%, transparent);
  --line-2:       color-mix(in srgb, var(--ink) 9%, transparent);

  /* the ink keyline that everything in the artwork is drawn with */
  /* the deep ground under the dark bands: oxblood, not green */
  --deep:         #3A1621;
  --deep-ink:     #F9F2E4;
  --deep-ink-2:   #E0C9CB;
  --deep-ink-3:   #BBA0A5;

  /* The footer's own ground, kept apart from --deep so the band of links
     above it can stay oxblood while the footer goes gold. A soft butter
     rather than the full gold: a whole page width of the strong one is a lot
     of yellow. Safari samples this for the bar the search box sits in, in
     assets/js/safari-bar.js. */
  --footer-bg:     #F3DEAF;
  --footer-ink:    #14110D;
  --footer-ink-2:  #4A3D1F;
  --footer-ink-3:  #5C4A26;
  --footer-brass:  #6B4E13;
  --footer-hover:  #7A2436;
  --footer-line:   #14110D2b;
  --footer-invert: 0;

  /* dusk's own ground, named here so the toggle's dot can show the color it
     switches to without repeating the number */
  --dusk-paper:   #0B1F25;

  --keyline:      2px solid var(--ink);
  --r-lg:         20px;
  --r-md:         14px;
  --r-sm:         10px;

  --shadow-sm: 0 1px 2px color-mix(in srgb, var(--ink) 7%, transparent),
               0 6px 18px color-mix(in srgb, var(--ink) 7%, transparent);
  --shadow-lg: 0 2px 4px color-mix(in srgb, var(--ink) 6%, transparent),
               0 18px 50px color-mix(in srgb, var(--ink) 14%, transparent);

  /* Type , chunky and a bit wonky, to sit next to a chunky, wonky ink line */
  --display: "Gloock", "Hoefler Text", "Times New Roman", Georgia, serif;
  --hand:    "Caveat", "Bradley Hand", "Segoe Script", cursive;
  --script:  var(--hand);
  --sans:    "Space Grotesk", "Helvetica Neue", Inter, system-ui, sans-serif;

  /* Motion */
  --ease:      cubic-bezier(.22, 1, .36, 1);
  --ease-soft: cubic-bezier(.4, 0, .2, 1);

  /* Measure */
  /* the fixed nav's height once it shrinks on scroll; sticky things clear it */
  /* each page carries one accent from the palette; set via body[data-page] */
  --page: var(--blue);
  --page-ink: var(--blue-deep);   /* the same accent, dark enough to set text in */
  --nav-h: 56px;
  --gutter: clamp(1.25rem, 5vw, 5rem);
  --maxw: 1440px;
  --rule: 1px;

  --art-invert: 0;
  color-scheme: light;
}

[data-theme="dusk"] {
  /* Dusk , the cellar */
  --paper:        var(--dusk-paper);
  --paper-2:      #102B32;
  --paper-3:      #16383F;
  --ink:          #F4EBD6;
  --ink-2:        #BFC9C1;
  --ink-3:        #A0AEA8;

  --blue:         #77B4CC;
  --blue-deep:    #5E9BB4;
  --sage-500:     #9BC0A6;
  --sage-300:     #BFDBC6;
  --glacier:      #BFDCE3;

  --khaki:        #CDB689;
  --gold:         #F4DCA2;
  --rose:         #E6D0CE;
  --coral:        #F0806F;

  --wine:         #D07E90;
  --wine-2:       #DE9AA8;
  --wine-3:       #EBBCC5;

  --brass:        #D9B876;
  --brass-ink:    #E7C88A;
  --brass-2:      #F2DEB0;

  /* deep shades in dusk, so cream type and lines stay readable on them */
  --quilt-1:      #3D7B95;
  --quilt-2:      #B8571E;
  --quilt-3:      #4E7A62;
  --quilt-4:      #9A4E86;

  --line:   color-mix(in srgb, var(--ink) 18%, transparent);
  --line-2: color-mix(in srgb, var(--ink) 10%, transparent);

  --shadow-sm: 0 1px 2px #0004, 0 6px 18px #0005;
  --shadow-lg: 0 2px 4px #0004, 0 18px 50px #0007;

  /* the footer in dusk: the page's own dark teal, a shade off it rather than
     a block sitting on top of it */
  --footer-bg:     #0E2327;
  --footer-ink:    #F4EBD6;
  --footer-ink-2:  #C7D5CD;
  --footer-ink-3:  #9DB0A8;
  --footer-brass:  #F2DEB0;
  --footer-hover:  #F2DEB0;
  --footer-line:   #ffffff26;
  --footer-invert: 1;

  --art-invert: 1;
  color-scheme: dark;
}

/* Per-page accent. --page tints marks and dots, --page-ink sets type. */
body[data-page="home"]  { --page: var(--blue);     --page-ink: var(--blue-deep); }
body[data-page="story"] { --page: var(--sage-500); --page-ink: var(--sage-600); }
body[data-page="table"] { --page: var(--gold);     --page-ink: var(--brass-ink); }
body[data-page="day"]   { --page: var(--coral);    --page-ink: #A8391F; }
body[data-page="honeymoon"]  { --page: var(--rose);  --page-ink: var(--wine-2); }
body[data-page="highlights"] { --page: var(--khaki); --page-ink: var(--brass-ink); }
/* on the dark ground the light accent already reads, so type uses it directly */
[data-theme="dusk"] body[data-page] { --page-ink: var(--page); }

/* 2 ── RESET & BASE ────────────────────────────────────────────────────── */

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

/* No color of its own: the body's paper propagates up to the canvas, so the
   page behind the designs is cream in dawn and dark teal in dusk, and the
   0.6s theme transition comes with it. The phone browser bar is held at the
   footer's oxblood by assets/js/safari-bar.js, not by a color back here. */
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  font-weight: 350;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  transition: background-color .6s var(--ease-soft), color .6s var(--ease-soft);
}

/* A whisper of paper grain , keeps large flat fields from going dead. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  opacity: .04;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}
[data-theme="dusk"] body::before { mix-blend-mode: screen; opacity: .05; }

img, svg { display: block; max-width: 100%; }
/* The UA gives <figure> a 40px side margin , it would eat 80px off every photo. */
figure, blockquote, dl, dd { margin: 0; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

::selection { background: var(--gold); color: #14110D; }
[data-theme="dusk"] ::selection { background: var(--gold); color: #14110D; }

:focus-visible {
  outline: 2px solid var(--brass);
  outline-offset: 3px;
  border-radius: 2px;
}

/* 3 ── TYPOGRAPHY ──────────────────────────────────────────────────────── */

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 400;
  letter-spacing: -.005em;
  line-height: 1.04;
  margin: 0;
  text-wrap: balance;
}

.t-mega {
  /* capped against viewport height too, so the hero never outgrows one screen */
  font-size: min(clamp(3.2rem, 12.5vw, 11.5rem), 21vh);
  line-height: .92;
  letter-spacing: -.018em;
}
.t-xl   { font-size: clamp(2.4rem, 6.2vw, 5.2rem); line-height: 1.0; letter-spacing: -.012em; }
.t-lg   { font-size: clamp(1.9rem, 3.6vw, 3.1rem); line-height: 1.1; letter-spacing: -.008em; }
.t-md   { font-size: clamp(1.35rem, 2.1vw, 1.85rem); line-height: 1.22; letter-spacing: -.004em; }
.t-sm   { font-size: 1.075rem; line-height: 1.32; letter-spacing: 0; }

.amp {
  font-family: var(--display);
  font-weight: 400;
  color: var(--coral);
  letter-spacing: 0;
  padding-inline: .03em;
}

.eyebrow {
  font-family: var(--sans);
  font-size: .69rem;
  font-weight: 500;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0;
}
.eyebrow--brass { color: var(--brass-ink); }

.lede {
  font-size: clamp(1.075rem, 1.55vw, 1.32rem);
  line-height: 1.62;
  color: var(--ink-2);
  max-width: 46ch;
  font-weight: 350;
  text-wrap: pretty;
}
p { margin: 0 0 1.1em; text-wrap: pretty; }
/* a longer intro gets a wider measure, balanced so no line ends on one word */
.lede--wide { max-width: 64ch; text-wrap: balance; }
p:last-child { margin-bottom: 0; }

.serif-note {
  font-family: var(--hand);
  font-weight: 500;
  font-size: clamp(1.7rem, 3.2vw, 2.7rem);
  line-height: 1.24;
  color: var(--ink);
  letter-spacing: .002em;
}

.num {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2.7rem, 5.6vw, 4.6rem);
  line-height: .95;
  letter-spacing: -.02em;
  color: var(--blue-deep);
}
[data-theme="dusk"] .num { color: var(--blue); }

.tag {
  font-size: .66rem;
  letter-spacing: .22em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--ink-3);
}

/* Inline link with a growing rule */
.link {
  display: inline-block;
  position: relative;
  color: var(--ink);
  padding-bottom: 2px;
}
.link::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: currentColor;
  transform-origin: right;
  transform: scaleX(1);
  transition: transform .5s var(--ease);
  opacity: .45;
}
.link:hover::after { transform-origin: left; animation: rule-swipe .6s var(--ease); opacity: 1; }
@keyframes rule-swipe { 0% { transform: scaleX(1); transform-origin: right; } 49% { transform: scaleX(0); transform-origin: right; } 50% { transform: scaleX(0); transform-origin: left; } 100% { transform: scaleX(1); transform-origin: left; } }

/* 4 ── LAYOUT ──────────────────────────────────────────────────────────── */

.shell { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }
.shell--narrow { max-width: 980px; }

section { position: relative; }
.band { padding-block: clamp(4.5rem, 11vw, 10rem); }
.band--tight { padding-block: clamp(3rem, 6vw, 5rem); }
.band--deep {
  background: var(--deep);
  color: var(--deep-ink);
  --ink: var(--deep-ink);
  --ink-2: var(--deep-ink-2);
  --ink-3: var(--deep-ink-3);
  --brass-ink: #EBC97E;
  --line: #ffffff26;
  --line-2: #ffffff16;
  --art-invert: 1;
  --wine: #E39AA8;
  --brass: #EBC97E;
}
.band--paper2 { background: var(--paper-2); }

.rule { height: var(--rule); background: var(--line); border: 0; margin: 0; }
.rule--brass { background: linear-gradient(90deg, transparent, var(--brass) 18%, var(--brass) 82%, transparent); opacity: .55; }

.grid { display: grid; gap: clamp(1.5rem, 3vw, 3rem); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--12 { grid-template-columns: repeat(12, minmax(0, 1fr)); }
.stack { display: flex; flex-direction: column; }
.gap-xs { gap: .5rem } .gap-s { gap: 1rem } .gap-m { gap: 1.75rem } .gap-l { gap: 3rem }

/* Section heading: number + rule + title */
.sec-head { display: grid; grid-template-columns: auto 1fr; gap: 1.25rem 2rem; align-items: baseline; margin-bottom: clamp(2.5rem, 5vw, 4.5rem); }
.sec-head__idx {
  font-family: var(--sans); font-size: .7rem; letter-spacing: .24em;
  color: var(--brass-ink); padding-top: .55em;
  display: flex; align-items: center; gap: .55rem;
}
.sec-head__idx::before {
  content: "";
  width: 9px; height: 9px;
  flex: none;
  border-radius: 50%;
  background: var(--page);
  box-shadow: 0 0 0 1.5px var(--ink);
}
.sec-head__body { display: grid; gap: 1.1rem; }

/* A section head whose intro sits beside the heading rather than under it,
   so a long intro fills the row instead of leaving the right side empty. */
.sec-head--split .sec-head__body {
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: end;
}
.sec-head--split .lede { max-width: 44ch; }
@media (max-width: 900px) {
  .sec-head--split .sec-head__body { grid-template-columns: 1fr; gap: 1.1rem; }
}

/* Buttons */
.btn {
  --btn-fg: var(--paper);
  --btn-bg: var(--deep);
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: .85rem;
  padding: 1.05em 1.9em;
  border-radius: 999px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: .17em;
  text-transform: uppercase;
  overflow: hidden;
  isolation: isolate;
  border: var(--keyline);
  box-shadow: 5px 5px 0 var(--ink);
  transition: transform .35s var(--ease), box-shadow .35s var(--ease), color .45s var(--ease-soft);
  will-change: transform;
}
.btn:hover { transform: translate(3px, 3px); }
.btn:active { transform: translate(5px, 5px); box-shadow: 0 0 0 var(--ink); }
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  /* fixed deep wine: the hover text is always white, in both themes */
  background: #7A2436;
  transform: translateY(101%);
  transition: transform .55s var(--ease);
}
.btn:hover { box-shadow: 2px 2px 0 var(--ink); }
.btn:hover::before { transform: translateY(0); }
.btn:hover { color: #fff; }
.btn__arrow { transition: transform .5s var(--ease); }
.btn:hover .btn__arrow { transform: translateX(4px); }

/* Secondary: same geometry as .btn so a pair sits on one baseline, but the
   keyline and the offset shadow are dialed back so it reads as the quieter
   of the two. Hover fills it in like any other button. */
.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: currentColor;
  border-color: color-mix(in srgb, currentColor 34%, transparent);
  box-shadow: 5px 5px 0 color-mix(in srgb, currentColor 20%, transparent);
  opacity: .82;
}
.btn--ghost:hover { opacity: 1; border-color: var(--ink); }
[data-theme="dusk"] .btn { --btn-bg: var(--gold); --btn-fg: #14110D; box-shadow: 5px 5px 0 var(--ink); }
[data-theme="dusk"] .btn--ghost { --btn-bg: transparent; --btn-fg: currentColor; }

/* A row of calls to action: side by side while the row has space for the
   pair, stacked when it hasn't. Whether it fits depends on what the buttons
   say, not on the width of the screen, so initButtonRows() in site.js
   measures each row and hangs .is-stacked on it. A stack is set to one width
   and centered, so neither button reads as the smaller of the two. */
.btns { display: flex; flex-wrap: wrap; gap: 1rem; }
.btns--center { justify-content: center; }

.btns.is-stacked, .since__btns.is-stacked, .yclose__btns.is-stacked {
  flex-direction: column;
  align-items: center;
}
.btns.is-stacked > .btn,
.since__btns.is-stacked > .btn,
.yclose__btns.is-stacked > .btn { width: 100%; max-width: 34rem; justify-content: center; }

/* Without the script, and on any screen too narrow to hold a pair whatever
   they say, the same stack. */
@media (max-width: 520px) {
  .btns, .since__btns, .yclose__btns { flex-direction: column; align-items: center; }
  .btns > .btn, .since__btns > .btn, .yclose__btns > .btn { width: 100%; max-width: 34rem; justify-content: center; }
}
/* They stack from the width where the longest pair on the site would have
   wrapped anyway: a wrapped row is a stack whose two buttons happen not to
   match. Capped so the stack never stretches into a pair of banners, and the
   6px of room on the right is for the offset print under each button, which
   would otherwise hang into the margin. */
/* Brand marks (the little SVG drawings) */
.mark { width: 44px; height: 44px; object-fit: contain; filter: invert(var(--art-invert)); opacity: .9; }
.mark--lg { width: 74px; height: 74px; }

/* 5 ── REVEAL SYSTEM ───────────────────────────────────────────────────── */

[data-reveal] { --d: 0ms; }

[data-reveal="up"] {
  opacity: 0;
  transform: translate3d(0, 26px, 0);
  transition: opacity .95s var(--ease) var(--d), transform .95s var(--ease) var(--d);
}
[data-reveal="up"].is-in { opacity: 1; transform: none; }

[data-reveal="fade"] { opacity: 0; transition: opacity 1.1s var(--ease-soft) var(--d); }
[data-reveal="fade"].is-in { opacity: 1; }

/* Curtain wipe for imagery.
   The clip lives on the CHILDREN, never on the observed element itself , an
   element clipped to zero area never intersects, so it would never reveal. */
[data-reveal="wipe"] > * {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1.15s var(--ease) var(--d);
}
[data-reveal="wipe"].is-in > * { clip-path: inset(0 0 0 0); }
[data-reveal="wipe"] > *:nth-child(2) { transition-delay: calc(var(--d) + 130ms); }
[data-reveal="wipe"] > *:nth-child(3) { transition-delay: calc(var(--d) + 260ms); }

/* Hairline that draws itself */
[data-reveal="rule"] { transform: scaleX(0); transform-origin: left; transition: transform 1.15s var(--ease) var(--d); }
[data-reveal="rule"].is-in { transform: scaleX(1); }

/* Word-by-word masked rise (applied by JS to [data-split]) */
.w { display: inline-block; overflow: hidden; vertical-align: top; padding-bottom: .14em; margin-bottom: -.14em; }
.wi {
  display: inline-block;
  transform: translate3d(0, 115%, 0);
  transition: transform 1.05s var(--ease) var(--wd, 0ms);
  will-change: transform;
}
.is-in .wi, .wi.is-in { transform: none; }

/* 6 ── NAV & FOOTER ────────────────────────────────────────────────────── */

.progress {
  position: fixed;
  inset: 0 0 auto 0;
  height: 2px;
  z-index: 90;
  background: transparent;
  pointer-events: none;
}
.progress__bar {
  height: 100%;
  width: 100%;
  transform: scaleX(0);
  transform-origin: left;
  background: linear-gradient(90deg, var(--blue), var(--sage-500) 28%, var(--gold) 52%, var(--coral) 76%, var(--wine));
}

.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 80;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.15rem var(--gutter);
  transition: padding .5s var(--ease);
}
/* The frosted bar is a layer of its own, never the nav itself: backdrop-filter
   on the nav would make it the containing block for everything fixed inside
   it, and the full-screen menu below would collapse into the bar's own box. */
.nav::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  backdrop-filter: blur(16px) saturate(1.3);
  -webkit-backdrop-filter: blur(16px) saturate(1.3);
  box-shadow: 0 1px 0 var(--line-2);
  opacity: 0;
  transition: opacity .5s var(--ease-soft);
  pointer-events: none;
}
.nav.is-stuck::before { opacity: 1; }
.nav.is-stuck { padding-block: .8rem; }

.brand { display: flex; align-items: center; gap: .75rem; }
.brand__glyph {
  width: 34px; height: 34px;
  flex: none;
  border-radius: 50%;
  display: block;
  object-fit: cover;
  box-shadow: 0 0 0 1px var(--line);
  transition: transform .6s var(--ease), box-shadow .4s;
}
.brand:hover .brand__glyph { transform: scale(1.07); box-shadow: 0 0 0 1px var(--brass), 0 3px 14px color-mix(in srgb, var(--ink) 20%, transparent); }
.nav.is-stuck .brand__glyph { width: 30px; height: 30px; }
.brand__name {
  font-family: var(--display);
  font-size: 1.1rem;
  letter-spacing: .005em;
  white-space: nowrap;
}

.nav__links { display: flex; align-items: center; gap: clamp(1rem, 2.4vw, 2.4rem); }
.nav__link {
  position: relative;
  font-size: .74rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--ink-2);
  padding-block: .35rem;
  /* one line, always: a label on two lines sets the whole bar crooked */
  white-space: nowrap;
  transition: color .35s;
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--brass);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform .5s var(--ease);
}
.nav__link:hover { color: var(--ink); }
.nav__link:hover::after, .nav__link[aria-current="page"]::after { transform: scaleX(1); transform-origin: left; }
.nav__link[aria-current="page"] { color: var(--ink); }

.theme-toggle {
  position: relative;
  width: 58px; height: 30px;
  border-radius: 999px;
  box-shadow: inset 0 0 0 1px var(--line);
  display: grid;
  place-items: center;
  flex: none;
}
.theme-toggle__knob {
  position: absolute;
  top: 3px; left: 3px;
  width: 24px; height: 24px;
  border-radius: 50%;
  /* the dot shows the ground it switches to, which is dusk's deep teal, not
     the oxblood of the footer */
  background: var(--dusk-paper);
  transition: transform .6s var(--ease), background-color .5s;
}
[data-theme="dusk"] .theme-toggle__knob { transform: translateX(28px); background: var(--brass-2); }
.theme-toggle__ico { position: absolute; font-size: .62rem; opacity: .5; }
.theme-toggle__ico--sun { left: 9px; } .theme-toggle__ico--moon { right: 9px; }

.nav__tail { display: none; }
.nav__tail a { color: inherit; }
.nav__tail a:hover { color: var(--wine); }

.nav__burger { display: none; width: 34px; height: 34px; place-items: center; position: relative; z-index: 2; }
.nav__burger span { display: block; width: 20px; height: 1px; background: var(--ink); position: relative; transition: transform .45s var(--ease), opacity .3s; }
.nav__burger span::before, .nav__burger span::after {
  content: ""; position: absolute; left: 0; width: 20px; height: 1px; background: var(--ink);
  transition: transform .45s var(--ease);
}
.nav__burger span::before { top: -6px; } .nav__burger span::after { top: 6px; }
body.menu-open .nav__burger span { background: transparent; }
body.menu-open .nav__burger span::before { transform: translateY(6px) rotate(45deg); }
body.menu-open .nav__burger span::after { transform: translateY(-6px) rotate(-45deg); }

.footer {
  background: var(--footer-bg);
  color: var(--footer-ink);
  padding-block: clamp(3.5rem, 7vw, 6rem) 2.25rem;
  --ink: var(--footer-ink);
  --ink-2: var(--footer-ink-2);
  --ink-3: var(--footer-ink-3);
  --brass-ink: var(--footer-brass);
  --line: var(--footer-line);
  --line-2: var(--footer-line);
  --art-invert: var(--footer-invert);
}
.footer a { color: var(--footer-ink); }
.footer__top { display: grid; grid-template-columns: 1.2fr 1fr 1fr; gap: 2.5rem; align-items: start; }
.footer__word { font-family: var(--display); font-size: clamp(3rem, 11vw, 9rem); line-height: .95; letter-spacing: -.015em; color: var(--footer-ink); opacity: .96; margin-block: clamp(2.5rem, 6vw, 4.5rem) 1.75rem; }
.footer__meta { display: flex; flex-wrap: wrap; gap: 1.25rem 2.5rem; justify-content: space-between; font-size: .74rem; letter-spacing: .16em; text-transform: uppercase; color: var(--footer-ink-3); }
.footer__cols { display: grid; gap: .55rem; }
.footer__cols a { color: var(--footer-ink-2); font-size: .82rem; transition: color .3s; }
.footer__cols a:hover { color: var(--footer-hover); }
/* The ampersand was coral on oxblood. On gold the coral goes soft, so dawn
   takes the wine instead; dusk's dark green keeps the coral. */
.footer .amp { color: #7A2436; }
[data-theme="dusk"] .footer .amp { color: var(--coral); }

/* 7 ── HERO & THE POUR ─────────────────────────────────────────────────── */

.hero { position: relative; min-height: 100svh; display: flex; flex-direction: column; justify-content: center; padding-top: 6rem; padding-bottom: 1.5rem; overflow: hidden; }

/* soft aurora wash , calm, not loud */
.hero__wash { position: absolute; inset: -20% -10% auto -10%; height: 120%; pointer-events: none; z-index: 0; opacity: .55; }
.hero__wash::before, .hero__wash::after {
  content: ""; position: absolute; border-radius: 50%; filter: blur(90px);
}
.hero__wash::before { width: 54vw; height: 54vw; left: -8vw; top: 6vw; background: radial-gradient(circle, var(--glacier), transparent 68%); }
.hero__wash::after  { width: 46vw; height: 46vw; right: -6vw; top: 22vw; background: radial-gradient(circle, var(--rose), transparent 68%); }
[data-theme="dusk"] .hero__wash { opacity: .3; }

.hero__inner { position: relative; z-index: 2; display: grid; gap: clamp(1.1rem, 2.4vh, 2.25rem); }
.hero__title { position: relative; }
.hero__sub { display: flex; flex-wrap: wrap; gap: 1rem 2.5rem; align-items: baseline; justify-content: space-between; }
/* wider than the 46ch default so the bio sets on two lines, balanced so neither is a runt */
.hero__sub .lede { max-width: 58ch; text-wrap: balance; }

/* The stage: two figures + the pour slider */
.stage { position: relative; display: grid; grid-template-columns: 1fr auto 1fr; align-items: end; gap: clamp(.5rem, 3vw, 3rem); margin-top: clamp(.5rem, 1.5vh, 1.5rem); }

.fig { position: relative; justify-self: center; cursor: pointer; transition: transform .7s var(--ease); }
.fig:hover { transform: translateY(-10px); }
/* Color sits BEHIND the line art, so the ink stays crisp on top of it. */
/* Sized by height so the pair always fits the viewport, whatever its shape. */
.fig__layer { position: relative; isolation: isolate; height: min(clamp(190px, 40vh, 470px), 44vw); }
/* The ink stays black in both themes , it is the artist's line, not a UI color. */
.fig__out {
  position: relative;
  z-index: 2;
  height: 100%; width: auto;
}
.fig__fillwrap {
  position: absolute; inset: 0;
  z-index: 1;
  clip-path: inset(calc(100% - var(--pour, 0%)) 0 0 0);
  transition: clip-path .12s linear;
}
.fig__fill { height: 100%; width: auto; }
/* In dusk, a ghost of the color sits under the line so black ink still reads
   on the dark ground , and it looks like a drawing waiting to be filled in. */
.fig__ghost {
  position: absolute; left: 0; top: 0;
  z-index: 0;
  height: 100%; width: auto;
  opacity: 0;
  transition: opacity .6s var(--ease-soft);
  pointer-events: none;
}
[data-theme="dusk"] .fig__ghost { opacity: .34; }
[data-theme="dusk"] .fig__layer::before {
  content: "";
  position: absolute;
  inset: -10% -14%;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(58% 52% at 50% 48%, color-mix(in srgb, var(--glacier) 22%, transparent), transparent 70%);
  filter: blur(26px);
  pointer-events: none;
}
/* the meniscus , a faint line where the color stops */
.fig__line {
  position: absolute; left: -4%; right: -4%;
  z-index: 3;
  bottom: var(--pour, 0%);
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--brass), transparent);
  opacity: 0;
  transition: bottom .12s linear, opacity .4s;
  pointer-events: none;
}
.stage.is-pouring .fig__line { opacity: .85; }

.fig__name {
  --name-w: clamp(90px, 9vw, 130px);
  position: absolute;
  /* the script PNG has empty space under the letters; this sets the baseline at the feet */
  bottom: calc(5% - var(--name-w) * .05);
  width: var(--name-w);
  filter: invert(var(--art-invert));
  opacity: .0;
  transition: opacity .5s var(--ease), transform .6s var(--ease);
  pointer-events: none;
}
/* beside the feet, facing each other across the ampersand, so the script never
   sits on the drawing or under the bio card on the outer side. The drawings end
   around 72% of their image width at the feet, so 76% leaves a small gap; the
   multipliers cancel the empty margin at the side of each script PNG. */
.fig--bear  .fig__name { left: calc(76% - var(--name-w) * .137); }
.fig--tiger .fig__name { right: calc(76% - var(--name-w) * .16); }
.fig:hover .fig__name { opacity: .9; transform: translateY(-4px); }

.fig__card {
  position: absolute;
  top: 8%;
  width: max(210px, 15vw);
  padding: 1rem 1.15rem;
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: blur(10px);
  box-shadow: inset 0 0 0 1px var(--line), var(--shadow-sm);
  border-radius: 2px;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .5s var(--ease), transform .5s var(--ease);
  pointer-events: none;
}
.fig--bear  .fig__card { right: 84%; text-align: right; }
.fig--tiger .fig__card { left: 84%; }
.fig:hover .fig__card { opacity: 1; transform: none; }
.fig__card p { font-size: .78rem; line-height: 1.5; color: var(--ink-2); margin: .35rem 0 0; }

.stage__center { display: grid; place-items: center; gap: 1rem; align-self: center; }
.stage__amp { font-family: var(--display); font-size: clamp(3.4rem, 8vw, 6.5rem); color: var(--coral); line-height: 1; transition: transform .8s var(--ease); }
.stage:hover .stage__amp { transform: scale(1.08); }

/* the pour control */
.pour { display: grid; gap: .5rem; justify-items: center; margin-top: clamp(.75rem, 2vh, 1.75rem); }
.pour__label { display: flex; align-items: center; gap: .8rem; font-size: .66rem; letter-spacing: .26em; text-transform: uppercase; color: var(--ink-3); }
.pour__val { font-family: var(--display); font-size: .95rem; letter-spacing: -.01em; color: var(--brass-ink); min-width: 3.2ch; text-align: right; }

.pour__track { position: relative; width: min(440px, 82vw); }
.pour__range {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 34px; background: transparent; display: block; cursor: grab; margin: 0;
}
.pour__range:active { cursor: grabbing; }
.pour__range::-webkit-slider-runnable-track { height: 34px; background: transparent; }
.pour__range::-moz-range-track { height: 34px; background: transparent; }
.pour__range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 26px; height: 26px; margin-top: 4px;
  border-radius: 50%;
  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--brass), 0 3px 12px #0002;
  transition: transform .3s var(--ease), box-shadow .3s;
}
.pour__range::-moz-range-thumb {
  width: 26px; height: 26px; border: 0;
  border-radius: 50%;
  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--brass), 0 3px 12px #0002;
}
.pour__range:hover::-webkit-slider-thumb { transform: scale(1.14); box-shadow: inset 0 0 0 1px var(--brass), 0 4px 18px #0003; }
.pour__rail {
  position: absolute; left: 13px; right: 13px; top: 50%; height: 3px;
  transform: translateY(-50%);
  border-radius: 2px;
  background: var(--line);
  pointer-events: none;
  overflow: hidden;
}
.pour__rail::after {
  content: ""; position: absolute; inset: 0 auto 0 0;
  width: var(--pour, 0%);
  background: linear-gradient(90deg, var(--blue), var(--sage-500) 40%, var(--gold) 72%, var(--coral));
  transition: width .12s linear;
}


/* 8 ── HOME SECTIONS ───────────────────────────────────────────────────── */

/* Ticker of small loves */
.ticker { overflow: hidden; padding-block: 1.1rem; background: var(--blue); border-block: var(--keyline); mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent); }
.ticker__row { display: flex; width: max-content; animation: ticker 46s linear infinite; }
.ticker:hover .ticker__row { animation-play-state: paused; }
/* The band is always the illustration blue, so the ink is always dark. */
.ticker__item {
  display: flex; align-items: center; gap: 1.2rem; padding-inline: 1.2rem;
  font-family: var(--sans); font-weight: 500; font-size: .78rem;
  letter-spacing: .24em; text-transform: uppercase;
  color: #14110D; white-space: nowrap;
}
.ticker__item::after {
  content: "";
  width: 15px; height: 15px;
  background: var(--gold);
  clip-path: polygon(50% 0%, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0% 50%, 40% 40%);
}
.ticker__item:hover { color: #6B1F2E; transform: translateY(-2px) rotate(-2deg); }
@keyframes ticker { to { transform: translateX(-50%); } }

/* ── DRAWN LIKE THE ILLUSTRATIONS ──────────────────────────────────────────
   The artwork is heavy black ink over flat color that sits a hair off
   register. Three devices carry that into the interface: a chunky ink
   keyline, a color block nudged out from behind it, and generous curves. */

.inked {
  position: relative;
  border: var(--keyline);
  border-radius: var(--r-lg);
  background: var(--paper);
  transition: transform .5s var(--ease);
}
.inked::before {                     /* the fill, printed slightly off */
  content: "";
  position: absolute;
  inset: -2px;
  z-index: -1;
  border-radius: inherit;
  background: var(--off, var(--blue));
  transform: translate(8px, 8px);
  transition: transform .5s var(--ease);
}
.inked:hover { transform: translate(3px, 3px); }
.inked:hover::before { transform: translate(2px, 2px); }

/* Cards across the site take the ink treatment */
.table-card, .glass, .memory__card, .chapter, .fact, .portrait__mat, .shot, .memory__pic {
  border-radius: var(--r-md);
}
/* The color sits behind as a hard offset shadow. A pseudo-element would be
   clipped by these cards' own overflow and stacking contexts. */
.table-card, .glass, .memory__card {
  position: relative;
  border: var(--keyline);
  background: var(--paper);
  box-shadow: 7px 7px 0 var(--off, var(--blue));
  transition: transform .45s var(--ease), box-shadow .45s var(--ease);
}
.table-card:hover, .glass:hover, .memory__card:hover {
  box-shadow: 3px 3px 0 var(--off, var(--blue));
}
.glass:hover, .glass.is-full { transform: translate(4px, 4px); }

/* Chapter doors clip their hover fill, so they take the off-register color
   as a hard shadow instead of a block behind. */
.chapter { box-shadow: 8px 8px 0 var(--off, var(--blue)); transition: color .5s var(--ease-soft), transform .45s var(--ease), box-shadow .45s var(--ease); }
.chapter:hover { transform: translate(4px, 4px); box-shadow: 4px 4px 0 var(--off, var(--blue)); }
.chapters .chapter:nth-child(1) { --off: var(--blue); }
.chapters .chapter:nth-child(2) { --off: var(--gold); }
.chapters .chapter:nth-child(3) { --off: var(--rose); }
.chapters .chapter:nth-child(4) { --off: var(--coral); }

.fact { box-shadow: 6px 6px 0 var(--off, var(--blue)); }
.facts .fact:nth-child(1) { --off: var(--blue); }
.facts .fact:nth-child(2) { --off: var(--sage-500); }
.facts .fact:nth-child(3) { --off: var(--gold); }
.facts .fact:nth-child(4) { --off: var(--rose); }

.tables .table-card:nth-child(3n+1) { --off: var(--blue); }
.tables .table-card:nth-child(3n+2) { --off: var(--sage-500); }
.tables .table-card:nth-child(3n+3) { --off: var(--rose); }
.pours .glass:nth-child(1) { --off: var(--gold); }
.pours .glass:nth-child(2) { --off: var(--khaki); }
.memory__card { --off: var(--blue); }

/* Sticker: a rotated, ink-lined badge */
.sticker {
  display: inline-block;
  padding: .5em 1.1em;
  border: var(--keyline);
  border-radius: 999px;
  background: var(--gold);
  color: #14110D;
  font-family: var(--sans);
  font-weight: 500;
  font-size: .7rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  line-height: 1.1;
  transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(-3.5deg);
  transition: transform .5s var(--ease);
}
.sticker:hover { transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(2deg) scale(1.04); }

/* ── CELEBRATION ───────────────────────────────────────────────────────── */

/* Sparks , the gold stars from the logo, thrown into the air */
.spark {
  position: fixed;
  z-index: 400;
  pointer-events: none;
  will-change: transform, opacity;
  animation: spark-fly var(--dur, 1100ms) cubic-bezier(.16, .62, .3, 1) forwards;
}
@keyframes spark-fly {
  0%   { transform: translate3d(0, 0, 0) scale(.2) rotate(0deg); opacity: 0; }
  14%  { opacity: 1; }
  30%  { transform: translate3d(calc(var(--dx) * .55), calc(var(--dy) * .8), 0) scale(1) rotate(120deg); opacity: 1; }
  100% { transform: translate3d(var(--dx), calc(var(--dy) + 190px), 0) scale(.25) rotate(var(--rot, 300deg)); opacity: 0; }
}

/* Speech bubbles on the two characters */
/* Speech bubble. On wide screens it takes the same outer slot as the info
   card (and the card steps aside); on narrow screens it sits above the head. */
.fig__say {
  position: absolute;
  top: 6%;
  width: max(190px, 14vw);
  padding: .95rem 1.15rem;
  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--line), var(--shadow-lg);
  font-family: var(--hand);
  font-weight: 600;
  font-size: 1.35rem;
  line-height: 1.18;
  color: var(--ink);
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px) scale(.95);
  transition: opacity .35s var(--ease), transform .45s var(--ease), visibility .35s;
  z-index: 6;
}
.fig--bear  .fig__say { right: 84%; text-align: right; border-radius: 14px 14px 4px 14px; }
.fig--tiger .fig__say { left: 84%;  text-align: left;  border-radius: 14px 14px 14px 4px; }
.fig__say::after {
  content: "";
  position: absolute;
  bottom: 18%;
  width: 12px; height: 12px;
  background: var(--paper);
  transform: rotate(45deg);
}
.fig--bear  .fig__say::after { right: -6px; box-shadow: inset -1px 1px 0 var(--line); }
.fig--tiger .fig__say::after { left: -6px;  box-shadow: inset 1px -1px 0 var(--line); }
.fig__say.is-said { opacity: 1; visibility: visible; transform: none; }
.fig.is-talking .fig__card { opacity: 0 !important; }

@media (max-width: 860px) {
  .fig__say {
    left: 50%; right: auto;
    top: auto; bottom: calc(100% + .6rem);
    width: min(62vw, 260px);
    text-align: center;
    transform: translateX(-50%) translateY(8px) scale(.95);
    border-radius: 14px;
  }
  .fig--bear .fig__say, .fig--tiger .fig__say { left: 50%; right: auto; text-align: center; border-radius: 14px; }
  .fig__say.is-said { transform: translateX(-50%); }
  /* no room beside the figures at this width */
  .fig__name { display: none; }
  .fig__say::after { bottom: -6px; left: 50%; margin-left: -6px; right: auto; box-shadow: inset -1px -1px 0 var(--line); }
  .fig--bear .fig__say::after, .fig--tiger .fig__say::after { left: 50%; right: auto; box-shadow: inset -1px -1px 0 var(--line); }
}

.fig__poke {
  position: absolute;
  left: 50%; bottom: -2.6rem;
  transform: translateX(-50%);
  font-size: .6rem;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--ink-3);
  opacity: 0;
  transition: opacity .4s var(--ease);
  pointer-events: none;
  white-space: nowrap;
}
.fig:hover .fig__poke { opacity: .85; }
.fig.is-bouncing { animation: fig-bounce .7s var(--ease); }
@keyframes fig-bounce {
  0%, 100% { transform: translateY(-10px) rotate(0deg); }
  30%      { transform: translateY(-26px) rotate(-3deg); }
  60%      { transform: translateY(-4px) rotate(2deg); }
}

/* The memory machine */
.memory { position: relative; container-type: inline-size; display: grid; gap: clamp(1.75rem, 3.5vw, 2.75rem); justify-items: start; }

/* ── Draggable stickers ───────────────────────────────────────────────
   Places we actually went. They sit in a tidy row on the shelf above the
   card, chip at one end and stickers at the other, each one nudged off
   straight so the row reads as hand-placed rather than laid out. Pick one
   up and it goes wherever you drop it. Fills stay light and keylines stay
   ink in both themes, the same rule the deck and the two figures follow. */
.memory__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1.25rem 1.75rem;
  width: 100%;
}
.memory__controls { display: flex; align-items: center; flex-wrap: wrap; gap: .9rem 1.15rem; }
.stickers { display: flex; align-items: center; gap: clamp(.55rem, 1.6vw, 1.35rem); }

.dsticker {
  position: relative;
  display: block;
  flex: none;
  transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(var(--rot, 0deg));
  transition: transform .45s var(--ease), filter .45s var(--ease);
  filter: drop-shadow(2px 3px 0 rgb(20 17 13 / .16));
  animation: bob 6s var(--ease-soft) infinite;
  animation-delay: var(--bob, 0s);
}
.dsticker { width: var(--w, 60px); padding: 0; border: 0; background: none; color: inherit; font: inherit; cursor: pointer; }
.dsticker svg { display: block; width: 100%; height: auto; }
.dsticker:focus-visible { outline: 2px solid var(--ink); outline-offset: 5px; border-radius: 14px; }
/* the one dressing the card sits up straight with a little dot under it */
.dsticker[aria-pressed="true"] {
  transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(0deg) scale(1.14);
  animation-play-state: paused;
}
.dsticker[aria-pressed="true"]::after {
  content: ""; position: absolute; left: 50%; bottom: -12px;
  width: 7px; height: 7px; margin-left: -3.5px; border-radius: 50%;
  background: var(--ink);
}
/* hover straightens it and lifts it off the page, like peeling one up */
.dsticker:hover {
  transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(0deg) scale(1.12);
  filter: drop-shadow(4px 7px 0 rgb(20 17 13 / .22));
  animation-play-state: paused;
}
@keyframes bob {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -4px; }
}

/* sizes and tilts vary so the row is a row, not a grid */
/* size is the sticker's own business; tilt, stagger and bob delay are dealt
   per position by initStickers so any five drawn still sit as a tidy row */
.dsticker--dome   { --w: 72px; }
.dsticker--crater { --w: 60px; }
.dsticker--canyon { --w: 74px; }
.dsticker--bear   { --w: 62px; }
.dsticker--light  { --w: 42px; }
.dsticker--smoky  { --w: 74px; }
.dsticker--dunes  { --w: 72px; }
.dsticker--stacks { --w: 74px; }
.dsticker--elk    { --w: 64px; }
.dsticker--cactus { --w: 56px; }
/* .dsticker sets display:block, which would otherwise beat the UA [hidden] rule */
.dsticker[hidden] { display: none; }

/* [data-drag] elements are yours to move about */
[data-drag] { cursor: grab; -webkit-user-select: none; user-select: none; }
/* only a mouse drags; on touch the page must still scroll past them */
@media (pointer: fine) { [data-drag] { touch-action: none; } }
.memory__lever[data-drag], .dsticker[data-drag] { cursor: pointer; }
[data-drag].is-dragging, .dsticker.is-dragging, .memory__lever.is-dragging { cursor: grabbing; transition: none; animation: none; z-index: 6; position: relative; }

@media (prefers-reduced-motion: reduce) { .dsticker { animation: none; } }
/* Stickers are controls now, so they stay on small screens: they drop
   under the lever and shrink a little to fit a phone. */
@media (max-width: 900px) { .memory__top { justify-content: flex-start; } .stickers { flex-wrap: wrap; } }
@media (max-width: 600px) { .dsticker { width: calc(var(--w, 60px) * .8); } .stickers { gap: .7rem 1rem; } }
.memory__lever {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 1rem;
  padding: 1.15em 2.1em;
  border-radius: 999px;
  background: #7A2436;
  color: #FBF6EE;
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  border: var(--keyline);
  box-shadow: 5px 5px 0 var(--ink);
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}
.memory__lever { transform: translate(var(--dx, 0px), var(--dy, 0px)); }
.memory__lever:hover { transform: translate(calc(var(--dx, 0px) + 3px), calc(var(--dy, 0px) + 3px)); box-shadow: 2px 2px 0 var(--ink); }
.memory__lever:active { transform: translate(calc(var(--dx, 0px) + 5px), calc(var(--dy, 0px) + 5px)); box-shadow: 0 0 0 var(--ink); }
.memory__lever svg { transition: transform .6s var(--ease); }
.memory__lever:hover svg { transform: rotate(150deg); }

.memory__card {
  display: grid;
  /* holds the empty and dealt states at the same height, so pulling a
     memory swaps content rather than moving the page */
  min-height: 300px;
  /* the photo column, in one place: the mat behind the photo is drawn from
     the same number, so the two can never drift apart */
  --mem-pic: 260px;
  --mem-pad: clamp(1.25rem, 2.2vw, 1.75rem);
  /* how far the mat behind the photograph sits inside the card. Measured off
     the padding, so the band of mat that shows round the photo is the same
     8px at every size, which is what lets one corner radius per look stay
     parallel to the card's on any screen. */
  --mat-inset: calc(var(--mem-pad) - 8px);
  grid-template-columns: minmax(0, var(--mem-pic)) minmax(0, 1fr);
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: center;
  width: 100%;
  padding: var(--mem-pad);
  border-radius: var(--r-md);
}
/* Empty state. It mirrors the dealt card exactly, photo box and all, so
   pulling a memory swaps content in place instead of shoving the page down. */
.memory__card { cursor: pointer; }
.memory__card.is-empty .memory__date { color: var(--ink-3); }
.memory__card.is-empty .memory__place,
.memory__card.is-empty .memory__text { color: var(--ink-2); }
/* A little deck of memories. It fans open when you reach for it. */
.memory__pic.memory__pic--deck {
  position: relative;
  display: grid;
  place-items: center;
  /* a warm ground so the three colored cards read against it */
  background: var(--paper-3);
  overflow: hidden;
}
.deck { position: relative; display: block; width: 58%; max-width: 148px; aspect-ratio: 4 / 3.1; }
.deck__card {
  position: absolute;
  inset: 0;
  border: 2px solid #14110D;
  border-radius: 9px;
  transform-origin: 50% 135%;
  transition: transform .6s var(--ease), box-shadow .6s var(--ease);
}
.deck__card--a { background: #BDE0F0; transform: rotate(-9deg); z-index: 1; }
.deck__card--c { background: #DCC0BE; transform: rotate(9deg);  z-index: 2; }
.deck__card--b { background: #F7F0E0; transform: none;          z-index: 3; }

.memory__card.is-empty:hover .deck__card--a,
.memory__card.is-empty:focus-visible .deck__card--a { transform: rotate(-24deg) translate(-10%, -4%); }
.memory__card.is-empty:hover .deck__card--c,
.memory__card.is-empty:focus-visible .deck__card--c { transform: rotate(24deg) translate(10%, -4%); }
.memory__card.is-empty:hover .deck__card--b,
.memory__card.is-empty:focus-visible .deck__card--b {
  transform: translateY(-14%) rotate(-2deg);
  box-shadow: 0 12px 22px #14110d33;
}

.deck__spark {
  position: absolute;
  z-index: 4;              /* the cards carry z-index 1 to 3 */
  width: 15px; height: 15px;
  fill: #14110D;
  opacity: 0;
  transform: scale(.3) rotate(-40deg);
  transition: opacity .45s var(--ease) var(--sd, 0ms), transform .55s var(--ease) var(--sd, 0ms);
}
.deck__spark--1 { top: 20%;  left: 17%; --sd: 60ms;  }
.deck__spark--2 { top: 13%;  right: 19%; --sd: 150ms; width: 19px; height: 19px; }
.deck__spark--3 { bottom: 20%; right: 26%; --sd: 240ms; width: 12px; height: 12px; }
.memory__card.is-empty:hover .deck__spark { opacity: .9; transform: scale(1) rotate(0deg); }
/* The deck keeps its inked pastel cards in both themes, but the sparks sit on the
   card ground rather than on a card, so they have to follow the theme. */
[data-theme="dusk"] .deck__spark { fill: var(--gold); }

@media (prefers-reduced-motion: reduce) {
  .deck__card, .deck__spark { transition: none; }
  .deck__spark { opacity: .9; transform: none; }
}


.memory__card.is-dealt { animation: deal .7s var(--ease); }
@keyframes deal {
  0%   { opacity: 0; transform: translateY(22px) rotate(-1.4deg); }
  100% { opacity: 1; transform: none; }
}
.memory__pic { position: relative; aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--r-sm); background: var(--paper-3); }
.memory__pic img { width: 100%; height: 100%; object-fit: cover; }
.memory__body { display: grid; gap: .7rem; align-content: center; }
.memory__date { font-size: .68rem; letter-spacing: .22em; text-transform: uppercase; color: var(--brass-ink); }
.memory__place { font-family: var(--display); font-size: clamp(1.4rem, 2.4vw, 2rem); line-height: 1.1; }
.memory__text { font-size: .92rem; line-height: 1.62; color: var(--ink-2); }
.memory__go { justify-self: start; margin-top: .3rem; font-size: .68rem; letter-spacing: .2em; text-transform: uppercase; border-bottom: 1px solid var(--line); padding-bottom: 3px; transition: color .3s, border-color .3s; }
.memory__go:hover { color: var(--wine); border-color: var(--wine); }
@media (max-width: 760px) {
  .memory__card { grid-template-columns: 1fr; }
}

/* ── Card scenes ──────────────────────────────────────────────────────
   A little illustrated place along the foot of the card, with one thing
   in it that moves. Every card holds the band open, dressed or not, so
   the text never runs under a scene and dressing never shifts the page. */
/* the scene is drawn 600 by 90, so a band 15% of the card's width shows all
   of it, edge to edge, at any size */
.memory .memory__card { --scene-h: clamp(44px, 15cqi, 140px); padding-bottom: calc(var(--scene-h) + 16px); }
/* full bleed along the foot, tucked into the card's own bottom corners, so
   the card looks like it is standing in the place rather than holding a strip */
.memory__scene {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: var(--scene-h);
  overflow: hidden;
  border-bottom-left-radius: inherit;
  border-bottom-right-radius: inherit;
  color: var(--ink);
  pointer-events: none;
}
.memory__scene svg {
  position: absolute;
  bottom: 0;
  left: 50%;
  height: 100%;
  width: calc(var(--scene-h) * 600 / 90);
  margin-left: calc(var(--scene-h) * -300 / 90);
  overflow: visible;
}
/* strokes stay the width they are written at, never scaled with the art, so
   the scene draws with the same 2px line as the card border, the stickers
   and the wallpaper; small details step down to 1.5px */
.memory__scene * { vector-effect: non-scaling-stroke; }
.memory__scene [stroke-width]:not([stroke-width="10"]) { stroke-width: 2px; }
.memory__scene [stroke-width^="1"]:not([stroke-width="10"]) { stroke-width: 1.5px; }
.memory__scene.is-new svg { animation: scene-in .7s var(--ease); }
@keyframes scene-in { from { opacity: 0; transform: translateY(14px); } }
.memory__scene g, .memory__scene path, .memory__scene circle { transform-box: fill-box; }

.sc-pop { transform-origin: 50% 100%; animation: sc-pop 4.4s var(--ease) infinite; animation-delay: var(--d, .6s); }
@keyframes sc-pop {
  0%, 10%  { transform: translateY(70%); }
  22%, 68% { transform: translateY(0); }
  74%      { transform: translateY(-5%); }
  86%, 100% { transform: translateY(70%); }
}
.sc-bob     { transform-origin: 50% 100%; animation: sc-bob 3s ease-in-out infinite; }
@keyframes sc-bob { 0%, 100% { transform: translateY(0) rotate(-2.5deg); } 50% { transform: translateY(3px) rotate(2.5deg); } }
.sc-sway    { animation: sc-sway 3.6s ease-in-out infinite; }
@keyframes sc-sway { 50% { transform: translateX(10px); } }
.sc-glide   { animation: sc-glide 9s ease-in-out infinite; }
@keyframes sc-glide { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(60px, -6px); } }
.sc-twinkle { transform-origin: center; animation: sc-twinkle 2.4s ease-in-out infinite; animation-delay: var(--d, 0s); }
@keyframes sc-twinkle { 0%, 100% { opacity: .25; transform: scale(.7); } 50% { opacity: 1; transform: scale(1); } }
.sc-drive   { animation: sc-drive 7s linear infinite; }
@keyframes sc-drive { from { transform: translateX(-90px); } to { transform: translateX(690px); } }
.sc-run     { animation: sc-run 5.5s linear infinite; animation-delay: var(--d, .8s); }
@keyframes sc-run { from { transform: translateX(-70px); } to { transform: translateX(670px); } }
.sc-hop     { animation: sc-hop .34s ease-in-out infinite; }
@keyframes sc-hop { 50% { transform: translateY(-3px); } }
.sc-roll    { transform-origin: center; animation: sc-roll 8s linear infinite; }
@keyframes sc-roll { from { transform: translateX(-40px) rotate(0deg); } to { transform: translateX(660px) rotate(900deg); } }
.sc-puff    { transform-origin: center; opacity: 0; animation: sc-puff 3s ease-out infinite; animation-delay: var(--d, 0s); }
@keyframes sc-puff { 0% { opacity: 0; transform: translate(0, 0) scale(.5); } 20% { opacity: .95; } 100% { opacity: 0; transform: translate(12px, -34px) scale(1.5); } }
.sc-buzz    { animation: sc-buzz 2.2s ease-in-out infinite; animation-delay: var(--d, 0s); }
@keyframes sc-buzz { 0%, 100% { transform: translate(0, 0); } 25% { transform: translate(10px, -6px); } 50% { transform: translate(18px, 2px); } 75% { transform: translate(6px, 8px); } }
.sc-jump    { transform-origin: center; opacity: 0; animation: sc-jump 3.4s ease-in-out infinite; }
@keyframes sc-jump { 0%, 55% { opacity: 0; transform: translate(0, 10px) rotate(-30deg); } 62% { opacity: 1; } 75% { transform: translate(14px, -16px) rotate(10deg); } 88% { opacity: 1; transform: translate(28px, 6px) rotate(60deg); } 92%, 100% { opacity: 0; } }
.sc-graze   { transform-origin: 50% 100%; animation: sc-graze 6s ease-in-out infinite; }
@keyframes sc-graze { 0%, 40%, 100% { transform: translateY(0); } 55%, 80% { transform: translateY(22px); } }
.sc-flutter { transform-origin: center; animation: sc-flutter .45s ease-in-out infinite alternate; }
@keyframes sc-flutter { to { transform: scaleX(.35); } }
@media (prefers-reduced-motion: reduce) {
  .memory__scene *, .memory__scene svg { animation: none !important; }
}

/* ── Card looks ───────────────────────────────────────────────────────
   Each sticker dresses the memory card as its own place: paper, a wash, a
   few doodles, a shape and a postmark. Colors are pinned rather than themed,
   the same rule the stickers follow, so every look reads the same at dawn
   and at dusk. Pressing the lit sticker again takes the card back.

   A look sets two corner radii, and they are not the same number: the
   photograph sits 8px inside the mat, so its radius is the card's less 8
   and the two curves run parallel. Give it the card's own radius and the gap
   between them pinches shut at the diagonal. Crater Lake cuts a circle and
   Prickly Pear an arch, which are meant to be other shapes entirely.  */
.memory .memory__card[data-look] {
  background: var(--lk-tex, linear-gradient(transparent, transparent)), var(--lk-bg);
  color: var(--lk-ink, #14110D);
  border-color: #14110D;
  border-radius: var(--lk-radius, var(--r-md));
  box-shadow: var(--lk-shadow, 7px 7px 0 var(--lk-accent));
  outline: var(--lk-outline, 0 solid transparent);
  outline-offset: var(--lk-outline-offset, 0);
  transition: border-radius .5s var(--ease), box-shadow .5s var(--ease), transform .45s var(--ease);
}
.memory .memory__card[data-look]:hover { box-shadow: var(--lk-shadow, 7px 7px 0 var(--lk-accent)); transform: translate(2px, 2px); }
/* The wallpaper is a mat panel behind the photo: a clean-edged swatch with a
   hairline border, not a fade, so no motif is ever left half-dissolved. It
   sits in the photo column beside the text on a wide card, and across the
   top around the photo once the card stacks. Copy always sits on paper. */
.memory .memory__card[data-look] { isolation: isolate; }
.memory .memory__card[data-look]::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: var(--mat-inset);
  left: var(--mat-inset);
  bottom: calc(var(--scene-h) + 6px);
  /* card padding + the photo column + half the column gap */
  width: calc(var(--mem-pad) + var(--mem-pic) + clamp(.75rem, 1.5vw, 1.25rem) - var(--mat-inset));
  border-radius: inherit;
  border-top-right-radius: 14px;
  border-bottom-right-radius: 14px;
  background: var(--lk-pattern), color-mix(in srgb, var(--lk-accent) 8%, var(--lk-bg));
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--lk-accent) 30%, transparent);
  pointer-events: none;
}
@media (max-width: 760px) {
  /* Stacked: the mat spans the top and stops just under the photograph. Its
     height is the photo's, so a look that caps the photo has to say so, or
     the mat runs on as a long empty band below it. */
  .memory .memory__card[data-look]::before {
    right: var(--mat-inset);
    bottom: auto;
    width: auto;
    height: var(--lk-mat-h, calc(72cqi - 2px));
    border-radius: inherit;
    border-bottom-left-radius: 14px;
    border-bottom-right-radius: 14px;
  }
  /* a taller band on a phone; the scene sizes by height, so it zooms in */
  .memory .memory__card { --scene-h: clamp(72px, 24cqi, 110px); }

  /* Crater Lake cuts a round window 230px across and rings it, so the mat
     that reads right for a photograph the width of the card is far too tall
     for this one: it ran over the date below. The window is a fixed size on
     any phone, so the mat is too, and the card takes a little more room at
     the top to leave the pool centered in it. */
  .memory__card[data-look="crater"] { padding-top: 28px; --lk-mat-h: 266px; }
}
.memory .memory__card[data-look] .memory__place { color: var(--lk-ink, #14110D); }
.memory .memory__card[data-look] .memory__text  { color: var(--lk-ink-2, #3D372F); }
.memory .memory__card[data-look] .memory__date  { color: var(--lk-accent); }
.memory .memory__card[data-look] .memory__go    { color: var(--lk-ink, #14110D); border-color: currentColor; }
.memory .memory__card[data-look] .memory__go:hover { color: var(--lk-accent); }
.memory .memory__card[data-look] .memory__pic {
  width: 100%;
  max-width: var(--lk-pic-max, none);
  justify-self: center;
  aspect-ratio: var(--lk-pic-ratio, 4 / 3);
  border-radius: var(--lk-pic-radius, var(--r-sm));
  border: var(--lk-pic-border, 0 solid transparent);
  box-shadow: var(--lk-pic-shadow, none);
  transform: rotate(var(--lk-pic-rot, 0deg));
  transition: border-radius .5s var(--ease), transform .5s var(--ease);
}
/* the postmark, slapped over the top edge: where and when this memory is,
   read from data.js, so it always agrees with the card underneath */
.memory .memory__card[data-look]::after {
  content: attr(data-stamp);
  position: absolute;
  top: -15px;
  right: clamp(14px, 3vw, 30px);
  z-index: 2;
  padding: .5em 1em .44em;
  font-family: var(--sans);
  font-size: .6rem;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  line-height: 1.3;
  color: var(--lk-stamp-ink, #14110D);
  background: var(--lk-stamp-bg, #F0D89C);
  border: 2px solid #14110D;
  /* a pill on one line, a rounded tag if a long place name needs two:
     never cut off, since a clipped name would stop matching the card */
  border-radius: 1.4em;
  max-width: calc(100% - 44px);
  text-align: center;
  text-wrap: balance;
  transform: rotate(4deg);
  pointer-events: none;
}
.memory__card.is-restyled { animation: restyle .55s var(--ease); }
.memory .memory__card[data-look].is-dealt::after,
.memory .memory__card[data-look].is-restyled::after { animation: thump .5s var(--ease); }
@keyframes restyle {
  0%   { transform: scale(.97) rotate(-1deg); }
  45%  { transform: scale(1.015) rotate(.6deg); }
  100% { transform: none; }
}
@keyframes thump {
  0%   { opacity: 0; transform: scale(1.8) rotate(-14deg); }
  60%  { opacity: 1; transform: scale(.94) rotate(6deg); }
  100% { opacity: 1; transform: rotate(4deg); }
}
@media (prefers-reduced-motion: reduce) {
  .memory__card.is-restyled, .memory .memory__card[data-look]::after { animation: none !important; }
}

/* Each look is flat paper in that place's color, a swatch of its own
   wallpaper as a mat behind the photo (two motifs to a repeat, pinecones
   and tents, sailboats and fish), and a moving scene along the foot of the
   card, which lives in site.js (SCENES). */
/* Half Dome: granite washed in morning light, pines and a cloud drawn in the corner */
.memory__card[data-look="dome"] {
  --lk-bg: #E9EEF0;
  --lk-pattern: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='104' height='104' viewBox='0 0 104 104'%3E%3Cg transform='translate(26 28) rotate(-18) scale(1)' stroke='%232F5F72' stroke-opacity='0.36' fill='%232F5F72' fill-opacity='0.14' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cellipse rx='7' ry='10'/%3E%3Cpath d='M-6 -3 h12 M-7 3 h14 M-5 8 h10 M0 -10 v-5' fill='none'/%3E%3C/g%3E%3Cg transform='translate(78 80) rotate(4) scale(1)' stroke='%232F5F72' stroke-opacity='0.36' fill='%232F5F72' fill-opacity='0.14' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M-12 9 L0 -10 L12 9 Z M0 -10 V9 M-3 9 L0 3 L3 9' fill='none'/%3E%3C/g%3E%3C/svg%3E") 0 0 / 104px 104px;
  --lk-radius: 110px 18px 18px 18px;
  /* the mat's 110px corner less the 10px of mat that shows round the photo,
     so the two curves run parallel instead of the photo cutting a tighter one */
  --lk-pic-radius: 102px 10px 10px 10px;
  --lk-accent: #2F5F72;
  --lk-stamp-bg: #BFDCE3;
}
/* Crater Lake: a deep blue pool of wash behind the round window, a sailboat out on it */
.memory__card[data-look="crater"] {
  --lk-bg: #DFEFF5;
  --lk-pattern: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='104' height='104' viewBox='0 0 104 104'%3E%3Cg transform='translate(26 30) rotate(-8) scale(1)' stroke='%231F5A78' stroke-opacity='0.36' fill='%231F5A78' fill-opacity='0.17' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M-12 4 H12 L8 10 H-8 Z M0 4 V-12 L9 1 H0'/%3E%3C/g%3E%3Cg transform='translate(78 78) rotate(12) scale(1)' stroke='%231F5A78' stroke-opacity='0.36' fill='%231F5A78' fill-opacity='0.17' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M-10 0 c5 -6 13 -6 16 0 c-3 6 -11 6 -16 0 z M6 0 l6 -4 v8 z'/%3E%3C/g%3E%3C/svg%3E") 0 0 / 104px 104px;
  --lk-radius: 42px;
  --lk-pic-ratio: 1 / 1; --lk-pic-radius: 50%; --lk-pic-max: 230px;
  --lk-pic-border: 4px solid #2A6E91; --lk-pic-shadow: 0 0 0 7px #A9BFB0, 0 0 0 9px #14110D;
  --lk-accent: #1F5A78;
  --lk-stamp-bg: #A9BFB0;
}
/* Grand Canyon: a sunset bleeding across the paper, the rim and a sun sketched in */
.memory__card[data-look="canyon"] {
  --lk-bg: #F8E7CD;
  --lk-pattern: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='104' height='104' viewBox='0 0 104 104'%3E%3Cg transform='translate(26 28) rotate(0) scale(1)' stroke='%239A3520' stroke-opacity='0.36' fill='%239A3520' fill-opacity='0.14' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle r='5'/%3E%3Cpath d='M0 -12 v3 M0 9 v3 M-12 0 h3 M9 0 h3 M-8.5 -8.5 l2 2 M6.5 6.5 l2 2 M-8.5 8.5 l2 -2 M6.5 -6.5 l2 -2' fill='none'/%3E%3C/g%3E%3Cg transform='translate(78 80) rotate(0) scale(1.1)' stroke='%239A3520' stroke-opacity='0.36' fill='%239A3520' fill-opacity='0.14' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M-15 9 H-10 L-8 -3 H4 L6 9 H15' fill='none'/%3E%3C/g%3E%3C/svg%3E") 0 0 / 104px 104px;
  --lk-radius: 6px; --lk-pic-radius: 3px;
  --lk-accent: #9A3520;
  --lk-stamp-bg: #F0CE84;
}
/* The bear: honey-warm paper with a trail of paw prints wandering off the corner */
.memory__card[data-look="bear"] {
  --lk-bg: #F5EBDA;
  --lk-pattern: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='104' height='104' viewBox='0 0 104 104'%3E%3Cg transform='translate(26 28) rotate(-22) scale(1)' stroke='%237E3F22' stroke-opacity='0.38' fill='%237E3F22' fill-opacity='0.18' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cellipse cy='4' rx='6' ry='5'/%3E%3Cellipse cx='-7' cy='-4' rx='2.4' ry='3'/%3E%3Cellipse cx='-2.4' cy='-8' rx='2.4' ry='3'/%3E%3Cellipse cx='3' cy='-8' rx='2.4' ry='3'/%3E%3Cellipse cx='7.4' cy='-4' rx='2.3' ry='2.9'/%3E%3C/g%3E%3Cg transform='translate(78 80) rotate(6) scale(1)' stroke='%237E3F22' stroke-opacity='0.38' fill='%237E3F22' fill-opacity='0.18' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M-8 9 C-12 1 -9 -5 -5 -6 H5 C9 -5 12 1 8 9 Z M-7 -6 H7' fill='none'/%3E%3C/g%3E%3C/svg%3E") 0 0 / 104px 104px;
  --lk-radius: 30px; --lk-pic-radius: 22px;
  --lk-accent: #7E3F22;
  --lk-stamp-bg: #E2604F;
}
/* Traffic light: a highway sign, reflective border, and a little car heading out */
.memory__card[data-look="light"] {
  --lk-bg: #285E45;
  --lk-pattern: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='104' height='104' viewBox='0 0 104 104'%3E%3Cg transform='translate(26 28) rotate(0) scale(1)' stroke='%23FFFFFF' stroke-opacity='0.24' fill='%23FFFFFF' fill-opacity='0.17' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M0 -11 L11 0 L0 11 L-11 0 Z M-4 0 H4 M1 -3 L4 0 L1 3' fill='none'/%3E%3C/g%3E%3Cg transform='translate(78 80) rotate(0) scale(1)' stroke='%23FFFFFF' stroke-opacity='0.24' fill='%23FFFFFF' fill-opacity='0.17' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M-14 3 V-1 L-8 -2 L-4 -8 H6 L10 -2 L14 -1 V3 Z' fill='none'/%3E%3Ccircle cx='-8' cy='4' r='2.6'/%3E%3Ccircle cx='8' cy='4' r='2.6'/%3E%3C/g%3E%3C/svg%3E") 0 0 / 104px 104px;
  --lk-ink: #FFFFFF; --lk-ink-2: #E4EFE8; --lk-accent: #F4D896;
  --lk-radius: 16px; --lk-pic-radius: 8px;
  --lk-outline: 3px solid #FFFFFF; --lk-outline-offset: -10px;
  --lk-pic-border: 3px solid #FFFFFF;
  --lk-shadow: 7px 7px 0 #14110D;
  --lk-stamp-bg: #F0CE84;
}
/* The Smokies: fog pooled low in soft washes, one ridge line and two birds over it */
.memory__card[data-look="smoky"] {
  --lk-bg: #E5EDEF;
  --lk-pattern: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='104' height='104' viewBox='0 0 104 104'%3E%3Cg transform='translate(26 30) rotate(-4) scale(1.1)' stroke='%23335A45' stroke-opacity='0.36' fill='%23F4C443' fill-opacity='0.5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M0 -12 L-6 -2 H-3 L-8 7 H8 L3 -2 H6 Z M0 7 V11' fill='none'/%3E%3C/g%3E%3Cg transform='translate(78 80) rotate(0) scale(1)' stroke='%23335A45' stroke-opacity='0.36' fill='%23F4C443' fill-opacity='0.5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle r='6' opacity='.45'/%3E%3Ccircle r='2.4'/%3E%3C/g%3E%3C/svg%3E") 0 0 / 104px 104px;
  --lk-radius: 36px; --lk-pic-radius: 28px;
  --lk-accent: #335A45;
  --lk-stamp-bg: #DCE9EC;
}
/* Death Valley: heat haze washed over the page, dunes and a sun drawn freehand */
.memory__card[data-look="dunes"] {
  --lk-bg: #FBE7C9;
  --lk-pattern: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='104' height='104' viewBox='0 0 104 104'%3E%3Cg transform='translate(26 30) rotate(-6) scale(1)' stroke='%23963219' stroke-opacity='0.36' fill='%23963219' fill-opacity='0.14' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M0 11 V-10 M0 1 H-6 V-6 M0 4 H6 V-3' fill='none' stroke-width='3.2'/%3E%3C/g%3E%3Cg transform='translate(78 80) rotate(0) scale(0.95)' stroke='%23963219' stroke-opacity='0.36' fill='%23963219' fill-opacity='0.14' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle r='5'/%3E%3Cpath d='M0 -12 v3 M0 9 v3 M-12 0 h3 M9 0 h3 M-8.5 -8.5 l2 2 M6.5 6.5 l2 2 M-8.5 8.5 l2 -2 M6.5 -6.5 l2 -2' fill='none'/%3E%3C/g%3E%3C/svg%3E") 0 0 / 104px 104px;
  --lk-radius: 46px 10px 46px 10px; --lk-pic-radius: 38px 2px 38px 2px;
  --lk-accent: #963219;
  --lk-stamp-bg: #E2604F;
}
/* Olympic: a postcard, sea-mist wash, a postage stamp and its cancellation in the corner */
.memory__card[data-look="stacks"] {
  --lk-bg: #FAF4E6;
  --lk-pattern: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='104' height='104' viewBox='0 0 104 104'%3E%3Cg transform='translate(26 28) rotate(14) scale(1)' stroke='%232B5E73' stroke-opacity='0.36' fill='%232B5E73' fill-opacity='0.13' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M0 -11 L3 -3 L11 -3 L5 2 L7 10 L0 5 L-7 10 L-5 2 L-11 -3 L-3 -3 Z' fill='none'/%3E%3C/g%3E%3Cg transform='translate(78 80) rotate(-10) scale(1)' stroke='%232B5E73' stroke-opacity='0.36' fill='%232B5E73' fill-opacity='0.13' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M-9 6 C-9 -7 9 -7 9 6 Z M0 6 V-4 M-5 6 L-3 -2 M5 6 L3 -2' fill='none'/%3E%3C/g%3E%3C/svg%3E") 0 0 / 104px 104px;
  --lk-radius: 6px; --lk-pic-radius: 2px;
  --lk-pic-border: 7px solid #FFFFFF; --lk-pic-shadow: 0 4px 0 rgb(20 17 13 / .18); --lk-pic-rot: -2.5deg;
  --lk-accent: #2B5E73;
  --lk-stamp-bg: #FAF4E6; --lk-stamp-ink: #9A3520;
}
/* The elk: a kraft-paper trail journal, hoof prints and a pressed leaf */
.memory__card[data-look="elk"] {
  --lk-bg: #ECDFC6;
  --lk-pattern: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='104' height='104' viewBox='0 0 104 104'%3E%3Cg transform='translate(26 28) rotate(-14) scale(1.05)' stroke='%23335A45' stroke-opacity='0.38' fill='%23335A45' fill-opacity='0.14' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M0 11 C0 1 -2 -5 -6 -11 M-1 3 C-6 1 -9 -2 -10 -6 M0 -3 C4 -5 6 -8 6 -12' fill='none'/%3E%3C/g%3E%3Cg transform='translate(78 80) rotate(24) scale(1)' stroke='%23335A45' stroke-opacity='0.38' fill='%23335A45' fill-opacity='0.14' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M-8 8 C-8 -4 0 -10 9 -10 C9 2 1 8 -8 8 Z M-8 8 L4 -4' fill='none'/%3E%3C/g%3E%3C/svg%3E") 0 0 / 104px 104px;
  --lk-radius: 10px; --lk-pic-radius: 2px;
  --lk-pic-border: 6px solid #FFFFFF; --lk-pic-shadow: 0 3px 0 rgb(20 17 13 / .16); --lk-pic-rot: 1.8deg;
  --lk-accent: #335A45;
  --lk-stamp-bg: #F0CE84;
}
/* Prickly pear: desert-bloom pink wash, a few flowers and sparkles tossed in the corner */
.memory__card[data-look="cactus"] {
  --lk-bg: #F8E0DB;
  --lk-pattern: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='104' height='104' viewBox='0 0 104 104'%3E%3Cg transform='translate(26 28) rotate(10) scale(1.05)' stroke='%238A3527' stroke-opacity='0.36' fill='%235E8A6E' fill-opacity='0.25' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle r='2.4'/%3E%3Cellipse cy='-6' rx='2.8' ry='4.2' transform='rotate(0)' fill='none'/%3E%3Cellipse cy='-6' rx='2.8' ry='4.2' transform='rotate(72)' fill='none'/%3E%3Cellipse cy='-6' rx='2.8' ry='4.2' transform='rotate(144)' fill='none'/%3E%3Cellipse cy='-6' rx='2.8' ry='4.2' transform='rotate(216)' fill='none'/%3E%3Cellipse cy='-6' rx='2.8' ry='4.2' transform='rotate(288)' fill='none'/%3E%3C/g%3E%3Cg transform='translate(78 80) rotate(-12) scale(1)' stroke='%238A3527' stroke-opacity='0.36' fill='%235E8A6E' fill-opacity='0.25' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cellipse rx='7' ry='9.5'/%3E%3Ccircle cy='-11' r='2.6'/%3E%3C/g%3E%3C/svg%3E") 0 0 / 104px 104px;
  --lk-radius: 44px; --lk-pic-radius: 999px 999px 16px 16px;
  --lk-accent: #8A3527;
  --lk-stamp-bg: #9FB8A6;
}

/* Small joys */
.figure:hover .figure__n { animation: wobble .6s var(--ease); }
@keyframes wobble {
  0%, 100% { transform: rotate(0) }
  30% { transform: rotate(-4deg) scale(1.05) }
  65% { transform: rotate(3deg) scale(1.02) }
}
.figure__n { display: inline-block; transform-origin: 12% 80%; cursor: default; }
.ticker__item { transition: color .3s, transform .4s var(--ease); }

/* Anniversary , computed live, so it stays true without anyone editing it */
.anniv { display: grid; grid-template-columns: 1.35fr 1fr; gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }
.anniv__main { display: grid; gap: 1.1rem; align-content: start; }
.anniv__count { display: grid; justify-items: end; }
.anniv__big {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(3.4rem, 8vw, 6.6rem);
  line-height: .94;
  letter-spacing: -.02em;
  color: var(--wine);
  cursor: pointer;
  transition: transform .5s var(--ease);
}
.anniv__big:hover { transform: scale(1.04) rotate(-1.5deg); }
.anniv__k { font-size: .7rem; letter-spacing: .2em; text-transform: uppercase; color: var(--ink-3); max-width: 22ch; }
.anniv__ord { color: var(--brass-ink); }

/* ── THE COUNTDOWN ───────────────────────────────────────────────────────
   A tear-off pad rather than a single page, because the number means
   something you can picture: three hundred and nineteen pages still under
   the top one. Drawn, not boxed, in the same hand as the four marks above
   it, so the fills and the one heavy ink line are the drawing and the CSS
   only colors it and tilts it.                                            */

.cal {
  position: relative;
  width: 252px; max-width: 100%;
  margin: .6rem 2.6rem 2.3rem 0;
}
/* ── What animates, and what does not ───────────────────────────────────
   The wrapper this sits in carries data-reveal="up", which already fades it
   in and lifts it 26px over most of a second. Rotating and scaling the pad
   on top of that, and sliding the sheets inside it at the same time, put
   three motions on one object at once: the whole thing wobbled, and the
   stamp did not land until two seconds in.

   So the arrival belongs to the wrapper. The pad only does the things that
   are actually being done to it, in the order somebody would do them: the
   wire threads itself loop by loop, the perforation is scored across, the
   pen goes round the day, and the stamp comes down last. All of it runs
   under the wrapper's lift, so the whole thing is finished in about 1.3s. */
.calart {
  display: block;
  width: 100%; height: auto;
  overflow: visible;
  rotate: -2.5deg;
}
.calart__print { fill: var(--rose); }
.calart__sheet, .calart__page {
  stroke: var(--ink);
  stroke-width: 2.6;
  vector-effect: non-scaling-stroke;
}
.calart__sheet { fill: var(--paper-3); }
.calart__sheet--a { fill: var(--paper-2); }
.calart__page { fill: var(--paper); }
/* a fixed wine and cream, so the head reads the same in dawn and dusk */
.calart__band { fill: #7A2436; }
.calart__rule { stroke: var(--ink); stroke-width: 2.6; vector-effect: non-scaling-stroke; }
/* the punched hole, dark enough against the band that the wire is visibly
   going into something */
.calart__hole { fill: #3D101B; stroke: #21070D; stroke-width: 1.2; vector-effect: non-scaling-stroke; }
/* the wire: out of its hole, up across the top edge, over the crest, and
   behind the paper on the far side, where it simply stops */
.calart__wire {
  fill: none;
  stroke: var(--ink);
  stroke-width: 2.6;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset .5s var(--ease) var(--d, 0s);
}
.anniv__count.is-in .calart__wire { stroke-dashoffset: 0; }
.calart__month { font-family: var(--display); font-size: 21px; fill: #F9F2E4; }
.calart__year { font-family: var(--sans); font-size: 9px; font-weight: 500; letter-spacing: 2.2px; fill: #F9F2E4; }
.calart__date { font-family: var(--display); font-size: 72px; fill: var(--ink); }
.calart__dow { font-family: var(--sans); font-size: 9px; font-weight: 500; letter-spacing: 2.4px; text-transform: uppercase; fill: var(--ink-3); }
/* tear here: a dotted rule with a notch bitten out of each edge */
.calart__perf {
  fill: none;
  stroke: var(--ink);
  stroke-width: 2.4;
  stroke-dasharray: 0 6.5;
  stroke-linecap: round;
  opacity: .55;
  vector-effect: non-scaling-stroke;
  transition: opacity .45s var(--ease-soft) .34s;
}
.anniv__count:not(.is-in) .calart__perf { opacity: 0; }
.calart__notch {
  fill: var(--paper-2);
  stroke: var(--ink);
  stroke-width: 2.6;
  vector-effect: non-scaling-stroke;
  transform-box: fill-box; transform-origin: 50% 50%;
  transition: scale .45s cubic-bezier(.34, 1.56, .64, 1) .38s;
}
.anniv__count:not(.is-in) .calart__notch { scale: 0; }
/* the day circled in pen, drawn on once the pad scrolls in */
.cal__ring {
  fill: none;
  stroke: var(--coral);
  stroke-width: 4;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset .85s var(--ease) .48s;
}
.anniv__count.is-in .cal__ring { stroke-dashoffset: 0; }

/* The stamp. Gold and near-black pinned, like the postmark on the letters
   and the sticker between the vows, with the count in the hand so it never
   reads as another number on the calendar. It sits over the corner of the
   pad, clear of the date and clear of the perforation. */
.cal__stamp {
  position: absolute;
  z-index: 4;
  right: -2.4rem; bottom: -2rem;
  width: 122px; aspect-ratio: 1;
  display: grid; place-content: center; justify-items: center; gap: 0;
  border: 2px solid #14110D;
  border-radius: 50%;
  background: #F0CE84;
  color: #14110D;
  box-shadow: 3px 3px 0 #14110D;
  text-align: center;
  rotate: -7deg;
  scale: 0;
  transition: scale .55s cubic-bezier(.34, 1.7, .6, 1) .76s,
              rotate .55s cubic-bezier(.34, 1.56, .64, 1) .76s;
}
/* the postmark's inner ring, a hair inside the edge */
.cal__stamp::before {
  content: "";
  position: absolute; inset: 7px;
  border: 1.5px dashed color-mix(in srgb, #14110D 45%, transparent);
  border-radius: 50%;
  pointer-events: none;
}
.anniv__count.is-in .cal__stamp { scale: 1; }
/* it comes down a shade over-rotated and rights itself */
.anniv__count:not(.is-in) .cal__stamp { rotate: -22deg; }
.cal:hover .cal__stamp { rotate: 4deg; }
/* Space Grotesk, not the hand: in Caveat the 1 has no flag to speak of and
   "319" kept reading as 379. A grotesque numeral is what a postmark would
   be set in anyway, and it cannot be mistaken for the serif 6 on the page. */
.cal__stamp .anniv__big {
  font-family: var(--sans); font-weight: 700;
  font-size: 2.45rem; line-height: .95; letter-spacing: -.01em;
  color: #14110D;
}
.cal__stamp .anniv__k {
  max-width: 10ch;
  margin-top: .12rem;
  font-size: .5rem; font-weight: 700; line-height: 1.22; letter-spacing: .11em;
  color: #14110D;
}
/* two brass sparks tucked at its corners, the same pair the vows sticker has */
.cal__star { position: absolute; fill: var(--brass); transition: rotate .8s var(--ease), scale .8s var(--ease); }
.cal__star--a { width: 16px; top: -10px; right: -7px; }
.cal__star--b { width: 11px; bottom: -5px; left: -10px; }
.cal:hover .cal__star { rotate: 90deg; scale: 1.18; }

@media (prefers-reduced-motion: reduce) {
  .calart, .calart__print, .calart__sheet, .calart__wire,
  .calart__perf, .calart__notch, .cal__ring, .cal__stamp,
  .cal__star { transition: none !important; }
}
@media (max-width: 860px) {
  .anniv { grid-template-columns: 1fr; align-items: start; }
  .anniv__count { justify-items: start; text-align: left; }
}

/* Numbers */
.figures { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: clamp(1.5rem, 3vw, 2.5rem); margin-top: clamp(2.25rem, 4.5vw, 3.5rem); }
.figure { padding-top: 1.3rem; border-top: 1px solid var(--line); }
.figure__n { display: block; }
.figure__k { display: block; margin-top: .6rem; font-size: .7rem; letter-spacing: .2em; text-transform: uppercase; color: var(--ink-3); }

/* Where we've been: the map beside the figures. Cut out on paper, the states
   we've been to printed in four colors with paper seams between them,
   swinging in nearest home first when the map scrolls into view. */
.atlas-row {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
  gap: clamp(2rem, 4.5vw, 4rem);
  align-items: center;
  margin-top: clamp(2.25rem, 4.5vw, 3.5rem);
}
.atlas-row .figures { margin-top: 0; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.atlas {
  --atlas-ground: var(--paper);
  --atlas-land: var(--paper-2);
  --atlas-edge: color-mix(in srgb, var(--ink) 22%, transparent);
  --atlas-1: var(--quilt-1);
  --atlas-2: var(--quilt-2);
  --atlas-3: var(--quilt-3);
  --atlas-4: var(--quilt-4);
  position: relative;
  display: grid;
  gap: .4rem;
  margin: 0;
  padding: clamp(1rem, 2vw, 1.4rem) clamp(1rem, 2.2vw, 1.6rem);
  border: var(--keyline);
  border-radius: var(--r-lg);
  background: var(--atlas-ground);
  box-shadow: 6px 6px 0 var(--blue);
}
[data-theme="dusk"] .atlas { --atlas-land: var(--paper-2); }
.atlas__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .5rem 1.25rem; }
.atlas__key { display: flex; flex-wrap: wrap; gap: .35rem 1rem; margin: 0; padding: 0; list-style: none; font-size: .62rem; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-3); }
.atlas__key li { display: inline-flex; align-items: center; gap: .45rem; }
.atlas__sw { position: relative; width: 13px; height: 10px; border: 1px solid var(--atlas-edge); border-radius: 2px; background: var(--atlas-land); }
/* the four quilt colors, so the key matches the map in either theme */
.atlas__sw--been { width: 14px; height: 12px; border-color: transparent; background: conic-gradient(var(--atlas-1) 0 25%, var(--atlas-2) 0 50%, var(--atlas-3) 0 75%, var(--atlas-4) 0); }
.atlas__sw-star { width: 14px; height: 14px; fill: var(--gold); stroke: #14110D; stroke-width: 1.6; }

.atlas__map { position: relative; }
/* Canada runs off the top edge, cropped like a print */
.atlas__map svg { display: block; width: 100%; height: auto; overflow: hidden; }
.atlas__st {
  fill: var(--atlas-land);
  stroke: var(--atlas-edge);
  stroke-width: .8px;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  transition: fill .3s var(--ease-soft);
}
.atlas__st:not(.is-been).is-hot { fill: var(--paper-3); }
.atlas__fill {
  pointer-events: none;
  fill: var(--atlas-1);
  stroke: var(--atlas-ground);
  stroke-width: 1px;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0;
  transform: translate(-9px, -11px) scale(.7) rotate(-9deg);
  transition: opacity .3s var(--ease-soft) var(--t, 0ms), transform .9s cubic-bezier(.34, 1.56, .64, 1) var(--t, 0ms);
}
.atlas__fill[data-q="1"] { fill: var(--atlas-2); }
.atlas__fill[data-q="2"] { fill: var(--atlas-3); }
.atlas__fill[data-q="3"] { fill: var(--atlas-4); }
.atlas.is-in .atlas__fill { opacity: 1; transform: none; }
/* once printed, pointing at a state lifts it a touch */
.atlas.is-done .atlas__fill { transition-delay: 0ms; transition-duration: .25s, .45s; }
.atlas.is-done .atlas__fill.is-hot { transform: scale(1.06); }
.atlas__dc { pointer-events: none; fill: var(--coral); stroke: var(--atlas-ground); stroke-width: 1.3px; vector-effect: non-scaling-stroke; opacity: 0; transition: opacity .3s var(--ease-soft) var(--t, 0ms); }
.atlas.is-in .atlas__dc { opacity: 1; }
.atlas__home {
  pointer-events: none;
  fill: var(--gold);
  stroke: #14110D;
  stroke-width: 1.5px;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  transform: scale(0) rotate(-120deg);
  transition: transform .8s cubic-bezier(.34, 1.56, .64, 1) 60ms;
}
.atlas.is-in .atlas__home { transform: scale(1.35) rotate(0deg); }
.atlas__label { font-family: var(--sans); font-size: 13px; font-weight: 500; letter-spacing: .5em; fill: var(--ink-3); pointer-events: none; }

.atlas__tip {
  position: absolute;
  z-index: 3;
  left: 0; top: 0;
  display: grid;
  gap: .1rem;
  margin: 0;
  padding: .45rem .75rem .4rem;
  border: 1.5px solid var(--ink);
  border-radius: var(--r-sm);
  background: var(--paper);
  box-shadow: 3px 3px 0 var(--blue);
  white-space: nowrap;
  text-align: center;
  pointer-events: none;
  transform: translate(-50%, calc(-100% - 14px));
}
.atlas__tip[hidden] { display: none; }
.atlas__tip b { font-family: var(--display); font-size: 1rem; font-weight: 400; line-height: 1.15; }
.atlas__tip span { font-size: .56rem; letter-spacing: .18em; text-transform: uppercase; color: var(--ink-3); }
.atlas__cap { font-size: .8rem; line-height: 1.5; color: var(--ink-3); }

@media (max-width: 1080px) {
  .atlas-row { grid-template-columns: minmax(0, 1fr); }
  .atlas-row .figures { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
/* four figures, then two by two: never three with one under it */
@media (max-width: 780px) {
  .atlas-row .figures { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  .atlas { box-shadow: 4px 4px 0 var(--blue); }
  .atlas__label { display: none; }
  .atlas.is-in .atlas__home { transform: scale(2.2) rotate(0deg); }
  .atlas-row .figures { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (prefers-reduced-motion: reduce) {
  .atlas__fill, .atlas__dc, .atlas__home { transition-delay: 0ms !important; }
}

/* Chapter cards */
/* ── Four doors ───────────────────────────────────────────────────────
   Pick a door, so they are drawn as doors: arched head, square foot, a
   recessed panel, a brass knob and a number plate. Hover swings the room
   behind into view (the fill on ::before) rather than tilting anything,
   which keeps them in step with every other card on the site.          */
.chapters { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(1.1rem, 2vw, 1.75rem); }
.chapter {
  position: relative;
  background: var(--paper);
  border: var(--keyline);
  /* arched head, square foot */
  border-radius: 46% 46% var(--r-sm) var(--r-sm) / 20% 20% 3% 3%;
  padding: clamp(4.2rem, 7vw, 6rem) clamp(2rem, 2.8vw, 2.7rem) clamp(2.2rem, 3.6vw, 2.9rem);
  display: grid;
  gap: 1.05rem;
  /* the note takes up the slack, so every CTA sits on the sill */
  grid-template-rows: auto auto 1fr auto;
  overflow: hidden;
  isolation: isolate;
  transition: color .5s var(--ease-soft), transform .45s var(--ease), box-shadow .45s var(--ease);
}
/* the recessed panel, following the arch */
.chapter::after {
  content: "";
  position: absolute;
  inset: 17px 27px;
  z-index: -1;
  border: 1.5px solid color-mix(in srgb, currentColor 22%, transparent);
  border-radius: 46% 46% 5px 5px / 19% 19% 3% 3%;
  pointer-events: none;
  transition: border-color .5s var(--ease-soft);
}
.chapter__knob {
  position: absolute;
  right: 6.5px;
  top: 62%;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  /* brass in both themes: it is hardware, not text */
  background: #C9A24A;
  border: 2px solid #14110D;
  box-shadow: 0 0 0 3px color-mix(in srgb, #C9A24A 28%, transparent);
  transition: transform .55s var(--ease), box-shadow .55s var(--ease);
}
.chapter:hover .chapter__knob { transform: scale(1.22); box-shadow: 0 0 0 5px color-mix(in srgb, #C9A24A 40%, transparent); }
.chapter::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--deep);
  transform: translateY(100%);
  transition: transform .7s var(--ease);
}
.chapter:hover { color: var(--deep-ink); }
.chapter:hover::before { transform: translateY(0); }
.chapter:hover .chapter__note { color: #EBC97E; }
.chapter:hover .mark { filter: invert(1); }
.chapter__idx {
  position: absolute;
  top: clamp(1.1rem, 2vw, 1.6rem);
  left: 50%;
  transform: translateX(-50%);
  /* letter-spacing trails the last numeral: give it back on the right */
  padding: .34em calc(.95em - .24em) .3em .95em;
  /* a screwed-on plate: fixed colors so it survives the hover fill */
  background: #F0D89C;
  color: #14110D;
  border: 2px solid #14110D;
  border-radius: 999px;
  font-size: .64rem;
  letter-spacing: .24em;
  line-height: 1.2;
}
.chapter__title { font-size: clamp(1.6rem, 2.2vw, 2.05rem); }
.chapter__note { font-size: .88rem; color: var(--ink-2); transition: color .5s; }
.chapter__go { display: inline-flex; align-items: center; gap: .6rem; font-size: .7rem; letter-spacing: .2em; text-transform: uppercase; margin-top: .4rem; }
.chapter__go svg { transition: transform .5s var(--ease); }
.chapter:hover .chapter__go svg { transform: translateX(6px); }
.chapter .mark { transition: filter .5s, transform .7s var(--ease); }
.chapter:hover .mark { transform: rotate(-8deg) scale(1.08); }

/* Split feature (text | art) */
.feature { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 5vw, 5rem); align-items: center; }
.feature__art { position: relative; }
.feature__art img { width: 100%; filter: invert(var(--art-invert)); }

/* The film sits beside the words on a wide screen and between the words and
   the buttons on a narrow one: a pair of buttons under a heading pushes the
   thing they are about off the bottom of the screen. */
.feature--film {
  grid-template-areas: "words film" "btns film";
  grid-template-rows: auto auto;
  align-content: center;
  row-gap: 1.75rem;
}
.feature--film .feature__words { grid-area: words; }
.feature--film .tube { grid-area: film; }
.feature--film .btns { grid-area: btns; }

/* A framed print , the mat, keyline and pinned-up tilt of the logo artwork */
.portrait {
  position: relative;
  justify-self: center;
  width: min(100%, 380px);
  margin: 0;
  transform: rotate(-2deg);
  transition: transform .7s var(--ease);
}
.portrait:hover { transform: rotate(0deg) translateY(-6px); }
.portrait__mat {
  padding: clamp(.85rem, 1.5vw, 1.25rem) clamp(.85rem, 1.5vw, 1.25rem) .9rem;
  background: var(--rose);
  border: var(--keyline);
  border-radius: var(--r-md);
  box-shadow: 10px 10px 0 var(--ink);
}
.portrait__mat img {
  width: 100%;
  height: auto;
  display: block;
  border: var(--keyline);
  border-radius: calc(var(--r-md) - 6px);
}
.portrait__cap {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding-top: .8rem;
  color: #241C16;
}
.portrait__who { font-family: var(--display); font-size: 1.05rem; line-height: 1; }
.portrait__when { font-size: .6rem; letter-spacing: .22em; text-transform: uppercase; opacity: .7; }
.portrait__star {
  position: absolute;
  top: -22px; right: -18px;
  transform: rotate(12deg);
  animation: twinkle 3.6s var(--ease-soft) infinite;
}
@keyframes twinkle {
  0%, 100% { transform: rotate(12deg) scale(1); opacity: .95; }
  50%      { transform: rotate(20deg) scale(1.16); opacity: 1; }
}

/* An embedded film, framed like everything else: ink keyline, color behind */
.tube {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: var(--keyline);
  border-radius: var(--r-md);
  overflow: hidden;
  background: #000;
  box-shadow: 10px 10px 0 var(--off, var(--gold));
  transition: box-shadow .45s var(--ease), transform .45s var(--ease);
}
.tube:hover { transform: translate(3px, 3px); box-shadow: 6px 6px 0 var(--off, var(--gold)); }
.tube iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }

.tube__poster {
  position: absolute;
  inset: 0;
  display: block;
  padding: 0;
  cursor: pointer;
  background: #14110D;
}
.tube__poster img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 1.1s var(--ease), filter .5s;
  filter: saturate(.95);
}
.tube__poster:hover img { transform: scale(1.04); filter: saturate(1.05); }
.tube__poster::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, #0000 40%, #00000073);
}
.tube__play {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  display: grid; place-items: center;
  width: 74px; height: 74px;
  padding-left: 5px;
  border-radius: 50%;
  background: #E2604F;
  color: #14110D;
  box-shadow: 0 0 0 2px #14110D, 0 10px 30px #0006;
  transition: transform .4s var(--ease), background-color .35s;
  z-index: 2;
}
.tube__poster:hover .tube__play { transform: translate(-50%, -50%) scale(1.09); background: #F0806F; }
.tube__label {
  position: absolute;
  left: 50%; bottom: 1.1rem;
  transform: translateX(-50%);
  z-index: 2;
  font-size: .66rem;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: #F9F2E4;
  white-space: nowrap;
}
.tube__cta { color: #F9F2E4; }

/* Quote */
/* Let the quote use its whole column: at 26ch the handwriting broke into
   five stubby lines. The open mark now sits on the first line, not above it. */
.quote { max-width: 100%; }
.quote__mark { font-family: var(--display); font-size: 3.2rem; line-height: 0; color: var(--coral); opacity: .8; float: left; margin: .42em .12em 0 -.06em; }

/* Who: the words on the left, a loose pile of three photographs on the right.
   initSnaps in site.js deals the photographs: fresh on every load, and again
   whenever someone clicks an empty spot in the section. A deal gathers the
   prints into one stack in the middle of the column, then throws them back out
   to their places, where each settles into its tilt with a little spring. Under
   a mouse a print can be picked up and moved; the last one picked up stays on top. */
.who__grid { align-items: center; }
/* the empty space in the section is what shuffles, so under a mouse it says so,
   while the words keep their text cursor */
.who { cursor: pointer; }
.who :is(p, h2, .sec-head__idx, .quote, hr) { cursor: auto; }

.snaps {
  /* a settle that overshoots a touch and comes back, like a print landing */
  --spring: cubic-bezier(.32, 1.35, .5, 1);
  position: relative;
  width: 100%;
  max-width: 580px;
  justify-self: center;
  /* the pile's footprint is fixed, so whatever gets dealt, the page never moves */
  aspect-ratio: 1 / 1.34;
}
/* no script means no photographs, so the empty pile takes no room */
.snaps:empty { display: none; }
.snap {
  position: absolute;
  width: 42%;
  padding: .5rem .5rem .65rem;
  background: var(--paper);
  border: var(--keyline);
  border-radius: var(--r-sm);
  box-shadow: 6px 6px 0 var(--off, var(--blue));
  transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(var(--tilt, 0deg));
  translate: 0 0;
  rotate: 0deg;
  /* dealt: out of the stack to its place, one after another, with a spring */
  transition: transform .5s var(--ease), box-shadow .5s var(--ease),
              translate .7s var(--spring) var(--sd, 0ms), rotate .7s var(--spring) var(--sd, 0ms);
}
.snap img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border: 1.5px solid var(--ink);
  border-radius: 5px;
  background: var(--paper-3);
  /* the frame is what gets dragged, never the picture inside it */
  pointer-events: none;
  -webkit-user-drag: none;
}
.snap__cap { display: grid; gap: .2rem; padding: .55rem .2rem 0; }
.snap__where { font-family: var(--display); font-size: clamp(.9rem, 1.2vw, 1.05rem); line-height: 1.15; color: var(--ink); }
.snap__when { font-size: .58rem; letter-spacing: .22em; text-transform: uppercase; color: var(--ink-3); }

/* Where each one lands, with its own tilt and color, and the lean it takes
   while it sits in the stack. A zig-zag down the column: every caption stays
   clear, and the only overlap is the right-hand print resting on a top corner
   of the one below it. Dealt in reading order. */
.snap:nth-child(1) { top: 0;    left: 1%;  --tilt: -4deg; --lean: -8deg; --off: var(--blue); }
.snap:nth-child(2) { bottom: 0; left: 21%; --tilt: 3deg;  --lean: 6deg;  --off: var(--rose); --sd: 160ms; }
.snap:nth-child(3) { top: 23%;  right: 1%; --tilt: -2deg; --lean: -1deg; --off: var(--gold); --sd: 80ms; }

/* On a narrow screen the prints are too small to half-hide: one over two. */
@media (max-width: 620px) {
  .snaps { max-width: 420px; aspect-ratio: 1 / 1.6; }
  .snap { width: 49%; }
  .snap:nth-child(1) { top: auto; bottom: 0; left: 0;     --sd: 80ms; }
  .snap:nth-child(2) { top: 0; bottom: auto; left: 25.5%; --sd: 0ms; }
  .snap:nth-child(3) { top: auto; bottom: 0; right: 0;    --sd: 160ms; }
}

/* Gathered: all three in one stack in the middle of the column, each at its
   own slight lean (initSnaps measures the trip into --gx and --gy). They wait
   here until the stack scrolls into view, and come back here for every
   shuffle. Gathering is quick and even; only the deal out gets the spring. */
.snaps:not(.is-dealt) .snap {
  translate: var(--gx, 0px) var(--gy, 0px);
  rotate: calc(var(--lean, 0deg) - var(--tilt, 0deg));
  pointer-events: none;
  transition-duration: .34s;
  transition-delay: 0ms;
  transition-timing-function: var(--ease-soft);
}
/* the moment the new photographs go on, nothing may animate */
.snaps.is-swapping .snap { transition: none; }

/* The hint sits in the one corner the pile never covers, and only shows while
   a mouse is over the section. */
.snaps__hint {
  position: absolute;
  right: 1%;
  bottom: 1.5%;
  max-width: 34%;
  text-align: right;
  text-wrap: balance;
  font-size: .62rem;
  line-height: 1.7;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--ink-3);
  opacity: 0;
  transition: opacity .45s var(--ease-soft);
}
.who:hover .snaps__hint { opacity: 1; }
@media (hover: none), (max-width: 620px) { .snaps__hint { display: none; } }

/* hover straightens a print and lifts it off the table */
.snap:hover {
  transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(0deg) scale(1.03);
  box-shadow: 9px 10px 0 var(--off, var(--blue));
}
/* the shared drag rule sets position: relative, which would pull a print out of the pile */
.snaps .snap.is-dragging { position: absolute; box-shadow: 13px 15px 0 var(--off, var(--blue)); }

/* 9 ── TIMELINE ────────────────────────────────────────────────────────── */

.page-head { padding-top: clamp(8rem, 15vw, 12rem); padding-bottom: clamp(3rem, 6vw, 5rem); }
.page-head__row { display: flex; align-items: flex-end; justify-content: space-between; gap: 2rem; flex-wrap: wrap; }

.yearbar {
  position: sticky; top: var(--nav-h); z-index: 60;
  display: flex; align-items: center; gap: 1.5rem;
  padding: .85rem var(--gutter);
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-block: 1px solid var(--line-2);
  overflow-x: auto;
  scrollbar-width: none;
}
.yearbar::-webkit-scrollbar { display: none; }
.yearbar__label { font-size: .64rem; letter-spacing: .24em; text-transform: uppercase; color: var(--ink-3); flex: none; }
.yearbar__list { display: flex; gap: .4rem; }
.yearbtn {
  position: relative;
  padding: .45em 1.1em;
  border-radius: 999px;
  font-size: .74rem;
  letter-spacing: .1em;
  color: var(--ink-2);
  white-space: nowrap;
  transition: color .35s, background-color .45s var(--ease-soft), box-shadow .35s;
}
.yearbtn:hover { color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
.yearbtn.is-on { background: var(--deep); color: var(--deep-ink); }
[data-theme="dusk"] .yearbtn.is-on { background: var(--gold); color: #14110D; }
/* a hairline between a page's own jumps and the links to other pages */
.yearbar__rule { flex: none; align-self: stretch; width: 1px; background: var(--line); }
a.yearbtn { display: inline-block; }

.timeline { position: relative; padding-block: clamp(3rem, 6vw, 5rem); --rail: 1.7rem; }
.timeline__spine { position: absolute; left: max(var(--gutter), calc(50vw - var(--maxw) / 2 + var(--gutter))); top: 0; bottom: 0; width: 1px; background: var(--line); }
.timeline__spine::after { content: ""; position: absolute; inset: 0 0 auto 0; height: var(--spine, 0%); background: linear-gradient(180deg, var(--blue), var(--sage-500) 28%, var(--gold) 52%, var(--coral) 76%, var(--wine)); }

.chap { position: relative; display: grid; grid-template-columns: 200px 1fr; gap: clamp(1.5rem, 4vw, 4rem); padding-block: clamp(2.5rem, 5vw, 4.5rem); }
.chap + .chap { border-top: 1px solid var(--line-2); }
.chap__aside { position: relative; }
/* The spine runs down the aside's left edge, so content has to clear it. */
.chap__sticky { position: sticky; top: calc(var(--nav-h) + 4.75rem); display: grid; gap: .55rem; padding-left: var(--rail); }
/* The aside's left edge sits exactly on the spine, so center the dot on it. */
.chap__dot { position: absolute; left: -4.5px; top: .55rem; width: 9px; height: 9px; border-radius: 50%; background: var(--paper); box-shadow: inset 0 0 0 1px var(--ink-3); transition: background-color .5s, box-shadow .5s, transform .5s var(--ease); }
.chap.is-in .chap__dot { background: var(--wine); box-shadow: inset 0 0 0 1px var(--wine), 0 0 0 5px color-mix(in srgb, var(--wine) 14%, transparent); transform: scale(1.1); }
.chap__date { font-family: var(--display); font-size: 1.05rem; letter-spacing: .01em; color: var(--brass-ink); }

/* The open chapter , the archive is not finished */
.chap--open .chap__place { color: var(--ink-3); }
.chap--open .chap__dot {
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--brass);
  animation: breathe 3.4s var(--ease-soft) infinite;
}
.chap--open.is-in .chap__dot { background: transparent; box-shadow: inset 0 0 0 1px var(--brass); transform: none; }
@keyframes breathe {
  0%, 100% { box-shadow: inset 0 0 0 1px var(--brass), 0 0 0 0 color-mix(in srgb, var(--brass) 40%, transparent); }
  50%      { box-shadow: inset 0 0 0 1px var(--brass), 0 0 0 7px color-mix(in srgb, var(--brass) 0%, transparent); }
}
.chap__body { display: grid; gap: 1.4rem; max-width: 62ch; }
.chap__place { font-size: clamp(1.7rem, 3.1vw, 2.7rem); }
.chap__text { color: var(--ink-2); font-size: 1rem; line-height: 1.66; }

/* Gallery , a small mosaic that changes shape with the number of photographs */
.strip { display: grid; gap: .7rem; margin-top: .6rem; }
.strip[data-n="1"] { grid-template-columns: 1fr; }
.strip[data-n="1"] .shot { aspect-ratio: 16 / 10; }
.strip[data-n="2"] { grid-template-columns: 1fr 1fr; }
.strip[data-n="2"] .shot { aspect-ratio: 4 / 5; }
.strip[data-n="3"] {
  grid-template-columns: 1.35fr 1fr;
  grid-template-rows: repeat(2, minmax(0, 1fr));
  aspect-ratio: 16 / 11;
}
.strip[data-n="3"] .shot { aspect-ratio: auto; }
.strip[data-n="3"] .shot:first-child { grid-row: span 2; }
.strip[data-n="4"] { grid-template-columns: repeat(2, 1fr); }
.strip[data-n="4"] .shot { aspect-ratio: 4 / 3; }
.strip[data-n="5"], .strip[data-n="6"] { grid-template-columns: repeat(3, 1fr); }
.strip[data-n="5"] .shot, .strip[data-n="6"] .shot { aspect-ratio: 4 / 5; }

.shot {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border: var(--keyline);
  border-radius: var(--r-sm);
  background: var(--paper-3);
  cursor: zoom-in;
}
.shot img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 1.1s var(--ease), filter .6s;
  filter: saturate(.92) contrast(1.02);
}
.shot::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 55%, color-mix(in srgb, var(--ink) 45%, transparent));
  opacity: 0; transition: opacity .5s;
}
.shot:hover img { transform: scale(1.06); filter: saturate(1) contrast(1.04); }
.shot:hover::after { opacity: 1; }

/* 10 ── TABLES & DRINKS ────────────────────────────────────────────────── */

.pours { display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(1rem, 2.5vw, 2rem); }
.glass {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: "art n" "art name" "art ings";
  column-gap: clamp(1.25rem, 2.6vw, 2.25rem);
  row-gap: .85rem;
  align-content: center;
  padding: clamp(1.6rem, 2.6vw, 2.4rem);
  border-radius: var(--r-md);
  overflow: hidden;
  isolation: isolate;
  cursor: pointer;
}
.glass::before {
  content: ""; position: absolute; inset: auto 0 0 0; z-index: -1;
  height: 0;
  background: var(--liquid, var(--sage-500));
  opacity: .13;
  transition: height 1.1s var(--ease);
}

.glass:hover::before, .glass.is-full::before { height: 100%; }

/* The glass itself , line art that fills when you hover the card */
.glass__art { grid-area: art; align-self: center; width: clamp(84px, 9vw, 118px); height: auto; color: var(--ink); }
.glass__art .ln { fill: none; stroke: currentColor; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.glass__garnish { opacity: .45; transition: opacity .6s var(--ease); }
.glass:hover .glass__garnish, .glass.is-full .glass__garnish { opacity: 1; }
/* once the glass is full the fruit takes its color: the citrus wheel goes
   lemon and gives a quarter turn, the blackberries fill one after another */
.glass__art .glass__fruit { fill: transparent; transition: fill .45s var(--ease-soft) .35s; }
.glass:hover .glass__fruit, .glass.is-full .glass__fruit { fill: var(--fruit); }
.glass__wheel { transform-box: fill-box; transform-origin: center; transition: transform .9s cubic-bezier(.34, 1.4, .64, 1) .3s; }
.glass:hover .glass__wheel, .glass.is-full .glass__wheel { transform: rotate(60deg); }
.glass__berry { transform-box: fill-box; transform-origin: center; transition: fill .3s var(--ease-soft) var(--bd, .35s), scale .45s cubic-bezier(.34, 1.8, .64, 1) var(--bd, .35s); }
.glass:hover .glass__berry, .glass.is-full .glass__berry { scale: 1.12; }
.glass__berry:nth-of-type(2) { --bd: .41s; }
.glass__berry:nth-of-type(3) { --bd: .47s; }
.glass__berry:nth-of-type(4) { --bd: .53s; }
.glass__berry:nth-of-type(5) { --bd: .59s; }
.glass__berry:nth-of-type(6) { --bd: .65s; }
.glass__berry:nth-of-type(7) { --bd: .71s; }
/* and the ice: it frosts over, catches a glint of light, and floats up on the
   pour with a little tip, the second cube a beat behind the first */
.glass__art .glass__cube { fill: transparent; transition: fill .5s var(--ease-soft) .3s; }
.glass:hover .glass__cube, .glass.is-full .glass__cube { fill: color-mix(in srgb, #EAF5F8 80%, transparent); }
[data-theme="dusk"] .glass:hover .glass__cube,
[data-theme="dusk"] .glass.is-full .glass__cube { fill: color-mix(in srgb, #CFE6EC 80%, transparent); }
.glass__glint { fill: none; stroke: #fff; stroke-width: 2.2; stroke-linecap: round; opacity: 0; transition: opacity .4s var(--ease-soft) .75s; }
.glass:hover .glass__glint, .glass.is-full .glass__glint { opacity: .95; }
/* dusk draws in light ink, which disappears on a lemon wheel or frosted ice,
   so once a glass is full its whole drawing takes a deep shade of the drink
   (--line-dusk on each card: burned orange for the tiger, plum for the bear),
   kept light enough to hold 3:1 on the dark card. The ice goes deep teal and
   the blackberries a darker purple, so each still reads against its fill. */
[data-theme="dusk"] .glass__art .ln:not(.glass__berry) { transition: stroke .45s var(--ease-soft) .35s, fill .5s var(--ease-soft) .3s; }
[data-theme="dusk"] .glass__art .glass__berry { transition: fill .3s var(--ease-soft) var(--bd, .35s), stroke .3s var(--ease-soft) var(--bd, .35s), scale .45s cubic-bezier(.34, 1.8, .64, 1) var(--bd, .35s); }
[data-theme="dusk"] .glass:is(:hover, .is-full) .glass__art .ln { stroke: var(--line-dusk, currentColor); }
[data-theme="dusk"] .glass:is(:hover, .is-full) .glass__art .glass__cube { stroke: #1F4F62; }
[data-theme="dusk"] .glass:is(:hover, .is-full) .glass__art .glass__berry { stroke: #3E1230; }
.glass__ice {
  transform-box: fill-box;
  transform-origin: center;
  transition: translate 1.1s cubic-bezier(.34, 1.45, .64, 1) var(--id, .2s), rotate 1.1s cubic-bezier(.34, 1.45, .64, 1) var(--id, .2s);
}
.glass__ice + .glass__ice { --id: .34s; }
.glass:hover .glass__ice, .glass.is-full .glass__ice { translate: 0 -8px; rotate: 7deg; }
.glass:hover .glass__ice + .glass__ice, .glass.is-full .glass__ice + .glass__ice { translate: 1px -6px; rotate: -6deg; }
@media (prefers-reduced-motion: reduce) {
  .glass__wheel, .glass__berry, .glass__art .glass__fruit { transition: none; }
  .glass:hover .glass__wheel, .glass.is-full .glass__wheel { transform: none; }
  .glass:hover .glass__berry, .glass.is-full .glass__berry { scale: 1; }
  .glass__ice, .glass__glint, .glass__art .glass__cube { transition: none; }
  .glass:hover .glass__ice, .glass.is-full .glass__ice,
  .glass:hover .glass__ice + .glass__ice, .glass.is-full .glass__ice + .glass__ice { translate: none; rotate: none; }
}
.glass__pourfill {
  transform: translateY(66px);
  transition: transform 1.25s var(--ease);
  opacity: .88;
}
.glass:hover .glass__pourfill, .glass.is-full .glass__pourfill { transform: translateY(0); }

.glass__n { grid-area: n; font-size: .68rem; letter-spacing: .24em; color: var(--brass-ink); }
.glass__name { grid-area: name; font-size: clamp(1.5rem, 2.4vw, 2.05rem); }
.glass__ings { grid-area: ings; display: grid; gap: .35rem; }
.glass__ing {
  font-size: .78rem; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-2);
  opacity: .55; transform: translateY(4px);
  transition: opacity .6s var(--ease) var(--d, 0ms), transform .6s var(--ease) var(--d, 0ms);
}
.glass:hover .glass__ing, .glass.is-full .glass__ing { opacity: 1; transform: none; }

.tables { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1.2rem, 2.4vw, 2rem); }
/* Corners, ink and the offset color all come from the shared card rule
   further up; this only handles layout. */
.table-card {
  position: relative;
  display: grid;
  grid-template-rows: auto 1fr;
  border-radius: var(--r-md);
  overflow: hidden;
  transform-style: preserve-3d;
}

.table-card__pic { position: relative; aspect-ratio: 3 / 2; overflow: hidden; background: var(--paper-3); border-bottom: var(--keyline); border-radius: calc(var(--r-md) - 3px) calc(var(--r-md) - 3px) 0 0; }
.table-card__pic img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.2s var(--ease), filter .6s; filter: saturate(.9); }
.table-card:hover .table-card__pic img { transform: scale(1.07); filter: saturate(1.05); }
/* The number sits over a photograph, so it carries its own dark chip
   rather than relying on whatever happens to be behind it. */
.table-card__no {
  position: absolute; top: .7rem; left: .7rem;
  display: grid; place-items: center;
  min-width: 2.1em; height: 2.1em;
  padding-inline: .35em;
  border-radius: 999px;
  background: #14110D;
  font-family: var(--display);
  font-size: 1.1rem; line-height: 1;
  color: #F9F2E4;
}
.table-card__pic--empty {
  display: grid;
  place-items: center;
  gap: .7rem;
  background: var(--off, var(--blue));
  color: #14110D;
}
.table-card__pic--empty svg { width: 42%; max-width: 92px; height: auto; opacity: .75; }
.table-card__soon {
  font-size: .6rem;
  letter-spacing: .24em;
  text-transform: uppercase;
  opacity: .8;
}

.table-card__body { display: grid; gap: .6rem; align-content: start; padding: 1.4rem 1.5rem 1.6rem; }
.table-card__name { font-size: 1.35rem; }
.table-card__meta { font-size: .68rem; letter-spacing: .2em; text-transform: uppercase; color: var(--brass-ink); }
.table-card__note { font-size: .86rem; line-height: 1.6; color: var(--ink-2); }
.table-card__addr { font-size: .76rem; color: var(--ink-3); letter-spacing: .02em; }
.table-card__go { justify-self: start; margin-top: .4rem; display: inline-flex; align-items: center; gap: .5rem; font-size: .68rem; letter-spacing: .2em; text-transform: uppercase; color: var(--ink); border-bottom: 1px solid var(--line); padding-bottom: 3px; transition: color .35s, border-color .35s, gap .35s var(--ease); }
.table-card__go:hover { color: var(--wine); border-color: var(--wine); gap: .8rem; }

/* Menu card */
.menu { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(2rem, 4vw, 3.5rem); }
.menu__col { display: grid; gap: 1.4rem; align-content: start; }
.menu__head { display: grid; gap: .8rem; }
.menu__title { font-size: 1.55rem; }
.menu__list { display: grid; gap: 1.05rem; margin: 0; padding: 0; list-style: none; }
.menu__item { display: grid; gap: .2rem; padding-bottom: 1.05rem; border-bottom: 1px solid var(--line-2); }
.menu__item:last-child { border-bottom: 0; padding-bottom: 0; }
.menu__dish { font-size: .93rem; letter-spacing: .04em; }
.menu__desc { font-size: .74rem; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.menu__v { color: var(--sage-600); }
[data-theme="dusk"] .menu__v { color: var(--sage-300); }
.band--deep .menu__v { color: #A9CDB4; }

/* 11 ── THE DAY ────────────────────────────────────────────────────────── */

/* The date, then the toast illustration beneath it as a signature.
   (The artwork carries its own hand-lettered "Highlights", so nothing overlaps it.) */
.toast { position: relative; display: grid; justify-items: center; gap: clamp(1rem, 2.5vw, 2rem); margin-top: clamp(1rem, 3vw, 2rem); }
.toast__art { width: 100%; max-width: 1080px; height: auto; }
.toast__art--dusk { display: none; }
[data-theme="dusk"] .toast__art--dawn { display: none; }
[data-theme="dusk"] .toast__art--dusk { display: block; }
.toast__date { display: grid; gap: .9rem; justify-items: center; }
.toast__date .tag { color: var(--ink-3); }

.day-hero { position: relative; text-align: center; display: grid; gap: 1.6rem; justify-items: center; }
.day-date { display: flex; align-items: baseline; justify-content: center; gap: clamp(.4rem, 1.6vw, 1.2rem); flex-wrap: nowrap; margin: 0; }
.day-date__part { font-family: var(--display); font-size: clamp(3rem, 13vw, 11rem); line-height: .92; letter-spacing: -.015em; }
.day-date__part--roman { letter-spacing: .02em; color: var(--page-ink, var(--ink-2)); }
.day-date__sep { font-family: var(--display); font-size: clamp(1.4rem, 5vw, 4rem); line-height: .92; color: var(--page-ink, var(--ink-3)); opacity: .55; }
.toast .day-date__part { font-size: clamp(2.6rem, 11vw, 9.5rem); }
.day-ring { width: clamp(90px, 12vw, 150px); filter: invert(var(--art-invert)); opacity: .85; }

/* The band the summary cards sit in. They are the same object on every page
   that has them, so the room around them is the same too, and the rule lives
   here beside .facts rather than in trip.css or year.css: day.html loads
   neither of those and had been carrying the full band padding, close to
   twice the top and four times the bottom of everywhere else. */
.band--facts { padding-block: clamp(3rem, 6vw, 5rem) clamp(1.25rem, 2.5vw, 2rem); }

.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: clamp(.9rem, 1.6vw, 1.4rem); }
/* four of them: two by two once four no longer fit, then one, never three
   with the fourth alone underneath */
@media (max-width: 900px) { .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .facts { grid-template-columns: minmax(0, 1fr); } }
.fact { background: var(--paper); border: var(--keyline); border-radius: var(--r-md); padding: clamp(1.5rem, 2.6vw, 2.1rem); display: grid; gap: .6rem; align-content: start; }
.band--deep .fact { background: transparent; border-color: var(--deep-ink); }
.fact__k { font-size: .66rem; letter-spacing: .24em; text-transform: uppercase; color: var(--brass-ink); }
.fact__v { font-family: var(--display); font-size: clamp(1.3rem, 2.1vw, 1.75rem); line-height: 1.16; }
.fact__s { font-size: .8rem; color: var(--ink-3); }

/* Thanks: four snapshot cards, each with a picture of who it thanks. They
   lean at their own angles and step up and down the row; under a mouse a
   card straightens and lifts. The reveal sits on the slot so the card's own
   lean and lift never fight it. */
.credits {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(1.25rem, 2.6vw, 2.5rem);
  align-items: start;
}
.credits__slot:nth-child(1) { --off: var(--blue);     --tilt: -2deg; }
.credits__slot:nth-child(2) { --off: var(--gold);     --tilt:  1.6deg; margin-top: clamp(1.5rem, 3.5vw, 3rem); }
.credits__slot:nth-child(3) { --off: var(--sage-500); --tilt: -1.2deg; }
.credits__slot:nth-child(4) { --off: var(--coral);    --tilt:  2.2deg; margin-top: clamp(1.5rem, 3.5vw, 3rem); }

.credit {
  position: relative;
  display: grid;
  gap: .55rem;
  justify-items: start;
  padding: .65rem .65rem 1.1rem;
  color: var(--ink);
  text-decoration: none;
  background: var(--paper);
  border: var(--keyline);
  border-radius: var(--r-sm);
  box-shadow: 6px 6px 0 var(--off, var(--rose));
  rotate: var(--tilt, 0deg);
  transition: rotate .5s var(--ease), translate .5s var(--ease), box-shadow .5s var(--ease);
}
.credit:hover { rotate: 0deg; translate: 3px 3px; box-shadow: 3px 3px 0 var(--off, var(--rose)); }

.credit__pic {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  margin-bottom: .35rem;
  border: 1.5px solid var(--ink);
  border-radius: calc(var(--r-sm) - 3px);
  background: color-mix(in srgb, var(--off, var(--rose)) 30%, var(--paper));
}
.credit__pic img { width: 100%; height: 100%; object-fit: cover; transition: transform .8s var(--ease); }
.credit:hover .credit__pic img { transform: scale(1.06); }
/* the two characters, side by side, cropped at the waist */
.credit__pic--art { display: flex; justify-content: center; align-items: flex-start; padding-top: 12%; }
.credit__fig { position: relative; width: 52%; margin-inline: -3%; transform-origin: 50% 20%; transition: transform .8s var(--ease); }
.credit__pic--art .credit__fig img { display: block; width: 100%; height: auto; object-fit: contain; transition: none; }
.credit__pic--art .credit__fig img + img { position: absolute; inset: 0; }   /* line art over its color */
.credit:hover .credit__pic--art img { transform: none; }
.credit:hover .credit__fig:first-child { transform: rotate(-4deg); }
.credit:hover .credit__fig:last-child  { transform: rotate(4deg); }

.credit__role {
  font-family: var(--sans);
  font-size: .6rem; font-weight: 500;
  letter-spacing: .22em; text-transform: uppercase;
  color: var(--ink);
  background: color-mix(in srgb, var(--off, var(--rose)) 38%, var(--paper));
  border: 1.5px solid var(--ink);
  border-radius: 999px;
  padding: .3em .85em .25em;
}
.credit__name {
  font-family: var(--display);
  font-size: clamp(1.05rem, 1.45vw, 1.3rem);
  line-height: 1.15;
  overflow-wrap: anywhere;
  padding-inline: .15rem;
}
.credit--all .credit__name {
  font-family: var(--hand);
  font-weight: 700;
  font-size: clamp(1.45rem, 2vw, 1.8rem);
  line-height: 1;
  color: var(--page-ink, var(--coral));
  rotate: -2deg;
}

.credit__go {
  position: absolute;
  top: -.85rem; right: -.85rem;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  color: var(--paper);
  background: var(--ink);
  border-radius: 50%;
  transition: transform .5s var(--ease);
}
.credit:hover .credit__go { transform: rotate(45deg) scale(1.08); }

[data-theme="dusk"] .credit__role { background: var(--off, var(--rose)); color: #14110D; border-color: #14110D; }

@media (max-width: 900px) {
  .credits { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .credits__slot:nth-child(3) { margin-top: 0; }
}
@media (max-width: 520px) {
  .credits { grid-template-columns: 1fr; gap: 1.5rem; }
  .credits__slot:nth-child(n) { margin-top: 0; }
  .credit { rotate: calc(var(--tilt, 0deg) * .35); }   /* a wide card only needs a hint of lean */
  .credit { grid-template-columns: 88px minmax(0, 1fr); column-gap: 1rem; row-gap: .4rem; align-items: center; align-content: center; padding: .6rem; }
  .credit__pic { grid-row: 1 / span 2; margin: 0; }
  .credit__role, .credit__name { grid-column: 2; }
  .credit__role { align-self: end; }
  .credit__name { align-self: start; }
}
@media (prefers-reduced-motion: reduce) {
  .credit, .credit__pic img, .credit__go { transition: none; }
}

/* Vows: two letters that lean in towards each other ────────────────────
   Each is a card with a printed photo tucked over its top edge, the promise
   in David's and Yinja's own hand, and their signature to close. David's
   card sits left with his photo on the outside, Yinja's mirrors it a step
   lower, and an "I do" sticker is stamped between them. As a card arrives a
   highlighter picks out every "I promise", the same marker the speeches use.
   The reveal sits on the slot, so the card's own lean never fights it. */

.vows {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(2.25rem, 6vw, 5.5rem);
  align-items: start;
  padding-top: clamp(1.75rem, 3vw, 2.75rem);          /* room for the photos over the top edge */
}
.vows__slot:first-child { --off: var(--blue); --lean:  1deg;   --tip: -4deg; }
.vows__slot:last-child  { --off: var(--gold); --lean: -1deg;   --tip:  4deg; margin-top: clamp(2rem, 5vw, 4.5rem); }

.vow {
  position: relative;
  display: grid;
  grid-template-columns: clamp(112px, 11.5vw, 158px) minmax(0, 1fr);
  gap: clamp(1.1rem, 2.2vw, 1.9rem);
  padding: clamp(1.4rem, 2.4vw, 2rem) clamp(1.4rem, 2.4vw, 2.1rem) clamp(1rem, 1.8vw, 1.4rem);
  background: color-mix(in srgb, var(--off) 13%, var(--paper));
  border: var(--keyline);
  border-radius: var(--r-md);
  box-shadow: 7px 7px 0 var(--off);
  align-items: start;
  rotate: var(--lean);
  transition: rotate .6s var(--ease), translate .45s var(--ease), box-shadow .45s var(--ease);
}
/* a second, finer frame inside the first, like printed stationery */
.vow::before {
  content: "";
  position: absolute;
  inset: 8px;
  border: 1.5px solid color-mix(in srgb, var(--off) 75%, var(--paper));
  border-radius: 8px;
  pointer-events: none;
}
.vow:hover { rotate: 0deg; translate: 3px 3px; box-shadow: 4px 4px 0 var(--off); }

.vow__pic {
  position: relative;
  z-index: 1;
  margin: calc(-1 * clamp(2.9rem, 5vw, 4rem)) 0 0;
  padding: 6px;
  background: var(--paper);
  border: var(--keyline);
  border-radius: 6px;
  box-shadow: 4px 4px 0 color-mix(in srgb, var(--off) 80%, var(--ink));
  rotate: var(--tip);
  transition: rotate .7s cubic-bezier(.34, 1.4, .64, 1);
}
.vow__pic img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; border-radius: 3px; }
.vow:hover .vow__pic { rotate: calc(var(--tip) * -.5); }

.vow__body { display: grid; gap: .85rem; align-content: start; min-width: 0; }
.vow__to {
  justify-self: start;
  margin: 0;
  font-family: var(--sans);
  font-size: .62rem; font-weight: 500;
  letter-spacing: .22em; text-transform: uppercase; line-height: 1.2;
  color: var(--ink);
  background: color-mix(in srgb, var(--off) 45%, var(--paper));
  border: 1.5px solid var(--ink);
  border-radius: 999px;
  padding: .35em .9em .3em;
}
.vow__text {
  margin: 0;
  font-family: var(--hand);
  font-weight: 500;
  font-size: clamp(1.3rem, 1.75vw, 1.55rem);
  line-height: 1.34;
  color: var(--ink);
}
.vow__promise {
  font-weight: 700;
  background-image: linear-gradient(color-mix(in srgb, var(--off) 75%, transparent), color-mix(in srgb, var(--off) 75%, transparent));
  background-repeat: no-repeat;
  background-position: 0 88%;
  background-size: 0% .42em;
  transition: background-size .7s var(--ease) calc(var(--d, 0ms) + .75s);
}
.vow__promise:nth-of-type(2) { transition-delay: calc(var(--d, 0ms) + .95s); }
.vow__promise:nth-of-type(3) { transition-delay: calc(var(--d, 0ms) + 1.15s); }
.is-in .vow__promise { background-size: 100% .42em; }
/* in dusk the text is light, so a band behind the letters would put cream on
   gold; the marker drops below the words instead and becomes an underline */
[data-theme="dusk"] .vow__promise { background-image: linear-gradient(var(--off), var(--off)); background-position: 0 100%; background-size: 0% .14em; }
[data-theme="dusk"] .is-in .vow__promise { background-size: 100% .14em; }

.vow__sign {
  justify-self: end;
  width: clamp(112px, 10vw, 146px);
  height: auto;
  margin: -1rem -.4rem -1.1rem 0;                     /* the artwork carries its own margins */
  rotate: -5deg;
  filter: invert(var(--art-invert));
}

/* mirrored: Yinja's photo on the outside edge */
.vows__slot:last-child .vow { grid-template-columns: minmax(0, 1fr) clamp(112px, 11.5vw, 158px); }
.vows__slot:last-child .vow__pic  { grid-column: 2; grid-row: 1; }
.vows__slot:last-child .vow__body { grid-column: 1; grid-row: 1; }

/* the sticker between the two cards: colors pinned, like the curtain's ampersand */
.vows__stamp {
  position: absolute;
  z-index: 3;
  left: 50%;
  top: clamp(3.25rem, 7vw, 6rem);
  translate: -50% 0;
  width: clamp(62px, 5.8vw, 78px);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  border: 2px solid #14110D;
  border-radius: 50%;
  background: #F0CE84;
  color: #14110D;
  box-shadow: 3px 3px 0 #14110D;
  font-family: var(--hand);
  font-weight: 700;
  font-size: clamp(1.35rem, 2vw, 1.75rem);
  line-height: 1;
  rotate: -8deg;
  transition: rotate .6s cubic-bezier(.34, 1.56, .64, 1), scale .6s cubic-bezier(.34, 1.56, .64, 1);
}
.vows__stamp span { translate: 0 .06em; }
.vows__star { position: absolute; fill: var(--brass); transition: rotate .8s var(--ease), scale .8s var(--ease); }
.vows__star--a { width: 16px; top: -12px; right: -14px; }
.vows__star--b { width: 11px; bottom: -6px; left: -16px; }
.vows:hover .vows__stamp { rotate: 5deg; scale: 1.06; }
.vows:hover .vows__star { rotate: 90deg; scale: 1.2; }

[data-reveal="stamp"]:not(.is-in) { opacity: 0; }
[data-reveal="stamp"].is-in { animation: vow-stamp .6s cubic-bezier(.34, 1.56, .64, 1) .5s backwards; }
@keyframes vow-stamp { from { opacity: 0; scale: 1.8; rotate: -30deg; } }

[data-theme="dusk"] .vow__to { background: var(--off); color: #14110D; border-color: #14110D; }

@media (max-width: 900px) {
  .vows { grid-template-columns: 1fr; padding-top: clamp(2.25rem, 6vw, 3rem); }
  .vows__slot:first-child { --lean: .5deg; }
  .vows__slot:last-child  { --lean: -.5deg; margin-top: 0; }
  .vows__stamp { position: relative; left: auto; top: auto; translate: none; justify-self: center; margin: -1.1rem 0 1.9rem; }
}
@media (max-width: 620px) {
  .vow,
  .vows__slot:last-child .vow { grid-template-columns: 1fr; }
  .vow__pic { width: 140px; }
  .vows__slot:last-child .vow__pic  { grid-column: 1; grid-row: 1; justify-self: end; }
  .vows__slot:last-child .vow__body { grid-column: 1; grid-row: 2; }
}
@media (prefers-reduced-motion: reduce) {
  .vow, .vow__pic, .vows__stamp, .vows__star, .vow__promise { transition: none; }
  [data-reveal="stamp"].is-in { animation: none; }
}

/* Speeches: five cards on a rail that scrolls itself ───────────────────
   Set out as a grid of portraits, each speech had to hold a photograph, a
   name, a role and a quote inside one card, and no two screens wanted the
   same shape: two up on a desktop, one up on a tablet, stacked on a phone,
   and none of it fitted a phone held sideways. A rail asks for one shape
   only, so it is the same card from 320px to a wide desktop, and the page
   no longer grows by the length of a speech. Each card carries the line its
   speech is remembered for; the whole speech opens in a window over the
   page. The rail is a real scroller, so a thumb can push it about and the
   keyboard can reach it; initTalk only nudges it along.                  */

.talk {
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  -ms-overflow-style: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
}
.talk::-webkit-scrollbar { display: none; }
/* room above and below for the pulled-out quote mark, the tilts and the
   printed offset, none of which a scroller will make room for by itself */
.talk__track {
  display: flex;
  /* hung from the names rather than stood on the bubbles: a long line and a
     short one make bubbles of different heights, and it is the row of faces
     the eye reads along */
  align-items: flex-end;
  gap: clamp(1.1rem, 2.4vw, 1.9rem);
  width: max-content;
  padding: 2.6rem var(--gutter) 1.6rem;
}

.talk__item {
  flex: none;
  width: clamp(252px, 74vw, 348px);
  --off: var(--blue);
  --tilt: -1.5deg;
}
.talk__item[data-tone="1"] { --off: var(--blue);     --tilt: -1.5deg; }
.talk__item[data-tone="2"] { --off: var(--sage-500); --tilt:  1.4deg; }
.talk__item[data-tone="3"] { --off: var(--gold);     --tilt: -1.1deg; }
.talk__item[data-tone="4"] { --off: var(--coral);    --tilt:  1.6deg; }
.talk__item[data-tone="5"] { --off: var(--wine);     --tilt: -1.3deg; }

/* the card is a link to the speech itself, which is on the page under it */
.talk__card {
  display: grid;
  grid-template-columns: 54px minmax(0, 1fr);
  grid-template-areas: "line line" "pic  who";
  gap: .9rem .75rem;
  color: var(--ink);
}
.talk__line {
  grid-area: line;
  position: relative;
  padding: 1.05rem 1.2rem 1.15rem;
  background: color-mix(in srgb, var(--off) 20%, var(--paper));
  border: var(--keyline);
  /* one sharp corner, on the side the tail comes out of */
  border-radius: 18px 18px 18px 5px;
  font-family: var(--hand);
  font-size: 1.26rem; line-height: 1.34;
  box-shadow: 5px 5px 0 color-mix(in srgb, var(--off) 55%, var(--paper));
  rotate: var(--tilt);
  transition: transform .4s var(--ease), box-shadow .4s var(--ease), rotate .4s var(--ease);
}
/* The opening quote, pulled out of the bubble and set big in the card's own
   accent: it says "someone said this" before a word of it is read. Same
   device as the rail at the foot of the home page. */
.talk__line::before {
  content: "\201C";
  position: absolute;
  top: -.5em; left: -.05em;
  font-family: var(--display);
  font-size: 3.4rem; line-height: 1;
  color: var(--off);
  rotate: -7deg;
  pointer-events: none;
  transition: rotate .5s var(--ease), scale .5s var(--ease);
  transform-origin: 60% 80%;
}
.talk__line::after {                         /* the tail, pointing at the face */
  content: "";
  position: absolute;
  left: 22px; bottom: -9px;
  width: 14px; height: 14px;
  background: color-mix(in srgb, var(--off) 20%, var(--paper));
  border-left: var(--keyline);
  border-bottom: var(--keyline);
  rotate: -45deg;
}
.talk__pic {
  grid-area: pic;
  width: 54px; height: 54px;
  overflow: hidden;
  border: var(--keyline);
  border-radius: 50%;
  background: var(--paper-3);
  box-shadow: 3px 3px 0 var(--off);
  rotate: -5deg;
  transition: rotate .4s var(--ease), box-shadow .4s var(--ease);
}
.talk__pic img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 30%; display: block; }
.talk__who {
  grid-area: who;
  align-self: center;
  display: grid; gap: .25rem; justify-items: start;
  font-family: var(--display);
  font-size: 1.28rem; line-height: 1.1;
}
.talk__role {
  font-family: var(--sans);
  font-size: .56rem; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink);
  background: color-mix(in srgb, var(--off) 38%, var(--paper));
  border: 1.5px solid var(--ink);
  border-radius: 999px;
  padding: .32em .8em .26em;
  /* it wraps rather than running out of the card: "Officiant, Yinja's former
     boss" is wider than a 320px screen leaves beside a face */
  max-width: 100%;
  text-align: center;
}
/* the invitation, tucked into the bubble's own corner */
.talk__more {
  grid-area: line;
  align-self: end; justify-self: end;
  position: relative;
  margin: 0 1rem -.75rem 0;
  display: none;
  font-family: var(--sans);
  font-size: .58rem; font-weight: 500;
  letter-spacing: .2em; text-transform: uppercase; line-height: 1;
  color: var(--paper);
  background: var(--ink);
  border-radius: 999px;
  padding: .55em 1em .5em;
  rotate: var(--tilt);
  transition: transform .4s var(--ease), rotate .4s var(--ease);
}
.talk.is-ready .talk__more { display: block; }

.talk__card:hover .talk__line,
.talk__card:focus-visible .talk__line {
  transform: translate(2px, 2px);
  box-shadow: 3px 3px 0 color-mix(in srgb, var(--off) 55%, var(--paper));
  rotate: 0deg;
}
.talk__card:hover .talk__line::before { rotate: 2deg; scale: 1.1; }
.talk__card:hover .talk__pic { rotate: 0deg; box-shadow: 2px 2px 0 var(--off); }
.talk__card:hover .talk__more { transform: translate(2px, 2px) scale(1.05); rotate: 0deg; }
.talk__card:focus-visible { outline: none; }
.talk__card:focus-visible .talk__line { outline: 2px solid var(--ink); outline-offset: 4px; }

/* In dusk a tint of a light accent over a dark ground goes muddy, so the
   bubble becomes a clean dark card and the accent moves to the offset and
   the pill, where it reads bright. Same trick the vows and the pile use. */
[data-theme="dusk"] .talk__line,
[data-theme="dusk"] .talk__line::after { background: var(--paper-2); }
[data-theme="dusk"] .talk__line { box-shadow: 5px 5px 0 var(--off); }
[data-theme="dusk"] .talk__card:hover .talk__line,
[data-theme="dusk"] .talk__card:focus-visible .talk__line { box-shadow: 3px 3px 0 var(--off); }
[data-theme="dusk"] .talk__role { background: var(--off); color: #14110D; border-color: #14110D; }

.talk__foot {
  margin: clamp(.75rem, 1.6vw, 1.25rem) 0 0;
  font-size: .72rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-3);
}

/* The whole speech, on the page under its own card. The script hides these
   and opens them in a window instead; without it they are simply read where
   they are, which is where each card's link points. */
.talk__full {
  margin: 1rem 0 0;
  padding: 1rem 1.15rem;
  border: 1.5px dashed var(--line);
  border-radius: var(--r-sm);
  font-size: .95rem; line-height: 1.66;
}
.talk__full p { margin: 0; }
.talk.is-ready .talk__full { display: none; }

/* A highlighter under the line the card carries, the same marker the vows
   use. It sits behind the words in dawn and drops to an underline in dusk,
   where a band of color behind light text would put cream on gold. The
   marker is the accent mixed back into the paper rather than laid over it:
   wine and coral at full strength are dark, and dark ink on a dark band is
   the one thing a highlighter must not do. */
.talk__key {
  font-weight: 500;
  background-image: linear-gradient(color-mix(in srgb, var(--off) 45%, var(--paper)), color-mix(in srgb, var(--off) 45%, var(--paper)));
  background-repeat: no-repeat;
  background-position: 0 90%;
  background-size: 100% .85em;
}
[data-theme="dusk"] .talk__key {
  background-image: linear-gradient(var(--off), var(--off));
  background-position: 0 100%;
  background-size: 100% .12em;
}

/* ── The speech, opened over the page ─────────────────────────────────────
   One card, the speaker at the top of it and the speech under them, with a
   way through to the next one so five can be read without closing it. The
   card is held to a reading measure and scrolls inside itself, which is what
   makes it work on a phone held sideways, where there are 390px of height
   to put a speech into.                                                   */

.quote {
  position: fixed; inset: 0; z-index: 200;
  display: grid;
  place-items: center;
  padding: clamp(.75rem, 3vw, 2rem);
  background: color-mix(in srgb, var(--deep) 92%, transparent);
  backdrop-filter: blur(8px);
  opacity: 0; visibility: hidden;
  /* Visible the instant it opens and hidden only once it has faded out: the
     close button has to be reachable in the same frame the window opens, and
     nothing inside a hidden window can take the focus. */
  transition: opacity .4s var(--ease), visibility 0s .4s;
}
.quote.is-open {
  opacity: 1; visibility: visible;
  transition: opacity .4s var(--ease), visibility 0s;
}
.quote[data-tone="1"] { --off: var(--blue); }
.quote[data-tone="2"] { --off: var(--sage-500); }
.quote[data-tone="3"] { --off: var(--gold); }
.quote[data-tone="4"] { --off: var(--coral); }
.quote[data-tone="5"] { --off: var(--wine); }
.quote__card {
  position: relative;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  width: min(58ch, 100%);
  max-height: min(86svh, 100%);
  /* a clean sheet to read a whole speech off: the accent stays on the
     printed offset, the portrait and the marker, where it is a mark rather
     than a tint over four hundred words */
  background: var(--paper);
  color: var(--ink);
  border: var(--keyline);
  border-radius: var(--r-md);
  box-shadow: 10px 10px 0 var(--off, var(--blue));
  transform: translateY(14px) scale(.98);
  transition: transform .5s var(--ease);
}
.quote.is-open .quote__card { transform: none; }
[data-theme="dusk"] .quote__card { background: var(--paper-2); }

.quote__head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: .9rem;
  padding: clamp(1rem, 2.4vw, 1.5rem) clamp(1.1rem, 3vw, 1.9rem) .9rem;
  padding-right: calc(clamp(1.1rem, 3vw, 1.9rem) + 44px);
  border-bottom: 1.5px solid var(--line);
}
.quote__pic {
  width: 62px; height: 62px;
  overflow: hidden;
  border: var(--keyline);
  border-radius: 50%;
  background: var(--paper-3);
  box-shadow: 3px 3px 0 var(--off, var(--blue));
  rotate: -5deg;
}
.quote__pic img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 30%; display: block; }
.quote__who {
  display: grid; gap: .3rem; justify-items: start;
  min-width: 0;
  margin: 0;
  font-family: var(--display);
  font-size: clamp(1.3rem, 3.2vw, 1.7rem); line-height: 1.1;
}

.quote__body {
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: clamp(1rem, 2.6vw, 1.5rem) clamp(1.1rem, 3vw, 1.9rem) clamp(1.1rem, 3vw, 1.75rem);
  font-size: clamp(.95rem, 2.2vw, 1.02rem); line-height: 1.7;
}
.quote__body p { margin: 0; }
.quote__body p + p { margin-top: .9rem; }

.quote__x {
  position: absolute;
  top: clamp(.6rem, 2vw, 1rem); right: clamp(.6rem, 2vw, 1rem);
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--ink);
  border: 1.5px solid var(--line);
  background: var(--paper);
  transition: background-color .35s, transform .5s var(--ease);
}
.quote__x:hover { background: var(--paper-3); transform: rotate(90deg); }

/* previous and next sit under the speech rather than over it: at 390px wide
   there is no room beside the card, and inside it they are reachable by a
   thumb on any screen */
.quote__feet {
  display: flex; align-items: center; justify-content: space-between; gap: .75rem;
  padding: .75rem clamp(1.1rem, 3vw, 1.9rem) clamp(1rem, 2.4vw, 1.4rem);
  border-top: 1.5px solid var(--line);
}
.quote__nav {
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: var(--sans);
  font-size: .6rem; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink);
  border: 1.5px solid var(--ink);
  border-radius: 999px;
  padding: .6em 1em .55em;
  background: var(--paper);
  transition: background-color .35s var(--ease), transform .4s var(--ease);
}
.quote__nav:hover { background: var(--off, var(--blue)); transform: translateY(-1px); }
[data-theme="dusk"] .quote__nav:hover { color: #14110D; }
.quote__count { font-size: .6rem; letter-spacing: .18em; text-transform: uppercase; color: var(--ink-3); }

@media (prefers-reduced-motion: reduce) {
  .talk__line, .talk__pic, .talk__more, .quote, .quote__card, .quote__x, .quote__nav { transition: none; }
}

/* The pile: snapshots dropped on a table, each at its own angle ───────── */

.frames {
  --cols: 3;
  --col-gap: clamp(1rem, 2vw, 1.6rem);
  columns: var(--cols);
  column-gap: var(--col-gap);
}
/* Browser columns fill one at a time, so the last one ran out early and left
   the pile with a couple of hundred pixels of nothing under its right-hand
   side. initPile() in site.js deals the photographs into columns of its own
   instead, each one going to whichever column is shortest, so all three
   finish within a photograph of each other. Without the script the columns
   above still work. */
.frames.is-packed {
  columns: auto;
  display: flex;
  align-items: stretch;
  gap: 0 var(--col-gap);
}
/* The columns come out within a photograph of each other, and the column
   that is still short spreads what is left of the difference through its own
   gaps, so the pile finishes on one line. A few pixels between two snapshots
   is not something anyone reads; a column ending short is. */
.frames__col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.frames__col .frame { flex: 0 0 auto; }
.frames__col .frame:last-child { margin-bottom: 0; }
.frame {
  break-inside: avoid;
  margin: 0 0 clamp(1.1rem, 2.2vw, 1.8rem);
  padding: 0;
  border: var(--keyline);
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--paper-3);
  cursor: zoom-in;
  transform: rotate(var(--tilt, 0deg));
  box-shadow: 6px 6px 0 var(--off, var(--blue));
  transition: transform .45s var(--ease), box-shadow .45s var(--ease);
}
.frame img { width: 100%; height: auto; display: block; }
.frame:hover, .frame:focus-visible {
  transform: rotate(0deg) scale(1.02);
  box-shadow: 3px 3px 0 var(--off, var(--blue));
  z-index: 2;
  position: relative;
}

/* Every frame gets its own color and lean, cycling through the palette. The
   tone is stamped in the markup rather than counted off the position, since
   the packer moves a photograph into whichever column has room and a
   nth-child count would repaint half the pile as it went. */
.frame[data-tone="1"] { --off: var(--blue);     --tilt: -1.8deg; }
.frame[data-tone="2"] { --off: var(--gold);     --tilt:  1.4deg; }
.frame[data-tone="3"] { --off: var(--rose);     --tilt: -1.1deg; }
.frame[data-tone="4"] { --off: var(--sage-500); --tilt:  2deg; }
.frame[data-tone="5"] { --off: var(--coral);    --tilt: -2.2deg; }
.frame[data-tone="6"] { --off: var(--khaki);    --tilt:  1.6deg; }

@media (max-width: 900px) { .frames { --cols: 2; } }
/* Two to a row right down to the smallest phone: one long column of big
   photographs stops reading as a pile. The leans stay, and the offset print
   comes in so a tilted frame and its color clear the column beside it. */
@media (max-width: 520px) {
  .frames { --cols: 2; --col-gap: .7rem; }
  .frame { margin-bottom: .9rem; box-shadow: 4px 4px 0 var(--off, var(--blue)); }
  .frame[data-tone="1"] { --tilt: -1.4deg; }
  .frame[data-tone="2"] { --tilt:  1.1deg; }
  .frame[data-tone="3"] { --tilt: -.9deg; }
  .frame[data-tone="4"] { --tilt:  1.5deg; }
  .frame[data-tone="5"] { --tilt: -1.7deg; }
  .frame[data-tone="6"] { --tilt:  1.2deg; }
}

/* A hand-written phrase inside a set heading */
.squiggle {
  font-family: var(--hand);
  font-weight: 700;
  font-size: 1.16em;
  line-height: 0;
  color: var(--page-ink, var(--coral));
  display: inline-block;
  transform: rotate(-2deg);
  padding-inline: .06em;
}
/* on the dark bands the ink shade of the accent goes dim, so use the bright one */
.band--deep .squiggle { color: var(--page, var(--coral)); }

/* Up next: the hand-off card at the foot of a page. It already wears the
   next page's accent (coral for the day), and the whole card is the link. */
.nextup-band { padding-block: clamp(4.5rem, 8vw, 7rem); }
.nextup {
  --page: var(--coral);
  --page-ink: #A8391F;
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  align-items: center;
  gap: clamp(1.5rem, 4vw, 4rem);
  max-width: 1120px;
  margin-inline: auto;
  padding: clamp(1.75rem, 4vw, 3.25rem) clamp(1.5rem, 4vw, 3.5rem);
  background: var(--paper);
  color: var(--ink);
  border: var(--keyline);
  border-radius: var(--r-lg);
  box-shadow: 10px 10px 0 var(--coral);
  transition: transform .45s var(--ease), box-shadow .45s var(--ease);
}
[data-theme="dusk"] .nextup { --page-ink: var(--coral); }
.nextup:hover { transform: translate(4px, 4px); box-shadow: 6px 6px 0 var(--coral); }
.nextup__text { display: grid; gap: 1.05rem; justify-items: start; }
/* the same screwed-on plate as the home chapter cards */
.nextup__plate {
  padding: .34em calc(.95em - .24em) .3em .95em;
  background: #F0D89C;
  color: #14110D;
  border: 2px solid #14110D;
  border-radius: 999px;
  font-size: .64rem;
  letter-spacing: .24em;
  text-transform: uppercase;
  line-height: 1.2;
}
.nextup__title { margin: .2rem 0 0; }
.nextup__note { margin: 0; max-width: 36ch; color: var(--ink-2); font-size: clamp(1rem, 1.3vw, 1.12rem); line-height: 1.6; }
.nextup__date { margin: 0; color: var(--ink-3); }
.nextup__btn { margin-top: .5rem; }
/* the card is the link, so its button answers to the card's hover */
.nextup:hover .btn { transform: translate(3px, 3px); box-shadow: 2px 2px 0 var(--ink); color: #fff; }
.nextup:hover .btn::before { transform: translateY(0); }
.nextup:hover .btn__arrow { transform: translateX(4px); }

/* the illustration leans out over the top edge of the card */
.nextup__art {
  position: relative;
  isolation: isolate;
  margin-top: clamp(-5rem, -6vw, -2rem);
  transform: rotate(2.5deg);
  transition: transform .7s var(--ease);
}
.nextup__art::before {
  content: "";
  position: absolute;
  inset: 6% 2% 0;
  z-index: -1;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--coral) 24%, transparent), transparent);
}
.nextup:hover .nextup__art { transform: rotate(0deg) translateY(-6px); }
.nextup__img { display: block; width: 100%; height: auto; }
.nextup__img--dusk { display: none; }
[data-theme="dusk"] .nextup__img--dawn { display: none; }
[data-theme="dusk"] .nextup__img--dusk { display: block; }
.nextup__star {
  position: absolute;
  top: 4%; left: -3%;
  transform: rotate(12deg);
  animation: twinkle 3.6s var(--ease-soft) infinite;
}

@media (max-width: 760px) {
  .nextup { grid-template-columns: 1fr; box-shadow: 7px 7px 0 var(--coral); }
  .nextup:hover { box-shadow: 4px 4px 0 var(--coral); }
  /* Stacked, the art is the top of the card, so the lean that took it over
     the card's top edge beside the words now takes it clean off the card. */
  .nextup__art { order: -1; transform: rotate(1.5deg); margin-top: 0; }
  .nextup__star { width: 30px; height: 30px; }
}

/* 12 ── LIGHTBOX, CURSOR, MOTION ───────────────────────────────────────── */

/* Two rows, not one: the photograph gets whatever height is left over once
   the caption has taken its own, so a tall photograph is scaled down rather
   than run under the words. The padding keeps the close button clear of the
   top row, and the photograph's width leaves room for the two arrows. */
.lightbox {
  position: fixed; inset: 0; z-index: 200;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  place-items: center;
  gap: clamp(.8rem, 2vw, 1.25rem);
  padding: calc(clamp(1rem, 3vw, 2rem) + 44px + .75rem) clamp(1rem, 4vw, 3rem) clamp(1.75rem, 4vw, 2.75rem);
  background: color-mix(in srgb, var(--deep) 94%, transparent);
  backdrop-filter: blur(8px);
  opacity: 0; visibility: hidden;
  transition: opacity .5s var(--ease-soft), visibility .5s;
}
.lightbox.is-open { opacity: 1; visibility: visible; }
.lightbox__img { max-width: min(1100px, calc(100vw - clamp(2rem, 14vw, 10rem))); max-height: 100%; object-fit: contain; border-radius: 2px; box-shadow: 0 30px 90px #0009; transform: scale(.97); transition: transform .6s var(--ease); }
.lightbox.is-open .lightbox__img { transform: none; }
.lightbox__cap { margin: 0; max-width: min(760px, 88vw); line-height: 1.5; color: #C9D6D8; font-size: .74rem; letter-spacing: .18em; text-transform: uppercase; text-align: center; }
.lightbox__x { position: absolute; top: clamp(1rem, 3vw, 2rem); right: clamp(1rem, 3vw, 2rem); width: 44px; height: 44px; display: grid; place-items: center; border-radius: 50%; color: #EDE8DA; box-shadow: inset 0 0 0 1px #ffffff30; transition: background-color .35s, transform .5s var(--ease); }
.lightbox__x:hover { background: #ffffff14; transform: rotate(90deg); }
.lightbox__nav { position: absolute; top: 50%; transform: translateY(-50%); width: 52px; height: 52px; display: grid; place-items: center; color: #EDE8DA; border-radius: 50%; box-shadow: inset 0 0 0 1px #ffffff26; transition: background-color .35s; }
.lightbox__nav:hover { background: #ffffff14; }
.lightbox__nav--prev { left: clamp(.5rem, 2vw, 2rem); }
.lightbox__nav--next { right: clamp(.5rem, 2vw, 2rem); }

/* soft trailing cursor ring (pointer devices only) */
.cursor {
  position: fixed; top: 0; left: 0; z-index: 300;
  width: 30px; height: 30px; margin: -15px 0 0 -15px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px var(--brass);
  pointer-events: none;
  opacity: 0;
  transition: opacity .4s, width .35s var(--ease), height .35s var(--ease), margin .35s var(--ease), background-color .35s;
  will-change: transform;
}
.cursor.is-on { opacity: .75; }
.cursor.is-hot { width: 54px; height: 54px; margin: -27px 0 0 -27px; background: color-mix(in srgb, var(--brass) 12%, transparent); }
@media (hover: none), (pointer: coarse) { .cursor { display: none; } }

/* Intro curtain
   The logo goes up like a pinned print. It lands at a tilt, its color block
   slides out a hair off register, the stars pop, and the two names write
   themselves in towards the ampersand. Then the cloth lifts on a scalloped
   hem with the blue lining a beat behind it, and the hero rises as it is
   uncovered.
   The entrance is pure CSS and plays from the first paint; site.js only
   decides when to lift. Colors are fixed rather than theme tokens, so the
   curtain is the same oxblood at dawn and at dusk. Spring easings go in the
   timing-function longhand, never the shorthand: a browser that can't read
   linear() then falls back to ease instead of dropping the animation. */

.curtain {
  --hem: clamp(14px, 1.9vw, 24px);                 /* scallop radius */
  /* two springs sampled from a damped oscillator: a gentle settle and a pop */
  --settle: linear(0, .023 2.5%, .048 3.8%, .122 6.2%, .267 10%, .637 18.8%, .812 23.8%, .94 28.7%, .987 31.2%, 1.038 35%, 1.074 40%, 1.083 46.2%, 1.003 75%, .993 87.5%, 1);
  --pop: linear(0, .013 1.2%, .049 2.5%, .104 3.8%, .175 5%, .348 7.5%, .636 11.2%, .816 13.8%, .971 16.2%, 1.035 17.5%, 1.136 20%, 1.173 21.2%, 1.219 23.8%, 1.234 26.2%, 1.21 30%, 1.008 42.5%, .969 46.2%, .949 50%, .951 56.2%, .998 68.8%, 1.011 75%, 1);
  position: fixed; inset: 0; z-index: 500;
  overflow: hidden;
  /* failsafe: if the script never runs, the curtain still gets out of the way */
  animation: curtain-gone .6s 12s forwards;
}
.curtain-seen .curtain { display: none; }
.curtain.is-up { pointer-events: none; }

.curtain__cloth,
.curtain__lining {
  position: absolute;
  inset: 0 0 calc(-1 * var(--hem));
  /* a solid sheet with a row of half-circles hanging off the hem */
  -webkit-mask:
    linear-gradient(#000 0 0) top / 100% calc(100% - var(--hem) + 1px) no-repeat,
    radial-gradient(circle at 50% 0, #000 calc(var(--hem) - .6px), #0000 var(--hem)) 50% 100% / calc(2 * var(--hem)) var(--hem) repeat-x;
          mask:
    linear-gradient(#000 0 0) top / 100% calc(100% - var(--hem) + 1px) no-repeat,
    radial-gradient(circle at 50% 0, #000 calc(var(--hem) - .6px), #0000 var(--hem)) 50% 100% / calc(2 * var(--hem)) var(--hem) repeat-x;
}
.curtain__lining { background: #5E9BB4; bottom: calc(-1 * var(--hem) - 7px); }   /* hangs just below the cloth, a scalloped trim */
.curtain__cloth  { background: radial-gradient(58% 52% at 50% 44%, #50202E, #3A1621 72%) #3A1621; }
.curtain__cloth::before {                           /* the page's paper grain */
  content: "";
  position: absolute; inset: 0;
  opacity: .12;
  mix-blend-mode: soft-light;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

.curtain__inner {
  position: absolute; inset: 0 0 var(--hem);
  display: grid; place-content: center; justify-items: center;
  padding: 2rem;
}

/* the print: logo, off-register color block, stars */
.curtain__print {
  --off: clamp(7px, 1vw, 11px);
  position: relative;
  width: min(clamp(160px, 23vw, 250px), 32vh);
  aspect-ratio: 1;
  rotate: -3deg;
  opacity: 0;
  animation: curtain-land .95s .15s both;
  animation-timing-function: var(--settle);
}
.curtain__logo {
  position: relative; z-index: 1;
  width: 100%; height: 100%;
  border: 2px solid #14110D;
  border-radius: 14px;
}
.curtain__block {
  position: absolute; inset: 0;
  border-radius: 14px;
  background: #5E9BB4;
  animation: curtain-offset .7s .55s both;
  animation-timing-function: var(--pop);
}
.curtain__star {
  --sd: .7s;
  position: absolute; z-index: 2;
  overflow: visible;
  fill: #F0CE84;
  opacity: 0;
  animation: curtain-pop .6s var(--sd) both, curtain-twinkle 2.8s calc(var(--sd) + .6s) infinite;
  animation-timing-function: var(--pop), ease-in-out;
}
.curtain__star--pin { --sd: .68s; width: 20%; top: -9%; right: -9%; stroke: #14110D; stroke-width: 1.2; }
.curtain__star--a   { --sd: .8s;  width: 11%; top: 18%; left: -19%; }
.curtain__star--b   { --sd: .9s;  width: 8%; bottom: 9%; right: -17%; }

/* the names write in from either side, towards the ampersand */
.curtain__names {
  display: flex; align-items: center; justify-content: center;
  gap: clamp(.2rem, 1vw, .7rem);
  margin-top: clamp(1.2rem, 3.6vh, 2.2rem);
}
.curtain__name {
  width: clamp(100px, 15vw, 172px);
  aspect-ratio: 5 / 3;
}
/* Plain images, not CSS masks: masks can refuse to load (a page opened
   straight off the disk, for one) and the names would vanish. */
.curtain__name img {
  display: block; width: 100%; height: 100%;
  filter: invert(1);
  opacity: .94;                                     /* white, warmed a touch by the oxblood */
}
.curtain__name--david { animation: curtain-write .75s cubic-bezier(.45, .05, .35, 1) .62s both, curtain-in-l 1s var(--ease) .62s both; }
.curtain__name--yinja { animation: curtain-write .75s cubic-bezier(.45, .05, .35, 1) .8s both, curtain-in-r 1s var(--ease) .8s both; }

/* the ampersand is a sticker, stamped on once both names have arrived */
.curtain__amp {
  display: grid; place-items: center;
  flex: none;
  width: clamp(40px, 4.9vw, 56px);
  aspect-ratio: 1;
  padding-top: .12em;                               /* Gloock's ampersand sits high */
  border: 2px solid #14110D;
  border-radius: 50%;
  background: #F0CE84;
  box-shadow: 3px 3px 0 #14110D;
  color: #14110D;
  font-family: var(--display);
  font-size: clamp(1.25rem, 2.35vw, 1.75rem);
  line-height: 1;
  rotate: 7deg;                                     /* leans against the print's tilt */
  opacity: 0;
  animation: curtain-stamp .7s 1.22s both;
  animation-timing-function: var(--pop);
}

.curtain__line {
  display: flex; align-items: baseline;
  margin: clamp(.4rem, 1.4vh, .9rem) 0 0;
  padding-left: calc(.25em + 17px);                 /* the dots hang, so the words center */
  font-size: .64rem; font-weight: 500;
  letter-spacing: .3em; text-transform: uppercase;
  color: #BBA0A5;
  opacity: 0;
  animation: curtain-rise .8s var(--ease) 1.45s both;
}
.curtain__dots { display: flex; gap: 4px; margin-left: .25em; }   /* an ellipsis, sat on the baseline */
.curtain__dots span { width: 3px; height: 3px; border-radius: 50%; background: #EBC97E; animation: curtain-dot 1.2s ease-in-out infinite; }
.curtain__dots span:nth-child(2) { animation-delay: .2s; }
.curtain__dots span:nth-child(3) { animation-delay: .4s; }

/* the lift: the print leaves first, then the cloth, then its lining */
.curtain.is-up .curtain__inner  { animation: curtain-leave .5s cubic-bezier(.55, 0, .75, .2) both; }
.curtain.is-up .curtain__cloth  { animation: curtain-lift 1s cubic-bezier(.76, 0, .24, 1) .05s both; }
.curtain.is-up .curtain__lining { animation: curtain-lift 1s cubic-bezier(.76, 0, .24, 1) .065s both; }

/* While the curtain is down the hero holds its entrance, so the headline
   rises as the cloth clears it instead of finishing out of sight. */
.is-curtained .hero [data-reveal] { opacity: 0 !important; }
.is-curtained .hero [data-reveal="up"] { transform: translate3d(0, 26px, 0) !important; }
.is-curtained .hero .wi { transform: translate3d(0, 115%, 0) !important; }

@keyframes curtain-land    { from { opacity: 0; transform: translateY(-28px) rotate(-14deg) scale(.86); } to { opacity: 1; transform: none; } }
@keyframes curtain-offset  { from { transform: none; } to { transform: translate(var(--off), var(--off)); } }
@keyframes curtain-pop     { from { opacity: 0; transform: scale(0) rotate(-90deg); } to { opacity: 1; transform: none; } }
@keyframes curtain-twinkle { 50% { scale: .7; } }
@keyframes curtain-write   { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes curtain-in-l    { from { transform: translateX(-22px); } to { transform: none; } }
@keyframes curtain-in-r    { from { transform: translateX(22px); } to { transform: none; } }
@keyframes curtain-stamp   { from { opacity: 0; transform: scale(1.8) rotate(-30deg); } to { opacity: 1; transform: none; } }
@keyframes curtain-rise    { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes curtain-dot     { 0%, 70%, 100% { opacity: .25; } 35% { opacity: 1; } }
@keyframes curtain-leave   { to { opacity: 0; transform: translateY(-5vh) scale(.97); } }
@keyframes curtain-lift    { to { transform: translateY(-100%); } }
@keyframes curtain-gone    { to { opacity: 0; visibility: hidden; } }

/* 12b ── SINCE THE WEDDING, SWIPE ROWS, FOLDS, BACK TO TOP ─────────────── */

/* Home: the year pages' Christmas cards, pinned up in a row on the dark band.
   Built by initSince from assets/js/years/index.js. */
.since__cards {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  /* one column per year (initSince sets --n), never a count that auto-fit
     would break into a row of three and one left hanging */
  grid-template-columns: repeat(var(--n, 4), minmax(0, 1fr));
  gap: 2.25rem clamp(1.25rem, 2.6vw, 2.25rem);
}
/* When the full row no longer fits: even counts split in half, odd counts take
   the bigger half first (five go three and two), so no card ends up alone. */
@media (max-width: 1080px) {
  .since__cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .since__cards[data-n="5"], .since__cards[data-n="6"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .since__cards[data-n="7"], .since__cards[data-n="8"] { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 860px) {
  .since__cards[data-n="5"], .since__cards[data-n="6"],
  .since__cards[data-n="7"], .since__cards[data-n="8"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.since__cards:empty { display: none; }
.since__item { min-width: 0; }
.since__card { position: relative; display: grid; gap: .4rem; color: var(--ink); }
.since__pic {
  display: block;
  aspect-ratio: 7 / 5;
  overflow: hidden;
  margin-bottom: .75rem;
  border: var(--keyline);
  border-radius: var(--r-md);
  background: #2A0F18;
  box-shadow: 8px 8px 0 var(--off, var(--gold));
  rotate: var(--tilt, 0deg);
  transition: rotate .5s var(--ease), translate .5s var(--ease), box-shadow .5s var(--ease);
}
.since__pic img { width: 100%; height: 100%; object-fit: cover; transition: transform .8s var(--ease); }
.since__card:hover .since__pic,
.since__card:focus-visible .since__pic { rotate: 0deg; translate: 0 -6px; box-shadow: 8px 14px 0 var(--off, var(--gold)); }
.since__card:hover .since__pic img { transform: scale(1.05); }
.since__year { font-family: var(--display); font-size: clamp(1.7rem, 2.4vw, 2.15rem); line-height: 1; transition: color .35s; }
.since__card:hover .since__year { color: var(--brass-ink); }
.since__name { font-size: .84rem; line-height: 1.4; color: var(--ink-2); text-wrap: balance; }
/* colors pinned: the sticker is the same gold on the dark band in both themes */
.since__new {
  position: absolute;
  top: -.7rem; right: -.45rem;
  z-index: 2;
  padding: .34em .8em .28em;
  border: 1.5px solid #14110D;
  border-radius: 999px;
  background: #F0CE84;
  color: #14110D;
  box-shadow: 2px 2px 0 #14110D;
  font-size: .58rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  rotate: 7deg;
}
.since__blank {
  display: grid; place-items: center;
  width: 100%; height: 100%;
  font-family: var(--display); font-size: 2.6rem; color: #14110D;
  background: radial-gradient(90% 80% at 25% 20%, #F0CE8466, transparent 65%), #F7F0E0;
}
.since__btns { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: clamp(2.75rem, 5vw, 3.75rem); }

/* Swipe rows. Below 620px these grids become one row you swipe through, the
   next card peeking in from the right, instead of stacking several screens
   tall. The padding leaves room for the offset color and the tilts. Photo
   strips of four or more do the same on the year pages (year.css). */
.rail-count { display: none; }
@media (max-width: 620px) {
  .since__cards, .chapters, .tables {
    display: flex;
    gap: 1.1rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    margin-inline: calc(-1 * var(--gutter));
    padding: .9rem var(--gutter) 1.4rem;
    scroll-padding-inline: var(--gutter);
    scrollbar-width: none;
  }
  .since__cards::-webkit-scrollbar, .chapters::-webkit-scrollbar, .tables::-webkit-scrollbar { display: none; }
  .since__cards > *, .chapters > *, .tables > * { flex: 0 0 80%; scroll-snap-align: start; }
  .chapters > * { flex-basis: 84%; }
  .rail-count {
    display: flex;
    align-items: center;
    gap: .55rem;
    margin: .1rem 0 0;
    font-size: .64rem; font-weight: 500; letter-spacing: .22em; text-transform: uppercase;
    color: var(--ink-3);
  }
  .rail-count b { font-weight: 600; color: var(--ink); }
}

/* Nine tables in two columns always leave the ninth hanging on its own, so
   between the three-a-row layout and the phone they become a row you swipe. */
@media (min-width: 621px) and (max-width: 1080px) {
  .tables {
    display: flex;
    gap: 1.1rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    margin-inline: calc(-1 * var(--gutter));
    padding: .9rem var(--gutter) 1.4rem;
    scroll-padding-inline: var(--gutter);
    scrollbar-width: none;
  }
  .tables::-webkit-scrollbar { display: none; }
  .tables > * { flex: 0 0 46%; scroll-snap-align: start; }
  .tables + .rail-count {
    display: flex;
    align-items: center;
    gap: .55rem;
    margin: .1rem 0 0;
    font-size: .64rem; font-weight: 500; letter-spacing: .22em; text-transform: uppercase;
    color: var(--ink-3);
  }
}

/* Folds. On a phone a trip with several paragraphs shows the first and a
   button for the rest (initFolds). Wider screens never see the button. */
.fold__btn { display: none; }
.fold__more:focus { outline: none; }
@media (max-width: 620px) {
  .fold.is-folded .fold__more { display: none; }
  /* More than eight lines of the first paragraph is a whole screen of type
     before the first photograph. It is cut to eight, and the button opens
     the rest of it whether or not more paragraphs follow. */
  .fold.is-folded .fold__lede {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 8;
            line-clamp: 8;
    overflow: hidden;
  }
  .fold.is-folded .fold__btn {
    display: inline-flex;
    align-items: center;
    gap: .6rem;
    justify-self: start;
    margin-top: .3rem;
    padding: .55em .6em .55em 1.1em;
    border: 1.5px solid var(--ink);
    border-radius: 999px;
    background: var(--paper);
    color: var(--ink);
    box-shadow: 3px 3px 0 var(--off, var(--gold));
    font: 500 .68rem/1.1 var(--sans);
    letter-spacing: .18em;
    text-transform: uppercase;
    cursor: pointer;
    transition: translate .3s var(--ease), box-shadow .3s var(--ease);
  }
  .fold__btn:active { translate: 2px 2px; box-shadow: 1px 1px 0 var(--off, var(--gold)); }
  .fold__n { padding: .32em .6em; border-radius: 999px; background: var(--ink); color: var(--paper); letter-spacing: .04em; }
}

/* Back to the top: a round inked button that rolls in once a long page has
   been scrolled a way (initToTop) */
.totop {
  position: fixed;
  right: max(1rem, env(safe-area-inset-right));
  bottom: max(1rem, env(safe-area-inset-bottom));
  z-index: 55;
  display: grid;
  place-items: center;
  width: 46px; height: 46px;
  padding: 0;
  border: var(--keyline);
  border-radius: 50%;
  background: var(--paper);
  color: var(--ink);
  box-shadow: 4px 4px 0 var(--gold);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  translate: 0 14px;
  rotate: -10deg;
  transition: opacity .35s var(--ease-soft), visibility .35s, translate .55s var(--ease), rotate .55s var(--ease), box-shadow .3s var(--ease);
}
.totop.is-on { opacity: 1; visibility: visible; translate: 0 0; rotate: 0deg; }
.totop:hover { translate: 2px 2px; box-shadow: 2px 2px 0 var(--gold); }
body.menu-open .totop { opacity: 0; visibility: hidden; }

/* Theme swap: the new theme opens out from the toggle (initTheme). While it
   does, transitions are off so every color lands in the same frame; the
   toggle's knob still slides. */
::view-transition-old(root),
::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
.theme-swap *:not(.theme-toggle__knob),
.theme-swap *::before,
.theme-swap *::after { transition: none !important; }

/* 13 ── RESPONSIVE ─────────────────────────────────────────────────────── */

@media (max-width: 1180px) {
  /* Two doors a row. A door is portrait, so cap the width and center the
     pair: the arch keeps its shape instead of stretching into a banner. */
  .chapters { grid-template-columns: repeat(2, minmax(0, 420px)); justify-content: center; }
}

@media (max-width: 1080px) {
  .tables, .pours { grid-template-columns: repeat(2, 1fr); }
  .menu { grid-template-columns: minmax(0, 1fr); }
}

/* The footer keeps its three columns while all three fit, then stacks. Two
   columns would leave the third hanging on a row of its own. */
@media (max-width: 880px) {
  .footer__top { grid-template-columns: 1fr; gap: 2rem; }
  /* the three credits go one to a line here: side by side they wrap two and
     one, which leaves the last credit stranded */
  .footer__meta { flex-direction: column; align-items: flex-start; gap: .8rem; }
}

/* The links stop being a row where the row stops fitting on one line. Laid
   out edge to edge, the brand, the five labels and the toggle need a shade
   under 1000px; below that a label wraps to two lines, so the menu takes
   over instead. The layouts further down have nothing to do with the nav and
   keep their own 860px. */
@media (max-width: 1020px) {
  /* Full-screen takeover. It sits at z-index -1 *within the nav's own layer*,
     so it covers the page but stays under the logo and the close button. */
  .nav__links {
    position: fixed;
    inset: 0;
    z-index: -1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    gap: clamp(.6rem, 2.2vh, 1.4rem);
    padding: 6.5rem var(--gutter) 6rem;
    background: var(--paper);
    overflow-y: auto;
    opacity: 0;
    visibility: hidden;
    transition: opacity .4s var(--ease-soft), visibility .4s;
  }
  .nav__links.is-open { opacity: 1; visibility: visible; }

  .nav__link {
    font-family: var(--display);
    font-size: clamp(1.85rem, 8.5vw, 3.1rem);
    line-height: 1.1;
    letter-spacing: -.025em;
    text-transform: none;
    color: var(--ink);
    padding-block: .18em;
    white-space: normal;
    opacity: 0;
    transform: translateY(16px);
    transition: opacity .55s var(--ease) var(--i, 0ms), transform .55s var(--ease) var(--i, 0ms);
  }
  .nav__links.is-open .nav__link { opacity: 1; transform: none; }
  .nav__link:nth-child(1) { --i: 60ms; }
  .nav__link:nth-child(2) { --i: 130ms; }
  .nav__link:nth-child(3) { --i: 200ms; }
  .nav__link:nth-child(4) { --i: 270ms; }
  .nav__link:nth-child(5) { --i: 340ms; }
  .nav__link::after { bottom: .14em; height: 1.5px; }
  .nav__link[aria-current="page"] { color: var(--wine); }
  .nav__link[aria-current="page"]::after { display: none; }

  .nav__tail {
    position: absolute;
    left: var(--gutter); right: var(--gutter); bottom: 2.25rem;
    display: flex;
    gap: 1.5rem;
    flex-wrap: wrap;
    font-size: .68rem;
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--ink-3);
    opacity: 0;
    transform: translateY(12px);
    transition: opacity .55s var(--ease) 410ms, transform .55s var(--ease) 410ms;
  }
  .nav__links.is-open .nav__tail { opacity: 1; transform: none; }

  body.menu-open { overflow: hidden; }
  .nav__burger { display: grid; }
}

@media (max-width: 860px) {
  .feature { grid-template-columns: 1fr; }
  /* one column has to redraw the areas too: left at two names wide, the grid
     keeps a second column for the film and squeezes it to nothing */
  .feature--film { grid-template-areas: "words" "film" "btns"; }
  .fig__card { display: none; }
  .chap { grid-template-columns: 1fr; padding-left: var(--rail); }
  .chap__sticky { position: static; display: flex; align-items: baseline; gap: 1rem; padding-left: 0; }
  .chap__dot { top: .45rem; left: calc(-1 * var(--rail) - 4.5px); }
  .timeline__spine { left: var(--gutter); }
  .grid--2 { grid-template-columns: 1fr; }
}

@media (max-width: 720px) {
  .chapters { grid-template-columns: minmax(0, 460px); }
  .toast { gap: 1.25rem; }
  .toast .day-date__part { font-size: clamp(2.4rem, 18vw, 5.5rem); }
}

@media (max-width: 620px) {
  /* the doors swipe in one row here: the centring for two a row above would
     push the first door off the left edge, where no scroll can reach it */
  .chapters { justify-content: flex-start; }
  .tables, .pours, .menu { grid-template-columns: 1fr; }
  .footer__top { grid-template-columns: 1fr; }
  .yearbtn__more { display: none; }
  .strip[data-n="3"] { aspect-ratio: 4 / 3; }
  .strip[data-n="5"], .strip[data-n="6"] { grid-template-columns: repeat(2, 1fr); }
  .sec-head { grid-template-columns: 1fr; gap: .8rem; }
  .stage { gap: .25rem; }
  .stage__center { padding-bottom: 20%; }
}

/* ── A PHONE ON ITS SIDE ─────────────────────────────────────────────────
   Short and wide. Everything above stacks because the screen is narrow, and
   this one is not: there is room for two columns, and a column of full-width
   photographs on a screen this short is a very long scroll for very little
   read. Anything that stacks for want of height stays stacked, and a screen
   too narrow to hold two columns anyway (an older phone, under 700px) keeps
   the stack. The map switches to its floating window here too, in
   assets/css/map.css, which reads the same two measurements. */

@media (min-width: 700px) and (max-height: 520px) and (orientation: landscape) {
  .feature { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .feature--film { grid-template-areas: "words film" "btns film"; }

  /* Sections are set by the width of the screen, which is the long side
     here: 90-odd pixels of air above and below each one is a quarter of a
     short screen. They take their measure from the height instead. */
  .band { padding-block: clamp(2.5rem, 9vh, 4.5rem); }
  .band--tight { padding-block: clamp(2rem, 7vh, 3.5rem); }
  .page-head { padding-top: clamp(5rem, 22vh, 7rem); padding-bottom: clamp(1.5rem, 6vh, 3rem); }

  /* The date rail goes back beside the chapter it belongs to. Only on The
     Long Way Round: a month on a year page needs its whole width to put the
     photographs beside the writing, which is what year.css does here. */
  body[data-page="story"] .chap { grid-template-columns: 140px minmax(0, 1fr); padding-left: 0; }
  body[data-page="story"] .chap__sticky {
    position: sticky;
    top: calc(var(--nav-h) + 3.25rem);
    display: grid;
    align-items: start;
    gap: .35rem;
    padding-left: var(--rail);
  }
  body[data-page="story"] .chap__dot { top: .55rem; left: -4.5px; }

  /* three to a row, since the row is wide and the screen is short */
  .frames { --cols: 3; }

  /* Sideways there are 390px of height, most of it under the bar, so the
     rail gives back the room it keeps for the tilts and the printed offset,
     and the speech window takes nearly the whole screen. */
  .talk__track { padding-block: 2rem 1.1rem; }
  .quote { padding: .6rem; }
  .quote__card { max-height: 94svh; }
  .quote__head { padding-block: .7rem .6rem; }
  .quote__pic { width: 48px; height: 48px; }
}

/* The menu is a full-screen takeover, and sideways the screen is 390px tall.
   At the size the tall layout sets it, five links and the line under them come
   to 495px: the first is cut off at the top, the last runs under the credits,
   and the whole thing scrolls. It is set by the height here instead. This one
   takes every phone on its side, narrow ones included, since the menu is the
   same five links whatever the width. */
@media (orientation: landscape) and (max-height: 520px) {
  .nav__links {
    justify-content: center;
    gap: clamp(.3rem, 1.6vh, .8rem);
    padding: 4.5rem var(--gutter) 3rem;
  }
  .nav__link { font-size: clamp(1.4rem, 8vh, 2.1rem); padding-block: .1em; }
  .nav__tail { bottom: 1rem; gap: 1rem 1.5rem; font-size: .62rem; }
}

/* A memory is a picture beside its words again on a phone held sideways, in
   a card that fits a short screen: stacked, one card was two and a half
   screens of scrolling. Only above 760px, where the card is two columns
   anyway, so the mat behind the photo keeps the shape that goes with it. */
@media (min-width: 761px) and (max-height: 520px) and (orientation: landscape) {
  .memory__card { --mem-pic: 190px; min-height: 0; }
  .memory .memory__card { --scene-h: clamp(38px, 8cqi, 60px); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  [data-reveal] { opacity: 1 !important; transform: none !important; clip-path: none !important; }
  .wi { transform: none !important; }
  .curtain { display: none; }
  .cursor { display: none; }
}

@media print {
  .nav, .footer, .cursor, .curtain, .progress, .yearbar { display: none !important; }
  body { background: #fff; color: #000; }
}

/* 13 ── HOME: THE MAP, THE TALLY AND THE SPEECHES ──────────────────────────
   The home page is three short sections under the hero. Everything here is
   its own, so nothing in this block is shared with home-archive.html.      */

/* the pair of buttons at the right of the bar, which used to be written
   inline on the home page */
.nav__tools { display: flex; align-items: center; gap: .75rem; }

/* the years in the footer, a row of pills rather than five more lines */
/* Two by two rather than a wrapping row: four across only just fits the
   column, and the width it wants depends on the gutter, so a row would
   leave the last year on its own somewhere. */
.footer__years { display: grid; grid-template-columns: repeat(2, max-content); gap: .4rem; margin-top: .3rem; }
.footer__years a {
  padding: .2rem .6rem;
  border: 1px solid var(--footer-line);
  border-radius: 999px;
  font-size: .76rem; letter-spacing: .06em;
  transition: background .3s, border-color .3s, color .3s;
}
.footer__years a:hover { background: var(--footer-hover); border-color: var(--footer-hover); color: var(--footer-bg); }
/* Four columns now that the timelines have their own, but only while the
   footer is still a row: it stacks at 880px, below the rule above. */
@media (min-width: 881px) { .footer__top { grid-template-columns: 1.25fr 1fr 1fr 1fr; } }

/* ── 01 Memories ─────────────────────────────────────────────────────────
   Map on the left, the photographs it deals on the right. Below 1000px the
   panel drops under the map and rides a little way up onto it, so a phone
   sees the pictures land rather than a second screen of nothing.          */

.mem { position: relative; display: grid; gap: clamp(1.25rem, 3vw, 2.25rem); }
/* overflow-x: hidden on <body> turns it into a scroll container, and a sticky
   child of a scroll container that never scrolls never sticks. "clip" clips
   the same way without making one, which is what lets the map hold its place.
   Scoped to this page so nothing else changes shape; hidden stays as the
   fallback for anything that does not know clip. */
body[data-page="home"] { overflow-x: hidden; overflow-x: clip; }

.mem__mapcol { position: relative; z-index: 1; }
@media (min-width: 1000px) {
  .mem { grid-template-columns: minmax(0, 1.08fr) minmax(0, .92fr); align-items: start; }
  /* The column of photographs is the taller of the two, so the map follows it
     down rather than leaving a hole under itself. */
  .mem__mapcol { position: sticky; top: calc(var(--nav-h) + 1.5rem); }
}
/* The box holds its proportions whether or not the map is in it: on a phone
   the svg moves into the pop-up and back, and a collapsing box would jump
   the page under the reader. */
.mem__map { aspect-ratio: 1000 / 645.6; }
.mem__map svg { display: block; width: 100%; height: 100%; overflow: hidden; }

/* Not been there: the quiet ground the colored states sit on. No ink line
   on any of them, there are fifty and it turns the map into a net. */
.memmap__st {
  fill: var(--paper-2);
  stroke: color-mix(in srgb, var(--ink) 14%, transparent);
  stroke-width: .8px;
  vector-effect: non-scaling-stroke;
}
/* Been there: the four quilt colors, separated by the paper rather than
   by ink, and cut out of the same sheet as the ground. */
/* The color sits on top of the plain ground, so if the print never runs the
   map is a gray map rather than no map at all. */
.memmap__been {
  fill: var(--quilt-1);
  stroke: var(--paper);
  stroke-width: 1.4px;
  vector-effect: non-scaling-stroke;
  cursor: pointer;
  transform-box: fill-box;
  transform-origin: 50% 50%;
  opacity: 0;
  transform: scale(.5) rotate(-12deg);
  transition:
    opacity .34s var(--ease-soft) var(--t, 0ms),
    transform .74s var(--stamp) var(--t, 0ms),
    filter .35s var(--ease-soft);
}
.memmap__been[data-q="1"] { fill: var(--quilt-2); }
.memmap__been[data-q="2"] { fill: var(--quilt-3); }
.memmap__been[data-q="3"] { fill: var(--quilt-4); }
.memmap__been:hover { filter: brightness(1.08) saturate(1.1); }

/* One state chosen: it keeps its color and takes the ink line, the rest
   step back. One outline on the map, never thirty-six. */
.memmap.is-picked.is-printed .memmap__been { opacity: .38; }
.memmap.is-picked.is-printed .memmap__been.is-on { opacity: 1; }
.memmap__ring {
  fill: none;
  stroke: var(--ink);
  stroke-width: 2.4px;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
  opacity: 0;
  transition: opacity .3s var(--ease-soft);
}
.memmap.is-picked .memmap__ring { opacity: 1; }
.memmap__dc {
  fill: var(--coral); stroke: var(--paper); stroke-width: 1.2px;
  vector-effect: non-scaling-stroke; cursor: pointer;
  transform-box: fill-box; transform-origin: 50% 50%;
  opacity: 0; transform: scale(.4);
  transition: opacity .3s var(--ease-soft) var(--t, 0ms), transform .6s var(--stamp) var(--t, 0ms);
}
.memmap.is-picked.is-printed .memmap__dc { opacity: .38; }
.memmap.is-picked.is-printed .memmap__dc.is-on { opacity: 1; }
.memmap__home {
  fill: var(--gold); stroke: var(--ink); stroke-width: 1.1px;
  vector-effect: non-scaling-stroke; pointer-events: none;
  transform-box: fill-box; transform-origin: 50% 50%;
  opacity: 0; transform: scale(.2) rotate(-140deg);
  transition: opacity .4s var(--ease-soft) 1.35s, transform 1s var(--stamp) 1.35s;
}

/* The print itself: once, on the way in. */
.memmap.is-printed .memmap__been { opacity: 1; transform: none; }
.memmap.is-printed .memmap__dc   { opacity: 1; transform: none; }
.memmap.is-printed .memmap__home { opacity: 1; transform: scale(1.3) rotate(0deg); }
/* and once it has landed, no state waits its turn to light up */
.memmap.is-set .memmap__been,
.memmap.is-set .memmap__dc {
  transition-delay: 0ms;
  transition-duration: .3s, .35s, .3s;
}
.memmap__label { font-family: var(--sans); font-size: 13px; font-weight: 500; letter-spacing: .5em; fill: var(--ink-3); pointer-events: none; }

/* A sentence, not a label: letterspaced capitals took half again the width
   for no more meaning, and this only ever has to sit quietly under the map. */
.mem__hint { margin: .9rem 0 0; font-size: .86rem; color: var(--ink-3); }
/* The one action in the panel: it rolls the map to a state we have written up */
.mem__roll {
  flex: none;
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .32rem .85rem .32rem .6rem;
  border: 1.5px solid var(--ink);
  border-radius: 999px;
  background: var(--gold);
  color: #14110D;
  font: inherit; font-size: .74rem; font-weight: 500; letter-spacing: .1em; text-transform: uppercase;
  cursor: pointer;
  box-shadow: 2px 2px 0 var(--ink);
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}
.mem__roll:hover { transform: translate(2px, 2px); box-shadow: 0 0 0 var(--ink); }
.mem__roll:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.mem__die { display: grid; place-items: center; }
.mem__die svg { display: block; }
.is-rolling .mem__die { animation: memRoll .55s cubic-bezier(.34, 1.42, .5, 1); }
@keyframes memRoll {
  0%   { rotate: 0deg; scale: 1; }
  55%  { rotate: 200deg; scale: 1.22; }
  100% { rotate: 360deg; scale: 1; }
}

/* The panel. A fixed floor so choosing a state never jumps the page. */
.mem__panel {
  position: relative;
  display: grid;
  align-content: start;
  gap: 1rem;
  min-height: 300px;
}
/* The row never wraps; the title wraps inside it. Let the row wrap instead and
   whether the button keeps its place depends on how long the state is called,
   so "Ohio" and "Washington, DC" would lay the section out differently. */
.mem__headrow {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: nowrap; gap: 1rem;
}
.mem__title {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem .75rem;
  min-width: 0;
  margin: 0;
  font-family: var(--display); font-size: clamp(1.45rem, 2.4vw, 2rem); line-height: 1.1;
}
.mem__count { font-family: var(--sans); font-size: .72rem; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-3); }

.mem__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(.7rem, 1.6vw, 1rem); }
/* an odd one out takes the whole row rather than sitting on its own */
.mem__grid > :last-child:nth-child(odd) { grid-column: 1 / -1; }

.mem__card {
  position: relative;
  display: grid;
  gap: .5rem;
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  font: inherit; color: inherit;
  cursor: pointer;
  rotate: var(--tilt, 0deg);
  transition: rotate .4s var(--ease), translate .4s var(--ease);
}
.mem__card::before {                        /* the color, printed off register */
  content: "";
  position: absolute;
  /* Right and down only. Inset on the left as well and the color starts
     inboard of the photograph above it, which leaves the caption sitting off
     the edge of its own background. */
  inset: 0 -6px -6px 0;
  border-radius: var(--r-sm);
  background: var(--off, var(--gold));
  transition: inset .4s var(--ease);
}
.mem__card:hover, .mem__card:focus-visible { rotate: 0deg; translate: 0 -4px; outline: none; }
.mem__card:hover::before, .mem__card:focus-visible::before { inset: 0 -10px -10px 0; }
.mem__card:focus-visible .mem__shot { box-shadow: 0 0 0 3px var(--gold); }
.mem__shot {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border: var(--keyline);
  border-radius: var(--r-sm);
  background: var(--paper-3);
}
.mem__shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mem__n {                                   /* how many more are behind it */
  position: absolute; right: .4rem; bottom: .4rem;
  padding: .1rem .45rem;
  border: 1.5px solid #14110D;
  border-radius: 999px;
  background: #F7F0E0; color: #14110D;
  font-size: .66rem; font-weight: 500; letter-spacing: .06em;
}
.mem__label { position: relative; display: grid; gap: .12rem; padding: .35rem .8rem .6rem .7rem; }
.mem__where { font-weight: 500; font-size: .86rem; line-height: 1.3; color: #14110D; }
.mem__when { font-size: .7rem; letter-spacing: .12em; text-transform: uppercase; color: #4B443A; }

/* A card opened: the same picture, bigger, with the rest of the roll under
   it and the line David wrote at the time. */
.mem__open {
  position: relative;
  display: grid;
  gap: .85rem;
  padding: clamp(.85rem, 2vw, 1.1rem);
  border: var(--keyline);
  border-radius: var(--r-md);
  background: var(--paper);
  box-shadow: 6px 6px 0 var(--off, var(--gold));
}
.mem__open.is-new { animation: memPop .42s var(--ease) both; }
@keyframes memPop {
  from { opacity: 0; transform: scale(.94) translateY(10px); }
  to   { opacity: 1; transform: none; }
}
.mem__back {
  justify-self: start;
  display: inline-flex; align-items: center; gap: .4rem;
  padding: 0; border: 0; background: none;
  font: inherit; font-size: .72rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-3); cursor: pointer;
}
.mem__back:hover { color: var(--ink); }
.mem__lead {
  position: relative;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  border: var(--keyline);
  border-radius: var(--r-sm);
  background: var(--paper-3);
}
.mem__lead img { width: 100%; height: 100%; object-fit: cover; display: block; animation: memFade .35s var(--ease-soft) both; }
@keyframes memFade { from { opacity: 0 } to { opacity: 1 } }
.mem__cap {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 1.6rem .7rem .5rem;
  background: linear-gradient(transparent, #14110Dcc);
  color: #F9F2E4; font-size: .76rem; line-height: 1.4;
}
/* The rest of the roll, under the lead photograph. It used to carry the same
   class as the "Surprise me" button above the grid, which dressed it as a
   gold pill the square thumbnails then hung out of. Its own name now, and a
   rounded rectangle cut to what is inside it. */
.mem__shots {
  display: flex;
  gap: .4rem;
  padding: .4rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--paper-2);
}
.mem__thumb {
  flex: 1 1 0;
  aspect-ratio: 1 / 1;
  padding: 0;
  overflow: hidden;
  border: 1.5px solid var(--ink);
  border-radius: 7px;
  background: var(--paper-3);
  cursor: pointer;
  opacity: .55;
  transition: opacity .3s, translate .3s var(--ease);
}
.mem__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mem__thumb:hover { opacity: .85; translate: 0 -2px; }
.mem__thumb.is-on { opacity: 1; box-shadow: 0 0 0 2px var(--gold); }
.mem__head { display: grid; gap: .2rem; }
.mem__place { margin: 0; font-family: var(--display); font-size: clamp(1.15rem, 2vw, 1.5rem); line-height: 1.15; }
.mem__date { font-size: .7rem; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3); }
.mem__text { margin: 0; font-size: .92rem; line-height: 1.6; color: var(--ink-2); }
.mem__go {
  justify-self: start;
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .5rem .95rem;
  border: var(--keyline);
  border-radius: 999px;
  background: var(--gold);
  color: #14110D;
  font-size: .82rem; font-weight: 500;
  box-shadow: 3px 3px 0 var(--ink);
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}
.mem__go:hover { transform: translate(3px, 3px); box-shadow: 0 0 0 var(--ink); }

/* Nothing filed under this one yet, said plainly rather than left blank */
.mem__none {
  display: grid; gap: .6rem; justify-items: start;
  padding: 1.25rem;
  border: 1.5px dashed var(--line);
  border-radius: var(--r-md);
  color: var(--ink-3); font-size: .9rem; line-height: 1.6;
}
.mem__none.is-soon { border-style: solid; border-color: var(--gold); color: var(--ink-2); }
.mem__soon {
  padding: .26rem .7rem;
  border: 1.5px solid var(--ink);
  border-radius: 999px;
  background: var(--gold);
  color: #14110D;
  font-size: .64rem; font-weight: 500; letter-spacing: .18em; text-transform: uppercase;
}

@media (max-width: 999px) {
  .mem__panel { min-height: 0; }
  .mem__open { padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; }
  /* The count goes above the map here, so that nothing sits between the map
     and the photographs for the pill to float over on its way past. It reads
     as an opening line there in any case. */
  .mem__mapcol { display: flex; flex-direction: column; }
  .mem__hint { order: -1; margin: 0 0 .9rem; }
}

/* ── 02 The tally ──────────────────────────────────────────────────────── */

.tally__cards {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(.8rem, 2vw, 1.5rem);
}
.tally__card {
  position: relative;
  display: grid;
  gap: .3rem;
  padding: clamp(1rem, 2.2vw, 1.5rem);
  border: var(--keyline);
  border-radius: var(--r-md);
  background: var(--paper);
  box-shadow: 6px 6px 0 var(--fill, var(--gold));
  rotate: -.6deg;
  transition: transform .4s var(--ease), box-shadow .4s var(--ease), rotate .4s var(--ease);
}
.tally__card:nth-child(even) { rotate: .7deg; }
.tally__card:hover { rotate: 0deg; transform: translateY(-5px); box-shadow: 9px 9px 0 var(--fill, var(--gold)); }
.tally__mark { display: block; width: clamp(42px, 6vw, 56px); margin-bottom: .35rem; }
.tally__mark svg { display: block; width: 100%; height: auto; }
.tally__n {
  font-family: var(--display);
  font-size: clamp(2.6rem, 5.5vw, 4rem);
  line-height: 1;
  transform-origin: 12% 80%;
}
.tally__card:hover .tally__n { animation: wobble .6s var(--ease); }
.tally__k { font-size: .92rem; font-weight: 500; line-height: 1.3; }
/* the page accent on its own comes to 4.1:1 on cream, under AA for text
   this size, so the note is taken a little further towards the ink */
.tally__q { font-family: var(--hand); font-size: 1.05rem; line-height: 1.25;
  color: color-mix(in srgb, var(--page-ink) 72%, var(--ink)); }

.tally__end {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(1.5rem, 5vw, 4rem);
  align-items: center;
  margin-top: clamp(3rem, 7vw, 5.5rem);
}
.tally__cal { justify-items: start; }
/* Wide enough for the pair of buttons to stay a pair: the prose keeps its
   own measure below. */
.tally__cta { display: grid; gap: 1rem; justify-items: start; max-width: 52ch; }
.tally__cta .lede, .tally__cta .t-md { max-width: 44ch; }
.tally__cta .lede { margin: 0; }
/* The pair of buttons takes the column, not just the width of its words, so
   initButtonRows has a width to measure the pair against. */
.tally__cta .btns { justify-self: stretch; }

@media (max-width: 860px) {
  .tally__cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tally__end { grid-template-columns: 1fr; justify-items: start; }
}

/* ── 03 Said about us ──────────────────────────────────────────────────────
   A rail that scrolls itself. It is a real scroller, so a thumb can push it
   about and the keyboard can reach it; initSay only nudges it along.      */

.say__head { display: grid; gap: .6rem; margin-bottom: clamp(1.5rem, 3vw, 2.25rem); }
.say__rail {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  -ms-overflow-style: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
}
.say__rail::-webkit-scrollbar { display: none; }
/* room above for the pulled-out quote marks and the tilts */
.say__track { display: flex; gap: clamp(1.1rem, 2.2vw, 1.7rem); width: max-content; padding: 2.5rem var(--gutter) 1.5rem; }

/* This band is the oxblood in dawn and in dusk, so everything on it is
   pinned rather than themed, the way the postmark and the calendar sticker
   are: one wine for the paper, cream for the line, and one accent a card
   printed off register behind it.

   --keyline is no use here. It is declared on :root as "2px solid
   var(--ink)", so it resolves against root's ink and inherits already
   resolved: overriding --ink on .band--deep cannot reach back into it. In
   dawn that left a near-black line on the oxblood, which is what made these
   read as unfinished beside the speeches on day.html. */
.said {
  flex: none;
  width: clamp(232px, 68vw, 340px);
  display: grid;
  /* the face grows with the card: 48px is right on a phone and too shy of
     the bubble above it on a desktop */
  --face: 48px;
  grid-template-columns: var(--face) minmax(0, 1fr);
  grid-template-areas: "bubble bubble" "pic who";
  gap: .85rem .7rem;
  margin: 0;
  align-content: start;
  --line-ink: var(--deep-ink);
  --off: #F0CE84;
}
.said:nth-child(2) { --off: #5E9BB4; }
.said:nth-child(3) { --off: #7FA08A; }
.said:nth-child(4) { --off: #DCC0BE; }
.said:nth-child(5) { --off: #E2604F; }
/* Pinned up, not laid out. Nothing on this site sits square: the calendar
   page, the memory cards, the prints and the signatures all sit a degree or
   two off and come back to true when you go near them. These were the one
   set that did not, which is most of why they read as a table of quotes
   rather than five notes somebody stuck on the wall. */
.said:nth-child(odd)  { --tilt: -1.5deg; }
.said:nth-child(even) { --tilt: 1.3deg; }
.said__bubble {
  grid-area: bubble;
  position: relative;
  margin: 0;
  padding: 1rem 1.15rem;
  border: 2px solid var(--line-ink);
  /* one sharp corner, on the side the tail comes out of, the shape the
     speeches on day.html are cut to */
  border-radius: 18px 18px 18px 5px;
  /* the same wine as the band behind it, so the bubble and its tail are one
     color and the line is the only thing drawing the shape */
  background: var(--deep);
  color: var(--deep-ink);
  font-family: var(--hand);
  font-size: 1.24rem; line-height: 1.34;
  box-shadow: 5px 5px 0 var(--off);
  rotate: var(--tilt, 0deg);
  transition: transform .4s var(--ease), box-shadow .4s var(--ease), rotate .4s var(--ease);
}
.said:hover .said__bubble { transform: translate(2px, 2px); box-shadow: 3px 3px 0 var(--off); rotate: 0deg; }
/* The opening quote, pulled out of the bubble and set big in the card's own
   accent, the way the ampersand and the squiggles are set: it says "someone
   said this" before a word of it is read. */
.said__bubble::before {
  content: "\201C";
  position: absolute;
  top: -.52em; left: -.06em;
  font-family: var(--display);
  font-size: 3.4rem; line-height: 1;
  color: var(--off);
  rotate: -7deg;
  pointer-events: none;
  transition: rotate .5s var(--ease), scale .5s var(--ease);
  transform-origin: 60% 80%;
}
.said:hover .said__bubble::before { rotate: 2deg; scale: 1.1; }
.said__bubble::after {                       /* the tail, pointing at the face */
  content: "";
  position: absolute;
  left: 22px; bottom: -9px;
  width: 14px; height: 14px;
  background: var(--deep);
  border-left: 2px solid var(--line-ink);
  border-bottom: 2px solid var(--line-ink);
  rotate: -45deg;
}
.said__who {
  grid-area: who;
  align-self: center;
  display: grid; gap: .1rem;
  font-size: .86rem; font-weight: 500;
}
/* the role as a pill in the card's own accent, the way day.html sets it */
.said__who span {
  justify-self: start;
  margin-top: .1rem;
  padding: .3em .7em .24em;
  border: 1.5px solid var(--line-ink);
  border-radius: 999px;
  background: var(--off);
  color: #14110D;
  font-size: .56rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  white-space: nowrap;
}
.said__pic {
  grid-area: pic;
  width: var(--face); height: var(--face);
  overflow: hidden;
  border: 2px solid var(--line-ink);
  border-radius: 50%;
  background: var(--deep);
  box-shadow: 3px 3px 0 var(--off);
  rotate: -5deg;
  transition: rotate .4s var(--ease), box-shadow .4s var(--ease);
}
.said:hover .said__pic { rotate: 0deg; box-shadow: 2px 2px 0 var(--off); }
.said__pic img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 30%; display: block; }
.say__foot { margin-top: .75rem; }

@media (min-width: 900px) { .say .said { --face: 64px; } }
@media (max-width: 620px) {
  .said { width: 78vw; }
  .said__bubble { font-size: 1.16rem; }
}

/* ── Pages still being written ─────────────────────────────────────────────
   Honeymoon and Highlights carry the nav and the footer and say plainly that
   there is nothing here yet, with the places the writing already lives.   */

.soon {
  display: grid; justify-items: start; gap: 1.25rem;
  max-width: 64ch;
  padding: clamp(1.5rem, 4vw, 2.5rem);
  border: 2px dashed var(--line);
  border-radius: var(--r-lg);
  background: var(--paper-2);
}
.soon__tag {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .28rem .8rem;
  border: 1.5px solid var(--ink);
  border-radius: 999px;
  background: var(--page);
  color: #14110D;
  font-size: .68rem; font-weight: 500; letter-spacing: .18em; text-transform: uppercase;
}
.soon__line { margin: 0; font-size: clamp(1rem, 1.5vw, 1.1rem); line-height: 1.65; color: var(--ink-2); }

/* A phone on its side is wide and very short: stacking the map and the sheet
   there would be two screens of scrolling for one choice, so it takes the two
   columns, with the map given less of the width than a desktop gives it. */
@media (min-width: 700px) and (max-height: 520px) and (orientation: landscape) {
  .mem { grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr); align-items: start; }
  /* Six cards two across is three rows, and three rows on a screen this
     short is a long scroll past a map that has gone. It stays, the way it
     does on a desktop, and the pill never has to stand in for it. */
  .mem__mapcol { position: sticky; top: calc(var(--nav-h) + .6rem); }
  .mem__panel {
    z-index: auto; margin-top: 0; padding: 0; min-height: 0;
    border: 0; border-radius: 0; background: none; box-shadow: none;
  }
  .mem__panel::before { content: none; }
  .mem__open { padding: clamp(.85rem, 2vw, 1.1rem); border: var(--keyline); border-radius: var(--r-md); background: var(--paper); box-shadow: 6px 6px 0 var(--off, var(--gold)); }
  .mem__hint { justify-content: flex-start; margin-bottom: 0; }
  .tally__cards { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .tally__end { grid-template-columns: auto minmax(0, 1fr); align-items: center; }
}

/* ── A TABLET STOOD UP ───────────────────────────────────────────────────
   Wide enough to be a desktop by the width alone, and tall enough that the
   two columns leave the map sitting in the top corner of a long empty one
   while six cards stack down the other. So the map takes the top of the
   section at a size it can be read at, and the cards become one row to
   swipe: the whole section is a screen, and the map is still on it.
   Landscape is handled above and does not reach this. */
@media (min-width: 700px) and (orientation: portrait) {
  .mem { grid-template-columns: minmax(0, 1fr); }
  .mem__mapcol { position: static; }
  .mem__map { width: 100%; max-width: 620px; margin-inline: auto; }

  .mem__grid {
    display: flex;
    gap: 1.1rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    margin-inline: calc(-1 * var(--gutter));
    padding: .9rem var(--gutter) 1.4rem;
    scroll-padding-inline: var(--gutter);
    scrollbar-width: none;
  }
  .mem__grid::-webkit-scrollbar { display: none; }
  /* Two and a bit: the third card showing at the edge is what says the row
     goes on. The odd-one-out rule belongs to the grid and has nothing to do
     here, where there is only ever the one row. */
  .mem__grid > * { flex: 0 0 42%; scroll-snap-align: start; }
}

/* ── The map as a pill (phones) ───────────────────────────────────────────
   A phone cannot hold the map and the photographs on screen together, and a
   map that has scrolled away is a map nobody can reach. So the map scrolls
   away like anything else and hands over, as it goes, to a small pill that
   stays put: what you are looking at, a die to reshuffle it, and the map one
   tap away. Tapping it does not raise a panel from somewhere else, the pill
   itself grows into the map and shrinks back into the pill afterwards, which
   is what keeps the two reading as one object rather than two.            */

:root { --stamp: cubic-bezier(.34, 1.42, .5, 1); }

.mem__bar {
  position: fixed;
  z-index: 70;
  top: calc(var(--nav-h) + 10px);
  left: 50%;
  display: flex;
  align-items: center;
  gap: .1rem;
  max-width: calc(100vw - 2rem);
  padding: .26rem .26rem .26rem .6rem;
  border-radius: 999px;
  background: var(--deep);
  color: var(--deep-ink);
  box-shadow: 0 12px 34px #00000059, 0 2px 8px #00000038;
  translate: -50% -12px;
  scale: .84;
  opacity: 0;
  pointer-events: none;
  transition: opacity .26s var(--ease-soft), scale .44s var(--stamp), translate .44s var(--stamp);
}
.mem__bar.is-up { opacity: 1; scale: 1; translate: -50% 0; pointer-events: auto; }
/* while the map is up, the pill it grew out of is not there to see */
.memsheet-open .mem__bar { opacity: 0; scale: .9; pointer-events: none; transition-duration: .16s; }
/* Phones only. Anything wider either keeps the map beside the photographs
   or fits the map and the cards on one screen, so the pill has nothing to
   stand in for. Matches phone() in assets/js/site.js. */
@media (min-width: 700px) { .mem__bar { display: none; } }

.mem__pick {
  display: flex; align-items: center; gap: .55rem;
  min-width: 0;
  padding: .3rem .5rem .3rem 0;
  border: 0; background: none; color: inherit; font: inherit;
  border-radius: 999px;
  cursor: pointer;
}
.mem__shape { flex: none; display: grid; place-items: center; width: 23px; height: 23px; }
.mem__shape svg { display: block; width: 100%; height: 100%; }
.mem__shape path { fill: var(--gold); }
.mem__now { display: grid; gap: .05rem; min-width: 0; text-align: left; }
.mem__now b {
  font-weight: 500; font-size: .84rem; line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mem__now span { font-size: .58rem; letter-spacing: .14em; text-transform: uppercase; color: var(--deep-ink-3); }
/* A rotated bordered square puts its visual weight below its own box, which
   is what had the chevron sitting low in the circle. An svg centers exactly. */
.mem__chev {
  flex: none;
  display: grid; place-items: center;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: #ffffff1f;
  color: var(--deep-ink);
}
.mem__chev svg { display: block; }
.mem__dice {
  flex: none;
  display: grid; place-items: center;
  width: 34px; height: 34px;
  border: 0; border-radius: 50%;
  background: #ffffff1f;
  color: var(--deep-ink);
  cursor: pointer;
  transition: background .25s, color .25s, rotate .5s var(--stamp);
}
.mem__dice:hover, .mem__dice:active { background: var(--gold); color: #14110D; rotate: -20deg; }
.mem__pick:focus-visible, .mem__dice:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* ── The pill, grown ──────────────────────────────────────────────────────
   Hung off <body>, so no frosted or clipped ancestor can trap it. The card
   starts at the pill's own place and size, fully round, and opens out from
   there; everything inside waits for the shape to arrive before fading up. */

.memsheet { position: fixed; inset: 0; z-index: 95; }
.memsheet[hidden] { display: none; }
.memsheet__scrim {
  position: absolute; inset: 0;
  background: #14110Dbf;
  opacity: 0;
  transition: opacity .34s var(--ease-soft);
}
.memsheet.is-open .memsheet__scrim { opacity: 1; }

.memsheet__card {
  position: absolute;
  top: var(--fy, 40%); left: var(--fx, 25%);
  width: var(--fw, 180px); height: var(--fh, 44px);
  display: flex; flex-direction: column;
  overflow: hidden;
  /* the pill's own radius, in pixels: "999px" would uncap as the box grows and
     the card would pass through a great circle on its way open */
  border-radius: calc(var(--fh, 44px) / 2);
  background: var(--deep);
  color: var(--deep-ink);
  box-shadow: 0 26px 70px #00000073;
  /* Shutting, and only shutting: this is the state the card goes back to, so
     the transition written here is the one it goes back with. The stamp below
     has a spring in it, which is what throws the card open; run backwards the
     same spring ducks the card inside the pill it is landing on, and a blank
     wine lozenge sits over the pill's own label for a beat before it is taken
     off the page. So it comes back the plain way, and the last beat of the
     shrink is a fade: by then the card is the pill's box in the pill's
     color, and the label underneath simply arrives. */
  opacity: 0;
  transition:
    top .4s var(--ease-soft), left .4s var(--ease-soft),
    width .4s var(--ease-soft), height .4s var(--ease-soft),
    border-radius .3s var(--ease-soft),
    opacity .14s linear .28s;
}
.memsheet.is-open .memsheet__card {
  top: calc(var(--nav-h) + 10px);
  left: calc((100% - var(--tw, 320px)) / 2);
  width: var(--tw, 320px);
  height: var(--th, 320px);
  border-radius: 30px;
  opacity: 1;
  transition:
    top .46s var(--stamp), left .46s var(--stamp),
    width .46s var(--stamp), height .46s var(--stamp),
    border-radius .3s var(--ease-soft),
    opacity .01s;
}
.memsheet__card > * { opacity: 0; transition: opacity .14s var(--ease-soft); }
.memsheet.is-open .memsheet__card > * { opacity: 1; transition: opacity .26s var(--ease-soft) .2s; }

.memsheet__grab {
  flex: none;
  width: 40px; height: 4px;
  margin: .5rem auto .1rem;
  border-radius: 999px;
  background: #ffffff33;
}
.memsheet__head {
  flex: none;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: .3rem .95rem .1rem 1.1rem;
}
.memsheet__title { margin: 0; font-family: var(--display); font-size: 1.3rem; line-height: 1.2; }
.memsheet__x {
  display: grid; place-items: center;
  width: 34px; height: 34px;
  border: 0; border-radius: 50%;
  background: var(--deep-ink);
  color: var(--deep);
  cursor: pointer;
  box-shadow: 0 2px 10px #00000047;
  transition: background .25s, color .25s, scale .25s var(--ease);
}
.memsheet__x:hover, .memsheet__x:focus-visible { background: var(--gold); color: #14110D; scale: 1.06; }
.memsheet__map { flex: 1; min-height: 0; display: grid; place-items: center; padding: .2rem .9rem; }
/* hidden, not visible: left visible the map prints out over the heading and
   the close button and there is nothing clean for them to sit on */
.memsheet__map svg { width: 100%; height: 100%; overflow: hidden; }
/* On the deep ground the map needs its own paper, not the page's */
.memsheet__map .memmap__st { fill: #ffffff14; stroke: #ffffff26; }
.memsheet__map .memmap__been { stroke: var(--deep); }
.memsheet__map .memmap__ring { stroke: var(--gold); stroke-width: 3px; }
.memsheet__map .memmap__label { fill: var(--deep-ink-3); }
.memsheet__map .memmap__home { stroke: var(--deep); }
.memsheet__foot {
  flex: none;
  display: flex; align-items: center; justify-content: space-between; gap: .75rem;
  padding: .55rem 1.1rem 1rem;
}
.memsheet__all {
  padding: .4rem .9rem;
  border: 1.5px solid #ffffff3d;
  border-radius: 999px;
  background: none;
  color: var(--deep-ink);
  font: inherit; font-size: .8rem;
  cursor: pointer;
  transition: background .25s, border-color .25s, color .25s;
}
.memsheet__all:hover { background: var(--gold); border-color: var(--gold); color: #14110D; }
.memsheet__note { font-size: .62rem; letter-spacing: .12em; text-transform: uppercase; color: var(--deep-ink-3); text-align: right; }

@media (min-width: 1000px) { .memsheet { display: none; } }
