/* ==========================================================================
   Bawbee - site styles
   Palette and radii are lifted straight from the app's asset catalogue so the
   site and the app cannot drift apart. Fredoka is the app's own display face.
   ========================================================================== */

/* --- Fonts ---------------------------------------------------------------- */

@font-face {
  font-family: 'Fredoka';
  src: url('../assets/fonts/Fredoka-Regular.ttf') format('truetype');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Fredoka';
  src: url('../assets/fonts/Fredoka-Medium.ttf') format('truetype');
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: 'Fredoka';
  src: url('../assets/fonts/Fredoka-SemiBold.ttf') format('truetype');
  font-weight: 600;
  font-display: swap;
}

/* Fraunces is variable: one file covers 300-700 plus the optical size,
   softness and wonk axes that give it its warmth. */
@font-face {
  font-family: 'Fraunces';
  src: url('../assets/fonts/Fraunces-latin.woff2') format('woff2');
  font-weight: 300 700;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Fraunces';
  src: url('../assets/fonts/Fraunces-latin-ext.woff2') format('woff2');
  font-weight: 300 700;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --- Tokens --------------------------------------------------------------- */

:root {
  /* Straight from Assets.xcassets/Palette */
  --cream: #fdf4da;
  --surface: #fffdf4;
  --sunken: #f5ebcf;
  --espresso: #3b2c1b;
  --espresso-soft: #7a6a55;
  --leaf: #5fa836;
  --leaf-deep: #3e7a20;
  --honey: #f5b62e;
  --honey-deep: #c88a14;
  --kraft: #c89b6b;
  --kraft-tint: #f1e2c8;
  --tomato: #de4f36;

  /* The app's own radii: chip 14, card 20, cta 28. Deliberately not one
     uniform value, which is the giveaway of a generated layout. */
  --r-chip: 14px;
  --r-card: 20px;
  --r-cta: 28px;

  --display: 'Fredoka', ui-rounded, system-ui, sans-serif;
  --text: 'Fraunces', Georgia, serif;

  --measure: 34ch;
  --gutter: clamp(20px, 5vw, 56px);
  --shell: 1180px;

  /* One spring, one snap, one unhurried ease. Nothing improvised per section. */
  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-settle: cubic-bezier(0.16, 1, 0.3, 1);
}

/* --- Reset ---------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

/* The bar is sticky, so a link to #faq would otherwise scroll the heading in
   underneath it. The bar is 67px tall at every width the nav keeps its full
   size, and this leaves a little air under it. */
section[id] {
  scroll-margin-top: 75px;
}

/* iOS paints a grey box over a tapped link by default, which looks nothing
   like the rest of this. */
a,
summary {
  -webkit-tap-highlight-color: rgba(200, 155, 107, 0.18);
}

body {
  margin: 0;
  background: var(--cream);
  color: var(--espresso);
  font-family: var(--text);
  font-size: clamp(17px, 1.15vw, 19px);
  line-height: 1.62;
  font-variation-settings: 'SOFT' 22, 'WONK' 0, 'opsz' 14;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

a {
  color: inherit;
}

h1,
h2,
h3,
h4 {
  font-family: var(--display);
  font-weight: 600;
  line-height: 1.04;
  letter-spacing: -0.015em;
  /* The app sets headings lower case. It is a voice, so the site keeps it. */
  text-transform: lowercase;
  margin: 0;
}

p {
  margin: 0;
}

/* --- Paper grain ---------------------------------------------------------- */
/* An feTurbulence tile over the whole page. About a kilobyte, and it is the
   cheapest thing that makes a screen read as printed rather than rendered. */

body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  opacity: 0.4;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.34'/%3E%3C/svg%3E");
}

/* --- Layout --------------------------------------------------------------- */

.shell {
  width: min(100% - (var(--gutter) * 2), var(--shell));
  margin-inline: auto;
}

section {
  position: relative;
}

.eyebrow {
  font-family: var(--display);
  font-weight: 500;
  font-size: 0.74rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--espresso-soft);
  margin-bottom: 18px;
  display: block;
}

.lede {
  max-width: var(--measure);
  color: var(--espresso-soft);
  font-size: 1.08em;
}

/* Hand-drawn underline. An SVG squiggle rather than a border, because a
   straight 2px rule under a word is the stock move. */
.marked {
  position: relative;
  white-space: nowrap;
}
.marked::after {
  content: '';
  position: absolute;
  left: -2%;
  right: -2%;
  bottom: -0.12em;
  height: 0.34em;
  background: no-repeat center/100% 100%
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 14' preserveAspectRatio='none'%3E%3Cpath d='M3 9.5c34-5 62-6.5 96-5.5 32 1 58 4 98 2' stroke='%23F5B62E' stroke-width='5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  z-index: -1;
}

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

.cta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.02rem;
  text-decoration: none;
  padding: 17px 30px;
  border-radius: var(--r-cta);
  /* Flat leaf green. No gradient on an interactive surface, ever. */
  background: var(--leaf);
  color: #fff;
  border: none;
  cursor: pointer;
  transition: transform 0.22s var(--ease-out), background 0.22s var(--ease-out),
    box-shadow 0.22s var(--ease-out);
  box-shadow: 0 2px 0 var(--leaf-deep);
}
.cta:hover {
  background: var(--leaf-deep);
  transform: translateY(-2px);
  box-shadow: 0 4px 0 #2f5c18;
}
.cta:active {
  transform: translateY(1px);
  box-shadow: 0 1px 0 var(--leaf-deep);
}

.cta--ghost {
  background: transparent;
  color: var(--espresso);
  box-shadow: inset 0 0 0 2px var(--kraft);
}
.cta--ghost:hover {
  background: var(--kraft-tint);
  color: var(--espresso);
  box-shadow: inset 0 0 0 2px var(--kraft);
  transform: translateY(-2px);
}

/* --- Nav ------------------------------------------------------------------ */

.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: color-mix(in srgb, var(--cream) 88%, transparent);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s var(--ease-out);
}
.nav.is-stuck {
  border-bottom-color: color-mix(in srgb, var(--kraft) 40%, transparent);
}
.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 14px 0;
}
.brand {
  display: flex;
  align-items: center;
  gap: 11px;
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.25rem;
  text-decoration: none;
  letter-spacing: -0.02em;
}
.brand img {
  width: 38px;
  height: 38px;
  border-radius: 10px;
}
.nav__links {
  display: flex;
  align-items: center;
  gap: 30px;
  font-family: var(--display);
  font-size: 0.95rem;
  font-weight: 500;
}
.nav__links a {
  text-decoration: none;
  color: var(--espresso-soft);
  transition: color 0.2s var(--ease-out);
}
.nav__links a:hover {
  color: var(--espresso);
}

/* --- Hero ----------------------------------------------------------------- */

/* The top padding is deliberately small. On a laptop the whole point of this
   section is that the badge and the proof line clear the fold; a tall hero
   pushed the call to action half off the bottom of a 1440x830 window. */
.hero {
  padding: clamp(20px, 3.2vw, 44px) 0 clamp(52px, 7vw, 96px);
  overflow: hidden;
}
.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
}
.hero h1 {
  font-size: clamp(2.5rem, 5vw, 3.9rem);
  margin-bottom: 20px;
}
.hero .lede {
  max-width: 40ch;
  font-size: 1.05em;
}
.hero__actions {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  margin-top: 28px;
}
.hero__note {
  font-family: var(--display);
  font-size: 0.86rem;
  font-weight: 500;
  color: var(--espresso-soft);
}

/* The App Store badge, unlinked until the app ships. Apple's guidelines say
   use their artwork unmodified, so it is dimmed by opacity rather than redrawn. */
.badge {
  display: inline-block;
  transition: opacity 0.2s var(--ease-out), transform 0.2s var(--ease-out);
}
.badge img {
  height: 54px;
  width: auto;
}
.badge[aria-disabled='true'] {
  opacity: 0.42;
  cursor: default;
  filter: saturate(0.4);
}

/* --- Phone ---------------------------------------------------------------- */
/* Drawn in CSS rather than pasted in as a mockup PNG, so it stays sharp and
   the screen inside it can be swapped on scroll. */

/* The whole device has to fit on the screen, or the phone runs off the bottom of
   a laptop and you never see the tab bar. The screenshots are 1320x2868, so a
   phone H tall is H x 0.4603 wide, which means capping the WIDTH against the
   height of the window is what controls how far down the page it reaches. The
   170px has to cover the sticky bar, and then the taller of the two things that
   sit above the phone: the hero's top padding, or a beat's, which is 128px when
   you land on it from a nav link. Measured at both. The plain min() first is
   the fallback for anything that does not understand svh. */
.phone,
.hero__stage {
  width: min(100%, 335px);
  width: min(100%, 335px, calc((100svh - 170px) * 0.4603));
}

.phone {
  position: relative;
  aspect-ratio: 1320 / 2868;
  margin-inline: auto;
  border-radius: 52px;
  padding: 11px;
  background: linear-gradient(160deg, #4a3925, #2b2013);
  box-shadow: 0 30px 70px -28px rgba(59, 44, 27, 0.55),
    0 2px 6px rgba(59, 44, 27, 0.2), inset 0 0 0 1px rgba(255, 255, 255, 0.12);
}
.phone__screen {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 42px;
  overflow: hidden;
  background: var(--cream);
}
.phone__screen img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}
/* Stacked screens for the scroll sequence. Only one is opaque at a time. */
.phone__screen img + img {
  opacity: 0;
}

.phone__glare {
  position: absolute;
  inset: 0;
  border-radius: 42px;
  pointer-events: none;
  background: linear-gradient(
    118deg,
    rgba(255, 255, 255, 0.16) 0%,
    rgba(255, 255, 255, 0) 38%
  );
}

/* --- Dealt cards (hero decoration) ---------------------------------------- */
/* Three meal chips that deal in around the phone like cards onto a table.
   They carry real numbers from the screenshot behind them. */

.deal {
  position: absolute;
  display: flex;
  align-items: center;
  gap: 11px;
  background: var(--surface);
  border-radius: var(--r-chip);
  padding: 11px 16px 11px 12px;
  /* A cream ring as well as a shadow: over a photographed screen a shadow
     alone is not enough to lift the chip off what is behind it. */
  box-shadow: 0 14px 30px -14px rgba(59, 44, 27, 0.45),
    0 0 0 4px color-mix(in srgb, var(--cream) 82%, transparent);
  font-family: var(--display);
  font-weight: 500;
  font-size: 0.92rem;
  white-space: nowrap;
  z-index: 3;
}
.deal span.emoji {
  font-size: 1.3rem;
  line-height: 1;
}
.deal span.price {
  color: var(--leaf-deep);
  font-weight: 600;
}
/* Hung off the phone's edges by a fraction of their own width, so they read as
   sitting on top of it without covering anything you are meant to read. The
   offsets are self-relative on purpose: tying them to the column instead put
   one chip over the greeting and pushed another off the side of the screen. */
.deal--a {
  top: 15%;
  left: 0;
  translate: -64% 0;
  rotate: -5deg;
}
/* The overhang is deliberately asymmetric. To the left there is the gap between
   the words and the phone to hang into; to the right there is only the edge of
   the page, and a bigger offset here gets the chip clipped on any viewport
   about as wide as the shell. */
.deal--b {
  top: 44%;
  right: 0;
  translate: 22% 0;
  rotate: 4deg;
}
.deal--c {
  bottom: 13%;
  left: 0;
  translate: -42% 0;
  rotate: 3deg;
}

/* The stage is the phone, so a percentage means a percentage of the phone. */
.hero__stage {
  position: relative;
  margin-inline: auto;
}
.hero__stage .phone {
  width: 100%;
}

/* --- Feature beats -------------------------------------------------------- */

.beat {
  padding: clamp(56px, 7vw, 100px) 0;
}
.beat .phone {
  width: min(100%, 335px, calc((100svh - 250px) * 0.4603));
}
.beat__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(36px, 6vw, 88px);
  align-items: center;
}
/* Alternating sides. A page where every row is text-left is a template. */
.beat--flip .beat__grid > *:first-child {
  order: 2;
}
.beat h2 {
  font-size: clamp(2rem, 3.9vw, 3.05rem);
  margin-bottom: 20px;
}
.beat__body {
  max-width: var(--measure);
}
.beat__body p + p {
  margin-top: 18px;
}

.notes {
  margin-top: 30px;
  display: grid;
  gap: 13px;
  padding: 0;
  list-style: none;
}
.notes li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: 0.97em;
  color: var(--espresso-soft);
}
.notes svg {
  flex: none;
  width: 21px;
  height: 21px;
  margin-top: 3px;
  color: var(--leaf);
}

/* --- FAQ ------------------------------------------------------------------ */

.faq {
  padding: clamp(60px, 8vw, 110px) 0;
  background: var(--sunken);
  border-block: 1px solid color-mix(in srgb, var(--kraft) 45%, transparent);
}
.faq__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr);
  gap: clamp(30px, 5vw, 70px);
  align-items: start;
}
.faq h2 {
  font-size: clamp(1.9rem, 3.6vw, 2.7rem);
}
details {
  border-bottom: 1px solid color-mix(in srgb, var(--kraft) 45%, transparent);
}
details:first-of-type {
  border-top: 1px solid color-mix(in srgb, var(--kraft) 45%, transparent);
}
summary {
  font-family: var(--display);
  font-weight: 500;
  font-size: 1.1rem;
  cursor: pointer;
  /* The padding belongs here, not on the details. On the details it padded the
     box while the tap target stayed the 28.5px of the text itself, under the
     24px WCAG 2.2 asks for and well under Apple's 44pt. The row is now ~68px. */
  padding: 20px 0;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
}
summary::-webkit-details-marker {
  display: none;
}
summary::after {
  content: '';
  flex: none;
  width: 13px;
  height: 13px;
  border-right: 2.5px solid var(--kraft);
  border-bottom: 2.5px solid var(--kraft);
  rotate: 45deg;
  transition: rotate 0.25s var(--ease-out);
  margin-right: 4px;
}
details[open] summary::after {
  rotate: 225deg;
}
details p {
  margin-top: 0;
  padding-bottom: 22px;
  color: var(--espresso-soft);
  max-width: 58ch;
  font-size: 0.97em;
}

/* --- Footer --------------------------------------------------------------- */

.footer {
  background: var(--espresso);
  color: var(--kraft-tint);
  padding: clamp(46px, 6vw, 72px) 0 34px;
  font-size: 0.94rem;
}
.footer a {
  color: var(--kraft-tint);
  text-decoration: none;
  opacity: 0.78;
  transition: opacity 0.2s var(--ease-out);
}
.footer a:hover {
  opacity: 1;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, 1fr));
  gap: 40px;
  padding-bottom: 36px;
  border-bottom: 1px solid rgba(241, 226, 200, 0.16);
}
.footer .brand {
  color: var(--cream);
  margin-bottom: 14px;
}
.footer__blurb {
  max-width: 32ch;
  opacity: 0.66;
  font-size: 0.94em;
}
.footer h4 {
  font-size: 0.76rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--honey);
  margin-bottom: 16px;
  font-weight: 500;
}
.footer ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  /* Was 11px with no padding, which made each link a 19px-tall target. The
     padding below carries the spacing now, so this comes down to match. */
  gap: 0;
}
.footer ul a {
  display: inline-block;
  padding: 7px 0;
}
.footer__base {
  padding-top: 26px;
  display: flex;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  font-size: 0.86rem;
  opacity: 0.62;
}

/* --- Legal / support pages ------------------------------------------------ */

.page {
  padding: clamp(46px, 6vw, 84px) 0 clamp(60px, 8vw, 110px);
}
.page__head {
  max-width: 60ch;
  margin-bottom: 26px;
}
.page__head h1 {
  font-size: clamp(2.3rem, 5vw, 3.4rem);
  margin-bottom: 18px;
}
.prose {
  max-width: 66ch;
}
.prose h2 {
  font-size: 1.5rem;
  margin: 46px 0 14px;
}
.prose h3 {
  font-size: 1.16rem;
  margin: 30px 0 10px;
}
.prose p,
.prose li {
  color: var(--espresso-soft);
}
.prose p + p,
.prose ul + p {
  margin-top: 16px;
}
.prose ul {
  margin: 14px 0 0;
  padding-left: 22px;
  display: grid;
  gap: 9px;
}
.prose a {
  color: var(--leaf-deep);
  text-underline-offset: 3px;
  text-decoration-skip-ink: auto;
}
.support-card a {
  color: var(--leaf-deep);
  text-underline-offset: 3px;
  text-decoration-skip-ink: auto;
}

/* A visible marker so nobody mistakes the placeholder wording for real terms. */
.placeholder-note {
  background: var(--kraft-tint);
  border-left: 4px solid var(--honey);
  border-radius: 0 var(--r-chip) var(--r-chip) 0;
  padding: 18px 22px;
  margin-bottom: 40px;
  font-size: 0.94em;
  max-width: 66ch;
}
.placeholder-note strong {
  font-family: var(--display);
  font-weight: 600;
}

.support-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 360px));
  gap: 20px;
  margin: 34px 0 10px;
}
.support-card {
  background: var(--surface);
  border-radius: var(--r-card);
  padding: 26px 24px;
  box-shadow: 0 16px 34px -28px rgba(59, 44, 27, 0.55);
}
.support-card h3 {
  font-size: 1.18rem;
  margin-bottom: 9px;
}
.support-card p {
  color: var(--espresso-soft);
  font-size: 0.95em;
}

/* --- Motion --------------------------------------------------------------- */
/* Hiding is gated on js-ready, which the head sets before the first paint. A
   browser with no JavaScript never gets the class, so it shows the page whole
   rather than a page of empty cream waiting for a script that will not run. */

.js-ready .reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.72s var(--ease-settle), transform 0.72s var(--ease-settle);
}
.js-ready .reveal.is-in {
  opacity: 1;
  transform: none;
}

/* Reduce Motion: travel goes, cross-fades stay. The same rule the app follows. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  /* Has to match the gated selector above or it loses on specificity. */
  .js-ready .reveal {
    transform: none;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.12s !important;
  }
}

/* --- Responsive ----------------------------------------------------------- */

@media (max-width: 940px) {
  .hero__grid,
  .beat__grid,
  .faq__grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .hero__grid {
    gap: 54px;
  }
  /* On one column the flip would put the picture above the words it explains. */
  .beat--flip .beat__grid > *:first-child {
    order: 0;
  }
  .beat__grid {
    gap: 44px;
  }
  .footer__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
  .nav__links {
    gap: 20px;
    font-size: 0.88rem;
  }
  /* Shrinking the links drops them under the 24px minimum, so they get a real
     target here. The brand image is taller, so the bar does not grow. */
  .nav__links a {
    display: inline-block;
    padding: 8px 0;
  }
}

@media (max-width: 560px) {
  /* The wordmark and both links have to share a 320px-wide bar at the worst
     case, so the brand gives up a little size to make room. */
  .nav__inner {
    gap: 12px;
  }
  .brand {
    font-size: 1.1rem;
    gap: 9px;
  }
  .brand img {
    width: 32px;
    height: 32px;
  }
  .nav__links {
    gap: 15px;
    font-size: 0.82rem;
  }

  /* The chips are dealt onto the top and bottom edges of the device rather than
     across its screen. On desktop they hang into the gap between the words and
     the phone; a phone has no such gap, so at their old offsets they lay over
     the screenshot and the first one covered the greeting outright. Straddling
     an edge keeps the dealt-card feel and leaves the screen readable. */
  .deal {
    font-size: 0.74rem;
    padding: 8px 12px 8px 9px;
    gap: 8px;
    box-shadow: 0 10px 22px -12px rgba(59, 44, 27, 0.45),
      0 0 0 3px color-mix(in srgb, var(--cream) 82%, transparent);
  }
  .deal span.emoji {
    font-size: 1.05rem;
  }
  /* Sits on the top edge, a little over half of it over the device. */
  .deal--a {
    top: auto;
    bottom: 100%;
    left: 0;
    translate: -5% 58%;
    rotate: -4deg;
  }
  /* The only one still over the screen. Kept low and hard right, where the
     screenshot is meal rows rather than the total. */
  .deal--b {
    top: auto;
    bottom: 26%;
    right: 0;
    translate: 14% 0;
    rotate: 4deg;
  }
  /* And this one hangs off the bottom-left corner. It is pushed far enough out
     that it only ever crosses the bezel, never the app's own tab bar, which
     otherwise looked like a mistake rather than a card lying on top. */
  .deal--c {
    bottom: 0;
    left: 0;
    translate: -20% 82%;
    rotate: 3deg;
  }

  .footer__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 32px;
  }
}

/* On a window this narrow the phone fills the column outright, so the only
   room left for a chip to hang into is the 20px gutter. The overhangs above
   are wider than that and got clipped at the page edge, so they come in.
   Only reachable on a tall 320px window; every 320px phone is short enough
   that the device is sized off the viewport height instead. */
@media (max-width: 360px) {
  .deal--b {
    translate: 6% 0;
  }
  .deal--c {
    translate: -12% 82%;
  }
}
