* { box-sizing: border-box; }

html { overflow-x: hidden; }
:root { --col-half: 244px; }
body {
  margin: 0;
  min-height: 100vh;
  background: var(--ground);
  color: var(--ink);
  font-family: 'Inter', -apple-system, 'Segoe UI', Roboto, sans-serif;
}

.t-wordmark { font-size: 19px; font-weight: 700; letter-spacing: 1.6px; text-transform: uppercase; }
/* The wordmark is the app's own script asset, not type — the ramp above only
   covers the fallback. Height, not width, and the aspect ratio is stated so
   nothing reflows between layout and the file arriving: an SVG has no
   intrinsic size for the browser to reserve space from the way a raster does.
   Those are the vector's own units, the export's full filter region, so they
   include the 3-unit shadow offset below and right of the letterforms. */
.t-wordmark img { display: block; height: var(--mark-h, 36px); width: auto; aspect-ratio: 242.89 / 32.57; }
.t-bar-title { font-size: 19px; font-weight: 700; }
.t-heading { font-size: 25px; font-weight: 700; line-height: 1.2; }
.t-card-title { font-size: 16px; font-weight: 700; line-height: 1.2; }
.t-body { font-size: 14.5px; font-weight: 400; line-height: 1.5; }
.t-meta { font-size: 13px; font-weight: 400; line-height: 1.45; }
.t-label { font-size: 11px; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; }
.t-button { font-size: 15px; font-weight: 700; }
.t-button-secondary { font-size: 13.5px; font-weight: 600; }
.t-stat { font-size: 12px; font-weight: 500; }
.t-row-title { font-size: 15.5px; font-weight: 700; }

#top-bar {
  background: var(--band);
  color: var(--band-ink);
  /* The masthead's one number: the wordmark's height, which the figure and
     the bar's own height are both derived from. 72px is twice what the bar
     first stood at, and the calc is what a narrow screen gets instead — the
     figure, the gap and the wordmark's own 7.46:1 aspect come to ~8.6 times
     this height plus the side padding, so below ~665px the mark steps down to
     whatever the viewport actually has room for rather than overflowing. */
  --mark-h: min(72px, calc((100vw - 48px) / 8.6));
  height: calc(var(--mark-h) + 40px);
  display: flex;
  align-items: center;
  gap: var(--space-ml);
  padding: 0 var(--space-xl);
  /* The bar is the app's band, and so is the first slab under it — left alone
     the two would merge into one field. A hairline separates them rather than
     the app's BandEdge: at twice the app's height this is the page's masthead,
     not a strip of chrome, and a cast shadow at that scale reads as a seam
     across the page. Still has to out-paint the slab, which comes later in
     the document. */
  position: relative;
  z-index: 1;
  border-bottom: 1px solid var(--overlay-border);
}
#top-bar.centered { justify-content: center; }
/* The splash figure, leading the wordmark. Square and full-bleed — the
   artwork's arms reach its own edges, so it carries no padding of its own and
   runs a touch taller than the wordmark beside it to read as the same weight.
   Hidden in the page-title states, where the bar is the app's titled band and
   the branding is not what it carries. */
#bar-figure {
  display: block;
  width: calc(var(--mark-h) * 1.11);
  height: calc(var(--mark-h) * 1.11);
  flex-shrink: 0;
}
#top-bar:not(.centered) #bar-figure { display: none; }
#bar-title {
  margin: 0;
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

#band {
  background: var(--band);
  padding: var(--space-m) var(--space-xl);
  box-shadow: 0 6px 14px var(--band-shadow);
}
#band a {
  color: var(--band-ink-secondary);
  text-decoration: none;
}

main {
  max-width: 520px;
  margin: 0 auto;
  padding: var(--space-xxl) var(--space-xl) 40px;
}
#app { text-align: left; }

p.copy { color: var(--ink-reading); text-align: center; margin: 0 0 var(--space-m); font-size: 14.5px; font-weight: 400; line-height: 1.5; }

.buttons { display: flex; flex-direction: column; }
a.open {
  display: block;
  background: var(--button-fill);
  color: var(--button-ink);
  border-radius: var(--radius-md);
  padding: var(--space-xl);
  font-size: 15px;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
}
a.open:hover, a.open:active { background: var(--button-fill-pressed); }
a.secondary {
  display: block;
  text-align: center;
  background: none;
  border: none;
  color: var(--ink-secondary);
  font-size: 13.5px;
  font-weight: 600;
  padding: var(--space-ml);
  margin-top: var(--space-xs);
  text-decoration: none;
}
p.note { color: var(--ink-muted); font-size: 13px; line-height: 1.45; text-align: center; margin: var(--space-s) 0 0; }

img.thumb { display: block; width: 100%; height: 200px; object-fit: cover; border-radius: var(--radius-md); margin: 0 0 var(--space-m); }

.detail-card {
  background: var(--insight-surface);
  border: 1px solid var(--overlay-border);
  border-radius: var(--radius-md);
  padding: var(--space-l);
  margin: 0 0 var(--space-m);
}
.detail-card-title { margin: 0 0 var(--space-ml); font-size: 16px; font-weight: 700; line-height: 1.2; color: var(--ink); }
.detail-card-body { margin: 0; color: var(--ink-reading); font-size: 14.5px; font-weight: 400; line-height: 1.5; }
.detail-row { margin: 0 0 var(--space-xxs); font-size: 14.5px; font-weight: 400; line-height: 1.5; color: var(--ink-reading); }
.detail-row:last-child { margin-bottom: 0; }
.detail-row strong { color: var(--ink); font-weight: 700; }

.portrait-shell {
  background: var(--insight-surface);
  border: 1px solid var(--overlay-border);
  border-radius: var(--radius-md);
  margin: 0 0 var(--space-m);
}
img.coach-portrait { display: block; width: 100%; height: 220px; object-fit: cover; border-radius: var(--radius-sm); }

.bio {
  background: var(--overlay-deep);
  border-radius: var(--radius-md);
  padding: var(--space-l);
  margin: 0 0 var(--space-m);
  color: var(--ink);
  font-size: 14.5px;
  font-weight: 400;
  line-height: 1.5;
  white-space: pre-wrap;
}

a.byline, div.byline {
  display: flex;
  align-items: center;
  gap: var(--space-ml);
  margin: 0 0 var(--space-l);
  text-decoration: none;
  color: inherit;
}
.post-title { margin: 0 0 var(--space-l); font-size: 25px; font-weight: 700; line-height: 1.2; color: var(--ink); }
img.byline-avatar { width: 40px; height: 40px; flex-shrink: 0; border-radius: 50%; object-fit: cover; background: var(--overlay); }
.byline-name { margin: 0; font-size: 15.5px; font-weight: 700; color: var(--ink); }
.byline-date { margin: var(--space-xxs) 0 0; font-size: 13px; font-weight: 400; line-height: 1.45; color: var(--ink-secondary); }
hr.hairline { border: none; border-top: 1px solid var(--overlay-border); margin: 0 0 var(--space-l); }

.post-body { margin: 0 0 var(--space-xxl); }
.post-heading { margin: var(--space-s) 0; font-size: 14.5px; font-weight: 700; line-height: 1.5; color: var(--ink); }
.post-para { margin: 0 0 var(--space-s); font-size: 14.5px; font-weight: 400; line-height: 1.5; color: var(--ink); }
.post-para:last-child { margin-bottom: 0; }

.skeleton {
  border-radius: var(--radius-md);
  background: linear-gradient(90deg, var(--skeleton-block) 0%, var(--skeleton-shine) 50%, var(--skeleton-block) 100%);
  background-size: 200% 100%;
  animation: skeleton-shine 1.4s linear infinite;
  margin: 0 0 var(--space-m);
}
.skeleton-hero { height: 220px; }
.skeleton-card { height: 96px; }
.skeleton-button { height: 52px; }
@keyframes skeleton-shine {
  from { background-position: 200% 0; }
  to { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; background: var(--skeleton-block); }
}

.section-label { margin: var(--space-xxl) 0 var(--space-s); font-size: 11px; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; color: var(--ink-label); }

a.prog-card {
  display: flex;
  align-items: center;
  gap: var(--space-ml);
  background: var(--insight-surface);
  border: 1px solid var(--overlay-border);
  border-radius: var(--radius-md);
  padding: var(--space-l);
  margin: 0 0 var(--space-m);
  text-decoration: none;
  color: inherit;
}
a.prog-card:hover { background: var(--list-pressed-surface); border-color: var(--list-pressed-border); }
.prog-card-tile { width: 64px; height: 64px; flex-shrink: 0; border-radius: var(--radius-sm); object-fit: cover; background: var(--overlay); }
.prog-card-info { min-width: 0; flex: 1; }
.prog-card-name { margin: 0; font-size: 15.5px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prog-card-meta { margin: var(--space-xxs) 0 0; font-size: 13px; font-weight: 400; line-height: 1.45; color: var(--ink-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prog-card-stat { margin: var(--space-xxs) 0 0; font-size: 12px; font-weight: 500; color: var(--ink-stat); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prog-card-chevron { flex-shrink: 0; font-size: 20px; line-height: 1; color: var(--ink-icon); }

.slab {
  margin-inline: calc(50% - 50vw);
  margin-bottom: var(--space-xxl);
  padding: var(--space-xxxxl) max(var(--space-xl), calc(50vw - var(--col-half)));
  background: var(--band);
  box-shadow: 0 6px 14px var(--band-shadow);
}

.slab:first-child { margin-top: calc(-1 * var(--space-xxl)); }
.slab:last-child { margin-bottom: 0; }

.hero { text-align: center; }
.hero-status {
  display: inline-block;
  margin: 0 0 var(--space-l);
  padding: var(--space-xs) var(--space-ml);
  border-radius: var(--radius-xl);
  background: var(--sage-fill);
  border: 1px solid var(--sage-ring);
  color: var(--sage);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
}
.hero-title {
  margin: 0 0 var(--space-ml);
  font-size: 25px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--band-ink);
}
.hero-copy {
  margin: 0;
  color: var(--band-ink-secondary);
  font-size: 14.5px;
  font-weight: 400;
  line-height: 1.5;
}

/* The promise opens the page, so it's set a step above the ramp: the heading
   size the showcase titles don't reach, over body type larger than the 14.5px
   every other slab reads at. Deliberately off the app's copied type ramp —
   this is the one block meant to be read before anything else on the page. */
.promise-name { margin: 0 0 var(--space-ml); font-size: 32px; font-weight: 700; line-height: 1.15; color: var(--sage); }
.promise-copy { margin: 0; color: var(--band-ink-secondary); font-size: 16px; font-weight: 400; line-height: 1.5; }

/* The carousel: one slab, its slides paged sideways.

   The track is a scroll-snap container and nothing more, so a swipe, a
   trackpad and a shift-wheel all work with the script blocked; carousel.js
   only builds the dots and arrows, which stay [hidden] until it does. The
   scrollbar is suppressed because the dots say the same thing more quietly —
   the track keeps its own keyboard focus, so that costs no one the ability to
   reach it.

   Slides are flex children at exactly the track's width, and start-aligned so
   each is its own height rather than the tallest one's — a short slide would
   otherwise carry half a phone screen of void under it, with the dots pushed
   down past the fold. carousel.js then holds the track at the height of the
   slide actually showing, and eases between the two; without the script the
   track falls back to the tallest slide, which is airy but never broken. */
.carousel-track {
  display: flex;
  align-items: flex-start;
  overflow-x: auto;
  /* Explicitly hidden, not left alone: with overflow-x set and overflow-y
     unstated, CSS computes the y axis to auto too, making this a scroller in
     both directions. A slide measures a fraction of a pixel taller than the
     height carousel.js sets, so WebKit finds a pixel of vertical overflow,
     locks the touch gesture to the vertical axis and eats the sideways swipe —
     which is why this did nothing on an iPad. */
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
  transition: height .25s ease;
}
.carousel-track::-webkit-scrollbar { display: none; }
.carousel-track:focus-visible { outline: 2px solid var(--sage); outline-offset: var(--space-xs); }
.slide {
  flex: 0 0 100%;
  min-width: 0;
  scroll-snap-align: start;
}

/* The slab places the track, the two arrows and the dots itself, so where an
   arrow sits is a question of grid areas and nothing has to move in the DOM.
   Narrow: the track takes the full width and the arrows flank the dots under
   it, since a 16px screen edge is no place to stand an arrow that would then
   cover the copy. Wide (below): they step out into the slab's own side gutter,
   either side of the slides. */
.slab.carousel {
  /* The arrow's box, stated once: the wide layout below pulls the slab's own
     padding in by this plus the gap, so the slides keep landing on the same
     content edge as every other slab however big the chevrons get. */
  --arrow: 48px;
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas:
    "track track track"
    "prev  dots  next";
  align-items: center;
  row-gap: var(--space-xl);
}
.carousel-track { grid-area: track; }
.carousel-arrow[data-step="-1"] { grid-area: prev; }
.carousel-arrow[data-step="1"] { grid-area: next; }
.carousel-dots { grid-area: dots; justify-self: center; }

/* A bare chevron, no chrome around it. The box stays the full --arrow square
   so the target is still a comfortable size to hit on a touchscreen — it's
   only the border and the fill that have gone, not the area. */
.carousel-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--arrow);
  height: var(--arrow);
  padding: 0;
  border: none;
  background: none;
  color: var(--band-ink-secondary);
  font: inherit;
  font-size: 46px;
  line-height: 1;
  cursor: pointer;
}
/* Nothing to fill on hover now, so the glyph itself answers. */
.carousel-arrow:hover:not(:disabled) { color: var(--band-ink); }
.carousel-arrow:disabled { opacity: .3; cursor: default; }

.carousel-dots { display: flex; align-items: center; gap: var(--space-s); }
.carousel-dot {
  width: 8px;
  height: 8px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--band-track);
  cursor: pointer;
}
.carousel-dot[aria-current="true"] { background: var(--sage); }

/* A reduced-motion reader gets the jump, not the glide — and the snap goes
   with it, since a mandatory snap animates its own settle. */
@media (prefers-reduced-motion: reduce) {
  .carousel-track { scroll-behavior: auto; scroll-snap-type: x proximity; transition: none; }
}

/* The closing slab: the two store links. Centred, since it's
   the page's sign-off rather than another section of it. */
.stores { text-align: center; }
.stores-title { margin: 0 0 var(--space-s); font-size: 25px; font-weight: 700; line-height: 1.2; color: var(--sage); }
.stores-copy { margin: 0; color: var(--band-ink-secondary); font-size: 16px; font-weight: 400; line-height: 1.5; }
.store-buttons {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  /* Room above each row for the badge's caption, which takes no space of its
     own (see .store-badge-caption) — between the copy and a single row, and
     between the rows once they stack on a phone. */
  gap: calc(2 * var(--space-xl)) var(--space-ml);
  margin: calc(2 * var(--space-xl)) 0 0;
}
/* Sized like a store badge so the real ones drop into the same hole later. */
.store-button {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 190px;
  padding: var(--space-m) var(--space-l);
  border: 1px solid var(--overlay-border);
  border-radius: var(--radius-md);
  background: var(--overlay-deep);
  color: var(--band-ink);
  text-align: left;
  text-decoration: none;
}
.store-button-lead { font-size: 11px; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; color: var(--band-ink-secondary); }
.store-button-name { margin-top: var(--space-xxs); font-size: 19px; font-weight: 700; line-height: 1.2; }
/* Unpublished: visibly not something to press yet. Drops away the moment the
   placeholder becomes a real anchor. */
.store-button[aria-disabled] { opacity: .55; }
a.store-button:hover { background: var(--list-pressed-surface); border-color: var(--list-pressed-border); }
/* Google's badge as supplied. The PNG carries its required clear space as
   transparent padding, evenly top and bottom, so the image is sized rather
   than padded: 88px tall puts the visible badge at the placeholder's 60px,
   and centring the row lines the two up. The caption sits outside the
   artwork, which may not be altered, and is lifted out of the flow above it
   so it can't push the badge off that centre line. */
.store-badge { position: relative; display: block; text-decoration: none; }
.store-badge-caption { position: absolute; bottom: 100%; left: 0; right: 0; text-align: center; font-size: 11px; font-weight: 600; letter-spacing: 1px; line-height: 1.2; text-transform: uppercase; color: var(--band-ink-secondary); }
.store-badge img { display: block; }

/* The legal links: quiet, centred, and outside main so they sit below the
   slabs' 40px tail rather than inside the last one. */
.site-footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-xs) var(--space-xxl);
  padding: 0 var(--space-xl) 40px;
  text-align: center;
}
.site-footer a { color: var(--ink-secondary); font-size: 14px; line-height: 1.5; text-decoration: none; }
.site-footer a:hover, .site-footer a:active { color: var(--sage); text-decoration: underline; }

.showcase-label { margin: 0 0 var(--space-s); font-size: 11px; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; color: var(--sage); }
.showcase-title { margin: 0 0 var(--space-s); font-size: 19px; font-weight: 700; line-height: 1.2; color: var(--band-ink); }
.showcase-lead { margin: 0; color: var(--band-ink-secondary); font-size: 14.5px; font-weight: 400; line-height: 1.5; }
ul.points { list-style: none; margin: var(--space-l) 0 0; padding: 0; }
li.point { border-top: 1px solid var(--band-track); padding: var(--space-l) 0 0; margin: var(--space-l) 0 0; }
li.point:first-child { border-top: none; padding-top: 0; margin-top: 0; }
.point-name { margin: 0; font-size: 14.5px; font-weight: 700; line-height: 1.5; color: var(--band-ink); }
.point-copy { margin: var(--space-xxs) 0 0; color: var(--band-ink-secondary); font-size: 14.5px; font-weight: 400; line-height: 1.5; }

.shots { display: flex; gap: var(--space-ml); margin: var(--space-xl) 0 0; }
.shots img {
  display: block;
  min-width: 0;
  flex: 1;
  height: auto;
  border-radius: var(--radius-md);
  border: 1px solid var(--overlay-border);
}

.shots.single { justify-content: center; }
.shots.single img { flex: 0 1 248px; }

@media (min-width: 900px) {
  :root { --col-half: 430px; }
  .slab.carousel {
    grid-template-areas:
      "prev track next"
      "dots dots dots";
    column-gap: var(--space-ml);
    padding-inline: max(var(--space-xl),
                        calc(50vw - var(--col-half) - var(--arrow) - var(--space-ml)));
  }

  .showcase {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 250px;
    column-gap: var(--space-empty-state);
    align-items: center;
  }
  /* A slide that wants its screenshot on the left swaps the two columns and
     sends the text after it. Only the picture column moves — the text stays
     the wide one either way. */
  .showcase.flip { grid-template-columns: 250px minmax(0, 1fr); }
  .showcase.flip .showcase-text { order: 2; }
  .showcase-text { align-self: start; }
  .shots { flex-direction: column; margin: 0; }
  .shots img, .shots.single img { flex: 0 0 auto; width: 100%; }

  /* The promise takes the slab's full content width, not a measure of its
     own: a showcase spans the same slab with its text column and its
     screenshot together, so a 640px cap here stopped the opening block a
     picture's width short of where every section below it ends. */
}
