/* Jitter Squad Cafe. Two inks on paper: cream, black, orange. Nothing else. */

:root {
  --cream: #F3EBDD;
  --ink: #141210;
  --orange: #FF4B1F;

  /* Written by js/dose.js: 0 (still) to 4 (too many). */
  --dose: 0;
  /* Colour of the out-of-register copy behind display type. */
  --misprint: var(--orange);

  --bar-h: 56px;
  --pad: clamp(1rem, 4vw, 3.5rem);
  --display: Anton, Impact, "Arial Narrow Bold", sans-serif;
  --mono: "Space Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
  /* The step between small labels and display type: footer details, guide text. */
  --text-mid: clamp(1rem, 0.9rem + 0.45vw, 1.3rem);

  /* Layers: content 0, bar 20, grain 30. */
  --z-bar: 20;
  --z-grain: 30;

  color-scheme: light;
}

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

html {
  -webkit-text-size-adjust: 100%;
  /* One scroll lands on the next section. A section taller than the screen
     still scrolls freely inside itself. */
  scroll-snap-type: y mandatory;
}

/* The bar's links glide to their section, unless motion is paused. */
@media (prefers-reduced-motion: no-preference) {
  html:not(.is-decaf) {
    scroll-behavior: smooth;
  }
}

[data-dose] {
  scroll-snap-align: start;
  scroll-snap-stop: always;
  min-height: 100dvh;
}

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--mono);
  font-size: clamp(0.95rem, 0.9rem + 0.2vw, 1.0625rem);
  line-height: 1.55;
  overflow-x: hidden;
}

/* Paper grain. Fixed and inert so it never repaints with scroll. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: var(--z-grain);
  pointer-events: none;
  opacity: 0.14;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

h1,
h2,
h3,
p,
ul,
ol {
  margin: 0;
}

ul,
ol {
  padding: 0;
  list-style: none;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

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

/* ---------- Display type and misregistration ---------- */

.display {
  font-family: var(--display);
  font-weight: 400;
  line-height: 0.92;
  letter-spacing: 0.005em;
  /* A hard second impression that slips further as the dose rises. */
  text-shadow: calc(var(--dose) * 0.012em) calc(var(--dose) * 0.006em) 0 var(--misprint);
}

/* Headings that hold display type take its tight leading, so the body's
   line-height does not pad every line. */
.hero__title,
.section-title,
.finale__title {
  line-height: 0.92;
}

/* Letters and words created by js/jitter.js. */
.w {
  display: inline-block;
  white-space: nowrap;
}

.l {
  display: inline-block;
}

/* Inline-block so the highlight is as tall as the line, not the font's full
   ascent and descent, and does not cover the line above. */
mark {
  display: inline-block;
  background: var(--orange);
  color: var(--ink);
  line-height: 0.95;
  padding: 0.06em 0.12em 0;
  text-shadow: none;
}

/* ---------- Buttons ---------- */

.btn {
  font: inherit;
  font-weight: 700;
  color: var(--ink);
  background: var(--cream);
  border: 2px solid var(--ink);
  border-radius: 0;
  cursor: pointer;
  white-space: nowrap;
  transition: transform 120ms ease-out;
}

.btn:active {
  transform: translateY(2px);
}

.btn--big {
  font-size: clamp(1.1rem, 2.4vw, 1.6rem);
  padding: 0.9rem 2.2rem;
  background: var(--ink);
  color: var(--cream);
}

.btn--big:hover {
  background: var(--cream);
  color: var(--ink);
}

/* ---------- Top bar: mark, links, progress dots, motion switch ---------- */

.bar {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-bar);
  height: var(--bar-h);
  padding: 0 var(--pad);
  display: flex;
  align-items: center;
  gap: clamp(0.75rem, 2.5vw, 2rem);
  background: var(--cream);
  border-bottom: 2px solid var(--ink);
}

.bar__mark {
  font-size: 1.35rem;
  line-height: 1;
  text-shadow: none;
  color: inherit;
  text-decoration: none;
}

.bar__nav {
  display: flex;
  gap: clamp(0.75rem, 2vw, 1.5rem);
  font-size: 0.85rem;
  font-weight: 700;
}

.bar__nav a {
  color: inherit;
  text-decoration: none;
  padding: 0.3rem 0;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}

.bar__nav a:hover {
  border-bottom-color: var(--ink);
}

.bar__dose {
  display: flex;
  align-items: center;
  gap: clamp(0.75rem, 2vw, 1.25rem);
  margin-left: auto;
}

.meter {
  display: flex;
  gap: 5px;
}

.pip {
  position: relative;
  width: 12px;
  height: 12px;
  border: 2px solid var(--ink);
  border-radius: 50%;
  overflow: hidden;
}

.pip__fill {
  position: absolute;
  inset: 0;
  background: var(--orange);
  transform: scaleY(var(--f, 0));
  transform-origin: bottom;
}

/* The quietest thing in the bar: plain text with a small square that fills
   when motion is paused. */
.motion {
  font: inherit;
  font-size: 0.8rem;
  color: var(--ink);
  background: none;
  border: 0;
  padding: 0.3rem 0;
  display: flex;
  align-items: center;
  gap: 0.45rem;
  white-space: nowrap;
  cursor: pointer;
}

.motion::before {
  content: "";
  width: 9px;
  height: 9px;
  border: 2px solid var(--ink);
}

.motion[aria-pressed="true"]::before {
  background: var(--ink);
}

.motion:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ---------- Hero (dose 0) ---------- */

/* Phones first: Espresso stands in the free space above the title. */
.hero {
  /* Keeps its stain behind its own content. */
  position: relative;
  isolation: isolate;
  padding: calc(var(--bar-h) + 1.25rem) var(--pad) var(--pad);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto auto;
}

.eyebrow {
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.hero__cup {
  position: relative;
  height: 100%;
  max-height: 300px;
  min-height: 0;
  align-self: end;
  justify-self: start;
  margin: 0 0 0.5rem 6vw;
}

.hero__figure {
  position: relative;
  height: 100%;
}

.hero__figure svg {
  display: block;
  width: auto;
  height: 100%;
}

.hero__title {
  position: relative;
  align-self: end;
  justify-self: start;
  /* Sized so both lines fit the width in portrait and the height in landscape. */
  font-size: min(34vw, 31dvh);
}

.hero__line {
  display: block;
}

/* "Cafe" sits on the rule at the end of "Squad", overlapping the foot of the
   "d" a little. Its bottom offset is the foot's top margin, which is what
   separates the title from the rule. Other sizes are in the label's own em,
   which is 0.24 of the title's. */
.stamp {
  position: absolute;
  right: -1.25em;
  bottom: -1.25rem;
  font-size: 0.24em;
  line-height: 1;
  padding: 0.22em 0.4em 0.16em;
  background: var(--orange);
  color: var(--ink);
  text-shadow: none;
}

/* The top border is the rule the title sits on. */
.hero__foot {
  margin-top: 1.25rem;
  padding-top: 1rem;
  border-top: 2px solid var(--ink);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 2rem;
}

.hero__headline {
  font-weight: 700;
  font-size: clamp(1.1rem, 2.2vw, 1.75rem);
  line-height: 1.2;
}

/* Wider screens: the title on the left, Espresso standing on the rule at the right. */
@media (min-width: 720px) {
  .hero {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: auto minmax(0, 1fr) auto;
    column-gap: var(--pad);
  }

  .eyebrow,
  .hero__foot {
    grid-column: 1 / -1;
  }

  .hero__title {
    grid-column: 1;
    grid-row: 2;
    /* Leaves room for Espresso beside it. */
    font-size: min(22vw, 31dvh);
  }

  /* More room to the right here, so the label covers less of the "d". */
  .stamp {
    right: -1.75em;
  }

  .hero__cup {
    grid-column: 2;
    grid-row: 2;
    width: clamp(200px, 27vw, 400px);
    height: auto;
    max-height: none;
    justify-self: end;
    /* Pulls the feet down onto the rule, across the foot's top margin. */
    margin: 0 0 -1.25rem;
  }

  .hero__figure {
    height: auto;
  }

  .hero__figure svg {
    width: 100%;
    height: auto;
  }
}

/* ---------- The squad (dose 2): the menu as a line-up ---------- */

.squad {
  /* Keeps its stain behind its own content. */
  position: relative;
  isolation: isolate;
  padding: calc(var(--bar-h) + clamp(0.75rem, 3vh, 2.5rem)) var(--pad) clamp(1rem, 3vh, 2.5rem);
  max-width: 1400px;
  margin-inline: auto;
  display: grid;
  align-content: center;
}

.section-title {
  font-size: clamp(2.75rem, 6.2vw, 5.75rem);
}

.squad__statement {
  font-size: clamp(1.35rem, 2.7vw, 2.5rem);
  line-height: 1.06;
  margin-top: clamp(0.9rem, 2.4vh, 1.6rem);
  max-width: 22em;
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.1rem;
  margin-top: clamp(0.75rem, 2vh, 1.5rem);
  font-size: 0.8rem;
}

.legend li {
  display: flex;
  align-items: center;
  gap: 0.45rem;
}

.swatch {
  width: 16px;
  height: 16px;
  border: 2px solid var(--ink);
  background: var(--cream);
}

.swatch--coffee {
  background: var(--orange);
}

.swatch--water {
  background: repeating-linear-gradient(45deg, var(--ink) 0 2px, var(--cream) 2px 6px);
}

.swatch--choc {
  background: var(--ink);
}

.swatch--foam {
  background-image: radial-gradient(var(--ink) 1.4px, transparent 1.6px);
  background-size: 6px 6px;
  background-position: 0 0;
}

/* Three across on phones, all nine in one row on wide screens. */
.lineup {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  row-gap: 0.5rem;
  margin-top: clamp(0.75rem, 2.5vh, 3rem);
}

.member {
  text-align: center;
}

/* The bottom border is the ground the squad stands on. */
.member__art {
  display: grid;
  justify-items: center;
  border-bottom: 2px solid var(--ink);
}

.member__figure {
  display: block;
  max-width: 100%;
}

.member__figure svg {
  display: block;
  width: auto;
  max-width: 100%;
  height: clamp(72px, 10.5dvh, 150px);
}

/* The character and its name link to that drink in the guide. */
.member__link {
  display: block;
  color: inherit;
  text-decoration: none;
}

.member__link:hover .member__name {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

.member__name {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(1.05rem, 1.7vw, 1.5rem);
  line-height: 1;
  margin-top: 0.55rem;
}

.member__temp {
  font-size: 0.85rem;
  line-height: 1.3;
  margin-top: 0.2rem;
}

.lineup__note {
  margin-top: 1rem;
  font-size: 0.85rem;
}

.lineup__note a {
  color: inherit;
  font-weight: 700;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

@media (min-width: 900px) {
  .lineup {
    grid-template-columns: repeat(9, minmax(0, 1fr));
    margin-top: clamp(1.25rem, 4vh, 3rem);
  }

  /* Each drawing has empty margins, so it can be wider than its column
     without two neighbours touching. Much past this and they would. */
  .member__figure {
    width: 116%;
    max-width: none;
  }

  .member__figure svg {
    width: 100%;
    max-width: none;
    height: auto;
  }
}

/* The squad walks in one by one when the menu first comes into view.
   "translate" is used so it does not fight the jitter's "transform". */
@keyframes walk-in {
  from {
    translate: 2.2rem 0;
    opacity: 0;
  }

  to {
    translate: 0 0;
    opacity: 1;
  }
}

.lineup:not(.is-in) .member__figure {
  opacity: 0;
}

.lineup.is-in .member__figure {
  animation: walk-in 520ms cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
  animation-delay: calc(var(--i) * 70ms);
}

/* ---------- Coffee stains in the empty paper ---------- */

/* Each stain sits in empty paper only, clear of type and characters. */
.stain {
  position: absolute;
  z-index: -1;
  aspect-ratio: 1;
  pointer-events: none;
}

.stain svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* In the top right quarter of the hero on every screen, and never directly
   above Espresso. On phones the cup stands at the left, so the stain hugs the
   right edge. */
.stain--hero {
  top: calc(var(--bar-h) + 5dvh);
  right: 3vw;
  width: min(36vw, 22dvh);
}

/* On wider screens the cup stands at the far right, so the stain moves in
   from the edge to sit between the title and the cup. */
@media (min-width: 720px) {
  .stain--hero {
    right: auto;
    left: 54vw;
    width: min(18vw, 28dvh);
  }
}

/* The phone menu has no empty paper to spare. */
.stain--menu {
  display: none;
}

@media (min-width: 900px) {
  /* Top right, beside the title. Tied to the screen height as well as its
     width so it stays clear of the line-up on short screens. */
  .stain--menu {
    display: block;
    right: 2vw;
    top: calc(var(--bar-h) + 1vh);
    width: min(19vw, 28dvh);
  }
}

/* ---------- Footer (dose 4): the one colour-block switch ---------- */

.finale {
  --misprint: var(--cream);
  padding: calc(var(--bar-h) + 1.5rem) var(--pad) var(--pad);
  background: var(--orange);
  display: grid;
  grid-template-rows: 1fr auto;
}

/* Left-aligned, like the hero and the details below it. */
.finale__joke {
  display: grid;
  align-content: center;
  justify-items: start;
  gap: clamp(1.25rem, 4vh, 2.5rem);
}

.finale__title {
  font-size: clamp(3.5rem, min(13vw, 21dvh), 11rem);
}

.foot {
  margin-top: clamp(1.25rem, 4vh, 2.5rem);
  padding-top: 1.25rem;
  border-top: 2px solid var(--ink);
  display: grid;
  gap: 1.1rem 2rem;
  font-size: var(--text-mid);
  line-height: 1.4;
  /* Clears the fixed bar when "Find us" jumps here. */
  scroll-margin-top: var(--bar-h);
}

.foot h3 {
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.5rem;
  line-height: 1;
  margin-bottom: 0.45rem;
}

.foot a {
  color: inherit;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

.foot__small {
  font-size: 0.75rem;
}

@media (min-width: 720px) {
  .foot {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .foot__small {
    grid-column: 1 / -1;
  }
}

/* ---------- Small phones ---------- */

@media (max-width: 519px) {
  .bar__mark {
    display: none;
  }
}

/* ---------- Motion paused, or reduced motion ---------- */

.is-decaf .btn {
  transition: none;
}

.is-decaf .lineup:not(.is-in) .member__figure {
  opacity: 1;
}

.is-decaf .lineup.is-in .member__figure {
  animation: none;
}

@media (prefers-reduced-motion: reduce) {
  .btn {
    transition: none;
  }

  .lineup:not(.is-in) .member__figure {
    opacity: 1;
  }

  .lineup.is-in .member__figure {
    animation: none;
  }
}
