/* Hardpack Rally, hardpackrally.com
   A teaser: a hero, four lines about the game, the shots, and where it is
   going. The palette is sampled out of the game -- the owner's own frame
   of the pale country the hero shows (12 Sep 2026, "can we have a color
   scheme like this?"): its horizon haze for the page, its mountains'
   blue-gray deepened for the text, its pines for the accent, and the
   car's stripe for the one warm mark. The face is the same system
   monospace the game asks Godot for, so the page still reads in the
   game's voice. */

:root {
  --snow:   #eef2f3;   /* the page: the shot's haze at the horizon */
  --haze:   #e3eaec;   /* one step down: the closing band */
  --face:   #dbe4e4;   /* tile faces */
  --line:   #c3d0d2;
  --slate:  #22333c;   /* the text: its mountains, deepened to read */
  --dim:    #55676e;
  --pine:   #2f6360;   /* the accent: its pines, deepened to read */
  --pine-2: #45857f;   /* hover */
  --sky:    #b2d4ed;   /* its sky, for a wash */
  --rust:   #c4522f;   /* the car's stripe: the one warm mark */
  --bar-h:    58px;
  --pad:      clamp(20px, 5vw, 72px);
  /* One column for the whole page. Every band is full width so its
     background reaches the edges, and every band's content sits inside
     this: the page's own margin until the screen is wider than the
     content, then whatever centers it. The bar, the hero's words, the
     paragraph, the shots and the footer all line up on it. */
  --wrap:     1320px;
  --gutter:   max(var(--pad), calc((100% - var(--wrap)) / 2));
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--snow);
  color: var(--slate);
  font-family: ui-monospace, "Cascadia Mono", Consolas, "DejaVu Sans Mono",
               "Liberation Mono", "Noto Sans Mono", monospace;
  font-size: 15px;
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
}

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

a { color: var(--pine); text-decoration: none; }
a:hover { color: var(--pine-2); }

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

/* ---------------------------------------------------------------- the bar */

.bar {
  position: sticky; top: 0; z-index: 50;
  height: var(--bar-h);
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 0 var(--gutter);
  background: rgba(238, 242, 243, 0.93);
  border-bottom: 1px solid var(--line);
}
.mark {
  color: var(--slate); font-size: 14px; letter-spacing: 0.08em;
  white-space: nowrap;
}
.bar-right { display: flex; align-items: center; gap: 12px; }
.pill {
  font-size: 11px; letter-spacing: 0.12em; color: var(--pine);
  border: 1px solid rgba(47, 99, 96, 0.45);
  background: rgba(47, 99, 96, 0.09);
  padding: 5px 11px; white-space: nowrap;
}

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

.hero { position: relative; min-height: min(92vh, 860px); display: flex; overflow: hidden; }
.hero-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  max-width: none;   /* the page-wide img cap would pin it to the frame */
  object-fit: cover; object-position: 50% 54%;
}
/* The shot is pale enough to carry dark words on its own, so the wash is
   only what it has to be: a breath on the left for the wordmark, and the
   last hand's width fading into the page's own color, which is where the
   picture's fog was going anyway. A heavier veil bleached the car. */
.hero::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(to bottom, rgba(238,242,243,0) 0%, rgba(238,242,243,0) 70%,
                    rgba(238,242,243,0.45) 92%, var(--snow) 100%),
    linear-gradient(to right, rgba(238,242,243,0.26) 0%, rgba(238,242,243,0) 46%);
}
/* The words carry their own ground. How deep `cover` crops depends on the
   shape of the window, so the car can turn up anywhere -- on the owner's
   screen it sat right under the lede, which then read straight across a
   white car door (12 Sep 2026, "lets make the text easier to read"). A
   wash over the whole picture bleached it; this one is a soft corner that
   travels with the block of words and is gone by the middle of the
   frame, so the road and the car keep their color. */
.hero-wrap {
  position: relative; z-index: 2;
  align-self: flex-end;
  padding: clamp(34px, 6vh, 72px) var(--gutter) clamp(56px, 9vh, 110px);
  width: 100%;
  background: radial-gradient(125% 165% at 0% 100%,
    rgba(238, 242, 243, 0.94) 0%, rgba(238, 242, 243, 0.88) 32%,
    rgba(238, 242, 243, 0.58) 54%, rgba(238, 242, 243, 0) 78%);
}
.hero h1 {
  font-size: clamp(42px, 9.2vw, 116px);
  line-height: 0.98;
  letter-spacing: 0.02em;
  margin: 0 0 20px;
  color: var(--slate);
  font-weight: 400;
  text-shadow: 0 2px 18px rgba(238, 242, 243, 0.85);
}
.lede {
  margin: 0 0 26px;
  font-size: clamp(15px, 1.7vw, 19px);
  line-height: 1.6;
  max-width: 42ch;
  color: var(--slate);
  text-shadow: 0 1px 10px rgba(238, 242, 243, 0.95);
}
.facts {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 10px;
}
.facts li {
  font-size: 11.5px; letter-spacing: 0.1em; text-transform: uppercase;
  border: 1px solid rgba(34, 51, 60, 0.22);
  background: rgba(255, 255, 255, 0.55);
  padding: 6px 12px;
}
.facts li:first-child { border-color: rgba(47, 99, 96, 0.55); color: var(--pine); }

/* The narrower the frame, the deeper `cover` crops into the picture's
   middle -- and the car lives there, right where the wordmark sits. So the
   picture slides left as the screen narrows, which walks the car to the
   right until the words have the road to themselves. */
@media (max-width: 1100px) { .hero-img { object-position: 42% 54%; } }
@media (max-width: 700px) {
  /* A phone frame is portrait, so `cover` scales the picture by its height
     and the car lands halfway up whatever the crop -- which is exactly
     where a block of words at the bottom would be. On a phone the words go
     to the top instead, over the sky, and the car has the road below them
     to itself. */
  .hero { min-height: min(82vh, 700px); }
  .hero-img { object-position: 44% 54%; }
  .hero-wrap {
    align-self: flex-start;
    padding-top: clamp(26px, 5vh, 52px);
    padding-bottom: clamp(30px, 6vh, 60px);
    background: radial-gradient(135% 150% at 0% 0%,
      rgba(238, 242, 243, 0.94) 0%, rgba(238, 242, 243, 0.88) 38%,
      rgba(238, 242, 243, 0.55) 62%, rgba(238, 242, 243, 0) 86%);
  }
}

/* ------------------------------------------------------------- the teaser */

.intro {
  padding: clamp(48px, 7vw, 86px) var(--gutter) clamp(34px, 4vw, 52px);
}
.intro p {
  margin: 0; max-width: 78ch;
  font-size: clamp(15px, 1.5vw, 17.5px); line-height: 1.85;
  color: var(--slate);
}

/* -------------------------------------------------------------- the shots */

.grid {
  padding: 0 var(--gutter) clamp(56px, 8vw, 104px);
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px;
}
.tile {
  padding: 0; border: 1px solid var(--line); background: var(--face);
  cursor: zoom-in; overflow: hidden; display: block;
}
.tile img {
  aspect-ratio: 16 / 9; object-fit: cover; width: 100%;
  transition: transform 0.35s ease, opacity 0.35s ease;
}
.tile:hover { border-color: var(--pine); }
.tile:hover img { transform: scale(1.05); opacity: 0.92; }
@media (prefers-reduced-motion: reduce) { .tile img { transition: none; } }
@media (max-width: 900px) {
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) { .grid { grid-template-columns: 1fr; } }

/* ------------------------------------------------------- the closing note */

.cta {
  padding: clamp(60px, 9vw, 116px) var(--gutter);
  background:
    radial-gradient(90% 140% at 22% 0%, rgba(178, 212, 237, 0.55) 0%,
                    rgba(227, 234, 236, 0) 62%),
    var(--haze);
  border-top: 1px solid var(--line);
}
.cta h2 {
  margin: 0 0 16px; font-weight: 400; color: var(--slate);
  font-size: clamp(26px, 4.4vw, 48px); letter-spacing: 0.02em;
}
.cta p { margin: 0; max-width: 60ch; }
.cta .small { margin-top: 18px; color: var(--dim); font-size: 12.5px; }

/* The channel, the one link that leaves the page. It is a link, not a new
   band (web/README.md): the bar, a button in the closing block, a word in
   the footer. The mark is drawn inline, so the page still fetches nothing
   from anyone else. */
.cta .watch { margin-top: 30px; }
.yt {
  display: inline-flex; align-items: center; gap: 10px;
  color: var(--slate);
  font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase;
  border: 1px solid rgba(196, 82, 47, 0.45);
  background: rgba(196, 82, 47, 0.09);
  padding: 11px 18px;
  transition: border-color 0.2s ease, background 0.2s ease;
}
.yt svg { width: 20px; height: 20px; flex: none; color: var(--rust); }
.yt:hover {
  color: var(--slate); border-color: var(--rust);
  background: rgba(196, 82, 47, 0.16);
}
@media (prefers-reduced-motion: reduce) { .yt { transition: none; } }

/* The same link in the bar, where it has to survive a phone: the word goes
   first, then the padding, and the mark stays. */
.yt-top {
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--slate);
  font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
  border: 1px solid var(--line);
  padding: 5px 10px; white-space: nowrap;
}
.yt-top svg { width: 16px; height: 16px; flex: none; color: var(--rust); }
.yt-top:hover {
  color: var(--slate); border-color: var(--rust);
  background: rgba(196, 82, 47, 0.09);
}
@media (max-width: 760px) {
  .yt-top .label { display: none; }
  .yt-top { padding: 5px 8px; gap: 0; }
}
@media (max-width: 430px) {
  .bar { gap: 10px; }
  .bar-right { gap: 8px; }
  .mark { font-size: 12.5px; }
  .pill { font-size: 10px; padding: 5px 8px; }
}

footer {
  display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  padding: 26px var(--gutter); border-top: 1px solid var(--line);
  color: var(--dim); font-size: 11.5px; letter-spacing: 0.1em;
  background: var(--haze);
}

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

.lightbox {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(238, 242, 243, 0.96);
  display: grid; place-items: center; padding: 3vw;
}
.lightbox[hidden] { display: none; }
.lightbox img {
  max-width: 100%; max-height: 94vh; border: 1px solid var(--line);
  box-shadow: 0 18px 60px rgba(34, 51, 60, 0.18);
}
.lightbox .close {
  position: absolute; top: 14px; right: 20px;
  background: none; border: 0; color: var(--slate);
  font-size: 34px; line-height: 1; cursor: pointer; padding: 6px 12px;
  font-family: inherit;
}
.lightbox .close:hover { color: var(--pine); }

/* ------------------------------------------------------------ the reveals */

.rise { opacity: 0; transform: translateY(16px); }
.rise.in { opacity: 1; transform: none; transition: opacity 0.6s ease, transform 0.6s ease; }
@media (prefers-reduced-motion: reduce) {
  .rise { opacity: 1; transform: none; }
  .rise.in { transition: none; }
}
