/* Hingst global nav — full-width Apple-glass bar with the brand lockup.
 *
 * Motion grammar ported from the apple-navbar-demo study (see apple-nav.js):
 * measured-height expand at 280ms on cubic-bezier(.4,0,.6,1), 200ms + 20ms/index
 * first-open stagger, 40ms + 15ms/index switch replay, 140ms close delay then a
 * 320ms settle with reverse-order fade.
 *
 * Bar surface, height, brand lockup and shadow are taken from the report's
 * reference header (johor-data-centre-report/index-i18n.html): 14px 24px
 * padding, 58px mark / 22px Roboto 700 wordmark, and the navy shadow pair.
 * Heights step down at the same breakpoints the reference uses.
 *
 * Layout is full-bleed: bar and flyout span the viewport edge to edge, only the
 * inner content is capped at --gn-maxw so a 3-column grid does not stretch into
 * whitespace on wide displays.
 *
 * Colour/type come from the hingst report tokens (day3.css) and site.css.
 */

:root {
  /* Bar height is content-driven: padding + mark. Steps at the reference
     breakpoints (1180 / 900 / 640). */
  --gn-bar-h: 86px;          /* 14px x 2 + 58px mark */
  --gn-mark: 58px;
  --gn-wm: 22px;
  --gn-pad-y: 14px;
  --gn-pad-x: 24px;

  --gn-maxw: 1400px;

  /* Surface: reference header.top */
  --gn-bg: rgba(255, 255, 255, 0.88);
  --gn-blur: saturate(1.6) blur(14px);
  --gn-line: var(--line, #dfe4ec);
  --gn-shadow:
    0 12px 32px -12px rgba(3, 64, 120, 0.28),
    0 2px 8px rgba(3, 64, 120, 0.08);
  --gn-inner-shadow: drop-shadow(0 6px 16px rgba(3, 64, 120, 0.08));

  --gn-ink: var(--ink, #152233);
  --gn-muted: var(--ink-3, #6f7b8c);
  --gn-accent: var(--navy, #034078);
  --gn-wm-color: #064078;

  --gn-ease: cubic-bezier(0.4, 0, 0.6, 1);
  --gn-fly-rate: 280ms;

  /* 1px for the always-on border under the bar */
  --gn-bar-total: calc(var(--gn-bar-h) + 1px);
  /* Content height inside the vertical padding. min-height is border-box, so
     children must size against this, not --gn-bar-h, or they re-add the
     padding and inflate the bar. */
  --gn-bar-inner: calc(var(--gn-bar-h) - var(--gn-pad-y) * 2);
}

@media (max-width: 1180px) {
  :root { --gn-bar-h: 76px; --gn-mark: 48px; --gn-wm: 18px; }
}
@media (max-width: 900px) {
  :root { --gn-bar-h: 73px; --gn-mark: 45px; }
}
@media (max-width: 640px) {
  :root { --gn-bar-h: 65px; --gn-pad-y: 10px; --gn-pad-x: 16px; }
}

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

.gn {
  position: sticky;
  top: 0;
  z-index: 60;
  isolation: isolate;
  color: var(--gn-ink);
  background: var(--gn-bg);
  -webkit-backdrop-filter: var(--gn-blur);
  backdrop-filter: var(--gn-blur);
  border-bottom: 1px solid var(--gn-line);
  box-shadow: var(--gn-shadow);
}
/* While a panel is open the bar drops its own fill and the panel carries it. */
.gn.open { background: none; box-shadow: none; }

.gn-in {
  position: relative;
  box-sizing: border-box;
  filter: var(--gn-inner-shadow);
  max-width: var(--gn-maxw);
  margin: 0 auto;
  min-height: var(--gn-bar-h);
  display: flex;
  align-items: center;
  gap: var(--gn-s5, 24px);
  padding: var(--gn-pad-y) var(--gn-pad-x);
}

/* ---- brand lockup: mark + Roboto 700 wordmark, per reference ---------- */

.gn-logo {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;
  white-space: nowrap;
  text-decoration: none;
}
.gn-logo .mark {
  width: var(--gn-mark);
  height: var(--gn-mark);
  flex: none;
  display: block;
}
.gn-logo .wm {
  font-family: Roboto, "Helvetica Neue", sans-serif;
  font-size: var(--gn-wm);
  font-weight: 700;
  color: var(--gn-wm-color);
  letter-spacing: -0.018em;
  line-height: 1;
}
/* Narrow phones carry "Hingst" instead of the full lockup. Both strings live
   in the markup and CSS picks one, so there is no JS swap (no flash) and the
   hidden span is correctly removed from the accessibility tree. */
.gn-logo .wm-short { display: none; }

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

.gn-list {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--gn-s5, 24px);
  list-style: none;
  margin: 0;
  padding: 0;
  flex: 1;
  min-width: 0;
}

.gn-link {
  display: block;
  padding: 0;
  min-height: var(--gn-bar-inner);
  line-height: var(--gn-bar-inner);
  font-size: 15px;
  font-weight: 500;
  color: var(--gn-ink);
  opacity: 0.78;
  text-decoration: none;
  white-space: nowrap;
  transition: opacity 0.24s var(--gn-ease), color 0.24s var(--gn-ease);
}
.gn-link:hover { opacity: 1; }
.gn-link.active { opacity: 1; color: var(--gn-accent); }
.gn-link[aria-current="page"] { opacity: 1; font-weight: 600; }
.gn-link:focus-visible {
  outline: 2px solid var(--gn-accent);
  outline-offset: 3px;
  border-radius: 3px;
}

@media (max-width: 1180px) {
  .gn-list { gap: 10px; }
  .gn-link { font-size: 14px; }
}

/* ---- language switch: Day 2 control, sized for the taller bar ---------- */

.gn-lang {
  position: relative;
  display: inline-flex;
  align-items: center;
  flex: none;
  margin-left: 12px;
  background: #e9edf2;
  border-radius: 999px;
  padding: 3px;
}
.gn-lang .lang-thumb {
  position: absolute;
  /* Anchored to the pill, not the bar. Deriving height from --gn-bar-inner
     overhung the pill by the padding amount at every breakpoint. left:2px
     lines up with day2.js paintSwitch, which offsets by (offsetLeft - 2). */
  top: 3px;
  bottom: 3px;
  left: 2px;
  border-radius: 999px;
  background: var(--gn-accent);
  box-shadow: 0 2px 6px rgba(3, 64, 120, 0.35);
  transition: transform 0.28s cubic-bezier(0.3, 1.2, 0.4, 1), width 0.28s cubic-bezier(0.3, 1.2, 0.4, 1);
  pointer-events: none;
  z-index: 0;
}
.gn-lang button {
  position: relative;
  z-index: 1;
  appearance: none;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--gn-ink-2, #3a4759);
  min-height: 36px;
  min-width: 44px;
  padding: 7px 14px;
  cursor: pointer;
  border-radius: 999px;
  transition: color 0.2s var(--gn-ease);
}
.gn-lang button:hover { color: var(--gn-ink); }
.gn-lang button[aria-pressed="true"] { color: #fff; }

.gn-burger {
  display: none;
  place-items: center;
  width: 38px;
  min-width: 38px;
  height: 34px;
  margin-left: 12px;
  background: none;
  border: 1px solid var(--gn-line);
  border-radius: 9px;
  cursor: pointer;
  color: var(--gn-accent);
  padding: 0;
  flex: none;
}
.gn-burger svg { display: block; }

/* ---- scroll progress: 3px navy-to-lime hairline on the bar's edge ----- */

.gn > .progress {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 3px;
  width: 0;
  background: linear-gradient(90deg, var(--navy, #034078), var(--lime, #bcec00));
  z-index: 1;
}

/* ---- flyout: measured height, Apple ease(.4,0,.6,1) 280ms ------------- */

.fly {
  position: fixed;
  top: var(--gn-bar-total);
  left: 0;
  right: 0;
  z-index: 58;
  /* Near-opaque while reading. The bar can stay at 0.88 because page content
     only ever scrolls behind it, but a flyout sits on top of hero copy and a
     22px display headline reads straight through a translucent wash. */
  background: rgba(255, 255, 255, 0.985);
  -webkit-backdrop-filter: saturate(1.6) blur(26px);
  backdrop-filter: saturate(1.6) blur(26px);
  border-bottom: 1px solid var(--gn-line);
  overflow: hidden;
  height: 0;
  visibility: hidden;
  transition:
    height var(--gn-fly-rate) var(--gn-ease),
    visibility 0s linear var(--gn-fly-rate);
}
.gn.open .fly,
.gn.opening .fly,
.gn.closing .fly {
  visibility: visible;
  transition:
    height var(--gn-fly-rate) var(--gn-ease),
    visibility 0s;
}

.fly-in {
  max-width: var(--gn-maxw);
  margin: 0 auto;
  padding: 34px var(--gn-pad-x) 56px;
  display: grid;
  grid-template-columns: 1.2fr 1fr 1fr;
  gap: 40px;
  opacity: 0;
  transition: opacity 0.2s var(--gn-ease) 80ms;
}
.gn.opening .fly-in,
.gn.open .fly-in { opacity: 1; }
.gn.closing .fly-in { opacity: 0; transition-delay: 0ms; }

.fly h4 {
  margin: 0 0 12px;
  font-size: 12px;
  font-weight: 500;
  color: var(--gn-muted);
}
.fly ul { list-style: none; margin: 0; padding: 0; }
.fly li { opacity: 0; transform: translateY(-8px); }

/* First open: 200ms lead-in, +20ms per index. */
.gn.opening .fly-in[data-enter="first"] li,
.gn.open .fly-in[data-enter="first"] li {
  animation: gn-rise 0.24s var(--gn-ease) both;
  animation-delay: calc(200ms + var(--i, 0) * 20ms);
}
/* Switch replay: 40ms + 15ms per index, so sweeping the bar stays snappy. */
.gn.opening .fly-in[data-enter="switch"] li,
.gn.open .fly-in[data-enter="switch"] li {
  animation: gn-rise 0.24s var(--gn-ease) both;
  animation-delay: calc(40ms + var(--i, 0) * 15ms);
}
/* Full close only: reverse-order fade. Switches unmount instantly, no fade-out. */
.gn.closing .fly li {
  animation: none;
  opacity: 0;
  transform: translateY(-8px);
  transition:
    opacity 0.2s var(--gn-ease),
    transform 0.2s var(--gn-ease);
  transition-delay: var(--rev, 0ms);
}

@keyframes gn-rise {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.fly a {
  text-decoration: none;
  transition: color 0.18s var(--gn-ease);
}
.fly a.big {
  display: block;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.25;
  color: var(--gn-ink);
  padding: 5px 0;
}
.fly a.small {
  display: block;
  font-size: 12px;
  line-height: 1.4;
  color: var(--gn-ink);
  opacity: 0.85;
  padding: 6px 0;
  min-height: 32px;
}
.fly a.compare {
  display: inline-block;
  margin-top: 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--gn-accent);
  min-height: 32px;
  line-height: 32px;
}
.fly a.big:hover,
.fly a.small:hover,
.fly a.compare:hover { text-decoration: underline; }
.fly a:focus-visible { outline: 2px solid var(--gn-accent); outline-offset: 3px; border-radius: 3px; }

/* ---- mobile drawer ------------------------------------------------------ */

.gn-m-menu {
  position: fixed;
  inset: var(--gn-bar-total) 0 0 0;
  z-index: 59;
  background: var(--gn-bg);
  -webkit-backdrop-filter: var(--gn-blur);
  backdrop-filter: var(--gn-blur);
  transform: translateY(-6px);
  opacity: 0;
  visibility: hidden;
  transition: 0.25s var(--gn-ease);
  overflow: auto;
  -webkit-overflow-scrolling: touch;
}
.gn-m-menu.show { transform: none; opacity: 1; visibility: visible; }
.gn-m-menu a.row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  max-width: var(--gn-maxw);
  margin: 0 auto;
  padding: 13px var(--gn-pad-x);
  min-height: 44px;
  font-size: 17px;
  font-weight: 600;
  color: var(--gn-ink);
  text-decoration: none;
  border-bottom: 1px solid var(--gn-line);
}
.gn-m-menu a.row span { color: var(--gn-muted); }

body.has-flyout,
body.gn-mobile-open { overflow: hidden; }

@media (max-width: 833px) {
  .gn-list { display: none; }
  .gn-burger { display: grid; margin-left: 12px; }
  .gn-logo { gap: 8px; }
  /* .gn-list carried flex:1 and was what pinned the right-hand controls to
     the edge. Once it is display:none that spacer is gone, so the pill and
   burger have to claim the slack themselves or they stack up against the
     mark with dead space to the right. */
  .gn-lang { margin-left: auto; }
  .fly-in { grid-template-columns: 1fr; gap: 20px; padding: 24px var(--gn-pad-x) 40px; }
}

/* Phone tier.
   Two constraints pulled against each other here:
   1. Lockup + pill + burger needed 444px at desktop metrics, so every phone
      width clipped the burger (html overflow-x:hidden hid the symptom as a
      cut-off edge rather than a scrollbar). 393px had 83px of overflow.
   2. The wordmark still has to appear, so it cannot simply be dropped.
   Resolution: keep the mark plus a reduced 14px wordmark, shrink the pill 20%
   (126x40 -> ~101x32), and tighten the gap 24 -> 12.
   .gn-list carried flex:1 and was what pinned the right-hand controls to the
   edge. Once it is display:none that spacer is gone, so the pill has to claim
   the slack itself (margin-left:auto) or everything collapses left against the
   mark with dead space on the right. */
@media (max-width: 640px) {
  :root { --gn-mark: 40px; --gn-wm: 17px; }
  .gn-in { gap: 12px; }
  .gn-logo { gap: 8px; }
  .gn-logo .wm { letter-spacing: -0.014em; }
  .gn-lang { margin-left: auto; padding: 2px; }
  .gn-lang .lang-thumb { top: 2px; bottom: 2px; }
  .gn-lang button {
    min-width: 28px;
    min-height: 28px;
    padding: 4px 6px;
    /* Font held at 12px on purpose. The 20% comes out of padding, min-width
       and min-height; dropping the type below 12px would buy a few px and
       cost legibility on 中文 at 3x DPR. */
    font-size: 12px;
  }
  .gn-burger { margin-left: 12px; }
}

/* Very narrow (SE 1st gen, small Androids). The full "Hingst Research"
   lockup is what forces the wordmark out here: at 17px it is ~122px, which
   leaves ~11px of slack at 360px and goes negative at 320px. "Hingst" is ~50px
   of that, so the mark and a short wordmark both fit down to 320. */
@media (max-width: 380px) {
  :root { --gn-mark: 38px; --gn-wm: 17px; }
  .gn-in { gap: 10px; }
  .gn-logo .wm-long { display: none; }
  .gn-logo .wm-short { display: inline; }
  .gn-lang button { min-width: 26px; padding: 4px 6px; }
  .gn-burger { width: 32px; min-width: 32px; margin-left: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  .fly,
  .fly li,
  .fly-in,
  .gn-m-menu,
  .gn-lang .lang-thumb {
    animation: none !important;
    transition: none !important;
  }
  .fly li { opacity: 1; transform: none; }
  .fly-in { opacity: 1; }
}