/* ------------------------------------------------------------------
   Train footer — engraved viaduct with a steaming train that crosses,
   waits two seconds off-screen, and crosses again. Timing lives in --cycle.
   ------------------------------------------------------------------ */

:root {
  --paper: #fbfaf6;
  --ink: #2b2420;
  --ink-soft: #6f6862;
  --ink-mute: #8b837c;
  --rule: rgba(43, 36, 32, 0.08);

  --serif: "Newsreader", "Iowan Old Style", Georgia, serif;
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  /* one full loop: 14s crossing + 2s pause off-screen */
  --cycle: 16s;
  /* how far the rail slides: the train (47.6% of scene width) plus its smoke trail clear the right edge */
  --cross: 158%;
}

* { box-sizing: border-box; }

html, body { margin: 0; }

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ---------- footer shell ---------- */
.footer {
  position: relative;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  overflow: hidden;
  border-top: 1px solid var(--rule);
}

.footer__top {
  flex: 0 0 auto;
  position: relative;
  z-index: 1;                        /* text stays above smoke that drifts up into this area */
  width: min(100% - 96px, 1540px);
  margin: 0 auto;
  padding: 88px 0 56px;
  display: grid;
  grid-template-columns: minmax(280px, 1.6fr) minmax(0, 1.4fr);
  gap: 48px 64px;
  align-items: start;
}

/* brand column */
.footer__logo {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  color: var(--ink);
  text-decoration: none;
}
.footer__mark {
  width: 36px;
  height: 36px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
}
.footer__mark circle:nth-child(3) { fill: currentColor; stroke: none; }
.footer__wordmark {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 38px;
  line-height: 1;
  letter-spacing: -0.01em;
  transform: translateY(-2px);
}
.footer__tagline {
  max-width: 34ch;
  margin: 34px 0 0;
  font-size: 17px;
  line-height: 1.5;
  color: var(--ink-soft);
}

/* link columns */
.footer__nav {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 32px;
  padding-top: 6px;
}
.footer__col { display: grid; gap: 22px; align-content: start; }
.footer__col h3 {
  margin: 0 0 8px;
  font-family: var(--serif);
  font-weight: 500;
  font-size: 26px;
  line-height: 1;
  letter-spacing: -0.005em;
}
.footer__col a {
  font-size: 17px;
  line-height: 1.3;
  color: var(--ink-soft);
  text-decoration: none;
  transition: color 180ms ease;
}
.footer__col a:hover { color: var(--ink); }
.footer__col a:focus-visible,
.footer__logo:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 4px;
  border-radius: 2px;
}

/* ---------- the scene ---------- */
.scene {
  position: relative;
  width: 100%;
  aspect-ratio: 2000 / 844;
  min-height: 405px;                /* never shrink the engraving below this on phones */
  overflow: clip visible;           /* crop the plate sideways on phones, but let smoke rise above the box */
  pointer-events: none;
  user-select: none;
}
.scene__inner {
  position: absolute;
  bottom: 0;
  left: 50%;
  width: max(100%, 960px);          /* on narrow screens the plate is center-cropped instead of shrunk */
  aspect-ratio: 2000 / 844;
  transform: translateX(-50%);
}
:where(.scene) img {           /* low specificity so per-layer sizes below win */
  display: block;
  position: absolute;
  height: auto;
}

/* viaduct layer */
.scene__viaduct { position: absolute; inset: 0; }
.scene__bridge {
  left: 0; bottom: 0;
  width: 100%;
}
.scene__rail {
  position: absolute; inset: 0;
  will-change: transform;
  animation: cross-right var(--cycle) linear infinite;
}
.scene__train {
  position: absolute;
  top: 2.962%;
  width: 47.6%;                      /* 952 / 2000 (viewBox width) */
  height: 46.564%;                   /* 393 / 844  */
  right: 100%;                       /* parked just off the left edge; the rail slides it across */
  overflow: visible;
}

/* ---------- the living parts of the train (sprite space: 832×393) ----------
   wheel spin is SMIL in the markup (0.766s per turn ≈ 226 sprite-px/s, the rail speed at --cycle 16s)
   smoke is a chain of puff sprites; each slot below runs the same 4.4s life, staggered by 0.275s  */
.train__rumble {
  animation: rumble 0.42s ease-in-out infinite alternate;
}
.puff {
  transform-box: fill-box;
  transform-origin: 50% 50%;
  opacity: 0;
  animation: puff-life 4.4s linear infinite;
  animation-delay: calc(var(--i) * -0.275s);
}
@keyframes rumble {
  from { transform: translateY(0); }
  to   { transform: translateY(0.7px); }
}
/* Horizontal drift is exactly the ground speed (226 px/s × 4.4s = 993px) so a puff stays put in
   the world while the train drives on; it rises quickly at first, then slows, and swells as it thins. */
@keyframes puff-life {
  0%   { transform: translate(0,      0)                              scale(calc(0.18 * var(--size))) rotate(0deg);                    opacity: 0; }
  5%   { transform: translate(-50px,  calc(-16px  * var(--lift)))     scale(calc(0.34 * var(--size))) rotate(calc(var(--spin) * .05)); opacity: 0.95; }
  25%  { transform: translate(-248px, calc(-92px  * var(--lift)))     scale(calc(0.70 * var(--size))) rotate(calc(var(--spin) * .25)); opacity: 0.92; }
  50%  { transform: translate(-497px, calc(-158px * var(--lift)))     scale(calc(1.05 * var(--size))) rotate(calc(var(--spin) * .5));  opacity: 0.82; }
  75%  { transform: translate(-745px, calc(-186px * var(--lift)))     scale(calc(1.32 * var(--size))) rotate(calc(var(--spin) * .75)); opacity: 0.55; }
  100% { transform: translate(-993px, calc(-210px * var(--lift)))     scale(calc(1.55 * var(--size))) rotate(var(--spin));             opacity: 0; }
}

/* ---------- timeline (percent of --cycle = 16s) ----------
   0–14s   train crosses the viaduct at constant speed (226 sprite-px/s)
   14–16s  empty bridge, then the train re-enters from the left
------------------------------------------------------------ */
@keyframes cross-right {
  0%     { transform: translateX(0); }
  87.5%  { transform: translateX(var(--cross)); }
  100%   { transform: translateX(var(--cross)); }
}
@keyframes cross-left {
  0%     { transform: translateX(0); }
  87.5%  { transform: translateX(calc(-1 * var(--cross))); }
  100%   { transform: translateX(calc(-1 * var(--cross))); }
}

/* mirror the run: locomotive faces left and travels right → left */
.footer[data-direction="left"] .scene__rail { animation-name: cross-left; }
.footer[data-direction="left"] .scene__train {
  right: auto;
  left: 100%;
  transform: scaleX(-1);              /* wheels then read as turning the other way too */
}

/* On desktop the footer is exactly one viewport tall: the text block keeps its size and the
   scene takes whatever is left, with the plate anchored to the bottom edge. If the plate is
   taller than that space, only its empty sky overflows upward, behind the text. */
@media (min-width: 641px) and (min-height: 620px) {
  .footer { height: 100vh; }
  .scene  { flex: 1 1 auto; min-height: 0; aspect-ratio: auto; }
}

/* ---------- accessibility ----------
   The train's slow, linear crossing is gentle enough to keep under Reduce Motion
   (macOS ships with it on for many users); only the rumble goes. */
@media (prefers-reduced-motion: reduce) {
  .train__rumble { animation: none; }
}

/* ---------- responsive ---------- */
@media (max-width: 1100px) {
  .footer__top {
    grid-template-columns: 1fr;
    padding-top: 64px;
    gap: 48px;
  }
  .footer__col h3 { font-size: 23px; }
}
@media (max-width: 640px) {
  .footer { min-height: auto; }
  .footer__top { width: min(100% - 48px, 1540px); padding: 56px 0 40px; }
  .footer__nav { grid-template-columns: 1fr 1fr; gap: 28px; }
  .footer__wordmark { font-size: 32px; }
  .footer__mark { width: 30px; height: 30px; }
  .footer__col { gap: 16px; }
  .footer__col a, .footer__tagline { font-size: 16px; }
}
