/* CocoBuddy press page.
   The tokens, sky and footer rules are copied from landing.css by
   selector. Why copied and not linked: the landing stylesheet's scroll lock
   and card geometry are landing-only, and the landing page is never edited. */

@font-face {
  font-family: "Momo Trust Display";
  src: url("../fonts/MomoTrustDisplay-Regular.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Momo Trust Sans";
  src: url("../fonts/MomoTrustSans-Regular.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Momo Trust Sans";
  src: url("../fonts/MomoTrustSans-Semibold.woff2") format("woff2");
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: "Momo Trust Sans";
  src: url("../fonts/MomoTrustSans-Bold.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
}

:root {
  /* palette */
  --cream: #FFF7ED;
  --navy: #373A60;
  --muted: #5C5F86;
  --yellow: #FFE875;

  /* motion */
  --cloud-speed: 1;
  /* Why: the cloud loop distance is one sky width, in a unit that does not
     resize with a parent. Percentages of a resizing parent made them jump. */
  --track-w: 100vw;

  /* Why: every height-relative value is declared in vh here and re-declared
     in svh inside the @supports block below. A custom property accepts any
     token stream at parse time, so a plain "fallback first" pair does NOT
     protect against an engine that cannot resolve svh. The @supports gate is
     the only construction that actually degrades. */
  /* Why: --sky-base is the art scale (sun, clouds, wordmark); --sky-h is the
     band's own height. */
  --sky-base: clamp(120px, 20vh, 190px);
  --sun-w: calc(var(--sky-base) * 0.9);
  --cloud-back-w: calc(var(--sky-base) * 1.25);
  --cloud-front-w: calc(var(--sky-base) * 0.85);
  --cloud-back-x: -100px;
  --cloud-front-x: calc(var(--track-w) * 0.72);
  /* the wordmark art is 760 x 554 (ratio 1.3718). The 1.3705 below was
     computed from the original 2922 x 2132 source and is kept: the two
     ratios differ by 0.15 px at the widest the art ever renders. */
  --wordmark-w: min(calc(var(--sky-base) * 0.98), 58vw);
  --wordmark-h: calc(var(--wordmark-w) / 1.3705);
  --wordmark-top: calc(var(--sky-base) * 0.09);
  /* the strip of sky under the wordmark */
  --sky-below: clamp(8px, 1.4vh, 12px);
  --sky-h: calc(var(--wordmark-top) + var(--wordmark-h) + var(--sky-below));

  --measure: 62ch;
}

/* Why: svh is the better unit on a phone (it ignores the collapsing toolbar,
   so the layout does not jump), but it must never be the only definition. */
@supports (height: 1svh) {
  :root {
    --sky-base: clamp(120px, 20svh, 190px);
    --sky-below: clamp(8px, 1.4svh, 12px);
  }
}

@media (min-width: 720px) {
  :root {
    --sky-base: clamp(140px, 17vh, 190px);
    --sky-h: var(--sky-base);
    /* Why: at 1.15 the art ends at 93% of the sky height at every size. */
    --wordmark-w: min(calc(var(--sky-base) * 1.15), 30vw);
  }
}

@supports (height: 1svh) {
  @media (min-width: 720px) {
    :root {
      --sky-base: clamp(140px, 17svh, 190px);
    }
  }
}

/* Why: below ~560px tall there is no height left to scale into, so the sky
   stops scaling by viewport height and uses fixed phone-sized values. */
@media (max-height: 560px) {
  :root {
    --sky-base: 96px;
    --sky-h: 96px;
    --wordmark-w: 150px;
    --wordmark-top: 3px;
  }
}

/* ---------- base ---------- */

* { box-sizing: border-box; }

/* Why: root overflow propagates to the viewport, so a wide child can never
   raise a horizontal scrollbar on the page. */
html { overflow-x: hidden; }

body {
  margin: 0;
  background: var(--cream);
  color: var(--navy);
  font-family: "Momo Trust Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-weight: 400;
  font-size: 17px;
  line-height: 1.55;
  -webkit-text-size-adjust: 100%;
}

@media (min-width: 640px) {
  body { font-size: 18px; }
}

img {
  user-select: none;
  -webkit-user-drag: none;
}

/* ---------- sky ---------- */

.sky {
  position: relative;
  width: 100%;
  height: var(--sky-h);
  overflow: hidden;
}

.sky-art {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.sun {
  position: absolute;
  width: var(--sun-w);
  height: auto;
  top: -26px;
  right: -40px;
  z-index: 1;
}

.wordmark {
  /* Why: centred by auto margins between left:0 and right:0, not by
     translateX(-50%). A transform is the one thing on this element that any
     other rule or animation shorthand can overwrite, and when it is lost the
     art lands at the sky's left edge at its natural 760px width and is
     clipped. Auto margins cannot be lost that way. */
  position: absolute;
  z-index: 5;
  top: var(--wordmark-top);
  left: 0;
  right: 0;
  margin-inline: auto;
  display: block;
  width: var(--wordmark-w);
  max-width: 100%;
}

/* Why: the wordmark is the page's link home, so the anchor carries the
   position and width and the art fills it. The clamp stays on the image, with
   object-fit, so a short viewport letterboxes the art instead of overflowing
   the anchor. */
.wordmark img {
  display: block;
  width: 100%;
  height: auto;
  /* belt and braces: never taller than the sky that clips it */
  max-height: calc(var(--sky-h) - var(--wordmark-top) - 4px);
  object-fit: contain;
}

.cloud-track {
  position: absolute;
  left: 0;
  width: calc(var(--track-w) * 2);
  display: flex;
  z-index: 0;
}

.cloud-slot {
  flex: 0 0 var(--track-w);
  position: relative;
  height: 1px;
}

.cloud-slot img {
  position: absolute;
  top: 0;
  height: auto;
}

.cloud-track--back {
  top: 6px;
  animation: drift-right calc(420s / var(--cloud-speed)) linear infinite;
}
.cloud-track--back img {
  width: var(--cloud-back-w);
  left: var(--cloud-back-x);
}

.cloud-track--front {
  top: calc(var(--sky-base) * 0.46);
  animation: drift-left calc(280s / var(--cloud-speed)) linear infinite;
}
.cloud-track--front img {
  width: var(--cloud-front-w);
  left: var(--cloud-front-x);
}

/* Why: on a phone the band (--sky-h) is shorter than the art scale
   (--sky-base), so below the desktop breakpoint both tracks are re-anchored
   to the BAND instead: the front cloud is parked a fixed 8px clear of the
   band's bottom, and the back cloud keeps its old proportion of the band.
   The two heights are the art's own aspect ratios: CloudFront is 493x262,
   CloudBack is 732x320. */
@media (max-width: 719px) {
  :root {
    --cloud-front-h: calc(var(--cloud-front-w) / 1.8817);
    --cloud-back-h: calc(var(--cloud-back-w) / 2.2875);
  }
  .cloud-track--front {
    top: max(0px, calc(var(--sky-h) - var(--cloud-front-h) - 8px));
  }
  .cloud-track--back {
    top: calc(var(--sky-h) * 0.59 - var(--cloud-back-h));
  }
}

/* Why: the loop travels exactly one track width, so the second copy lands
   where the first started and the wrap is seamless at any size. */
@keyframes drift-right {
  from { transform: translateX(calc(-1 * var(--track-w))); }
  to   { transform: translateX(0); }
}
@keyframes drift-left {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(-1 * var(--track-w))); }
}

@media (prefers-reduced-motion: reduce) {
  .cloud-track--back,
  .cloud-track--front {
    animation: none;
  }
  .cloud-track--back { transform: translateX(calc(-1 * var(--track-w))); }
  .cloud-track--front { transform: translateX(0); }
}

/* ---------- column ---------- */

/* Why: the content measure is 62ch inside 20px gutters. */
.wrap {
  /* Why: WebKit paints the selection gaps between lines out to the nearest
     positioned or clipped ancestor, so without this a selection inside the
     column highlights the full width of the viewport. */
  position: relative;
  max-width: calc(var(--measure) + 40px);
  margin: 0 auto;
  padding: 0 20px 48px;
}

/* ---------- story ---------- */

/* Why: a one-column grid on a phone, where the photos split around the text by
   order alone while the markup keeps the text and its photos in reading order
   for a screen reader. */
.story {
  display: grid;
  grid-template-columns: 1fr;
  margin-top: 72px;
}

/* Why: the two photos stack as one column beside the text, so they keep their
   own 4:3 shape instead of being stretched to the text's height. */
.story-photos {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* Why: both photos are 4:3 exports, so the box matches the file and object-fit
   only has to absorb rounding. */
.photo {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 18px;
  border: 3px solid var(--navy);
  margin: 0;
}

.story p {
  /* Why: Alice asked for clearer breaks between the story paragraphs on a phone (2026-09-21). */
  margin: 22px 0 0;
}

/* Why: below the desktop breakpoint the photo wrapper dissolves so its two
   photos join the story grid directly, letting the family photo lead and the
   lovies photo close the section with the text between them. */
@media (max-width: 719px) {
  .story {
    display: grid;
    grid-template-columns: 1fr;
    row-gap: 24px;
  }
  .story-photos { display: contents; }
  .photo--family { order: -1; }
  .story-text { order: 0; }
  .photo--lovies { order: 1; }
}

/* Why: from the desktop breakpoint the text and the photo column are two equal
   columns starting at the same top line, so "Our story" sits level with the top
   of the family photo. */
@media (min-width: 720px) {
  .story {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 32px;
    align-items: start;
  }
}

/* ---------- links and focus ---------- */

a,
.dl {
  color: var(--navy);
  text-decoration: underline;
  text-underline-offset: 2px;
  font-weight: 700;
}

a:hover,
a:focus-visible { text-decoration-thickness: 2px; }

/* Why: an email address is one unbreakable token, so at large text sizes it is
   wider than a phone column and spills past the viewport edge. */
a[href^="mailto:"] { overflow-wrap: anywhere; }

:focus-visible {
  outline: 3px solid var(--navy);
  outline-offset: 3px;
}

.dl {
  display: inline-block;
  min-height: 44px;
  line-height: 44px;
}

/* ---------- band ---------- */

/* Why: the band groups the reference sections that follow the kit. Its own
   top margin is smaller than a section's, so the gap above "Features" is the
   normal gap between sections. */
.band {
  margin-top: 20px;
  padding-top: 0;
  padding-bottom: 28px;
}

.band h2,
.story h2,
.section h2 {
  font-family: "Momo Trust Display", Georgia, serif;
  font-weight: 400;
  font-size: 1.5rem;
  line-height: 1.2;
  margin: 28px 0 10px;
}

/* Why: from the desktop breakpoint the story heading starts the text column, so
   it drops the shared heading's top margin and aligns with the top of the first
   photo beside it. On a phone the family photo leads instead, and the heading
   keeps its margin so it is not flush against that photo's bottom edge.
   The block sits after the shared h2 rule on purpose: the two selectors have
   equal specificity, so source order is what decides. */
@media (min-width: 720px) {
  .story h2 { margin-top: 0; }
}

.features { padding: 0 0 0 1.1em; margin: 0; }
.features li { margin: 6px 0; }

.section { margin-top: 36px; }

/* ---------- press kit ---------- */

/* Why: the kit is its own block under the story, so it takes a wider gap than
   the gap between two ordinary sections. */
.kit {
  margin-top: 64px;
  /* Why: /press#kit still points at the kit, so it keeps the anchor offset. */
  scroll-margin-top: 64px;
}

/* Why: "Brand assets" and "Screenshots" sit inside the kit, so they are one
   step down from its h2 in both level and size. */
.kit h3 {
  font-family: "Momo Trust Display", Georgia, serif;
  font-weight: 400;
  font-size: 1.3rem;
  line-height: 1.2;
  margin: 32px 0 8px;
}

/* Why: the kit opens straight into "Brand assets", so the first inner section
   drops its own top margin and its heading alone sets the gap under the usage
   note. A heading inside .section-head is a flex item, so its margin cannot
   collapse into the section's and the two would otherwise add up. */
.kit > .section:first-of-type { margin-top: 0; }
.kit > .section:first-of-type .section-head h3 { margin-top: 28px; }

/* ---------- downloads ---------- */

/* Why: each section owns its zip, so the "Download all" link is a pill that
   rides in the section head row next to the heading. inline-flex centres the
   label inside the 44px tap target without changing the pill's own width. The
   label is allowed to wrap: at large text sizes it is wider than a phone
   column, and nowrap pushed it past the viewport edge where the page's
   overflow-x: hidden clipped it. */
.dl-big {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 10px 18px;
  margin: 0;
  background: var(--navy);
  color: var(--cream);
  text-decoration: none;
  border-radius: 999px;
  text-align: center;
  line-height: 1.2;
}

.dl-big:hover,
.dl-big:focus-visible { text-decoration: underline; }

/* Why: the usage note now follows the "Press kit" heading directly, so it
   sits tight under it and reads as part of that heading's group. */
.intro-note {
  color: var(--muted);
  margin: 8px 0 0;
}

/* Why: the heading and its pill share one row, centred on each other. On a
   phone the pill wraps under the heading and stays left aligned, so row-gap
   sets the space between the two rows. */
.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  row-gap: 10px;
}

/* Why: the heading keeps its own vertical margins (a large top, a small
   bottom) and a flex row centres margin boxes, not border boxes, so an
   uncompensated pill rides high against the heading. Matching the difference
   between the heading's two margins puts the pair on one optical line. Only
   from the desktop breakpoint, where the two actually share a row - below it
   the pill wraps and row-gap alone sets the space. */
@media (min-width: 720px) {
  .section-head .dl-big { margin-top: 24px; }
  .kit > .section:first-of-type .section-head .dl-big { margin-top: 20px; }
}

/* Why: two cards across on a phone, three from the desktop breakpoint, and
   both grids use the same track count so the two sections line up. */
.cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  padding: 0;
  margin: 12px 0 0;
  list-style: none;
}

@media (min-width: 720px) {
  .cards { grid-template-columns: repeat(3, 1fr); }
}

/* Why: a square white tile keeps the five brand files on one baseline
   whatever their own aspect ratios are. */
.card-art {
  background: #fff;
  border: 2px solid var(--navy);
  border-radius: 14px;
  padding: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1 / 1;
}

.card-art img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
}

/* Why: a screenshot fills its tile at the frame's own tall ratio instead of
   sitting small inside a square. */
.cards--shots .card-art {
  aspect-ratio: 480 / 1043;
  padding: 0;
  overflow: hidden;
  background: var(--yellow);
}

.cards--shots .card-art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Why: the body is Regular now, so the card name would sit at the same weight
   as the .meta line under it. 600 keeps the name the heavier of the pair. */
.card-name {
  margin: 8px 0 0;
  font-weight: 600;
}

/* Why: .meta is a span inside .card-name, so it would inherit that 600. The
   explicit 400 holds it at the body weight and keeps the name the heavier
   of the two lines. */
.meta {
  display: block;
  color: var(--muted);
  font-size: 14px;
  font-weight: 400;
}

/* ---------- about ---------- */

.about-panel {
  background: #fff;
  border: 2px solid var(--navy);
  border-radius: 16px;
  padding: 14px 16px;
  margin: 0;
}

.about-panel p { margin: 0 0 12px; }
.about-panel p:last-child { margin-bottom: 0; }

/* ---------- facts ---------- */

/* Why: a fixed layout holds the two columns to the 34/66 split and the page
   width instead of letting the longest cell set the table's size, which at
   large text sizes pushed the table past the viewport where the page's
   overflow-x: hidden clipped the right-hand column. */
.facts {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}

.facts th,
.facts td {
  text-align: left;
  vertical-align: top;
  padding: 8px 0;
  border-top: 1px solid rgba(55, 58, 96, 0.14);
  /* Why: a fixed layout cannot widen for a long unbroken run, so the cell has
     to be allowed to break one rather than spill out of its column. */
  overflow-wrap: anywhere;
}

.facts th {
  width: 34%;
  color: var(--muted);
  font-weight: 700;
}

/* ---------- footer ---------- */

.footer {
  margin: 40px auto 0;
  width: 100%;
  max-width: 480px;
  padding: 12px 16px 16px;
  text-align: center;
}

.links {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  /* Why: 6px between the two phone rows as well as between the items. */
  gap: 6px;
  font-size: clamp(12px, 1.85svh, 14px);
}

/* Why: on a phone the family line does not fit on the links row, so it takes
   a full-width flex line of its own and everything else wraps below it. The
   inline separator only exists for the desktop one-row layout. */
.family { flex: 0 0 100%; }
.family-dot { display: none; }

.links a {
  color: var(--navy);
  text-decoration: none;
  font-weight: 600;
}
.links a:hover,
.links a:focus-visible { text-decoration: underline; }
.dot { color: var(--muted); }

/* Why: on a phone the family line sits on a row of its own above the nav
   links, where full navy made it read as the loudest thing in the footer.
   The muted navy drops it back (5.76:1 on the cream, so it still clears
   4.5:1). Desktop keeps it inline in link colour. */
@media (max-width: 719px) {
  .links a.family { color: var(--muted); }
}

@media (min-width: 720px) {
  .footer { max-width: none; }
  .family { flex: 0 1 auto; }
  .family-dot { display: inline; }
}

/* Why: screen-reader-only. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
