/* Public gallery: quiet masthead, justified grid with margins, lightbox.
   Motion (ADR 017): photos arrive by fading over their placeholder; tiles rise in as they
   enter the viewport; hover zooms the photo inside its own frame. Transform/opacity only. */
.gallery-page { padding-bottom: 5.5rem; }
.gallery-page:has(.cart-fab:not([hidden])) { padding-bottom: 8.5rem; }
.gallery-page .site-footer { position: fixed; z-index: 4; inset: auto 0 0; max-width: none; margin: 0; padding: .55rem var(--page) calc(.55rem + env(safe-area-inset-bottom, 0px)); align-items: center; font-size: .75rem; pointer-events: none; }
.gallery-page .site-footer > * { position: relative; pointer-events: auto; }
.gallery-page .site-footer::before { content: ""; position: absolute; inset: -1.25rem 0 0; background: color-mix(in srgb, var(--bg) 62%, transparent); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); -webkit-mask-image: linear-gradient(to top, #000 45%, transparent); mask-image: linear-gradient(to top, #000 45%, transparent); }
.gallery-page .site-footer .brand { display: none; }
/* The blurred bar only when the footer offers something; the Customer's "Sign in" alone keeps the photos clear. */
.gallery-page .site-footer:not(:has(nav a:not([data-customer-link])))::before { display: none; }
.gallery-page .site-footer:not(:has(nav a:not([data-customer-link]))) a[data-customer-link] { padding: .2rem .6rem; border-radius: 999px; color: var(--fg); text-decoration: none; background: color-mix(in srgb, var(--bg) 62%, transparent); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); }
.after-brand { margin: 1rem 0 0; }
.after-brand .brand-mark { height: 1.5rem; }

/* ---- Masthead ------------------------------------------------------------- */
.gallery-page { --page: clamp(1.25rem, 7vw, 7rem); --row-h: 340px; --gap: .45rem; }
.masthead { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: .5rem 2rem; padding: clamp(1.25rem, 3vw, 2.25rem) var(--page) clamp(1.5rem, 4vw, 3rem); }
.wordmark { margin: 0; font-size: clamp(1.2rem, 2.2vw, 1.55rem); font-weight: 700; letter-spacing: -.01em; animation: rise 700ms var(--ease-out) backwards; }
.album-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .15rem 1rem; animation: rise 700ms var(--ease-out) 80ms backwards; }
.album-head h1 { margin: 0; font-size: 1rem; font-weight: 500; letter-spacing: 0; }
.album-head .meta { margin: 0; }
.masthead { padding-right: calc(var(--page) + 2.25rem); }
.js .masthead { position: sticky; top: 0; z-index: 4; pointer-events: none; }
.js .masthead::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--bg); transform-origin: top; transition: transform var(--t-base) var(--ease-out); }
.wordmark, .album-head, .gallery-page .theme-corner { transition: transform var(--t-base) var(--ease-out), opacity var(--t-fast) ease; }
.wordmark { transform-origin: left center; }
.album-head { transform-origin: left top; }
.is-compact .masthead::before { transform: scaleY(var(--squash, .4)); }
.is-compact .wordmark { transform: translateY(calc(var(--lift, 0px) * -1)) scale(var(--wordmark-scale, .8)); }
.is-compact .album-head { transform: translateY(calc(var(--head-lift, 0px) * -1)) scale(var(--head-scale, 1)); }
.js .gallery-page:not(.is-compact) .theme-corner { transform: translateY(var(--lift, 0px)); }
/* The switch lines up with the logo only once gallery.js has measured it; until then it waits unseen, so it
   never jumps on a first visit. If the script never runs, it shows anyway after a few seconds. */
.js .gallery-page:has(.masthead):not(.mast-ready) .theme-corner { opacity: 0; transition: none; animation: show-anyway 0s 4s forwards; }
@media (prefers-reduced-motion: reduce) { .js .masthead::before, .wordmark, .album-head, .gallery-page .theme-corner { transition: none; } }

/* ---- Justified grid -------------------------------------------------------- */
/* Each tile grows in proportion to its aspect ratio, so rows share one height and no
   photo is cropped. With JS, gallery.js chooses the line breaks so the last row fills too. */
.grid { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--gap); padding: 0 var(--page); max-width: 100%; }
.tile {
  position: relative; display: block; aspect-ratio: var(--r);
  flex: calc(var(--r) * 100) 1 calc(var(--r) * var(--row-h));
  overflow: hidden;
  background: var(--line) var(--ph, none) center / cover no-repeat;
}
.tile picture, .tile img { width: 100%; height: 100%; }
.tile img {
  object-fit: cover;
  transition: opacity 500ms ease, transform 900ms var(--ease-out), filter 500ms ease;
}
.js .tile img { opacity: 0; }
.js .tile img.ready { opacity: 1; }
.tile:focus-visible { outline: 2px solid var(--fg); outline-offset: -2px; }
/* One photo to a line on a phone, each at its own proportions. */
@media (max-width: 640px) { .grid[data-size=large] .tile, .grid[data-size=xlarge] .tile { flex: 1 1 100%; } }
/* Without JS the size sets the row height; with it gallery.js works from photos across. */
.grid[data-size=small] { --row-h: 200px; }
.grid[data-size=medium] { --row-h: 280px; }
.grid[data-size=large] { --row-h: 380px; }
.grid[data-size=xlarge] { --row-h: 560px; }
@media (max-width: 640px) { .grid[data-size=small] { --row-h: 90px; } .grid[data-size=medium] { --row-h: 140px; } }

/* Rise in once, as the tile scrolls into view. Hidden from the first paint, not from when gallery.js runs:
   on a first visit the script arrives after the page has painted, and tiles shown in the plain CSS layout would
   flash and jump. If the script never runs, they show anyway after a few seconds. */
.js .tile { opacity: 0; transform: translateY(14px); }
.js .tile:not(.in) { animation: show-anyway 0s 4s forwards; }
@keyframes show-anyway { to { opacity: 1; transform: none; } }
.js .tile.in {
  opacity: 1; transform: none;
  transition: opacity 700ms ease var(--d, 0ms), transform 900ms var(--ease-out) var(--d, 0ms);
}

/* Hover: the photo eases forward inside its frame; the frame itself never moves. */
@media (hover: hover) and (pointer: fine) {
  .tile:hover img.ready { transform: scale(1.035); }
  .grid:has(.tile:hover) .tile:not(:hover) img.ready { filter: brightness(.88); }
}

.after { max-width: 34rem; margin: 0 auto; padding: 2.5rem 1.25rem 0; text-align: center; }
.after-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem; }
.share-button, .get-album { display: inline-flex; align-items: center; gap: .4rem; }
/* Get album in the masthead: its own centred row, faded out in the small header (the one below the photos stays);
   centred between the brand and the title where the row is wide enough for all three. */
.mast-get { flex-basis: 100%; display: flex; justify-content: center; transition: opacity var(--t-fast) ease; }
.mast-get .buy-album { margin: 0; }
.js .mast-get :is(button, a) { pointer-events: auto; }
.is-compact .mast-get { opacity: 0; visibility: hidden; transition: opacity var(--t-fast) ease, visibility 0s var(--t-fast); }
@media (min-width: 75rem) {
  .masthead:has(.mast-get) { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; }
  .masthead:has(.mast-get) .album-head { grid-column: 3; justify-self: end; }
  .masthead .mast-get { grid-column: 2; grid-row: 1; }
  .is-compact .mast-get { opacity: 1; visibility: visible; transform: translateY(calc(var(--lift, 0px) * -1)); transition: transform var(--t-base) var(--ease-out); }
}
.share-button[hidden] { display: none; }
.notify-toggle { position: absolute; opacity: 0; width: 1px; height: 1px; }
.after:has(.notify-toggle:focus-visible) label[for=notify-toggle] { outline: 2px solid var(--muted); outline-offset: 2px; }
.after:has(.notify-toggle:checked) label.button[for=notify-toggle] { border-color: var(--muted); }
.after-meta { margin: 1rem 0 0; }
/* The policy links at the end of the photos (ADR 093): a small row, wrapping between links, not inside one. */
.after-policies { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.25rem 1rem; }
.after-policies a { color: var(--muted); white-space: nowrap; }
.notify-link { color: inherit; text-decoration: underline; cursor: pointer; }
html:not(.js) .with-js, html.js .without-js, html:not(.js) [data-tip-link] { display: none; }
.notify-pane { display: none; flex-basis: 100%; margin: 1rem 0 .75rem; text-align: left; }
.notify-toggle:checked ~ .notify-pane { display: block; animation: rise var(--t-base) var(--ease-out) both; }
.notify-pane .notice { margin: 0; }

/* ---- Lightbox -------------------------------------------------------------- */
/* The dialog is transparent; .lb-bg fades the black in so the photo can zoom out of
   its tile over the page (the zoom itself is driven from gallery.js). */
.lightbox {
  border: 0; padding: 0; margin: 0; width: 100vw; height: 100dvh; max-width: none; max-height: none;
  background: transparent; color: #eee; overflow: hidden;
  --lb-gap: 12px; /* the photo never quite touches the screen edge (gallery.js reads this) */
}
.lightbox::backdrop { background: transparent; }
.lb-leaving { pointer-events: none; }
/* The viewer itself takes focus when it opens (gallery.js), so the arrow keys never light up the close button; Tab
   still reaches it, and its ring keeps its round shape. */
.lightbox:focus, .lightbox:focus-visible { outline: none; }
.lightbox .lb-close:focus-visible { border-radius: 999px; outline: 2px solid var(--fg); outline-offset: 2px; }
.lb-bg { position: absolute; inset: 0; background: var(--lb-bg); transition: background-color var(--t-base) ease; }
.lb-img { position: absolute; inset: var(--lb-gap); margin: auto; width: min(100% - 2 * var(--lb-gap), var(--cap-w, 100%)); height: min(100% - 2 * var(--lb-gap), var(--cap-h, 100%)); object-fit: contain; transform-origin: 50% 50%; touch-action: pan-y pinch-zoom; user-select: none; -webkit-user-drag: none; }
.lb-close, .lb-arrow {
  background: rgba(0,0,0,.35); color: #fff; border: 0; border-radius: 999px; width: 44px; height: 44px; font-size: 1.6rem; line-height: 1; padding: 0;
}
.lb-close { position: absolute; z-index: 2; top: max(1.25rem, env(safe-area-inset-top)); right: 1.75rem; transition: opacity var(--t-base) ease, background-color var(--t-fast) ease; }
.lb-close:hover { background: rgba(0,0,0,.6); }
/* Each side of the screen is one click strip; its arrow barely shows until the pointer is in it. */
.lb-nav { position: absolute; z-index: 1; top: 0; bottom: 0; display: flex; align-items: center; width: clamp(4.5rem, 18vw, 15rem); padding: 0 1.75rem; border: 0; background: none; color: #fff; cursor: pointer; transition: opacity var(--t-base) ease; }
.lb-prev { left: 0; justify-content: flex-start; }
.lb-next { right: 0; justify-content: flex-end; }
.lb-arrow { display: grid; place-items: center; opacity: .12; transition: opacity var(--t-base) ease, transform var(--t-fast) var(--ease-out); }
.lb-nav:hover .lb-arrow, .lb-nav:focus-visible .lb-arrow { opacity: 1; }
.lb-nav:active .lb-arrow { transform: scale(.94); }
@media (hover: none) { .lb-nav { display: none; } }
.lb-bar {
  pointer-events: none; position: absolute; z-index: 2; left: 0; right: 0; bottom: max(12px, env(safe-area-inset-bottom)); display: flex; justify-content: center; gap: 1.5rem; font-size: .85rem; color: var(--lb-fg);
  transition: opacity var(--t-base) ease;
}
.lb-bar a { color: inherit; }
.lb-bar > * { pointer-events: auto; }
/* Chrome fades in after the photo lands and out while it travels. The Cart button is exempt:
   it sits exactly over the page's own, so it stays put rather than blinking out and back. */
.lightbox:not(.settled) .lb-close, .lightbox:not(.settled) .lb-nav, .lightbox:not(.settled) .lb-bar, .lightbox:not(.settled) .lb-buy { opacity: 0; pointer-events: none; }

/* ---- Buying and tips -------------------------------------------------------- */
.buy-album { margin: 0; }
.lb-buy { position: absolute; z-index: 2; display: grid; place-items: center; width: 2.75rem; height: 2.75rem; padding: 0; border: 0; border-radius: 50%; background: rgba(0, 0, 0, .2); color: #fff; opacity: .55; cursor: pointer; transition: opacity var(--t-fast) ease; }
@media (hover: hover) { .lightbox:not(.over-photo) .lb-buy:not(.in-cart):not(:focus-visible):not(:hover) { opacity: 0; } }
.lb-buy svg { width: 1.25rem; height: 1.25rem; }
.lb-buy:hover, .lb-buy:focus-visible { opacity: 1; }
.offer { width: min(26rem, calc(100vw - 2rem)); padding: 1.75rem 1.5rem 1.5rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); color: var(--fg); }
.offer::backdrop { background: rgba(0,0,0,.55); }
.offer[open], .offer[open]::backdrop { animation: fade var(--t-base) ease both; }
.offer h2 { margin: 0 0 .35rem; font-size: 1.2rem; font-weight: 500; }
.offer .meta { margin: 0 0 1.1rem; }
.offer-close { position: absolute; top: .35rem; right: .35rem; width: 2.5rem; height: 2.5rem; padding: 0; border: 0; background: none; color: var(--muted); font-size: 1.5rem; line-height: 1; }
.tip-choices { display: grid; grid-template-columns: repeat(auto-fit, minmax(3.5rem, 1fr)); gap: .4rem; margin-bottom: .9rem; }
.tip-heading { margin: 0 0 .5rem; font-size: .9rem; font-weight: 600; }
.tip-choices small { display: block; font-size: .72rem; opacity: .7; }
.tip-choices input { position: absolute; opacity: 0; pointer-events: none; }
.tip-choices span { display: block; padding: .6rem .25rem; border: 1px solid var(--line); border-radius: var(--radius); text-align: center; cursor: pointer; transition: background-color var(--t-fast) ease, color var(--t-fast) ease; }
.tip-choices input:checked + span { background: var(--fg); color: var(--bg); border-color: var(--fg); }
.tip-choices input:focus-visible + span { outline: 2px solid var(--muted); outline-offset: 1px; }
.tip-other { display: none; align-items: center; gap: .5rem; margin-bottom: .9rem; font-size: .9rem; color: var(--muted); }
.tip-other.on { display: flex; }
.tip-other input { flex: 1; min-width: 0; }
.offer-actions { display: grid; gap: .5rem; }
.offer-actions .button { text-align: center; }
.offer-actions [hidden] { display: none; }
.offer-consent { margin: .75rem 0 0; font-size: .8rem; text-align: center; }
.offer-consent[hidden] { display: none; }
.offer-consent a { color: inherit; }

/* Save protection: a deterrent, see the spec. */
.tile, .tile img, .lb-img, .lb-bg { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; -webkit-user-drag: none; }
.save-unprotected :is(.tile, .tile img, .lb-img, .lb-bg) { -webkit-touch-callout: default; -webkit-user-select: auto; user-select: auto; -webkit-user-drag: auto; }

/* ---- Cart -------------------------------------------------------------------- */
.tile { position: relative; }
.tile-add { position: absolute; right: .5rem; bottom: .5rem; display: grid; place-items: center; width: 2rem; height: 2rem; padding: 0; border: 0; border-radius: 50%; background: rgba(0, 0, 0, .2); color: #fff; opacity: 0; cursor: pointer; transition: opacity var(--t-fast) ease; }
.tile-add svg { width: 1rem; height: 1rem; }
.tile:hover .tile-add { opacity: .55; }
.tile .tile-add:hover, .tile-add:focus-visible { opacity: 1; }
@media (hover: none) { .tile-add { display: none; } .tile-add.in-cart { display: grid; pointer-events: none; } }
/* In the Cart: a frosted check that stays put, turning to a trash icon on hover. */
.tile .tile-add.in-cart, .tile:hover .tile-add.in-cart, .lb-buy.in-cart { border: 1px solid rgba(255, 255, 255, .6); background: rgba(255, 255, 255, .28); -webkit-backdrop-filter: blur(10px) saturate(1.3); backdrop-filter: blur(10px) saturate(1.3); color: #fff; opacity: 1; }
.icon-rest, .icon-hover { display: grid; grid-area: 1 / 1; transition: opacity var(--t-fast) ease; }
.in-cart svg { filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .5)); }
.icon-hover { opacity: 0; }
@media (hover: hover) {
  .tile:hover .icon-rest, .lb-buy:hover .icon-rest { opacity: 0; }
  .tile:hover .icon-hover, .lb-buy:hover .icon-hover { opacity: 1; }
}
@media (hover: none) { .lb-buy .icon-rest { opacity: 0; } .lb-buy .icon-hover { opacity: 1; } }
/* On a touch screen the add button keeps one place, centred just above the cart button, so a thumb finds it on
   every photo. */
@media (hover: none) {
  .lb-buy { position: fixed; width: 2.5rem; height: 2.5rem; right: calc(max(1.5rem, env(safe-area-inset-right, 0px)) + .625rem); bottom: calc(8.25rem + env(safe-area-inset-bottom, 0px)); opacity: 1; background: rgba(0, 0, 0, .35); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); }
  .lb-buy svg { width: 1.125rem; height: 1.125rem; }
}
.cart-fab { position: fixed; z-index: 5; right: max(1.5rem, env(safe-area-inset-right, 0px)); bottom: calc(3.75rem + env(safe-area-inset-bottom, 0px)); display: grid; place-items: center; width: 3.75rem; height: 3.75rem; padding: 0; border: 1px solid var(--line); border-radius: 50%; background: var(--panel); color: var(--fg); box-shadow: 0 6px 20px rgba(0, 0, 0, .35); cursor: pointer; transition: transform var(--t-fast) var(--ease-out); }
.cart-fab:hover { transform: scale(1.05); }
.cart-fab[hidden] { display: none; }
.lb-fab { z-index: 2; transition: opacity var(--t-base) ease, transform var(--t-fast) var(--ease-out); }
.cart-count:empty { visibility: hidden; }
.offer.is-empty .tip-heading, .offer.is-empty .tip-choices, .offer.is-empty .tip-other { display: none; }
.fx { position: fixed; inset: 0; width: 100vw; height: 100dvh; max-width: none; max-height: none; margin: 0; padding: 0; border: 0; background: none; overflow: hidden; pointer-events: none; }
.fx-photo { position: absolute; top: 0; left: 0; width: 34px; height: 34px; border-radius: 5px; object-fit: cover; box-shadow: 0 3px 8px rgba(0, 0, 0, .4); }
.fx-cloud { position: absolute; top: 0; left: 0; width: 22px; height: 22px; }
.fx-cloud svg { display: block; width: 100%; height: 100%; }
.fx-puff { position: absolute; top: 0; left: 0; width: 4px; height: 4px; box-sizing: border-box; border: 1px solid #23232b; border-radius: 50%; background: #fff; }
.fx-ray { position: absolute; top: 0; left: 0; width: 3px; height: 10px; border-radius: 2px; }
.cart-count { position: absolute; top: -.2rem; right: -.2rem; min-width: 1.4rem; height: 1.4rem; padding: 0 .3rem; border-radius: 999px; background: var(--fg); color: var(--bg); font-size: .78rem; font-weight: 600; line-height: 1.4rem; text-align: center; }
.cart-items { max-height: 38vh; margin: 0 0 .9rem; padding: 0; overflow-y: auto; list-style: none; }
.cart-items[hidden] { display: none; }
.cart-items li { display: flex; align-items: center; gap: .75rem; padding: .3rem 0; font-size: .9rem; }
.cart-items img { width: 3rem; height: 3rem; border-radius: var(--radius); object-fit: cover; }
.offer.is-cart { width: min(48rem, calc(100vw - 2rem)); height: min(60rem, calc(100dvh - 2rem)); max-width: none; max-height: none; overflow-y: auto; }
.offer.is-cart form { display: flex; flex-direction: column; min-height: 100%; }
.offer.is-cart .cart-items { flex: 1 1 0; min-height: 7rem; max-height: none; padding-right: 1.5rem; scrollbar-gutter: stable; }
.cart-items span { flex: 1; }
.cart-items button { display: grid; place-items: center; flex: none; width: 2.5rem; height: 2.5rem; padding: 0; border: 0; border-radius: 50%; background: none; color: var(--muted); cursor: pointer; transition: color var(--t-fast) ease; }
.cart-items button:hover { color: var(--danger); }
.cart-items button svg { width: 1.25rem; height: 1.25rem; }
.cart-whole { margin: 0 0 .9rem; }
.cart-whole[hidden] { display: none; }
.cart-whole button { padding: 0; border: 0; background: none; color: inherit; font-size: .9rem; text-decoration: underline; cursor: pointer; }
.lb-bar { flex-wrap: wrap; justify-content: center; gap: .5rem 1rem; }
.lb-bar > * { white-space: nowrap; }
/* ---- Website: the description as a quiet caption, and the admin's Preview bar ---- */
.lb-bar .lb-caption { flex-basis: 100%; max-width: 40rem; margin: 0 var(--page); white-space: normal; text-align: center; opacity: .8; }
.lb-caption:empty { display: none; }
.preview-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: .25rem 1.25rem; padding: .5rem var(--page); background: var(--panel); border-bottom: 1px solid var(--line); font-size: .85rem; color: var(--muted); }
.preview-bar a { color: var(--fg); }
/* The theme toggle sits in the top-right corner; keep the bar's links clear of it. */
.preview-bar { padding-right: calc(var(--page) + 2.75rem); }
.website-empty { padding: 0 var(--page); color: var(--muted); }
.offer-email { display: block; margin-bottom: .9rem; color: var(--muted); font-size: .9rem; }
.offer-email[hidden] { display: none; }
.offer-email input { display: block; width: 100%; margin-top: .3rem; }
@media (min-width: 48rem) {
  .offer.is-cart { padding: 2.25rem 2.25rem 2rem; }
  .offer.is-cart .cart-items { margin-bottom: 1.5rem; }
  .offer.is-cart .cart-items li { gap: 1.5rem; padding: .7rem 0; font-size: 1rem; }
  .offer.is-cart .cart-items img { width: 8rem; height: 8rem; }
}
/* Choosing a tip must not move anything: these rows keep their space in the Cart even while empty. */
.offer.is-cart .tip-other { display: flex; visibility: hidden; }
.offer.is-cart .tip-other.on { visibility: visible; }
.offer.is-cart[data-free=yes] .offer-email[hidden] { display: block; visibility: hidden; }
.offer.is-cart.is-empty .tip-other { display: none; }
.offer.is-cart #offer-pay { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Every tip button is the height of the tallest, its text centred. */
.tip-choices label { display: grid; }
.tip-choices label[hidden] { display: none; }
.tip-choices span { display: grid; place-content: center; }
/* Keeps the logo clear of the Admin link where the side margin is too narrow to hold it. */
@media (max-width: 62rem) { .gallery-page:has(:is(.admin-back:not([hidden]), .customer-back)) .masthead { padding-left: 4.25rem; } }
.js .gallery-page:not(.is-compact) :is(.admin-back, .customer-back) { transform: translateY(var(--lift, 0px)); }
.gallery-page :is(.admin-back, .customer-back) { transition: transform var(--t-base) var(--ease-out); }

/* ---- Website: the Hero ------------------------------------------------------- */
/* A still, full-screen photo cropped around its Focal point (--focus), over its Placeholder. The ink is white in
   both themes because it sits on a photograph; the scrim, not the theme, keeps it readable. Its motion is
   website.css's (ADR 069). */
.hero { position: relative; isolation: isolate; height: 100vh; height: 100svh; min-height: 24rem; overflow: hidden; background: #0b0b0c; color: #fff; }
.preview-bar ~ .hero { height: calc(100svh - 2.4rem); }
.hero-frame, .hero-photo, .hero-scrim { position: absolute; inset: 0; }
.hero-photo { display: block; background: var(--ph) var(--focus, 50% 50%) / cover no-repeat; }
.hero-photo img { width: 100%; height: 100%; max-width: none; object-fit: cover; object-position: var(--focus, 50% 50%); }
/* Three layers: a little shade under the theme switch, a soft pool behind the words, and the floor they stand on. */
.hero-scrim { pointer-events: none; background:
  linear-gradient(to bottom, rgb(0 0 0 / .34), rgb(0 0 0 / 0) 18%),
  radial-gradient(ellipse 70% 42% at 50% 80%, rgb(0 0 0 / .32), rgb(0 0 0 / 0) 72%),
  linear-gradient(to top, rgb(0 0 0 / .58), rgb(0 0 0 / .18) 38%, rgb(0 0 0 / 0) 62%); }
.hero-overlay { position: absolute; inset: auto 0 0; display: flex; flex-direction: column; align-items: center; gap: .55rem; padding: 0 var(--page) calc(clamp(3.75rem, 10svh, 6.5rem) + env(safe-area-inset-bottom, 0px)); text-align: center; text-shadow: 0 1px 2px rgb(0 0 0 / .25), 0 2px 24px rgb(0 0 0 / .3); }
.hero-brand { margin: 0; font-size: clamp(2.1rem, 6.2vw, 4.6rem); font-weight: 600; letter-spacing: -.025em; line-height: 1.02; text-wrap: balance; }
.hero-brand .brand-mark { height: clamp(4rem, 12vw, 8.5rem); filter: drop-shadow(0 2px 18px rgb(0 0 0 / .35)); }
.hero-tagline { margin: 0; max-width: 34rem; font-size: clamp(1rem, 1.7vw, 1.2rem); letter-spacing: .01em; color: rgb(255 255 255 / .9); text-wrap: balance; }
.hero-book { margin: .65rem 0 0; }
.hero-book a { display: inline-block; padding: .6rem 1.35rem; border: 1px solid rgb(255 255 255 / .6); border-radius: 999px; background: rgb(255 255 255 / .08); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); color: #fff; font-size: .78rem; font-weight: 600; letter-spacing: .14em; text-decoration: none; text-transform: uppercase; text-shadow: none; position: relative; }
/* Hover brightens the pill by fading in a lighter layer with a full-white edge: opacity only (ADR 017). */
.hero-book a::after { content: ""; position: absolute; inset: -1px; border: 1px solid #fff; border-radius: inherit; background: rgb(255 255 255 / .1); opacity: 0; transition: opacity var(--t-fast) ease; pointer-events: none; }
.hero-book a:hover::after { opacity: 1; }
.hero-book a:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
.hero-cue { position: absolute; left: 0; right: 0; bottom: calc(.75rem + env(safe-area-inset-bottom, 0px)); width: 2.75rem; height: 2.75rem; margin: 0 auto; display: grid; place-items: center; color: rgb(255 255 255 / .78); }
.hero-cue svg { width: 26px; height: 26px; }
.hero-cue:hover { color: #fff; }
.hero-cue:focus-visible { outline: 2px solid #fff; outline-offset: 2px; border-radius: 999px; }
.hero ~ main .website-grid { padding-top: clamp(2rem, 5vw, 4rem); }
/* The navigation, theme switch and footer over and after the Hero are website.css's (ADR 067). */

/* ---- Glass and settling (ADR 106) ------------------------------------------------ */
/* The small header frosts over the photos sliding under it, rather than covering them; it is the same tint as the
   page at rest, so the large header looks as it always did. */
.js .masthead::before { background: color-mix(in srgb, var(--bg) 80%, transparent); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); }
/* A photo settles into its frame as it fades in over its placeholder: from a hair larger, by transform. */
.js .tile img:not(.ready) { transform: scale(1.04); }
/* The lightbox's close and arrows are the Cart button's glass, so its controls read as one set. Their icons are
   drawn, not typed, so they sit at the exact centre of the circle. */
.lb-close, .lb-arrow { display: grid; place-items: center; color: var(--fg); background: var(--glass-tint-strong); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); box-shadow: var(--glass-edge), var(--glass-lift); }
.lb-close:hover, .lb-nav:hover .lb-arrow { background: color-mix(in srgb, var(--panel) 92%, transparent); }
.lb-close svg, .lb-arrow svg { display: block; }
.tile-add, .lb-buy:not(.in-cart) { -webkit-backdrop-filter: blur(12px) saturate(1.6); backdrop-filter: blur(12px) saturate(1.6); box-shadow: var(--glass-ink-edge); }
/* The Cart button floats over the photos as a pane of the page's glass, and settles in when its first photo arrives. */
.cart-fab { border-color: transparent; background: var(--glass-tint-strong); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); box-shadow: var(--glass-edge), var(--glass-lift); }
#cart-open:not([hidden]) { animation: settle var(--t-base) var(--ease-out) backwards; }
/* The Cart and the tip sheet: frosted over a softly blurred page, settling in rather than appearing. */
.offer { border-color: transparent; border-radius: 12px; background: var(--glass-tint-strong); -webkit-backdrop-filter: blur(28px) saturate(1.8); backdrop-filter: blur(28px) saturate(1.8); box-shadow: var(--glass-edge), 0 24px 64px -12px rgb(0 0 0 / .45); }
.offer::backdrop { background: rgb(0 0 0 / .42); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
.offer[open] { animation: settle var(--t-base) var(--ease-out) both; }
