/* Fit for Love — homepage.
   Colour is the product's own day palette, never the comp's sampled pixels.
   Geometry is measured from the approved comp. */

:root {
  /* the day palette */
  --page:     #F8E9F0;
  --sheet:    #FCF3F7;
  --raised:   #FFFBFD;
  --ink:      #3B0F25;
  --ink-worn: #783B56;
  --you:      #D93DB4;   /* one partner */
  --partner:  #A051C4;   /* the other  */
  /* The two hues are display colours: at body size they fail 4.5:1 on the pale
     grounds, so small type uses these darkened siblings. The hue is kept and
     only the lightness moves, so the two-people coding still reads. */
  --you-text:     #B63397;   /* 4.58:1 */
  --partner-text: #954BB6;   /* 4.52:1 */
  --you-fill:     #CA39A7;   /* white label on it: 4.51:1 */

  /* an edge is light catching a surface, never a drawn line */
  --edge:     rgba(59, 15, 37, 0.10);
  --edge-strong: rgba(59, 15, 37, 0.22);

  /* one unit = one pixel of the 1536-wide comp */
  --u: calc(min(100vw, 1760px) / 1536);
  /* the width the hero actually occupies; the card is measured against it */
  --B: min(100vw, 1760px);
  /* 0 at rest, 1 once the page has been scrolled; set by home.js */
  --shrink: 0;

  /* Karla is the companion for controls and small chrome, which the comp sets
     in a sans. */
  /* EB Garamond is the display voice: it reaches the comp's 50.5px cap height
     where Baskervville could not, and its figures sit on the baseline. */
  --serif: 'EB Garamond', Georgia, 'Times New Roman', serif;
  --sans:  'Karla', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

body {
  background: var(--sheet);
  color: var(--ink);
  font-family: var(--serif);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection { background: rgba(217, 61, 180, 0.18); color: var(--ink); }

html { caret-color: var(--you-text); scrollbar-color: rgba(59,15,37,0.28) var(--sheet); scrollbar-width: thin; }

a { color: inherit; }

/* Read, never seen. The page's own statement is the equation, which rewrites
   itself as you scroll and so cannot be the heading; this names the page once
   for a crawler and a screen reader and occupies no space. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

/* ── the first viewport ─────────────────────────────────────────────── */

.hero {
  position: relative;
  width: 100%;
  aspect-ratio: 1536 / 1024;
  overflow: hidden;
  background:
    radial-gradient(115% 70% at 50% 40%, var(--page) 0%, rgba(248, 233, 240, 0) 72%),
    var(--sheet);
}

/* ── the hero is the map ────────────────────────────────────────────── */
/* The plate is 1536x1024 and so is the hero, which is why this can be a true
   full bleed: no crop, and a pin written as a percentage of the hero lands on
   exactly the feature it was placed on. The layer takes no z-index on purpose
   — it must not open a stacking context, or the pin cards inside it could
   never rise over the line and the form that follow them. */

.hero__map { position: absolute; inset: 0; }

.hero__map-img {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* The ground the line and the form sit on. It was a linear fade, which is a
   band: parallel edges the full width of the page, and the eye reads the top
   of it as a drawn line across the map. An ellipse rising from the foot has no
   edge to find — it is only ever light pooling where the text is.
   z-index 1 keeps it over the plate and under the pins, which would otherwise
   be washed out by it wherever one sits low on the map. */
.hero__map::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(60% 30% at 50% 97%,
      rgba(252, 243, 247, 0.98) 0%,
      rgba(252, 243, 247, 0.9) 40%,
      rgba(252, 243, 247, 0.5) 68%,
      rgba(252, 243, 247, 0) 88%),
    linear-gradient(to bottom, var(--sheet) 0%, rgba(252, 243, 247, 0) 13%);
}


/* ── header ─────────────────────────────────────────────────────────── */

/* Layering in the hero, bottom to top: the plate (0), the wash that gives the
   foot its ground (1), the map's labels (2), and the page's own furniture —
   wordmark, line, form — above all of it (3). */
.hero__head {
  position: absolute;
  z-index: 3;
  left: 1.95%; top: 1.17%; right: 1.82%;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}

.wordmark {
  font-size: calc(27 * var(--u));
  line-height: 1;
  letter-spacing: 0;
  color: var(--ink);
  text-decoration: none;
}

.navlink {
  font-family: var(--sans);
  font-size: calc(15 * var(--u));
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--ink);
  text-decoration: none;
  /* the link's ink is ~17px tall; the hit area must clear 24px */
  padding: 6px 2px;
  margin: -6px -2px;
  border-bottom: 1px solid transparent;
  transition: border-color 220ms ease-out;
}
.navlink:hover,
.navlink:focus-visible { border-bottom-color: rgba(59, 15, 37, 0.35); }

/* ── the equation, and the bar it floats in ─────────────────────────── */

/* ── the top: one floating group, lattice and card together ─────────── */
/* It is fixed above the whole page from the first pixel, it never hands off to
   a second element, and scrolling only makes it smaller. The lattice travels
   with the card because it is part of the same object, not hero decoration. */

.top {
  position: fixed;
  z-index: 60;
  left: 50%;
  top: calc(var(--B) * 0.0720);
  width: calc(var(--B) * 0.8000);
  height: calc(var(--B) * 0.1550);
  margin-left: calc(var(--B) * -0.4000);
  transform-origin: 50% 0;
  /* driven continuously by scroll, so there is no step between the two sizes */
  transform:
    translateY(calc(var(--B) * -0.0984 * var(--shrink)))
    scale(calc(1 - 0.24 * var(--shrink)));
  will-change: transform;
  pointer-events: none;   /* it floats over the page without swallowing clicks */
}

.top__lattice {
  position: absolute;
  inset: 0;
  /* the rules, then a translucent pane beneath them. The mask fades pane and
     rules together, so the whole panel dissolves into the page as one thing,
     and the page stays partly readable through it. */
  background:
    repeating-linear-gradient(to right,  rgba(217, 61, 180, 0.22) 0 1px, transparent 1px calc(100% / 12)),
    repeating-linear-gradient(to bottom, rgba(217, 61, 180, 0.22) 0 1px, transparent 1px calc(100% / 4)),
    linear-gradient(rgba(255, 252, 254, 0.72), rgba(255, 252, 254, 0.72));
  -webkit-backdrop-filter: blur(12px) saturate(1.08);
          backdrop-filter: blur(12px) saturate(1.08);
  /* An ellipse whose radii stay INSIDE the box, so the fade actually reaches
     zero before the element's rectangle and no straight edge can show.
     Percentage radii are measured from the centre: anything over 50% finishes
     off-box and leaves a hard edge, which is what 74%/62% was doing. The ramp
     starts early and is fully out by 86%, so the panel reads as a soft round
     pool rather than a panel with corners. */
  -webkit-mask-image: radial-gradient(46% 48% at 50% 50%,
              rgba(0,0,0,1) 0%, rgba(0,0,0,0.94) 22%,
              rgba(0,0,0,0.48) 58%, rgba(0,0,0,0) 86%);
          mask-image: radial-gradient(46% 48% at 50% 50%,
              rgba(0,0,0,1) 0%, rgba(0,0,0,0.94) 22%,
              rgba(0,0,0,0.48) 58%, rgba(0,0,0,0) 86%);
}

.equation-bar {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--B) * 0.6400);
  height: calc(var(--B) * 0.0545);
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  padding: 6px 22px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.97);
  -webkit-backdrop-filter: blur(16px) saturate(1.15);
          backdrop-filter: blur(16px) saturate(1.15);
  box-shadow:
    0 calc(14 * var(--u)) calc(38 * var(--u)) calc(-14 * var(--u)) rgba(59, 15, 37, 0.20),
    0 calc(3 * var(--u))  calc(10 * var(--u)) calc(-5 * var(--u))  rgba(59, 15, 37, 0.08);
  -webkit-mask-image: radial-gradient(96% 300% at 50% 50%, #000 82%, transparent 100%);
          mask-image: radial-gradient(96% 300% at 50% 50%, #000 82%, transparent 100%);
}

.equation {
  margin: 0;
  font-size: calc(63 * var(--u));
  line-height: 1;
  letter-spacing: -0.004em;
  white-space: nowrap;
  /* the comp's numeral sits on the baseline, not below it */
  font-variant-numeric: lining-nums;
  font-feature-settings: 'lnum' 1;
}

.equation__count  { color: var(--you); }
.equation__unit,
.equation__eq     { color: var(--ink); }
.equation__reward { color: var(--partner); }

/* ── the line beneath ───────────────────────────────────────────────── */

.subline {
  position: absolute;
  z-index: 3;
  /* The comp put this in the middle of the hero, which was empty then. Over a
     map that spot is the busiest part of the plate and the line disappears
     into the trees, so it moves down to join the form on the wash. */
  left: 50%; top: 77%;
  transform: translateX(-50%);
  /* it lies over a live map: a paragraph box is invisible and would still
     swallow a pin underneath it */
  pointer-events: none;
  margin: 0;
  width: 46%;
  text-align: center;
  font-size: calc(18 * var(--u));
  line-height: 1.45;
  color: var(--ink-worn);
}

/* ── the waitlist ───────────────────────────────────────────────────── */

.waitlist {
  /* The comp had this at 91.41%, which a 1440x900 window cuts in half now the
     hero is a 3:2 plate rather than the comp's own frame. It sits with the
     line instead, and the whole group clears the fold. */
  position: absolute;
  z-index: 3;
  left: 37.11%; top: 85.5%; width: 25.46%;
  height: calc(34 * var(--u));
  display: flex;
  align-items: stretch;
  gap: calc(8 * var(--u));
}

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

.waitlist__hp {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  opacity: 0;
}

.waitlist__input {
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  padding: 0 calc(22 * var(--u));
  font-family: var(--sans);
  font-size: calc(11 * var(--u));
  line-height: 1.2;
  color: var(--ink);
  background: var(--raised);
  border: 1px solid var(--edge);
  border-radius: 999px;
}
.waitlist__input::placeholder { color: #6E3550; opacity: 1; }
.waitlist__input:focus-visible {
  outline: 2px solid var(--you);
  outline-offset: calc(2 * var(--u));
  border-color: transparent;
}

.waitlist__submit {
  flex: 0 0 auto;
  width: calc(135 * var(--u));
  height: 100%;
  padding: 0;
  font-family: var(--sans);
  font-weight: 500;
  font-size: calc(12 * var(--u));
  letter-spacing: 0.01em;
  line-height: 1.2;
  color: #FFFFFF;
  /* lifted by light, like every other surface here */
  background: linear-gradient(180deg, var(--you-fill) 0%, #BC3499 55%, #A82B88 100%);
  box-shadow:
    0 calc(6 * var(--u)) calc(16 * var(--u)) calc(-6 * var(--u)) rgba(217, 61, 180, 0.45),
    inset 0 1px 0 rgba(255, 255, 255, 0.30);
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  transition: background-color 200ms ease-out, transform 200ms ease-out;
}
.waitlist__submit:hover { background: #B22E93; }
.waitlist__submit:active { transform: translateY(1px); }
.waitlist__submit:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: calc(2 * var(--u));
}

/* ── the rest of the page ───────────────────────────────────────────── */
/* Beyond the first viewport the layout stops being measured against the comp
   and becomes fluid: the comp fixed the world, not the whole scroll. Type
   returns to rem so it stays readable when the window is not 1536 wide. */

section {
  padding: clamp(60px, 6.5vw, 108px) clamp(24px, 6vw, 80px);
  /* the card floats over everything, so an anchored heading must not land under it */
  scroll-margin-top: calc(var(--B) * 0.075);
}

/* The comp is a centred, full-width composition. Left-aligning a 60ch measure
   inside a 1200px field leaves the right half dead, so every block is centred
   on the page and the text keeps its own comfortable measure. */
.packs { display: flex; flex-direction: column; align-items: center; text-align: center; }
.packs > * { width: 100%; max-width: 72ch; }
.packs > 
/* Each section is its own room, so the scroll has a rhythm instead of one
   continuous ground: the calmest surface explains, the night room holds the
   packs, and the close returns to light. */






/* the approval is the product, so it gets the weight */

.foot { background: var(--raised); }

.packs__lede {
  margin: 20px auto 0;
  max-width: 54ch;
  text-wrap: pretty;
  font-family: var(--sans);
  font-size: 1.15rem;
  line-height: 1.6;
  color: var(--ink-worn);
}




/* ── the packs ──────────────────────────────────────────────────────── */







/* ── the close ──────────────────────────────────────────────────────── */

.close {
  background:
    radial-gradient(90% 120% at 50% 0%, var(--page) 0%, rgba(248, 233, 240, 0) 70%),
    var(--sheet);
  text-align: center;
}

.close__title { margin-inline: auto; max-width: 18ch; }

.close__t {
  margin: 22px auto 0;
  text-wrap: pretty;
  max-width: 48ch;
  font-family: var(--serif);
  font-size: clamp(1.1rem, 1.7vw, 1.4rem);
  line-height: 1.55;
  color: var(--ink-worn);
}

.waitlist--close {
  position: static;
  width: min(440px, 100%);
  height: auto;
  margin: clamp(32px, 4vw, 48px) auto 0;
  gap: 10px;
}
.waitlist--close .waitlist__input { height: 52px; padding: 0 22px; font-size: 1rem; }
.waitlist--close .waitlist__submit { width: auto; height: 52px; padding: 0 26px; font-size: 0.95rem; }

.close__honest {
  margin: 26px auto 0;
  max-width: 52ch;
  font-family: var(--sans);
  font-size: 0.92rem;
  line-height: 1.65;
  color: var(--ink-worn);
}

/* ── foot ───────────────────────────────────────────────────────────── */

.foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  padding: 30px clamp(24px, 8vw, 160px) 42px;
  border-top: 1px solid var(--edge);
  background: var(--sheet);
  font-family: var(--sans);
  font-size: 0.9rem;
  color: var(--ink-worn);
}

.foot__mark { font-family: var(--serif); font-size: 1.05rem; color: var(--ink); }
.foot__nav { display: flex; gap: 26px; }
.foot__nav a {
  color: var(--ink-worn);
  text-decoration: none;
  padding: 6px 2px;
  margin: -6px -2px;
  border-bottom: 1px solid transparent;
}
.foot__nav a:hover, .foot__nav a:focus-visible { border-bottom-color: var(--edge-strong); }

/* ── the equation keeps rewriting itself ────────────────────────────── */

.equation__count,
.equation__unit,
.equation__reward {
  display: inline-block;
  transition: opacity 210ms cubic-bezier(0.4, 0, 0.2, 1),
              transform 210ms cubic-bezier(0.4, 0, 0.2, 1),
              text-shadow 460ms ease-out;
}

/* the old value falls away downward */
.is-out .equation__count,
.is-out .equation__unit,
.is-out .equation__reward {
  opacity: 0;
  transform: translateY(0.42em);
}

/* the new value is placed above, then released into position */
.is-in .equation__count,
.is-in .equation__unit,
.is-in .equation__reward {
  opacity: 0;
  transform: translateY(-0.42em);
  transition: none;
}

/* and it lights briefly as it lands, each half in its own hue */
.is-glow .equation__count,
.is-glow .equation__reward {
  text-shadow: 0 0 0.42em currentColor;
}



/* ── what the form says back ────────────────────────────────────────── */

.waitlist__note {
  margin: 12px 0 0;
  min-height: 1.4em;
  font-family: var(--sans);
  font-size: 0.92rem;
  line-height: 1.45;
  color: var(--ink-worn);
}
.waitlist__note.is-good { color: var(--partner-text); }
.waitlist__note.is-bad  { color: #C4304A; }

.hero .waitlist__note {
  position: absolute;
  left: 37.11%; top: calc(91.41% + 42 * var(--u));
  width: 25.46%;
  margin: 0;
  font-size: calc(12 * var(--u));
}

.waitlist__submit:disabled { opacity: 0.6; cursor: default; }


/* ── other viewports ────────────────────────────────────────────────── */

.hero { max-width: 1760px; margin-inline: auto; }

/* Tablet: the measured hero still holds proportionally, but the sum needs
   room to breathe before it is allowed to wrap. */
@media (max-width: 1240px) {
  .equation { font-size: calc(72 * var(--u)); }
  .subline  { width: 62%; font-size: calc(20 * var(--u)); }
}

/* Phone: the comp's absolute geometry is abandoned deliberately. Holding a
   1536x1024 frame at 390px would render the equation at 18px — technically
   faithful and practically unreadable. The page becomes flow instead, and the
   equation keeps the largest type on the screen, which is the actual promise. */
@media (max-width: 820px) {
  /* The comp's absolute geometry is abandoned deliberately here: holding a
     1536x1024 frame at 390px would render the equation at 18px — faithful and
     unreadable. The page becomes flow, and the card stays the top card. */
  .hero {
    aspect-ratio: auto;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: clamp(24px, 6vw, 40px);
    padding: calc(104px + 6vw) 20px clamp(40px, 10vw, 64px);
    background:
      radial-gradient(140% 46% at 50% 30%, var(--page) 0%, rgba(248, 233, 240, 0) 76%),
      var(--sheet);
  }

  /* still the top group, still over everything — only compact and static */
  .top {
    top: calc(8px + 2vw);
    left: 14px;
    width: calc(100% - 28px);
    height: auto;
    margin-left: 0;
    transform: none;
  }
  .top__lattice { display: none; }
  .equation-bar {
    position: static;
    width: 100%;
    height: auto;
    transform: none;
    padding: 16px 16px;
    border-radius: 24px;
    -webkit-mask-image: none;
            mask-image: none;
    box-shadow: 0 18px 44px -22px rgba(59, 15, 37, 0.30);
  }

  .equation {
    font-size: clamp(1.55rem, 6.6vw, 2.3rem);
    line-height: 1.14;
    white-space: normal;
    text-align: center;
    text-wrap: balance;
  }

  .hero__head { position: static; order: -1; }
  .wordmark { font-size: 1.3rem; }
  .navlink  { font-size: 0.9rem; }

  .subline {
    position: static;
    transform: none;
    width: 100%;
    max-width: 34ch;
    margin-inline: auto;
    font-size: 1rem;
  }

  /* The map joins the flow rather than lying behind it. Full bleed under a
     column of text is a desktop move: at 390px the plate would be behind the
     line and the form at the size of a stamp, and neither would be readable
     over it. Here it is simply the thing between them, the way the photograph
     it replaced was. */
  .hero__map {
    position: relative;
    inset: auto;
    order: 1;
    width: 100%;
    aspect-ratio: 1536 / 1024;
  }
  .hero__map-img { border-radius: 14px; }
  .hero__map::after { border-radius: 14px; background: none; }

  /* the column's order, now that the map is one of its items */
  .subline      { order: 0; }
  .hero .waitlist { order: 2; }

  .hero .waitlist {
    position: static;
    width: 100%;
    max-width: 420px;
    height: auto;
    margin-inline: auto;
    flex-wrap: wrap;
  }
  .hero .waitlist__input  { height: 50px; padding: 0 20px; font-size: 1rem; flex: 1 1 12ch; }
  .hero .waitlist__submit { width: auto; height: 50px; padding: 0 22px; font-size: 0.95rem; flex: 0 0 auto; }
  .hero .waitlist__note {
    position: static;
    width: 100%;
    margin-top: 10px;
    font-size: 0.9rem;
    text-align: center;
  }

  
}

/* ── the packs: its own room ────────────────────────────────────────── */
/* The night half of the product's palette, which this site had never used.
   A different environment, not a different system: these are the same tokens
   the app ships after dark. Scoped here so nothing leaks out of the section. */

.packs {
  /* The nineteen reveals are absolutely positioned and centred on their chip,
     so the ones at the right of a row hang past the edge even while closed.
     Absolute boxes still count toward scrollable overflow, so that handed the
     whole document a horizontal scroll — and a fixed element sized in percent
     then measures itself against the widened page, which is what was clipping
     the equation card off the right of every phone. Clipped, not hidden: hidden
     would make this a scroll container and cost the page its sticky behaviour,
     and clip leaves the vertical axis alone. The open panel is kept inside the
     viewport by the nudge in home.js, so nothing legible is ever cut. */
  overflow-x: clip;

  /* the day palette's deeper end — floor and sunken, which the rest of the
     page never uses, so this room is distinctly warmer without leaving the
     system or going dark */
  --n-page:    #F4CFE0;
  --n-burn:    #E8B9D4;
  --n-floor:   #F3E1EB;
  --n-raised:  #FFFBFD;
  --n-ink:     #3B0F25;
  --n-worn:    #783B56;
  --n-you:     #D93DB4;
  --n-partner: #A051C4;
  --n-edge:    rgba(59, 15, 37, 0.10);

  position: relative;
  isolation: isolate;
  color: var(--n-ink);
  background:
    radial-gradient(120% 62% at 50% 46%, var(--n-burn) 0%, rgba(232, 185, 212, 0) 70%),
    linear-gradient(var(--n-page) 0%, var(--n-floor) 100%);
  padding-block: clamp(84px, 9vw, 148px);
}

.packs__title { color: var(--n-ink); }
.packs__lede  { color: var(--n-worn); }

.packlist {
  list-style: none;
  margin: clamp(40px, 4.5vw, 68px) auto 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
  max-width: 78ch;
}

/* Each pack floats: no drawn edge, only light on a dark ground. */
.pack { position: relative; }

.pack__btn {
  font-family: var(--serif);
  font-size: 1.12rem;
  line-height: 1.2;
  color: var(--n-ink);
  background: var(--n-raised);
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 13px 24px;
  box-shadow: 0 1px 2px rgba(59, 15, 37, 0.06),
              0 10px 22px -16px rgba(59, 15, 37, 0.45);
  cursor: pointer;
  transition: transform 260ms cubic-bezier(0.2, 0.8, 0.2, 1),
              background-color 260ms ease-out,
              box-shadow 260ms ease-out;
}

.pack__btn:hover,
.pack__btn:focus-visible,
.pack.is-open .pack__btn {
  transform: translateY(-3px);
  background: #FFFFFF;
  box-shadow: 0 18px 38px -16px rgba(59, 15, 37, 0.30),
              0 0 0 1px rgba(217, 61, 180, 0.30);
  outline: none;
}

/* The reveal sits over the field rather than in it, so opening one pack never
   reflows the other eighteen. */
.pack__reveal {
  position: absolute;
  z-index: 3;
  top: calc(100% + 10px);
  left: 50%;
  /* --nudge is set by home.js only when centring would put the panel off the
     screen; it is 0 for the chips that sit comfortably inside a row. */
  translate: calc(-50% + var(--nudge, 0px)) 0;
  width: max-content;
  max-width: min(19rem, 74vw);
  padding: 16px 20px;
  border-radius: 20px;
  background: var(--n-raised);
  /* lifted by light, not separated by an outline */
  box-shadow: 0 1px 2px rgba(59, 15, 37, 0.08),
              0 26px 56px -22px rgba(59, 15, 37, 0.38);
  opacity: 0;
  transform: translateY(-6px) scale(0.97);
  transform-origin: 50% 0;
  pointer-events: none;
  transition: opacity 220ms ease-out, transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.pack:hover .pack__reveal,
.pack:focus-within .pack__reveal,
.pack.is-open .pack__reveal {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}

.pack__reveal ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 7px;
  text-align: left;
}

.pack__reveal li {
  font-family: var(--sans);
  font-size: 0.92rem;
  line-height: 1.45;
  color: var(--n-worn);
}
.pack__reveal li::before {
  content: "";
  display: inline-block;
  width: 0.42em; height: 0.42em;
  margin-right: 0.6em;
  border-radius: 50%;
  background: var(--n-partner);
  vertical-align: 0.12em;
}

@media (max-width: 620px) {
  .pack__btn { font-size: 1rem; padding: 11px 18px; }
  .pack__reveal { max-width: min(17rem, 82vw); }
}


/* ── the streak ─────────────────────────────────────────────────────── */
/* Three layers, each saying a different thing: the flame says SHARED, the grid
   says DURATION, the number says HOW LONG.

   The flame is pinned and scrubbed by scroll while the copy moves past it, so
   the two must never share a column — a sticky graphic with text running
   through it collides on every frame, whatever the z-index says. Desktop puts
   them side by side; narrow screens stack them and give the pinned half its own
   ground so nothing shows through. */

.streak {
  position: relative;
  background:
    radial-gradient(90% 60% at 50% 30%, var(--page) 0%, rgba(248, 233, 240, 0) 72%),
    var(--sheet);
  padding: clamp(60px, 6.5vw, 108px) clamp(24px, 6vw, 80px);
}

.streak__inner {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  gap: clamp(32px, 5vw, 88px);
  align-items: stretch;
  max-width: 1180px;
  margin-inline: auto;
}

.streak__stage {
  /* The column is full height so the pin inside it has somewhere to travel.
     Sticky on the grid item itself does nothing: align-items shrinks the item
     to its own content and a sticky box with no room simply scrolls away. */
  position: relative;
}

.streak__pin {
  position: sticky;
  /* clears the floating card, which is fixed above everything at z-index 60 */
  top: clamp(112px, 15vh, 190px);
  height: min(56vh, 500px);
  display: grid;
  place-items: center;
}

.streak__flame,
.streak__still {
  /* let the intrinsic 560x784 decide the shape and simply fit the box */
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  /* a grid item's automatic minimum is its intrinsic size, which would stop
     max-height clamping the canvas to the pin */
  min-width: 0;
  min-height: 0;
  filter: drop-shadow(0 26px 44px rgba(217, 61, 180, 0.22));
}

.streak__copy {
  /* The copy is what gives the pin somewhere to travel: without real height
     here the flame releases after a few hundred pixels and never scrubs. Each
     block gets room, and the reveals are paced against that. */
  min-height: 210vh;
  padding-block: clamp(40px, 12vh, 140px) clamp(60px, 16vh, 200px);
  display: grid;
  align-content: space-between;
  gap: clamp(40px, 8vh, 90px);
  text-align: left;
}

/* three beats, not six orphans: the travel belongs between the groups, and the
   lines inside a group stay tight to each other */
.streak__beat { display: grid; gap: clamp(14px, 1.6vw, 22px); }

.streak__title {
  margin: 0;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.9rem, 3.6vw, 3rem);
  line-height: 1.12;
  letter-spacing: -0.012em;
  color: var(--ink);
  text-wrap: balance;
}

.streak__lede {
  margin: 0;
  max-width: 46ch;
  font-family: var(--sans);
  font-size: 1.1rem;
  line-height: 1.62;
  color: var(--ink-worn);
  text-wrap: pretty;
}

/* The 52 weeks, as four rows of thirteen — quarters. Wrapping them freely made
   a ragged block that read as a texture; a fixed thirteen reads as a year, and
   the wider gap between rows lets each quarter be seen. The gaps within are the
   point and are drawn, never hidden. */
.weeks {
  list-style: none;
  display: grid;
  /* an explicit track: 1fr inside a fit-content container has nothing to size against */
  grid-template-columns: repeat(13, clamp(13px, 1.3vw, 19px));
  column-gap: clamp(4px, 0.5vw, 7px);
  row-gap: clamp(9px, 1.1vw, 15px);
  margin: 0;
  padding: 0;
  width: fit-content;
  max-width: 100%;
}

.wk {
  width: 100%;
  aspect-ratio: 1;
  border-radius: 4px;
  background: rgba(59, 15, 37, 0.07);
  opacity: 0;
  transform: scale(0.6);
  transition: opacity 260ms ease-out, transform 320ms cubic-bezier(0.2, 0.8, 0.2, 1),
              background-color 260ms ease-out;
  transition-delay: calc(var(--i) * 9ms);
}

.weeks.is-on .wk { opacity: 1; transform: scale(1); }
.weeks.is-on .wk.is-on { background: var(--you-text); }
.weeks.is-on .wk:nth-last-child(-n+7).is-on { background: var(--you); }

.weeks__key {
  margin: -12px 0 0;
  font-family: var(--sans);
  font-size: 0.92rem;            /* {typography.caption} */
  line-height: 1.65;
  color: var(--ink-worn);
}
.weeks__swatch {
  display: inline-block;
  width: 10px; height: 10px;
  border-radius: 3px;
  background: var(--you-text);
  vertical-align: -1px;
}
.weeks__swatch--off { background: rgba(59, 15, 37, 0.12); }

.streak__count {
  margin: 0;
  font-family: var(--serif);
  font-size: clamp(1.9rem, 3.6vw, 2.9rem);
  line-height: 1.1;
  color: var(--ink);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 420ms ease-out, transform 420ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.streak.is-counted .streak__count { opacity: 1; transform: none; }
.streak__n { color: var(--you); }

.streak__note {
  margin: 0;
  max-width: 44ch;
  font-family: var(--sans);
  font-size: 0.92rem;            /* {typography.caption} */
  line-height: 1.65;
  color: var(--ink-worn);
}

@media (max-width: 900px) {
  .streak__inner { grid-template-columns: 1fr; gap: 0; }

  /* One cell, two layers — not two rows. Stacked, the stage is only as tall as
     the flame it holds, so the sticky pin inside it has nowhere to travel and
     releases on the first screen: the section then runs its remaining 165vh
     with nothing held on the screen at all, which is how the phone lost the
     one mechanic the section exists for. Sharing the cell hands the stage the
     copy's full height, the same way `align-items: stretch` does on the wide
     layout, and the copy reads underneath the flame as it goes. */
  .streak__stage,
  .streak__copy { grid-area: 1 / 1; }
  .streak__stage { z-index: 2; pointer-events: none; }
  .streak__copy  { z-index: 1; }

  .streak__pin {
    top: calc(92px + 6vw);
    height: min(32vh, 300px);
    /* its own ground, so copy passing behind it never shows through */
    background:
      radial-gradient(70% 120% at 50% 45%, var(--page) 0%, var(--sheet) 72%);
    margin-inline: calc(clamp(24px, 6vw, 80px) * -1);
    padding-inline: clamp(24px, 6vw, 80px);
  }

  .streak__copy {
    min-height: 165vh;
    /* the first beat starts clear of the flame's resting place rather than
       underneath it */
    padding-block: calc(92px + 6vw + min(32vh, 300px) + 3vh) clamp(40px, 12vh, 90px);
    text-align: left;
  }
  .weeks { column-gap: 4px; row-gap: 8px; }
}

/* ── the archive ────────────────────────────────────────────────────── */
/* The mechanic is the message: the wall fills as you read it, because this is
   the one part of the product that improves purely with time. Nothing else on
   the page grows while you look at it. */

.archive {
  background: var(--raised);
  padding: clamp(72px, 8vw, 130px) clamp(24px, 6vw, 80px) clamp(60px, 6.5vw, 108px);
}

.archive__head { max-width: 62ch; margin-inline: auto; text-align: center; }

.archive__title {
  margin: 0;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(2rem, 4.2vw, 3.4rem);
  line-height: 1.12;
  letter-spacing: -0.012em;
  color: var(--ink);
  text-wrap: balance;
}

.archive__lede {
  margin: 20px auto 0;
  max-width: 54ch;
  font-family: var(--sans);
  font-size: 1.15rem;
  line-height: 1.6;
  color: var(--ink-worn);
  text-wrap: pretty;
}

.wall {
  margin: clamp(44px, 5vw, 76px) auto 0;
  max-width: 1120px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: clamp(16px, 2vw, 30px);
}

.print {
  margin: 0;
  opacity: 0;
  transform: translateY(22px) scale(0.96);
  transition: opacity 520ms ease-out, transform 620ms cubic-bezier(0.2, 0.8, 0.2, 1);
  transition-delay: calc(var(--i) * 70ms);
}

.archive.is-filling .print { opacity: 1; transform: none; }

.print img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 14px;
  background: var(--sunken, #F3E1EB);
  box-shadow: 0 1px 2px rgba(59, 15, 37, 0.06),
              0 16px 34px -22px rgba(59, 15, 37, 0.5);
}

.print figcaption {
  margin-top: 10px;
  font-family: var(--sans);
  font-size: 0.9rem;
  line-height: 1.45;
  color: var(--ink-worn);
}

/* every third print sits a little low, so the wall is kept rather than laid out */
.print:nth-child(3n+2) { margin-top: clamp(14px, 2vw, 30px); }

.archive__note {
  margin: clamp(34px, 4vw, 54px) auto 0;
  max-width: 52ch;
  text-align: center;
  font-family: var(--sans);
  font-size: 0.92rem;            /* {typography.caption} */
  line-height: 1.65;
  color: var(--ink-worn);
}

@media (max-width: 620px) {
  .wall { grid-template-columns: repeat(2, 1fr); gap: 14px; }
  .print:nth-child(3n+2) { margin-top: 0; }
  .print:nth-child(even) { margin-top: 18px; }
}

/* ── the map ────────────────────────────────────────────────────────── */
/* Not a live map: a real one needs a key, a bill and a location, and a map of
   nowhere would be a lie told with someone else's tiles. An authored plate is
   honest about being an illustration. Live partner location was cut from the
   product and must never appear here.

   It is the first thing on the page rather than a section further down. The
   claim the page opens with is that this is where the two of them actually
   went, and the sum floats over it. One surface, two layers — a plain mark
   for somewhere they train, a photograph for something they earned there.
   The two are told apart by form and never by hue: magenta and violet are
   spoken for on this page, they mean the two people, and a third meaning
   would break that. */

/* The legend the map needs, in a strip directly under it: the hero holds the
   sum, the line and the form already, and a key inside it would be a fifth
   thing competing in a composition measured for four. */
.pins { list-style: none; margin: 0; padding: 0; }

/* Every pin is read at a glance rather than opened: the labels are the point,
   so they are on the map, not behind a tap. That is also why there are six and
   not nine — six open labels is a legible map, nine is a wall. */
.pin { position: absolute; left: var(--x); top: var(--y); z-index: 2; }

.pin__dot {
  position: absolute;
  left: 50%; top: 50%;
  translate: -50% -50%;
  width: clamp(11px, 1.05vw, 15px);
  height: clamp(11px, 1.05vw, 15px);
  border-radius: 50%;
  /* Hue by whose it is, the same as the sum overhead: the workout is yours and
     carries your magenta, the reward is theirs to give and carries their
     violet. Never by category — the two hues mean the two people. */
  background: var(--you-fill);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.92),
              0 5px 12px -4px rgba(59, 15, 37, 0.55);
  transition: transform 260ms cubic-bezier(0.2, 0.8, 0.2, 1),
              box-shadow 260ms ease-out;
}
.pin--reward .pin__dot { background: var(--partner); }

/* Glass, because it sits on a drawn map and has to let the place it marks keep
   showing through: a blurred, saturated pull of whatever is beneath, a bright
   rim where light would catch the top edge, and one specular sweep across it. */
.pin__chip {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 13px);
  translate: calc(-50% + var(--nudge, 0px)) 0;
  display: flex;
  align-items: center;
  /* Sized against the viewport, not in fixed rem: the plate is a percentage of
     the window, so a chip that does not shrink with it collides with its
     neighbours at every width between the phone and the wide layout. */
  gap: clamp(6px, 0.64vw, 9px);
  padding: clamp(5px, 0.56vw, 8px) clamp(9px, 0.98vw, 14px) clamp(5px, 0.56vw, 8px) clamp(6px, 0.7vw, 10px);
  border-radius: 14px;           /* {rounded.plate} */
  white-space: nowrap;
  background: linear-gradient(147deg,
    rgba(255, 255, 255, 0.72) 0%,
    rgba(255, 255, 255, 0.42) 48%,
    rgba(255, 255, 255, 0.58) 100%);
  -webkit-backdrop-filter: blur(14px) saturate(1.75);
          backdrop-filter: blur(14px) saturate(1.75);
  /* The rim is an inset ring, not a border: on this page an edge is light
     catching a surface and never a drawn line — and a hairline border under a
     wide shadow is the generic generated-UI signature besides. */
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.6),
    inset 0 1px 0 rgba(255, 255, 255, 0.96),
    inset 0 -7px 14px -9px rgba(255, 255, 255, 0.8),
    0 12px 26px -13px rgba(59, 15, 37, 0.5),
    0 2px 6px -3px rgba(59, 15, 37, 0.24);
  transition: transform 260ms cubic-bezier(0.2, 0.8, 0.2, 1),
              box-shadow 260ms ease-out, background-color 260ms ease-out;
}

/* the sweep: one band of light across the top-left, as glass catches it */
.pin__chip::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(118deg,
    rgba(255, 255, 255, 0.78) 0%,
    rgba(255, 255, 255, 0.22) 30%,
    rgba(255, 255, 255, 0) 52%);
}

.pin__thumb {
  position: relative;
  width: clamp(20px, 2.1vw, 30px);
  height: clamp(20px, 2.1vw, 30px);
  border-radius: clamp(6px, 0.63vw, 9px);
  object-fit: cover;
  flex: none;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.75),
              0 3px 8px -3px rgba(59, 15, 37, 0.45);
}

.pin__lines { position: relative; display: grid; gap: 1px; }

.pin__kind {
  font-family: var(--sans);
  /* not uppercased: this page sets nothing in caps, and at this size the
     tracking alone already reads as a label */
  font-size: clamp(0.58rem, 0.7vw, 0.7rem);
  letter-spacing: 0.05em;
  color: var(--you-text);
}
.pin--reward .pin__kind { color: var(--partner-text); }

.pin__name {
  font-family: var(--serif);
  font-size: clamp(0.76rem, 1.05vw, 1.02rem);
  line-height: 1.2;
  color: var(--ink);
}

.pin__cost {
  font-family: var(--sans);
  font-size: clamp(0.6rem, 0.78vw, 0.74rem);
  line-height: 1.3;
  color: var(--ink-worn);
}

/* Hovering lifts the glass and brightens it, and the mark it belongs to grows
   with it, so it is never ambiguous which place the label is naming. */
.pin:hover .pin__chip {
  transform: translateY(-3px);
  background: linear-gradient(147deg,
    rgba(255, 255, 255, 0.9) 0%,
    rgba(255, 255, 255, 0.66) 48%,
    rgba(255, 255, 255, 0.8) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 1),
    inset 0 -7px 14px -9px rgba(255, 255, 255, 0.9),
    0 0 0 1px rgba(217, 61, 180, 0.34),
    0 20px 38px -16px rgba(59, 15, 37, 0.5);
}
.pin--reward:hover .pin__chip { box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 1),
    inset 0 -7px 14px -9px rgba(255, 255, 255, 0.9),
    0 0 0 1px rgba(160, 81, 196, 0.38),
    0 20px 38px -16px rgba(59, 15, 37, 0.5); }

.pin:hover .pin__dot {
  transform: scale(1.3);
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.98),
              0 7px 16px -4px rgba(59, 15, 37, 0.6);
}

/* the chips at the ends still carry --nudge, which home.js sets on load and on
   resize now that they are open from the start rather than on a tap */
.pin--w .pin__chip { left: 0; translate: var(--nudge, 0px) 0; }
.pin--e .pin__chip { left: auto; right: 0; translate: var(--nudge, 0px) 0; }

@media (max-width: 620px) {
  /* Six open labels need a plate to spread across. At 350px wide they stack on
     each other, so the two that sit closest to their neighbours stand down and
     four remain — still one of each kind on each side of the map. */
  .pin--crowd { display: none; }
  .pin__chip { bottom: calc(100% + 8px); }
}

/* ── the loop ───────────────────────────────────────────────────────── */
/* Five steps and then back to one. Each is coloured by WHOSE move it is, which
   is the only colour rule this page has: magenta is one of them, violet is the
   other, by meaning and never by index. So the run reads as the thing passing
   back and forth — her, him, her, him, then both — and the ground deepens as it
   goes, because the last step is the one worth arriving at.

   They are bands, not cards. This page has no section that is a card, and a
   card holding three more cards is the lazy version of a sequence. The band
   carries the colour; a raised tile inside it is the system's own way of
   lifting a surface and is the only lifted thing in each step. */

.loop {
  background: var(--raised);
  padding: clamp(72px, 8vw, 130px) 0 0;
}

.loop__head {
  max-width: 62ch;
  margin-inline: auto;
  padding-inline: clamp(24px, 6vw, 80px);
  text-align: center;
}

.loop__title {
  margin: 0;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(2rem, 4.2vw, 3.4rem);
  line-height: 1.12;
  letter-spacing: -0.012em;
  color: var(--ink);
  text-wrap: balance;
}

.loop__lede {
  margin: 18px auto 0;
  max-width: 46ch;
  font-family: var(--sans);
  font-size: 1.15rem;            /* {typography.lede} */
  line-height: 1.6;
  color: var(--ink-worn);
}

.steps {
  list-style: none;
  margin: clamp(46px, 5vw, 76px) 0 0;
  padding: 0;
}

/* whose move it is — the two hues, and nothing else */
.step--you  { --hue: var(--you);     --hue-text: var(--you-text); }
.step--them { --hue: var(--partner); --hue-text: var(--partner-text); }
.step--both { --hue: var(--you);     --hue-text: var(--you-text); }

/* ...and the ground deepens step by step, so the sequence has somewhere to go */
.step--1 { --tint: 4%; }
.step--2 { --tint: 5.5%; }
.step--3 { --tint: 7%; }
.step--4 { --tint: 9%; }
.step--5 { --tint: 11%; }

.step {
  padding: clamp(40px, 4.6vw, 78px) clamp(24px, 6vw, 80px);
  background: color-mix(in srgb, var(--hue) var(--tint), var(--raised));
}
/* the last one belongs to both of them, so its ground is both */
.step--both {
  background: linear-gradient(100deg,
    color-mix(in srgb, var(--you) var(--tint), var(--raised)) 0%,
    color-mix(in srgb, var(--partner) var(--tint), var(--raised)) 100%);
}

.step__inner {
  max-width: 1120px;
  margin-inline: auto;
  display: grid;
  grid-template-columns: clamp(68px, 7vw, 96px) minmax(0, 1.08fr) minmax(0, 0.92fr);
  align-items: start;
  gap: clamp(20px, 2.6vw, 44px);
}

/* the even steps are his, and they run the other way, so the page passes back
   and forth the way the week does */
.step--them .step__inner {
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr) clamp(68px, 7vw, 96px);
}
.step--them .step__show { order: 1; }
.step--them .step__say  { order: 2; }
.step--them .step__mark { order: 3; text-align: right; justify-items: end; }

.step__mark { display: grid; gap: 7px; }

.step__n {
  font-family: var(--serif);
  font-size: clamp(2rem, 4.2vw, 3.4rem);   /* {typography.display} */
  line-height: 0.9;
  color: var(--hue-text);
}
.step--both .step__n { color: var(--ink); }

.step__who {
  font-family: var(--sans);
  font-size: 0.78rem;            /* {typography.label} */
  line-height: 1.4;
  /* {typography.label} specifies 0.08em, which is drawn for a capitalised
     label. This page sets nothing in caps, and that much tracking on lowercase
     breaks the word shapes, so these carry the token's size and half its
     tracking. */
  letter-spacing: 0.04em;
  color: var(--hue-text);
}
.step--both .step__who { color: var(--ink-worn); }

.step__say { display: grid; gap: 15px; align-content: start; }

.step__title {
  margin: 0;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.35rem, 2.2vw, 1.95rem);   /* {typography.headline} */
  line-height: 1.18;
  letter-spacing: -0.008em;
  color: var(--ink);
  text-wrap: balance;
}

.step__t {
  margin: 0;
  font-family: var(--sans);
  font-size: 1.15rem;            /* {typography.lede} */
  line-height: 1.6;
  color: var(--ink-worn);
  text-wrap: pretty;
}
.step__t em { font-style: italic; color: var(--ink); }

/* The example is the point of the section, so it is set apart — by a hairline
   and its own ink, which is what this page uses to divide, rather than by
   becoming a third card inside a card. */
.step__eg {
  margin: 3px 0 0;
  padding-top: 15px;
  border-top: 1px solid var(--edge);
  font-family: var(--sans);
  font-size: 0.92rem;            /* {typography.caption} */
  line-height: 1.65;
  color: var(--ink);
  text-wrap: pretty;
}
.step__eg-k {
  color: var(--hue-text);
  font-style: italic;
}
.step__eg-k::after { content: " — "; color: var(--ink-worn); font-style: normal; }

.step__show { margin: 0; display: grid; gap: 12px; align-content: start; }

/* ── the small objects the steps are made of ─────────────────────────── */

.shot { position: relative; }
.shot img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 14px;           /* {rounded.plate} */
  box-shadow: 0 1px 2px rgba(59, 15, 37, 0.06),
              0 18px 34px -22px rgba(59, 15, 37, 0.5);
}
.shot__cap, .shot__where {
  margin: 9px 0 0;
  font-family: var(--sans);
  font-size: 0.92rem;            /* {typography.caption} */
  line-height: 1.65;
  color: var(--ink-worn);
}
.shot__pin {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--hue);
  vertical-align: 0.5px;
  margin-right: 5px;
}
.shot__stamp {
  position: absolute;
  left: 12px; bottom: 12px;
  margin: 0;
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(255, 251, 253, 0.94);
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
  font-family: var(--sans);
  font-size: 0.78rem;            /* {typography.label} */
  line-height: 1.4;
  /* {typography.label} specifies 0.08em, which is drawn for a capitalised
     label. This page sets nothing in caps, and that much tracking on lowercase
     breaks the word shapes, so these carry the token's size and half its
     tracking. */
  letter-spacing: 0.04em;
  color: var(--hue-text);
  box-shadow: 0 6px 16px -8px rgba(59, 15, 37, 0.5);
}
.shot--checked .shot__stamp { bottom: 44px; }
.shot--done .shot__stamp { bottom: 16px; }

/* the one lifted surface per step */
.tile, .claim {
  padding: 16px 19px;
  border-radius: 20px;           /* {rounded.chip} */
  background: var(--raised);
  box-shadow: 0 1px 2px rgba(59, 15, 37, 0.06),
              0 14px 30px -20px rgba(59, 15, 37, 0.45);
}
.tile__k, .claim__k {
  margin: 0;
  font-family: var(--sans);
  font-size: 0.78rem;            /* {typography.label} */
  line-height: 1.4;
  /* {typography.label} specifies 0.08em, which is drawn for a capitalised
     label. This page sets nothing in caps, and that much tracking on lowercase
     breaks the word shapes, so these carry the token's size and half its
     tracking. */
  letter-spacing: 0.04em;
  color: var(--ink-worn);
}
.claim__k { color: var(--partner-text); }
.tile__v {
  margin: 7px 0 0;
  font-family: var(--serif);
  font-size: clamp(1.35rem, 2.2vw, 1.95rem);   /* {typography.headline} */
  line-height: 1.15;
  color: var(--ink);
}
.tile__was { color: var(--ink-worn); }
.tile__arw { color: var(--ink-worn); font-size: 0.92rem; }
.tile__now { color: var(--hue-text); }
.tile__u   { font-family: var(--sans); font-size: 0.92rem; color: var(--ink-worn); }
.tile__note {
  margin: 8px 0 0;
  font-family: var(--sans);
  font-size: 0.92rem;            /* {typography.caption} */
  line-height: 1.65;
  color: var(--ink-worn);
}

.wkstrip {
  list-style: none;
  margin: 13px 0 0;
  padding: 0;
  display: flex;
  gap: 5px;
}
.wkstrip__c {
  width: 15px; height: 15px;
  border-radius: 4px;
  background: rgba(59, 15, 37, 0.1);
}
.wkstrip__c.is-on  { background: var(--hue-text); }
.wkstrip__c.is-new {
  background: var(--hue);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--hue) 24%, transparent);
}

.tile--sum .sum {
  margin: 9px 0 0;
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-family: var(--serif);
}
.sum__n  { font-size: clamp(1.35rem, 2.2vw, 1.95rem); color: var(--ink); }
.sum__op { font-size: clamp(1.15rem, 2vw, 1.6rem); color: var(--ink-worn); }
.sum__t  { font-size: clamp(2rem, 4.2vw, 3.4rem); color: var(--hue-text); }

.claim { display: grid; gap: 4px; }
.claim__name {
  font-family: var(--serif);
  font-size: clamp(1.15rem, 2vw, 1.6rem);   /* {typography.title} */
  line-height: 1.32;
  color: var(--ink);
}
.claim__cost, .claim__turn {
  font-family: var(--sans);
  font-size: 0.92rem;            /* {typography.caption} */
  line-height: 1.65;
  color: var(--ink-worn);
}
.claim__turn { margin-top: 7px; }
.turnmark {
  display: inline-block;
  width: 9px; height: 9px;
  border-radius: 50%;
  margin-right: 3px;
}
.turnmark--you  { background: var(--you); }
.turnmark--them { background: var(--partner); }

.yearwall {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 9px;
}
.yearwall img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 14px;           /* {rounded.plate} */
  box-shadow: 0 1px 2px rgba(59, 15, 37, 0.06),
              0 12px 24px -18px rgba(59, 15, 37, 0.5);
}
.yearwall__k {
  margin: 13px 0 0;
  font-family: var(--sans);
  font-size: 0.92rem;            /* {typography.caption} */
  line-height: 1.65;
  color: var(--ink-worn);
}
.yearwall__sw {
  display: inline-block;
  width: 10px; height: 10px;
  border-radius: 3px;
  vertical-align: -1px;
}
.yearwall__sw--you  { background: var(--you); }
.yearwall__sw--them { background: var(--partner); }

.loop__back {
  margin: 0;
  padding: clamp(34px, 4vw, 58px) clamp(24px, 6vw, 80px) clamp(44px, 5vw, 74px);
  text-align: center;
  font-family: var(--serif);
  font-size: clamp(1.1rem, 1.7vw, 1.4rem);   /* {typography.body-quiet} */
  line-height: 1.55;
  color: var(--ink-worn);
}

@media (max-width: 900px) {
  .step__inner,
  .step--them .step__inner {
    grid-template-columns: 1fr;
    gap: 18px;
  }
  .step--them .step__mark { order: 0; text-align: left; justify-items: start; }
  .step--them .step__say  { order: 1; }
  .step--them .step__show { order: 2; }
  .step__mark { grid-auto-flow: column; justify-content: start; align-items: baseline; gap: 12px; }
}

/* Last in the file on purpose: this must win over every rule above it, and
   source order is what decides between selectors of equal weight. */
@media (prefers-reduced-motion: reduce) {
  .equation__count, .equation__unit, .equation__reward,
  .equation-bar, .top,
  .pack__btn, .pack__reveal,
  .wk, .streak__count, .print,
  .pin__chip, .pin__dot { transition: none; }
}
