/* Shared chrome for alpinevelo.ai. Everything here is a web translation of the
   App Store frame recipe in app-store/appStoreImagesV1/build-frames.mjs — same
   plate-over-charcoal dissolve, same type treatment, same device edge. Keeping
   it in one file means the three pages can't drift apart. */

html { scroll-behavior: smooth; }
body { -webkit-font-smoothing: antialiased; }

/* ── The plate ──
   An alpine photograph occupying the top of a section and dissolving into the
   charcoal ground. Stop positions are lifted from build-frames.mjs:56-63: the
   scrim stays LIGHT where there's no type (.30 → .12) and thickens only where
   the headline sits, so the photograph survives instead of being flattened. */
/* Position/height come from utilities in the markup — deliberately NOT set here,
   so a Tailwind class and this rule can't fight over the same property. */
.plate { position: absolute; overflow: hidden; }
.plate img {
  width: 100%; height: 100%;
  object-fit: cover;
  /* Same grade as the store frames. */
  filter: saturate(0.92) brightness(0.94);
}
/* The hero is the one daylight plate on the site, and the whole point of it is
   the summer green — so it gets almost no grade. Every other plate is a dusk or
   night photograph that can afford to be pushed down; this one can't. */
.plate-hero img { filter: saturate(1.02) brightness(0.98) contrast(1.02); }

/* Its own scrim, opened up. The shared dissolve is tuned to crush a dark plate
   into the charcoal ground; run at those values it flattens the meadow into
   grey and the hero stops saying "summer". Left column still gets enough
   horizontal weight to hold white Playfair. */
.plate-hero::after {
  background:
    linear-gradient(to right,
      rgba(16, 18, 22, 0.62) 0%,
      rgba(16, 18, 22, 0.30) 42%,
      rgba(16, 18, 22, 0.04) 72%,
      rgba(16, 18, 22, 0.20) 100%),
    linear-gradient(to bottom,
      rgba(16, 18, 22, 0.30) 0%,
      rgba(16, 18, 22, 0.18) 18%,
      rgba(16, 18, 22, 0.46) 46%,
      rgba(16, 18, 22, 0.90) 74%,
      rgba(16, 18, 22, 0.99) 92%,
      #101216 100%);
}
.plate::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    /* Horizontal pass. The web layout puts copy on the left and the device on
       the right, which the portrait store frame never had to solve — this is
       what keeps the headline column readable over a bright patch of sky. */
    linear-gradient(to right,
      rgba(16, 18, 22, 0.72) 0%,
      rgba(16, 18, 22, 0.42) 42%,
      rgba(16, 18, 22, 0.10) 72%,
      rgba(16, 18, 22, 0.28) 100%),
    /* Vertical pass — the store-frame dissolve. */
    linear-gradient(to bottom,
      rgba(16, 18, 22, 0.30) 0%,
      rgba(16, 18, 22, 0.12) 24%,
      rgba(16, 18, 22, 0.52) 46%,
      rgba(16, 18, 22, 0.88) 74%,
      rgba(16, 18, 22, 0.99) 92%,
      #101216 100%);
}

/* Closing CTA runs the dissolve the other way: solid charcoal at the top of the
   section, opening into the photograph as the page ends. */
.plate-invert::after {
  background:
    linear-gradient(to bottom,
      #101216 0%,
      rgba(16, 18, 22, 0.97) 12%,
      rgba(16, 18, 22, 0.86) 30%,
      rgba(16, 18, 22, 0.72) 52%,
      rgba(16, 18, 22, 0.62) 78%,
      rgba(16, 18, 22, 0.70) 100%);
}

/* The interlude plate is the most saturated of the three daylight photographs.
   Left alone it shouts louder than the hero, which breaks the illusion that all
   three came off the same shoot — a mid-page moment shouldn't out-sing the top
   of the page. Pulled down just enough to sit with it. */
.plate-mid img { filter: saturate(0.86) brightness(0.9) contrast(1.03); }

/* Mid-page interlude: charcoal at BOTH ends, open in the middle, so the
   photograph surfaces out of the ground and sinks back into it. Breaks the long
   flat run of feature rows without introducing a new kind of section. */
.plate-mid::after {
  background:
    linear-gradient(to bottom,
      #101216 0%,
      rgba(16, 18, 22, 0.92) 10%,
      rgba(16, 18, 22, 0.50) 30%,
      rgba(16, 18, 22, 0.44) 62%,
      rgba(16, 18, 22, 0.86) 88%,
      #101216 100%);
}

/* Short plate for the secondary pages — a band, not a stage. */
.plate-band::after {
  background:
    linear-gradient(to bottom,
      rgba(16, 18, 22, 0.42) 0%,
      rgba(16, 18, 22, 0.30) 30%,
      rgba(16, 18, 22, 0.72) 62%,
      rgba(16, 18, 22, 0.96) 88%,
      #101216 100%);
}

/* ── Logo ──
   `logo.png` is a black disc with the mountain knocked out of it in white —
   drawn for a light page. On charcoal the disc sinks into the background and
   the glyph floats loose. Inverting flips it to a white disc with a dark
   mountain: legible on the dark ground, shape intact.

   NOT a mask. `mask-image` with a white fill would paint every opaque pixel —
   disc and glyph alike — and the mountain would disappear. The alpha channel
   here is only the disc's outer edge. */
.logo-invert { filter: invert(1); }

/* Type over a photograph. The shadow is what lets #ECEEF2 hold its edge on a
   bright patch of cloud — without it the headline dissolves into the sky. */
.on-plate  { text-shadow: 0 2px 40px rgba(0, 0, 0, 0.55); text-wrap: balance; }
.on-plate-sub { text-shadow: 0 2px 28px rgba(0, 0, 0, 0.5); }

/* ── Device ──
   build-frames.mjs:71-76, scaled for the web: a lit top edge, a hairline ring,
   and a drop deep enough to lift the screen off the charcoal.

   The store frame gets its depth from a photograph behind the device. On the
   flat sections there is nothing behind it, so a black drop shadow lands on a
   ground of the same value and does nothing. The last two shadows put the light
   back: a wide cool bloom and a tighter neutral one, so each phone sits IN
   space rather than ON a panel. */
.device {
  border-radius: 22px;
  overflow: hidden;
  box-shadow:
    0 -1px 0 rgba(255, 255, 255, 0.07) inset,
    0 0 0 1px rgba(255, 255, 255, 0.08),
    0 30px 70px rgba(0, 0, 0, 0.65),
    0 0 160px 50px rgba(76, 159, 255, 0.07),
    0 0 80px 8px rgba(236, 238, 242, 0.035);
}

/* ── Grain ──
   The plates are photographs; the charcoal between them is not, and an unbroken
   4,000px of #101216 reads as a flat panel. Fractal noise gives that ground the
   same material as the pictures it sits between. It deliberately sits OVER the
   content — that's what film does — which is safe at this opacity and with
   pointer-events off. */
.grain { position: relative; }
.grain::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 220px 220px;
  /* No blend mode: `overlay` and `soft-light` both multiply against a base this
     dark, which crushes the noise back to nothing. Painting mid-grey noise
     straight on at low alpha is what actually lifts the ground. */
  opacity: 0.05;
}

/* Light spilling down out of the hero, so the first flat section starts as a
   continuation of the photograph rather than a hard cut to panel. */
.spill { position: relative; }
.spill::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 380px;
  pointer-events: none;
  background:
    radial-gradient(70% 100% at 50% 0%, rgba(76, 159, 255, 0.07) 0%, transparent 70%),
    linear-gradient(to bottom, rgba(255, 255, 255, 0.035) 0%, transparent 100%);
}

/* ── Prose (privacy, support) ── */
.prose > * + * { margin-top: 1rem; }
.prose h2 { font-family: '"Playfair Display"', serif; }
.prose h2 + * { margin-top: 0.75rem; }
.prose ul { list-style: disc; padding-left: 1.25rem; }
.prose ul > li + li { margin-top: 0.4rem; }
.prose a { color: #4C9FFF; text-decoration: underline; text-underline-offset: 2px; }
.prose a:hover { color: #7FBBFF; }

/* ── App Store badge ──
   Apple's own artwork, pulled from the marketing toolbox (US/UK RGB, white
   lockup, 092917 revision) and served from our own origin so the primary CTA on
   the site can never be broken by someone else's CDN.

   The WHITE lockup is the one Apple specifies for a dark ground, and it is the
   only one that works here: the black badge is a black pill on #101216 and
   reads as a hole punched in the page, with nothing but its grey hairline
   holding the shape.

   Apple's rules this has to respect: don't redraw or recolour the artwork,
   don't crowd it, and leave clear space of at least a tenth of the badge height
   on every side. The padding is that clear space. The matching negative margin
   cancels it back out of the layout, so the artwork's own edge still lines up
   with the headline above it instead of sitting inset by the clear space.

   Height comes from a utility in the markup; width is always auto so the
   lockup can't be stretched. */
.app-badge {
  display: inline-block;
  padding: 0.4rem;
  margin: -0.4rem;
  border-radius: 12px;
  transition: opacity 0.15s ease;
}
.app-badge img { display: block; width: auto; }
.app-badge:hover { opacity: 0.88; }
/* Outline rather than a ring utility: the badge is its own shape, and a box
   shadow would paint a second rounded rect a few pixels off from the artwork. */
.app-badge:focus-visible { outline: 2px solid #4C9FFF; outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  .app-badge { transition: none; }
}
