@import url("tokens.css");

/* ===================================================================
   Base
   =================================================================== */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--fs-body);
  line-height: 1.45;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Nothing on this page appears, fades, slides or waits. Everything is
   there from the first paint. */

img { display: block; width: 100%; height: auto; }

/* The UA stylesheet gives figure `margin: 1em 40px`, which quietly stops
   every full-bleed picture on this page from reaching the viewport edge. */
figure { margin: 0; }

h1, h2, h3, h4 {
  font-weight: 500;
  line-height: 1.04;
  letter-spacing: -0.025em;
  margin: 0;
  text-wrap: pretty;
}

p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

a { color: inherit; text-decoration: none; }

::selection { background: var(--ink); color: var(--bg); }

:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

.skip-link {
  position: absolute; left: var(--pad); top: -4rem; z-index: 100;
  background: var(--ink); color: var(--bg); padding: .6rem 1rem;
}
.skip-link:focus-visible { top: .5rem; }

/* ===================================================================
   Frame
   =================================================================== */

.wrap {
  max-width: var(--page);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.section { padding-block: var(--s6); }
.section--tight { padding-block: var(--s5); }

.section--dark {
  background: var(--dark);
  color: var(--bg);
}
.section--dark .meta { color: var(--dark-grey); }

/* A label and a rule, the only recurring structural device on the page. */
.marker {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  border-top: 1px solid var(--rule);
  padding-top: var(--s1);
  margin-bottom: var(--s4);
}
.section--dark .marker { border-top-color: #333; }

h2.meta, .marker h2 {
  font-weight: 400;
  line-height: inherit;
  letter-spacing: 0.02em;
}

.meta {
  font-size: var(--fs-label);
  letter-spacing: 0.02em;
  color: var(--grey);
  margin: 0;
}

/* ===================================================================
   Nav
   =================================================================== */

.nav {
  position: sticky; top: 0; z-index: 50;
  background: var(--bg);
  border-bottom: 1px solid var(--rule);
}
.nav__inner {
  max-width: var(--page);
  margin-inline: auto;
  padding: 0.9rem var(--pad);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
}
.nav__mark {
  font-family: var(--serif);
  font-size: 1.5rem;
  line-height: 1;
  letter-spacing: 0;
  white-space: nowrap;
}
.nav__links {
  display: flex;
  gap: clamp(0.9rem, 2.2vw, 2.25rem);
  margin: 0; padding: 0; list-style: none;
  overflow-x: auto;
  scrollbar-width: none;
}
.nav__links::-webkit-scrollbar { display: none; }
.nav__links a {
  font-size: var(--fs-small);
  color: var(--ink);
  white-space: nowrap;
  padding-bottom: 1px;
  border-bottom: 1px solid transparent;
}
.nav__links a:hover { border-bottom-color: var(--ink); }
.nav__links a[aria-current="true"] { border-bottom-color: var(--ink); }

/* ===================================================================
   Hero: full-bleed media with the headline sitting on it.
   The media wrapper takes either an <img> or a <video> with no other
   change, so swapping in footage later is a one-element edit.
   =================================================================== */

.hero {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: clamp(28rem, 86svh, 56rem);
  background: var(--dark);
  isolation: isolate;
}

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

/* The scrim only has to carry the lower third, where the type sits. Any
   heavier and the photograph stops being the point. */
.hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    rgba(0, 0, 0, 0.74) 0%,
    rgba(0, 0, 0, 0.52) 22%,
    rgba(0, 0, 0, 0.18) 48%,
    rgba(0, 0, 0, 0) 72%
  );
}

.hero__overlay {
  position: relative;
  width: 100%;
  color: #fff;
  padding-top: var(--s5);
  padding-bottom: clamp(2rem, 5vw, 4rem);
}

.hero__kicker {
  font-size: clamp(1.125rem, 0.7rem + 1.8vw, 2.25rem);
  font-weight: 500;
  line-height: 1.04;
  letter-spacing: -0.025em;
  margin: 0 0 0.12em;
}

.hero h1 {
  font-size: clamp(2.25rem, 1rem + 5.4vw, 5.75rem);
  letter-spacing: -0.038em;
  max-width: 19ch;
  color: #fff;
}

.hero__where {
  font-size: var(--fs-small);
  color: rgba(255, 255, 255, 0.86);
  margin: var(--s3) 0 0;
}

/* ===================================================================
   Grid of pictures, Pentagram style:
   uniform image ratio, caption below, tops aligned, bottoms ragged.
   =================================================================== */

.grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s4) var(--gutter);
  align-items: start;
}
/* With captions gone, picture grids want an even gap in both directions.
   The people grid is text, so it keeps the taller row gap. */
.grid--pics { gap: var(--gutter); }

@media (min-width: 40rem) { .grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 64rem) { .grid--3 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 64rem) { .grid--4 { grid-template-columns: repeat(4, 1fr); } }

.card { margin: 0; }
.card img {
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: #f2f2f2;
}
.card--portrait img { aspect-ratio: 3 / 4; }
.card--wide img { aspect-ratio: 16 / 9; }

.card__title { font-size: var(--fs-small); margin: 0; }
.card__note { font-size: var(--fs-small); color: var(--grey); margin: 0; }

/* ===================================================================
   Standfirst
   =================================================================== */

.statement-line {
  font-size: var(--fs-h2);
  letter-spacing: -0.03em;
  line-height: 1.06;
  max-width: 20ch;
  margin: 0;
}

/* ===================================================================
   Itinerary

   Each day is a numeral, a time rule, a photograph and the schedule.
   The rule is the motif: one hairline per day on a shared 4am to
   midnight scale, with a dot at every entry that has a time. Repeated
   six times it reads as the shape of the trip, and it is real data
   rather than decoration.
   =================================================================== */

.days { display: grid; gap: var(--s5); }

/* ---- day head ---- */

.day__head {
  display: flex;
  align-items: baseline;
  gap: var(--s2) var(--s3);
  border-top: 1px solid var(--rule);
  padding-top: var(--s2);
}
.section--dark .day__head { border-top-color: #333; }

.day__num {
  font-size: clamp(2rem, 1.1rem + 2.6vw, 3.25rem);
  line-height: 1;
  letter-spacing: -0.04em;
  color: #c4c4c4;
  margin: 0;
  font-variant-numeric: lining-nums tabular-nums;
}
.section--dark .day__num { color: #555; }

.day__title { font-size: var(--fs-h3); margin: 0; flex: 1 1 auto; }
.day__night { white-space: nowrap; margin: 0; }

/* ---- the time rule ---- */

.rule { margin: var(--s3) 0 var(--s4); }

.rule__track { position: relative; height: 26px; }

.rule__line {
  position: absolute;
  left: 0; right: 0; top: 13px;
  height: 1px;
  background: var(--rule);
}
.section--dark .rule__line { background: #3a3a3a; }

.rule__tick {
  position: absolute;
  top: 8px;
  width: 1px; height: 11px;
  background: var(--rule);
}
.section--dark .rule__tick { background: #3a3a3a; }

.rule__dot {
  position: absolute;
  top: 9px;
  width: 9px; height: 9px;
  margin-left: -4.5px;
  border-radius: 50%;
  background: var(--ink);
}
.section--dark .rule__dot { background: #fff; }

.rule__scale { position: relative; height: 1.1rem; }
.rule__scale span {
  position: absolute;
  transform: translateX(-50%);
  font-size: 0.6875rem;
  color: var(--grey);
  white-space: nowrap;
}
.section--dark .rule__scale span { color: #777; }

/* ---- photograph and schedule ---- */

.day__body { display: grid; grid-template-columns: 1fr; gap: var(--s3); }
@media (min-width: 56rem) {
  .day__body { grid-template-columns: 19rem 1fr; gap: var(--s4); }
}

.day__photo { align-self: start; }
.day__photo img { aspect-ratio: 4 / 3; object-fit: cover; background: #f2f2f2; }
.section--dark .day__photo img { background: #222; }

/* A day with one or two entries would otherwise put a full-height
   photograph beside a single line. Shorten the picture instead, so a
   short day reads as a short block. */
.day--sparse .day__photo img { aspect-ratio: 16 / 9; }

.entries { margin: 0; }

.entry {
  display: grid;
  grid-template-columns: 8.5rem 1fr;
  gap: var(--s2);
  padding-block: 0.8rem;
  border-bottom: 1px solid var(--rule);
}
.section--dark .entry { border-bottom-color: #2a2a2a; }
.entry:first-child { padding-top: 0; }

.entry__time {
  font-size: var(--fs-small);
  color: var(--grey);
  margin: 0;
  font-variant-numeric: tabular-nums;
}
.section--dark .entry__time { color: var(--dark-grey); }

.entry__body { min-width: 0; }
.entry__title { font-size: var(--fs-small); margin: 0; }
.entry__detail {
  font-size: var(--fs-small);
  color: var(--grey);
  margin: 0.15rem 0 0;
  max-width: 58ch;
}
.section--dark .entry__detail { color: var(--dark-grey); }

@media (max-width: 34rem) {
  .entry { grid-template-columns: 1fr; gap: 0.1rem; }
}

/* ===================================================================
   People
   =================================================================== */

.person { }
.person h3 { font-size: var(--fs-h3); margin-bottom: 0.2rem; }
.person .role { font-size: var(--fs-small); color: var(--grey); display: block; margin-bottom: var(--s2); }

/* ===================================================================
   Footer
   =================================================================== */

.footer {
  border-top: 1px solid var(--rule);
  padding-block: var(--s4);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s2) var(--s4);
  align-items: baseline;
}
.footer__mark { font-family: var(--serif); font-size: 1.5rem; line-height: 1; }
.footer p { font-size: var(--fs-small); color: var(--grey); margin: 0; }

/* ===================================================================
   Panel: a dark full-bleed band with a strip of pictures running
   through it. Used once, for the Mezban, because the Mezban is the one
   thing here that is genuinely a sequence.
   =================================================================== */

.panel {
  background: #1a1a1a;
  color: #fff;
  padding-block: var(--s5) var(--s4);
  overflow: hidden;           /* the strip bleeds past both edges */
}
.panel .marker { border-top-color: #333; }
.panel .meta { color: var(--dark-grey); }

/* The strip. Items are duplicated once in the markup, so translating the
   track by exactly half its width (plus half a gap) lands on the copy and
   the loop is seamless. The duplicate set is aria-hidden so a screen
   reader hears each picture once. */
.marquee { margin-top: var(--s4); overflow: hidden; }

.marquee__track {
  display: flex;
  gap: var(--gutter);
  width: max-content;
  padding-inline: var(--pad);
  animation: marquee-scroll 90s linear infinite;
}
.marquee:hover .marquee__track,
.marquee:focus-within .marquee__track { animation-play-state: paused; }

@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(-50% - (var(--gutter) / 2))); }
}

/* Width as its own property, not in the `flex` shorthand. WebKit fails to
   parse a clamp() in the shorthand's basis slot and then drops the WHOLE
   declaration, so the cards silently collapsed to content width in Safari
   while Chromium looked perfect. */
.marquee__item {
  flex: none;
  width: clamp(15rem, 24vw, 22rem);
  margin: 0;
}
.marquee__item img { aspect-ratio: 5 / 4; object-fit: cover; background: #222; }
.marquee__label {
  font-size: var(--fs-label);
  color: var(--dark-grey);
  margin: 0 0 0.5rem;
}

/* No motion for anyone who has asked for none: the strip becomes an
   ordinary horizontal scroller and the duplicate set is dropped. */
@media (prefers-reduced-motion: reduce) {
  .marquee { overflow-x: auto; }
  .marquee__track { animation: none; }
  .marquee__track > [aria-hidden="true"] { display: none; }
}

/* ===================================================================
   Links
   =================================================================== */

.underline {
  text-decoration: underline;
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1px;
}
.underline:hover { text-decoration-thickness: 2px; }

/* ===================================================================
   Story page
   =================================================================== */

/* The story is one narrow column of running text. In the full 110rem frame
   the rules and headings strand it off to the left, so this template runs on
   a narrower page. */
.page--article .wrap { max-width: 64rem; }

.article__head { margin-bottom: var(--s5); }
.article__head h1 {
  font-size: var(--fs-h2);
  letter-spacing: -0.03em;
  max-width: 18ch;
}
.article__by { margin-top: var(--s2); }

/* A single column at reading measure. Two columns would be wrong here:
   this is one long first-person piece, not a page of blocks. */
.article { max-width: 38rem; }
.article p {
  font-size: clamp(1.0625rem, 1rem + 0.35vw, 1.25rem);
  line-height: 1.55;
  margin-bottom: 1.3em;
}

.article__figure { margin-block: var(--s5); }
.article__figure img { aspect-ratio: 3 / 2; object-fit: cover; }

.article__back {
  margin-top: var(--s5);
  padding-top: var(--s2);
  border-top: 1px solid var(--rule);
  font-size: var(--fs-small);
}
