/**
 * Navbar - core shell (blocking tier).
 *
 * Header bar, brand, top-level rows, buttons. Panels/dropdowns/drawer live in
 * base_navbar_panels.css (deferred) so the render-blocking cost stays small.
 *
 * Closed panels need no first-paint guard here: they carry the `hidden`
 * attribute, which the UA stylesheet already renders as display:none, so there is
 * no window in which they can flash before the deferred sheet arrives.
 *
 * COLOUR RULE: this file contains no colour literals. Every colour resolves from
 * --primary-blue through the --brand* / --nb-* variables declared in
 * base_style.css, so a project rebrands by overriding one variable. If you find
 * yourself typing a hex value here, add a derived variable there instead.
 *
 * There are deliberately no !important declarations. The `nb-` prefix is new, so
 * legacy project navbar CSS matches nothing and dies harmlessly rather than
 * half-applying - that is what removes the need for overrides.
 */

/* ---------------------------------------------------- third-party reset */

/*
 * The admin/web layouts load Skeleton from a CDN, whose global
 * `.button, button, input[type=submit]…` rule uppercases every button, adds
 * letter-spacing and a bottom margin, and forces its own height. Those land on
 * the navbar's <button> elements (triggers, theme control, collapses) but not on
 * the <a> ones, which is why only some rows looked wrong.
 *
 * A single class selector (0,1,0) outranks Skeleton's element selectors (0,0,1),
 * so this resets cleanly without !important.
 *
 * Reset ONLY properties no navbar component sets for itself. `.nb-root button`
 * scores 0,1,1 and would therefore beat `.nb-icon-btn` (0,1,0) - putting `height`
 * in here would silently collapse the 40px icon buttons.
 */
.nb-root button,
.nb-drawer button {
  text-transform: none;
  letter-spacing: normal;
  margin: 0;
}

/* --------------------------------------------------------------- shell */

:root,
body {
  --nb-height: 74px;
  /* Other stylesheets (sidebar, blog, theme switcher, user panel) position
     against --navbar-offset, so keep it equal to the real bar height. */
  --navbar-offset: 74px;
}

.nb-root {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  background: var(--nb-rest-bg);
  border-bottom: 1px solid transparent;

  /* How much of the surface survives in the scrolled (un-hovered) bar. Kept as
     variables rather than theme-scoped rules for `.nb-root--scrolled`: such a
     rule would out-specify the `:hover` one below and the bar could no longer
     settle to solid. */
  --nb-glass-strength: 42%;
  --nb-glass-blur: 20px;
}

@media (min-width: 901px) {
  .nb-root {
    z-index: 1300;
  }
}

/*
 * PROJECT THEMING HOOKS
 *
 * The base navbar is one shared template, so a project that wants a different
 * *look* must not fork the markup or re-declare these rules - it sets these
 * variables in its own stylesheet and the shared rules below pick them up.
 * Every default here is the value that was previously hardcoded, so a project
 * that sets nothing renders exactly as before.
 *
 * Declared on .nb-root AND .nb-drawer because the drawer is rendered outside
 * the bar. A project overrides them by re-stating the same two selectors in a
 * stylesheet that loads after this one - equal specificity, later wins, so no
 * !important is ever needed. Setting them on `body` will NOT work: a value
 * declared directly on .nb-root beats an inherited one.
 */
.nb-root,
.nb-drawer {
  /* Shape. --control covers bar links and buttons, --row the rows inside
     panels, --panel the floating cards. Pill bar by default. */
  --nb-radius-control: 999px;
  --nb-radius-row: 14px;
  --nb-radius-panel: 20px;

  /* Display face for bar links/CTA. Panel rows follow --nb-row-font instead. */
  --nb-font: 'Plus Jakarta Sans', sans-serif;

  /* Bar-link typography. */
  --nb-link-font: var(--nb-font, inherit);
  --nb-link-size: 14px;
  --nb-link-weight: 700;
  --nb-link-tracking: -0.3px;

  /* Panel-row typography - body face, distinct from the bar's display face. */
  --nb-row-font: 'Be Vietnam Pro', sans-serif;
  --nb-row-size: 13px;
  --nb-row-weight: 600;

  /* Hover treatment. The two transforms are the micro-motion vocabulary:
     bar links lift, panel rows slide. Both default to no movement. */
  --nb-link-hover-bg: var(--brand-softer);
  --nb-link-hover-lift: 1px;
  --nb-row-hover-bg: var(--brand-softer);
  --nb-row-hover-shift: 0px;

  /* Extra background layer(s) painted over --nb-panel on every floating card -
     e.g. corner radial blooms. Must be a background-IMAGE value. */
  --nb-panel-bloom: none;

  /* Primary call-to-action. Accepts a gradient, and the shadow is a full
     box-shadow value so a project can stack inset highlights onto it. */
  --nb-cta-bg: linear-gradient(
    135deg,
    var(--cta-gradient-start) 0%,
    var(--cta-gradient-mid) 55%,
    var(--cta-gradient-end) 100%
  );
  --nb-cta-ink: var(--brand-ink);
  --nb-cta-shadow: 0 6px 18px -6px var(--brand);

  /* The bar's background before the page has scrolled. Defaults to
     `transparent` so the bar shows the actual pixels behind it rather than
     repainting a flat band: at rest (scrollTop 0) that is the top of the page,
     so the page's own decoration layer - the fixed body::before texture, or a
     flush hero's blooms - reads straight through the bar with no seam. On any
     non-flush page the reserved spacer means the page background shows through
     unchanged, so this only ever adds seamlessness, never removes contrast. A
     project that wants a solid band at rest sets this to `var(--bg-gradient)`
     (or any colour) instead. */
  --nb-rest-bg: transparent;
}

/* Light needs to go further to read as glass: a white surface over a near-white
   page barely separates at the dark theme's 42%, so it just looks like a flat
   band. More transparency and a wider blur is what actually sells it here. */
body.theme-light .nb-root {
  --nb-glass-strength: 24%;
  --nb-glass-blur: 24px;
}

/* On dark the shared page palette (#eeeeee / #bebebe) reads distinctly grey in
   the navbar, especially against the translucent scrolled surface. Lift the two
   text tokens to white here only - scoping to .nb-root keeps the rest of the
   page on the softer body palette. Panels are descendants, so the products and
   language menus inherit it too. */
body.theme-dark .nb-root {
  --text-primary: #ffffff;
  --muted-text: #d5d5d5;
}

/* Only gains a surface once the page is scrolled, so it floats over heroes.
   At rest the surface stays translucent so the page reads through it as you
   scroll; pointing at the bar settles it to the fully solid surface so the
   rows and menus are at full contrast while you are actually using them. */
.nb-root--scrolled {
  background: color-mix(
    in srgb,
    var(--nb-surface) var(--nb-glass-strength),
    transparent
  );
  border-bottom-color: color-mix(in srgb, var(--border-color) 45%, transparent);
  box-shadow: 0 8px 30px -10px var(--nb-shadow);
  backdrop-filter: saturate(1.8) blur(var(--nb-glass-blur));
  -webkit-backdrop-filter: saturate(1.8) blur(var(--nb-glass-blur));
  transition:
    background 0.22s ease,
    border-bottom-color 0.22s ease,
    backdrop-filter 0.22s ease;
}

/* `:focus-within` keeps it solid for keyboard users, and an open menu counts as
   "in use" even when the pointer has wandered off the bar. */
.nb-root--scrolled:hover,
.nb-root--scrolled:focus-within,
.nb-root--scrolled.nb-root--open {
  background: var(--nb-surface);
  border-bottom-color: var(--border-color);
  backdrop-filter: saturate(1.5) blur(10px);
  -webkit-backdrop-filter: saturate(1.5) blur(10px);
}

/*
 * Full-bleed: the brand sits at the left edge and the actions at the right,
 * rather than inside a 1240px column with large empty gutters. The design's
 * fixed max-width left ~22% of a wide screen unused on either side.
 *
 * A project that wants the bar to line up with a centred page container can put
 * the cap back with `.nb-bar { max-width: 1240px; margin: 0 auto; }`.
 */
/*
 * Reserve the bar's height for the page.
 *
 * The previous navbar was `position: sticky`, so it occupied normal flow and
 * content sat below it for free. This one is `fixed` - required for the design's
 * transparent-over-hero behaviour - which takes it out of flow, so every page
 * would otherwise start underneath it.
 *
 * Done with a spacer element emitted next to the bar, so it works on every page
 * without touching a single project template - and unlike padding on <main>, no
 * page stylesheet can cancel it.
 */
.nb-spacer {
  height: var(--nb-height);
  flex-shrink: 0;
}

/* Full-bleed pages: the hero is designed to sit under the transparent bar, so
   the spacer collapses. `container-fullwidth` is the layout's existing marker
   for that, so no project template needs a new class. */
/*
 * Only an explicit opt-in collapses it.
 *
 * There is no reliable existing marker for "this page is designed to run under
 * the bar": `container-fullwidth` is used by both the landing hero (which is)
 * and the feedback app (which is not), and `landing-container` marks auth /
 * user-panel / error pages that all need the offset. Guessing from those left
 * pages broken, so the spacer applies everywhere until a page opts out with
 * `nb-flush`.
 */
body:has(.nb-flush) .nb-spacer {
  height: 0;
}

.nb-bar {
  /* Follows --nb-height so a project can change the bar height from one
     variable; --navbar-offset and .nb-spacer already track the same token. */
  height: var(--nb-height);
  padding: 0 24px;
  display: flex;
  align-items: center;
  gap: 6px;
  /* Keeps .nb-actions hard right at mobile widths, where .nb-nav is
     display:none and so cannot grow into the gap for it. At desktop this is a
     no-op - the nav has already eaten all the free space. See the note on
     .nb-nav for why an auto margin can't be used for either case. */
  justify-content: space-between;
  /* One hook for the whole bar's typeface. Defaults to the page font, so the
     navbar follows whatever the project sets on body; point it at a display
     font to match the headings instead. */
  font-family: var(--nb-font, inherit);
}

/* --------------------------------------------------------------- brand */

.nb-brand {
  /* Skeleton styles bare `a`; this anchor's text lives in child spans, so
     without a colour of its own it inherits Skeleton's link blue. */
  color: inherit;
  display: flex;
  align-items: center;
  gap: 11px;
  margin-right: 6px;
  flex-shrink: 0;
  text-decoration: none;
}

/*
 * Neutral tile, matching the lockup the previous navbar used: surface fill, a
 * hairline border and a 10px radius - no gradient, no shadow, nothing painted
 * over the mark. The tile is what keeps a light or white logo legible against a
 * transparent header.
 */
.nb-brand__badge {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: var(--nb-surface);
  border: 1px solid var(--border-color);
  display: grid;
  place-items: center;
  flex-shrink: 0;
  /* The mark is completely static - it is a logo, not a control. Global rules
     put `transition: all` on descendants of an <a>, so pin it off here rather
     than relying on nothing happening to declare a hover state later. */
  transition: none;
}

.nb-brand__img {
  width: 28px;
  height: 28px;
  object-fit: contain;
  transition: none;
}

/* Same neutral system-font default as .footer-brand-name (base_footer.css)
   for the same reason: a project that never set its own display font
   should not silently pick up body's 'Be Vietnam Pro'. */
.nb-brand__text {
  font-family:
    -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
  font-weight: 600;
  font-size: 20px;
  letter-spacing: -0.5px;
  color: var(--text-primary);
  white-space: nowrap;
}

.nb-brand__text .brand-tld {
  font-size: 0.72em;
  color: var(--primary-blue);
}

/* ----------------------------------------------------------------- nav */

.nb-nav {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-left: 8px;
  position: relative;
  /* Grow into the empty middle of the bar so .nb-actions ends up hard right.
     `margin-left: auto` on .nb-actions cannot do this job: the dropdown panels
     live inside .nb-nav, so its max-content width runs into the thousands, the
     flex line's free space is NEGATIVE, and an auto margin only absorbs
     POSITIVE free space - it silently collapses to 0 and the actions bunch up
     against the nav mid-bar. min-width:0 lets the nav shrink below that
     intrinsic width instead of overflowing on narrow viewports. */
  flex: 1 1 auto;
  min-width: 0;
}

.nb-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}

/* ---------------------------------------------------------------- rows */

.nb-row {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 14px;
  border: none;
  background: none;
  border-radius: var(--nb-radius-row);
  font-family: var(--nb-row-font);
  font-weight: var(--nb-row-weight);
  font-size: var(--nb-row-size);
  line-height: 1.2;
  color: var(--text-primary);
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}

/* Bar links can differ from panel rows in shape and type - eduloo, for one,
   runs a 999px pill bar in one face over 14px dropdown rows in another. */
.nb-row--top {
  border-radius: var(--nb-radius-control);
  font-family: var(--nb-link-font);
  font-size: var(--nb-link-size);
  font-weight: var(--nb-link-weight);
  letter-spacing: var(--nb-link-tracking);
}

@media (prefers-reduced-motion: no-preference) {
  .nb-row {
    transition:
      background 0.22s ease,
      color 0.22s ease,
      border-color 0.22s ease,
      transform 0.22s ease;
  }
}

/*
 * Two selectors deep on purpose. `base_elements.css` carries
 * `a .fas { font-size: 0.9em }`, which at 0,1,1 outranks a single class - so
 * anchor rows rendered their icons at 13px while <button> triggers kept the full
 * size, a 45% mismatch sitting side by side in the same bar. Winning at 0,2,0
 * makes every row agree regardless of its tag.
 */
.nb-row .nb-row__icon,
.nb-row__icon {
  font-size: 16px;
  color: var(--brand);
}

.nb-row__chev {
  font-size: 13px;
  color: var(--muted-text);
}

.nb-row__flag.fi {
  /* `.fi` from the flag-icons sheet sizes in em (1.333em x 1em) and loads after
     this file, so an equal-specificity selector loses. Doubling up on .fi wins
     without !important. */
  width: 21px;
  height: 15px;
  border-radius: 3px;
  box-shadow: 0 0 0 1px var(--border-color);
  flex-shrink: 0;
}

.nb-row__label {
  min-width: 0;
}

.nb-row--top:hover,
.nb-row--top[aria-expanded='true'] {
  color: var(--brand);
  background: var(--nb-link-hover-bg);
}

.nb-row--top:hover .nb-row__icon,
.nb-row--top[aria-expanded='true'] .nb-row__icon {
  color: var(--brand);
}

/* --------------------------------------------------------------- buttons */

.nb-icon-btn {
  width: 40px;
  height: 40px;
  /* Both declared deliberately: Skeleton's global button rule ships
     `padding: 0 30px` and `line-height: 38px`, and padding sets an element's
     minimum width - without this the 40px square renders 62px wide. */
  padding: 0;
  line-height: 1;
  display: grid;
  place-items: center;
  border: 1px solid var(--border-color);
  background: var(--nb-surface);
  border-radius: var(--nb-radius-control);
  color: var(--text-primary);
  font-size: 18px;
  cursor: pointer;
}

/*
 * Mix toward an opaque surface rather than using the translucent --brand-softer.
 * A 10% brand tint over an already-dark background is essentially invisible, so
 * hover gave no feedback in dark mode. Mixing against --nb-surface produces a
 * solid colour with real contrast in both themes, and the border lifts too so
 * the affordance survives even where the fill is subtle.
 */
.nb-icon-btn:hover,
.nb-icon-btn[aria-expanded='true'],
.nb-user__toggle:hover,
.nb-user__toggle[aria-expanded='true'] {
  background: color-mix(in oklch, var(--brand) 18%, var(--nb-surface));
  border-color: color-mix(in oklch, var(--brand) 45%, var(--border-color));
  color: var(--brand);
}

.nb-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 22px;
  border: none;
  border-radius: var(--nb-radius-control);
  font-family: var(--nb-font, inherit);
  font-weight: 700;
  font-size: 14px;
  cursor: pointer;
  text-decoration: none;
}

.nb-btn--primary {
  color: var(--nb-cta-ink);
  background: var(--nb-cta-bg);
  box-shadow: var(--nb-cta-shadow);
}

.nb-root .nb-btn--primary,
.nb-drawer .nb-btn--primary {
  color: var(--nb-cta-ink);
}

/* The tile follows the button into its brand state, so the whole control reads
   as one piece rather than a neutral circle inside a brand-tinted pill. */
.nb-user__toggle:hover .nb-user__avatar,
.nb-user__toggle[aria-expanded='true'] .nb-user__avatar {
  background: color-mix(in oklch, var(--brand) 22%, transparent);
  color: var(--brand);
}

/* `.nb-btn--primary` is an <a>, so the global `a:hover { color: var(--link-hover) }`
   (0,1,1) outranks the button's own colour (0,1,0) and repainted the label in the
   link colour on hover. Restating it here at 0,2,0 keeps the ink colour. */
.nb-btn--primary:hover,
.nb-btn--primary:focus {
  color: var(--nb-cta-ink);
  filter: brightness(1.06);
}

.nb-btn--danger {
  width: 100%;
  padding: 14px;
  border: 1px solid var(--border-color);
  background: none;
  color: var(--danger);
  font-size: 15px;
}

.nb-btn--danger:hover {
  color: var(--danger);
  background: color-mix(in oklch, var(--danger) 12%, transparent);
}

:where(.nb-root, .nb-drawer) button:hover,
:where(.nb-root, .nb-drawer) button:focus {
  color: var(--text-primary);
}

/* -------------------------------------------------------------- account */

.nb-user {
  position: relative;
}

.nb-user__toggle {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 4px 8px 4px 4px;
  border: 1px solid var(--border-color);
  background: var(--nb-surface);
  border-radius: 24px;
  font-family: inherit;
  cursor: pointer;
}

.nb-user__avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  /* A neutral tile with a normal-ink glyph, matching the notification and
     products buttons beside it. The brand colour belongs to the button's
     hover/open state (below), not to its resting icon. */
  background: color-mix(in oklch, var(--text-primary) 7%, transparent);
  color: var(--text-primary);
  font-size: 20px;
  /* Skeleton's global `button { line-height: 38px }` is inherited from the
     toggle, and a 38px line box inside a 32px circle pushes the glyph off
     centre. .nb-icon-btn sets this for the same reason. */
  line-height: 1;
}

.nb-user__avatar--lg {
  width: 40px;
  height: 40px;
  font-size: 24px;
}

/* ------------------------------------------------------------ responsive */

.nb-burger {
  display: none;
}

/* Matches the design's 960px breakpoint. Below it the bar collapses to
   brand + account + burger, and everything else moves into the drawer. */
@media (max-width: 960px) {
  :root,
  body {
    --nb-height: 64px;
    --navbar-offset: 64px;
  }

  .nb-bar {
    height: 64px;
    padding: 0 16px;
  }

  /* The account menu and the notification bell both repeat inside the drawer,
     so showing them in the bar as well just crowds a 375px header with three
     controls that lead to the same places. The burger is the single entry
     point at this width. */
  .nb-nav,
  .nb-big-wrap,
  .nb-btn--top,
  .nb-user,
  .nb-notif {
    display: none;
  }

  .nb-burger {
    display: grid;
  }

  .nb-brand__text {
    font-size: 17px;
  }
}

/* --------------------------------------------------------------- motion */

@media (prefers-reduced-motion: no-preference) {
  .nb-root {
    transition:
      background 0.3s ease,
      box-shadow 0.3s ease,
      border-color 0.3s ease,
      backdrop-filter 0.3s ease;
  }

  .nb-bar {
    transition: height 0.32s cubic-bezier(0.4, 0, 0.2, 1);
  }

  /* The brand mark is deliberately static - no hover transform or colour
     shift. It is a logo, not a control. */

  .nb-row {
    transition:
      color 0.2s ease,
      background 0.2s ease,
      transform 0.24s cubic-bezier(0.34, 1.56, 0.64, 1);
  }

  .nb-row__icon {
    transition:
      transform 0.32s cubic-bezier(0.34, 1.56, 0.64, 1),
      color 0.2s ease;
  }

  /* Overshoot-and-settle: the icon scales past its target then eases back. */
  /* The lift lives here (inside the reduced-motion guard) rather than on the
     base :hover rule, so a project that disables motion keeps its colours.
     Default 2px is what the bar has always used. */
  .nb-row--top:hover {
    transform: translateY(calc(-1 * var(--nb-link-hover-lift, 2px)));
  }

  .nb-row--top:hover .nb-row__icon {
    transform: scale(1.14) rotate(-4deg);
  }

  .nb-row__chev {
    transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  }

  .nb-row[aria-expanded='true'] .nb-row__chev,
  .nb-user__toggle[aria-expanded='true'] .nb-row__chev {
    transform: rotate(180deg);
  }

  .nb-icon-btn,
  .nb-btn {
    transition:
      background 0.15s ease,
      filter 0.15s ease,
      transform 0.15s ease;
  }

  .nb-btn--primary:hover {
    transform: translateY(-1px);
  }
}
