/* ============================================================
   Refresh Health — components.css
   The three blocks that repeat on ALL pages (header, partner-with-us
   CTA, footer), the two small shared bits (.pill-button,
   .section-marker), and .reveal — the arrival primitive the page
   stylesheets spend on their own sections.

   Requires base.css to be loaded first.

   MARKUP LIVES IN ASTRO, NOT HERE. The components in src/components/
   are the single source of truth for the skeletons these rules style:

     .site-header / .button-bar ... src/components/Header.astro
                                    src/components/ButtonBar.astro
     .partner-cta / .pill-button .. src/components/PartnerCta.astro
     .site-footer / .contact-item . src/components/Footer.astro
     .section-marker .............. used inline by the pages that need it

   Two things about that markup are load-bearing here:

   - The header is transparent: whatever band it sits on supplies the
     background. On pages where it overlays a hero, the hero is
     position: relative and the header is its first child.
   - .button-bar__spotlight is required markup, but the hover/focus
     spotlight that moves it is JS (ButtonBar.astro) and pure
     enhancement — without the script it stays at width/height 0 and
     the :hover / [aria-current] rules below carry the bar on their own.

   ============================================================ */

/* ============================================================
   THE GLASS MATERIAL
   ============================================================
   The site has exactly one authored material, and this is the only
   place it is described. Every surface made of it is listed here; each
   of those rules then supplies nothing but its own geometry — radius,
   padding, layout. Retune the material in :root (the --glass-* group in
   base.css), not here, and every surface below follows.

   Two of these selectors are defined in page stylesheets rather than in
   this file, which is the one deliberate exception to "components.css
   holds only what repeats on all pages": the material is shared even
   where the box using it is not, and splitting it back across four
   files is what let the recipe drift in the first place.

   .feature__card is the only surface with an accent under the glass, so
   the tint inset is carried here with a transparent default — a card
   sets --card-tint, nothing else does, and the layer costs the others
   nothing.

   .pill-button is glass too but is NOT in this list: its background is
   a three-layer padding-box/border-box composite that paints its own
   gradient border, so it can only share the shadow and the blur. It
   spends the same --glass-* tokens where it can. */
.site-header .logo,
.button-bar,
.partner-cta__overlay,
.hero__panel,
.feature__card {
  border: 1px solid var(--glass-border);
  background: var(--glass-fill);
  box-shadow:
    inset 0 1px 0 var(--glass-highlight),
    inset 4px 4px 16px var(--card-tint, transparent),
    var(--glass-shadow);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
}

/* Bars, gradients and shadows still read as "glass" without the blur;
   this keeps the fill from washing out to near-invisible white. One
   block for every surface above, for the same reason. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header .logo,
  .button-bar,
  .partner-cta__overlay,
  .hero__panel,
  .feature__card { background: var(--glass-fallback); }
}

/* ============================================================
   Shared: logo lockup (header + footer)
   ============================================================ */

.logo {
  display: inline-flex;
  align-items: center;
  flex: none;
  transition: opacity var(--transition);
}

.logo:hover { opacity: 0.75; }

.logo-img {
  width: clamp(124px, 11vw, 154px);
  height: auto;
}

/* Header only: same frosted-glass pill as .button-bar, sized to sit
   behind the logo so the two glass shapes read as one family inline
   across the header row. Hover/press states mirror .button-bar__item
   (brighten the glass, lift, press) minus the traveling spotlight,
   which needs more than one item to travel between. */
.site-header .logo {
  padding: clamp(10px, 1.4vw, 16px) clamp(18px, 2.4vw, 26px);
  border-radius: var(--radius-pill);
  transition: opacity var(--transition), background var(--transition), border-color var(--transition), transform var(--transition-fast);
}

.site-header .logo:hover {
  opacity: 1;
  background: var(--glass-hover-fill);
  border-color: var(--glass-hover-border);
  transform: translateY(-1px);
}

.site-header .logo:active {
  transform: translateY(0) scale(0.96);
  transition-duration: 90ms;
}

/* ============================================================
   1. Site header
   ============================================================ */

.site-header {
  position: relative;
  z-index: 5;
  background: transparent;
}

.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm) var(--space-lg);
  padding-block: clamp(20px, 2.4vw, 34px);
}

/* Button bar: groups the primary nav links into one frosted-glass pill.
   The bar is a single glass layer (blur + translucent fill + soft
   border); the active/hover link is a second, brighter glass layer
   riding on top of it — "glass on glass" — built from gradients and
   inset highlights rather than a nested backdrop-filter, which would
   double the blur cost for no visible gain at this size. */
.button-bar {
  position: relative;
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 5px;
  border-radius: var(--radius-pill);
}

/* The traveling spotlight: a second glass pane, positioned by JS to
   exactly cover whichever item has hover or keyboard focus, that
   glides between items instead of popping per-button. Sits under the
   item content (z-index 0 vs. items' z-index 1) and costs nothing at
   rest — opacity 0, no listeners firing — until a pointer or focus
   event moves it. Falls back cleanly to the item's own :hover /
   [aria-current] styling below if JS never runs. */
.button-bar__spotlight {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
  width: 0;
  height: 0;
  border-radius: var(--radius-pill);
  background: var(--glass-raised-fill);
  border: 1px solid var(--glass-raised-border);
  box-shadow:
    inset 0 1px 0 var(--glass-raised-highlight),
    var(--glass-raised-shadow);
  opacity: 0;
  pointer-events: none;
  transition:
    transform 320ms cubic-bezier(0.16, 1, 0.3, 1),
    width 320ms cubic-bezier(0.16, 1, 0.3, 1),
    height 320ms cubic-bezier(0.16, 1, 0.3, 1),
    opacity 160ms ease;
}

.button-bar__item {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px clamp(14px, 1.8vw, 22px);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-nav);
  font-weight: 400;
  font-size: 13px;
  line-height: 1.2;
  letter-spacing: 0.02em;
  color: var(--ink);
  background: transparent;
  transition: background var(--transition), border-color var(--transition), box-shadow var(--transition), transform var(--transition-fast);
}

.button-bar__item:hover {
  background: var(--glass-hover-fill);
  border-color: var(--glass-hover-border);
  transform: translateY(-1px);
}

.button-bar__item:active {
  transform: translateY(0) scale(0.96);
  transition-duration: 90ms;
}

.button-bar__item[aria-current="page"] {
  font-weight: 500;
  background: var(--glass-current-fill);
  border-color: var(--glass-current-border);
  box-shadow:
    inset 0 1px 0 var(--glass-current-highlight),
    var(--glass-current-shadow);
}

.button-bar__icon {
  flex: none;
  width: 22px;
  height: auto;
  transition: transform var(--transition-fast);
}

.button-bar__item:hover .button-bar__icon,
.button-bar__item:focus-visible .button-bar__icon {
  transform: translateY(-1px) scale(1.06);
}

/* Bars, gradients and shadows still read as "glass" without the blur;
   this just keeps the fill from washing out to near-invisible white. */


/* Under 720px the logo keeps the first row and the bar drops to a
   second, full-width row. No JS, no hamburger. */
@media (max-width: 720px) {
  .site-header__inner { justify-content: flex-start; }

  .button-bar {
    width: 100%;
    flex-wrap: wrap;
  }

  .button-bar__item { flex: 1 1 auto; justify-content: center; }
}

/* ============================================================
   2. Partner with us
   ============================================================ */

.partner-cta {
  display: grid;
  grid-template-columns: 710fr 730fr;   /* Figma: 710px photo | 730px panel */
}

.partner-cta__media {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: clamp(276px, 38vw, 546px);
  padding: var(--space-lg);
  overflow: hidden;
}

.partner-cta__photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The Figma export washes the photo out with a 39% white scrim. */
.partner-cta__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--scrim-photo);
}

/* Same frosted-glass recipe as .button-bar / .site-header .logo /
   .pill-button / the page hero panels, so this window reads as the
   same material — sized to hug the title + lead rather than a fixed
   width, since the flex column already shrinks to its content. */
.partner-cta__overlay {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(18px, 2.3vw, 33px);
  padding: clamp(28px, 4vw, 48px) clamp(32px, 5vw, 64px);
  border-radius: var(--radius-lg);
  text-align: center;
  color: var(--ink);
}

.partner-cta__title {
  font-family: var(--font-heading);
  font-size: clamp(30px, 3vw, 44px);
  line-height: 1.05;
  letter-spacing: 0.02em;
  color: var(--ink);
}

.partner-cta__lead {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: clamp(14px, 1.2vw, 17px);
  line-height: 1.25;
  letter-spacing: 0.01em;
  color: var(--ink);
}

.partner-cta__panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(20px, 3.6vw, 51px);
  padding: clamp(32px, 4.5vw, 64px) clamp(24px, 6.5vw, 93px);
  background: var(--surface-band);
}

@media (max-width: 900px) {
  .partner-cta { grid-template-columns: 1fr; }
}

/* ============================================================
   Shared: pill button
   ============================================================ */

.pill-button {
  /* Figma fills the pill with --band at 45% on top of the --band band,
     i.e. the fill resolves to the band colour. It is exposed as --pill-fill so a
     page can re-point the button at a different background; the padding-box
     layers stay opaque underneath (fill + white sheen) so the 1px gradient
     border doesn't bleed across the button. The sheen opacity and blur match
     .button-bar's glass treatment so header and footer buttons read as the
     same material. */
  --pill-fill: var(--band);
  --pill-sheen-top: var(--glass-fill-top);
  --pill-sheen-bottom: var(--glass-fill-bottom);

  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: clamp(14px, 2.1vw, 30px);
  width: 100%;
  max-width: 410px;
  min-height: clamp(64px, 6.8vw, 98px);
  padding: var(--space-sm) clamp(18px, 3.2vw, 46px);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background:
    linear-gradient(180deg, var(--pill-sheen-top), var(--pill-sheen-bottom)) padding-box,
    linear-gradient(var(--pill-fill), var(--pill-fill)) padding-box,
    var(--gradient-brand-edge) border-box;
  box-shadow:
    inset 0 1px 0 var(--glass-highlight),
    var(--glass-shadow);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  font-family: var(--font-nav);
  font-weight: 400;
  font-size: clamp(15px, 1.7vw, 24px);
  line-height: 1.1;
  letter-spacing: 0.02em;
  color: var(--ink);
  transition: transform var(--transition), background var(--transition);
}

.pill-button:hover {
  --pill-sheen-top: color-mix(in srgb, var(--white) 45%, transparent);
  --pill-sheen-bottom: color-mix(in srgb, var(--white) 15%, transparent);
  transform: translateY(-2px);
}

.pill-button__icon {
  flex: none;
  width: clamp(22px, 2.4vw, 34px);
  height: auto;
}

.pill-button__icon--mail {
  width: clamp(19px, 2.1vw, 30px);
}

@media (prefers-reduced-motion: reduce) {
  .pill-button:hover { transform: none; }
}

/* ============================================================
   3. Site footer
   ============================================================ */

.site-footer {
  background: var(--surface);
}

.site-footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm) clamp(32px, 5.8vw, 84px);
  min-height: 57px;
  padding-block: clamp(20px, 2.4vw, 34px);
}

.contact-list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs) clamp(28px, 5.6vw, 80px);
}

.contact-item {
  display: inline-flex;
  align-items: center;
  gap: clamp(14px, 2vw, 28px);
  font-family: var(--font-nav);
  font-weight: 400;
  font-size: clamp(16px, 1.4vw, 20px);
  line-height: 1.2;
  letter-spacing: 0.04em;
  color: var(--ink);
}

a.contact-item {
  transition: opacity var(--transition);
}

a.contact-item:hover { opacity: 0.65; }

.contact-item__icon {
  flex: none;
  height: auto;
}

.contact-item__icon--location,
.contact-item__icon--phone { width: clamp(15px, 1.55vw, 21px); }

/* ============================================================
   4. Section marker
   ============================================================ */

.section-heading {
  display: flex;
  align-items: center;
  gap: clamp(16px, 2.4vw, 34px);
}

.section-marker {
  flex: none;
  width: clamp(16px, 1.5vw, 21.5px);
  height: auto;
}

.who-we-are .section-marker {
  width: clamp(20px, 2.5vw, 36px);
}

/* ============================================================
   5. Scroll reveal

   The site's arrival primitive. Sections do not sit finished on the
   page waiting to be scrolled past — they land as they are reached,
   and then they are simply the page as drawn.

   Two rules govern everything below, and both are borrowed from the
   approach diagram, which had to solve the same problem first:

   1. Every entrance ends exactly on the authored value, and the end
      state is `transform: none` rather than a zeroed translate — so a
      settled element carries no residual transform, holds no
      compositing layer, and is not a containing block for anything
      positioned inside it.
   2. The still frame IS the page. Nothing here applies until the
      runtime arms it by putting .reveals-armed on <html> — see the head
      script in BaseLayout.astro. No JS, no IntersectionObserver, or a
      stated preference for stillness, and every rule below is dead
      weight: the page renders finished, which is the honest default.

   Applied per page (which element gets which material, and in what
   order) in home.css and platform.css. The observer that adds
   .is-revealed is in BaseLayout.astro.
   ============================================================ */

/* Everything a page needs to vary — the entrance transform, the duration,
   the delay — is a custom property rather than a declaration to override.
   That is not tidiness: an override of `transform` written in a page
   stylesheet would land at the same specificity as the .is-revealed rule
   below and, loading later, would win it. Composed through variables, a
   page can author any entrance it likes and the arrival still resolves.

   --reveal-rest is the transform the element wears when it is finished:
   empty for almost everything (hence `transform: none`, which leaves no
   compositing layer and no containing block behind), and set only where
   the artwork itself is already transformed — the rotated hero decor on
   /platform/ would otherwise unrotate itself as it landed.

   Longhand transition properties, deliberately: the variants below extend
   transition-property with a third and fourth property, and with the
   shorthand each would have to restate duration, easing and delay to do
   it. */
.reveals-armed .reveal {
  opacity: 0;
  transform: var(--reveal-rest, ) var(--reveal-from, translateY(var(--reveal-shift, 14px)));
  transition-property: opacity, transform;
  transition-duration: var(--reveal-duration, var(--reveal-base));
  transition-timing-function: var(--reveal-ease);
  transition-delay: var(--reveal-delay, 0ms);
}

/* --reveal-opacity is the same idea as --reveal-rest, for the other half
   of the entrance: an element the artwork holds under full strength — the
   hero decor on /platform/ is drawn at 0.85 and 0.9 — has to land there
   and not on 1, or the reveal quietly restyles the page it introduces. */
.reveals-armed .reveal.is-revealed {
  opacity: var(--reveal-opacity, 1);
  transform: var(--reveal-rest, none);
}

/* ---------- Materials ----------
   Chosen by what the thing IS, not by where it falls in the scroll. One
   entrance repeated down every section is the failure mode this set
   exists to avoid. */

/* A pane of the site's one authored material. It settles the last few
   pixels down and in from a hair under full size — glass arriving on a
   surface, not a card sliding in. */
.reveals-armed .reveal--glass {
  --reveal-from: translateY(20px) scale(0.985);
  --reveal-duration: var(--reveal-long);
}

/* The same pane, on every hero, with the frost setting in as it lands:
   the backdrop is untouched at the start and reaches --glass-blur — the
   material's own token, so tuning the glass tunes what the reveal lands
   on — exactly as the pane comes to rest. Guarded by the same @supports
   the material itself uses: where there is no backdrop-filter there is
   nothing to resolve, and the pane just settles. */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .reveals-armed .reveal--frost {
    -webkit-backdrop-filter: blur(0px) saturate(100%);
    backdrop-filter: blur(0px) saturate(100%);
    transition-property: opacity, transform, backdrop-filter, -webkit-backdrop-filter;
  }

  .reveals-armed .reveal--frost.is-revealed {
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
  }
}

/* A rule. The site separates things with 2.5px lines and 1px hairlines,
   and a line arrives the way a line is made: drawn from its own start,
   not faded up. Clipped rather than scaled so the stroke keeps its
   weight for the whole draw. */
.reveals-armed .reveal--rule {
  --reveal-from: none;
  --reveal-duration: var(--reveal-quick);
  opacity: 1;
  clip-path: inset(0 100% 0 0);
  transition-property: clip-path;
}

.reveals-armed .reveal--rule.is-revealed {
  clip-path: inset(0 0 0 0);
}

/* A container that carries the trigger but does not move: the arrival is
   its rule, drawn on a pseudo-element, or its children. */
.reveals-armed .reveal--still {
  --reveal-from: none;
  opacity: 1;
}

/* ---------- The one shared block that arrives: Partner with us ----------
   Every page ends on it, so it is the last thing that lands on all of
   them: the window frosts over the photograph, and the two ways forward
   rise under it in the order they are read. */

.reveals-armed .partner-cta__panel .pill-button:nth-child(1) { --reveal-delay: 140ms; }
.reveals-armed .partner-cta__panel .pill-button:nth-child(2) { --reveal-delay: 230ms; }

/* A page that renders finished is the correct page. If the preference is
   stated after the observer has already armed itself, everything not yet
   reached simply appears — and paper has no viewport to arrive into, so a
   printed page is the whole page whether or not it was ever scrolled. */
@media (prefers-reduced-motion: reduce), print {
  .reveals-armed .reveal {
    opacity: var(--reveal-opacity, 1);
    transform: var(--reveal-rest, none);
    clip-path: none;
  }
}
