/* Landing layout. Tokens and chrome come from `_style.css`.

   The structure is taken from two references rather than invented: an inset
   dark hero panel with a row of cards docked across its bottom edge, and a
   hairline-divided stat bar over a full-bleed strip of content cards. The
   finish stays the app's - white ground, black ink, system type ramp, a
   raised surface is white plus a hairline. */

section { padding: clamp(56px, 7vw, 96px) 0; }

/* Two plain sections in a row share one band of air rather than stacking two. */
section.tight { padding-top: 0; }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 20px;
  color: var(--accent);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* Aligned to the first line rather than to the middle of the block, so a label
   that wraps on a phone does not leave the dot floating between its two rows. */
.eyebrow::before {
  content: '';
  flex: none;
  align-self: flex-start;
  width: 7px; height: 7px;
  margin-top: .5em;
  border-radius: 50%;
  background: currentColor;
}

h1, h2, h3 { letter-spacing: -.035em; text-wrap: balance; }

h1 {
  font-size: clamp(36px, 5.4vw, 62px);
  line-height: 1.02;
  font-weight: 700;
  margin: 0 0 22px;
}

h2 {
  font-size: clamp(28px, 4vw, 40px);
  line-height: 1.08;
  font-weight: 700;
  margin: 0 0 14px;
}

h3 {
  font-size: 19px;
  line-height: 1.25;
  font-weight: 600;
  letter-spacing: -.02em;
  margin: 0 0 8px;
}

.lede {
  font-size: clamp(18px, 2vw, 21px);
  line-height: 1.5;
  color: var(--ink-2);
  margin: 0 0 32px;
  max-width: 36ch;
}

p { margin: 0 0 12px; }

/* --- hero panel --------------------------------------------------------- */

.hero { padding: clamp(8px, 1.5vw, 16px) 0 0; }

.panel {
  position: relative;
  overflow: hidden;
  border-radius: clamp(24px, 3vw, 40px);
  background: var(--panel);
  color: #fff;
  padding: clamp(40px, 5vw, 76px) clamp(24px, 4vw, 64px) clamp(44px, 5vw, 76px);
}

.panel .eyebrow { color: var(--accent-on-panel); }
.panel .lede { color: var(--on-panel); }

.panel-grid {
  display: grid;
  gap: clamp(40px, 5vw, 64px);
  align-items: center;
}

@media (min-width: 900px) {
  .panel { padding-bottom: clamp(96px, 9vw, 132px); }
  .panel-grid {
    grid-template-columns: minmax(0, 1.06fr) minmax(0, .94fr);
    align-items: end;
  }
  .panel .lede { max-width: 30ch; }

  /* The phone runs off the bottom of the panel rather than being scaled down
     to fit inside it. A whole 19.5:9 device drawn small enough to fit is
     600-odd pixels of column and unreadable at the end of it; cut off by the
     panel's own edge it stays legible and the panel stays the height of its
     text. `overflow: hidden` on the panel is what does the cutting. */
  .panel .shot-stage { align-self: end; margin-bottom: -190px; }
}

/* The card fan: the app's own category artwork, at the card's own 2:3.
   Everything is a percentage of the container, so the whole arrangement
   scales with the column instead of breaking at a breakpoint.

   The ring in `box-shadow` is what stops it reading as one dark mass. All
   three photographs are graded dark on purpose (see
   assets/categories/SOURCES.md), so without a band between them the stack has
   no edges - and on this panel the ring is the one white thing in the picture,
   which is what makes them read as cards lying on a surface. */
.fan {
  position: relative;
  width: 100%;
  max-width: 460px;
  margin-inline: auto;
  aspect-ratio: 1 / 1;
}

.fan figure {
  position: absolute;
  top: 0;
  width: 52%;
  margin: 0;
  aspect-ratio: 2 / 3;
  border-radius: 20px;
  overflow: hidden;
  background: #222;
  box-shadow: 0 0 0 4px #fff, 0 24px 50px -16px rgba(0, 0, 0, .9);
  transition: transform .5s var(--ease);
}

/* The spread is set by the longest label rather than by taste: the right-hand
   card is overlapped from the left, and `Bodybuilding` has to fit in whatever
   strip of it the front card leaves showing. */
.fan figure:nth-child(1) { left: 0;   top: 10%; transform: rotate(-8deg) scale(.94); }
.fan figure:nth-child(2) { left: 52%; top: 6%;  transform: rotate(8deg) scale(.94); }
.fan figure:nth-child(3) { left: 22%; top: 18%; z-index: 2; }

.fan:hover figure:nth-child(1) { transform: rotate(-10deg) scale(.94) translateY(-8px); }
.fan:hover figure:nth-child(2) { transform: rotate(10deg) scale(.94) translateY(-8px); }
.fan:hover figure:nth-child(3) { transform: translateY(-12px); }

.fan img, .strip img { width: 100%; height: 100%; object-fit: cover; }

/* The scrim the app draws over the bottom half, so the name keeps its
   contrast against whatever the photograph is doing under it. */
.fan figcaption, .strip figcaption {
  position: absolute;
  inset: auto 0 0 0;
  padding: 46px 14px 12px;
  background: linear-gradient(to top, rgba(0, 0, 0, .8), rgba(0, 0, 0, 0));
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.01em;
}

/* Only the front card is named. The two behind it show about a quarter of
   their width, which is not enough for `Bodybuilding` at any size the label
   can honestly be set at - and a clipped word is worse than no word. The full
   list of seven is the strip further down the page. */
.fan figure:not(:nth-child(3)) figcaption { display: none; }

/* --- app screenshots ---------------------------------------------------- */

/* A capture off the simulator is the screen only, with no bezel, so the device
   is drawn here: two rings for the frame and its highlight, and the corner
   radius stated as a share of the frame so it stays the phone's own corner at
   every size. */
.shot {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 300px;
  margin-inline: auto;
  aspect-ratio: 1290 / 2796;
  border-radius: 12.5% / 5.8%;
  overflow: hidden;
  background: #000;
  box-shadow:
    0 0 0 6px #16161a,
    0 0 0 7px rgba(255, 255, 255, .16),
    0 40px 80px -28px rgba(0, 0, 0, .7);
}

.shot img { width: 100%; height: 100%; object-fit: cover; }

.shot-stage { position: relative; display: grid; place-items: center; }

/* The hero phone runs off the panel on a phone too, or the panel alone is a
   whole screen of scrolling before the first word underneath it. */
@media (max-width: 899px) {
  .panel .shot { max-width: 260px; }
  .panel .shot-stage { margin-bottom: calc(-1 * clamp(30px, 22vw, 150px)); }
}

/* The accent, thrown behind the phone. It is the one place on the page the
   brand blue is used as light rather than as ink. */
.shot-stage::before {
  content: '';
  position: absolute;
  inset: 4% -14%;
  background: radial-gradient(closest-side,
              rgba(77, 163, 255, .34), rgba(77, 163, 255, 0) 72%);
  pointer-events: none;
}

/* --- alternating feature rows ------------------------------------------- */

.feature .wrap {
  display: grid;
  gap: clamp(36px, 5vw, 80px);
  align-items: center;
}

.feature p { color: var(--muted); max-width: 42ch; }
.feature .shot { max-width: 264px; }

@media (min-width: 900px) {
  .feature .wrap { grid-template-columns: minmax(0, 1fr) minmax(0, .78fr); }

  /* Flipping puts the phone on the left, so the column widths swap with it -
     otherwise the narrow column keeps the prose and the wide one holds a
     264px image. */
  .feature.flip .wrap { grid-template-columns: minmax(0, .78fr) minmax(0, 1fr); }
  .feature.flip .wrap > :first-child { order: 2; }
}

.feature .shot-stage::before {
  background: radial-gradient(closest-side,
              rgba(0, 93, 191, .12), rgba(0, 93, 191, 0) 72%);
}

/* --- the three halves, docked over the panel ---------------------------- */

.trio {
  display: grid;
  gap: 14px;
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
}

.trio li {
  padding: 24px;
  border: 1px solid var(--rule);
  border-radius: 22px;
  background: var(--ground);
  box-shadow: var(--shadow);
}

.trio h3 { margin-bottom: 6px; }
.trio p { color: var(--muted); font-size: 16px; margin: 0; }

.trio .tag {
  display: block;
  margin-bottom: 12px;
  color: var(--accent);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
}

@media (min-width: 860px) {
  .trio {
    position: relative;
    z-index: 2;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    margin-top: -68px;
  }
}

/* --- store badges ------------------------------------------------------- */

/* Apple's and Google's own artwork, unaltered beyond trimming the transparent
   padding Google bakes into theirs - which is the only reason two badges set
   to one height used to read as two different sizes. */
.stores { display: flex; flex-wrap: wrap; gap: 12px; }

.stores a {
  display: block;
  border-radius: 8px;
  transition: transform .18s var(--ease);
}

.stores a:active { transform: scale(.97); }
.stores img { height: 46px; width: auto; }

/* Two badges side by side measure 304px at full height, which is 10px more
   than a 390pt phone leaves inside the panel - so they wrapped into a column.
   Four pixels off each brings the pair back onto one row. */
@media (max-width: 480px) {
  .stores { gap: 10px; }
  .stores img, .close .stores img { height: 42px; }
}

.close .stores { justify-content: center; margin-top: 28px; }
.close .stores img { height: 50px; }

/* --- wedge -------------------------------------------------------------- */

.wedge { background: var(--bed); }

.wedge p {
  font-size: clamp(24px, 3.6vw, 38px);
  line-height: 1.18;
  letter-spacing: -.035em;
  font-weight: 600;
  max-width: 26ch;
  margin: 0 0 20px;
  color: var(--muted);
}

.wedge p.hit { color: var(--ink); margin: 0; }

/* --- the short four ------------------------------------------------------ */

/* Four columns of one line each, which is what both references do with the
   features that do not earn a screenshot of their own. No cards: the columns
   are held apart by space, and by a rule on the wide layout only. */
.quad {
  display: grid;
  gap: 32px 28px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 900px) {
  .quad { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 40px; }
  .quad li + li { border-left: 1px solid var(--rule); padding-left: 40px; }
}

.quad h3 { margin-bottom: 6px; }
.quad p { color: var(--muted); font-size: 16px; margin: 0; }

/* --- stat bar ----------------------------------------------------------- */

.statbar {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: 40px;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.statbar div { padding: 26px 0 26px 24px; }
.statbar div:first-child { padding-left: 0; }
.statbar div + div { border-left: 1px solid var(--rule); }

.statbar b {
  display: block;
  font-size: clamp(30px, 4vw, 44px);
  font-weight: 700;
  letter-spacing: -.04em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.statbar span { display: block; margin-top: 8px; color: var(--muted); font-size: 15px; }

/* --- category strip ----------------------------------------------------- */

/* Full bleed on purpose: the point of the row is that it runs past the edge of
   the screen, the same way the floor does. The left edge still lines up with
   the text column above it, so only the right side reads as unfinished. */
.strip {
  display: flex;
  gap: 14px;
  margin: 28px 0 0;
  padding: 4px var(--gutter) 12px
           max(var(--gutter), calc(50vw - var(--page) / 2 + var(--gutter)));
  overflow-x: auto;
  scroll-snap-type: x proximity;
  /* Without this the first card snaps its own start edge to the scroll port
     and the inset above is scrolled straight past, which lands the row hard
     against the window while every other section starts at the text column. */
  scroll-padding-inline-start:
    max(var(--gutter), calc(50vw - var(--page) / 2 + var(--gutter)));
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}

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

.strip figure {
  position: relative;
  flex: 0 0 clamp(168px, 21vw, 232px);
  margin: 0;
  aspect-ratio: 2 / 3;
  border-radius: 22px;
  overflow: hidden;
  background: var(--raised);
  scroll-snap-align: start;
}

/* --- coaches ------------------------------------------------------------ */

.coaches .wrap {
  display: grid;
  gap: clamp(32px, 5vw, 64px);
  align-items: center;
}

@media (min-width: 860px) {
  .coaches .wrap { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); }
}

.coaches p { color: var(--muted); max-width: 48ch; }
.coaches .mark-plinth { justify-self: center; }
.coaches .mark-plinth img { width: clamp(150px, 22vw, 220px); height: auto; }

/* --- closing call ------------------------------------------------------- */

.close { background: var(--bed); }

/* Raised is white plus a hairline and a drop, never a tinted fill.
   See CLAUDE.md `Design Target`. */
.close .card {
  background: var(--ground);
  border: 1px solid var(--rule);
  border-radius: clamp(26px, 3vw, 36px);
  padding: clamp(40px, 6vw, 76px) clamp(26px, 5vw, 64px);
  box-shadow: var(--shadow);
  text-align: center;
}

.close h2 { margin-bottom: 12px; }
.close .lede { color: var(--muted); margin: 0 auto; max-width: 40ch; }

/* --- mobile sticky call ------------------------------------------------- */

.dock {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 20;
  display: none;
  padding: 10px var(--gutter) calc(10px + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--ground) 86%, transparent);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-top: 1px solid var(--rule);
  transform: translateY(110%);
  transition: transform .35s var(--ease);
}

.dock .btn { width: 100%; }

@media (max-width: 760px) {
  .dock { display: block; }
  .dock.show { transform: none; }
  body.has-dock { padding-bottom: 76px; }
}

/* --- entrance ----------------------------------------------------------- */

/* The hidden state is applied only once the script has claimed the document,
   so a reader with no JavaScript gets the page rather than a blank one. */
.js .rise {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .6s var(--ease), transform .6s var(--ease);
  transition-delay: calc(var(--i, 0) * 70ms);
}

.js .rise.in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .js .rise { opacity: 1; transform: none; }
}
