/* ===========================================================================
   The product bar.

   The rule this follows: the island never changes shape, size or position.
   Only its CONTENT flips.

     at rest      row 1  company lockup · company nav · Sign in · Get started
                  row 2  "cRUD Webinar" in text · the product's sections

     scrolled     one row, 60px, in exactly the place row 1 occupied:
                  cRUD Webinar lockup · the product's sections · Sign in ·
                  Get started

   So the reader never sees a second shape appear. They see one navigation bar
   whose contents change once they are inside a product.

   Three things follow from that and are load bearing:
     - the bar has NO background of its own. The island is white; the bar is
       part of the island, not a panel sitting on it.
     - there is ONE set of calls to action. They live in the company row and
       ride down onto the product row when the company row leaves, so nothing
       is duplicated.
     - the product row grows from 46px to the full 60px when it becomes the
       only row, so the retracted bar is dimensionally identical to the bar it
       replaced.
   =========================================================================== */

:root { --prodbar-h: 46px; }

/* ------------------------------- the bar --------------------------------- */

.prodbar {
  position: relative; z-index: 1;
  height: var(--prodbar-h);
  display: flex; align-items: center; gap: 20px;
  /* the company row's own padding, so the two rows share a left edge and the
     right edge clears the island's 32px corner exactly as row 1 does */
  /* The company row's own padding, plus a standing reserve for the calls to
     action on the right. The reserve is held in BOTH states, not only once the
     actions join this row: otherwise the sections sit under the buttons at
     rest and then jump left as the bar becomes the navbar. Holding it always
     means the sections occupy one position and never move. */
  padding: 0 calc(var(--actions-w, 210px) + 56px) 0 24px;
  background: none;                      /* the island is the surface */
  transition: height var(--t-panel, 380ms) var(--ease, cubic-bezier(.22,.61,.36,1));
}

/* -- the identity slot ----------------------------------------------------
   One fixed 104x52 box, the same box the company lockup occupies in the row
   above, holding two images stacked on top of each other:

     at rest      the product wordmark alone, no favicon
     retracted    the full product lockup, favicon included

   The numbers below are not guesses. The wordmark is sized and placed so its
   letters land exactly where the same letters sit inside the full lockup, so
   when the two crossfade the words do not move at all and the only thing that
   visibly happens is the favicon arriving. The company lockup is never cut
   apart; nothing in the baseline navbar changes.

   The crossfade starts as the slide settles, so the favicon arrives as the bar
   becomes the navbar rather than as a second beat after it (see the flip).
   Coming back it reverses immediately, with no wait. */

.prodbar__id {
  flex: none; display: block; text-decoration: none;
  width: 104px; height: 52px; position: relative;
}
.prodbar__id img { position: absolute; }

.prodbar__wordmark {
  left: var(--wm-x); top: var(--wm-y);
  width: var(--wm-w); height: var(--wm-h);
  opacity: 1;
  transition: opacity 170ms var(--ease, cubic-bezier(.22,.61,.36,1));
}
.prodbar__lockup {
  left: 0; top: 0; width: 104px; height: 52px;
  opacity: 0;
  transition: opacity 200ms var(--ease, cubic-bezier(.22,.61,.36,1));
}

/* where each product's letters sit, measured from its own lockup */
.prodbar--webinar { --wm-x: 51.9px; --wm-y: 15.5px; --wm-w: 51.2px; --wm-h: 21.0px; }
.prodbar--collab  { --wm-x: 56.1px; --wm-y: 15.4px; --wm-w: 40.0px; --wm-h: 21.2px; }

/* Hover dims the link, not the two images. Child opacity multiplies into the
   parent's, so whichever image is showing dims and the hidden one stays
   hidden. There is no specificity fight with the swap rules. */
.prodbar__id { transition: opacity var(--t-fast, 160ms) var(--ease, cubic-bezier(.22,.61,.36,1)); }
.prodbar__id:hover { opacity: 0.72; }

/* -------------------------------- sections -------------------------------
   The sections speak the primary navbar's language exactly: same size, same
   weight, same padding, and the same underline on hover. No fill behind a nav
   label anywhere on this site, so none here either.

   They also spread to fill the row rather than bunching against the wordmark,
   which is what left a wide blank stretch under the primary row's links. */

.prodbar__links {
  flex: 1; min-width: 0;
  display: flex; align-items: center; justify-content: flex-start; gap: 6px;
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none; -ms-overflow-style: none;
}
.prodbar__links::-webkit-scrollbar { display: none; }

.prodbar__links a {
  position: relative;
  padding: 9px 12px;                     /* the primary navbar's own padding */
  font-size: 15px;                       /* its own size; never larger */
  font-weight: 500; line-height: 1; white-space: nowrap;
  color: var(--text-secondary); text-decoration: none;
  transition: color var(--t-fast) var(--ease);
}
.prodbar__links a:hover { color: var(--text-primary); }

/* the same line, drawn the same way, at the same speed */
.prodbar__links a::after {
  content: "";
  position: absolute; left: 12px; right: 12px; bottom: 3px; height: 1.5px;
  background: var(--identity); border-radius: 2px;
  transform: scaleX(0); transform-origin: left center;
  transition: transform 340ms cubic-bezier(0.22, 1, 0.36, 1);
}
.prodbar__links a:hover::after,
.prodbar__links a:focus-visible::after { transform: scaleX(1); }
.prodbar__links a:focus-visible { outline: none; }
.prodbar__links a:focus-visible::after { height: 2.5px; }

/* the current section is that same line, held */
.prodbar__links a[aria-current="page"] { color: var(--text-primary); font-weight: 600; }
.prodbar__links a[aria-current="page"]::after { transform: scaleX(1); }

/* ------------------- out of the dropdown's way --------------------------- */
/* The products panel hangs from the primary row and lands on top of this one.
   Rather than let the two overlap, the product row stands down while the panel
   is open and returns when it closes. The island keeps its height throughout,
   so nothing below it moves. */

/* Hiding the contents was not enough: the row kept its 46px, so the island
   stayed tall and a white band sat either side of the panel. The row gives up
   its height as well, which collapses the island back to the single bar the
   panel is designed to hang from, exactly as on a page with no product row. */
.site-header.has-prodbar:has(.nav__link[aria-expanded="true"]) .prodbar,
.site-header.has-prodbar:has(.nav__panel.is-open) .prodbar {
  height: 0; opacity: 0; visibility: hidden; overflow: hidden;
  transition: height 200ms var(--ease, cubic-bezier(.22,.61,.36,1)),
              opacity 120ms var(--ease, cubic-bezier(.22,.61,.36,1)),
              visibility 0s linear 200ms;
}
/* the elevation layer is a sibling, so it is reached from the root */
html:has(.nav__panel.is-open) .header-shade.has-prodbar,
html:has(.nav__link[aria-expanded="true"]) .header-shade.has-prodbar {
  height: var(--header-h);
  transition: height 200ms var(--ease, cubic-bezier(.22,.61,.36,1));
}
.prodbar {
  opacity: 1; visibility: visible;        /* an explicit state to return to */
  transition: height var(--nav-swap) var(--nav-swap-ease),
              opacity 180ms var(--ease, cubic-bezier(.22,.61,.36,1)),
              visibility 0s;
}

/* ======================= the flip ======================================== */

/* One clock for every part of the flip: the island, the fillets, the product
   row, the calls to action and the shadow all move on it, so they stay together
   at every frame. It is the swap's own, not the site's --t-panel: that token is
   240ms with a fast start, which covered most of the 60px in the first 100ms
   and read as a snap. 320ms with an even ease-in-out moves the same distance
   without the jolt. */
:root {
  --nav-swap: 320ms;
  --nav-swap-ease: cubic-bezier(0.45, 0, 0.25, 1);
}

.site-header.has-prodbar {
  transition: top var(--nav-swap) var(--nav-swap-ease);
}

/* The island rises by the company row's height, so the product row lands
   exactly where the company row was. The product row has already grown to the
   full bar height, so the shape that remains is the shape that left. */
.site-header.has-prodbar.is-retracted { top: calc(var(--header-top) - var(--header-h)); }
.site-header.has-prodbar.is-retracted .prodbar { height: var(--header-h); }

/* The company row is gone: not visible, not clickable, not focusable. The
   hide waits for the slide to finish, otherwise the row blanks on frame one
   and leaves an empty white band travelling up the screen. Coming back it is
   visible immediately, because it is arriving rather than leaving. */
.site-header.has-prodbar .site-header__inner { transition: visibility 0s; }
.site-header.has-prodbar.is-retracted .site-header__inner {
  pointer-events: none; visibility: hidden;
  transition: visibility 0s linear var(--nav-swap);
}

/* The favicon arrives as the slide settles, 60% of the way through, so the
   crossfade overlaps the end of the movement. Waiting for the slide to finish
   made two separate beats: the bar stopped, then the logo changed. */
.site-header.has-prodbar.is-retracted .prodbar__wordmark {
  opacity: 0; transition-delay: calc(var(--nav-swap) * 0.6);
}
.site-header.has-prodbar.is-retracted .prodbar__lockup {
  opacity: 1; transition-delay: calc(var(--nav-swap) * 0.6);
}

/* ONE set of calls to action. They sit in the company row, and as the island
   rises by 60px they are pushed down by 60px, so they hold their place on
   screen and end up on the product row. Nothing is duplicated, and nothing
   appears or disappears. */
.site-header.has-prodbar .header__actions {
  position: relative; z-index: 2;
  pointer-events: auto;                   /* the row above may be hidden */
  transition: transform var(--nav-swap) var(--nav-swap-ease);
}
.site-header.has-prodbar.is-retracted .header__actions {
  transform: translateY(var(--header-h));
  visibility: visible;                    /* survives the row's own hiding */
}

/* The fillets belong to the shell's inner edge, not to the island. The island
   rises by 60px and they are pushed down by 60px, so their position on screen
   never changes.

   The transition here is what was missing and it is not cosmetic: without it
   the offset snapped to its end value on the first frame while the island was
   still travelling, so mid slide the fillets detached and floated below the
   bar as loose white wedges. Matching duration and easing on both makes the
   two movements cancel exactly, at every frame rather than only at the ends. */
.site-header.has-prodbar::before,
.site-header.has-prodbar::after {
  transition: top var(--nav-swap) var(--nav-swap-ease);
}
.site-header.has-prodbar.is-retracted::before,
.site-header.has-prodbar.is-retracted::after {
  top: calc(var(--frame) - var(--header-top) + var(--header-h));
}

/* Elevation follows the island's visible height. The shadow stays: without a
   tonal step between bar and page there is nothing else holding it off the
   content, and a 1.5% step is not a tonal step.

   The shadow moves on the island's clock. Without a height transition it
   snapped to the retracted height on the first frame while the island was
   still travelling, so the product row slid with no shadow under it and the
   shadow popped back in when the island stopped. The box-shadow transition is
   the one site.css gives the shade, repeated because this rule replaces it. */
.header-shade.has-prodbar {
  height: calc(var(--header-h) + var(--prodbar-h));
  transition: height var(--nav-swap) var(--nav-swap-ease),
              box-shadow var(--t-panel) var(--ease);
}
.header-shade.has-prodbar.is-retracted { height: var(--header-h); }

@media (prefers-reduced-motion: reduce) {
  .site-header.has-prodbar,
  .site-header.has-prodbar::before,
  .site-header.has-prodbar::after,
  .site-header.has-prodbar .prodbar,
  .site-header.has-prodbar .header__actions,
  .header-shade.has-prodbar { transition: none; }
}

/* ---------------------- room for the second row -------------------------- */

html:has(.site-header.has-prodbar) {
  scroll-padding-top: calc(var(--header-h) + var(--prodbar-h) + 28px);
}
html:has(.site-header.has-prodbar) main.no-hero > section.is-open-block:first-child {
  padding-top: calc(var(--open-pad-y) + var(--header-h) + var(--prodbar-h));
}
html:has(.site-header.has-prodbar) .abody h2,
html:has(.site-header.has-prodbar) .abody h3 {
  scroll-margin-top: calc(var(--header-h) + var(--prodbar-h) + 28px);
}

/* ------------------------------ narrow screens --------------------------- */

@media (max-width: 860px) {
  :root { --prodbar-h: 44px; }
  .prodbar { padding: 0 16px; gap: 12px; }
  .prodbar__links a { font-size: 13.5px; padding: 6px 8px; }
  .prodbar__id { transform: scale(0.86); transform-origin: left center; }
}

/* ------------------------- arriving already pinned -----------------------
   A page reached from the product bar opens with the bar already primary, so
   the island has to be in its retracted position at the FIRST paint. The class
   is set by product-nav.js before that paint and dropped two frames later; for
   its short life it takes every duration in this file to zero, so the reader
   is shown the pinned state rather than watching the island slide up into it.

   Specificity, not !important: each selector here carries one class more than
   the rule it has to beat. */
.site-header.has-prodbar.is-instant,
.site-header.has-prodbar.is-instant::before,
.site-header.has-prodbar.is-instant::after,
.site-header.has-prodbar.is-instant .prodbar,
.site-header.has-prodbar.is-instant .prodbar__id,
.site-header.has-prodbar.is-instant .prodbar__wordmark,
.site-header.has-prodbar.is-instant .prodbar__lockup,
.site-header.has-prodbar.is-instant .site-header__inner,
.site-header.has-prodbar.is-instant .header__actions,
.header-shade.has-prodbar.is-instant {
  transition-duration: 0s;
  transition-delay: 0s;
}

/* A two-link product row (cRUD Collab: Resources, Contact) clipped its last
   word on a 390px phone: the lockup, the gap and two padded links came to
   roughly 309px on a 284px island. Tighter link padding on the smallest
   screens lets it fit; the six-link Webinar row still scrolls as before. */
@media (max-width: 480px) {
  .prodbar { gap: 8px; }
  .prodbar__links { gap: 2px; }
  .prodbar__links a { padding: 6px 6px; font-size: 13px; }
}

/* Resources replaced Formats in the Webinar row and is a few pixels longer,
   which pushed Pricing under the reserve kept for the calls to action: at
   1440px its last letters were clipped. Two pixels less side padding per link
   gives the six links back 24px, enough to fit at rest and retracted, while
   the underline keeps the same inset from the words. */
@media (min-width: 861px) {
  .prodbar__links a { padding: 9px 10px; }
  .prodbar__links a::after { left: 10px; right: 10px; }
}

/* ---------------- Collab: one Contact action once the bar takes over ----- */
/* Collab pages carry the usual Webinar Sign in and Get started in the company
   row. When the Collab row becomes the navbar those two give way to a single
   Contact action to /lets-discuss/, and they return when the company row
   comes back. The swap follows .is-retracted, which already has hysteresis,
   so it cannot flicker at the boundary. Hidden actions are display:none, so
   they leave the tab order as well as the screen. */
.header__actions .header__discuss { display: none; }
.site-header.has-prodbar.is-retracted .header__actions:has(.header__discuss) .header__default { display: none; }
.site-header.has-prodbar.is-retracted .header__actions .header__discuss { display: inline-flex; }
