/* ==========================================================================
   BAMFLOW — assets/css/partner-hero.css · nocobase-partner.html hero (vòng 102)
   Linked after theme-fluent-glass.css. Hero parts ported from lab/nocobase-3d.css, re-scoped.
   Sky = the homepage's: the hero sits in .fold (gradient + .fold__aura fog + the .fold__grid dot
   grid main.js draws), so gradient, fog and dots are the same rules as index.html.
   Order, centred: badge → lockup pill → H1 → sub → CTAs. The 3D intro (partner-hero.js +
   np3d-logo.js) owns the hero first (canvas above the copy, no text on screen); the gold block
   splits into the DOM lockup (.np3d-stage .is-joining / .is-landing / .is-resolved), then the copy
   (.np3d-seq) fades up, staggered (hero .is-revealed). html.np3d-gl is set before first paint
   only when the intro can run; without it (reduced motion, no WebGL2) everything is final at once.
   ========================================================================== */

.np-fold { --np-ease: cubic-bezier(.22, 1, .36, 1); }

/* the hero fills the fold (index: .fold > .hero2--grad); the copy is kept on the navy/blue part of
   the sky: the bottom padding leaves the white fog below the CTAs */
.np-fold > .np3d-hero {
  position: relative;
  isolation: isolate;
  overflow: clip;
  text-align: center;
  color: #ffffff;
  padding-top: calc(var(--header-h) + var(--header-offset) + clamp(16px, 3vh, 40px));
  padding-bottom: clamp(120px, 21vh, 240px);
}
.np-fold > .np3d-hero > .container { position: relative; z-index: 1; }
.np-fold .np-hero__in {
  display: flex;
  flex-direction: column;
  align-items: center;
  max-width: 960px;
}
.np-fold .np3d-hero .hero2__partner { margin: 0; }

/* the intro canvas covers the whole hero, above the copy (clicks pass through) */
.np-fold .np3d-logo-canvas {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
/* at resolution the canvas cross-fades out over the DOM marks (np3d-logo.js sets the timing) */
.np-fold .np3d-logo-canvas.is-done,
.np-fold .np3d-hero.is-revealed .np3d-logo-canvas {
  opacity: 0;
  visibility: hidden;
  transition: opacity .35s var(--np-ease), visibility 0s linear .35s;
}

/* stage = the row where the real lockup rests (and where the 3D split lands).
   --lk is the lockup unit: the height of the official NocoBase logo image. */
.np-fold .np3d-stage {
  --lk: clamp(20px, 5.6vw, 36px);
  position: relative;
  display: flex;
  justify-content: center;
  width: 100%;
  margin-top: clamp(16px, 2.6vh, 26px);
}
.np-fold .np3d-lockup {
  position: relative;
  z-index: 1;
  display: inline-flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: center;
  max-width: 100%;
  padding: calc(var(--lk) * .44) calc(var(--lk) * .78);
  border-radius: 999px;
  white-space: nowrap;
  line-height: 1;
}
/* the translucent pill; drawn by ::before so it can arrive on its own */
.np-fold .np3d-lockup::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .24);
  transition: opacity .5s var(--np-ease), transform .7s var(--np-ease);
}
html.np3d-gl .np-fold .np3d-stage:not(.is-joining):not(.is-resolved) .np3d-lockup::before { opacity: 0; transform: scale(.92); }
.np-fold .np3d-lockup__bf {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--lk) * .22);
  font-family: var(--font-display);
  font-size: calc(var(--lk) * .8);
  font-weight: 800;
  letter-spacing: .06em;
  line-height: 1;
  color: #ffffff;
}
.np-fold .np3d-lockup__icon {
  display: block;
  flex: none;
  width: calc(var(--lk) * 1.2);
  height: calc(var(--lk) * 1.2);
  color: #ffffff;
}
.np-fold .np3d-lockup__word { display: block; }
.np-fold .np3d-lockup__x {
  display: block;
  margin-inline: calc(var(--lk) * .42);
  font-size: calc(var(--lk) * .66);
  font-weight: 400;
  line-height: 1;
  color: rgba(255, 255, 255, .62);
}
/* official NocoBase logo is 320×47: sized by height, width follows — never stretched; rendered
   white on the blue (black png → white) */
.np-fold .np3d-lockup__nb {
  display: block;
  flex: none;
  height: var(--lk);
  width: auto;
  aspect-ratio: 320 / 47;
  object-fit: contain;
  filter: brightness(0) invert(1);
}

/* DOM marks: laid out in place, hidden only while the 3D intro can run, revealed with the stage */
.np-fold .np3d-mk { transition: opacity .35s var(--np-ease); }
html.np3d-gl .np-fold .np3d-stage:not(.is-resolved) .np3d-mk { opacity: 0; }
html.np3d-gl .np-fold .np3d-stage.is-joining .np3d-lockup__x { opacity: 1; transition-duration: .45s; }
html.np3d-gl .np-fold .np3d-stage.is-landing .np3d-lockup__word,
html.np3d-gl .np-fold .np3d-stage.is-landing .np3d-lockup__nb { opacity: 1; transition-duration: .4s; }
/* failsafe: if the module never boots, show the lockup anyway */
html.np3d-gl:not(.np3d-boot) .np-fold .np3d-stage:not(.is-resolved) .np3d-mk { animation: np3d-failsafe .35s var(--np-ease) 6s both; }
html.np3d-gl:not(.np3d-boot) .np-fold .np3d-stage .np3d-lockup::before { animation: np3d-failsafe .35s var(--np-ease) 6s both; }
@keyframes np3d-failsafe { from { opacity: 0; } to { opacity: 1; } }
.np-fold .np3d-stage.is-static .np3d-mk,
.np-fold .np3d-stage.is-static .np3d-lockup::before { transition: none; }

/* copy: white on the navy/blue part of the sky */
.np-fold .np-hero__title {
  max-width: 18em;
  margin: clamp(20px, 3.4vh, 34px) auto 0;
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 4vw, 3.1rem);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: -0.03em;
  color: #ffffff;
  text-wrap: balance;
}
.np-fold .np-hero__sub {
  max-width: 60ch;
  margin: clamp(14px, 2.4vh, 22px) auto 0;
  font-size: clamp(1rem, 1.2vw, 1.15rem);
  line-height: 1.6;
  color: rgba(255, 255, 255, .88);
  text-wrap: pretty;
}
.np-fold .np-hero__actions { justify-content: center; margin-top: clamp(20px, 3.4vh, 32px); }
/* CTAs as on the homepage sky: white primary with blue text, outlined ghost */
.np-fold .np-hero__actions .btn--primary {
  background: #ffffff;
  color: #0b3f8c;
  box-shadow: inset 0 1px 0 #ffffff, 0 12px 30px -12px rgba(0, 0, 0, .45);
}
.np-fold .np-hero__actions .btn--primary:hover,
.np-fold .np-hero__actions .btn--primary:focus-visible { background: #eef5ff; color: #0b3f8c; }
.np-fold .np-hero__actions .btn--ghost {
  background: rgba(255, 255, 255, .1);
  border: 1.5px solid rgba(255, 255, 255, .85);
  color: #ffffff;
  font-weight: 600;
  box-shadow: none;
  /* the theme's glass .btn--ghost adds blur + saturate(1.4): on the sky that reads as a filled bright-blue
     button (and lowers the white text's contrast); the homepage's ghost has none */
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.np-fold .np-hero__actions .btn--ghost:hover,
.np-fold .np-hero__actions .btn--ghost:focus-visible { background: #ffffff; border-color: #ffffff; color: #123a9a; }
.np-fold .np3d-hero a:focus-visible,
.np-fold .np3d-hero button:focus-visible { outline-color: #ffffff; }
@media (min-width: 1024px) { .np-fold .np-hero__actions { flex-wrap: nowrap; } }

/* the copy waits while the intro owns the hero, then fades up in order: badge, H1, sub, CTAs */
.np3d-seq { --seq: 0; }
html.np3d-gl .np-fold .np3d-hero .np3d-seq { opacity: 0; transform: translateY(18px); }
html.np3d-gl .np-fold .np3d-hero.is-revealed .np3d-seq {
  opacity: 1;
  transform: none;
  transition: opacity .6s var(--np-ease), transform .8s var(--np-ease);
  transition-delay: calc(.08s + var(--seq) * .13s);
}
html.np3d-gl .np-fold .np3d-hero.is-static .np3d-seq { transition: none; }
/* failsafe: if the module never boots, the copy comes in anyway */
html.np3d-gl:not(.np3d-boot) .np-fold .np3d-hero .np3d-seq { animation: np3d-failsafe-up .5s var(--np-ease) 6.2s both; }
@keyframes np3d-failsafe-up { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }

/* tablets and phones: the sky's fog starts higher (≈ 2/3), so the fold grows below the CTAs */
@media (max-width: 960px) {
  .np-fold > .np3d-hero { padding-bottom: clamp(160px, 30vh, 300px); }
}
@media (max-width: 600px) {
  .np-fold > .np3d-hero { padding-top: calc(var(--header-h) + var(--header-offset) + clamp(28px, 6vh, 56px)); padding-bottom: clamp(260px, 50vh, 460px); }
  .np-fold .np-hero__title { font-size: clamp(1.75rem, 8.2vw, 2.2rem); }
  .np-fold .np-hero__actions .btn { width: 100%; justify-content: center; }
}

/* ---------- Reduced motion / frozen ---------- */
@media (prefers-reduced-motion: reduce) {
  .np-fold .np3d-mk, .np-fold .np3d-logo-canvas, .np-fold .np3d-seq, .np-fold .np3d-lockup::before { transition: none !important; }
}
.np3d-instant .np-fold .np3d-mk,
.np3d-instant .np-fold .np3d-seq,
.np3d-instant .np-fold .np3d-lockup::before,
.np3d-instant .np-fold .np3d-logo-canvas { transition: none !important; }

/* ---------- Round 108 ----------
   ≤ 600px: the hero buttons are full-width; a long label (EN "Discuss a NocoBase implementation")
   wraps inside the button instead of pushing the button past the 16–20px side gutter. */
@media (max-width: 600px) {
  .np-fold .np-hero__actions .btn { white-space: normal; max-width: 100%; text-align: center; text-wrap: balance; }
}
