/* ============================================================
   ERGÖK — CHROME LAYER
   topbar · header · navigation · footer · cookie banner · credit strip

   Loads after styles.css, app.css, theme.css, motion.css (see
   app/Views/layouts/main.php). Every rule here matches the original
   selector's specificity and wins on source order — no `!important`.

   Scroll state comes from the motion runtime (js/motion.js):
     html[data-scrolled="true"] · html[data-scroll-dir] · --scroll-progress
   Nothing in this file installs a scroll listener of its own, and every
   rest state is fully designed so the chrome is correct even if the
   runtime never reports anything.
   ============================================================ */

/* ------------------------------------------------------------
   1. CHROME METRICS
   `--header-h` is a legacy styles.css variable consumed by
   `scroll-padding-top` and `[id] { scroll-margin-top }`; it is
   re-declared (not redefined-as-new) so anchor offsets follow the
   compact header. The light selector has to be matched or the
   `html[data-theme="light"]` block in styles.css outranks `:root`.
   ------------------------------------------------------------ */
:root,
html[data-theme="light"] {
  --header-h: 118px;
  --header-h-scrolled: 88px;
  --topbar-h: 38px;
  --logo-h: 92px;
  --logo-h-scrolled: 66px;
  --control-h: 2.4rem;
  /* Total height the fixed chrome reserves in the document. Constant by
     design: the spacer must never animate, or the page reflows mid-scroll. */
  --chrome-h: calc(var(--topbar-h) + var(--header-h));
}

/* ------------------------------------------------------------
   1b. CHROME SHELL — the anti-jitter contract
   Topbar + header live inside one `position: fixed` shell and a
   static-height spacer holds their place in the flow. Nothing the
   chrome does on scroll (topbar collapse, header shrink) can reflow
   the document any more, which is what made the header shudder.
   The shell must stay free of transform / filter / backdrop-filter:
   either would make it a containing block for the `position: fixed`
   mobile nav overlay.
   ------------------------------------------------------------ */
.chrome-shell {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 40;
}

.chrome-spacer {
  height: var(--chrome-h);
  flex: none;
  pointer-events: none;
}

/* Shared stroke icon — 24px grid, currentColor, 1.6 weight.
   Matches the sun glyph in the theme toggle. */
.chrome-icon {
  width: 20px;
  height: 20px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ------------------------------------------------------------
   2. TOPBAR — collapses away on scroll
   The 1fr → 0fr grid row animates without touching the children's
   own box, so nothing reflows inside while it closes.
   ------------------------------------------------------------ */
.topbar {
  display: grid;
  grid-template-rows: 1fr;
  flex: none;
  background: linear-gradient(90deg, var(--steel-950), var(--steel-900) 50%, var(--steel-950));
  font-size: var(--fs-xs);
  letter-spacing: 0.04em;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  transition: grid-template-rows var(--dur-3) var(--ease-in-out);
}

.topbar-rail {
  min-height: 0;
  overflow: hidden;
}

.topbar-inner {
  min-height: var(--topbar-h);
  gap: 0.75rem 1.5rem;
}

html[data-scrolled="true"] .topbar {
  grid-template-rows: 0fr;
}

.topbar-left,
.topbar-right {
  gap: 0.85rem 1.15rem;
}

.topbar-item {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  line-height: 1;
}

.topbar-item .chrome-icon {
  width: 14px;
  height: 14px;
  stroke-width: 1.7;
  color: var(--brand-500);
  opacity: 0.85;
  transition: opacity var(--dur-2) var(--ease-out);
}

.topbar a.topbar-item:hover .chrome-icon,
.topbar a.topbar-item:focus-visible .chrome-icon {
  opacity: 1;
}

.topbar-sep {
  height: 11px;
  background: rgba(255, 255, 255, 0.16);
}

/* ------------------------------------------------------------
   3. HEADER SHELL
   The frosted pane lives on `::before`, not on `.site-header`:
   `backdrop-filter` on the header itself would make it a containing
   block for the `position: fixed` mobile nav overlay, which then
   could not fill the viewport.
   ------------------------------------------------------------ */
.site-header {
  position: relative;
  z-index: 40;
  flex: none;
  background: transparent;
  border-bottom: 0;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  transition: box-shadow var(--dur-3) var(--ease-out);
}

.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--surface-glass);
  backdrop-filter: blur(16px) saturate(150%);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  border-bottom: 1px solid var(--line-soft);
  transition:
    background var(--dur-3) var(--ease-out),
    border-color var(--dur-3) var(--ease-out);
}

@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .site-header::before {
    background: var(--surface-raised);
  }
}

html[data-scrolled="true"] .site-header::before {
  background: var(--surface-glass-strong);
  backdrop-filter: blur(24px) saturate(168%);
  -webkit-backdrop-filter: blur(24px) saturate(168%);
  border-bottom-color: var(--line-strong);
}

html[data-scrolled="true"] .site-header {
  box-shadow: 0 8px 24px rgba(7, 11, 15, 0.09);
}

html[data-theme="dark"][data-scrolled="true"] .site-header {
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.55);
}

.header-inner {
  position: relative;
  z-index: 2;
  min-height: var(--header-h);
  gap: clamp(0.75rem, 2vw, 2rem);
  transition: min-height var(--dur-3) var(--ease-out);
}

html[data-scrolled="true"] .header-inner {
  min-height: var(--header-h-scrolled);
}

/* Scroll-progress hairline along the bottom edge. Driven entirely by
   the runtime's `--scroll-progress`; with no runtime it reads 0 and
   the track stays hidden. */
.header-progress {
  position: absolute;
  z-index: 1;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-3) var(--ease-out);
}

html[data-scrolled="true"] .header-progress {
  opacity: 1;
}

.header-progress-bar {
  display: block;
  height: 100%;
  background: var(--grad-brand);
  box-shadow: 0 0 10px var(--edge-glow);
  transform: scaleX(var(--scroll-progress, 0));
  transform-origin: left center;
  will-change: transform;
}

/* ------------------------------------------------------------
   4. BRAND
   The dark-mode `filter: invert()` hack in styles.css is replaced by
   serving the artwork that was drawn for each ground.
   ------------------------------------------------------------ */
.brand {
  position: relative;
  z-index: 3;
  gap: 0;
}

/* Both wordmarks are 470x368; pinning the ratio keeps the light/dark swap
   from shifting the nav by a sub-pixel. */
.brand-logo {
  height: var(--logo-h);
  width: auto;
  aspect-ratio: 470 / 368;
  max-width: none;
  transition:
    height var(--dur-3) var(--ease-out),
    opacity var(--dur-2) var(--ease-out);
}

html[data-theme="dark"] .brand-logo {
  filter: none;
}

html[data-scrolled="true"] .brand-logo {
  height: var(--logo-h-scrolled);
}

.brand-logo--dark {
  display: none;
}

html[data-theme="dark"] .brand-logo--light {
  display: none;
}

html[data-theme="dark"] .brand-logo--dark {
  display: block;
}

.brand:hover .brand-logo,
.brand:focus-visible .brand-logo {
  opacity: 0.78;
}

/* ------------------------------------------------------------
   5. NAVIGATION — desktop
   `.nav-panel` is layout-transparent on desktop so the list, the CTA
   and the mobile-only meta block stay direct flex children of `.nav`.
   ------------------------------------------------------------ */
.nav {
  position: relative;
  z-index: 1;
}

.nav-panel {
  display: contents;
}

.nav-list {
  display: flex;
  align-items: center;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav-item {
  display: block;
}

.nav-meta {
  display: none;
}

.nav .nav-link {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  height: var(--control-h);
  padding: 0 0.9rem;
  color: var(--muted);
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.075em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: color var(--dur-2) var(--ease-out);
}

/* Hover plate — the one place a chamfer appears in the header. */
.nav .nav-link::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  background: var(--surface-sunken);
  clip-path: polygon(7px 0, 100% 0, 100% calc(100% - 7px), calc(100% - 7px) 100%, 0 100%, 0 7px);
  opacity: 0;
  transform: scale(0.88);
  transition:
    opacity var(--dur-2) var(--ease-out),
    transform var(--dur-2) var(--ease-spring),
    background var(--dur-2) var(--ease-out);
}

/* Indicator — grows out of the centre, so hover and the current-page
   state read as the same object settling into place. */
.nav .nav-link::after {
  content: "";
  position: absolute;
  left: 0.9rem;
  right: 0.9rem;
  bottom: 0.32rem;
  height: 2px;
  background: var(--grad-brand);
  transform: scaleX(0);
  transform-origin: center;
  transition:
    transform var(--dur-3) var(--ease-emphasis),
    box-shadow var(--dur-3) var(--ease-out);
}

.nav .nav-link:hover,
.nav .nav-link:focus-visible {
  color: var(--text);
}

.nav .nav-link:hover::before,
.nav .nav-link:focus-visible::before {
  opacity: 1;
  transform: scale(1);
}

.nav .nav-link:hover::after,
.nav .nav-link:focus-visible::after {
  transform: scaleX(1);
}

.nav .nav-link.is-active {
  color: var(--text);
}

.nav .nav-link.is-active::before {
  opacity: 1;
  transform: scale(1);
  background: var(--accent-soft);
}

.nav .nav-link.is-active::after {
  transform: scaleX(1);
  box-shadow: 0 0 10px var(--edge-glow);
}

/* The motion runtime's entrance is only wanted inside the mobile
   overlay; on desktop the bar must be solid from first paint. */
@media (min-width: 981px) {
  .nav .nav-list > .nav-item[data-anim] {
    opacity: 1;
    transform: none;
    animation: none;
    clip-path: none;
    filter: none;
  }
}

/* ------------------------------------------------------------
   6. HEADER CONTROLS
   Square, 0-radius precision controls — chamfers stay reserved for
   larger surfaces, and clipping a control would clip its focus ring.
   ------------------------------------------------------------ */
.header-actions {
  position: relative;
  z-index: 3;
  gap: 0.5rem;
}

/* Segmented TR / EN control with a sliding thumb. */
.lang-switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  height: var(--control-h);
  padding: 3px;
  border: 1px solid var(--line-strong);
  background: var(--surface-sunken);
}

.lang-thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 2.3rem;
  height: calc(100% - 6px);
  background: linear-gradient(120deg, var(--brand-400), var(--brand-500));
  box-shadow: var(--shadow-xs);
  transition: transform var(--dur-3) var(--ease-emphasis);
}

.lang-switch--en .lang-thumb {
  transform: translateX(2.3rem);
}

.lang-seg {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.3rem;
  height: 100%;
  padding: 0;
  color: var(--muted);
  font-family: var(--font-display);
  font-size: 0.84rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  transition: color var(--dur-2) var(--ease-out);
}

.lang-seg.is-current {
  color: var(--steel-900);
}

html[data-theme="dark"] .lang-seg.is-current {
  color: var(--steel-900);
}

.lang-switch .lang-link:hover,
.lang-switch .lang-link:focus-visible {
  color: var(--text);
}

/* Theme toggle — both glyphs stay in the DOM and cross-rotate. */
.theme-toggle {
  position: relative;
  width: var(--control-h);
  height: var(--control-h);
  border: 1px solid var(--line-strong);
  background: var(--surface-sunken);
  color: var(--text);
  transition:
    color var(--dur-2) var(--ease-out),
    border-color var(--dur-2) var(--ease-out),
    background var(--dur-2) var(--ease-out);
}

.theme-toggle:hover,
.theme-toggle:focus-visible {
  border-color: var(--brand-500);
  color: var(--accent-ink);
  background: var(--accent-soft);
}

.theme-toggle .icon-moon,
.theme-toggle .icon-sun,
html[data-theme="dark"] .theme-toggle .icon-moon,
html[data-theme="dark"] .theme-toggle .icon-sun {
  display: block;
}

.theme-toggle svg,
.theme-toggle .icon-moon,
.theme-toggle .icon-sun {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 18px;
  height: 18px;
  margin: -9px 0 0 -9px;
  transition:
    opacity var(--dur-3) var(--ease-out),
    transform var(--dur-3) var(--ease-emphasis);
}

.theme-toggle .icon-moon {
  fill: currentColor;
  stroke: none;
  opacity: 1;
  transform: rotate(0deg) scale(1);
}

.theme-toggle .icon-sun {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0;
  transform: rotate(-90deg) scale(0.4);
}

html[data-theme="dark"] .theme-toggle .icon-moon {
  opacity: 0;
  transform: rotate(90deg) scale(0.4);
}

html[data-theme="dark"] .theme-toggle .icon-sun {
  opacity: 1;
  transform: rotate(0deg) scale(1);
}

/* The single primary CTA. Its mobile twin lives inside the nav panel
   (`.nav-quote`), which app.css swaps in below 981px. */
.header-actions .header-cta {
  height: var(--control-h);
  padding: 0 1.1rem;
  font-size: 0.82rem;
  letter-spacing: 0.1em;
}

.nav-toggle {
  width: var(--control-h);
  height: var(--control-h);
  padding: 0;
  align-items: center;
  gap: 5px;
  border: 1px solid var(--line-strong);
  background: var(--surface-sunken);
  transition:
    border-color var(--dur-2) var(--ease-out),
    background var(--dur-2) var(--ease-out);
}

.nav-toggle:hover,
.nav-toggle:focus-visible {
  border-color: var(--brand-500);
  background: var(--accent-soft);
}

.nav-toggle span {
  width: 20px;
  height: 2px;
  background: var(--text);
  transition:
    transform var(--dur-3) var(--ease-emphasis),
    opacity var(--dur-1) var(--ease-out);
}

/* Re-tuned to the 2px bar / 5px gap rhythm set above. */
.nav-toggle[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* ------------------------------------------------------------
   7. NAVIGATION — mobile overlay (≤ 980px, the breakpoint site.js
   mirrors with its `min-width: 981px` reset)
   ------------------------------------------------------------ */
@media (max-width: 980px) {
  :root,
  html[data-theme="light"] {
    --header-h: 92px;
    --header-h-scrolled: 76px;
    --logo-h: 68px;
    --logo-h-scrolled: 54px;
    /* The topbar is hidden below 980px, so the shell is header-only. */
    --chrome-h: var(--header-h);
  }

  .topbar {
    display: none;
  }

  /* Background lock while the panel is open. `hidden`/`is-open` is
     still driven entirely by site.js; this only reacts to it. */
  html:has(#primary-nav.is-open),
  html:has(#primary-nav.is-open) body {
    overflow: hidden;
  }

  .nav {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: calc(var(--header-h) + 1.25rem) 0 2.5rem;
    background: var(--surface-glass-strong);
    backdrop-filter: blur(28px) saturate(160%);
    -webkit-backdrop-filter: blur(28px) saturate(160%);
    border-bottom: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
    transition:
      opacity var(--dur-3) var(--ease-out),
      visibility 0s linear var(--dur-3);
  }

  @supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
    .nav {
      background: var(--surface-raised);
    }
  }

  .nav.is-open {
    display: flex;
    visibility: visible;
    opacity: 1;
    pointer-events: auto;
    transition:
      opacity var(--dur-3) var(--ease-out),
      visibility 0s linear 0s;
  }

  .nav-panel {
    display: flex;
    flex-direction: column;
    width: min(var(--container), calc(100% - 3rem));
    margin-inline: auto;
  }

  .nav-list {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }

  .nav .nav-link {
    height: auto;
    padding: 1.05rem 0.2rem;
    font-size: 1.5rem;
    letter-spacing: 0.02em;
    color: var(--text);
    border-bottom: 1px solid var(--line-soft);
  }

  .nav .nav-link::before {
    display: none;
  }

  /* styles.css hides `.nav a::after` at this width; the indicator has to
     be switched back on explicitly, not just repositioned. */
  .nav .nav-link::after {
    display: block;
    left: 0.2rem;
    right: auto;
    bottom: -1px;
    width: 2.75rem;
    transform-origin: left;
  }

  .nav .nav-link.is-active {
    color: var(--accent-ink);
  }

  /* Staggered entrance. The `data-anim` / `data-anim-group` hooks are
     on the markup for the runtime, but the visible state is pinned
     here too: a panel that is `visibility: hidden` may never trip an
     IntersectionObserver, and links must never stay invisible. */
  .nav .nav-list > .nav-item[data-anim] {
    opacity: 0;
    transform: translateY(14px);
    transition:
      opacity var(--dur-3) var(--ease-out),
      transform var(--dur-3) var(--ease-out);
  }

  .nav.is-open .nav-list > .nav-item[data-anim] {
    opacity: 1;
    transform: none;
    transition-delay: calc(60ms + var(--i, 0) * var(--stagger));
  }

  .nav .nav-quote,
  .nav .nav-meta {
    opacity: 0;
    transform: translateY(14px);
    transition:
      opacity var(--dur-3) var(--ease-out),
      transform var(--dur-3) var(--ease-out);
  }

  .nav.is-open .nav-quote {
    opacity: 1;
    transform: none;
    transition-delay: 470ms;
  }

  .nav.is-open .nav-meta {
    opacity: 1;
    transform: none;
    transition-delay: 530ms;
  }

  .nav a.nav-quote {
    display: inline-flex;
    justify-content: center;
    height: auto;
    margin: 1.75rem 0 0;
    padding: 1.05rem 1.5rem;
    border-bottom: 0;
    color: var(--steel-900);
    font-size: 0.95rem;
    letter-spacing: var(--track-wide);
  }

  html[data-theme="dark"] .nav a.nav-quote {
    color: var(--steel-900);
  }

  /* `.nav a::after` in styles.css outranks `.btn-arrow::after`, so the
     arrow has to be restored (and un-positioned) at that specificity. */
  .nav a.nav-quote::after {
    content: "→";
    position: static;
    display: inline-block;
    width: auto;
    height: auto;
    margin-left: 0.1rem;
    background: none;
    box-shadow: none;
    transform: none;
    transition: transform var(--dur-3) var(--ease-spring);
  }

  .nav a.nav-quote:hover::after,
  .nav a.nav-quote:focus-visible::after {
    transform: translateX(5px);
  }

  /* app.css repaints this button on hover; hand it back to theme.css. */
  .nav a.nav-quote:hover,
  .nav a.nav-quote:focus-visible {
    color: var(--steel-900);
    background: var(--grad-brand-deep);
    border-color: transparent;
  }

  html[data-theme="dark"] .nav a.nav-quote:hover,
  html[data-theme="dark"] .nav a.nav-quote:focus-visible {
    color: var(--steel-900);
  }

  /* The topbar is gone at this width, so the panel carries the
     contact details instead of dropping them. */
  .nav .nav-meta {
    display: grid;
    gap: 0.1rem;
    margin-top: 2rem;
    padding-top: 1.35rem;
    border-top: 1px solid var(--line-soft);
  }

  .nav .nav-meta-item {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    min-height: 44px;
    padding: 0.35rem 0.2rem;
    border-bottom: 0;
    color: var(--muted);
    font-family: var(--font-body);
    font-size: var(--fs-sm);
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    transition: color var(--dur-2) var(--ease-out);
  }

  .nav a.nav-meta-item:hover,
  .nav a.nav-meta-item:focus-visible {
    color: var(--text);
  }

  .nav .nav-meta-item .chrome-icon {
    width: 18px;
    height: 18px;
    color: var(--accent-ink);
  }
}

@media (max-width: 640px) {
  :root,
  html[data-theme="light"] {
    --header-h: 80px;
    --header-h-scrolled: 68px;
    --logo-h: 58px;
    --logo-h-scrolled: 48px;
    --control-h: 2.3rem;
  }

  .nav-panel {
    width: min(var(--container), calc(100% - 2rem));
  }

  .nav .nav-link {
    font-size: 1.3rem;
  }
}

/* ------------------------------------------------------------
   8. FOOTER
   Always an inverted surface, in both themes — so the neutral
   tokens are re-pointed locally for this subtree rather than read
   from the page palette (where the light theme's hairlines would be
   invisible on a dark ground).
   ------------------------------------------------------------ */
.site-footer {
  --text: #f2f6f9;
  --muted: #a3b3c0;
  --line-soft: rgba(255, 255, 255, 0.09);
  --line-strong: rgba(255, 255, 255, 0.18);
  --accent-ink: var(--brand-500);
  --bg: #0b1220;
  --grain-opacity: 0.055;

  position: relative;
  isolation: isolate;
  overflow: hidden;
  margin-top: auto;
  padding: clamp(3.25rem, 6vw, 5rem) 0 0;
  background: var(--grad-steel);
  color: var(--muted);
}

.site-footer::before {
  z-index: 0;
}

.site-footer::after {
  z-index: 3;
}

.site-footer > .container,
.footer-edge {
  position: relative;
  z-index: 2;
}

.footer-edge {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--grad-hairline);
}

.footer-grid {
  grid-template-columns:
    minmax(0, 1.35fr)
    minmax(0, 0.8fr)
    minmax(0, 0.8fr)
    minmax(0, 1.05fr);
  gap: clamp(2rem, 4vw, 3rem) clamp(1.75rem, 3vw, 2.75rem);
  padding-bottom: clamp(2rem, 4vw, 3rem);
  border-bottom: 1px solid var(--line-soft);
}

.footer-brand-col {
  max-width: none;
}

.footer-col-title,
.footer-news-title {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0 0 1rem;
  color: var(--text);
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 800;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
  opacity: 1;
}

.footer-col-title::before,
.footer-news-title::before {
  content: "";
  flex: none;
  width: 1.15rem;
  height: 2px;
  background: var(--grad-brand);
}

/* --- brand column --- */
.footer-brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1rem;
  margin-bottom: 1.85rem;
}

.footer-brand img {
  width: auto;
  height: 88px;
  max-width: none;
  object-fit: contain;
}

.footer-brand span {
  display: block;
  max-width: 36ch;
  color: var(--muted);
  font-size: var(--fs-sm);
  line-height: 1.65;
}

.footer-contact {
  display: grid;
  gap: 0.1rem;
  font-size: var(--fs-sm);
}

.footer-contact .footer-contact-row {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  min-height: 44px;
  padding: 0.6rem 0.4rem 0.6rem 0;
  color: var(--muted);
  line-height: 1.5;
  transition:
    color var(--dur-2) var(--ease-out),
    transform var(--dur-2) var(--ease-out);
}

.footer-contact a.footer-contact-row:hover,
.footer-contact a.footer-contact-row:focus-visible {
  color: var(--text);
  transform: translateX(3px);
}

.footer-contact .footer-contact-row .chrome-icon {
  margin-top: 0.12rem;
  color: var(--brand-500);
  opacity: 0.8;
  transition: opacity var(--dur-2) var(--ease-out);
}

.footer-contact a.footer-contact-row:hover .chrome-icon,
.footer-contact a.footer-contact-row:focus-visible .chrome-icon {
  opacity: 1;
}

.footer-social {
  gap: 0.5rem;
  margin-top: 1.6rem;
}

.footer-social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--line-soft);
  background: rgba(255, 255, 255, 0.03);
  color: var(--muted);
  transition:
    color var(--dur-2) var(--ease-out),
    border-color var(--dur-2) var(--ease-out),
    background var(--dur-2) var(--ease-out),
    transform var(--dur-2) var(--ease-out);
}

.footer-social a:hover,
.footer-social a:focus-visible {
  color: var(--brand-500);
  border-color: var(--brand-500);
  background: rgba(255, 255, 255, 0.07);
  transform: translateY(-2px);
}

/* --- link columns --- */
.footer-links,
.footer-legal {
  gap: 0.1rem;
}

.footer-links a,
.footer-legal a {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.34rem 0;
  color: var(--muted);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  opacity: 1;
  transition: color var(--dur-2) var(--ease-out);
}

.footer-links a::before,
.footer-legal a::before {
  content: "";
  flex: none;
  width: 0.85rem;
  height: 1px;
  background: currentColor;
  opacity: 0.3;
  transform: scaleX(0.35);
  transform-origin: left center;
  transition:
    transform var(--dur-2) var(--ease-out),
    opacity var(--dur-2) var(--ease-out);
}

.footer-links a:hover,
.footer-links a:focus-visible,
.footer-legal a:hover,
.footer-legal a:focus-visible {
  color: var(--text);
  opacity: 1;
}

.footer-links a:hover::before,
.footer-links a:focus-visible::before,
.footer-legal a:hover::before,
.footer-legal a:focus-visible::before {
  transform: scaleX(1);
  opacity: 1;
}

/* --- newsletter --- */
.footer-news-col {
  align-self: start;
}

.footer-newsletter {
  position: relative;
  margin-top: 0;
  padding: 1.5rem 1.4rem 1.6rem;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--line-soft);
}

.footer-newsletter::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  background: var(--grad-brand);
}

.footer-news-title {
  margin-bottom: 0.5rem;
}

.footer-news-sub {
  margin: 0 0 1.15rem;
  color: var(--muted);
  font-size: var(--fs-sm);
  line-height: 1.6;
}

.footer-news-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  max-width: none;
}

.footer-news-row input {
  flex: 1 1 9rem;
  min-width: 0;
  height: 2.85rem;
  padding: 0 0.85rem;
  border: 1px solid var(--line-strong);
  background: rgba(0, 0, 0, 0.3);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  transition:
    border-color var(--dur-2) var(--ease-out),
    box-shadow var(--dur-2) var(--ease-out);
}

.footer-news-row input::placeholder {
  color: rgba(255, 255, 255, 0.44);
}

.footer-news-row input:focus {
  outline: none;
  border-color: var(--brand-500);
  box-shadow: 0 0 0 3px var(--edge-glow);
}

.footer-news-row .btn {
  flex: none;
  height: 2.85rem;
  padding-block: 0;
}

/* --- note row --- */
.footer-note {
  gap: 0.35rem 1.5rem;
  padding: 1.3rem 0 1.45rem;
  color: var(--muted);
  font-size: var(--fs-xs);
  letter-spacing: 0.03em;
}

.footer-note p:last-child {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
}

.footer-note p:last-child::before {
  content: "";
  width: 1.4rem;
  height: 1px;
  background: var(--brand-500);
  opacity: 0.7;
}

@media (max-width: 1180px) {
  .footer-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  .footer-brand-col,
  .footer-news-col {
    grid-column: 1 / -1;
  }

  .footer-newsletter {
    max-width: 32rem;
  }
}

@media (max-width: 640px) {
  .footer-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 2.25rem;
  }

  .footer-brand img {
    height: 72px;
  }

  .footer-note {
    justify-content: flex-start;
  }
}

/* ------------------------------------------------------------
   9. BEEUP CREDIT STRIP
   A deliberate plinth under the footer: hairline, then one quiet
   sentence. Id-scoped to match the specificity used in styles.css.
   ------------------------------------------------------------ */
#beeuptech {
  flex-direction: column;
  align-items: center;
  gap: 0;
  padding: 0 1.5rem 1.4rem;
  background: var(--steel-950);
  color: var(--steel-400);
  font-size: var(--fs-micro);
  letter-spacing: 0.05em;
}

#beeuptech .beeup-rule {
  display: block;
  width: min(var(--container), calc(100% - 1.5rem));
  height: 1px;
  margin-bottom: 1.15rem;
  background: var(--grad-hairline);
  opacity: 0.45;
}

#beeuptech .beeup-credit {
  margin: 0;
  line-height: 2;
  text-align: center;
}

#beeuptech .beeup-logo-link {
  display: inline-flex;
  vertical-align: middle;
  margin: 0 0.2rem;
  opacity: 0.5;
  filter: grayscale(1);
  transition:
    opacity var(--dur-2) var(--ease-out),
    filter var(--dur-2) var(--ease-out);
}

#beeuptech .beeup-logo-link:hover,
#beeuptech .beeup-logo-link:focus-visible {
  opacity: 1;
  filter: none;
}

#beeuptech .beeup-logo-img {
  width: 72px;
}

#beeuptech .beeup-text-link {
  color: var(--steel-400);
  border-bottom: 1px solid rgba(243, 146, 35, 0);
  transition:
    color var(--dur-2) var(--ease-out),
    border-color var(--dur-2) var(--ease-out);
}

#beeuptech .beeup-text-link:hover,
#beeuptech .beeup-text-link:focus-visible {
  color: #f39223;
  border-bottom-color: rgba(243, 146, 35, 0.65);
  text-decoration: none;
}

/* ------------------------------------------------------------
   10. COOKIE BANNER
   Frosted, chamfered panel that rises into place. Every hook
   site.js drives — `#cookie-banner`, `#cookie-manage`, the
   `data-cookie` buttons, the checkbox ids and the `hidden`
   attribute — is untouched.
   ------------------------------------------------------------ */
.cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1000;
  padding: 0 0 clamp(0.75rem, 2vw, 1.5rem);
  background: transparent;
  border-top: 0;
  box-shadow: none;
  color: var(--text);
  pointer-events: none;
  animation: cookie-rise var(--dur-4) var(--ease-out) both;
}

@keyframes cookie-rise {
  from {
    opacity: 0;
    transform: translateY(22px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.cookie-panel {
  position: relative;
  width: min(var(--container), calc(100% - 3rem));
  margin-inline: auto;
  padding: 1.35rem 1.6rem 1.45rem;
  pointer-events: auto;
  background: var(--surface-glass-strong);
  backdrop-filter: blur(24px) saturate(165%);
  -webkit-backdrop-filter: blur(24px) saturate(165%);
  border: 1px solid var(--line-strong);
  clip-path: polygon(
    var(--chamfer-sm) 0,
    100% 0,
    100% calc(100% - var(--chamfer-sm)),
    calc(100% - var(--chamfer-sm)) 100%,
    0 100%,
    0 var(--chamfer-sm)
  );
}

@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .cookie-panel {
    background: var(--surface-raised);
  }
}

.cookie-panel::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: var(--grad-brand);
}

.cookie-banner-inner,
.cookie-manage {
  width: auto;
  margin-inline: 0;
}

.cookie-banner-inner {
  gap: 1rem 2rem;
}

.cookie-copy {
  flex: 1 1 26rem;
  min-width: 0;
}

.cookie-banner-inner strong {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.4rem;
  color: var(--text);
  font-family: var(--font-display);
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
}

.cookie-banner-inner strong::before {
  content: "";
  flex: none;
  width: 1.15rem;
  height: 2px;
  background: var(--grad-brand);
}

.cookie-banner-inner p {
  max-width: 62ch;
  color: var(--muted);
  font-size: var(--fs-sm);
  line-height: 1.65;
}

.cookie-banner-inner p a {
  color: var(--accent-ink);
  font-weight: 600;
  border-bottom: 1px solid var(--line-strong);
  transition: border-color var(--dur-2) var(--ease-out);
}

.cookie-banner-inner p a:hover,
.cookie-banner-inner p a:focus-visible {
  border-bottom-color: currentColor;
}

/* app.css styles these for a dark bar; the panel is now themed. */
.cookie-banner .btn-outline {
  color: var(--accent-ink);
  border-color: var(--line-strong);
}

.cookie-banner .btn-outline:hover,
.cookie-banner .btn-outline:focus-visible {
  color: var(--steel-900);
  background: transparent;
  border-color: transparent;
}

html[data-theme="dark"] .cookie-banner .btn-outline:hover,
html[data-theme="dark"] .cookie-banner .btn-outline:focus-visible {
  color: var(--steel-900);
}

.cookie-manage {
  gap: 0.75rem 1.75rem;
  margin-top: 1.15rem;
  padding-top: 1.15rem;
  border-top: 1px solid var(--line-soft);
}

.cookie-manage label {
  min-height: 44px;
  gap: 0.6rem;
  color: var(--text);
  font-size: var(--fs-sm);
}

.cookie-manage input {
  width: 18px;
  height: 18px;
  accent-color: var(--brand-500);
}

@media (max-width: 640px) {
  .cookie-panel {
    width: min(var(--container), calc(100% - 1.5rem));
    padding: 1.15rem 1.2rem 1.25rem;
  }

  .cookie-actions {
    width: 100%;
  }
}

/* ------------------------------------------------------------
   11. REDUCED MOTION
   styles.css/app.css already neutralise durations globally; this
   guarantees nothing in the chrome can be left mid-transition or
   invisible when motion is off.
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .nav .nav-list > .nav-item[data-anim],
  .nav .nav-quote,
  .nav .nav-meta {
    opacity: 1;
    transform: none;
    transition-delay: 0s;
  }

  .header-progress-bar,
  .lang-thumb,
  .theme-toggle .icon-moon,
  .theme-toggle .icon-sun,
  .nav-toggle span {
    transition: none;
  }

  .cookie-banner {
    animation: none;
  }
}
