/* Hero. Every value measured on fora.so section#hero at 1440 / 768 / 390.
   See docs/research/components/hero.spec.md for the provenance of each number.
   Framer breakpoints reproduced exactly: base >=1280, (min-width:810px) and (max-width:1023.98px), (max-width:809.98px). */

.gf-hero{
  --gf-hero-ease:cubic-bezier(.25,.27,.16,1);   /* fit to a critically damped spring, RMS 0.0064 */
  --gf-hero-dur:.8s;                            /* omega 9 rad/s  */
  --gf-hero-dur-bg:.4s;                         /* omega 17.6 rad/s, the gradient only */
  --gf-hero-par:0px;                            /* written by hero.js, per layer */
  --gf-hero-page:rgb(240,235,229);              /* sampled from the bottom edge of aurelle.jpg */

  position:relative;
  display:flex;
  flex-flow:row nowrap;
  justify-content:center;
  align-items:flex-start;
  width:100%;
  /* Full bleed. This used to be capped at 1920 from the Framer capture, and on a screen wider than
     that the hero alone sat in a 1920 box with black down both sides while every section under it
     ran edge to edge: the artwork read as a small picture of a hero rather than the hero. The three
     layer plates are 2464px wide natives and object-fit:cover, so they fill any width; the content
     column keeps its own 1080 cap below, which is what the measured layout actually depends on. */
  margin-inline:auto;
  padding:0 24px;
  overflow:clip;
}

/* ---------------------------------------------------------------- layer 1: gradient */
/* The foreground hills are opaque to their last row, and that row sits at about 2/255 while the page
   below is pure black. Two levels is nothing on its own, but it runs dead straight across the full
   width, so it reads as a drawn line. This fades the last strip of the hero down to the page black so
   the artwork meets it instead of stopping against it. The same step is present in frozen v2, measured
   identical, so this is a fix rather than a revert of anything. */
.gf-hero::after{
  content:"";
  position:absolute;
  left:0;
  right:0;
  bottom:0;
  height:120px;
  z-index:3;
  pointer-events:none;
  background-image:linear-gradient(180deg,rgba(0,0,0,0) 0%,rgba(0,0,0,.55) 55%,var(--bg) 100%);
}

.gf-hero-gradient{
  position:absolute;
  inset:0;
  z-index:0;
  overflow:clip;
  background-image:radial-gradient(200% 83% at 50% 0px,rgb(16,20,30) 0%,rgb(40,50,68) 44%,rgb(150,170,196) 100%);
}

/* ------------------------------------------------- layers 2, 3, 6: the three photo layers
   The layer div is bottom-anchored and carries the scroll parallax.
   Its child carries the entrance, so the two transforms never overwrite each other. */
.gf-hero-layer{
  position:absolute;
  z-index:0;
  left:0;
  right:0;
  transform:translate3d(0,var(--gf-hero-par),0);
}
.gf-hero-layer-in{width:100%;height:100%}
.gf-hero-layer picture{display:block;width:100%;height:100%}
.gf-hero-layer img{width:100%;height:100%;object-fit:cover;object-position:center}

.gf-hero-far{bottom:0;aspect-ratio:2.71067 / 1}
.gf-hero-near{bottom:1px;aspect-ratio:2.90566 / 1}
.gf-hero-fore{bottom:0;aspect-ratio:5.04918 / 1}

/* ---------------------------------------------------------------- layer 4: content column */
.gf-hero-content{
  position:relative;
  flex:1 0 0;
  display:flex;
  flex-flow:column nowrap;
  justify-content:center;
  align-items:center;
  gap:80px;
  max-width:1080px;
  padding:160px 0 0;
}

.gf-hero-text{
  display:flex;
  flex-flow:column nowrap;
  justify-content:center;
  align-items:center;
  gap:48px;
  flex:0 0 auto;
  width:100%;
  position:relative;
}
.gf-hero-head{
  display:flex;
  flex-flow:column nowrap;
  justify-content:center;
  align-items:center;
  gap:24px;
  flex:0 0 auto;
  width:100%;
}
.gf-hero-heading{
  display:flex;
  flex-flow:column nowrap;
  justify-content:center;
  align-items:center;
  gap:16px;
  flex:0 0 auto;
  width:100%;
}
/* v2: two calls to action sit side by side, so the row wraps rather than overflowing
   on a narrow phone. With a single 48px row on desktop the measured height is unchanged. */
.gf-hero-cta-row{
  display:flex;
  flex-flow:row wrap;
  justify-content:center;
  align-items:center;
  gap:12px;
  flex:0 0 auto;
  width:100%;
  min-height:48px;
}

/* --- pill */
.gf-hero-pill-wrap{flex:0 0 auto}
.gf-hero-pill{
  display:flex;
  flex-flow:row nowrap;
  justify-content:center;
  align-items:center;
  gap:12px;
  width:min-content;
  height:30px;
  padding:4px 12px;
  position:relative;
  overflow:hidden;
  border-radius:393px;
  background:var(--ink-10);
  font-size:14px;
  line-height:21px;
  letter-spacing:-.28px;
  font-weight:400;
  color:var(--ink-80);
  text-align:center;
  white-space:pre;
  text-wrap:nowrap;
}
.gf-hero-pill::after{
  content:"";
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  border:1px solid var(--ink-10);
  border-radius:inherit;
  box-sizing:border-box;
  pointer-events:none;
}

/* --- headline and sub */
.gf-hero-h1-wrap{flex:0 0 auto;width:840px;max-width:840px}
.gf-hero-h1{
  font-family:var(--font);
  font-size:56px;
  line-height:72.8px;
  letter-spacing:-2.24px;
  font-weight:400;
  color:var(--ink);
  text-align:center;
  text-wrap:balance;
}
.gf-hero-sub-wrap{flex:0 0 auto;width:420px;max-width:420px}
.gf-hero-sub{
  font-size:14px;
  line-height:21px;
  letter-spacing:-.28px;
  font-weight:400;
  color:var(--ink-80);
  text-align:center;
  text-wrap:balance;
}

/* --- CTA */
.gf-hero-cta-wrap{flex:0 0 auto}
.gf-hero-cta{
  display:flex;
  flex-flow:row nowrap;
  justify-content:center;
  align-items:center;
  width:min-content;
  height:48px;
  padding:0 36px;
  position:relative;
  overflow:clip;
  border-radius:768px;
  background-color:rgba(255,255,255,.8);
  cursor:pointer;
  text-decoration:none;
  transition:background-color .2s cubic-bezier(0,0,.58,1);
}
.gf-hero-cta::after{
  content:"";
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  border:1px solid var(--ink);
  border-radius:inherit;
  box-sizing:border-box;
  pointer-events:none;
}
.gf-hero-cta-label{
  font-size:14px;
  line-height:21px;
  letter-spacing:-.28px;
  font-weight:400;
  color:#000;
  white-space:pre;
  text-wrap:nowrap;
}
@media (hover:hover) and (pointer:fine){
  .gf-hero-cta:hover{background-color:var(--ink)}
}
.gf-hero-cta:focus-visible{background-color:var(--ink)}

/* --- secondary CTA (v2). The quiet counterpart to the filled pill: the same glass
   treatment the nav pill uses, so the pair reads as one family on the black ground. */
.gf-hero-cta--ghost{
  background-color:rgba(255,255,255,.1);
  -webkit-backdrop-filter:blur(5px);
  backdrop-filter:blur(5px);
  padding:0 28px;
}
.gf-hero-cta--ghost::after{border-color:var(--ink-10)}
.gf-hero-cta--ghost .gf-hero-cta-label{color:var(--ink)}
@media (hover:hover) and (pointer:fine){
  .gf-hero-cta--ghost:hover{background-color:rgba(255,255,255,.22)}
}
.gf-hero-cta--ghost:focus-visible{background-color:rgba(255,255,255,.22)}

/* ---------------------------------------------------------------- layer 5: the browser window */
.gf-hero-mockup{
  position:relative;
  flex:0 0 auto;
  width:100%;
  max-width:960px;
  aspect-ratio:1.42105 / 1;
  transform:translate3d(0,var(--gf-hero-par),0);
}
.gf-hero-window{
  position:relative;
  display:flex;
  flex-flow:column nowrap;
  width:100%;
  height:100%;
  gap:6px;
  padding:6px;
  overflow:clip;
  border-radius:24px 24px 0 0;
  /* No backdrop-filter here. The surface is 90% opaque, so a blur of what is behind it was worth
     almost nothing visually, but the hills parallax behind this box while you scroll, so the blur was
     recomputed over a 960x675 area on every frame of the scroll through the hero. */
  background-color:rgba(23,23,23,.9);
}
.gf-hero-window::after{
  content:"";
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  border:1px solid var(--ink-10);
  border-radius:inherit;
  box-sizing:border-box;
  pointer-events:none;
}
/* the 1px lit top edge, masked to fade out at both ends */
.gf-hero-window-edge{
  position:absolute;
  top:0;
  left:0;
  right:0;
  height:1px;
  z-index:1;
  opacity:.75;
  background-color:var(--ink);
  -webkit-mask-image:linear-gradient(90deg,rgba(0,0,0,0) 0%,rgb(0,0,0) 50.0275%,rgba(0,0,0,0) 100%);
  mask-image:linear-gradient(90deg,rgba(0,0,0,0) 0%,rgb(0,0,0) 50.0275%,rgba(0,0,0,0) 100%);
  pointer-events:none;
}

.gf-hero-window-bar{
  position:relative;
  flex:0 0 auto;
  display:flex;
  flex-flow:row nowrap;
  align-items:center;
  height:40px;
  padding:0 14px;
  border-radius:18px;
  background:rgba(255,255,255,.04);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.06);
}
.gf-hero-dots{display:flex;flex-flow:row nowrap;align-items:center;gap:8px}
.gf-hero-dot{display:block;width:10px;height:10px;border-radius:50%}
.gf-hero-dot-1{background:#ff5f57}
.gf-hero-dot-2{background:#febc2e}
.gf-hero-dot-3{background:#28c840}
.gf-hero-window-chip{
  position:absolute;
  left:50%;
  top:50%;
  transform:translate(-50%,-50%);
  display:flex;
  align-items:center;
  height:24px;
  padding:0 12px;
  border-radius:var(--radius-pill);
  background:rgba(255,255,255,.06);
  border:1px solid var(--ink-10);
  font-size:12px;
  line-height:18px;
  letter-spacing:.6px;
  color:var(--ink-65);
  white-space:pre;
}

.gf-hero-window-view{
  position:relative;
  flex:1 1 auto;
  min-height:0;
  border-radius:18px;
  overflow:clip;
  background:var(--gf-hero-page);
}
.gf-hero-window-view picture{display:block;width:100%;height:100%}
.gf-hero-window-view img{
  width:100%;
  height:100%;
  /* the frame is 1.903:1 and the view is 1.535:1, so contain pins it to the top uncropped and the
     page colour fills the rest, which the foreground hills cover from section-y 1160 down */
  object-fit:contain;
  object-position:50% 0;
}

/* ---------------------------------------------------------------- hero carousel
   Four of our own demo sites in the window. The track is a flex row of full-width slides moved by
   transform; hero.js sets --gf-car-i (the index) and, while dragging, --gf-car-drag (px).
   The window keeps its own parallax and entrance transforms, so nothing here touches those. */
.gf-hero-car{touch-action:pan-y}
.gf-hero-car-track{
  display:flex;
  flex-flow:row nowrap;
  width:100%;
  height:100%;
  transform:translate3d(0,0,0);
  transition:transform .5s cubic-bezier(.22,1,.36,1);
  will-change:transform;
  backface-visibility:hidden;
}
.gf-hero-car-track.is-dragging{transition:none}
.gf-hero-car-slide{
  flex:0 0 100%;
  width:100%;
  height:100%;
  min-width:0;
}
.gf-hero-car-slide picture{display:block;width:100%;height:100%}

/* arrows sit in the band of the window that the foreground hills do not cover */
.gf-hero-car-arrow{
  position:absolute;
  top:34%;
  z-index:2;
  display:flex;
  align-items:center;
  justify-content:center;
  width:38px;
  height:38px;
  padding:0;
  border:1px solid rgba(255,255,255,.14);
  border-radius:50%;
  background:rgba(18,18,20,.62);
  color:rgba(255,255,255,.92);
  cursor:pointer;
  opacity:0;
  transform:translateY(-50%) scale(.94);
  transition:opacity .25s cubic-bezier(0,0,.58,1),transform .25s cubic-bezier(0,0,.58,1),background-color .2s cubic-bezier(0,0,.58,1);
}
.gf-hero-car-arrow--prev{inset-inline-start:12px}
.gf-hero-car-arrow--next{inset-inline-end:12px}
.gf-hero-car:hover .gf-hero-car-arrow,
.gf-hero-car:focus-within .gf-hero-car-arrow{opacity:1;transform:translateY(-50%) scale(1)}
.gf-hero-car-arrow:hover{background:rgba(18,18,20,.82)}
.gf-hero-car-arrow:focus-visible{opacity:1;transform:translateY(-50%) scale(1);outline:2px solid var(--ink);outline-offset:2px}
/* no hover on touch, so keep them visible there */
@media (hover:none){.gf-hero-car-arrow{opacity:.85;transform:translateY(-50%) scale(1)}}

/* slide picker in the title bar, right side */
.gf-hero-car-pips{
  position:absolute;
  inset-inline-end:14px;
  top:50%;
  transform:translateY(-50%);
  display:flex;
  flex-flow:row nowrap;
  align-items:center;
  gap:7px;
}
.gf-hero-car-pip{
  width:7px;
  height:7px;
  padding:0;
  border:0;
  border-radius:50%;
  background:rgba(255,255,255,.22);
  cursor:pointer;
  transition:background-color .25s cubic-bezier(0,0,.58,1),width .35s cubic-bezier(.22,1,.36,1);
}
.gf-hero-car-pip:hover{background:rgba(255,255,255,.45)}
.gf-hero-car-pip.is-on{width:18px;border-radius:4px;background:rgba(255,255,255,.8)}
.gf-hero-car-pip:focus-visible{outline:2px solid var(--ink);outline-offset:2px}

/* ---------------------------------------------------------------- v3: the window as a way in
   The address bar is a link to the demo on screen (scripts/hero.mjs writes the markup); the host is
   dim, the demo's own name is lit, and an arrow arrives on hover. When the slide changes, the name
   lands again instead of just changing. */
.gf-hero-window-chip{
  gap:6px;
  height:26px;
  padding:0 12px 0 10px;
  letter-spacing:0;
  font-size:12px;
  color:var(--ink-65);
  text-decoration:none;
  cursor:pointer;
  max-width:calc(100% - 300px);
  overflow:hidden;
  transition:background-color .25s cubic-bezier(0,0,.58,1),border-color .25s cubic-bezier(0,0,.58,1);
}
.gf-hero-chip-lock{flex:0 0 auto;opacity:.55}
.gf-hero-chip-host{color:rgba(255,255,255,.6);white-space:nowrap}
.gf-hero-chip-slug{display:inline-block;color:var(--ink);font-weight:500;white-space:nowrap}
.gf-hero-chip-go{flex:0 0 auto;margin-inline-start:2px;opacity:.35;transform:translate3d(-2px,1px,0);
  transition:opacity .25s cubic-bezier(0,0,.58,1),transform .35s cubic-bezier(.22,1,.36,1)}
@media (hover:hover) and (pointer:fine){
  .gf-hero-window-chip:hover{background:rgba(255,255,255,.1);border-color:var(--ink-25)}
  .gf-hero-window-chip:hover .gf-hero-chip-go{opacity:1;transform:none}
}
.gf-hero-window-chip:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
.gf-hero-window-chip.is-swap .gf-hero-chip-slug{animation:gf-chip-swap .55s cubic-bezier(.22,1,.36,1)}
@keyframes gf-chip-swap{from{opacity:0;transform:translate3d(0,7px,0)}}

/* the pips: the active one widens and fills over the dwell; its animationend is the slide clock */
.gf-hero-car-pip{position:relative}
.gf-hero-car-pip.is-on{width:24px;background:rgba(255,255,255,.26)}
.gf-hero-car-pip-fill{position:absolute;inset:0;border-radius:inherit;background:var(--ink);
  transform:scaleX(0);transform-origin:0 50%}
[dir="rtl"] .gf-hero-car-pip-fill{transform-origin:100% 50%}
.gf-hero-car-pip.is-on .gf-hero-car-pip-fill{animation:gf-car-fill 3.8s linear forwards}
.gf-hero-window:not(.is-playing) .gf-hero-car-pip.is-on .gf-hero-car-pip-fill{animation-play-state:paused}
@keyframes gf-car-fill{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* depth: the slide on screen is full size; its neighbours wait a step back and dim, so a drag or a
   change reads as one card passing another rather than a strip sliding */
.gf-hero-car-slide{transition:transform .8s cubic-bezier(.22,1,.36,1),opacity .8s cubic-bezier(.22,1,.36,1)}
.gf-hero-car-slide:not(.is-on){transform:scale(.94);opacity:.5}
.gf-hero-car-track{transition-duration:.7s}
.gf-hero-car{cursor:pointer}
.gf-hero-car-track.is-dragging{cursor:grabbing}

/* the label that follows the pointer over the window: one element, transform written by hero.js,
   'scale' kept as its own property so the two never overwrite each other */
.gf-hero-car-visit{
  position:absolute;left:0;top:0;z-index:3;pointer-events:none;
  display:inline-flex;align-items:center;gap:6px;
  height:34px;margin:-17px 0 0 18px;padding:0 14px;
  border-radius:var(--radius-pill);
  background:rgba(10,10,14,.82);
  box-shadow:0 10px 30px rgba(0,0,0,.35),inset 0 0 0 1px rgba(255,255,255,.14);
  color:rgba(255,255,255,.72);font-size:13px;line-height:1;white-space:nowrap;
  opacity:0;scale:.7;
  transition:opacity .2s cubic-bezier(0,0,.58,1),scale .35s cubic-bezier(.34,1.56,.64,1);
}
.gf-hero-car-visit b{color:#fff;font-weight:500}
.gf-hero-car-visit-go{margin-inline-start:2px;color:#fff}
.gf-hero-car-visit.is-on{opacity:1;scale:1}
[dir="rtl"] .gf-hero-car-visit{margin:-17px 0 0 -18px;translate:-100% 0}

@media (prefers-reduced-motion:reduce){
  .gf-hero-car-pip.is-on .gf-hero-car-pip-fill{animation:none;transform:none}
  .gf-hero-car-slide,.gf-hero-car-slide:not(.is-on){transition:none;transform:none;opacity:1}
  .gf-hero-window-chip.is-swap .gf-hero-chip-slug{animation:none}
}

/* ---------------------------------------------------------------- entrance
   Resting state is the default so the section is correct with JS off.
   hero.js adds .gf-hero-armed synchronously (before paint) to arm the from-state,
   then .gf-hero-in on the next frame to play it. */
.gf-hero-armed .gf-hero-appear,
.gf-hero-armed .gf-hero-layer-in,
.gf-hero-armed .gf-hero-gradient{will-change:opacity,transform}

/* from-state, measured in hero-appear-desktop.json `first`.
   Deliberately carries NO transition: it must land in one paint, or the arm itself animates and
   the play reverses out of it in a few milliseconds. */
.gf-hero-armed:not(.gf-hero-in) .gf-hero-gradient{opacity:.001}
.gf-hero-armed:not(.gf-hero-in) .gf-hero-far .gf-hero-layer-in{opacity:.001;transform:translate3d(0,72px,0)}
.gf-hero-armed:not(.gf-hero-in) .gf-hero-near .gf-hero-layer-in{transform:translate3d(0,48px,0)}
.gf-hero-armed:not(.gf-hero-in) .gf-hero-fore .gf-hero-layer-in{transform:translate3d(0,36px,0)}
.gf-hero-armed:not(.gf-hero-in) .gf-hero-appear{opacity:.001;transform:translate3d(0,24px,0)}

/* stagger, from the offsets between identical progress values in the samples */
.gf-hero-armed [data-gf-hero-step="h1"]{--gf-hero-delay:.1s}
.gf-hero-armed [data-gf-hero-step="sub"]{--gf-hero-delay:.2s}
.gf-hero-armed [data-gf-hero-step="cta"]{--gf-hero-delay:.3s}
.gf-hero-armed [data-gf-hero-step="mockup"]{--gf-hero-delay:.4s}

/* play: the transition arrives with the to-state, in the same style change, so it animates */
.gf-hero-armed.gf-hero-in .gf-hero-appear,
.gf-hero-armed.gf-hero-in .gf-hero-layer-in,
.gf-hero-armed.gf-hero-in .gf-hero-gradient{
  opacity:1;
  transform:none;
  transition:opacity var(--gf-hero-dur) var(--gf-hero-ease) var(--gf-hero-delay,0s),
             transform var(--gf-hero-dur) var(--gf-hero-ease) var(--gf-hero-delay,0s);
}
.gf-hero-armed.gf-hero-in .gf-hero-gradient{transition-duration:var(--gf-hero-dur-bg)}

/* ---------------------------------------------------------------- 810px - 1023.98px */
@media (max-width:1023.98px){
  .gf-hero-content{max-width:720px;padding-top:120px}
  .gf-hero-h1{font-size:36px;line-height:46.8px;letter-spacing:-1.44px}
  /* the headline breaks between its two sentences; the wrap has to hold one sentence per line */
  .gf-hero-h1-wrap{width:auto;max-width:680px}
  .gf-hero-sub-wrap{width:auto;max-width:420px}
  /* narrower frames: contain would leave dead page colour the hills do not cover down here */
  .gf-hero-window-view img{width:100%;height:auto;object-fit:fill;object-position:50% 0}
}

/* ---------------------------------------------------------------- <= 809.98px */
@media (max-width:809.98px){
  .gf-hero-far{left:-240px;right:-240px;bottom:-1px}
  .gf-hero-near{left:-152px;right:-152px;bottom:0}
  .gf-hero-fore{left:-120px;right:-120px}
  .gf-hero-mockup{aspect-ratio:.756322 / 1}
  /* the portrait frame only shows ~42% of the page width; anchored right it lands on the product
     and the top-right nav item, which reads as a real narrow view. Anchored left or centre it
     clips the display headline mid-word. */
  .gf-hero-window-view img{width:100%;height:auto;object-fit:fill;object-position:50% 0}
  .gf-hero-window-bar{height:32px;padding:0 10px}
  .gf-hero-dot{width:8px;height:8px}
  .gf-hero-dots{gap:6px}
  .gf-hero-window-chip{height:20px;padding:0 10px;font-size:11px}
  /* the portrait frame is narrow: shrink the controls and pull the chip left of the pips */
  .gf-hero-car-arrow{width:30px;height:30px;top:30%}
  .gf-hero-car-arrow--prev{inset-inline-start:8px}
  .gf-hero-car-arrow--next{inset-inline-end:8px}
  .gf-hero-car-pips{inset-inline-end:10px;gap:5px}
  .gf-hero-car-pip{width:6px;height:6px}
  .gf-hero-car-pip.is-on{width:14px}
  .gf-hero-window-chip{left:auto;inset-inline-end:72px;transform:translateY(-50%);max-width:38%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;line-height:20px}
}

/* ---------------------------------------------------------------- reduced motion
   hero.js never arms the entrance or the parallax under reduce, so the resting default above
   already applies. These rules are the belt-and-braces if the class ever lands anyway. */
@media (prefers-reduced-motion:reduce){
  .gf-hero-appear,
  .gf-hero-layer-in,
  .gf-hero-gradient{transition:none!important;opacity:1!important;transform:none!important;will-change:auto}
  .gf-hero-cta{transition:none}
  .gf-hero-car-track{transition:none}
  .gf-hero-car-arrow{transition:none;opacity:1;transform:translateY(-50%) scale(1)}
}

/* the portrait window has room for the demo's name only */
@media (max-width:809.98px){.gf-hero-chip-host,.gf-hero-chip-lock{display:none}.gf-hero-car-visit{display:none}}
