/*
 * home.css
 *
 * The homepage's styles (lifted out of mike.php's inline <style>). The
 * /letterboxd, /hardcover, /instagram and /strava archives load it too, for
 * the blurred hero background and the card/meta styles, and override the
 * sizes in their own <style>.
 */

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

html { background: #000; color: #fff; -webkit-font-smoothing: antialiased; }

body { min-height: 100vh; min-height: 100dvh; overflow-x: hidden; }

/* ─── HERO BG (fixed — never moves) ─────────────────────────────── */
.hero-bg {
  position: fixed;
  inset: 0;
  overflow: hidden;
  background: #000;
  z-index: 0;
}

#scene {
  position: absolute;
  inset: 0;
}

/* ── Portrait depth-of-field stack ── */
.layer {
  position: absolute;
  inset: 0;
  background-image: url('/source/images/users/mike-color.jpg');
  background-size: cover;
  background-position: center 0;
  background-repeat: no-repeat;
}

/* BG: deep, soft, atmospheric — what's behind the subject */
#layer-bg {
  filter: blur(calc(18px + var(--scroll-blur, 0px))) saturate(1.4) brightness(0.58);
  transform: scale(1.12);
}

/* MID: the subject — isolated by the real depth map (white=near).
   Sharp at rest, blurs as we scroll. */
#layer-mid {
  filter: blur(var(--scroll-blur, 0px));
  -webkit-mask-image: url('/source/images/users/mike-depth.png');
  -webkit-mask-size: cover;
  -webkit-mask-position: center 0;
  -webkit-mask-repeat: no-repeat;
  mask-image: url('/source/images/users/mike-depth.png');
  mask-size: cover;
  mask-position: center 0;
  mask-repeat: no-repeat;
}

/* ── Overlays (live with the fixed hero) ── */
.vignette {
  position: absolute;
  inset: 0;
  background: radial-gradient(
    ellipse 100% 100% at 50% 50%,
    transparent 0%, transparent 26%,
    rgba(0,0,0,0.32) 56%, rgba(0,0,0,0.7) 100%
  );
  pointer-events: none;
}

.bottom-fade {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  height: 52%;
  background: linear-gradient(to bottom, transparent, rgba(0,0,0,0.88));
  pointer-events: none;
}

/* ─── HERO FOREGROUND (in flow — scrolls up naturally) ──────────── */
.hero-foreground {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  min-height: 100svh;
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  pointer-events: none;
}

.hero-text {
  padding: 0 clamp(32px, 5.5vw, 88px) calc(clamp(44px, 7vh, 88px) + env(safe-area-inset-bottom, 0px));
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* text-shadow: 0 10px 20px rgba(0,0,0,0.8); */
}

@media (max-width: 560px) {
  .hero-text {
    align-items: center;
    text-align: center;
    padding-left: 24px;
    padding-right: 24px;
  }
}

.hero-name {
  font-family: 'Barlow', system-ui, -apple-system, sans-serif;
  font-size: clamp(3rem, 8.5vw, 8rem);
  font-weight: 600;
  line-height: 0.95;
  letter-spacing: -0.04em;
  color: #fff;
  text-rendering: optimizeLegibility;
  opacity: 0;
  transform: translateY(30px);
  animation: heroIn 1.15s cubic-bezier(0.16, 1, 0.3, 1) 0.2s forwards;
}

.hero-tagline {
  margin-top: 18px;
  font-family: 'Outfit', system-ui, -apple-system, sans-serif;
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.35;
  color: rgba(255,255,255,0.85);
  opacity: 0;
  transform: translateY(18px);
  animation: heroIn 1.15s cubic-bezier(0.16, 1, 0.3, 1) 0.48s forwards;
}

@keyframes heroIn {
  to { opacity: 1; transform: translateY(0); }
}

/* ── Scroll indicator (sits at bottom of hero foreground) ── */
.scroll-indicator {
  position: absolute;
  bottom: calc(clamp(20px, 3.5vh, 38px) + env(safe-area-inset-bottom, 0px));
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  opacity: 0;
  animation: fadeIn 1s ease 1.7s forwards;
  pointer-events: none;
}

.scroll-label {
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-size: 0.78rem;
  font-weight: 400;
  letter-spacing: -0.005em;
  color: rgba(255,255,255,0.55);
}

.scroll-line {
  width: 1px;
  height: 38px;
  background: rgba(255,255,255,0.1);
  position: relative;
  overflow: hidden;
}

.scroll-line::after {
  content: '';
  position: absolute;
  top: -100%;
  left: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(to bottom, transparent, rgba(255,255,255,0.6), transparent);
  animation: lineDrop 2.4s cubic-bezier(0.4, 0, 0.6, 1) 1.7s infinite;
}

@keyframes lineDrop {
  0%   { top: -100%; opacity: 0; }
  15%  { opacity: 1; }
  85%  { opacity: 1; }
  100% { top: 200%; opacity: 0; }
}

@keyframes fadeIn {
  to { opacity: 1; }
}

/* ── Idle scroll hint (appears after a few seconds of no scrolling) ── */
.scroll-hint {
  position: fixed;
  bottom: calc(clamp(22px, 4vh, 40px) + env(safe-area-inset-bottom, 0px));
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  color: rgba(255,255,255,0.7);
  font-size: 16px;
  opacity: 0;
  pointer-events: none;
  z-index: 10;
  transition: opacity .6s ease;
  text-shadow: 0 2px 10px rgba(0,0,0,0.55);
}
.scroll-hint.is-visible {
  opacity: 1;
  animation: scrollHintBounce 1.8s ease-in-out infinite;
}
@keyframes scrollHintBounce {
  0%, 100% { transform: translate(-50%, 0); }
  50%      { transform: translate(-50%, 8px); }
}

/* ── Animated film grain ── */
.grain {
  position: fixed;
  inset: -50%;
  width: 200%;
  height: 200%;
  z-index: 50;
  pointer-events: none;
  opacity: 0.028;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.88' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 160px 160px;
  animation: grainShift 0.55s steps(2) infinite;
}

@keyframes grainShift {
  0%   { transform: translate(0, 0); }
  25%  { transform: translate(-28px, -38px); }
  50%  { transform: translate(44px, 18px); }
  75%  { transform: translate(-18px, 44px); }
  100% { transform: translate(28px, -28px); }
}

/* ─── Sections (scroll up over fixed hero) ───────────────────── */
.section {
  position: relative;
  z-index: 2;
  width: 100vw;
  /* Was a full 100vh per section (content centered in dead space). Now each
     section is just as tall as its content, with a modest gap to its
     neighbours. Tune the gap with --section-gap. */
  --section-gap: 4vh;
  padding-block: var(--section-gap);
  display: flex;
  flex-direction: column;
  justify-content: center;
  pointer-events: auto;
}

/* Breathing room above the first section. The pull-quote sits between the
   hero and the first section, so match whichever element precedes it. */
.hero-foreground + .section,
.quote-inner + .section {
  padding-top: 20vh;
}

.section-icon {
  display: block;
  font-size: 1.5rem;
  color: #fff;
  margin-bottom: 10px;
  /* text-shadow: 0 2px 14px rgba(0,0,0,0.7), 0 1px 3px rgba(0,0,0,0.55); */
}

/* Section head is a regular flex item inside the scroll row — scrolls with the cards. */
.section-head {
  flex-shrink: 0;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  scroll-snap-align: start;
  width: clamp(180px, 20vw, 280px);
  padding: 0 clamp(20px, 2vw, 36px) 0 clamp(32px, 5.5vw, 88px);
  border-right: 1px solid rgba(255,255,255,0.12);
}

.section-eyebrow {
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.35;
  color: #fff;
  /* text-shadow: 0 2px 14px rgba(0,0,0,0.7), 0 1px 3px rgba(0,0,0,0.55); */
}

.section-eyebrow a,
.section-eyebrow a:visited {
  color: inherit;
  text-decoration: none;
  transition: opacity .2s;
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.section-eyebrow a:hover {
  opacity: 0.75;
}

.section-title {
  margin-top: 10px;
  font-family: 'Barlow', system-ui, -apple-system, sans-serif;
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: -0.005em;
  color: #fff;
  text-shadow: 0 4px 24px rgba(0,0,0,0.65), 0 1px 4px rgba(0,0,0,0.5);
}

/* ── Horizontal poster row ── */
/* overflow-x: auto requires overflow-y to be hidden/auto (spec quirk),
   so we can't make the row's vertical overflow visible. Instead, give
   the row generous top/bottom padding so the poster's drop shadow lives
   inside the clipping box. */
.films-row {
  display: flex;
  align-items: flex-start;
  min-width: 0;
  gap: clamp(32px, 3.5vw, 56px);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-padding-left: 14px;
  padding: 60px 0 110px;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.films-row::-webkit-scrollbar { display: none; }

.film-card {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  scroll-snap-align: start;
  text-decoration: none;
  color: inherit;
}
.film-card:hover .film-poster {
  box-shadow: 0 16px 32px rgba(0,0,0,0.4);
}

/* First card needs only a small gap from the header column. */
.film-card:last-child  { margin-right: 6vw; }

.film-poster {
  height: 50vh;
  aspect-ratio: 2 / 3;
  border-radius: 18px;
  background-size: cover;
  background-position: center;
  background-color: rgba(20,20,30,0.5);
  box-shadow: 0 8px 15px rgba(0,0,0,0.2);
  transition: box-shadow .35s cubic-bezier(.2,.7,.3,1);
}

.film-meta {
  margin-top: 14px;
  max-width: 33vh;
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  /* text-shadow: 0 2px 4px rgba(0,0,0,0.5), 0 1px 3px rgba(0,0,0,0.25); */
}

.film-title-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}

.film-title {
  color: #fff;
  font-weight: 500;
  font-size: 0.95rem;
  letter-spacing: -0.005em;
  line-height: 1.25;
}

.film-badges {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  padding-top: 2px;
  font-size: 0.72rem;
}
.film-badge-heart    { color: #ffffff; }
.film-badge-rewatch  { color: rgba(255,255,255,0.55); }

.film-year {
  margin-top: 3px;
  color: rgba(255,255,255,0.7);
  font-size: 0.78rem;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
}

/* ── Instagram row (mirrors films-row) ── */
.posts-row {
  display: flex;
  align-items: flex-start;
  min-width: 0;
  gap: clamp(32px, 3.5vw, 56px);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-padding-left: 14px;
  padding: 60px 0 110px;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.posts-row::-webkit-scrollbar { display: none; }

.post-card {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  scroll-snap-align: start;
  text-decoration: none;
  color: inherit;
  transition: transform 0.5s cubic-bezier(0.33, 1, 0.68, 1);
}
.post-card:hover .post-image {
  box-shadow: 0 16px 32px rgba(0,0,0,0.4);
}

.post-card:last-child  { margin-right: 6vw; }

.post-image {
  height: 60vh;
  aspect-ratio: 9 / 16;
  border-radius: 18px;
  position: relative;
  background-size: cover;
  background-position: center;
  background-color: rgba(20,20,30,0.5);
  box-shadow: 0 8px 15px rgba(0,0,0,0.2);
  transition: box-shadow .35s cubic-bezier(.2,.7,.3,1);
}

.post-image.is-video {
  position: relative;
  background-color: #000;
  overflow: hidden;
}

.post-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: inherit;
  background: #000;
}

/* Shared play-button styling for Instagram videos and Strava maps */
.post-play,
.ride-play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 68px;
  height: 68px;
  border: 1px solid rgba(255,255,255,0.4);
  border-radius: 50%;
  background: rgba(0,0,0,0.42);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  color: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform .25s cubic-bezier(.2,.7,.3,1), opacity .25s, background .2s;
  box-shadow: 0 14px 36px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.2);
  z-index: 5;
}
.post-play:hover,
.ride-play:hover { transform: translate(-50%, -50%) scale(1.08); background: rgba(0,0,0,0.58); }
.post-play:active,
.ride-play:active { transform: translate(-50%, -50%) scale(0.96); }
.post-play.is-hidden,
.ride-play.is-hidden { opacity: 0; pointer-events: none; transform: translate(-50%, -50%) scale(0.55); }
.post-play .fa-play,
.ride-play .fa-play { font-size: 20px; margin-left: 3px; /* optical centering */ }

/* Meta-as-link styling for video cards and ride cards */
a.post-meta,
a.ride-meta {
  text-decoration: none;
  color: inherit;
  transition: opacity .2s;
}
a.post-meta:hover,
a.ride-meta:hover { opacity: 0.85; }

.post-meta {
  margin-top: 14px;
  max-width: calc(60vh * 9 / 16);
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  /* text-shadow: 0 2px 4px rgba(0,0,0,0.5), 0 1px 3px rgba(0,0,0,0.25); */
}

.post-caption {
  color: #fff;
  font-weight: 500;
  font-size: 0.92rem;
  letter-spacing: -0.005em;
  line-height: 1.35;
}

.post-date {
  margin-top: 3px;
  color: rgba(255,255,255,0.7);
  font-size: 0.78rem;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
}

/* ── Strava row ── */
.rides-row {
  display: flex;
  align-items: flex-start;
  min-width: 0;
  gap: clamp(32px, 3.5vw, 56px);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-padding-left: 14px;
  padding: 60px 0 110px;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.rides-row::-webkit-scrollbar { display: none; }

.ride-card {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  scroll-snap-align: start;
  text-decoration: none;
  color: inherit;
  position: relative;
}

.ride-card:last-child  { margin-right: 6vw; }

.ride-map {
  width: 50vh;
  height: 50vh;
  border-radius: 18px;
  overflow: hidden;
  position: relative;
  background:
    radial-gradient(ellipse at 30% 20%, rgba(70,90,120,0.35) 0%, transparent 55%),
    radial-gradient(ellipse at 70% 80%, rgba(120,80,60,0.25) 0%, transparent 55%),
    linear-gradient(135deg, #1a1f2e 0%, #0a0c14 100%);
  box-shadow: 0 8px 15px rgba(0,0,0,0.2);
  transition: box-shadow .35s cubic-bezier(.2,.7,.3,1);
}

/* Winter rides: snowy placeholder so the load doesn't flash dark before
   the themed (white) tiles arrive. */
.ride-map[data-winter="1"] {
  background:
    radial-gradient(ellipse at 30% 20%, rgba(255,255,255,0.55) 0%, transparent 55%),
    radial-gradient(ellipse at 70% 80%, rgba(180,200,220,0.4) 0%, transparent 55%),
    linear-gradient(135deg, #eef2f6 0%, #c5d2dd 100%);
}

/* Hide the mapbox canvas while the winter theme is being applied to the
   initial tiles. Without this, you see one frame of the default green
   outdoors style before our paint overrides land. */
.ride-map .mapboxgl-canvas-container { transition: opacity .45s ease; }
.ride-map.is-loading .mapboxgl-canvas-container { opacity: 0; }

/* Style mapbox compact attribution to be unobtrusive */
.ride-map .mapboxgl-ctrl-attrib {
  background: rgba(0,0,0,0.5);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border-radius: 8px;
  font-size: 9px;
}
.ride-map .mapboxgl-ctrl-attrib a { color: rgba(255,255,255,0.6); }
.ride-map .mapboxgl-ctrl-bottom-right { right: 6px; bottom: 6px; }

.ride-meta {
  margin-top: 14px;
  max-width: 50vh;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  /* text-shadow: 0 2px 14px rgba(0,0,0,0.7), 0 1px 3px rgba(0,0,0,0.55); */
}

.ride-sport {
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 14px;
  flex-shrink: 0;
}

.ride-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.ride-name {
  color: #fff;
  font-weight: 500;
  font-size: 0.92rem;
  letter-spacing: -0.005em;
  line-height: 1.25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ride-stats {
  display: flex;
  align-items: center;
  gap: 10px 12px;
  flex-wrap: wrap;
  color: rgba(255,255,255,0.78);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.005em;
  font-variant-numeric: tabular-nums;
}

.ride-stat {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
}
.ride-stat i {
  font-size: 0.78rem;
  color: rgba(255,255,255,0.5);
  width: 12px;
  text-align: center;
}
.ride-stat-date { color: rgba(255,255,255,0.55); }

/* Strava playback controls (pause + stop-spin) */
.ride-controls {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 10;
  display: flex;
  gap: 6px;
  opacity: 0;
  transition: opacity 0.35s;
}
.ride-controls.is-visible { opacity: 1; }

.ride-ctrl {
  width: 30px;
  height: 30px;
  border: 1px solid rgba(255,255,255,0.3);
  border-radius: 50%;
  background: rgba(0,0,0,0.48);
  backdrop-filter: blur(10px) saturate(160%);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
  color: rgba(255,255,255,0.9);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  transition: background 0.2s, opacity 0.2s, transform 0.2s;
}
.ride-ctrl:hover { background: rgba(0,0,0,0.68); transform: scale(1.08); }
.ride-ctrl:active { transform: scale(0.92); }
.ride-ctrl.is-inactive { opacity: 0.38; }

/* Strava timeline (progress bar + current time) — floats above the map
   via absolute positioning so it never affects the map's layout */
.ride-timeline {
  position: absolute;
  bottom: 100%;
  left: 0;
  width: 50vh;
  max-width: 50vh;
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding-bottom: 10px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s;
}
.ride-timeline.is-visible { opacity: 1; }
/* Fade out after route finishes — delay so the final time is readable */
.ride-timeline.is-visible.is-done {
  opacity: 0;
  transition: opacity 1.8s 1.2s;
}

.ride-timeline-bar {
  height: 3px;
  background: rgba(255,255,255,0.18);
  border-radius: 2px;
  overflow: hidden;
}
.ride-timeline-fill {
  height: 100%;
  width: 0%;
  background: #fc4c02;
  border-radius: 2px;
  transition: width 0.08s linear;
}
.ride-timeline-time {
  text-align: right;
  color: rgba(255,255,255,0.82);
  font-size: 0.72rem;
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

/* ── Hero journey (flags + dashed planes) ── */
.hero-journey {
  margin-top: 26px;
  display: flex;
  align-items: center;
  gap: 26px;
  filter: drop-shadow(0 2px 4px rgba(0,0,0,0.25));
}
.journey-flag {
  width: 26px;
  height: auto;
  border-radius: 3px;
  /* box-shadow: 0 2px 8px rgba(0,0,0,0.4), inset 0 0 0 0.5px rgba(255,255,255,0.15); */
  display: block;
  opacity: 0;
}
.journey-leg {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  opacity: 0;
}
.journey-dash {
  display: inline-block;
  width: 14px;
  border-top: 1px dashed rgba(255,255,255,0.45);
  flex-shrink: 0;
}
.journey-plane {
  font-size: 11px;
  color: rgba(255,255,255,0.7);
}

@keyframes flagIn {
  from { opacity: 0; transform: scale(0.8); }
  to   { opacity: 1; transform: scale(1); }
}
@keyframes planeIn {
  from { opacity: 0; transform: translateX(-16px); }
  to   { opacity: 1; transform: translateX(0); }
}

/* Stagger: name (~1.35s) → tagline (~1.63s) → ZW → leg1 → ZA → leg2 → GB → leg3 → US */
.journey-flag-1 { animation: flagIn  .45s cubic-bezier(.16,1,.3,1) 1.75s forwards; }
.journey-leg-1  { animation: planeIn .55s cubic-bezier(.16,1,.3,1) 2.10s forwards; }
.journey-flag-2 { animation: flagIn  .45s cubic-bezier(.16,1,.3,1) 2.55s forwards; }
.journey-leg-2  { animation: planeIn .55s cubic-bezier(.16,1,.3,1) 2.85s forwards; }
.journey-flag-3 { animation: flagIn  .45s cubic-bezier(.16,1,.3,1) 3.25s forwards; }
.journey-leg-3  { animation: planeIn .55s cubic-bezier(.16,1,.3,1) 3.55s forwards; }
.journey-flag-4 { animation: flagIn  .45s cubic-bezier(.16,1,.3,1) 3.95s forwards; }

@media (max-width: 560px) {
  .hero-journey { justify-content: center; }
}

/* ── Quote ── */
.quote-inner {
  position: relative;
  z-index: 2;
  max-width: 880px;
  padding: 0 clamp(32px, 5.5vw, 88px);
}
.quote-text {
  font-family: 'Playfair Display', Georgia, serif;
  font-style: italic;
  font-weight: 300;
  font-size: clamp(1.4rem, 3vw, 2.4rem);
  line-height: 1.4;
  letter-spacing: -0.015em;
  color: rgba(255,255,255,0.94);
  /* text-shadow: 0 4px 26px rgba(0,0,0,0.7), 0 1px 4px rgba(0,0,0,0.55); */
}
.quote-text + .quote-text { margin-top: 28px; }
.quote-text a {
  color: inherit;
  text-decoration: none;
  transition: border-color .2s, color .2s;
}
.quote-text a:hover {
  color: #fff;
}
@media (max-width: 560px) {
  .quote-text { text-align: center; }
}

/* ── Side Projects (macOS browser windows) ── */
.projects-row {
  display: flex;
  align-items: flex-start;
  min-width: 0;
  gap: clamp(32px, 3.5vw, 56px);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-padding-left: 14px;
  padding: 60px 0 110px;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.projects-row::-webkit-scrollbar { display: none; }

/* Pull card rows away from the bottom home indicator on iOS */
.films-row, .posts-row, .rides-row, .projects-row {
  padding-bottom: calc(110px + env(safe-area-inset-bottom, 0px));
}

/* ── Progress dots — scroll position + click-to-scroll (built in JS) ──
   Lets mouse users without a horizontal scroll wheel jump between items. */
.section-dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 9px;
  margin-top: -70px;
  padding-bottom: calc(30px + env(safe-area-inset-bottom, 0px));
  position: relative;
  z-index: 6;
}
.section-dot {
  width: 8px;
  height: 8px;
  padding: 0;
  border: none;
  border-radius: 999px;
  background: rgba(255,255,255,0.28);
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition: width .3s cubic-bezier(.2,.7,.3,1), background .3s;
}
.section-dot:hover { background: rgba(255,255,255,0.55); }
.section-dot.is-active {
  width: 26px;
  background: rgba(255,255,255,0.9);
}

.project-card {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  scroll-snap-align: start;
  text-decoration: none;
  color: inherit;
}
.project-card:hover .project-window, .ride-card:hover .ride-map {
  box-shadow: 0 16px 32px rgba(0,0,0,0.4);
}
.project-card:last-child  { margin-right: 6vw; }

/* Shared wrapper (shadow + transition) for both variants */
.project-window {
  height: 50vh;
  overflow: hidden;
  box-shadow: 0 8px 15px rgba(0,0,0,0.2);
  transition: box-shadow .35s cubic-bezier(.2,.7,.3,1);
}

/* Mac browser variant — shown on desktop */
.project-window--mac {
  display: flex;
  flex-direction: column;
  width: calc(50vh * 4 / 3);
  border-radius: 14px;
  background: #1a1a25;
}

/* iPhone variant — shown on mobile (<= 768px) */
.project-window--ios {
  display: none;
  position: relative;
  width: calc(50vh * 9 / 19);
  border-radius: 38px;
  padding: 6px;
  background: #0a0a14;
}

@media (max-width: 768px) {
  .project-window--mac { display: none; }
  .project-window--ios { display: flex; }
}

.ios-screen {
  width: 100%;
  height: 100%;
  border-radius: 32px;
  background-size: cover;
  background-position: top center;
  background-color: #1a1a25;
  position: relative;
  overflow: hidden;
}

/* Dynamic Island — pill near top of screen */
.ios-island {
  position: absolute;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  width: 92px;
  height: 26px;
  background: #000;
  border-radius: 13px;
  z-index: 2;
  box-shadow: inset 0 0 0 0.5px rgba(255,255,255,0.05);
}

/* Home indicator — swipe-up handle at bottom */
.ios-home {
  position: absolute;
  bottom: 12px;
  left: 50%;
  transform: translateX(-50%);
  width: 32%;
  height: 4px;
  background: rgba(255,255,255,0.85);
  border-radius: 2px;
  z-index: 2;
}

.window-chrome {
  height: 38px;
  background: linear-gradient(to bottom, #2c2c38 0%, #1d1d28 100%);
  border-bottom: 1px solid rgba(0,0,0,0.45);
  display: flex;
  align-items: center;
  padding: 0 12px;
  gap: 12px;
  flex-shrink: 0;
}

.window-traffic { display: flex; gap: 8px; flex-shrink: 0; }
.dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 0.5px rgba(0,0,0,0.35);
}
.dot-red    { background: linear-gradient(to bottom, #ff6b62, #de4c45); }
.dot-yellow { background: linear-gradient(to bottom, #ffc742, #de9b1a); }
.dot-green  { background: linear-gradient(to bottom, #34d048, #14a229); }

.window-url {
  flex: 1;
  max-width: 65%;
  margin: 0 auto;
  background: rgba(0,0,0,0.45);
  border-radius: 6px;
  padding: 4px 12px;
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-size: 0.72rem;
  font-weight: 500;
  color: rgba(255,255,255,0.7);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: 0.005em;
}

/* keeps URL pill optically centered against the traffic lights on the left */
.window-spacer { width: 56px; flex-shrink: 0; }

.window-body {
  flex: 1;
  background-size: cover;
  background-position: top center;
  background-repeat: no-repeat;
  background-color: #0a0a14;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/* Slowly pan the full-page screenshot from top to bottom and back. Only
   runs on the card the reader is currently centered on (.is-active),
   set by JS — keeps the page calmer than panning all four at once. */
.project-card.is-active .window-body.has-shot,
.project-card.is-active .ios-screen.has-shot {
  animation: scrollShot 40s ease-in-out infinite;
}
.project-card:hover .window-body.has-shot,
.project-card:hover .ios-screen.has-shot {
  animation-play-state: paused;
}
@keyframes scrollShot {
  0%, 6%   { background-position: 50% 0%; }
  50%, 56% { background-position: 50% 100%; }
  100%     { background-position: 50% 0%; }
}

.window-placeholder {
  text-align: center;
  padding: 28px 24px;
  color: rgba(255,255,255,0.92);
  text-shadow: 0 2px 14px rgba(0,0,0,0.7), 0 1px 3px rgba(0,0,0,0.55);
}
.window-placeholder-name {
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-size: clamp(1.4rem, 2.6vw, 2rem);
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.05;
}
.window-placeholder-blurb {
  margin-top: 10px;
  font-size: 0.85rem;
  font-weight: 400;
  color: rgba(255,255,255,0.65);
  letter-spacing: 0.01em;
  max-width: 32ch;
  margin-left: auto;
  margin-right: auto;
  line-height: 1.45;
}

.project-meta {
  margin-top: 14px;
  max-width: calc(50vh * 4 / 3);
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  /* text-shadow: 0 2px 14px rgba(0,0,0,0.7), 0 1px 3px rgba(0,0,0,0.55); */
}
.project-name {
  color: #fff;
  font-weight: 500;
  font-size: 0.95rem;
  letter-spacing: -0.005em;
}
.project-blurb {
  margin-top: 3px;
  color: rgba(255,255,255,0.65);
  font-size: 0.78rem;
  font-weight: 400;
  letter-spacing: 0.005em;
}

/* Constrain meta to the iPhone width on mobile. Must come after the
   default .project-meta rule above — they share specificity, so the
   later rule wins regardless of media-query state. */
@media (max-width: 768px) {
  .project-meta { max-width: calc(50vh * 9 / 19); }
}

/* ── "See all" — last item in a row, links to that feed's archive page ──
   Sized to the row's media so the label sits level with the poster middle.
   Takes over the end-of-row margin from the last real card. */
.see-all-card {
  flex-shrink: 0;
  align-self: flex-start;
  height: var(--see-all-h, 50vh);
  padding: 0 clamp(16px, 2vw, 32px);
  margin-right: 6vw;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  scroll-snap-align: start;
  text-decoration: none;
  color: #fff;
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: -0.005em;
  text-align: center;
}
.posts-row .see-all-card { --see-all-h: 60vh; }

.see-all-icon {
  width: 56px;
  height: 56px;
  border: 1px solid rgba(255,255,255,0.4);
  border-radius: 50%;
  background: rgba(0,0,0,0.3);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  box-shadow: 0 10px 28px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.2);
  transition: transform .25s cubic-bezier(.2,.7,.3,1), background .2s;
}
.see-all-card:hover .see-all-icon { transform: scale(1.08); background: rgba(0,0,0,0.5); }
.see-all-card:active .see-all-icon { transform: scale(0.96); }

