/* tips coffee & eatery — menü */

:root {
  --cream: #f0e6d4;
  --green: #0b3120;
  --green-soft: rgba(11, 49, 32, 0.76);
  --green-faint: rgba(11, 49, 32, 0.42);
  --green-line: rgba(11, 49, 32, 0.14);
  --green-wash: rgba(11, 49, 32, 0.055);
  --glass: rgba(240, 230, 212, 0.9);

  --font: "Gotham Rounded", "Nunito", ui-rounded, "SF Pro Rounded", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --ease: cubic-bezier(0.22, 0.8, 0.24, 1);

  --gutter: 20px;
  --maxw: 1080px;
  --tabs-h: 58px;
}

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: calc(var(--tabs-h) + 10px);
  /* "only" is what opts out of Chrome/Samsung forced dark mode; the first line is for engines that reject it */
  color-scheme: light;
  color-scheme: only light;
}

body {
  margin: 0;
  overflow-x: hidden;
  background: var(--cream);
  color: var(--green);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
}

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

h1,
h2,
h3,
h4,
p {
  margin: 0;
}

a {
  color: inherit;
}

:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 3px;
  border-radius: 8px;
}

.skip {
  position: absolute;
  left: 12px;
  top: 12px;
  transform: translateY(calc(-100% - 24px));
  z-index: 50;
  padding: 10px 16px;
  border-radius: 999px;
  background: var(--green);
  color: var(--cream);
  font-weight: 600;
  text-decoration: none;
}

.skip:focus {
  transform: none;
}

.noscript {
  padding: 40px var(--gutter);
  text-align: center;
}

/* ---------- hero (the PDF cover: logo top right, mascot bottom left) ---------- */

.hero {
  position: relative;
  height: 78vh;
  height: min(78svh, 660px);
  min-height: 430px;
  overflow: hidden;
}

.hero__brand-in {
  position: absolute;
  top: 9%;
  right: max(var(--gutter), calc((100% - var(--maxw)) / 2 + var(--gutter)));
  z-index: 1; /* the text always paints above the mascot's line art */
  width: min(64%, 430px);
}

.hero__brand {
  text-align: right;
  transform-origin: 100% 0;
}

.hero__logo {
  width: 100%;
  height: auto;
}

.hero__note {
  margin-top: 14px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--green-soft);
}

.hero__note span {
  display: block;
  text-wrap: balance;
}

.hero__mascot-in {
  position: absolute;
  left: max(-14%, calc((100% - var(--maxw)) / 2 - 120px));
  bottom: -13%;
  width: min(88%, 540px);
}

/* On short phones a width-only mascot grows up into the logo; cap it by the hero's height as well. */
@media (max-width: 1079px) {
  .hero__mascot-in {
    width: min(88%, 540px, max(200px, calc(78svh - min(38vw, 255px) - 84px)));
  }
}

.hero__mascot {
  width: 100%;
  height: auto;
  transform-origin: 30% 100%;
}

.hero__hint {
  position: absolute;
  right: max(var(--gutter), calc((100% - var(--maxw)) / 2 + var(--gutter)));
  bottom: 22px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--green-soft);
}

/* and already on screen when the menu opens, opposite the logo */
.hero__lang {
  position: absolute;
  z-index: 2;
  top: 9%;
  left: max(var(--gutter), calc((100% - var(--maxw)) / 2 + var(--gutter)));
  background: var(--glass);
  -webkit-backdrop-filter: saturate(1.5) blur(14px);
  backdrop-filter: saturate(1.5) blur(14px);
}

/* ---------- category tabs ---------- */

.tabs {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--glass);
  -webkit-backdrop-filter: saturate(1.5) blur(14px);
  backdrop-filter: saturate(1.5) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s, box-shadow 0.3s;
}

.tabs.is-stuck {
  border-bottom-color: var(--green-line);
  box-shadow: 0 8px 24px -18px rgba(11, 49, 32, 0.5);
}

/* the scrolling categories keep the page's width; the language pill parks at its right edge */
.tabs__in {
  display: flex;
  align-items: center;
  max-width: var(--maxw);
  margin: 0 auto;
}

.tabs__scroll {
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 18px, #000 calc(100% - 28px), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 18px, #000 calc(100% - 28px), transparent 100%);
}

.tabs__scroll::-webkit-scrollbar {
  display: none;
}

.tabs__track {
  position: relative;
  display: inline-flex;
  gap: 2px;
  min-width: 100%;
  height: var(--tabs-h);
  padding: 10px var(--gutter);
}

/* switch to the other language's menu: the same pill in the hero and in the sticky bar */
.lang {
  display: inline-flex;
  align-items: center;
  height: calc(var(--tabs-h) - 20px);
  padding: 0 15px;
  border: 1px solid var(--green-line);
  border-radius: 999px;
  background: var(--green-wash);
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.06em;
  white-space: nowrap;
  text-decoration: none;
  color: var(--green);
  transition: background 0.35s var(--ease), color 0.35s var(--ease), transform 0.2s var(--ease);
}

.lang:hover {
  background: var(--green);
  color: var(--cream);
}

.lang:active {
  transform: scale(0.96);
}

/* in reach while you read the menu */
.tabs__lang {
  flex: none;
  margin-right: var(--gutter);
}

.tabs__pill {
  position: absolute;
  top: 10px;
  left: 0;
  width: var(--w, 0px);
  height: calc(100% - 20px);
  border-radius: 999px;
  background: var(--green);
  transform: translateX(var(--x, 0px));
  opacity: 0;
  transition: transform 0.5s var(--ease), width 0.5s var(--ease), opacity 0.3s;
}

.tabs__pill.is-ready {
  opacity: 1;
}

.tabs__link {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  padding: 0 15px;
  border-radius: 999px;
  font-size: 14.5px;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: none;
  color: var(--green);
  transition: color 0.35s var(--ease);
}

.tabs__link[aria-current="true"] {
  color: var(--cream);
}

/* invisible: stretches the 38px pill's tap target over the bar's own padding */
.tabs__link::after {
  content: "";
  position: absolute;
  inset: -10px -1px;
}

/* how far through the menu you are */
.tabs__progress {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: var(--green);
  transform: scaleX(0);
  transform-origin: 0 50%;
}

/* ---------- sections ---------- */

/* Parts waiting off to the side must not widen the page. clip (not hidden) keeps the sticky group
   header and the view timelines attached to the viewport; both axes avoids a WebKit 16.0-16.3
   sticky jitter with single-axis clip. */
main {
  overflow: clip;
}

@supports not (overflow: clip) {
  main {
    contain: paint;
  }
}

.section {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 54px var(--gutter) 14px;
}

.section--narrow {
  max-width: 720px;
}

.section__head {
  text-align: right;
}

.section__title {
  font-size: clamp(46px, 14vw, 92px);
  font-weight: 800;
  line-height: 0.92;
  letter-spacing: -0.03em;
}

/* staggered two-line titles, as on the printed menu */
.section__title .w {
  display: block;
}

.section__title .w:first-child:not(:last-child) {
  padding-right: 0.42em;
}

.section__intro {
  max-width: 34ch;
  margin: 14px 0 0 auto;
  font-size: 13.5px;
  color: var(--green-soft);
}

.section__outro {
  margin-top: 22px;
  padding: 14px 16px;
  border-radius: 16px;
  background: var(--green-wash);
  font-size: 13.5px;
  color: var(--green-soft);
}

/* under large system text a long word breaks instead of being clipped */
.section__title,
.dish__name,
.drink__name,
.bean__name,
.extras__name {
  overflow-wrap: anywhere;
}

.price {
  font-weight: 800;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.price .cur {
  margin-left: 0.18em;
  font-size: 0.82em;
  font-weight: 600;
}

/* ---------- dishes (photo + text rows) ---------- */

.dishes {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 24px 48px;
  margin-top: 18px;
}

.dish {
  display: grid;
  grid-template-columns: 41% minmax(0, 1fr);
  align-items: center;
  gap: 16px;
  padding: 16px 0;
}

.dish:nth-child(even) {
  grid-template-columns: minmax(0, 1fr) 41%;
  text-align: right;
}

.dish:nth-child(even) .dish__media {
  order: 2;
}

.dish:nth-child(even) .dish__meta,
.dish:nth-child(even) .allergens {
  justify-content: flex-end;
}

.dish--noimg,
.dish--noimg:nth-child(even) {
  grid-template-columns: minmax(0, 1fr);
}

.dish__media {
  position: relative;
  aspect-ratio: 1;
}

/* soft contact shadow under the plate: a gradient, not a filter, so scrolling stays cheap */
.dish__media::before {
  content: "";
  position: absolute;
  inset: 10% 6% 0;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(11, 49, 32, 0.3), rgba(11, 49, 32, 0.12) 62%, transparent 100%);
  transform: translateY(7%);
}

.dish__media img {
  position: relative;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.dish__name {
  font-size: 18.5px;
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -0.012em;
  text-wrap: balance;
}

.dish__desc {
  margin-top: 7px;
  font-size: 13.5px;
  line-height: 1.42;
  color: var(--green-soft);
  text-wrap: pretty;
}

.dish__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
  margin-top: 10px;
}

.dish__meta .price {
  font-size: 20px;
}

.kcal {
  font-size: 12.5px;
  font-style: italic;
  font-weight: 300;
  color: var(--green-soft);
}

.allergens {
  display: flex;
  flex-wrap: wrap;
  gap: 3px 9px;
  margin: 9px 0 0;
  padding: 0;
  list-style: none;
  font-size: 11.5px;
  line-height: 1.3;
  color: var(--green-soft);
}

.allergens li {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.allergens img {
  width: 15px;
  height: 15px;
  flex: none;
}

/* ---------- drinks (house specials) ---------- */

.group {
  margin-top: 22px;
}

/* the shared price rides along under the tabs while its drinks are on screen */
.group__head {
  position: sticky;
  top: var(--tabs-h);
  z-index: 10;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  margin: 0 calc(var(--gutter) * -1);
  padding: 10px var(--gutter);
  background: var(--glass);
  -webkit-backdrop-filter: saturate(1.5) blur(14px);
  backdrop-filter: saturate(1.5) blur(14px);
}

.group__title {
  font-size: 34px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
}

.group__kind {
  display: block;
  margin-bottom: 4px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--green-soft);
}

.group__price {
  padding: 5px 14px 6px;
  border-radius: 999px;
  background: var(--green);
  color: var(--cream);
  font-size: 17px;
}

/* Drinks are scattered the way the printed menu scatters them, not lined up like beads on a string:
   every other column rides lower so rows never align, and each drink drifts at its own pace while
   scrolling. Their sizes, though, are not scattered: see the glass classes below. */
.drinks {
  --shift: 108px;
  /* Drinks are printed at 70% scale: the media box is as tall as a tall glass at that scale
     (0.7 × 1.08 of the box width), and a cup takes this share of it. The scale lives in the box
     alone — the glass shares further down are untouched, so tall, short and cup keep the same
     proportions to one another. */
  --box-a: 0.756;
  --cup-h: 66%;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 54px 18px;
  margin: 18px 0 0;
  padding: 0 0 var(--shift); /* room for the lowered column's last drink */
  list-style: none;
}

.drink {
  position: relative;
  width: 100%;
  max-width: 240px;
  justify-self: center;
  text-align: center;
}

/* the drift cycles every 4, so neighbouring drinks never travel together */
.drink:nth-child(4n + 1) { --drift: -3%; }
.drink:nth-child(4n + 2) { --drift: -10%; }
.drink:nth-child(4n + 3) { --drift: -7%; }
.drink:nth-child(4n + 4) { --drift: -4%; }

/* the whole right column sits lower, so the two columns interleave like a zipper */
.drink:nth-child(even) {
  top: var(--shift);
}

/* with an odd count the lowered column ends inside the last row, so no extra room is needed */
@supports selector(:has(a)) {
  @media (max-width: 599px) {
    .drinks {
      padding-bottom: 0;
    }

    .drinks:has(> .drink:last-child:nth-child(even)) {
      padding-bottom: var(--shift);
    }
  }
}

/* Drinks stand free on the page, drawn at the size they are served in. Within a group the media box
   is one height and every glass rests on its floor, so the drinks share a baseline and the names
   below them line up; the glass class then decides how much of that height the drink itself takes,
   which is what keeps all the short glasses matching each other, and the tall ones and cups too. */
.drink__media {
  position: relative;
  aspect-ratio: 1 / var(--box-a);
}

.drink__media img {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  margin-inline: auto;
  width: auto;
  max-width: none; /* the height rules the size; the width follows the photo's own proportions */
  height: var(--glass-h, 100%);
  /* the drink's own soft shadow grounds it, and keeps a white cup from dissolving into the cream */
  filter: drop-shadow(0 9px 13px rgba(11, 49, 32, 0.2));
}

/* iced drinks come in tall glasses or short tumblers; everything hot is served in the same cup */
.drink--tall .drink__media img { --glass-h: 100%; }
.drink--short .drink__media img { --glass-h: 76%; }
.drink--cup .drink__media img { --glass-h: var(--cup-h); }

/* The hot groups are nothing but cups, and a box built for a tall glass would leave a band of empty
   page above them. Shorten the box there and grow the cup's share of it to match, so a cup still
   comes out the same size as every other cup on the menu. */
@supports selector(:has(a)) {
  .drinks:not(:has(.drink--tall, .drink--short)) {
    --box-a: 0.595; /* 0.7 × 0.85, the same 70% scale as the mixed groups above */
    --cup-h: 84%;
  }
}

.drink__name {
  max-width: 15ch;
  margin: 12px auto 0;
  font-size: 15.5px;
  font-weight: 800;
  line-height: 1.16;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

.drink__text .price {
  display: block;
  margin-top: 4px;
  font-size: 16px;
}

/* ---------- price lists ---------- */

.list {
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
}

.list li {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 15px 0;
}

.list__name {
  font-size: 17px;
}

.list__detail {
  display: inline-block;
  font-size: 13px;
  color: var(--green-soft);
}

.list__dots {
  position: relative;
  top: -4px;
  flex: 1;
  min-width: 18px;
  height: 0;
  border-bottom: 2px dotted var(--green-faint);
}

.list .price {
  font-size: 17px;
}

.sub {
  margin-top: 28px;
}

.sub__title {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--green-soft);
}

.beans {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  margin-top: 12px;
}

.bean {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: 14px;
  border-radius: 18px;
  background: var(--green-wash);
}

.bean__name {
  font-size: 14px;
  font-weight: 800;
  line-height: 1.2;
  text-wrap: balance;
}

.bean__notes {
  margin: 6px 0 12px;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--green-soft);
}

.bean__price {
  margin-top: auto;
  padding: 2px 10px 3px;
  border-radius: 999px;
  background: var(--green);
  color: var(--cream);
  font-size: 13px;
}

.extras {
  margin: 12px 0 0;
  padding: 4px 16px;
  border-radius: 18px;
  background: var(--green-wash);
  list-style: none;
}

.extras li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  padding: 15px 0;
}

.extras li + li {
  border-top: 1px solid var(--green-line);
}

.extras__name {
  font-size: 14.5px;
  font-weight: 600;
}

.extras__detail {
  display: block;
  margin-top: 2px;
  font-size: 12.5px;
  font-weight: 400;
  color: var(--green-soft);
}

.extras .price {
  font-size: 15px;
}

/* ---------- footer (mirrors the hero: the mascot comes back up) ---------- */

.foot {
  position: relative;
  min-height: 380px;
  margin-top: 64px;
  overflow: hidden;
  border-top: 1px solid var(--green-line);
}

/* until app.js fills it, keep the empty footer from painting right under the tabs */
.foot:empty {
  display: none;
}

.foot__text {
  position: relative;
  z-index: 1;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 40px var(--gutter) 0;
  text-align: right;
  font-size: 12.5px;
  color: var(--green-soft);
}

.foot__logo {
  width: 132px;
  height: auto;
  margin: 0 0 14px auto;
}

.foot__text p {
  max-width: 26ch;
  margin-left: auto;
  text-wrap: balance;
}

.foot__text p + p {
  margin-top: 4px;
}

.foot__mascot {
  position: absolute;
  left: max(-10%, calc((100% - var(--maxw)) / 2 - 60px));
  bottom: -22%;
  width: min(62%, 330px);
  height: auto;
}

.totop {
  position: fixed;
  right: calc(16px + env(safe-area-inset-right));
  bottom: calc(18px + env(safe-area-inset-bottom));
  z-index: 30;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--green);
  color: var(--cream);
  box-shadow: 0 10px 24px -10px rgba(11, 49, 32, 0.7);
  opacity: 0;
  visibility: hidden; /* out of the tab order and the accessibility tree while it is not shown */
  transform: translateY(14px) scale(0.9);
  pointer-events: none;
  transition: opacity 0.35s var(--ease), transform 0.35s var(--ease), visibility 0s linear 0.35s;
}

.totop[hidden] {
  display: none;
}

.totop.is-on {
  opacity: 1;
  visibility: visible;
  transform: none;
  pointer-events: auto;
  transition-delay: 0s;
}

/* ---------- larger screens ---------- */

@media (min-width: 600px) {
  :root {
    --gutter: 32px;
  }

  /* three columns: it is the middle one that rides lower */
  .drinks {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .drink:nth-child(even) {
    top: 0;
  }

  .drink:nth-child(3n + 2) {
    top: var(--shift);
  }

  .dish__name {
    font-size: 20px;
  }

  .dish__desc {
    font-size: 14.5px;
  }
}

@media (min-width: 820px) {
  .dishes {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* five columns: the 2nd and 4th ride lower, so a row of drinks reads as a wave */
  .drinks {
    --shift: 124px;
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }

  .drink:nth-child(3n + 2) {
    top: 0;
  }

  .drink:nth-child(5n + 2),
  .drink:nth-child(5n + 4) {
    top: var(--shift);
  }

  .tabs__track {
    justify-content: center;
  }

  /* the language pill takes room at the right; mirror it on the left so the centred tabs stay page-centred */
  .tabs__scroll {
    padding-left: calc(52px + var(--gutter));
  }
}

/* =====================================================================
   Scroll-driven motion

   .sd    a scroll subject: its trip through the viewport is the timeline
   .sd-a  a part (the subject itself or a descendant) scrubbed by that trip

   Who moves the keyframes along is decided in app.js:
     native  (Chromium, not framed) CSS scroll timelines, off the main thread
     waapi   (every iOS browser, Firefox, framed previews) app.js sets each paused animation's currentTime
     cssvar  (no getAnimations) app.js writes progress into --p, used as a negative animation-delay
   The engine below is the same for every motion preference; only the keyframe names differ.
   ===================================================================== */

.js .sd {
  view-timeline: --sd block;
  /* auto would inherit html's scroll-padding-top and start every timeline 68px in */
  view-timeline-inset: 0;
}

.js .sd-a {
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-fill-mode: both;
  animation-play-state: paused;
  animation-delay: calc(var(--p, 0) * -1s);
}

@supports (animation-timeline: view()) {
  html:not(.sd-js) .sd-a {
    animation-play-state: running;
    animation-delay: 0s;
    animation-duration: auto;
    animation-timeline: --sd;
    animation-range: cover 0% cover 100%;
  }

  html:not(.sd-js) .sd-a--exit {
    animation-range: exit 0% exit 100%;
  }

  html:not(.sd-js) .sd-a--entry {
    animation-range: entry 0% entry 100%;
  }

  html:not(.sd-js) .tabs__progress {
    animation-timeline: scroll(root block);
    animation-range: normal;
  }
}

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }

  .hero__mascot-in {
    animation: load-rise 1.1s var(--ease) both;
  }

  .hero__brand-in {
    animation: load-fade 0.9s 0.15s var(--ease) both;
  }

  .hero__hint svg {
    animation: nudge 1.6s ease-in-out 3;
  }

  .hero__mascot { animation-name: hero-mascot; }
  .hero__brand { animation-name: hero-brand; }
  .hero__hint { animation-name: hero-hint; }
  .tabs__progress { animation-name: grow-x; }

  .section__title .w { animation-name: word-in; --from: 22%; }
  .section__title .w + .w { --from: 58%; }
  .section__intro { animation-name: word-in; --from: 40px; }

  .dish:nth-child(odd) .dish__media { animation-name: serve-l; }
  .dish:nth-child(odd) .dish__media img { animation-name: spin-l; }
  .dish:nth-child(odd) .dish__body { animation-name: text-l; }
  .dish:nth-child(even) .dish__media { animation-name: serve-r; }
  .dish:nth-child(even) .dish__media img { animation-name: spin-r; }
  .dish:nth-child(even) .dish__body { animation-name: text-r; }

  .drink__media img { animation-name: drink-in; }
  .drink__text { animation-name: drink-text; }
  .drink:nth-child(even) .drink__media img { animation-name: drink-in-lag; }
  .drink:nth-child(even) .drink__text { animation-name: drink-text-lag; }

  .list__name { animation-name: row-name; }
  .list__dots { animation-name: row-dots; }
  .list .price { animation-name: row-price; }

  .bean,
  .sub__box,
  .section__outro { animation-name: pop; }
  .bean:nth-child(even) { animation-name: pop-lag; }

  .foot__mascot { animation-name: foot-mascot; }
}

/* Reduce Motion is a request for LESS motion, not for a dead page: nothing slides, spins or scales, but
   parts still fade in as they are scrolled to, and the progress line still grows. */
@media (prefers-reduced-motion: reduce) {
  .tabs__pill,
  .lang,
  .totop {
    transition: none;
  }

  .sd-a { animation-name: fade-in; }
  .hero .sd-a,
  .foot__mascot { animation-name: none; }
  .hero__hint { animation-name: hero-hint; }
  .tabs__progress { animation-name: grow-x; }
}

@keyframes fade-in {
  0%, 4% { opacity: 0; }
  22%, 100% { opacity: 1; }
}

@keyframes load-rise {
  from { opacity: 0; transform: translateY(60px); }
}

@keyframes load-fade {
  from { opacity: 0; transform: translateY(16px); }
}

@keyframes nudge {
  0%, 100% { transform: none; }
  50% { transform: translateY(5px); }
}

/* hero: scrubbed while the cover scrolls away */
@keyframes hero-mascot {
  to { transform: translateY(30%) rotate(-5deg); }
}

@keyframes hero-brand {
  to { opacity: 0; transform: translateY(-18%) scale(0.8); }
}

@keyframes hero-hint {
  0% { opacity: 1; }
  16%, 100% { opacity: 0; }
}

@keyframes grow-x {
  to { transform: scaleX(1); }
}

/* titles slide in from the right, second word from further away */
@keyframes word-in {
  0% { opacity: 0; transform: translateX(var(--from, 30%)); animation-timing-function: cubic-bezier(0.2, 0.7, 0.2, 1); }
  24%, 100% { opacity: 1; transform: none; }
}

/* plates are served from their side of the table, spinning to rest, then keep turning slowly */
@keyframes serve-l {
  0% { opacity: 0; transform: translateX(-95%); animation-timing-function: cubic-bezier(0.16, 0.8, 0.3, 1); }
  27%, 100% { opacity: 1; transform: none; }
}

@keyframes serve-r {
  0% { opacity: 0; transform: translateX(95%); animation-timing-function: cubic-bezier(0.16, 0.8, 0.3, 1); }
  27%, 100% { opacity: 1; transform: none; }
}

@keyframes spin-l {
  0% { transform: rotate(-150deg); animation-timing-function: cubic-bezier(0.16, 0.8, 0.3, 1); }
  27% { transform: rotate(-8deg); }
  100% { transform: rotate(22deg); }
}

@keyframes spin-r {
  0% { transform: rotate(150deg); animation-timing-function: cubic-bezier(0.16, 0.8, 0.3, 1); }
  27% { transform: rotate(8deg); }
  100% { transform: rotate(-22deg); }
}

/* text turns opaque well before it stops moving, so nothing in the reading zone is left half-faded */
@keyframes text-l {
  0%, 5% { opacity: 0; transform: translateX(40px); }
  17% { opacity: 1; }
  29%, 100% { opacity: 1; transform: none; }
}

@keyframes text-r {
  0%, 5% { opacity: 0; transform: translateX(-40px); }
  17% { opacity: 1; }
  29%, 100% { opacity: 1; transform: none; }
}

/* drinks: the drink is set down first, then its name lands; the right column runs a beat later,
   and the drink keeps drifting up a touch */
@keyframes drink-in {
  0%, 5% { opacity: 0; transform: translateY(-34%) rotate(-9deg) scale(0.86); animation-timing-function: cubic-bezier(0.2, 0.8, 0.3, 1); }
  27% { opacity: 1; transform: none; }
  100% { opacity: 1; transform: translateY(var(--drift, -4%)); }
}

@keyframes drink-in-lag {
  0%, 11% { opacity: 0; transform: translateY(-34%) rotate(9deg) scale(0.86); animation-timing-function: cubic-bezier(0.2, 0.8, 0.3, 1); }
  33% { opacity: 1; transform: none; }
  100% { opacity: 1; transform: translateY(var(--drift, -4%)); }
}

@keyframes drink-text {
  0%, 14% { opacity: 0; transform: translateY(14px); }
  30%, 100% { opacity: 1; transform: none; }
}

@keyframes drink-text-lag {
  0%, 20% { opacity: 0; transform: translateY(14px); }
  36%, 100% { opacity: 1; transform: none; }
}

/* price rows: name in, dotted leader draws across, price lands */
@keyframes row-name {
  0% { opacity: 0; transform: translateX(-16px); }
  12%, 100% { opacity: 1; transform: none; }
}

@keyframes row-dots {
  0%, 4% { clip-path: inset(-2px 100% -2px 0); }
  18%, 100% { clip-path: inset(-2px 0 -2px 0); }
}

@keyframes row-price {
  0%, 8% { opacity: 0; transform: translateX(16px); }
  18%, 100% { opacity: 1; transform: none; }
}

@keyframes pop {
  0% { opacity: 0; transform: translateY(34px) scale(0.95); }
  22%, 100% { opacity: 1; transform: none; }
}

@keyframes pop-lag {
  0%, 6% { opacity: 0; transform: translateY(34px) scale(0.95); }
  28%, 100% { opacity: 1; transform: none; }
}

@keyframes foot-mascot {
  from { transform: translateY(75%); }
  to { transform: none; }
}

.hero__note a,
.foot__text a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
}
