/* The one stylesheet of the site, built into a single external file (the CSP allows no inline styles). Each part
   lives in its own file, named after what it styles; the order below is the cascade order, so keep it. *//* Fonts are served from this domain (licences in /fonts): Caveat Brush (the logo's lettering, for the titles) and
   Space Grotesk under the SIL Open Font License, Permanent Marker (Kolosseum's lettering) under the Apache License 2.0. */
@font-face {
  font-family: "Caveat Brush";
  font-style: normal;
  font-display: swap;
  font-weight: 400;
  src: url("/fonts/caveat-brush-latin-400-normal.woff2") format("woff2");
}

@font-face {
  font-family: "Space Grotesk Variable";
  font-style: normal;
  font-display: swap;
  font-weight: 300 700;
  src: url("/fonts/space-grotesk-latin-wght-normal.woff2") format("woff2-variations");
}

@font-face {
  font-family: "Permanent Marker";
  font-style: normal;
  font-display: swap;
  font-weight: 400;
  src: url("/fonts/permanent-marker-latin-400-normal.woff2") format("woff2");
}

/* Night pond: moss and brass in the dark. */
:root {
  --abyss: #040807;
  --text: #eef2ea;
  --sub: #c3cec4;
  --faint: #97a699;
  --moss: #8fae7e;
  --moss-light: #b8d6a3;
  --brass: #e7b85c;
  --brass-light: #f3d08a;
  --line: rgba(225, 238, 220, 0.16);
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  --brush: "Caveat Brush", "Segoe Print", cursive;
  --sans: "Space Grotesk Variable", "Segoe UI", system-ui, sans-serif;
  color-scheme: dark;
}
/* What every page shares: the reset, the type, the layout width and the small pieces used across the page. */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: 5rem;
}

body {
  margin: 0;
  overflow-x: clip;
  background: var(--abyss);
  color: var(--text);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

::selection {
  background: var(--brass);
  color: #15110a;
}

a {
  color: var(--brass-light);
  text-underline-offset: 0.2em;
}

a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--brass);
  outline-offset: 4px;
  border-radius: 10px;
}

/* Titles in the logo's brush lettering. */
h1,
h2,
h3 {
  margin: 0;
  font-family: var(--brush);
  font-weight: 400;
  letter-spacing: 0;
  line-height: 1.02;
}

h1 {
  font-size: clamp(3rem, 7.4vw, 6.4rem);
}

h2 {
  max-width: 16ch;
  font-size: clamp(2.4rem, 5.2vw, 4.4rem);
}

h3 {
  font-size: clamp(2rem, 3.6vw, 3rem);
}

p {
  margin: 0 0 1rem;
}

.wrap {
  width: 100%;
  max-width: 72rem;
  margin: 0 auto;
  padding: 0 1.25rem;
}

@media (min-width: 700px) {
  .wrap {
    padding: 0 2rem;
  }
}

.kicker {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0 0 1.1rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--moss);
}

.kicker::before {
  content: "";
  flex: none;
  width: 2.25rem;
  height: 1px;
  background: currentColor;
  opacity: 0.7;
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 1.25rem 0 0;
  padding: 0;
  list-style: none;
}

.chips li {
  padding: 0.15rem 0.75rem;
  border: 1px solid rgba(143, 174, 126, 0.42);
  border-radius: 999px;
  color: var(--moss);
  font-size: 0.82rem;
  font-weight: 500;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 3rem;
  padding: 0 1.5rem;
  border-radius: 999px;
  font-size: 0.98rem;
  font-weight: 600;
  text-decoration: none;
  transition: transform 0.4s var(--ease-out), background-color 0.3s ease, box-shadow 0.4s ease;
}

.btn--brass {
  background: var(--brass);
  color: #1a1408;
  box-shadow: 0 10px 30px -12px rgba(231, 184, 92, 0.6);
}

.btn--brass:hover {
  box-shadow: 0 0 0 6px rgba(231, 184, 92, 0.14), 0 16px 40px -12px rgba(231, 184, 92, 0.7);
  transform: translateY(-2px);
}

.btn--ghost {
  border: 1px solid rgba(225, 238, 220, 0.3);
  background: rgba(4, 8, 7, 0.55);
  color: var(--text);
}

.btn--ghost:hover {
  background: rgba(20, 32, 28, 0.75);
  transform: translateY(-2px);
}

/* The stage behind the page: the film's poster, the two videos that take turns, a moving grain and the veil that
   darkens the side where the text sits. Fixed for everyone; without scripts only the first poster shows. */
.film {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background: var(--abyss);
  transition: opacity 0.28s ease;
}

/* A cut between distant stops: a short fade to black while the film jumps (film.js). */
.film.is-cut {
  opacity: 0;
}

/* With scripts, the poster only stands in when the film cannot play (data saving, a file that fails). */
.js .film__poster {
  visibility: hidden;
}

.js .film.stills .film__poster {
  visibility: visible;
}

.film__poster img,
.film__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.film__poster img {
  display: block;
}

/* The tall film keeps the frog in its upper half: on screens wider than it (tablets), the crop takes the bottom,
   where the text sits anyway. */
@media (max-aspect-ratio: 1/1) {
  .film__poster img,
  .film__video {
    object-position: 50% 0;
  }
}

.film__video {
  opacity: 0;
}

.film__video.on.ready {
  opacity: 1;
}

/* Film grain, added here instead of baked into the video (noise costs the encoder dearly). It moves in steps, on the
   film's own rhythm, never further than the margin it has past the screen's edges. */
.film__grain {
  position: absolute;
  inset: -10%;
  background: url("/grain.svg") repeat;
  opacity: 0.07;
  pointer-events: none;
  animation: grain 0.75s steps(6) infinite;
}

@keyframes grain {
  0% {
    transform: translate(0, 0);
  }
  20% {
    transform: translate(-6%, 4%);
  }
  40% {
    transform: translate(4%, -7%);
  }
  60% {
    transform: translate(-3%, 8%);
  }
  80% {
    transform: translate(7%, 2%);
  }
  100% {
    transform: translate(0, 0);
  }
}

.film__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(4, 8, 7, 0.84) 0, rgba(4, 8, 7, 0.58) 34%, rgba(4, 8, 7, 0) 56%);
  opacity: 0;
  transition: opacity 0.5s ease;
}

.film__scrim.on {
  opacity: 1;
}

@media (max-aspect-ratio: 1/1) {
  .film__scrim {
    background: linear-gradient(0deg, rgba(4, 8, 7, 0.92) 0, rgba(4, 8, 7, 0.62) 44%, rgba(4, 8, 7, 0) 62%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .film__grain {
    animation: none;
  }
}

/* A small brass ring that turns while the film waits for its frames. */
.loader {
  position: fixed;
  top: 5.25rem;
  right: 1.25rem;
  z-index: 4;
  width: 1.4rem;
  height: 1.4rem;
  border: 2px solid rgba(231, 184, 92, 0.22);
  border-top-color: var(--brass);
  border-radius: 50%;
  opacity: 0;
  transition: opacity 0.3s ease;
  animation: spin 0.9s linear infinite paused;
  pointer-events: none;
}

.loader.on {
  opacity: 1;
  animation-play-state: running;
}

@keyframes spin {
  to {
    transform: rotate(1turn);
  }
}

@media (max-height: 520px) and (min-aspect-ratio: 1/1) {
  .loader {
    top: 4.5rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .loader {
    animation: none;
  }
}

/* Depth gauge, like a dive computer: on wide screens, with the film running. */
.depth {
  position: fixed;
  top: 50%;
  right: 1.5rem;
  z-index: 3;
  display: none;
  justify-items: end;
  gap: 0.45rem;
  padding: 0.85rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 1rem;
  background: rgba(5, 11, 10, 0.66);
  color: var(--sub);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  transform: translateY(-50%);
  pointer-events: none;
}

@media (min-width: 1240px) and (min-aspect-ratio: 1/1) {
  .js .depth {
    display: grid;
  }
}

.depth__value {
  color: var(--text);
  font-size: 1rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}

.depth__track {
  width: 2px;
  height: 7rem;
  overflow: hidden;
  border-radius: 2px;
  background: var(--line);
}

.depth__fill {
  display: block;
  width: 100%;
  height: 100%;
  background: linear-gradient(var(--brass), rgba(231, 184, 92, 0.25));
  transform: scaleY(0);
  transform-origin: top;
}

/* Header: a dark veil from the top keeps the links readable even over the moon. */
.top {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10;
  border-bottom: 1px solid transparent;
  transition: background-color 0.4s ease, border-color 0.4s ease;
}

.top::before {
  content: "";
  position: absolute;
  inset: 0 0 -2.5rem;
  z-index: -1;
  background: linear-gradient(rgba(3, 7, 6, 0.82), rgba(3, 7, 6, 0.45) 55%, rgba(3, 7, 6, 0));
  transition: opacity 0.4s ease;
  pointer-events: none;
}

/* Solid, not blurred: a blur would be redrawn over every frame of the film. */
.top.is-glass {
  border-bottom-color: var(--line);
  background: rgba(5, 11, 10, 0.88);
}

.top.is-glass::before {
  opacity: 0;
}

.top__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  height: 4.25rem;
}

/* The logo: the frog's face and the name; on narrow phones, the frog peeking out of the water. */
.brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

.brand img {
  display: block;
  width: auto;
  height: 2.9rem;
}

.top__nav {
  display: flex;
  align-items: center;
  gap: clamp(0.9rem, 3vw, 2rem);
}

/* Phones on their side get a lower header; narrow phones, smaller links and the sound switch as an icon. */
@media (max-height: 520px) and (min-aspect-ratio: 1/1) {
  .top__row {
    height: 3.5rem;
  }

  .brand img {
    height: 2.3rem;
  }
}

@media (max-width: 400px) {
  .top__nav {
    gap: 0.7rem;
  }

  .top__nav a {
    font-size: 0.88rem;
  }
}

.top__nav a {
  position: relative;
  color: var(--text);
  font-size: 0.97rem;
  font-weight: 500;
  text-decoration: none;
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.65);
  transition: color 0.3s ease;
}

.top__nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.25em;
  height: 2px;
  border-radius: 2px;
  background: var(--brass);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.5s var(--ease-out);
}

.top__nav a:hover,
.top__nav a:focus-visible {
  color: var(--brass-light);
}

.top__nav a:hover::after,
.top__nav a:focus-visible::after,
.top__nav a[aria-current="true"]::after {
  transform: scaleX(1);
}

/* The section the film is in. */
.top__nav a[aria-current="true"] {
  color: var(--brass-light);
}

/* The film's playhead: a hairline along the header's bottom edge that fills as the film goes on (film.js). */
.top__progress {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  display: none;
  height: 2px;
  overflow: hidden;
  pointer-events: none;
}

.js .top__progress {
  display: block;
}

.top__playhead {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, rgba(231, 184, 92, 0.3), var(--brass));
  transform: scaleX(0);
  transform-origin: left;
}

/* The sound switch: off on arrival; a small wave that moves while the pond is playing. */
.sound {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.3rem 0.8rem;
  border: 1px solid rgba(225, 238, 220, 0.3);
  border-radius: 999px;
  background: rgba(4, 8, 7, 0.5);
  color: var(--text);
  font: inherit;
  font-size: 0.9rem;
  cursor: pointer;
}

.sound__wave {
  width: 1rem;
  height: 2px;
  background: currentColor;
  opacity: 0.6;
}

@media (max-width: 520px) {
  .sound {
    padding: 0.3rem 0.55rem;
  }

  .sound__label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

.sound[aria-pressed="true"] {
  border-color: var(--brass);
  color: var(--brass-light);
}

@media (prefers-reduced-motion: no-preference) {
  .sound[aria-pressed="true"] .sound__wave {
    animation: wave 0.9s ease-in-out infinite alternate;
  }
}

@keyframes wave {
  to {
    transform: scaleX(0.35);
  }
}

/* The page's text over the film. Without scripts it reads top to bottom, block after block. With scripts (.js), the
   home page is a run of stops (film.js): every stop is one screen of scroll and a snap point, so one scroll step is
   one scene, and each block sits fixed on screen, showing only while the film is inside its window (.on). */
.story,
.credits-host {
  position: relative;
  z-index: 2;
}

.scene {
  padding: 7rem 0 2rem;
}

.beat {
  max-width: 38rem;
  margin: 0 auto 3.5rem;
  padding: 0 1.25rem;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.55);
}

.credits-host {
  padding: 2rem 0 3rem;
}

/* ---------- the stops (scripts on) ---------- */
.js.film-page {
  scroll-snap-type: y mandatory;
  scroll-padding-top: 0;
}

.js .scene,
.js .credits-host {
  padding: 0;
}

.js .stop {
  height: 100vh;
  height: 100svh;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

/* The last stop is as tall as the largest viewport, so it reaches the top even with the browser's bars hidden. */
.js .credits-host.stop {
  height: 100vh;
  height: 100lvh;
}

.js .beat {
  position: fixed;
  z-index: 3;
  margin: 0;
  padding: 0;
  opacity: 0;
  transform: translateY(1rem);
  transition: opacity 0.45s ease, transform 0.7s var(--ease-out);
  pointer-events: none;
}

.js .beat.on {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* Wide screens: the text in a column on the left, the frog on the right. */
.js .zone-left {
  top: max(5.5rem, 19vh);
  left: max(1.25rem, 6vw);
  width: min(36rem, 42vw);
}

.js .zone-bottom {
  left: 1.25rem;
  right: 1.25rem;
  bottom: 8vh;
  max-width: none;
  text-align: center;
}

.js .zone-credits {
  left: max(1.25rem, 6vw);
  bottom: 1.75rem;
}

/* Titles follow the screen's height as well as its width, so a block fits a short laptop as it fits a monitor. */
.js .beat--hero h1 {
  font-size: clamp(2.6rem, min(7.6vw, 11vh), 6.8rem);
}

.js .beat h2 {
  font-size: clamp(2rem, min(5.2vw, 8vh), 4.4rem);
}

.js .beat h3 {
  font-size: clamp(1.8rem, min(3.6vw, 6.5vh), 3rem);
}

/* Phones on their side: little height, so the blocks get compact and the extras step aside. */
@media (max-height: 520px) and (min-aspect-ratio: 1/1) {
  .js .zone-left {
    top: 4rem;
    width: min(30rem, 52vw);
  }

  .js .beat .kicker {
    margin-bottom: 0.5rem;
  }

  .js .beat__text {
    margin-top: 0.5rem;
    font-size: 0.9rem;
    line-height: 1.45;
  }

  .js .beat .chips,
  .js .beat__note {
    display: none;
  }

  .js .beat__actions {
    margin-top: 0.9rem;
  }

  .js .beat .btn {
    min-height: 2.5rem;
    padding: 0 1.1rem;
    font-size: 0.9rem;
  }

  .js .beat__link,
  .js .mail {
    margin-top: 0.5rem;
  }

  .js .mail {
    font-size: 1.6rem;
  }

  .js .zone-bottom {
    bottom: 1rem;
  }

  .js .zone-credits {
    left: auto;
    right: 1.25rem;
    bottom: 0.75rem;
    text-align: right;
  }

  .js .zone-credits .mark--artrue {
    height: 1.8rem;
    margin: 0 0 0.25rem auto;
  }
}

/* Tall screens: the frog in the upper half, the text in the lower one, the frog's lines up top. */
@media (max-aspect-ratio: 1/1) {
  .js .zone-left {
    top: auto;
    right: max(1.25rem, 6vw);
    bottom: max(1.5rem, 4vh);
    width: auto;
    max-width: 36rem;
  }

  .js .zone-bottom {
    top: 5.25rem;
    bottom: auto;
  }

  .js .zone-credits {
    right: max(1.25rem, 6vw);
    bottom: 0.9rem;
  }

  .js .zone-credits .mark--artrue {
    height: 2rem;
    margin-bottom: 0.3rem;
  }

  .js .zone-credits .beat__line {
    font-size: 0.75rem;
  }

  /* With the credits on, the contact block moves up to make room for them. */
  .film-page:has(.beat--credits.on) .beat--contact.on {
    transform: translateY(-5.5rem);
  }
}

/* Small phones: tighter text, and the note steps aside. */
@media (max-aspect-ratio: 1/1) and (max-height: 740px) {
  .js .beat .kicker {
    margin-bottom: 0.6rem;
  }

  .js .beat__text {
    margin-top: 0.6rem;
    font-size: 0.92rem;
    line-height: 1.5;
  }

  .js .beat .chips {
    margin-top: 0.8rem;
  }

  .js .beat__note {
    display: none;
  }

  .js .beat__actions {
    margin-top: 1rem;
  }

  .js .beat .btn {
    min-height: 2.6rem;
    padding: 0 1.2rem;
    font-size: 0.92rem;
  }
}

/* Parts that arrive inside a block a little later (the e-mail). */
.js .beat [data-at] {
  opacity: 0;
  transition: opacity 0.45s ease;
}

.js .beat [data-at].on {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .js .beat,
  .js .beat [data-at] {
    transform: none;
    transition: opacity 0.2s linear;
  }
}

/* ---------- the blocks ---------- */
.beat__title,
.beat__brand {
  margin-bottom: 0.4rem;
}

.beat--hero h1 {
  font-size: clamp(3.2rem, 7.6vw, 6.8rem);
}

.beat .alive {
  color: var(--brass);
}

.beat__number,
.beat__meta,
.beat__tag {
  margin: 0 0 0.5rem;
  color: var(--brass);
  font-size: 0.86rem;
  font-weight: 600;
  letter-spacing: 0.1em;
}

.beat__text {
  margin: 0.9rem 0 0;
  color: var(--sub);
  font-size: clamp(1rem, 1.25vw, 1.15rem);
  line-height: 1.6;
}

.beat__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 1.6rem 0 0;
}

.beat__link {
  display: inline-block;
  margin-top: 1rem;
  font-weight: 600;
  text-decoration: none;
}

.beat__link:hover {
  text-decoration: underline;
}

.beat__note {
  margin: 0.75rem 0 0;
  color: var(--faint);
  font-size: 0.86rem;
}

.mail {
  display: inline-block;
  margin-top: 1.1rem;
  color: var(--brass-light);
  font-family: var(--brush);
  font-size: clamp(1.8rem, 4.4vw, 2.8rem);
  line-height: 1.1;
  overflow-wrap: anywhere;
  text-decoration: none;
}

.mail:hover {
  text-decoration: underline;
  text-decoration-thickness: 1px;
}

/* The frog's lines: subtitles under the film. */
.beat__subtitle {
  display: inline-block;
  margin: 0;
  padding: 0.35rem 1rem;
  background: rgba(4, 8, 7, 0.72);
  color: var(--text);
  font-size: clamp(1.15rem, 2vw, 1.5rem);
  font-style: italic;
}

.beat__cue {
  margin: 0;
  color: var(--sub);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
}

/* A brass line that keeps drawing itself downwards, under the cue. */
.js .beat__cue::after {
  content: "";
  display: block;
  width: 1px;
  height: 2.2rem;
  margin: 0.7rem auto 0;
  background: linear-gradient(var(--brass), rgba(231, 184, 92, 0));
  transform-origin: top;
  animation: cue 1.8s var(--ease-out) infinite;
}

@keyframes cue {
  0% {
    opacity: 1;
    transform: scaleY(0);
  }
  65% {
    opacity: 1;
    transform: scaleY(1);
  }
  100% {
    opacity: 0;
    transform: scaleY(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .js .beat__cue::after {
    animation: none;
  }
}

@media (max-height: 520px) and (min-aspect-ratio: 1/1) {
  .js .beat__cue::after {
    height: 1.2rem;
    margin-top: 0.35rem;
  }
}

@media (max-height: 400px) and (min-aspect-ratio: 1/1) {
  .js .beat__cue::after {
    display: none;
  }
}

.beat__line {
  margin: 0;
  color: var(--faint);
  font-size: 0.82rem;
}

/* The works' own marks and the Artrue logo, as their titles. */
.mark {
  display: block;
}

.mark--elite {
  width: auto;
  height: clamp(2.6rem, 5vw, 3.6rem);
}

.mark--kolo {
  display: inline-flex;
  align-items: center;
  color: #f4eee4;
  font-family: "Permanent Marker", "Comic Sans MS", cursive;
  font-size: clamp(2.4rem, 4.8vw, 3.4rem);
  letter-spacing: 0.01em;
  line-height: 1;
}

.mark--kolo img {
  width: 1.045em;
  height: 1.136em;
  margin: 0 -0.045em 0.068em;
}

.mark--artrue {
  width: auto;
  height: 2.6rem;
  margin-bottom: 0.5rem;
}

/* Page not found. */
.lost {
  display: grid;
  justify-items: center;
  align-content: center;
  min-height: 100vh;
  min-height: 100svh;
  padding: 6rem 1.25rem;
  text-align: center;
}

.lost img {
  margin-bottom: 2rem;
  filter: drop-shadow(0 0 30px rgba(231, 184, 92, 0.14));
}

.lost .kicker::before {
  display: none;
}

.lost h1 {
  max-width: 14ch;
  margin-bottom: 1.5rem;
  font-size: clamp(2.4rem, 6vw, 4.2rem);
}
