/* gfs-home.css — scroll motion for the homepage.
 *
 * WHY THIS IS NOT gfs-lp.css. The vertical landing pages are uniform argument
 * pages with no motion of their own, so a generic layer fits them. The homepage
 * already has a tuned reveal system (51 [data-reveal] elements, its own
 * IntersectionObserver), a WebGL hero with a sticky stage, and a pricing deck
 * that writes transforms every frame. A 42-agent audit of loading gfs-lp.css
 * here found 25 confirmed collisions, including:
 *   - .hero{overflow:hidden} overriding index.html's own overflow:visible >=900px
 *   - the hero headline shrinking 128px -> 92px at 1920px
 *   - .gfs-prog at z-index 60 sitting under .nav at z-index 100 (invisible)
 *   - every one of the 51 [data-reveal] elements being a target or inside one,
 *     so the page's own observer becomes dead code and the generic reveal wins
 *   - an inline transition-delay lagging the pinned pricing cards up to 830ms
 * So this file takes the IDEAS and none of the selectors. It overrides nothing
 * the homepage already styles.
 */

/* ---- 1. scroll progress -------------------------------------------------- */
/* z-index 250, not 60. The homepage stack is: .nav 100, .burger 120,
   .mobile-menu 110, .grain 200, .gfsv-fab 9997, .gfsv-panel 9998. At 60 the
   rule would render underneath the fixed nav and never be seen. 250 clears the
   grain and the nav, and stays under the voice agent's panel so it can never
   cover a dialog. */
.gfs-hprog{position:fixed;top:0;left:0;height:2px;width:100%;z-index:250;
  transform:scaleX(0);transform-origin:0 50%;background:var(--accent,#D9F24C);
  will-change:transform;pointer-events:none}

/* ---- 2. reveal for the blocks that have none ---------------------------- */
/* Deliberately mirrors the homepage's OWN [data-reveal] values (24px rise,
   .5s, --ease-out) rather than gfs-lp's 20px/.62s, so a section eyebrow that
   this file animates and the tiles underneath it that the page animates arrive
   looking like one system, not two. Applied ONLY to elements that carry no
   reveal today and contain none — never stacked on top of the page's own. */
.gfs-hpre{opacity:0;transform:translate3d(0,24px,0)}
.gfs-hin{opacity:1;transform:none;
  transition:opacity .5s var(--ease-out,cubic-bezier(.22,.61,.36,1)),
             transform .5s var(--ease-out,cubic-bezier(.22,.61,.36,1))}

/* ---- 3. the section spine ------------------------------------------------ */
/* Marks where one section's argument ends and the next begins, filling as the
   section passes. Two things the vertical pages did not have to handle:
   the homepage column is 1200px wide (not 1140), and it ALTERNATES a cream
   section against dark ones — a white hairline is invisible on #F2EDE1, so the
   colour is a token the light section overrides. */
/* 1300px, not 1080px. The homepage column is 1200px wide, so below ~1300 the
   viewport has no margin to put a rule in: measured at 1280px the spine landed
   20px from the edge with the text at 64px, and at 1080px it was 4px from the
   text — a stray edge line, not a margin mark. From 1300px up,
   calc(50% - 626px) holds a constant 50px of clearance at every width.
   --spine-on is the SINGLE source of truth for whether the spine is live;
   gfs-home.js reads it rather than repeating the breakpoint. */
@media(min-width:1300px){
  :root{--spine-on:1}
  .gfs-spine{--spine-line:rgba(255,255,255,.08);--spine-fill:var(--accent,#D9F24C);position:relative}
  .gfs-spine::before,.gfs-spine::after{
    content:"";position:absolute;left:calc(50% - 626px);width:1px}
  .gfs-spine::before{top:0;bottom:0;background:var(--spine-line)}
  .gfs-spine::after{top:0;height:var(--spine,0%);background:var(--spine-fill);opacity:.6}
  /* #studio is the cream section (#F2EDE1) — a white hairline does not exist there. */
  .sec.manifesto.gfs-spine{--spine-line:rgba(13,20,17,.12);--spine-fill:var(--forest,#1F4A3A)}
}

/* ---- 4. the sticky ask --------------------------------------------------- */
/* z-index 90, deliberately LOW. The homepage stack is .nav 100, .mobile-menu
   110, .burger 120, .grain 200. Sitting under all of them means the mobile menu
   covers this bar with no JS at all, and the bar picks up the same film grain as
   the rest of the page instead of floating above it. The one thing above it that
   matters is the voice agent's button (z 9997), which would otherwise land on
   top of the bar — so the bar publishes its own measured height and the FAB
   steps up by it. */
.gfs-bar{position:fixed;left:0;right:0;bottom:0;z-index:90;
  display:flex;align-items:center;gap:16px;
  padding:12px max(16px,calc(50% - 600px));
  background:rgba(11,13,16,.94);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  border-top:1px solid rgba(255,255,255,.1);
  transform:translateY(110%);visibility:hidden;pointer-events:none;
  transition:transform .32s cubic-bezier(.22,.61,.36,1),visibility .32s}
.gfs-bar[data-on="1"]{transform:none;visibility:visible;pointer-events:auto}

.gfs-bar .t{flex:1 1 auto;min-width:0;font-size:14.5px;line-height:1.45;
  color:var(--text-dim,rgba(251,248,240,.72))}
.gfs-bar .t b{color:var(--bone,#FBF8F0);font-weight:600}
.gfs-bar .go{flex:0 0 auto;display:inline-flex;align-items:center;
  min-height:44px;padding:11px 20px;border-radius:3px;
  font-size:14.5px;font-weight:600;text-decoration:none;
  background:var(--accent,#D9F24C);color:var(--accent-ink,#0D1411)}
.gfs-bar .go:hover{filter:brightness(1.06)}
.gfs-bar .x{flex:0 0 auto;width:44px;height:44px;border:0;cursor:pointer;
  background:none;color:var(--muted,#8A8577);font:inherit;font-size:19px;line-height:1;
  border-radius:3px}
.gfs-bar .x:hover{color:var(--bone,#FBF8F0)}
.gfs-bar :focus-visible{outline:2px solid var(--bone,#FBF8F0);outline-offset:2px}

/* The voice agent's button is fixed to the same corner at z-index 9997, so it
   would sit on top of the bar. --gfs-bar-h is measured and published by
   gfs-home.js, so this survives the text wrapping to two lines on a phone.
   Specificity 0,2,1 beats voice-agent.js's own 0,1,0 rule whichever order the
   two stylesheets end up in — that script injects its CSS at runtime. */
body.gfs-bar-on .gfsv-fab{bottom:calc(18px + var(--gfs-bar-h, 0px));
  transition:bottom .32s cubic-bezier(.22,.61,.36,1)}

@media(max-width:620px){
  .gfs-bar{gap:10px;padding:10px 14px}
  .gfs-bar .t{font-size:13px}
  .gfs-bar .go{padding:10px 15px;font-size:13.5px}
}

/* ---- 4. honest reduced-motion ------------------------------------------- */
@media(prefers-reduced-motion:reduce){
  .gfs-hpre{opacity:1;transform:none}
  .gfs-hin{transition:none}
  .gfs-bar{transition:none}
  body.gfs-bar-on .gfsv-fab{transition:none}
}
