/* ============================================================
   Tanzania Seven — design system
   Bone paper, serif display, generous air. Photographs lead.
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,300;9..144,400;9..144,600&family=Inter:wght@300;400;500&display=swap');

:root {
  /* Warm off-white, not white. Safari photography — ochre, dust, gold —
     sits badly on pure white, which makes photographs look like product shots. */
  --bone:       #F7F3EC;
  --bone-deep:  #EFE8DC;
  --ink:        #1A1714;
  --ink-soft:   #4A423A;
  --muted:      #857A6D;
  --rule:       rgba(26, 23, 20, .13);
  --ochre:      #A8622A;
  --night:      #14110E;

  --display: 'Fraunces', Georgia, serif;
  --sans:    'Inter', system-ui, -apple-system, sans-serif;

  --gutter: clamp(1.25rem, 5vw, 5rem);
  --measure: 34rem;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bone);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 300;
  font-size: clamp(1rem, .95rem + .2vw, 1.0625rem);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

img, video { display: block; max-width: 100%; }
a { color: inherit; }

/* ---------- masthead ---------- */

.masthead {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem;
  padding: .9rem var(--gutter);
  background: color-mix(in srgb, var(--bone) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color .3s, background .3s;
}
.masthead.is-stuck { border-bottom-color: var(--rule); }

.wordmark {
  font-family: var(--display);
  font-weight: 600;
  font-size: .95rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
}

.masthead nav {
  display: flex; align-items: baseline; gap: clamp(.85rem, 2vw, 1.9rem);
  font-size: .72rem; letter-spacing: .13em; text-transform: uppercase;
}
.masthead nav a { text-decoration: none; color: var(--ink-soft); transition: color .2s; }
.masthead nav a:hover,
.masthead nav a[aria-current="page"] { color: var(--ink); }
.masthead nav a[aria-current="page"] { border-bottom: 1px solid currentColor; padding-bottom: 2px; }

.lang { display: flex; gap: .4rem; color: var(--muted); }
.lang a { text-decoration: none; }
.lang a[aria-current="true"] { color: var(--ink); font-weight: 500; }

/* ---------- hero ---------- */

/* ---------- hero ----------
   Full-bleed photograph with the words floating over it in a glass panel.
   The panel sits LEFT rather than centred: a sunset has its brightest
   values in the middle, and dark text over a blown-out sun is unreadable. */

.hero {
  position: relative;
  display: grid;
  align-items: center;
  min-height: min(74vh, 48rem);
  overflow: hidden;
  border-bottom: 1px solid var(--rule);
}

.hero__image { position: absolute; inset: 0; z-index: 0; }
.hero__image img { width: 100%; height: 100%; object-fit: cover; }

/* A whisper of a scrim. Insurance for legibility without dulling the sky. */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(260deg, rgba(255,255,255,.30) 0%,
                                      rgba(255,255,255,.08) 40%,
                                      rgba(255,255,255,0) 66%);
}

.hero__text {
  position: relative; z-index: 2;
  justify-self: end;   /* clears the boat and the sun, which sit centre-left */
  margin: clamp(.75rem, 1.6vw, 1.5rem) var(--gutter);
  max-width: min(33rem, 90vw);
  display: flex; flex-direction: column; gap: 1.35rem;
  padding: .5rem;
  background: none;
  border: 0;
  box-shadow: none;
}

/* The glass lives on its own layer BEHIND the words.
   backdrop-filter blurs a hard-edged rectangle, so blurred meeting unblurred
   reads as a border even with border:0. Feathering the layer with a mask makes
   it fade out instead. It has to be a separate layer because a mask applies to
   an element's children too — masking the panel itself would fade the text. */
.hero__text::before {
  content: "";
  position: absolute;
  inset: -2.25rem;   /* wider than the padding, so the type keeps a cushion of glass */
  z-index: -1;
  /* Real glass SOFTENS what is behind it — you still read the shapes and
     colours through it. Heavy blur (36px) destroys the photograph and reads
     as fog, not glass. Modest blur plus a lift in saturation and brightness
     keeps the sunset legible through the panel. */
  background: rgba(255, 253, 249, .16);
  -webkit-backdrop-filter: blur(10px) saturate(1.5) brightness(1.08);
  backdrop-filter: blur(10px) saturate(1.5) brightness(1.08);
  -webkit-mask-image: radial-gradient(118% 125% at 50% 50%, #000 48%, rgba(0,0,0,0) 100%);
  mask-image: radial-gradient(118% 125% at 50% 50%, #000 48%, rgba(0,0,0,0) 100%);
}

/* Where backdrop-filter is unsupported, fall back to something opaque
   enough to read rather than a transparent smear. */
@supports not (backdrop-filter: blur(2px)) {
  .hero__text { background: rgba(255, 253, 249, .78); }
}

.hero__eyebrow {
  font-size: .7rem; letter-spacing: .28em; text-transform: uppercase;
  color: var(--ochre);
}
.hero h1 {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(1.9rem, 3.4vw, 3.1rem);
  line-height: 1;
  letter-spacing: -.02em;
  margin: 0;
}
.hero h1 em { font-style: italic; font-weight: 400; }
/* At 20% the glass is barely there, so the type carries legibility itself:
   true black, a touch heavier, with a soft white halo behind it. */
.hero__text, .hero h1, .hero__intro { color: #000; }
.hero__intro { font-size: .93rem; line-height: 1.6; font-weight: 400;
               text-shadow: 0 1px 4px rgba(255,255,255,.9), 0 0 14px rgba(255,255,255,.55); }
.hero h1 { text-shadow: 0 1px 12px rgba(255,255,255,.75), 0 0 30px rgba(255,255,255,.45); }
.hero__intro p { margin: 0 0 .8rem; }
.hero__intro p:last-child { margin-bottom: 0; }
.hero__intro .salutation { font-family: var(--display); font-size: 1.15em; }

/* The sign-off. Last line of the intro, and the one that should land. */
.hero__intro p:last-child,
.hero__intro p:last-child em {
  font-weight: 700;
  color: #000;
  font-style: normal;
  font-size: 1.02rem;
  letter-spacing: .01em;
  margin-top: 1rem;
}

@media (max-width: 700px) {
  .hero { min-height: 82vh; align-items: end; }
  .hero__text { margin-bottom: 2rem; }
  .hero::after {
    background: linear-gradient(180deg, rgba(255,255,255,.12) 0%,
                                        rgba(255,255,255,.30) 100%);
  }
}

/* ---------- the stat line ---------- */

.stats {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: clamp(1.5rem, 5vw, 4.5rem);
  padding: clamp(2rem, 5vw, 3.5rem) var(--gutter);
  text-align: center;
}
.stat__n {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.8rem, 4vw, 3rem); line-height: 1;
  display: block;
}
.stat__l {
  font-size: .68rem; letter-spacing: .18em; text-transform: uppercase;
  color: var(--muted); margin-top: .5rem; display: block;
}

/* ---------- the route ----------
   A white plate on the bone page, caption set beside the map rather than
   under it, so the pair reads as one printed figure. */

.tripmap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(13rem, 19rem);
  gap: 0;
  align-items: center;
  /* Full-bleed: the map spans the screen, edge to edge, like a plate
     bound into the middle of a magazine. */
  max-width: none;
  margin: 0 0 clamp(2rem, 5vw, 4rem);
  padding: 0;
  background: #fff;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.tripmap__plate { min-width: 0; }
/* Serengeti to Zanzibar is nearly as far north–south as it is east–west, so
   the map is naturally tall. Rather than distort real geography, cap the
   height and let the drawing centre itself in the white band. */
.tripmap svg {
  width: 100%;
  height: auto;
  max-height: min(66vh, 640px);
  display: block;
}
.tripmap figcaption {
  font-size: .88rem; line-height: 1.5;
  color: #000; font-weight: 700;
  border-left: 1px solid var(--rule);
  padding: clamp(1rem, 2.5vw, 2rem) clamp(1rem, 2vw, 1.75rem);
}

.tripmap .ocean { fill: #cfe0e8; stroke: none; }
.tripmap .isle  { fill: #b6cfda; stroke: none; }

.tripmap .sea-label {
  fill: #6d8e9d; font-family: var(--sans); font-size: 22px;
  letter-spacing: 7px; text-anchor: middle;
}
.tripmap .land-label {
  fill: #b8ae9e; font-family: var(--sans); font-size: 30px;
  letter-spacing: 11px; text-anchor: middle;
}

.tripmap .route { fill: none; stroke: var(--ochre); stroke-width: 3.5;
                  stroke-linecap: round; stroke-linejoin: round; }
/* Dotted, because it is a flight, not a road. A dotted line cannot ALSO be
   dash-animated — both need stroke-dasharray — so this one fades in while
   the aeroplane travels along it. */
.tripmap .route.flight {
  stroke-width: 2.5;
  stroke-dasharray: 2 12;
  opacity: 0;
}

.tripmap svg.is-drawn .route.drive  { animation: draw 2.6s cubic-bezier(.4,0,.2,1) forwards; }
.tripmap svg.is-drawn .route.flight { animation: fadeline 1.6s ease 2.3s forwards; }
@keyframes draw { to { stroke-dashoffset: 0; } }
@keyframes fadeline { to { opacity: .85; } }

/* The aeroplane follows the flight curve via CSS motion path and turns to
   face its direction of travel. */
.tripmap .plane { opacity: 0; }
.tripmap .plane path { fill: var(--ink); }
.tripmap svg.is-drawn .plane {
  animation: fly 1.6s cubic-bezier(.45,0,.4,1) 2.3s forwards;
}
@keyframes fly {
  0%   { offset-distance: 0%;   opacity: 0; }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { offset-distance: 100%; opacity: 1; }
}

.tripmap .stop circle { fill: #fff; stroke: var(--ink); stroke-width: 2.5; }
.tripmap .stop text { font-family: var(--display); font-size: 21px; fill: var(--ink);
                      dominant-baseline: middle; }

.tripmap svg .stop { opacity: 0; }
.tripmap svg.is-drawn .stop { animation: pop .5s ease forwards;
                              animation-delay: calc(.3s * var(--i)); }
@keyframes pop { to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .tripmap svg .stop { opacity: 1; animation: none; }
  .tripmap svg .route { stroke-dashoffset: 0 !important; animation: none; }
  .tripmap svg .route.flight { opacity: .85; }
  .tripmap svg .plane { opacity: 1; offset-distance: 100%; animation: none; }
}

@media (max-width: 760px) {
  .tripmap { grid-template-columns: 1fr; }
  .tripmap figcaption { border-left: 0; padding-left: 0; border-top: 1px solid var(--rule); padding-top: .9rem; }
  .tripmap .stop text { font-size: 30px; }
}

/* ---------- chapters ---------- */

/* The stat line has equal padding above and below, but the first chapter
   card adds its own top margin underneath — which read as a bigger gap below
   the numbers than above them. Drop it so the spacing is symmetrical. */
#story > .chapter:first-child { margin-top: 0; }

.chapter {
  position: relative;
  min-height: 66vh;
  display: grid; place-items: center;
  overflow: hidden;
  color: #fff;
  text-align: center;
  margin: clamp(3rem, 8vw, 7rem) 0;
}
.chapter__bg { position: absolute; inset: 0; z-index: 0; }
.chapter__bg img { width: 100%; height: 100%; object-fit: cover; }
.chapter::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(180deg, rgba(20,17,14,.10) 0%, rgba(20,17,14,.20) 45%, rgba(20,17,14,.55) 100%);
}
.chapter__inner { position: relative; z-index: 2; padding: 2rem; }
.chapter__num {
  font-family: var(--display);
  font-size: clamp(1rem, 1.6vw, 1.35rem);
  letter-spacing: .42em;
  text-indent: .42em;
  opacity: 1;
  margin-bottom: .35rem;
  text-shadow: 0 1px 12px rgba(0,0,0,.4);
}
.chapter h2 {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2.4rem, 8vw, 5rem); line-height: 1;
  margin: 0; letter-spacing: -.015em;
  text-shadow: 0 2px 24px rgba(0,0,0,.35);
}
.chapter__blurb { max-width: 30rem; margin: 1.2rem auto 0; opacity: .9; font-size: .95rem; }

/* ---------- spreads: the layout vocabulary ---------- */
/* Varied pacing is what separates "magazine" from "photo grid". */

.spread { margin: clamp(3rem, 7vw, 6.5rem) 0; }

/* Each chapter: the best-rated photograph as the header, then the next nine,
   three to a row. Predictable beats clever — every chapter reads the same. */
.chapter-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(.5rem, 1.4vw, 1.1rem);
  padding: 0 var(--gutter);
  margin: clamp(2.5rem, 6vw, 5rem) 0;
}
.chapter-grid figure { margin: 0; }
.chapter-grid .ph { cursor: zoom-in; }
.chapter-grid img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }
.chapter-grid figcaption { padding-left: 0; padding-right: 0; font-size: .72rem; }

@media (max-width: 780px) { .chapter-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 460px) { .chapter-grid { grid-template-columns: 1fr; } }

.spread--full figure { margin: 0; }
.spread--full .ph { height: min(82vh, 46rem); }

.spread--duo {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(.6rem, 2vw, 1.6rem);
  padding: 0 var(--gutter);
}
.spread--trio {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: clamp(.6rem, 2vw, 1.6rem);
  padding: 0 var(--gutter);
}
.spread--duo img, .spread--trio img { width: 100%; aspect-ratio: 3/2; object-fit: cover; }

.spread--aside {
  display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: center;
  padding: 0 var(--gutter);
}
.spread--aside.is-flipped { grid-template-columns: minmax(0,1fr) minmax(0,1.6fr); }
.spread--aside.is-flipped .spread__note { order: -1; }
.spread__note { max-width: 24rem; }
.spread__note p {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.15rem, 2vw, 1.5rem); line-height: 1.45;
  margin: 0 0 .8rem;
}

@media (max-width: 760px) {
  .spread--trio { grid-template-columns: 1fr 1fr; }
  .spread--aside, .spread--aside.is-flipped { grid-template-columns: 1fr; }
  .spread--aside.is-flipped .spread__note { order: 0; }
}

figure { margin: 0; }
figcaption {
  font-size: .78rem; color: var(--muted);
  padding: .55rem var(--gutter) 0;
  display: flex; gap: .6rem; flex-wrap: wrap;
}
.spread--duo figcaption, .spread--trio figcaption, .spread--aside figcaption { padding-left: 0; padding-right: 0; }
.credit { color: var(--ochre); white-space: nowrap; }

/* ---------- parallax ----------
   Transform-only. Never background-attachment: fixed — it is simply
   broken on iOS. Disabled entirely for prefers-reduced-motion. */

.parallax { will-change: transform; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .parallax { transform: none !important; }
}

/* ---------- lazy image fade ---------- */

.ph { background: var(--bone-deep); overflow: hidden; }
.ph img { opacity: 0; transition: opacity .7s ease; }
.ph img.is-loaded { opacity: 1; }

/* ---------- grids (archive, animals) ---------- */

.page-head { padding: clamp(2.5rem, 7vw, 5rem) var(--gutter) 1.5rem; }
.page-head h1 {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2rem, 5vw, 3.4rem); margin: 0 0 .5rem; letter-spacing: -.015em;
}
.page-head p { color: var(--muted); max-width: var(--measure); margin: 0; }

.filters {
  display: flex; flex-wrap: wrap; gap: .4rem;
  padding: 0 var(--gutter) 1.5rem;
}
.filters button {
  font: inherit; font-size: .78rem;
  padding: .3rem .8rem; border-radius: 999px;
  border: 1px solid var(--rule); background: transparent; color: var(--ink-soft);
  cursor: pointer; transition: all .18s;
}
.filters button:hover { border-color: var(--muted); }
.filters button[aria-pressed="true"] { background: var(--ink); color: var(--bone); border-color: var(--ink); }

.grid {
  display: grid; gap: clamp(.35rem, 1vw, .9rem);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 220px), 1fr));
  padding: 0 var(--gutter);
}
.grid figure { cursor: zoom-in; }
.grid img { width: 100%; aspect-ratio: 1; object-fit: cover; }

.cards {
  display: grid; gap: clamp(1rem, 2.5vw, 2rem);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
  padding: 0 var(--gutter);
}
.card { text-decoration: none; display: block; }
.card img { width: 100%; aspect-ratio: 4/3; object-fit: cover; }
.card__name {
  font-family: var(--display); font-size: 1.15rem; margin-top: .6rem;
}
.card__n { font-size: .74rem; color: var(--muted); letter-spacing: .1em; text-transform: uppercase; }

/* ---------- the seven ---------- */

.people {
  display: grid; gap: clamp(1rem, 3vw, 2.5rem);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 200px), 1fr));
  padding: 0 var(--gutter);
}
.person { border-top: 1px solid var(--rule); padding-top: 1rem; }
.person__name { font-family: var(--display); font-size: 1.4rem; }
.person__n { color: var(--muted); font-size: .8rem; }

/* ---------- lightbox ---------- */

dialog.lb {
  border: 0; padding: 0; max-width: 100vw; max-height: 100vh;
  width: 100vw; height: 100vh;
  background: var(--night); color: #fff;
}
dialog.lb::backdrop { background: rgba(10, 8, 6, .92); }
.lb__body { display: grid; place-items: center; height: 100%; padding: 1rem; }
.lb__body img, .lb__body video { max-width: 94vw; max-height: 88vh; object-fit: contain; }
.lb__meta {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 1rem var(--gutter); font-size: .8rem;
  display: flex; gap: 1rem; justify-content: space-between;
  background: linear-gradient(transparent, rgba(0,0,0,.6));
}
.lb__close {
  position: absolute; top: .75rem; right: 1rem;
  background: none; border: 0; color: #fff; font-size: 1.6rem;
  cursor: pointer; line-height: 1; opacity: .8;
}

/* ---------- footer ---------- */

.foot {
  margin-top: clamp(4rem, 10vw, 8rem);
  padding: clamp(2rem, 5vw, 3.5rem) var(--gutter);
  border-top: 1px solid var(--rule);
  color: var(--muted); font-size: .8rem;
  display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between;
}

.empty { padding: 4rem var(--gutter); color: var(--muted); text-align: center; }
