.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--color-paper);
  border-bottom: 1px solid var(--color-border);
  /* Zero in a normal browser — the browser's own chrome is above us there,
     so inset-top is 0px and this changes nothing. It only becomes non-zero
     in a standalone PWA or the native shell, where the page owns the whole
     screen and the header would otherwise sit under the status bar.
     Depends on viewport-fit=cover in base.html; without it, inert. */
  padding-top: env(safe-area-inset-top, 0px);
}

.site-header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  /* Longhand, not the `padding` shorthand — this element also carries
     .container (see includes/nav.html), and the shorthand would win the
     whole property over .container's own left/right padding (this file
     loads before components.css, but that's incidental — same bug class
     as the .section fix above; anything paired with .container must use
     top/bottom-only longhand or it silently zeroes .container's sides). */
  padding-top: var(--space-4);
  padding-bottom: var(--space-4);
}

.site-logo:hover { text-decoration: none; }
/* --brand-*, not --color-*, everywhere the mark is drawn: the palette is
   themable and the logo is not. See static/css/tokens.css. */
.site-logo:hover .logo-word { color: var(--brand-primary-light); }

.logo-lockup { display: inline-flex; align-items: center; gap: var(--space-2); }
.logo-mark { flex: none; margin-bottom: 7px; }
.logo-word {
  font-family: var(--font-serif);
  font-size: 1.375rem;
  line-height: 1;
  color: var(--brand-primary);
  font-weight: 400;
  letter-spacing: -0.01em;
  transition: color 0.15s ease;
}
.logo-word-accent { color: var(--brand-accent); }
.logo-word-light { color: #fff; }
.logo-word-light .logo-word-accent { color: var(--brand-accent-light); }

/* Tighter on the left (where the avatar sits flush against the pill edge)
   than the right (where the name needs breathing room) — overrides
   .btn-sm's uniform padding. Compound selector (not a bare class) so this
   wins on specificity alone, regardless of nav.css/components.css load
   order — see the note on .mobile-nav-* below for why that matters here. */
.nav-account-name.btn-sm { padding: 0.4rem 0.9rem 0.4rem 0.4rem; }

/* The mobile menu's account block (profile name + logout, moved out of the
   header row below 480px — see the media query further down) is hidden by
   default. This default MUST come before that media query in source order:
   it has the same specificity as the override, and a later unconditional
   rule always beats an earlier conditional one regardless of which media
   query currently matches. */
.mobile-nav-account { display: none; }

/* Below this width, the header (logo + language switcher + account
   actions + hamburger, all always visible — see .site-nav-actions)
   doesn't fit on one row. Dropping the wordmark and keeping just the mark
   (still a distinctive two-tone shape on its own) is the standard mobile
   pattern for this — the alternative, wrapping the header to two rows,
   would permanently cost vertical space on every page since the header is
   sticky, which is worse on exactly the small screens this is fixing for. */
/* 560px, not 480px: the logged-out login label already moves out of the
   header at 560 (see the block further down), and measuring the logged-IN
   header showed .site-nav-actions overflowing the page at 520px — the
   profile pill and logout still in the row. Same bug, same width, so both
   states now leave the header at the same point rather than one of them
   having a 80px window where it overflows. */
@media (max-width: 560px) {
  .site-header .logo-word { display: none; }
  /* Hiding the wordmark alone still isn't enough once logged in — the
     profile-name pill and logout icon push the hamburger button
     off-screen entirely on narrow phones. Their content moves into the
     mobile-nav panel instead (see .mobile-nav-profile-link below). */
  /* Qualified with .site-nav-actions (not just the bare class) so this
     beats components.css's .btn rule — same specificity, but components.css
     loads after nav.css, so the bare class alone would lose the cascade. */
  .site-nav-actions .nav-account-name, .site-nav-actions .nav-account-logout { display: none; }
  .mobile-nav-account { display: block; }
}

.site-nav-links {
  display: none;
  align-items: center;
  gap: var(--space-5);
}
.site-nav-links a { color: var(--color-body); font-size: 0.9375rem; font-weight: 500; white-space: nowrap; }
.site-nav-links a:hover, .site-nav-links a.is-active { color: var(--color-primary); text-decoration: none; }

.site-nav-actions { display: flex; align-items: center; gap: var(--space-2); }

/* "About" dropdown (How it works / Trust & fairness) — folds two nav links
   into one so the bar doesn't run out of room and wrap mid-word in longer
   languages (fr/de). */
.nav-dropdown { position: relative; }
.nav-dropdown > button {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  background: none;
  border: none;
  padding: 0;
  font-family: inherit;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--color-body);
  white-space: nowrap;
  cursor: pointer;
}
.nav-dropdown > button:hover, .nav-dropdown > button[aria-expanded="true"] { color: var(--color-primary); }
.nav-dropdown > button svg { width: 14px; height: 14px; transition: transform 180ms ease; }
/* Alpine writes the attribute as the string "true"/"false", so the open
   state is readable in CSS without a second toggled class. */
.nav-dropdown > button[aria-expanded="true"] svg { transform: rotate(180deg); }
.nav-dropdown-menu {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: var(--space-3);
  display: flex;
  flex-direction: column;
  min-width: 190px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: var(--space-2);
  z-index: 110;
}
.nav-dropdown-menu a {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm, 6px);
  color: var(--color-body);
  font-size: 0.9375rem;
  font-weight: 500;
  white-space: nowrap;
}
.nav-dropdown-menu a:hover { background: var(--color-sand); color: var(--color-primary); text-decoration: none; }

/* Language switcher — a custom dropdown (not a native <select>) so it can
   actually take the design system's surface/border/shadow tokens; native
   <select> option lists are OS-styled and can't be themed cross-browser.
   Shows short codes (EN/FR/DE/ES) rather than full language names to stay
   compact in the header. */
.lang-switcher { position: relative; margin: 0; }
.lang-switcher-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 0.4rem 0.75rem;
  font-family: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--color-body);
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.lang-switcher-toggle:hover { border-color: var(--color-primary); color: var(--color-primary); }
.lang-switcher-toggle svg { width: 14px; height: 14px; }

.lang-switcher-menu {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: var(--space-2);
  display: flex;
  flex-direction: column;
  min-width: 84px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: var(--space-2);
  z-index: 110;
}
.lang-switcher-option {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm, 6px);
  font-family: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--color-body);
  cursor: pointer;
}
.lang-switcher-option:hover { background: var(--color-sand); color: var(--color-primary); }
.lang-switcher-option.is-active { color: var(--color-primary); background: var(--color-sand); }

.nav-toggle {
  background: none;
  border: none;
  width: auto;
  padding: var(--space-2);
  cursor: pointer;
  color: var(--color-body);
}

/* Hamburger-to-X morph: each bar is a stroked path with a dash pattern
   sized to look like a straight line at rest; toggling .is-open shifts the
   dash offset/length so the two diagonal bars sweep into an X and the
   middle bar collapses to a dot-width sliver. */
.nav-toggle .line {
  fill: none;
  stroke: currentColor;
  stroke-width: 6;
  transition: stroke-dasharray 400ms cubic-bezier(0.4, 0, 0.2, 1), stroke-dashoffset 400ms cubic-bezier(0.4, 0, 0.2, 1);
}
.nav-toggle .line1 { stroke-dasharray: 60 207; }
.nav-toggle .line2 { stroke-dasharray: 60 60; }
.nav-toggle .line3 { stroke-dasharray: 60 207; }
.nav-toggle.is-open .line1 { stroke-dasharray: 90 207; stroke-dashoffset: -134; }
.nav-toggle.is-open .line2 { stroke-dasharray: 1 60; stroke-dashoffset: -30; }
.nav-toggle.is-open .line3 { stroke-dasharray: 90 207; stroke-dashoffset: -134; }

/* Mobile menu — an overlay, not part of the header's flow.
   Anchored to the sticky header (which, being positioned, is the containing
   block) with top:100%, so it drops *over* the page instead of growing the
   header and shoving every page below it down. Visibility (not display) does
   the hiding: display can't be transitioned, while visibility can be delayed
   until the fade-out finishes, and it still keeps the closed menu's links out
   of the tab order. */
.mobile-nav {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 2;
  /* Collapsed to nothing while closed, on purpose: an absolutely positioned
     element still contributes to the page's scrollable area even when
     invisible, so a full-height hidden panel would add a phantom screenful
     of scroll below the footer on every page. Both this and `visibility`
     flip only after the fade-out finishes (0s transition, 260ms delay), so
     the close still animates. */
  max-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px);
  transition:
    opacity 200ms ease,
    transform 260ms cubic-bezier(0.4, 0, 0.2, 1),
    visibility 0s linear 260ms,
    max-height 0s linear 260ms;
}
.mobile-nav.is-open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  max-height: calc(100vh - 100%);
  max-height: calc(100dvh - 100%);
  transition-delay: 0s, 0s, 0s, 0s;
}

/* Dims the page under the open menu and gives "tap outside to close" a
   target. Absolute (not fixed) and starting below the header, so it never
   tints the header itself — and since the header is sticky it stays pinned
   over the viewport anyway. */
.mobile-nav-scrim {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  height: 0; /* zero-footprint while closed — see the note on .mobile-nav */
  z-index: 1;
  background: rgba(26, 36, 32, 0.35);
  opacity: 0;
  visibility: hidden;
  transition: opacity 220ms ease, visibility 0s linear 220ms, height 0s linear 220ms;
}
.mobile-nav-scrim.is-open {
  height: 100vh;
  height: 100dvh;
  opacity: 1;
  visibility: visible;
  transition-delay: 0s, 0s, 0s;
}

/* Set by Alpine on <body> while the menu is open (see includes/nav.html) —
   stops the page scrolling behind the overlay. */
body.has-mobile-nav-open { overflow: hidden; }

/* Longhand top/bottom padding only: this element also carries .container,
   and the shorthand would wipe out .container's left/right padding — same
   trap documented on .site-header-inner above. */
.mobile-nav-inner {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: var(--space-3);
  padding-bottom: var(--space-5);
}

.mobile-nav-heading {
  margin: var(--space-2) 0 var(--space-1);
  padding: 0 var(--space-3);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-muted);
}
.mobile-nav-inner > .mobile-nav-heading:first-child { margin-top: 0; }

.mobile-nav-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  margin: 0;
  padding: var(--space-2) var(--space-3);
  border: none;
  border-radius: var(--radius-md);
  background: none;
  color: var(--color-ink);
  font-family: inherit;
  font-size: 1rem;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease;
}
.mobile-nav-item:hover, .mobile-nav-item:focus-visible, .mobile-nav-item.is-active {
  background: var(--color-sand);
  color: var(--color-primary);
  text-decoration: none;
}
/* Matched to .mobile-nav-item-icon's box so the avatar row's label lines up
   with every icon row's label. */
.mobile-nav-item .avatar { flex: none; width: 34px; height: 34px; }
.mobile-nav-item-label { flex: 1; min-width: 0; }

/* Tinted tile behind each glyph — gives the list a scannable left rail and
   an inexpensive hover accent (the tile inverts, the row doesn't). */
.mobile-nav-item-icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-sm);
  background: var(--color-sand);
  color: var(--color-primary);
  transition: background 150ms ease, color 150ms ease;
}
.mobile-nav-item-icon svg { width: 18px; height: 18px; }
.mobile-nav-item:hover .mobile-nav-item-icon, .mobile-nav-item:focus-visible .mobile-nav-item-icon {
  background: var(--color-primary);
  color: #fff;
}

.mobile-nav-item-chevron {
  flex: none;
  display: block;
  color: var(--color-muted);
  transition: transform 150ms ease;
}
.mobile-nav-item-chevron svg { display: block; width: 16px; height: 16px; }
.mobile-nav-item:hover .mobile-nav-item-chevron { transform: translateX(3px); }

.mobile-nav-account {
  border-top: 1px solid var(--color-border);
  margin-top: var(--space-2);
  padding-top: var(--space-2);
}
.mobile-nav-account .mobile-nav-item + form { margin-top: 2px; }
.mobile-nav-logout-btn:hover, .mobile-nav-logout-btn:focus-visible { color: var(--color-danger); background: var(--color-danger-bg); }
.mobile-nav-logout-btn:hover .mobile-nav-item-icon, .mobile-nav-logout-btn:focus-visible .mobile-nav-item-icon {
  background: var(--color-danger);
  color: #fff;
}

/* Rows rise in behind the panel's own drop, staggered — enough to read as
   one deliberate motion rather than a block appearing at once. `backwards`
   holds the pre-animation state during the delay so nothing flashes at its
   final position first. */
@keyframes mobile-nav-item-in {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}
.mobile-nav.is-open .mobile-nav-inner > * {
  animation: mobile-nav-item-in 280ms cubic-bezier(0.2, 0.7, 0.3, 1) backwards;
}
.mobile-nav.is-open .mobile-nav-inner > :nth-child(1) { animation-delay: 60ms; }
.mobile-nav.is-open .mobile-nav-inner > :nth-child(2) { animation-delay: 90ms; }
.mobile-nav.is-open .mobile-nav-inner > :nth-child(3) { animation-delay: 120ms; }
.mobile-nav.is-open .mobile-nav-inner > :nth-child(4) { animation-delay: 150ms; }
.mobile-nav.is-open .mobile-nav-inner > :nth-child(5) { animation-delay: 180ms; }
.mobile-nav.is-open .mobile-nav-inner > :nth-child(6) { animation-delay: 210ms; }
.mobile-nav.is-open .mobile-nav-inner > :nth-child(n + 7) { animation-delay: 240ms; }

@media (prefers-reduced-motion: reduce) {
  /* Zero the close-delays too: with the fade gone there is nothing left to
     wait for before collapsing the panel back to its zero footprint. */
  .mobile-nav, .mobile-nav-scrim { transition-duration: 1ms; transition-delay: 0s; }
  .mobile-nav { transform: none; }
  .mobile-nav.is-open .mobile-nav-inner > * { animation: none; }
  .nav-toggle .line { transition-duration: 1ms; }
}

@media (min-width: 900px) {
  .site-nav-links { display: flex; }
  .nav-toggle { display: none; }
  .mobile-nav, .mobile-nav-scrim { display: none !important; }
}

/* Logged-out header actions on narrow screens ---------------------------- */
/* The label is hidden by default here and revealed above the breakpoint —
   the same source-order discipline as .mobile-nav-account above: an
   unconditional rule later in the file would beat the media query
   regardless of whether it matches. */

/* Measured in German at a 500px viewport, the widest of the six locales:
   logo 156 (120 of it wordmark) + lang 63 + "Anmelden" 118 + "Registrieren"
   107 + hamburger 38 = 544px of content. At 360px there is ~312px to put
   it in, so something has to give even after the wordmark goes at 480px.
   Dropping the login label recovers ~80px of that, and the action keeps a
   visible icon rather than disappearing behind the hamburger.

   560px, not 480px: French and German still overflowed at 520px, and this
   is where the last of them fits. English and Turkish fit sooner but share
   the breakpoint — one behaviour is easier to reason about than a
   per-language rule nobody will remember to update. */
@media (max-width: 560px) {
  .site-nav-actions .nav-login-label { display: none; }
  /* btn-icon-text sets a gap for the label that is now absent. */
  .site-nav-actions .nav-login { gap: 0; padding-left: 0.5rem; padding-right: 0.5rem; position: relative; }
  /* Once it's icon-only it's a ~34px target, under the 44px floor the
     other icon buttons got. Same technique as .btn-icon: pan the hit area
     out with a pseudo-element rather than growing the visible box, which
     would put the header back over budget on exactly the screens this
     media query exists for. */
  .site-nav-actions .nav-login::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }
}

/* The logged-out drawer block appears at 560px, not the 480px used for the
   logged-in one, because it exists to compensate for the login label going
   away — and that happens at 560px. Tying it to 480px would leave an 80px
   band showing a bare icon with nothing in the drawer explaining it. */
@media (max-width: 560px) {
  .mobile-nav-auth { display: block; }
}
