/* topnav.css — canonical rules for the site topnav.
   Loaded by every page (index.html, harmony.html, the SSR year page)
   so the bar is pixel-identical everywhere. Edit ONLY this file when
   tweaking topnav appearance. */

/* Font fallbacks so pre-Google-Fonts metrics match across pages and
   the bar height doesn't jump while web fonts load. */
@font-face { font-family: 'DM Sans Fallback'; src: local('Arial'); size-adjust: 100.06%; ascent-override: 92.5%; descent-override: 24.1%; line-gap-override: 0%; }
@font-face { font-family: 'Lora Fallback'; src: local('Georgia'); size-adjust: 107.4%; ascent-override: 93.5%; descent-override: 25.65%; line-gap-override: 0%; }

.topnav { position: sticky; top: 0; z-index: 100; background: #ffffff; border-bottom: 1px solid var(--border); transition: box-shadow 0.22s ease; width: 100%; }
.topnav.scrolled { box-shadow: 0 6px 20px rgba(20,20,20,0.10); }
/* Pre-paint shadow on year-page reloads — applied via inline <head>
   script that reads sessionStorage so the shadow is present at first
   paint with no transition flicker. */
html.nan-preset-scrolled .topnav { box-shadow: 0 6px 20px rgba(20,20,20,0.10); transition: none; }
.topnav-inner { max-width: 1100px; margin: 0 auto; padding: 10px 2rem; display: flex; align-items: center; gap: 16px; min-height: 58px; }

.topnav-logo { display: flex; align-items: center; gap: 8px; text-decoration: none; color: var(--ink); flex-shrink: 0; min-width: 0; position: relative; top: -2px; }
.topnav-logo:hover, .topnav-logo:hover .topnav-logo-text { color: var(--ink); text-decoration: none; }
.topnav-logo-icon-stage { position: relative; width: 30px; height: 30px; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; overflow: hidden; }
.topnav-logo-icon { width: 30px; height: 30px; display: block; flex-shrink: 0; }
.topnav-logo-text { font-family: 'Lora', 'Lora Fallback', serif; font-size: 16px; font-weight: 600; white-space: nowrap; position: relative; top: 2px; display: inline-block; color: var(--ink); line-height: 1; vertical-align: baseline; }
.topnav-logo-text em { color: var(--blue); font-style: italic; }
.topnav-logo-not { position: relative; display: inline-block; line-height: 1; }
.topnav-logo-name { line-height: 1; }

/* Desktop layout (and mobile via the @media override below):
   logo on the left, then a flex gap, then the search bar, then the
   Baby names / Names by year / More tools pills aligned to the right
   edge. flex order: logo(1) → search(2) → links(3). The search's
   `margin-left: auto` consumes leading whitespace so search + links
   sit as one right-aligned group. */
.topnav-links { display: flex; align-items: center; gap: 16px; flex-shrink: 0; order: 3; }
.topnav-links .topnav-explore-wrap { display: inline-flex; }
.topnav-link {
  font-family: 'DM Sans', 'DM Sans Fallback', system-ui, sans-serif;
  font-size: 14px; font-weight: 500;
  color: var(--ink); text-decoration: none;
  /* Asymmetric vertical padding (9/7) shifts the text 1px down so it
     sits at the optical centre of the pill. DM Sans's cap-height/baseline
     ratio places glyphs slightly above the geometric centre of the line
     box; even 1px of correction is visible at this pill size. */
  padding: 9px 18px 7px; border-radius: 50px;
  background: var(--cream); border: 1px solid var(--border);
  transition: background 0.18s, color 0.18s, border-color 0.18s;
  white-space: nowrap; cursor: pointer;
  line-height: 1.2;
}
/* Hover and active share the same gold-family fill (--amber-light, a tint
   of the brand --amber rather than a separate yellow). The active state
   layers on an amber border — the rim is what says "selected", the fill
   says "interactive". Hover preview → click commits with the rim. */
.topnav-link:hover { background: var(--amber-light); color: var(--ink); text-decoration: none; }
.topnav-link.active,
.topnav-link.active:hover { background: var(--amber-light); color: var(--ink); border-color: var(--amber); }

.topnav-explore-wrap { position: relative; }
.topnav-explore-btn {
  padding: 9px 18px 7px; border-radius: 50px;
  background: var(--cream); color: var(--ink);
  border: 1px solid var(--border);
  font-family: 'DM Sans', 'DM Sans Fallback', system-ui, sans-serif;
  font-size: 14px; font-weight: 500;
  cursor: pointer; transition: background 0.18s, color 0.18s, border-color 0.18s;
  white-space: nowrap; display: inline-flex; align-items: center; gap: 6px;
  line-height: 1.2;
}
.topnav-explore-btn:hover { background: var(--amber-light); }
.topnav-explore-btn[aria-expanded="true"],
.topnav-explore-btn.active,
.topnav-explore-btn.active:hover { background: var(--amber-light); color: var(--ink); border-color: var(--amber); }
/* Caret drawn with CSS borders so it stays crisp at any font scale and
   stays vertically centred with the text. The character glyph used to
   stretch in some Lora/DM Sans weights. */
.topnav-explore-caret { display: inline-block; width: 0; height: 0; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 6px solid currentColor; transition: transform 0.18s; position: relative; top: 1px; font-size: 0; }
.topnav-explore-btn[aria-expanded="true"] .topnav-explore-caret { transform: rotate(180deg); }

/* Animated hamburger: three lines that fold into an X when the menu is open.
   Built from spans so we can transition them; a unicode glyph can't animate.
   Sized at 14×10 so it sits comfortably inside the 30px round mobile pill
   (matching the logo icon's diameter). */
.topnav-hamburger { display: inline-block; width: 14px; height: 10px; position: relative; vertical-align: middle; }
.topnav-hamburger span { position: absolute; left: 0; right: 0; height: 2px; background: currentColor; border-radius: 1px; transition: transform 0.22s ease, opacity 0.18s ease, top 0.22s ease; }
.topnav-hamburger span:nth-child(1) { top: 0; }
.topnav-hamburger span:nth-child(2) { top: 4px; }
.topnav-hamburger span:nth-child(3) { top: 8px; }
.topnav-explore-btn[aria-expanded="true"] .topnav-hamburger span:nth-child(1) { top: 4px; transform: rotate(45deg); }
.topnav-explore-btn[aria-expanded="true"] .topnav-hamburger span:nth-child(2) { opacity: 0; }
.topnav-explore-btn[aria-expanded="true"] .topnav-hamburger span:nth-child(3) { top: 4px; transform: rotate(-45deg); }

.topnav-explore-menu {
  position: absolute; top: calc(100% + 8px); right: 0;
  background: white; border: 1px solid var(--border);
  border-radius: 14px; box-shadow: 0 12px 36px rgba(44,44,42,0.10);
  width: 300px; padding: 6px;
  display: none; z-index: 200;
}
.topnav-explore-menu.open { display: block; }
.topnav-explore-menu a, .topnav-explore-menu button {
  display: block; width: 100%; text-align: left;
  padding: 12px 14px; border-radius: 10px;
  background: transparent; border: 0;
  color: var(--ink); text-decoration: none; cursor: pointer;
  font-family: inherit;
}
/* 6px breathing room between stacked menu items so a hover-tint never
   visually touches the rim of the active (current-page) item. 2px was
   too tight — the hover-bg still grazed the amber inset rim of its
   neighbour at common scroll-bar pixel snapping. */
.topnav-explore-menu > * + * { margin-top: 6px; }
.topnav-explore-menu a:hover, .topnav-explore-menu button:hover { background: var(--amber-light); text-decoration: none; }
/* Dropdown items have no native border, so the active rim is faked with
   an inset box-shadow — same visual language as the active pills above. */
.topnav-explore-current,
.topnav-explore-current:hover { background: var(--amber-light) !important; box-shadow: inset 0 0 0 1px var(--amber); }
.topnav-explore-menu strong {
  display: block;
  font-family: 'Lora', 'Lora Fallback', serif;
  font-size: 16px; font-weight: 600; color: var(--ink);
}
.topnav-explore-menu span {
  display: block; color: var(--muted);
  font-size: 13px; margin-top: 2px; line-height: 1.35;
}

.topnav-search { position: relative; width: 300px; margin-left: auto; flex-shrink: 0; order: 2; opacity: 0; transform: translateY(-4px); pointer-events: none; transition: opacity 0.22s ease, transform 0.22s ease; }
.topnav-search.visible, .topnav-search--always { opacity: 1; transform: translateY(0); pointer-events: auto; }
.topnav-search input {
  width: 100%; height: 36px; line-height: 36px;
  padding: 0 36px 0 18px;
  border: 1px solid var(--border); border-radius: 50px;
  font-family: 'DM Sans', 'DM Sans Fallback', system-ui, sans-serif; font-size: 14px;
  background: white; color: var(--ink);
  outline: none; box-sizing: border-box; text-overflow: ellipsis;
}
.topnav-search input:focus { border-color: var(--border); }
.topnav-search input::placeholder { color: var(--muted); text-overflow: ellipsis; overflow: hidden; }
.topnav-search-clear {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  width: 22px; height: 22px;
  display: none; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--cream); border: none;
  cursor: pointer; color: var(--muted);
  font-family: Arial, sans-serif;
  line-height: 22px; padding: 0; font-size: 14px;
}
.topnav-search-clear:hover { background: var(--border); color: var(--ink); }
.topnav-search-clear.visible { display: inline-flex; }

/* Responsive — applied identically across all three pages. */
@media (max-width: 1100px) {
  .topnav-link { padding: 7px 14px; font-size: 13px; }
  .topnav-explore-btn { padding: 7px 14px; font-size: 13px; }
  /* gap only — no margin-left. With the order flipped (search 2,
     links 3) extra margin-left on links would push them away from
     the search pill instead of keeping them adjacent on the right. */
  .topnav-links { gap: 6px; }
}
@media (max-width: 1000px) {
  .topnav-search { width: 240px; }
}
@media (max-width: 860px) {
  .topnav-link { padding: 7px 13px; font-size: 13px; }
  .topnav-explore-btn { padding: 7px 12px; font-size: 13px; }
  .topnav-inner { gap: 8px; padding: 10px 1rem; }
  .topnav-links { gap: 6px; }
  .topnav-search { width: 200px; }
}
@media (max-width: 720px) {
  .topnav-inner { padding: 8px 1rem; gap: 8px; }
  .topnav-search { width: 170px; }
}
@media (max-width: 640px) {
  /* On mobile, the dropdown anchors the right edge and the search bar sits
     to its left. Flex `order` is used to flip source order without
     touching the HTML, keeping the markup identical across pages. The
     standalone Baby names / Names by year pills hide; their entries
     resurface inside the dropdown (.topnav-explore-menu-mobile). */
  .topnav-links > a.topnav-link { display: none; }
  /* The search bar (order 2) has margin-left/right:auto, so even when
     collapsed to max-width:0 its auto margins still consume free
     space and push the hamburger to the right edge. */
  .topnav-links { order: 3; margin-left: 0; gap: 0; }
  /* Search is centred between logo and hamburger via balanced auto
     margins. Width transitions from 0 (collapsed) to 225 (expanded) so
     the layout doesn't reflow on scroll — the bar grows in place
     while the logo wordmark slides off. Default state is collapsed
     because the 225px wide invisible slot would otherwise push the
     hamburger past the right edge of a 375px viewport. */
  .topnav-search {
    order: 2; margin-left: auto; margin-right: auto;
    width: 225px; max-width: 0; overflow: hidden;
    transition: max-width 0.28s ease, opacity 0.22s ease, transform 0.22s ease;
  }
  .topnav-search.visible, .topnav-search--always { max-width: 225px; }
  /* iOS Safari zooms the page on input focus when font-size < 16px.
     Bump the search input to 16px on mobile so the viewport stays put
     when the keyboard opens — the placeholder still fits at 225px. */
  .topnav-search input { font-size: 16px; }
  /* Round hamburger pill sized to match the logo's 30px icon body — so
     the two visually balance at either end of the nav bar (round logo
     face on the left, round menu pill on the right). */
  .topnav-explore-btn { padding: 0; gap: 0; width: 30px; min-width: 30px; height: 30px; border-radius: 50%; justify-content: center; align-items: center; }
  /* Default mobile: show the full wordmark ("Not another Noah") so
     brand is visible on first paint. When the search input becomes
     visible (either via scroll on /, which toggles
     .topnav-search.visible, or by virtue of --always on /year and
     /harmony), the wordmark slides off to make room — see the
     :has() rule below. */
  .topnav-logo-text {
    display: inline-block;
    max-width: 200px; opacity: 1; transform: translateX(0);
    overflow: hidden; white-space: nowrap;
    transition: max-width 0.28s ease, opacity 0.2s ease, transform 0.28s ease;
  }
  .topnav-inner:has(.topnav-search.visible) .topnav-logo-text,
  .topnav-inner:has(.topnav-search--always) .topnav-logo-text {
    max-width: 0; opacity: 0; transform: translateX(-10px);
  }
  /* "Noah moment": when the user searches Noah, the logo gets
     .noah-moment and the scribble animates under "Not". On mobile that
     animation only lands if the full wordmark is visible, so the logo
     wins the real estate over the search bar while the moment is live. */
  .topnav-inner:has(.topnav-logo.noah-moment) .topnav-logo-text,
  .topnav-inner:has(.topnav-logo.noah-exit) .topnav-logo-text {
    max-width: 200px; opacity: 1; transform: translateX(0);
    /* Let the scribble paint below the baseline of "Not". The slide-off
       rule above clips it; we explicitly unclip while the moment is live. */
    overflow: visible;
  }
  .topnav-inner:has(.topnav-logo.noah-moment) .topnav-search,
  .topnav-inner:has(.topnav-logo.noah-exit) .topnav-search {
    /* Collapse to 0 width (rather than display:none) so the layout
       transitions in/out instead of snapping. The search's own auto
       margins still anchor the hamburger to the right edge. */
    max-width: 0;
  }
  .topnav-inner { padding: 8px 0.75rem; gap: 8px; }
  /* Dropdown anchored to viewport edge so it never clips off-screen. */
  .topnav-explore-menu { width: calc(100vw - 1.5rem); max-width: 320px; right: -0.25rem; }
}

/* Label swap on the dropdown button: "More tools" on desktop, animated
   hamburger on mobile so the only nav button doesn't read as boring as
   "Menu". */
.topnav-explore-btn-label-mobile { display: none; }
@media (max-width: 640px) {
  .topnav-explore-btn-label-desktop { display: none; }
  .topnav-explore-btn-label-mobile { display: inline-flex; line-height: 1; }
  /* Caret is redundant when the hamburger itself animates to an X. */
  .topnav-explore-caret { display: none; }
}

/* Floating shortlist button — same shape, position, and behaviour on
   every page that loads topnav.css. Visibility (count + .visible) is
   driven by JS on each page; the styling here is shared so the FAB
   never "jumps" between pages. Mirrors the main site's #shortlistFab
   in styles.css; defined here too so /harmony and /year/* pick it up
   without pulling in app.js. */
.shortlist-fab {
  position: fixed; bottom: 24px; right: 24px; z-index: 900;
  display: none; align-items: center; gap: 6px;
  padding: 12px 18px; border-radius: 50px;
  background: linear-gradient(135deg, #B8943E 0%, #D4B05A 50%, #B8943E 100%);
  color: white; border: none; text-shadow: 0 1px 1px rgba(0,0,0,0.1);
  font-family: 'DM Sans', 'DM Sans Fallback', sans-serif; font-size: 14px; font-weight: 600;
  cursor: pointer; box-shadow: 0 4px 16px rgba(0,0,0,0.15);
  transition: transform 0.2s, box-shadow 0.2s; white-space: nowrap;
  text-decoration: none;
}
.shortlist-fab.visible { display: inline-flex; }
.shortlist-fab:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0,0,0,0.2); text-decoration: none; color: white; }
.shortlist-fab svg { width: 18px; height: 18px; }
.shortlist-fab .fab-heart-icon { display: inline-flex; align-items: center; position: relative; top: 1px; }
.shortlist-fab .fab-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; border-radius: 10px;
  background: white; color: #B8943E; font-size: 12px; font-weight: 700;
  padding: 0 5px;
}
@media (max-width: 600px) {
  .shortlist-fab { bottom: 16px; right: 16px; padding: 10px 14px; font-size: 13px; }
}

/* Heart animations shared across pages. Originally only in
   styles.css (main site); promoted here so the FAB pulse + floating
   hearts also play when /harmony's in-card shortlist button writes
   a save. Mirrors the .heart-btn add experience on /name pages. */
.shortlist-fab.fab-added { animation: fabBtnPulse 0.35s cubic-bezier(0.34, 1.56, 0.64, 1); }
@keyframes fabBtnPulse {
  0% { transform: scale(1); }
  50% { transform: scale(1.1); }
  100% { transform: scale(1); }
}
.fab-float-heart {
  position: fixed; pointer-events: none; z-index: 901;
  color: #B8943E; opacity: 0;
  animation: floatHeartUp var(--dur) ease-out forwards;
  animation-delay: var(--delay);
}
@keyframes floatHeartUp {
  0%   { opacity: 0; transform: translate(0, 0) scale(0.5); }
  8%   { opacity: 0.7; }
  20%  { opacity: 0.6; transform: translate(var(--drift1), -12px) scale(0.85); }
  50%  { opacity: 0.4; transform: translate(var(--drift2), -35px) scale(0.75); }
  80%  { opacity: 0.12; transform: translate(var(--drift3), -58px) scale(0.6); }
  100% { opacity: 0; transform: translate(var(--drift3), -70px) scale(0.5); }
}
@keyframes heartPop {
  0% { transform: scale(1); }
  50% { transform: scale(1.25); }
  100% { transform: scale(1); }
}


/* Mobile-only entries that surface the Baby names / Names by year links
   inside the dropdown when the standalone pills are hidden. Selectors
   include `.topnav-explore-menu` so they beat the menu-anchor default
   `display: block` rule on specificity. */
.topnav-explore-menu .topnav-explore-menu-mobile { display: none; }
@media (max-width: 640px) {
  .topnav-explore-menu .topnav-explore-menu-mobile { display: block; }
}
