/* =====================================================================
   BIRTHDAY ALBUM: the photo in Birthdays is the cover of a red hardcover album; tapping it opens a flip book of
   party photos. The owner picked "G3 · Red hardcover" from the Birthday Sketchbook Variations page (3 November
   2026; https://claude.ai/artifact/DE3HCdQVZEHwqK4SB3NUZo). The book inside is the owner's Worn Sketchbook, with its
   class names prefixed fb- (the site already has a .book: the Book your party card). Script: js/birthday-album.js.
   ===================================================================== */

/* ---------- the closed album: a red cloth hardcover, page edges at the side, the party photo taped on the cover
   with washi tape, Birthdays at Mench on a label, and a yellow ribbon hanging out of the bottom. On hover the book
   straightens and lifts, the photo rises and the ribbon gets a little tug. ---------- */
.ba-open {
  /* the cover's colours: cloth, its highlight, the label, the ribbon */
  --bk: #b8241e;
  --bk-hi: #e2453c;
  --bk-ink: #fff4e0;
  --bk-band: #ffd731;
  --bk-shadow: 0 22px 30px -16px rgba(26, 23, 20, 0.75);
  --font-caption: "Fraunces", Georgia, "Times New Roman", serif;
  position: relative;
  display: block;
  justify-self: center;
  width: min(100%, 420px);
  aspect-ratio: 4 / 5;
  margin-block: 14px 36px; /* room under it for the ribbon */
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
/* night: a brighter red with a light rim, so the book keeps its edge against the plum page */
[data-mode="night"] .ba-open {
  --bk: #c62c25;
  --bk-hi: #ff5b52;
  --bk-shadow: 0 0 0 1.5px rgba(240, 235, 255, 0.2), 0 22px 34px -16px rgba(0, 0, 0, 0.9);
}
.ba-open:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 6px;
}
.ba-book {
  position: absolute;
  inset: 7% 3% 0 5%;
  transform: rotate(-4deg);
  transition: transform 0.5s cubic-bezier(0.34, 1.3, 0.64, 1);
}
/* the page block, showing at the right and bottom edges */
.ba-pages {
  position: absolute;
  inset: 4px -7px -7px 4px;
  border-radius: 3px 8px 8px 3px;
  background:
    repeating-linear-gradient(90deg, #efe6d2 0 2px, #d9cdb2 2px 3px) right / 12px 100% no-repeat,
    repeating-linear-gradient(0deg, #efe6d2 0 2px, #d9cdb2 2px 3px) bottom / 100% 10px no-repeat,
    #f3ecdc;
}
/* the cover: cloth weave, the spine's shading on the left, and darker cloth over the two outer corners */
.ba-cover {
  position: absolute;
  inset: 0;
  border-radius: 3px 8px 8px 3px;
  background:
    linear-gradient(
      90deg,
      rgba(0, 0, 0, 0.35),
      rgba(0, 0, 0, 0.35) 9%,
      rgba(255, 255, 255, 0.1) 9.5%,
      rgba(0, 0, 0, 0) 13%
    ),
    repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.05) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(90deg, rgba(0, 0, 0, 0.07) 0 1px, transparent 1px 3px),
    radial-gradient(120% 90% at 30% 20%, var(--bk-hi), var(--bk) 72%);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.06),
    inset 0 0 26px rgba(0, 0, 0, 0.32),
    var(--bk-shadow);
}
.ba-cover::before,
.ba-cover::after {
  content: "";
  position: absolute;
  right: 0;
  width: 15%;
  aspect-ratio: 1;
  background: color-mix(in srgb, var(--bk) 55%, #000);
}
.ba-cover::before {
  top: 0;
  border-top-right-radius: 8px;
  clip-path: polygon(0 0, 100% 0, 100% 100%);
}
.ba-cover::after {
  bottom: 0;
  border-bottom-right-radius: 8px;
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
}
/* the ribbon, behind the book, hanging out of the bottom */
.ba-ribbon {
  position: absolute;
  z-index: -1;
  right: 24%;
  bottom: -30px;
  width: 16px;
  height: 56px;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--bk-band) 80%, #000),
    var(--bk-band) 50%,
    color-mix(in srgb, var(--bk-band) 85%, #000)
  );
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 84%, 0 100%);
  transition: transform 0.45s cubic-bezier(0.34, 1.5, 0.64, 1);
}
.ba-label {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 6.5%;
  margin-inline: 20%;
  padding-block: 3px;
  border-block: 1px solid color-mix(in srgb, var(--bk-ink) 45%, transparent);
  color: var(--bk-ink);
  font: 500 0.75rem/1.4 var(--font-caption);
  letter-spacing: 0.3em;
  text-align: center;
  text-transform: uppercase;
}
/* the photo, taped to the cover (its tilt is on top of the book's) */
.ba-photo {
  position: absolute;
  inset: -7.5% 15.2% 22.6% 8.7%;
  border: 7px solid #fffaf0;
  background: #fffaf0;
  transform: rotate(7deg);
  box-shadow: 0 8px 18px -8px rgba(0, 0, 0, 0.6);
  transition: transform 0.5s cubic-bezier(0.34, 1.3, 0.64, 1);
}
.ba-photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 35%;
}
/* two strips of washi tape at the top corners */
.ba-photo::before,
.ba-photo::after {
  content: "";
  position: absolute;
  top: -12px;
  width: 76px;
  height: 24px;
  clip-path: polygon(0 0, 100% 0, 96% 25%, 100% 50%, 96% 75%, 100% 100%, 0 100%, 4% 75%, 0 50%, 4% 25%);
}
.ba-photo::before {
  left: -26px;
  background: rgba(255, 215, 49, 0.78);
  transform: rotate(-32deg);
}
.ba-photo::after {
  right: -26px;
  background: rgba(79, 166, 255, 0.72);
  transform: rotate(28deg);
}
.ba-open:hover .ba-book,
.ba-open:focus-visible .ba-book {
  transform: rotate(-2deg) translateY(-4px);
}
.ba-open:hover .ba-photo,
.ba-open:focus-visible .ba-photo {
  transform: rotate(3deg) translateY(-6px);
}
.ba-open:hover .ba-ribbon,
.ba-open:focus-visible .ba-ribbon {
  transform: translateY(10px);
}
/* narrow phones: the label keeps to one line */
@media (max-width: 440px) {
  .ba-label {
    margin-inline: 12%;
    font-size: 0.625rem;
    letter-spacing: 0.24em;
  }
}
/* tablets and desktops: the book is 20% smaller (336px, was 420px) so the whole of it fits on screen beside the
   text; phones keep the full width. At this width the label needs the narrow phones' smaller type to stay on one line. */
@media (min-width: 641px) {
  .ba-open {
    width: min(100%, 336px);
  }
  .ba-label {
    margin-inline: 12%;
    font-size: 0.625rem;
    letter-spacing: 0.24em;
  }
}
.ba-note {
  justify-self: center;
  margin: 0;
  color: var(--muted);
  font-size: 0.875rem;
  text-align: center;
}
.ba-opener {
  display: grid;
  gap: 4px;
  min-width: 0;
}
@media (prefers-reduced-motion: reduce) {
  .ba-book,
  .ba-photo,
  .ba-ribbon {
    transition: none;
  }
}

/* ---------- the nudge: every 2.5 seconds (owner, 11 November 2026; was 7) the closed album gives a soft hop and its
   cover bends up from the spine, as if someone had a thumb under its right edge, showing the pages, then drops shut,
   so it reads as a book you can open. Phones too. It stops while the pointer or focus is on it (the hover lift takes over) and for good once the album has
   been opened (.is-opened, from js/birthday-album.js). Visitors who ask for less motion never see it.
   How the cover bends: CSS can't curve a flat element, so js/birthday-album.js lays three copies of the cover
   (.ba-face) over the original and each one is clipped to a vertical strip (0-40%, 40-65%, 65-85%, 85-100%). Each
   strip turns at every seam to its left, a few degrees more at each one, so together they curve up most at the
   right edge. One animated number, --lift (0 flat, 1 fully bent), drives all of it. The strips only take over while
   the cover moves (--split is 1): the rest of the time the original face shows whole and the copies are hidden, so
   there are no seams between strips at rest (they'd show as faint lines in the shadow under the book).
   The hop animates `translate`, an individual transform property, not `transform`: it stacks on top of `transform`,
   so the book's tilt and its hover transition keep working while the nudge runs. ---------- */
@property --lift {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}
.ba-open {
  --split: 0;
}
.ba-lid,
.ba-face {
  position: absolute;
  inset: 0;
}
.ba-lid {
  /* how far the cover turns at the spine and at each seam, when fully bent */
  --b1: 3deg;
  --b2: 5deg;
  --b3: 7deg;
  --b4: 9deg;
}
.ba-face {
  transform-origin: left center; /* the spine */
  transform: rotateY(calc(var(--lift) * var(--b1) * -1));
}
/* each strip: turn at the spine, slide along to the next seam, turn there, and so on, then slide back to where the
   face starts (translateX percentages are of the face's own width, the cover's width) */
.ba-face.ba-strip-2 {
  transform: rotateY(calc(var(--lift) * var(--b1) * -1)) translateX(40%) rotateY(calc(var(--lift) * var(--b2) * -1))
    translateX(-40%);
}
.ba-face.ba-strip-3 {
  transform: rotateY(calc(var(--lift) * var(--b1) * -1)) translateX(40%) rotateY(calc(var(--lift) * var(--b2) * -1))
    translateX(25%) rotateY(calc(var(--lift) * var(--b3) * -1)) translateX(-65%);
}
.ba-face.ba-strip-4 {
  transform: rotateY(calc(var(--lift) * var(--b1) * -1)) translateX(40%) rotateY(calc(var(--lift) * var(--b2) * -1))
    translateX(25%) rotateY(calc(var(--lift) * var(--b3) * -1)) translateX(20%)
    rotateY(calc(var(--lift) * var(--b4) * -1)) translateX(-85%);
}
/* while it bends, each face shows only its strip; the clip reaches 80px past the cover at the top, bottom and outer
   sides, for its shadow, the photo and the tape. The original's right edge goes from -80px (not clipped) to 60% as
   --split goes from 0 to 1; the copies are see-through until then. */
.ba-lid.is-bendy > .ba-face:first-child {
  clip-path: inset(-80px calc(var(--split) * 60% + (1 - var(--split)) * -80px) -80px -80px);
}
.ba-face[class*="ba-strip-"] {
  opacity: var(--split);
}
.ba-face.ba-strip-2 {
  clip-path: inset(-80px 35% -80px 40%);
}
.ba-face.ba-strip-3 {
  clip-path: inset(-80px 15% -80px 65%);
}
.ba-face.ba-strip-4 {
  clip-path: inset(-80px -80px -80px 85%);
}
/* the shadow the lifted cover drops on the first page, darkest under the cover's edge */
.ba-pages::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, rgba(26, 23, 20, 0.4) 50%, rgba(26, 23, 20, 0) 95%);
  opacity: var(--lift);
}
@media (prefers-reduced-motion: no-preference) {
  .ba-book {
    animation:
      ba-hop 2.5s ease-in-out 1.5s infinite,
      ba-lift 2.5s ease-in-out 1.5s infinite;
  }
  .ba-lid {
    /* the eye sits off to the right of the book, so a cover lifting toward it looks narrower and the pages show */
    perspective: 1100px;
    perspective-origin: 160% 40%;
  }
  .ba-open:is(:hover, :focus-visible, .is-opened) .ba-book {
    animation: none;
  }
}
/* The moves keep the timings they had in the old 7s loop (hop 0.9s, cover up and down by 1.9s); only the still part
   after them is shorter, so the percentages are the old ones times 7 / 2.5 */
@keyframes ba-hop {
  0%,
  36.4%,
  100% {
    translate: 0 0;
  }
  11.2% {
    translate: 0 -9px;
  }
  22.4% {
    translate: 0 0;
  }
  29.4% {
    translate: 0 -3px;
  }
}
/* --split isn't registered with @property, so it can't blend: it jumps from 0 to 1 halfway between 13.7% and 14%,
   and back halfway between 75.6% and 75.9%, just around the moments the cover starts and stops moving */
@keyframes ba-lift {
  0%,
  13.7%,
  75.9%,
  100% {
    --split: 0;
  }
  14%,
  75.6% {
    --split: 1;
  }
  0%,
  14%,
  75.6%,
  100% {
    --lift: 0;
  }
  30.8%,
  53.2% {
    --lift: 1;
  }
  67.2% {
    --lift: -0.15; /* a little flap as it drops shut */
  }
}

/* ---------- the open album: a full-screen sheet in the page's colour with the book in the middle. Esc, the close
   button or a click on the empty space around the book closes it; the page behind doesn't scroll meanwhile. ---------- */
.ba-album {
  --album-bg: var(--bg);
  --album-ink: #857d71; /* its caption, arrows and dots (the book's own colour) */
  --album-ink-soft: #c4beb4;
  --album-hover: #f4f1ec;
  --font-caption: "Fraunces", Georgia, "Times New Roman", serif;
  position: fixed;
  inset: 0;
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: max(16px, env(safe-area-inset-top, 0px)) max(16px, env(safe-area-inset-right, 0px))
    max(16px, env(safe-area-inset-bottom, 0px)) max(16px, env(safe-area-inset-left, 0px));
  border: 0;
  background: var(--album-bg);
  color: var(--album-ink);
}
[data-mode="night"] .ba-album {
  --album-ink: #b3a8d6;
  --album-ink-soft: #4a3f74;
  --album-hover: #171030;
}
.ba-album[open] {
  display: grid;
  place-items: center;
  animation: ba-in 0.35s ease-out;
}
.ba-album::backdrop {
  background: transparent;
}
html:has(.ba-album[open]) {
  overflow: hidden;
}
@keyframes ba-in {
  from {
    opacity: 0;
  }
}
.ba-album[open] .fb-stage {
  animation: ba-rise 0.45s cubic-bezier(0.2, 0.8, 0.3, 1);
}
@keyframes ba-rise {
  from {
    transform: translateY(26px) scale(0.96);
  }
}
.ba-close {
  position: absolute;
  top: max(14px, env(safe-area-inset-top, 0px));
  right: max(14px, env(safe-area-inset-right, 0px));
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  padding: 0;
  border: 2px solid var(--album-ink);
  border-radius: 50%;
  background: transparent;
  color: var(--album-ink);
  cursor: pointer;
}
.ba-close:hover {
  background: var(--album-hover);
}
.ba-close svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}
.ba-title {
  position: absolute;
  top: max(26px, env(safe-area-inset-top, 0px));
  left: 50%;
  margin: 0;
  transform: translateX(-50%);
  font: 500 0.8125rem/1 var(--font-caption);
  letter-spacing: 0.32em;
  text-transform: uppercase;
  white-space: nowrap;
}
.fb-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(20px, 4vh, 36px);
}
@media (prefers-reduced-motion: reduce) {
  .ba-album[open],
  .ba-album[open] .fb-stage {
    animation: none;
  }
}

/* ---------- the Worn Sketchbook, as made for the owner (class names prefixed fb-) ---------- */
/* =====================================================================
   SETTINGS — change these to restyle the book
   ===================================================================== */
.fb-stage {
  --fb-paper: #f3ecdc; /* paper colour, shows at worn edges   */
  --fb-ink: #857d71; /* caption, arrows, dots               */
  --fb-ink-soft: #c4beb4;
  --fb-hover: #f4f1ec;
  --fb-shadow: rgba(52, 40, 20, 0.3);

  --ratio: 1.45; /* page height divided by page width   */
  --max-page-width: 330px; /* biggest size of ONE page            */
  --flip-time: 1050ms; /* length of a page turn               */
  --flip-ease: cubic-bezier(0.65, 0, 0.35, 1);
  --perspective: 2000px; /* lower = more dramatic 3D turn       */

  --font-caption: "Fraunces", Georgia, "Times New Roman", serif;
  --font-ui: ui-sans-serif, -apple-system, "Segoe UI", Roboto, system-ui, sans-serif;

  /* page size (derived) */
  --pw: max(120px, min(40vw, var(--max-page-width), calc((100vh - 230px) / var(--ratio))));
  --ph: calc(var(--pw) * var(--ratio));

  /* paper tooth + warm age, multiplied over each page */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='.14 0 0 0 .87 .14 0 0 0 .855 .14 0 0 0 .83 0 0 0 0 1'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
}

/* =====================================================================
   THE BOOK
   ===================================================================== */
.fb-book {
  position: relative;
  width: calc(var(--pw) * 2);
  height: var(--ph);
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  filter: drop-shadow(0 0.6px 0.8px rgba(70, 52, 24, 0.38));
  opacity: 0;
  transition: opacity 0.4s ease;
}
.fb-book.is-ready {
  opacity: 1;
}
.fb-book:focus-visible {
  outline: 2px solid var(--fb-ink);
  outline-offset: 14px;
  border-radius: 6px;
}

/* soft shadow on the table */
.fb-book::before {
  content: "";
  position: absolute;
  left: 2.5%;
  right: 2.5%;
  top: 10%;
  bottom: 1.5%;
  border-radius: 10px;
  box-shadow:
    0 20px 30px -16px var(--fb-shadow),
    0 42px 70px -40px var(--fb-shadow);
  pointer-events: none;
}

/* ---- a page ---- */
.fb-page {
  --turn: 0deg;
  position: absolute;
  top: 0;
  width: var(--pw);
  height: var(--ph);
  background: var(--fb-paper);
  transform: perspective(var(--perspective)) rotateY(var(--turn));
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  will-change: transform;
}
.fb-page--left {
  left: 0;
  transform-origin: right center;
  --gutter-side: to left;
}
.fb-page--right {
  left: var(--pw);
  transform-origin: left center;
  --gutter-side: to right;
}

.fb-page--left.is-ahead {
  --turn: 180deg;
} /* not reached yet: waiting on the right */
.fb-page--right.is-turned {
  --turn: -180deg;
} /* already turned: lying on the left    */

.fb-book.is-live > .fb-page {
  transition: transform var(--flip-time) var(--flip-ease);
}

/* the picture fills the page */
.fb-page > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--focus, 50% 50%);
  display: block;
  -webkit-user-drag: none;
}

/* browned, handled edges (pushed off the spine side) */
.fb-page::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 130%;
  z-index: 2;
  box-shadow: inset 0 0 calc(var(--pw) * 0.05) rgba(120, 88, 40, 0.45);
  mix-blend-mode: multiply;
  pointer-events: none;
}
.fb-page--left::before {
  left: 0;
}
.fb-page--right::before {
  left: -30%;
}

/* gutter fold shadow + paper grain */
.fb-page::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  background:
    linear-gradient(
      var(--gutter-side),
      rgba(38, 26, 10, 0.38),
      rgba(38, 26, 10, 0.17) 1.6%,
      rgba(38, 26, 10, 0.05) 6%,
      rgba(38, 26, 10, 0) 24%
    ),
    var(--grain);
  mix-blend-mode: multiply;
  pointer-events: none;
}

/* worn print: specks, scuffs, crease, cut edge (drawn by book.js) */
.fb-page > .wear,
.fb-sheet > .wear {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  color: var(--fb-paper);
  pointer-events: none;
}
.wear-speck,
.wear-scuff {
  fill: currentColor;
}
.wear-speck.is-faint {
  opacity: 0.55;
}
.wear-scuff {
  opacity: 0.4;
}
.wear-crease {
  fill: none;
  stroke: rgba(78, 56, 26, 0.3);
  stroke-width: 1.2;
  vector-effect: non-scaling-stroke;
}
.wear-edge {
  fill: none;
  stroke: rgba(96, 72, 38, 0.5);
  stroke-width: 1.3;
  vector-effect: non-scaling-stroke;
}

/* darkening while a page turns */
.fb-page > .shade {
  position: absolute;
  inset: 0;
  z-index: 4;
  opacity: 0;
  background: linear-gradient(var(--gutter-side), rgb(16, 10, 3), rgba(16, 10, 3, 0.7));
  pointer-events: none;
}
.fb-page.is-leaving > .shade {
  animation: fb-shade-leave var(--flip-time) linear;
}
.fb-page.is-arriving > .shade {
  animation: fb-shade-arrive var(--flip-time) linear;
}
@keyframes fb-shade-leave {
  0% {
    opacity: 0;
  }
  50%,
  100% {
    opacity: 0.5;
  }
}
@keyframes fb-shade-arrive {
  0%,
  50% {
    opacity: 0.5;
  }
  100% {
    opacity: 0;
  }
}

/* shown on a page whose image could not be found */
.fb-page > .missing {
  position: absolute;
  inset: 12% 10%;
  z-index: 5;
  display: grid;
  place-content: center;
  gap: 6px;
  text-align: center;
  font:
    12px/1.4 ui-monospace,
    Menlo,
    Consolas,
    monospace;
  color: #7a4a2a;
  overflow-wrap: anywhere;
}

/* ---- loose pages peeking out under each side ---- */
.fb-sheet {
  position: absolute;
  top: calc(var(--depth) * 2.3px);
  width: var(--pw);
  height: var(--ph);
  z-index: calc(5 - var(--depth));
  background: var(--tone, var(--fb-paper));
  box-shadow: inset 0 0 calc(var(--pw) * 0.04) rgba(120, 88, 40, 0.3);
  transition: opacity 0.5s ease;
  pointer-events: none;
}
.fb-sheet--left {
  left: calc(var(--depth) * -1.3px);
}
.fb-sheet--right {
  left: calc(var(--pw) + var(--depth) * 1.3px);
}
.fb-sheet.is-hidden {
  opacity: 0;
}

/* =====================================================================
   CAPTION + CONTROLS
   ===================================================================== */
.fb-meta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
.fb-meta p {
  margin: 0;
}
.fb-caption {
  font-family: var(--font-caption);
  font-weight: 500;
  font-size: clamp(11px, 1.5vw, 14px);
  text-transform: uppercase;
  letter-spacing: 0.42em;
  padding-left: 0.42em;
  text-align: center;
}
.fb-controls {
  display: flex;
  align-items: center;
  gap: 18px;
}
.fb-nav {
  appearance: none;
  border: none;
  cursor: pointer;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: transparent;
  color: var(--fb-ink);
  transition:
    background 0.2s ease,
    opacity 0.2s ease,
    transform 0.15s ease;
}
.fb-nav:hover:not(:disabled) {
  background: var(--fb-hover);
}
.fb-nav:active:not(:disabled) {
  transform: scale(0.92);
}
.fb-nav:disabled {
  opacity: 0.3;
  cursor: default;
}
.fb-nav:focus-visible {
  outline: 2px solid var(--fb-ink);
  outline-offset: 3px;
}
.fb-nav svg {
  width: 19px;
  height: 19px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.fb-dots {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  max-width: 60vw;
}
.fb-dots span {
  width: 6px;
  height: 6px;
  border-radius: 3px;
  background: var(--fb-ink-soft);
  transition:
    width 0.3s ease,
    background 0.3s ease;
}
.fb-dots span.is-on {
  width: 20px;
  background: var(--fb-ink);
}
.fb-hint {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fb-ink-soft);
  transition: opacity 0.5s ease;
}
.fb-hint.is-gone {
  opacity: 0;
}
.fb-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .fb-book.is-live > .fb-page {
    transition: none;
  }
  .fb-page > .shade {
    animation: none !important;
  }
  /* the colours still fade; the press-in and the dot stretching don't */
  .fb-nav {
    transition:
      background 0.2s ease,
      opacity 0.2s ease;
  }
  .fb-dots span {
    transition: background 0.3s ease;
  }
}

/* the page size: a little smaller than the sketchbook's own, so the caption and controls fit under it; and the
   caption, arrows and dots in the album's colours for day or night (after the book's settings, so these win) */
.fb-stage {
  --fb-ink: var(--album-ink);
  --fb-ink-soft: var(--album-ink-soft);
  --fb-hover: var(--album-hover);
  --pw: max(120px, min(42vw, var(--max-page-width), calc((100vh - 250px) / var(--ratio))));
}

/* ---------- tablets and desktops: a bigger book with the arrows at its sides. The page size comes from the screen's
   height (all but 200px for the title, caption and dots), up to 42% of its width per page, with no fixed cap, so on
   a laptop the book fills the sheet instead of sitting small in the middle. The caption and dots sit under it, and
   the hint at the bottom edge of the sheet.
   The page width is the smaller of two limits: the height, all but 120px of it (the title above the book; the
   caption, dots and hint below), and the width, all but 204px of it (the sheet's padding, the two 54px arrows and
   the gaps beside them) shared by two pages. So the book is as big as the screen allows without running into the
   arrows, the title or the caption.
   .fb-meta and .fb-controls are display: contents, so their children (the caption, the two arrows, the dots, the
   hint) become items of the stage's grid and can be placed round the book without changing the HTML. A soft pool of
   light behind the book gives the sheet some depth. ---------- */
@media (min-width: 641px) {
  .ba-album {
    background:
      radial-gradient(70% 60% at 50% 46%, color-mix(in srgb, var(--album-ink) 13%, transparent), transparent 70%),
      var(--album-bg);
  }
  .fb-stage {
    --pw: max(120px, min(calc((100vw - 204px) / 2), calc((100dvh - 120px) / var(--ratio))));
    display: grid;
    grid-template-columns: auto auto auto;
    grid-template-areas:
      "prev book next"
      ". caption ."
      ". dots .";
    align-items: center;
    justify-items: center;
    column-gap: clamp(10px, 2vw, 28px);
    row-gap: 10px;
  }
  .fb-meta,
  .fb-controls {
    display: contents;
  }
  .fb-book {
    grid-area: book;
  }
  .fb-caption {
    grid-area: caption;
  }
  .fb-dots {
    grid-area: dots;
  }
  .ba-title {
    top: max(16px, env(safe-area-inset-top, 0px)); /* up near the edge, so the book can be taller */
  }
  .fb-hint {
    position: absolute; /* at the bottom of the sheet (.ba-album), out of the book's way */
    left: 50%;
    bottom: max(14px, env(safe-area-inset-bottom, 0px));
    margin: 0;
    translate: -50% 0;
    white-space: nowrap;
  }
  .fb-prev {
    grid-area: prev;
  }
  .fb-next {
    grid-area: next;
  }
  .fb-nav {
    width: 54px;
    height: 54px;
    border: 1.5px solid var(--fb-ink-soft);
  }
  .fb-nav:hover:not(:disabled) {
    border-color: var(--fb-ink);
  }
  .fb-nav svg {
    width: 22px;
    height: 22px;
  }
  .ba-story {
    display: none;
  }
}

/* ---------- phones: Stories (the owner's pick from the Birthday Album Phone Variations page, 11 November 2026). The
   two-page book has no room on a phone, so each photo fills the whole screen over a blurred copy of itself (a wide
   photo shows whole; a tall one fills it), with its caption in big letters at the bottom. Tap the right of the
   screen for the next photo, the left for the one before; it also moves on by itself every 5 seconds, and holding a
   finger down pauses it. Bars at the top show how far through you are; after the last photo comes "Your party next?"
   with Book your party (it opens the booking popup). Visitors who ask for less motion tap through; nothing moves by
   itself. The book and the close button keep their places; the sheet's title gives way to the head row. ---------- */
@media (max-width: 640px) {
  .ba-album[open] {
    padding: 0;
  }
  .fb-stage,
  .ba-title {
    display: none;
  }
  .ba-close {
    z-index: 6;
    top: calc(env(safe-area-inset-top, 0px) + 22px);
    right: max(12px, env(safe-area-inset-right, 0px));
    width: 40px;
    height: 40px;
    border-color: rgba(255, 255, 255, 0.75);
    color: #fff;
  }
  .ba-close:hover {
    background: rgba(255, 255, 255, 0.12);
  }
}
.ba-story {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: #000;
  color: #fff;
  user-select: none;
  -webkit-user-select: none;
}
.ba-story-slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 0.35s ease;
}
.ba-story-slide.is-on {
  opacity: 1;
}
.ba-story-slide img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--focus, 50% 50%);
}
.ba-story-slide .ba-story-fill {
  filter: blur(26px) brightness(0.55) saturate(1.2);
  transform: scale(1.25);
}
.ba-story-slide.is-wide .ba-story-pic {
  object-fit: contain;
}
.ba-story-slide.is-on .ba-story-pic {
  animation: ba-story-zoom 6s ease-out both;
}
@keyframes ba-story-zoom {
  from {
    transform: scale(1.06);
  }
}
/* darker at the top and bottom, so the bars, the head and the caption read on any photo */
.ba-story::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(rgba(0, 0, 0, 0.55), transparent 22%, transparent 55%, rgba(0, 0, 0, 0.8));
}
/* the two halves of the screen are the buttons (left 35%: back; the rest: next) */
.ba-story-prev,
.ba-story-next {
  position: absolute;
  z-index: 2;
  top: 0;
  bottom: 0;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ba-story-prev {
  left: 0;
  width: 35%;
}
.ba-story-next {
  right: 0;
  width: 65%;
}
.ba-story-prev:focus-visible,
.ba-story-next:focus-visible {
  outline: 3px solid #fff;
  outline-offset: -6px;
}
.ba-story-bars {
  position: absolute;
  z-index: 3;
  top: calc(env(safe-area-inset-top, 0px) + 10px);
  left: 12px;
  right: 12px;
  display: flex;
  gap: 4px;
  pointer-events: none;
}
.ba-story-bars span {
  flex: 1;
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.32);
  overflow: hidden;
}
.ba-story-bars i {
  display: block;
  height: 100%;
  background: #fff;
  transform: scaleX(0);
  transform-origin: left;
}
.ba-story-bars .is-done i {
  transform: scaleX(1);
}
.ba-story-bars .is-running i {
  animation: ba-story-fill 5s linear forwards;
}
.ba-story.is-held .ba-story-bars i,
.ba-story.is-ended .ba-story-bars i {
  animation-play-state: paused;
}
@keyframes ba-story-fill {
  to {
    transform: scaleX(1);
  }
}
.ba-story-head {
  position: absolute;
  z-index: 3;
  top: calc(env(safe-area-inset-top, 0px) + 24px);
  left: 14px;
  right: 64px;
  display: flex;
  align-items: center;
  gap: 10px;
  pointer-events: none;
}
.ba-story-av {
  display: grid;
  flex: none;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: #db2e27;
  box-shadow: 0 0 0 2px #fff;
  font:
    900 1.4rem/1 "Big Shoulders Display",
    sans-serif;
}
.ba-story-head b {
  display: block;
  font-size: 0.875rem;
}
.ba-story-head small {
  font-size: 0.75rem;
  opacity: 0.8;
}
.ba-story-foot {
  position: absolute;
  z-index: 3;
  left: 22px;
  right: 22px;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 44px);
  display: grid;
  justify-items: start;
  gap: 12px;
  pointer-events: none;
}
.ba-story-cap {
  margin: 0;
  font:
    900 clamp(2.75rem, 15vw, 4.5rem)/0.84 "Big Shoulders Display",
    sans-serif;
  text-transform: uppercase;
  text-wrap: balance;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.4);
}
.ba-story-cap:empty {
  display: none;
}
.ba-story-cap span {
  display: inline-block;
  animation: ba-story-up 0.5s cubic-bezier(0.2, 0.8, 0.3, 1) both;
}
@keyframes ba-story-up {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
}
.ba-story-tag {
  padding: 6px 12px;
  border-radius: 99px;
  background: #ffd731;
  color: #1a1714;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
}
/* under the tag, centred, so the two never meet on a narrow phone */
.ba-story-hint {
  position: absolute;
  z-index: 3;
  left: 0;
  right: 0;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 16px);
  margin: 0;
  text-align: center;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.85;
  pointer-events: none;
  transition: opacity 0.4s;
}
.ba-story-hint.is-gone {
  opacity: 0;
}
.ba-story-end {
  position: absolute;
  z-index: 4;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 18px;
  padding: 40px;
  background: rgba(20, 23, 27, 0.72);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  text-align: center;
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 0.4s,
    visibility 0s 0.4s;
}
.ba-story.is-ended .ba-story-end {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.4s;
}
.ba-story-end h3 {
  margin: 0;
  font:
    900 clamp(2.5rem, 13vw, 4rem)/0.88 "Big Shoulders Display",
    sans-serif;
  text-transform: uppercase;
}
.ba-story-end p {
  margin: 0;
  font-size: 0.9375rem;
  opacity: 0.85;
}
.ba-story-book {
  padding: 14px 24px;
  border: 0;
  border-radius: 99px;
  background: #db2e27;
  color: #fff;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}
.ba-story-again {
  padding: 6px;
  border: 0;
  background: none;
  color: #fff;
  font: inherit;
  font-size: 0.875rem;
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
}
.ba-story-book:focus-visible,
.ba-story-again:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
  .ba-story-slide {
    transition: none;
  }
  .ba-story-slide.is-on .ba-story-pic,
  .ba-story-cap span {
    animation: none;
  }
  /* nothing moves on by itself: the current bar just shows as full */
  .ba-story-bars .is-running i {
    animation: none;
    transform: scaleX(1);
  }
}
