/* ============================================================
   Page-level adaptations.

   public/assets/ is the Orisa template, byte-for-byte unmodified — nothing in it is edited.
   This file carries the few overrides needed because the site mixes sections from demos that
   were built on different page backgrounds:

     index-5.html  (header, hero, footer)  -> <body class="... bg-neutral-50">  grey page
     index-4.html  (how we work)           -> <body class="... bg-neutral-50">  grey page
     index.html    (solutions, clients)    -> <body class="at-magic-cursor">    white page
     index-15.html (selected work)         -> <body class="at-magic-cursor">    white page
     index-2.html  (contact marquee)       -> <body class="at-magic-cursor">    white page

   The inner pages (about-1, services-1, portfolio-3, contact-1, 404) are all white-bodied, so
   the layout leaves <body> white and only the home page paints it grey — see
   components/GreyPage.tsx. Anything a white-bodied demo filled with neutral-0 to match its own
   page therefore only needs fixing on the home page, and the overrides below say so explicitly
   rather than applying everywhere. Loaded last, after main.css and sticky-cards.css.
   ============================================================ */

/* "Our solutions": main.css gives each row a solid neutral-0 fill. That is invisible on
   index.html's white page — which is what /services is — but reads as a white slab on the grey
   home page. `.on-grey` is added by the home page's copy of the section only. */
.on-grey .at-service-item {
  background-color: transparent;
}

/* Footer wordmark: `<p class="h1 d-flex ...">We’re <img> BuildASAP <sup>®</sup></p>`.
   The markup asks for a space either side of the image, but each text run is its own anonymous
   flex item and flex trims an item's leading/trailing whitespace — so the words end up touching
   the image (measure index-5.html and it does exactly the same: gap 0 on both sides). It reads
   fine there with "I’m" / "Orisa Nova"; with "We’re" / "BuildASAP" the collision is obvious.
   0.25em ≈ one space at this size, which is what the markup intended. */
.at-footer-copyright-area .h1 img {
  margin-inline: 0.25em;
}

/* Footer 5: the studio's email is longer than the template's and overflowed its column into
   the next one. Keep the heading inside its grid cell. */
.mp-footer-style .buildasap-footer-email,
.mp-footer-style .buildasap-footer-email a {
  max-width: 100%;
}

.mp-footer-style .buildasap-footer-email a {
  display: inline-block;
  overflow-wrap: anywhere;
}


/* Contact band: "Let's talk" was desktop-only. Keep it readable on a phone
   without the 70px h1 overflowing the 80px play button. */
@media (max-width: 767.98px) {
  .postbox-scroll-zoom-play {
    width: calc(100% - 2rem);
    padding-inline: 0.5rem;
  }

  .postbox-scroll-zoom-play h1 {
    font-size: clamp(1.75rem, 9vw, 2.75rem);
    margin-bottom: 0;
  }

  .postbox-play-btn a {
    height: 64px;
    width: 64px;
    flex-shrink: 0;
  }
}

/* Selected work: the pin stack is 70vh/80vh and sticks to the top of the
   viewport, so on a phone the cards sit in the upper third with empty
   space below. Fill the pin and keep transform-origin on the card centre
   so the scroll animation stays optically centred. */
@media (max-width: 991.98px) {
  .sec-4-home-15__cards {
    height: 100vh;
  }

  .sec-4-home-15__card {
    --sec4-gap: 120px;
    left: 50%;
    width: min(100%, calc((100vh - var(--sec4-gap)) * 1428 / 1011));
    transform-origin: center center;
  }
}

@media (max-width: 575.98px) {
  .sec-4-home-15__card {
    --sec4-gap: 96px;
    width: min(100%, calc((100vh - var(--sec4-gap)) * 4 / 5));
    transform-origin: center center;
  }
}

/* ============================================================
   Page loader

   main.css styles .page-loader / .bar / .page-loader-logo but no template page uses them, so the
   behaviour lives here.

   The reveal is pure CSS on purpose. The curtain is `position: fixed` over the whole viewport, so
   anything that can leave it up leaves the site invisible — a blocked CDN, a JS error, an old
   browser. Driving it from GSAP put exactly that failure in the critical path (and GSAP's ticker
   does not advance reliably in a headless capture, which is how it was caught). These keyframes
   run off the document's own timeline and always finish. TemplateAssets still removes the node
   afterwards, but only as tidying — the animation has already cleared the screen.
   ============================================================ */
.page-loader {
  background-color: transparent;
  pointer-events: none;
  animation: buildasap-loader-out 0.01s linear 1.35s forwards;
}

@keyframes buildasap-loader-out {
  to {
    visibility: hidden;
  }
}

.page-loader .bar {
  background: var(--at-neutral-900);
  transform-origin: top center;
  animation: buildasap-loader-bar 0.85s cubic-bezier(0.76, 0, 0.24, 1) forwards;
}

/* Ten bars, retracting left to right. */
.page-loader .bar:nth-child(1) { animation-delay: 0.30s; }
.page-loader .bar:nth-child(2) { animation-delay: 0.35s; }
.page-loader .bar:nth-child(3) { animation-delay: 0.40s; }
.page-loader .bar:nth-child(4) { animation-delay: 0.45s; }
.page-loader .bar:nth-child(5) { animation-delay: 0.50s; }
.page-loader .bar:nth-child(6) { animation-delay: 0.55s; }
.page-loader .bar:nth-child(7) { animation-delay: 0.60s; }
.page-loader .bar:nth-child(8) { animation-delay: 0.65s; }
.page-loader .bar:nth-child(9) { animation-delay: 0.70s; }
.page-loader .bar:nth-child(10) { animation-delay: 0.75s; }

@keyframes buildasap-loader-bar {
  from {
    transform: scaleY(1);
  }
  to {
    transform: scaleY(0);
  }
}

.page-loader-logo {
  animation: buildasap-loader-logo 0.75s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

@keyframes buildasap-loader-logo {
  0% {
    opacity: 0;
    transform: translateX(-50%) translateY(-50%) scale(0.94);
  }
  40% {
    opacity: 1;
    transform: translateX(-50%) translateY(-50%) scale(1);
  }
  100% {
    opacity: 0;
    transform: translateX(-50%) translateY(-50%) scale(1);
  }
}

.page-loader-mark {
  display: flex;
  align-items: center;
  gap: 14px;
}

.page-loader-word {
  color: var(--at-common-white, #fff);
  font-family: var(--at-ff-heading);
  font-size: clamp(28px, 5vw, 52px);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1;
  white-space: nowrap;
}

.page-loader-mark img {
  /* The favicon is a dark mark; the curtain behind it is dark too. */
  filter: invert(1);
  width: clamp(30px, 4vw, 44px);
  height: auto;
}

/* Respect a reduced-motion preference: no curtain at all rather than a jumpy one. */
@media (prefers-reduced-motion: reduce) {
  .page-loader {
    display: none;
  }
}

/* ============================================================
   Hero on phones and tablets

   Everything below is inside a max-width query, so the desktop layout stays exactly as
   index-5.html builds it. The template hides the portrait column below lg and leaves the small
   product shot as the only image, which drops the wordmark — the strongest thing in the section —
   off every phone. Below 992px this swaps them: the portrait and the BuildASAP wordmark become
   the hero image, and the small product shot steps aside.
   ============================================================ */
@media (max-width: 991.98px) {
  .hero-home-5 .hero-lead-col {
    padding-bottom: 0 !important;
  }

  /* The small product shot is a supporting detail on desktop; on a phone it competes with the
     portrait for the same job, so only one of them survives. */
  .hero-home-5 .hero-lead-col > img {
    display: none;
  }

  .hero-home-5 .hero-figure-col {
    display: block !important;
    margin-top: 28px;
  }

  /* Both the figure and the "See our work" button carry `at_fade_anim`, so main.js hands them to
     ScrollTriggers that start at opacity 0 and play when scrolled into view. Those triggers are
     built while the hero is still laying out at mobile width and never resolve here, leaving the
     portrait and the CTA invisible but still occupying space — a 530px hole and a missing button.
     This is the first screen: nothing in it should be waiting to be scrolled to. */
  .hero-home-5 .at_fade_anim {
    opacity: 1 !important;
    transform: none !important;
    visibility: visible !important;
  }

  /* fz-290 is 290px — roughly four phone widths. Scale it to the viewport instead. */
  .hero-home-5 .hero-figure-col .fz-290 {
    font-size: clamp(40px, 16vw, 140px);
  }

  /* On desktop the wordmark sits *behind* the portrait, which works because the column is only a
     third of the row and the letters run out either side. At phone width the portrait covers it
     almost entirely — you get one stray "P". So on mobile it drops out of absolute positioning
     and sits under the portrait, centred, where it can actually be read. */
  .hero-home-5 .hero-figure-col .p-absolute {
    display: block !important;
    position: static !important;
    transform: none !important;
    z-index: auto !important;
    margin-top: 10px;
    text-align: center;
  }

  .hero-home-5 .hero-figure-col img {
    display: block !important;
    width: 100%;
    max-width: 340px;
    margin-inline: auto;
  }

  .hero-home-5 .hero-pitch-col {
    margin-top: 32px;
  }
}

/* Hero pitch column, desktop: lift it clear of the wordmark.

   The row is `align-items-center`, so bottom padding raises a column's content — the lead column
   uses `pb-100` for exactly this. The pitch column needs the same or the CTA sits on the cap
   height of the giant BuildASAP wordmark behind it. spacing.css has no responsive variant of the
   100 step (`pb-lg-100` does not exist), so it is a rule rather than a class. */
@media (min-width: 992px) {
  .hero-home-5 .hero-pitch-col {
    padding-bottom: 100px;
  }
}
