/* Rangefinder Moments · redesign prototype
   Ink on paper, condensed display type, photos at their native ratio. */

:root {
  --ink: #111111;
  --paper: #FFFFFF;
  --muted: #6B6760;
  --light: #B5B1A6;
  --hair: #D9D5C9;
  --well: #EEEDE8;
  --map-bg: #F4F3EF;
  /* Porsche Star Ruby (Rubystone, paint code 82N), matched by eye: the one colour on the site */
  --rubystone: #CB1F6E;
  --gutter: 64px;
  --gap: 24px;
  --font-display: 'Anton', 'Impact', sans-serif;
  --font-body: 'Instrument Sans', system-ui, -apple-system, sans-serif;
  /* The page never gets wider than a 16:9 frame of the screen; on wider screens it
     sits centred. Sizes that used to follow the window width follow this instead. */
  --canvas: min(100vw, calc(100vh * 16 / 9));
}

/* Reversed theme: white type on a black page. The square toggle in the menu bar sets
   <html data-theme="dark">, remembered as rm-theme in localStorage. Photos never change. */
html[data-theme="dark"] {
  --ink: #F2F0EA;
  --paper: #0F0F0F;
  --muted: #9C988E;
  --light: #5E5B55;
  --hair: #34322E;
  --well: #1B1B1A;
  --map-bg: #161616;
  color-scheme: dark;
}
/* A short cross-fade while the theme flips */
html.theme-switching, html.theme-switching * {
  transition: background-color 0.35s ease, color 0.35s ease, border-color 0.35s ease, fill 0.35s ease, stroke 0.35s ease !important;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; touch-action: manipulation; /* no double-tap zoom of the page; pinch still works */ }
/* With the sticky bar on, links to #photos and #map stop below it */
html.sticky-bar { scroll-padding-top: 88px; }
body {
  max-width: calc(100vh * 16 / 9);
  margin: 0 auto;
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
a:hover { color: var(--muted); }
img { display: block; max-width: 100%; height: auto; }
button { font: inherit; cursor: pointer; }

/* --- Small caps label used everywhere --- */
.cap-meta, .meta, .stats, .topbar, .filters button, .place-list, .footer-link {
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-weight: 500;
}
.cap-meta, .meta, .stats { color: var(--muted); }
.cap-title {
  font-family: var(--font-display);
  font-size: 20px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1;
}
.cap-title.big { font-size: 32px; }

/* --- Top bar --- */
/* Solid, and above the masthead: the giant Anton letters have a text box taller than
   their line, which reached up over the menu and swallowed its clicks.
   Sticky bar: OFF for now. Add class="sticky-bar" to <html> to bring back the sticky
   bar, the rule that fades on scroll and the Photos/Map lines; everything is kept. */
.topbar {
  position: relative; z-index: 40;
  background: var(--paper);
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center;
  gap: 16px 32px;
  padding: 26px var(--gutter);
  font-size: 12px;
  border-bottom: 1px solid var(--ink);
  transition: border-color 0.25s ease;
}
html.sticky-bar .topbar { position: sticky; top: 0; }
/* The rule under the bar shows at the top of the page and fades once you scroll */
.topbar.scrolled { border-bottom-color: transparent; }
.topbar-gear { color: var(--muted); }
.topbar-nav { display: flex; flex-wrap: wrap; align-items: center; gap: 32px; }
/* While Photos or Map is in view, the other section link steps back and the active word
   gets a thick Porsche Rubystone line: under "Photos" it fills with how far you are
   through the photos; under "Map" it is simply drawn in full. */
.topbar-nav.has-current a[href^="#"]:not(.is-current) { color: var(--muted); }
.topbar-nav a { position: relative; }
.link-progress {
  position: absolute; left: 0; right: 0; top: calc(100% + 7px); height: 4px;
  background: var(--hair);
  opacity: 0; transition: opacity 0.3s ease;
  pointer-events: none;
}
.topbar-nav a.is-current .link-progress { opacity: 1; }
.link-progress span {
  position: absolute; inset: 0;
  background: var(--rubystone);
  clip-path: inset(0 calc((1 - var(--p, 0)) * 100%) 0 0);
}
/* Theme toggle: a square, half filled; it flips sides in the reversed theme */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; margin: -7px -7px -7px 0; padding: 0;
  border: 0; background: none; color: var(--ink);
}
.theme-toggle:hover { color: var(--muted); }
.theme-toggle svg { display: block; transition: transform 0.35s ease; }
html[data-theme="dark"] .theme-toggle svg { transform: scaleX(-1); }
/* Bar note: what the lock or the theme toggle just did, in a small inverted tag between the
   gear line (or the burger) and the menu, placed by js/app.js; ink ground and paper type, so
   black on the light theme, white on the dark */
.bar-note {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%) scale(0.9);
  background: var(--ink); color: var(--paper);
  padding: 8px 14px; white-space: nowrap;
  font-size: 11px; letter-spacing: 0.2em; text-transform: uppercase; font-weight: 600;
  opacity: 0; pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.bar-note.on { opacity: 1; transform: translate(-50%, -50%) scale(1); }
/* The theme's cross-fade forces colour-only transitions on everything; keep the tag's fade */
html.theme-switching .bar-note { transition: opacity 0.25s ease, transform 0.25s ease, background-color 0.35s ease, color 0.35s ease !important; }

/* Phone menu: a square-cut burger, shown on phones only; it turns into a cross when open */
.menu-toggle {
  display: none; align-items: center; justify-content: center;
  width: 28px; height: 28px; margin: -7px auto -7px -7px; padding: 0;
  border: 0; background: none; color: var(--ink);
}
.menu-toggle svg { display: block; }
.menu-toggle .menu-x { display: none; }
.menu-toggle[aria-expanded="true"] .menu-lines { display: none; }
.menu-toggle[aria-expanded="true"] .menu-x { display: inline; }
.menu-panel {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 39;
  background: var(--paper); color: var(--ink);
  overflow-y: auto; overscroll-behavior: contain;
  padding: 28px var(--gutter) 48px;
}
.menu-panel[hidden] { display: none; }
.menu-main { display: flex; flex-direction: column; gap: 8px; }
.menu-main a { font-family: var(--font-display); font-size: 48px; line-height: 1; text-transform: uppercase; }
.menu-label { margin: 36px 0 4px; font-size: 11px; letter-spacing: 0.2em; text-transform: uppercase; font-weight: 500; color: var(--muted); }
.menu-trips a { display: block; padding: 12px 0; border-bottom: 1px solid var(--ink); font-size: 16px; }
html.menu-open { overflow: hidden; }

/* Locked scrolling: a lock drawn on the same 14-unit square as the theme toggle, so the
   two read the same size; open outline when off, shut and filled when on */
.lock-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; margin: -7px -22px -7px 0; padding: 0;
  border: 0; background: none; color: var(--ink);
}
.lock-toggle:hover { color: var(--muted); }
.lock-toggle svg { display: block; }
.lock-toggle .lock-shut { display: none; }
.lock-toggle[aria-pressed="true"] .lock-open { display: none; }
.lock-toggle[aria-pressed="true"] .lock-shut { display: inline; }
.lock-toggle[aria-pressed="true"] .lock-body { fill: currentColor; }

/* --- Masthead --- */
.masthead {
  padding: 28px var(--gutter) 24px;
  border-bottom: 4px solid var(--ink);
}
.masthead h1 {
  margin: 0;
  font-family: var(--font-display);
  font-size: max(64px, calc(var(--canvas) * 0.176));
  line-height: 0.86;
  letter-spacing: -0.005em;
  text-transform: uppercase;
  display: flex; flex-direction: column;
}
.masthead h1 span:last-child { text-align: right; }

/* Interlock: on wide screens the slogan and stats sit in the space under "Range",
   left of "Moments", and the separate slogan row below is hidden. Narrower screens
   lose that space, so they get the slogan row back. */
.masthead { position: relative; }
.masthead-deck {
  position: absolute; left: var(--gutter); bottom: 34px;
  width: calc((var(--canvas) - 2 * var(--gutter)) * 0.25);
  display: flex; flex-direction: column; gap: 14px;
}
.masthead-deck p { margin: 0; }
.masthead-slogan {
  font-family: var(--font-display);
  font-size: clamp(20px, calc(var(--canvas) * 0.022), 40px);
  line-height: 1; letter-spacing: 0.01em; text-transform: uppercase;
}
.masthead-credit, .slogan-credit { font-size: 11px; letter-spacing: 0.2em; text-transform: uppercase; font-weight: 600; color: var(--ink); }
.masthead-deck .masthead-credit { margin-top: 10px; }
.slogan-credit { font-family: var(--font-body); margin-left: 12px; white-space: nowrap; vertical-align: 0.35em; }
.masthead-stats { font-size: 11px; letter-spacing: 0.2em; text-transform: uppercase; font-weight: 500; color: var(--muted); line-height: 1.7; }
@media (min-width: 1101px) {
  .masthead:has(.masthead-deck) + .slogan-row { display: none; }
}
@media (max-width: 1100px) {
  .masthead-deck { display: none; }
}

/* --- Invert lens: a disc under the mouse over the masthead name (and the opening
   photo while <html> has class="invert-photo"). White with difference turns black to
   white and white to black, in either theme, and turns a photo into its negative.
   The zone isolates and paints its own background, so the disc blends with that zone
   only and is clipped at its edges. js/app.js adds .invert-zone, mouse only. --- */
.invert-zone { isolation: isolate; overflow: hidden; cursor: none; }
.masthead.invert-zone { background: var(--paper); }
.invert-zone button { cursor: pointer; }
.invert-lens {
  position: absolute; left: 0; top: 0;
  border-radius: 50%;
  background: #fff;
  mix-blend-mode: difference;
  pointer-events: none;
  transform: scale(0);
  will-change: transform;
}

.slogan-row {
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline;
  gap: 12px 32px;
  padding: 18px var(--gutter);
  border-bottom: 1px solid var(--ink);
}
.slogan {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(26px, calc(var(--canvas) * 0.03), 44px);
  line-height: 1;
  letter-spacing: 0.01em;
  text-transform: uppercase;
}
.stats { margin: 0; }

/* --- Carousel --- */
.carousel { padding: 40px var(--gutter) 0; }
.carousel-stage {
  position: relative;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: var(--well);
}
.carousel-stage img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.7s ease;
}
.carousel-stage img.active { opacity: 1; }
.carousel-ui {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: 16px;
  padding: 24px;
}
.carousel-caption {
  background: var(--paper);
  padding: 14px 18px;
  display: flex; flex-direction: column; gap: 4px;
}
.carousel-caption .cap-title { font-size: 24px; }
.carousel-btns { display: flex; gap: 8px; }
.carousel-btn {
  width: 52px; height: 52px;
  border: 1px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  display: flex; align-items: center; justify-content: center;
  padding: 0;
}
.carousel-btn:hover { background: var(--ink); color: var(--paper); }
.carousel-foot {
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center;
  gap: 12px;
  padding-top: 16px;
}
.dots { display: flex; gap: 8px; align-items: center; }
.dots button {
  width: 44px; height: 4px;
  border: 0; padding: 0;
  background: var(--hair);
  display: block;
}
.dots button.active { background: var(--ink); }

/* --- Section heads --- */
.section-head {
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: 24px;
  border-bottom: 4px solid var(--ink);
  padding-bottom: 16px;
}
.section-head h2 {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(64px, calc(var(--canvas) * 0.089), 128px);
  line-height: 0.86;
  text-transform: uppercase;
}
.section-head .meta { margin: 0 0 8px; }

/* --- Photos --- */
.photos { padding: 112px var(--gutter) 0; }
.filters { display: flex; flex-wrap: wrap; gap: 12px; padding-bottom: 8px; }
.filters button {
  background: none;
  color: var(--ink);
  border: 1px solid var(--ink);
  padding: 10px 16px;
}
.filters button.active { background: var(--ink); color: var(--paper); }

.group { display: flex; flex-direction: column; gap: 48px; margin-top: 96px; }
.group-head {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: 12px 24px;
  border-bottom: 2px solid var(--ink);
  padding-bottom: 12px;
}
.group-head h3 {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(36px, calc(var(--canvas) * 0.044), 64px);
  line-height: 0.9;
  text-transform: uppercase;
}

.module { display: flex; flex-direction: column; gap: 14px; }
.row { display: grid; gap: var(--gap); align-items: start; }
.row.row-end { align-items: end; }
.row img { width: 100%; height: auto; }
.row a { display: block; }
.stack { display: flex; flex-direction: column; gap: var(--gap); }
.caps {
  display: grid; gap: var(--gap);
  border-top: 1px solid var(--ink);
  padding-top: 12px;
  align-items: start;
}
.cap { display: flex; flex-direction: column; gap: 4px; }
.cap-list { display: flex; flex-direction: column; gap: 8px; }
.cap-list .cap-meta { color: var(--ink); }
.cap-list .cap-meta span { color: var(--muted); }

.textblock {
  display: flex; flex-direction: column; gap: 16px;
  padding: 0 12px 24px;
}
.textblock p {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(28px, calc(var(--canvas) * 0.033), 48px);
  line-height: 0.95;
  letter-spacing: 0.01em;
  text-transform: uppercase;
}
.textblock .cap-meta { line-height: 1.8; }

.group-foot {
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center;
  gap: 24px;
  border-top: 4px solid var(--ink);
  margin-top: 96px;
  padding-top: 32px;
}
.group-foot .also {
  font-family: var(--font-display);
  font-size: clamp(20px, calc(var(--canvas) * 0.02), 28px);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1.2;
}
.btn-outline {
  font-family: var(--font-display);
  font-size: 22px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 16px 32px;
  border: 2px solid var(--ink);
  background: none;
  color: var(--ink);
}
.btn-outline:hover { background: var(--ink); color: var(--paper); }

/* Flat view for category filters: every row shares one height, no cropping */
.flat { display: flex; flex-wrap: wrap; gap: var(--gap); align-items: flex-start; margin-top: 48px; }
.flat figure { margin: 0; min-width: 0; display: flex; flex-direction: column; }
.flat figcaption {
  height: 40px; margin-top: 10px;
  border-top: 1px solid var(--ink);
  display: flex; align-items: center; gap: 10px;
  white-space: nowrap; overflow: hidden;
}
.flat figcaption .cap-title { font-size: 16px; overflow: hidden; text-overflow: ellipsis; }
.flat figcaption .cap-meta { overflow: hidden; text-overflow: ellipsis; }
.flat .spacer { flex-grow: 100000; flex-basis: 0; height: 0; }

/* --- Horizontal strips, one per trip (strip.html) --- */
:root { --strip-h: min(74vh, 1000px); }
.photos-strip { padding-right: 0; }
.photos-strip .section-head,
.photos-strip .group-head { margin-right: var(--gutter); }
.group-strip { gap: 0; }
.group-strip .group-head { align-items: center; }
.group-head-right { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }
.strip-arrow { width: 44px; height: 44px; }
/* No scroll snapping: it pulled every wheel or drag step back to the start. The strip
   stops at a white right margin as wide as the left one; the margin holds the spine. */
.strip {
  display: flex; align-items: flex-start;
  gap: 24px;
  overflow-x: auto; overflow-y: hidden;
  margin-right: var(--gutter);
  padding: 32px 0 8px 0;
  scrollbar-width: none;
  outline: none;
  cursor: grab;
}
.strip.dragging { cursor: grabbing; }
.strip::-webkit-scrollbar { display: none; }
.strip > * { flex: 0 0 auto; }
.strip-fig { margin: 0; display: flex; flex-direction: column; }
.strip-fig a { display: block; height: var(--strip-h); }
.strip-fig img { height: var(--strip-h); width: auto; max-width: none; }
.strip-fig figcaption {
  height: 44px; margin-top: 10px;
  border-top: 1px solid var(--ink);
  display: flex; align-items: center; gap: 12px;
  white-space: nowrap;
}
.strip-fig figcaption .cap-title { font-size: 18px; }
.strip-head {
  width: calc(var(--canvas) * 0.22); min-width: 260px;
  height: var(--strip-h);
  display: flex; flex-direction: column; justify-content: flex-end; gap: 16px;
  border-left: 4px solid var(--ink);
  padding-left: 24px;
  margin-right: 8px;
}
.strip-head h3 {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(40px, calc(var(--canvas) * 0.052), 84px);
  line-height: 0.88;
  text-transform: uppercase;
}
.strip-btns { display: flex; gap: 8px; }

/* Margin spines: 'More · trip' up the right margin, 'Back' in the left one once moved */
.strip-wrap { position: relative; }
.strip-spine {
  position: absolute; top: 32px; height: var(--strip-h); width: var(--gutter);
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 16px;
  background: none; border: 0; padding: 0; color: var(--ink);
  transition: opacity 0.3s ease;
}
.strip-spine.next { right: 0; }
.strip-spine.prev { left: calc(-1 * var(--gutter)); }
.strip-spine.off { opacity: 0; pointer-events: none; }
.strip-spine .t {
  writing-mode: vertical-rl; transform: rotate(180deg);
  white-space: nowrap;
  font-size: 10px; letter-spacing: 0.24em; text-transform: uppercase; font-weight: 600;
}
.strip-spine .t em { font-style: normal; color: var(--muted); font-weight: 500; }
.strip-spine svg { transition: transform 0.25s ease; }
.strip-spine.next:hover svg { transform: translateX(4px); }
.strip-spine.prev:hover svg, .strip-spine.next.at-end:hover svg { transform: translateX(-4px); }
@media (max-width: 760px) {
  .strip-spine .t { letter-spacing: 0.16em; }
  .strip-spine svg { width: 18px; height: 18px; }
}

/* --- Locked scrolling (the lock in the menu bar): each strip pins in the middle of the
   screen and scrolling down moves it sideways. js/app.js sets the heights. The strip is
   a little shorter so the whole pinned block fits on screen. --- */
html.scroll-lock { --strip-h: min(74vh, calc(100vh - 250px), 1000px); }
@media (max-width: 760px) { html.scroll-lock { --strip-h: min(58vh, calc(100vh - 250px)); } }
html.scroll-lock .strip { overflow-x: hidden; cursor: default; }
.lock-pin { position: sticky; display: flex; flex-direction: column; }
.group-strip.lock-on .group-head { position: relative; border-bottom-color: var(--hair); }
.lock-fill {
  display: none;
  position: absolute; left: 0; right: 0; bottom: -2px; height: 2px;
  background: var(--ink);
  transform: scaleX(0); transform-origin: left;
}
.group-strip.lock-on .lock-fill { display: block; }

/* --- Composed strips: feature frames with a headline, stacked pairs with spines, a quote in the gaps --- */
.strip-composed { align-items: flex-start; }
.strip-composed .strip-fig { --h: var(--strip-h); }
.strip-composed .strip-fig.size-half { --h: calc((var(--strip-h) - var(--gap)) / 2); }
.strip-composed .strip-fig.size-medium { --h: calc(var(--strip-h) * 0.64); }
.strip-composed .strip-fig a { height: var(--h); }
.strip-composed .strip-fig img { height: var(--h); width: auto; max-width: none; }
.strip-composed .stack { display: flex; flex-direction: column; gap: var(--gap); flex: 0 0 auto; }
.strip-composed .stack-row { display: flex; gap: var(--gap); align-items: stretch; }

/* A landscape frame stacked with a pair: the pair sets the width, and the landscape is
   trimmed equally at both sides to end where the pair ends. Never stretched; the viewer
   still opens the whole photograph. */
.strip-composed .strip-fig.fit-row { width: 0; min-width: 100%; }
.strip-composed .strip-fig.fit-row .cap-side { flex: none; }
.strip-composed .strip-fig.fit-row a { flex: 0 1 auto; min-width: 0; }
.strip-composed .strip-fig.fit-row img { max-width: 100%; object-fit: cover; }

.strip-composed .strip-fig.cap-e { flex-direction: row; align-items: flex-start; gap: 12px; }
.strip-composed .cap-side {
  display: flex; align-items: flex-start; gap: 10px;
  height: var(--h);
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  white-space: nowrap;
  overflow: hidden;
}
.strip-composed .cap-side .t { font-family: var(--font-display); font-size: 18px; line-height: 1; text-transform: uppercase; letter-spacing: 0.04em; }
.strip-composed .size-medium .cap-side .t { font-size: 24px; }
.strip-composed .cap-side .m { font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--muted); font-weight: 500; padding-top: 3px; }

.strip-composed .strip-fig.cap-h { flex-direction: column; }
.strip-composed .cap-head {
  display: flex; flex-direction: column; gap: 6px;
  width: 0; min-width: 100%;
  margin-top: 12px;
  border-top: 3px solid var(--ink);
  padding-top: 10px;
}
.strip-composed .cap-head .t { font-family: var(--font-display); font-size: 40px; line-height: 0.95; text-transform: uppercase; letter-spacing: 0.01em; }
.strip-composed .cap-head .m { font-size: 11px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--muted); font-weight: 500; }

/* Typographic tiles: frame-shaped, black, the quote set like a poster */
.strip-composed .tile {
  height: var(--h);
  box-sizing: border-box;
  background: var(--ink);
  color: var(--paper);
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: 7%;
  container-type: inline-size;
}
.strip-composed .tile.tile-p { aspect-ratio: 2 / 3; }
.strip-composed .tile.tile-l { aspect-ratio: 3 / 2; }
.strip-composed .tile p {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(16px, 9cqw, 48px);
  line-height: 1.02;
  letter-spacing: 0.01em;
  text-transform: uppercase;
}
.strip-composed .tile.tile-l p { font-size: clamp(16px, 6cqw, 48px); }

@media (max-width: 760px) {
  :root { --strip-h: 58vh; }
  .strip-head { width: calc(var(--canvas) * 0.7); min-width: 0; }
  .strip-composed .cap-head .t { font-size: 26px; }
}

/* --- Hover: a slow zoom inside the frame; tiles flip to paper --- */
.strip-fig a, .row a, .flat a { display: block; overflow: hidden; }
.strip-fig img, .row img, .flat img {
  transform-origin: 50% 50%;
  transition: transform 1.1s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.strip-fig a:hover img, .strip-fig a:focus-visible img,
.row a:hover img, .row a:focus-visible img,
.flat a:hover img, .flat a:focus-visible img { transform: scale(1.05); }
.strip-composed .tile { transition: background-color 0.45s ease, color 0.45s ease, box-shadow 0.45s ease; }
.strip-composed .tile-fig:hover .tile { background: var(--paper); color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
/* Entrance: frames rise in as they come into view (page scroll and sideways scroll alike) */
.strip-fig, .row > *, .flat figure {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.7s ease, transform 0.9s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.strip-fig.is-in, .row > .is-in, .flat figure.is-in { opacity: 1; transform: none; }

/* Focus: while one frame is hovered, the others in its strip or row fall back */
@media (hover: hover) {
  .strip:has(.strip-fig:hover) .strip-fig.is-in:not(:hover) { opacity: 0.4; }
  .row:has(a:hover) > .is-in:not(:hover) { opacity: 0.4; }
  .flat:has(a:hover) figure.is-in:not(:hover) { opacity: 0.4; }
}

/* Cursor: a small badge trails the pointer over photographs */
.cursor-badge {
  position: fixed; left: 0; top: 0; z-index: 60;
  width: 64px; height: 64px; border-radius: 50%;
  background: var(--ink); color: var(--paper);
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; letter-spacing: 0.22em; text-transform: uppercase; font-weight: 600;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.5);
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.cursor-badge.on { opacity: 1; transform: translate(-50%, -50%) scale(1); }
@media (hover: hover) and (pointer: fine) {
  body.badge-active a.glightbox { cursor: none; }
}

@media (prefers-reduced-motion: reduce) {
  .strip-fig img, .row img, .flat img, .strip-composed .tile { transition: none; }
  .strip-fig a:hover img, .row a:hover img, .flat a:hover img { transform: none; }
  .strip-fig, .row > *, .flat figure { opacity: 1; transform: none; transition: none; }
  .cursor-badge { display: none; }
}

/* --- Viewer: the clicked frame grows into full screen --- */
.viewer { position: fixed; inset: 0; z-index: 100; display: none; touch-action: none; }
.viewer.visible { display: block; }
.viewer-backdrop { position: absolute; inset: 0; background: var(--paper); opacity: 0; transition: opacity 0.5s ease; }
.viewer.open .viewer-backdrop { opacity: 1; }
.viewer-img {
  position: fixed; display: block;
  max-width: none; /* zoomed originals are wider than the screen; never squeeze or crop them */
  transform-origin: 0 0; /* a pinch in progress scales from the corner; js/app.js keeps the point under the fingers */
  object-fit: cover;
  transition: left 0.55s cubic-bezier(0.2, 0.7, 0.2, 1), top 0.55s cubic-bezier(0.2, 0.7, 0.2, 1),
              width 0.55s cubic-bezier(0.2, 0.7, 0.2, 1), height 0.55s cubic-bezier(0.2, 0.7, 0.2, 1),
              opacity 0.22s ease, transform 0.26s cubic-bezier(0.2, 0.7, 0.2, 1), filter 0.4s ease;
}
/* Title under the photo, aligned to its left edge, kept quiet */
/* Big title on the left, as tall as the two small rows beside it */
.viewer-cap {
  position: fixed;
  display: flex; flex-direction: row; align-items: center; gap: 28px;
  width: max-content; max-width: calc(100vw - 144px);
  border-top: 1px solid var(--ink);
  padding-top: 12px;
  opacity: 0; transform: translateY(10px);
  transition: opacity 0.4s ease, transform 0.4s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.viewer.ready .viewer-cap { opacity: 1; transform: none; }
/* While a photo is pinched bigger, its caption steps out of the way */
.viewer.touch-zoomed .viewer-cap { opacity: 0; }
.viewer-cap .t {
  font-family: var(--font-display);
  font-size: 46px;
  line-height: 38px;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  white-space: nowrap;
}
.viewer-cap .rows { display: flex; flex-direction: column; justify-content: center; gap: 2px; height: 38px; }
.viewer-cap .m { font-size: 11px; line-height: 18px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--muted); font-weight: 500; white-space: nowrap; }
.viewer-cap .x { font-size: 11px; line-height: 18px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--ink); font-weight: 500; white-space: nowrap; }
/* Beside a portrait frame the same block stacks: title above, the two rows below, bottom-aligned to the photo */
.viewer-cap.side { flex-direction: column; align-items: flex-start; gap: 10px; max-width: min(460px, calc(100vw - 144px)); }
.viewer-cap.side .t { white-space: normal; font-size: 40px; line-height: 0.95; }
.viewer-cap.side .rows { height: auto; }
.viewer-cap.side .m, .viewer-cap.side .x { white-space: normal; line-height: 1.5; }
.viewer-spine { display: none; }
/* Desktop zoom: click the open photo to see the original up close, move to pan, click to fit */
@media (hover: hover) and (pointer: fine) {
  .viewer.ready .viewer-img { cursor: zoom-in; }
  .viewer.zoomed .viewer-img { cursor: zoom-out; }
}
.viewer.ready.zoomed .viewer-cap, .viewer.ready.zoomed .viewer-btn { opacity: 0; pointer-events: none; }
.viewer.panning .viewer-img { transition: opacity 0.22s ease, filter 0.4s ease; }
/* Zoomed in before the original arrives: soft, with a small label until it sharpens */
.viewer.zoomed.loading-full .viewer-img,
.viewer.touch-zoomed.loading-full .viewer-img { filter: blur(5px); }
/* While zoomed in before the original has arrived: a tile in the middle of the screen
   with the theme toggle's half-filled square turning in it */
.viewer-loading {
  position: fixed; left: 50%; top: 50%; z-index: 3;
  width: 64px; height: 64px; margin: -32px 0 0 -32px;
  display: flex; align-items: center; justify-content: center;
  background: var(--paper); color: var(--ink); border: 1px solid var(--ink);
  opacity: 0; pointer-events: none; transition: opacity 0.25s ease;
}
.viewer-loading i {
  width: 22px; height: 22px;
  border: 1.5px solid currentColor;
  background: linear-gradient(90deg, currentColor 50%, transparent 50%);
  animation: viewer-spin 1.1s linear infinite;
}
@keyframes viewer-spin { to { transform: rotate(360deg); } }
.viewer.zoomed.loading-full .viewer-loading,
.viewer.touch-zoomed.loading-full .viewer-loading { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .viewer-loading i { animation: none; } }
/* Touch screens: a pinch hint in the middle of the photo when the viewer opens (js/app.js
   places it); the tile flashes three times while two fingertips spread toward frame-line corners */
.viewer-hint {
  position: fixed; left: 50%; top: 50%; z-index: 3;
  width: 76px; height: 76px; margin: -38px 0 0 -38px;
  display: flex; align-items: center; justify-content: center;
  background: var(--paper); color: var(--ink); border: 1px solid var(--ink);
  opacity: 0; pointer-events: none; transition: opacity 0.3s ease;
}
.viewer-hint svg { display: block; overflow: visible; }
.viewer.hint .viewer-hint { opacity: 1; animation: hint-flash 1.4s ease-in-out 3; }
.viewer-hint .f1 { animation: hint-spread-a 1.4s ease-in-out infinite; }
.viewer-hint .f2 { animation: hint-spread-b 1.4s ease-in-out infinite; }
@keyframes hint-flash { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
@keyframes hint-spread-a { 0%, 15% { transform: translate(3px, 3px); } 65%, 100% { transform: translate(-4px, -4px); } }
@keyframes hint-spread-b { 0%, 15% { transform: translate(-3px, -3px); } 65%, 100% { transform: translate(4px, 4px); } }
@media (prefers-reduced-motion: reduce) {
  .viewer.hint .viewer-hint, .viewer-hint .f1, .viewer-hint .f2 { animation: none; }
}
.viewer-btn {
  position: fixed; z-index: 2;
  width: 52px; height: 52px; padding: 0;
  border: 1px solid var(--ink); background: var(--paper); color: var(--ink);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  opacity: 0; transition: opacity 0.35s ease, background-color 0.2s, color 0.2s;
}
.viewer.ready .viewer-btn { opacity: 1; }
.viewer-btn:hover { background: var(--ink); color: var(--paper); }
.viewer-close { top: 20px; right: 20px; }
.viewer-prev { left: 20px; top: 50%; margin-top: -26px; }
.viewer-next { right: 20px; top: 50%; margin-top: -26px; }
/* Arrows under the caption, at the photo's edges (js/app.js places them) when the photo leaves
   no room beside it, as on a tablet held upright */
.viewer.arrows-below .viewer-prev, .viewer.arrows-below .viewer-next { right: auto; margin-top: 0; }
html.viewer-open { overflow: hidden; }
html.viewer-open .cursor-badge { display: none; }
html.viewer-open body.badge-active a.glightbox { cursor: auto; }
@media (max-width: 760px) {
  .viewer-cap { max-width: calc(100vw - 32px); flex-direction: column; align-items: flex-start; gap: 8px; }
  .viewer-cap .t { font-size: 24px; line-height: 1; white-space: normal; }
  .viewer-cap .rows { height: auto; }
  .viewer-cap .m, .viewer-cap .x { white-space: normal; line-height: 1.5; }
  .viewer-spine { display: none; }
  .viewer-prev, .viewer-next { display: none; }
  .viewer-close { top: 12px; right: 12px; width: 44px; height: 44px; }
}
@media (prefers-reduced-motion: reduce) {
  .viewer-img, .viewer-backdrop, .viewer-cap, .viewer-spine, .viewer-btn { transition: none; }
}

/* --- Trips --- */
.trips { padding: 112px var(--gutter) 0; }
/* Its own stacking context: Leaflet's panes use z-index 400+, which otherwise drew the
   map over the sticky top bar. */
#trip-map {
  position: relative; z-index: 0;
  height: 640px;
  margin-top: 32px;
  border: 1px solid var(--ink);
  background: var(--map-bg);
}
.leaflet-container { font-family: var(--font-body); }
.leaflet-popup-content-wrapper { border-radius: 0; box-shadow: none; border: 1px solid var(--ink); background: var(--paper); color: var(--ink); }
/* Markers and controls follow the theme; the map tiles are inverted in the reversed theme */
#trip-map path.leaflet-interactive { stroke: var(--paper); fill: var(--ink); }
#trip-map .leaflet-bar a { background: var(--paper); color: var(--ink); border-bottom-color: var(--hair); }
html[data-theme="dark"] #trip-map .leaflet-tile-pane { filter: invert(1) hue-rotate(180deg) brightness(0.92); }
html[data-theme="dark"] #trip-map .leaflet-control-attribution { background: rgba(15, 15, 15, 0.8); color: var(--muted); }
html[data-theme="dark"] #trip-map .leaflet-control-attribution a { color: var(--ink); }
.leaflet-popup-tip { display: none; }
.leaflet-popup-content { margin: 14px 16px; }
.map-popup h3 { margin: 0 0 8px; font-family: var(--font-display); font-size: 20px; text-transform: uppercase; letter-spacing: 0.02em; }
.map-popup-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.map-popup-grid a { display: block; }
.map-popup-grid img { width: 100%; aspect-ratio: 1; object-fit: cover; }
.map-popup .cap-meta { display: block; margin-top: 8px; }
.place-list {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0 40px;
  margin-top: 32px;
  font-size: 14px;
  letter-spacing: 0; text-transform: none; font-weight: 400;
}
.place-list a {
  display: flex; justify-content: space-between; gap: 12px;
  border-bottom: 1px solid var(--ink);
  padding: 10px 0;
}
.place-list a span:last-child { color: var(--muted); }

/* --- Footer --- */
.footer {
  margin: 96px var(--gutter) 0;
  padding: 28px 0 48px;
  border-top: 4px solid var(--ink);
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center;
  gap: 16px 32px;
}
.footer-brand {
  font-family: var(--font-display);
  font-size: 22px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* --- Responsive --- */
@media (max-width: 1024px) {
  :root { --gutter: 32px; }
  .place-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  :root { --gutter: 20px; --gap: 16px; }
  .row, .caps { grid-template-columns: minmax(0, 1fr) !important; }
  .row.row-end { align-items: start; }
  .caps > .cap:empty, .caps > div:empty { display: none; }
  .textblock { padding: 0; }
  .carousel-ui { padding: 12px; }
  .carousel-caption .cap-title { font-size: 18px; }
  #trip-map { height: 340px; }
  .section-head .meta { margin: 0; }
  .filters { gap: 8px; }
  .filters button { padding: 8px 12px; }
}

/* --- Phones: the strips and the opening photo run edge to edge, the trip header is one
   row (the title, fitted by js/app.js, and its arrows), and the gear line, the trip's
   place line, the margin spines and the carousel caption (all of .carousel-ui) go. The header arrows show that
   a strip moves sideways. --- */
@media (max-width: 760px) {
  .topbar-gear { display: none; }
  /* The bar stays at the top; its links move into the burger menu at the far left */
  html { scroll-padding-top: 56px; }
  .topbar { position: sticky; top: 0; padding-top: 16px; padding-bottom: 16px; flex-wrap: nowrap; }
  .menu-toggle { display: inline-flex; }
  .topbar-nav > a { display: none; }
  /* Opening carousel: the arrows sit under the photo at the right (js/app.js moves them);
     at the left the dots, and under them the place without the "Shutter Artefacts" label */
  .carousel-ui { display: none; }
  .carousel-foot {
    display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 10px 12px;
    grid-template-areas: "dots btns" "pos btns";
  }
  .carousel-foot .dots { grid-area: dots; }
  #carousel-pos { grid-area: pos; }
  #carousel-pos .pos-label { display: none; }
  .carousel-foot .carousel-btns { grid-area: btns; display: flex; gap: 8px; }
  .carousel-foot .dots button { width: 28px; }
  .carousel-foot .carousel-btn { width: 44px; height: 44px; }
  .carousel { padding-left: 0; padding-right: 0; }
  .carousel-foot { padding-left: var(--gutter); padding-right: var(--gutter); }
  .photos-strip { padding-left: 0; }
  .photos-strip .section-head,
  .photos-strip .group-head { margin-left: var(--gutter); margin-right: var(--gutter); }
  .strip { margin-right: 0; padding-left: var(--gutter); padding-right: var(--gutter); scroll-padding-inline: var(--gutter); gap: var(--gap); }
  .strip-spine { display: none; }
  .group-strip .group-head { flex-wrap: nowrap; gap: 12px; }
  .group-strip .group-head h3 { white-space: nowrap; min-width: 0; font-size: var(--trip-title-fs, 36px); }
  .group-strip .group-head-right { flex: none; }
  .group-strip .group-head-right .cap-meta { display: none; }
  .strip-arrow { width: 40px; height: 40px; }
}
