/* ============================================================
   Components — header, menu, footer, hero pieces, cards.
   ============================================================ */

/* ----------------------------------------------------------------
   Hero background — fixed video + readability gradient
   ---------------------------------------------------------------- */

/* Hero background layer — fixed-position container for the video
   AND a fallback poster background-image. Sits at z-index 0
   (NOT negative — see tokens.css for why). Content above is
   z-index 1+ and either transparent (the .hero section) or
   opaque (everything below) so it scrolls over cleanly. */
.hero-bg {
  position: fixed;
  inset: 0;
  z-index: var(--z-bg);
  pointer-events: none;
  background-color: var(--color-bg);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  /* Background poster wired in Phase 2 once Freesia hero clips land. */
  transform: translate3d(0, 0, 0);
}

/* Two stacked <video> elements, both fill .hero-bg. The intro
   sits on top with .is-active; the loop sits underneath at
   opacity 0. When the intro nears its end, JS starts the loop
   playing then instantly swaps z-index + opacity on `ended` —
   gapless, no fade, no black frame. */
.hero-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  z-index: 1;
  -webkit-transform: translate3d(0, 0, 0);
  transform: translate3d(0, 0, 0);
  /* Disable any pointer interaction on the video so user taps go to
     the page (e.g. menu toggle, scroll) rather than to the video's
     native play overlay. */
  pointer-events: none;
}

/* Suppress native browser play-button overlays that some browsers
   render when autoplay is blocked. iOS Safari, Android WebView and
   older Chromium ship a centered ▶ overlay on paused videos — these
   shadow-DOM pseudo-element overrides hide all of them so the user
   never sees a "tap to play" prompt even if our autoplay is blocked
   and the silent-gesture fallback hasn't fired yet. */
.hero-video::-webkit-media-controls,
.hero-video::-webkit-media-controls-panel,
.hero-video::-webkit-media-controls-overlay-play-button,
.hero-video::-webkit-media-controls-start-playback-button,
.hero-video::-webkit-media-controls-play-button,
.menu-video::-webkit-media-controls,
.menu-video::-webkit-media-controls-panel,
.menu-video::-webkit-media-controls-overlay-play-button,
.menu-video::-webkit-media-controls-start-playback-button,
.menu-video::-webkit-media-controls-play-button {
  display: none !important;
  -webkit-appearance: none !important;
  appearance: none !important;
  opacity: 0 !important;
  pointer-events: none !important;
}

.hero-video.is-active {
  opacity: 1;
  z-index: 2;
}

.hero-overlay {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg,
      rgba(14,22,32,0.20) 0%,
      transparent 40%,
      transparent 60%,
      rgba(14,22,32,0.65) 100%
    );
  pointer-events: none;
}

/* (Tap-to-play overlay removed — autoplay attributes + global
    play() retry on first user gesture make it unnecessary.) */

/* Glass-everywhere: the fixed hero-bg video plays on every page,
   not just the homepage. Internal pages still skip the hero-overlay
   gradient (it's only for darkening the hero section); the per-page
   sections supply their own glass tint. */
body:not(.page-home) .hero-overlay { display: none; }

/* ----------------------------------------------------------------
   Animated hero logo (homepage only).
   Fixed at viewport center; GSAP animates transform from
   center scale 1 → top-bar position scale ~0.32.
   ---------------------------------------------------------------- */

.hero-logo {
  position: fixed;
  top: 50%;
  left: 50%;
  z-index: var(--z-overlay);
  width: 22vw;
  max-width: 380px;
  min-width: 180px;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.94);
  will-change: transform, opacity;
}

.hero-logo img {
  width: 100%;
  height: auto;
  display: block;
}

body:not(.page-home) .hero-logo { display: none; }

/* ----------------------------------------------------------------
   Site header (top bar)
   ---------------------------------------------------------------- */

.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--header-h);
  z-index: var(--z-header);
  background: transparent;
  transition:
    background-color var(--dur-short) var(--ease-out),
    backdrop-filter  var(--dur-short) var(--ease-out);
}

.site-header.is-visible {
  /* Whisper glass (brief §3.5) — almost invisible, earns its
     presence on scroll. Tint very light so ocean motion bleeds
     through clearly. */
  background: var(--glass-whisper-bg);
  backdrop-filter: var(--glass-whisper-filter);
  -webkit-backdrop-filter: var(--glass-whisper-filter);
  border-bottom: var(--glass-whisper-border);
}

/* Top-edge specular highlight on the header — the same 1px line
   gradient pearl→transparent. */
.site-header.is-visible::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: var(--glass-highlight);
  pointer-events: none;
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header.is-visible { background: color-mix(in srgb, var(--abyssal) 88%, transparent); }
}

.site-header__inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  height: 100%;
  padding-inline: var(--gutter-x);
  max-width: var(--content-max);
  margin-inline: auto;
}

/* On homepage, top-bar elements start hidden — JS fades them in */
.page-home .site-header .lang-toggle,
.page-home .site-header .header-logo,
.page-home .site-header .menu-toggle {
  opacity: 0;
}

@media (max-width: 768px) {
  .site-header { height: var(--header-h-mobile); }
}

/* ----------------------------------------------------------------
   Header logo (static, in top bar)
   ---------------------------------------------------------------- */

.header-logo {
  display: block;
  justify-self: center;
  height: 38px;
  line-height: 0;
}

.header-logo img {
  height: 100%;
  width: auto;
  display: block;
}

@media (max-width: 768px) {
  .header-logo { height: 32px; }
}

/* ----------------------------------------------------------------
   Language toggle (left of header)
   ---------------------------------------------------------------- */

.lang-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0;
  border: none;
  background: transparent;
  justify-self: start;
}

.lang-toggle__btn {
  font-family: var(--font-mono, ui-monospace, "SF Mono", Menlo, Consolas, monospace);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
  padding: 4px 0;
  border: none;
  background: transparent;
  border-radius: 0;
  cursor: pointer;
  min-height: 32px;
  position: relative;
  transition: color var(--dur-micro) var(--ease-micro);
}

@media (hover: none) and (pointer: coarse) {
  .lang-toggle__btn { min-height: 36px; min-width: 36px; padding: 9px 14px; }
}

.lang-toggle__btn:hover {
  color: var(--color-text);
}

.lang-toggle__btn[aria-pressed="true"] {
  color: var(--color-text);
  background: transparent;
}
.lang-toggle__btn[aria-pressed="true"]::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--color-text);
}

@media (max-width: 480px) {
  .lang-toggle { gap: var(--space-1); }
  .lang-toggle__btn { font-size: 10px; letter-spacing: 0.18em; }
}

/* ----------------------------------------------------------------
   Menu toggle (hamburger, right of header)
   ---------------------------------------------------------------- */

.menu-toggle {
  justify-self: end;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: background-color var(--dur-micro) var(--ease-micro);
}

/* When the menu overlay is open, lift the entire header above it
   so the hamburger (now an X) stays visible and clickable. The class
   `body.menu-is-open` is set by js/nav.js openMenu/closeMenu so the
   header z-index switches in lockstep with the overlay. */
body.menu-is-open .site-header {
  z-index: calc(var(--z-modal) + 1);
}
body.menu-is-open .site-header.is-visible {
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-bottom: none;
}

.menu-toggle:hover {
  background: rgba(255, 255, 255, 0.06);
}

/* Two screen-reader labels stacked inside the toggle. CSS swaps which
   is visible to AT based on aria-expanded so screen readers always
   read the correct action ("Open menu" / "Close menu") even though
   the visible icon also morphs from ≡ to X. */
.menu-toggle__label--close { display: none; }
.menu-toggle[aria-expanded="true"] .menu-toggle__label--open { display: none; }
.menu-toggle[aria-expanded="true"] .menu-toggle__label--close { display: inline; }

.menu-toggle__icon {
  position: relative;
  display: block;
  width: 22px;
  height: 14px;
}

/* Both bars are centered vertically; spacing comes from transform only.
   Animating a single property (transform) prevents the jitter that
   shows up when top/bottom and transform animate concurrently. */
.menu-toggle__icon span {
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 1.5px;
  background: var(--color-text);
  transform-origin: center;
  transition: transform 320ms cubic-bezier(0.65, 0, 0.35, 1);
}

/* Closed: spread apart by ±5px from center */
.menu-toggle__icon span:first-child { transform: translateY(calc(-50% - 5px)); }
.menu-toggle__icon span:last-child  { transform: translateY(calc(-50% + 5px)); }

/* Open: collapse to center and rotate into an X */
.menu-toggle[aria-expanded="true"] .menu-toggle__icon span:first-child {
  transform: translateY(-50%) rotate(45deg);
}
.menu-toggle[aria-expanded="true"] .menu-toggle__icon span:last-child {
  transform: translateY(-50%) rotate(-45deg);
}

/* ----------------------------------------------------------------
   Full-screen menu overlay — opaque, centred, premium.
   Solid #0A0A0A covers everything (video included). The header
   stays above with class swap on body, so the X close icon is
   always visible.
   ---------------------------------------------------------------- */

.menu-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  /* Transparent — the .menu-glass child supplies the tint+blur,
     and the page-level fixed ocean video shows through behind it. */
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 300ms var(--ease-out);
  overflow: hidden;
}

/* Video layer — sits at the bottom of the stack inside the menu.
   Two stacked videos cycle intro→loop forever. */
.menu-bg-video {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
}

.menu-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  z-index: 1;
}

.menu-video.is-active {
  opacity: 1;
  z-index: 2;
}

/* Modal glass (brief §3.5) — the menu is a full-screen overlay,
   the heaviest surface tier. */
.menu-glass {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--glass-modal-bg);
  backdrop-filter: var(--glass-modal-filter);
  -webkit-backdrop-filter: var(--glass-modal-filter);
  pointer-events: none;
}
.menu-glass::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: var(--glass-highlight);
  pointer-events: none;
}

/* Content (links + footer) sits above the glass */
.menu-overlay__inner {
  position: relative;
  z-index: 3;
}

/* No-backdrop-filter fallback: solid dark fill instead of glass. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .menu-glass { background: color-mix(in srgb, var(--deep) 94%, transparent); }
}

/* Low-perf tier: skip the expensive blur entirely. */
html[data-perf="low"] .menu-glass {
  background: rgba(14, 22, 32, 0.94);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.menu-overlay[hidden] { display: none; }

.menu-overlay.is-open {
  opacity: 1;
  pointer-events: auto;
}

.menu-overlay__inner {
  max-width: 600px;
  width: 100%;
  padding-inline: var(--gutter-x);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
  text-align: center;
}

.menu-list {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
}

.menu-list li { width: 100%; }

.menu-list a {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 6vw, 4rem);
  font-weight: 500;
  line-height: 1.05;
  letter-spacing: var(--tr-display);
  color: var(--color-text);
  display: inline-block;
  position: relative;
  padding: 0;
  border: none;
  background: none;
  text-decoration: none;
  outline: none;        /* No box outline — focus is color only */
  opacity: 0;
  transform: translateY(20px);
  transition: color 200ms var(--ease-micro);
}

/* Focus uses colour, not an outline box. Keeps the menu clean
   while still accessible — keyboard users see the current focus
   in the same brand red used for hover and active page. */
.menu-list a:focus-visible {
  color: var(--color-brand);
  outline: none;
}

/* Open animation — stagger each link in */
.menu-overlay.is-open .menu-list a {
  opacity: 1;
  transform: translateY(0);
  transition:
    opacity 600ms var(--ease-out),
    transform 600ms var(--ease-out),
    color 200ms var(--ease-micro);
}
.menu-overlay.is-open .menu-list li:nth-child(1) a { transition-delay: 0ms,   0ms,   0ms; }
.menu-overlay.is-open .menu-list li:nth-child(2) a { transition-delay: 80ms,  80ms,  0ms; }
.menu-overlay.is-open .menu-list li:nth-child(3) a { transition-delay: 160ms, 160ms, 0ms; }
.menu-overlay.is-open .menu-list li:nth-child(4) a { transition-delay: 240ms, 240ms, 0ms; }
.menu-overlay.is-open .menu-list li:nth-child(5) a { transition-delay: 320ms, 320ms, 0ms; }

/* Couture restraint — hover on links is an italic shift, not a
   colour swap. White stays white. The Met Gala uses italics, not
   colour, to signal interaction. */
.menu-list a {
  font-style: italic;
  font-weight: 400;
  transition: opacity var(--dur-micro) var(--ease-micro), letter-spacing var(--dur-short) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .menu-list a:hover {
    opacity: 0.7;
  }
}

/* Active page — same white, with a hairline underline. */
.menu-list a[aria-current="page"] {
  color: var(--color-text);
}
.menu-list a[aria-current="page"]::after {
  content: "";
  display: block;
  width: 64px;
  height: 1px;
  background: rgba(255, 255, 255, 0.5);
  margin: 12px auto 0;
}

/* Footer — thin red rule + email block */
.menu-overlay__footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-4);
  opacity: 0;
  transition: opacity 400ms var(--ease-out);
}
.menu-overlay.is-open .menu-overlay__footer {
  opacity: 1;
  transition-delay: 600ms;
}

.menu-overlay__rule {
  display: block;
  width: 48px;
  height: 1px;
  background: var(--color-divider);
  border: none;
  margin: 0;
}

.menu-overlay__footer a {
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  text-decoration: none;
  transition: color var(--dur-micro) var(--ease-micro);
}

@media (hover: hover) and (pointer: fine) {
  .menu-overlay__footer a:hover { color: var(--color-text); }
}

/* Mobile — left-aligned, smaller link size. The whole menu inner
   pulls to the page's left gutter so it reads like the rest of
   the site's editorial column. Footer (rule + email) follows. */
@media (max-width: 768px) {
  .menu-overlay {
    justify-content: flex-start;
  }
  .menu-overlay__inner {
    align-items: flex-start;
    text-align: left;
    max-width: none;
    width: 100%;
  }
  .menu-list {
    align-items: flex-start;
  }
  .menu-list a {
    font-size: clamp(2rem, 8vw, 2.75rem);
    text-align: left;
  }
  /* Active-page underline aligns to the left edge of the text */
  .menu-list a[aria-current="page"]::after {
    margin: 12px 0 0;
  }
  .menu-overlay__footer {
    align-items: flex-start;
    margin-top: var(--space-6);
  }
  .menu-overlay__rule {
    margin: 0;
  }
}

/* ----------------------------------------------------------------
   CTA buttons (mailto cards) — used on home + contact
   ---------------------------------------------------------------- */

.cta-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2);
  /* align-items: start so a hovered button can grow downward
     without stretching its sibling to match its new height. */
  align-items: start;
}

/* Grid layout: row 1 holds the label + arrow (always visible),
   row 2 holds the email reveal (collapsed to 0 by default). The
   box height is determined by row 1 only — when row 2 expands on
   hover, the box grows downward. */
.cta-btn {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-rows: auto;
  column-gap: var(--space-3);
  row-gap: 0;
  align-items: center;
  padding: 14px var(--space-3);
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-divider);
  color: var(--color-text);
  text-decoration: none;
  overflow: hidden;
  transition:
    border-color var(--dur-micro) var(--ease-micro),
    background-color var(--dur-short) var(--ease-out);
}

.cta-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--color-brand);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform var(--dur-short) var(--ease-out);
  z-index: 0;
}

.cta-btn > * { position: relative; z-index: 1; }

.cta-btn__label {
  grid-column: 1;
  grid-row: 1;
  font-family: var(--font-sans);
  font-size: var(--fs-md);
  font-weight: 500;
  letter-spacing: -0.005em;
  color: var(--color-text);
  /* Block element with line-height 1.2 — pairs symmetrically
     with the arrow's centred line height for true vertical center. */
  line-height: 1.2;
  min-width: 0;
}

.cta-btn__arrow {
  grid-column: 2;
  grid-row: 1;
  font-size: var(--fs-xl);
  line-height: 1;
  color: var(--color-brand);
  /* Match the label's optical centre exactly */
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  transition:
    transform var(--dur-short) var(--ease-out),
    color var(--dur-micro) var(--ease-micro);
}

/* Email reveal — second grid row. Collapsed to zero height by
   default; the box reads as a clean rectangle with just label+arrow.
   On hover/focus the row expands and the email fades in. */
.cta-btn__reveal {
  grid-column: 1 / -1;
  grid-row: 2;
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-weight: 400;
  color: var(--color-text-muted);
  letter-spacing: 0.01em;
  word-break: break-word;
  overflow-wrap: anywhere;
  min-width: 0;
  opacity: 0;
  max-height: 0;
  margin-top: 0;
  overflow: hidden;
  transition:
    opacity var(--dur-micro) var(--ease-micro),
    max-height var(--dur-short) var(--ease-out),
    margin-top var(--dur-short) var(--ease-out);
}

.cta-btn:hover .cta-btn__reveal,
.cta-btn:focus-visible .cta-btn__reveal,
.cta-btn:focus-within .cta-btn__reveal {
  opacity: 1;
  max-height: 2em;
  margin-top: 8px;
  transition:
    opacity 200ms var(--ease-micro),
    max-height var(--dur-short) var(--ease-out),
    margin-top var(--dur-short) var(--ease-out);
}

@media (hover: hover) {
  .cta-btn:hover {
    border-color: var(--color-brand);
  }
  .cta-btn:hover::before { transform: scaleY(1); }
  .cta-btn:hover .cta-btn__arrow {
    color: var(--color-text);
    transform: translateX(6px);
  }
}

@media (max-width: 640px) {
  .cta-row { grid-template-columns: 1fr; }
}

/* ----------------------------------------------------------------
   Toast — bottom-center notification when mailto fallback fires
   (clipboard copy etc). Subtle, 2s lifetime, fade in/out.
   ---------------------------------------------------------------- */
.cta-toast {
  position: fixed;
  left: 50%;
  bottom: 32px;
  transform: translate(-50%, 12px);
  background: rgba(20, 20, 20, 0.96);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-weight: 500;
  letter-spacing: 0;
  padding: 12px 20px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  z-index: var(--z-modal);
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 200ms var(--ease-micro),
    transform 200ms var(--ease-out);
}

.cta-toast.is-visible {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* ----------------------------------------------------------------
   Custom cursor (hidden on touch devices)
   ---------------------------------------------------------------- */

.cursor-dot,
.cursor-ring {
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: var(--z-modal);
  mix-blend-mode: difference;
}

.cursor-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-brand);
  transform: translate(-50%, -50%) translate3d(0, 0, 0);
  transition: opacity var(--dur-micro) var(--ease-micro);
  opacity: 0;
}

.cursor-ring {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.55);
  transform: translate(-50%, -50%) translate3d(0, 0, 0);
  transition:
    width var(--dur-short) var(--ease-out),
    height var(--dur-short) var(--ease-out),
    border-color var(--dur-micro) var(--ease-micro),
    opacity var(--dur-micro) var(--ease-micro),
    background-color var(--dur-short) var(--ease-out);
  opacity: 0;
}

.cursor-ready .cursor-dot,
.cursor-ready .cursor-ring { opacity: 1; }

/* Hover state — ring grows, dot fades */
.cursor-hover .cursor-dot { opacity: 0; }
.cursor-hover .cursor-ring {
  width: 64px;
  height: 64px;
  border-color: var(--color-brand);
  background: rgba(58, 77, 110, 0.08);
}

/* Hide native cursor on devices with fine pointer */
@media (hover: hover) and (pointer: fine) {
  html.cursor-ready,
  html.cursor-ready *,
  html.cursor-ready a,
  html.cursor-ready button {
    cursor: none !important;
  }
}

/* Touch devices — hide entirely */
@media (hover: none), (pointer: coarse) {
  .cursor-dot, .cursor-ring { display: none; }
}

/* Reduced motion — hide custom cursor, restore native */
@media (prefers-reduced-motion: reduce) {
  .cursor-dot, .cursor-ring { display: none; }
  html.cursor-ready, html.cursor-ready * { cursor: auto !important; }
}

/* ----------------------------------------------------------------
   Site footer
   ---------------------------------------------------------------- */

.site-footer {
  position: relative;
  z-index: var(--z-content);
  /* Transparent — the .site-footer__glass child supplies tint+blur,
     and the page-level fixed ocean video shows through behind. */
  background: transparent;
  padding-block: var(--space-12) var(--space-6);
  border-top: 1px solid var(--color-divider);
  overflow: hidden;
  isolation: isolate;
}

/* Video layer — same intro+loop cycle pattern as the menu/hero.
   Lazy-loaded by js/footer.js when the footer enters viewport. */
.site-footer__bg-video {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  pointer-events: none;
}

.site-footer__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  z-index: 1;
  pointer-events: none;
}

.site-footer__video.is-active {
  opacity: 1;
  z-index: 2;
}

/* Suppress browser play overlays on these too. */
.site-footer__video::-webkit-media-controls,
.site-footer__video::-webkit-media-controls-panel,
.site-footer__video::-webkit-media-controls-overlay-play-button,
.site-footer__video::-webkit-media-controls-start-playback-button,
.site-footer__video::-webkit-media-controls-play-button {
  display: none !important;
  -webkit-appearance: none !important;
  appearance: none !important;
  opacity: 0 !important;
  pointer-events: none !important;
}

/* Card glass (brief §3.5) — the footer is a content surface but
   less dense than the menu modal. */
.site-footer__glass {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--glass-card-bg);
  backdrop-filter: var(--glass-card-filter);
  -webkit-backdrop-filter: var(--glass-card-filter);
  pointer-events: none;
}
.site-footer__glass::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: var(--glass-highlight);
  pointer-events: none;
}

/* No-backdrop-filter fallback: solid dark fill instead of glass. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-footer__glass { background: color-mix(in srgb, var(--surface) 92%, transparent); }
}

html[data-perf="low"] .site-footer__glass {
  background: color-mix(in srgb, var(--surface) 86%, transparent);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* Content sits above the glass + video. */
.site-footer__content {
  position: relative;
  z-index: 3;
  max-width: var(--content-max);
  margin-inline: auto;
  padding-inline: var(--gutter-x);
}

/* Legacy selector kept for any older markup that still scopes via
   .site-footer .container (none after this update, but harmless). */
.site-footer .container {
  max-width: var(--content-max);
}

/* Three columns on desktop: brand | address | email
   Address and email are siblings of equal width, so their
   labels share a baseline and their content aligns vertically. */
.site-footer__grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  column-gap: var(--space-8);
  row-gap: var(--space-8);
  padding-bottom: var(--space-10);
  align-items: start;
}

.site-footer__brand {
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
}

/* Logo above the tagline — anchored to the same left edge as
   the tagline text. Wrapped in a link to the home page so the
   footer mark behaves the same as the header logo. */
.site-footer__mark-link {
  display: inline-block;
  line-height: 0;
  margin: 0 0 var(--space-1) 0;
  padding: 0;
  border: none;
  transition: opacity var(--dur-micro) var(--ease-micro);
}

.site-footer__mark-link:hover { opacity: 0.85; }

.site-footer__mark {
  display: block;
  width: 96px;
  height: auto;
  margin: 0;
  padding: 0;
}

@media (max-width: 640px) {
  .site-footer__mark { width: 80px; }
}

.site-footer__tagline {
  font-size: var(--fs-xl);
  line-height: 1.15;
  max-width: 18ch;
  margin: 0;
}

.site-footer__col {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
}

.site-footer__col .label {
  font-size: var(--fs-xs);
  margin: 0 0 var(--space-1) 0;
  line-height: 1.2;
}

.site-footer__col > p,
.site-footer__col > a {
  font-size: var(--fs-sm);
  line-height: 1.55;
  max-width: none;
  margin: 0;
}

.site-footer__col a {
  display: inline-block;
  align-self: flex-start;
  border-bottom: 1px solid transparent;
  padding-bottom: 1px;
  width: fit-content;
  transition:
    color var(--dur-micro) var(--ease-micro),
    border-color var(--dur-micro) var(--ease-micro);
}
.site-footer__col a:hover {
  color: var(--color-brand-hover);
  border-color: var(--color-brand-hover);
}

.site-footer .divider { margin-block: var(--space-4); }

.site-footer__legal {
  font-size: var(--fs-xs);
  letter-spacing: 0.05em;
  text-align: left;
  margin: 0;
}

/* Tablet: brand on top, address+email side-by-side below */
@media (max-width: 1024px) {
  .site-footer__grid {
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "brand brand"
      "addr  email";
    column-gap: var(--space-6);
    row-gap: var(--space-6);
  }
  .site-footer__brand   { grid-area: brand; }
  .site-footer__col--address { grid-area: addr; }
  .site-footer__col--contact { grid-area: email; }
}

/* Mobile: everything stacks */
@media (max-width: 640px) {
  .site-footer__grid {
    grid-template-columns: 1fr;
    grid-template-areas:
      "brand"
      "addr"
      "email";
    row-gap: var(--space-5);
  }
}




/* ============================================================
   Hong Kong live clock — Aston-Martin-dashboard restraint.

   Mono tabular digits (so they don't reflow as numbers tick),
   small uppercase label, brand-red blinking colon between minutes
   and seconds as the live indicator. Two surfaces:

   - .hk-clock              — contact page, under the Office heading
   - .hk-clock--footer      — bottom row of every footer

   Format updated by js/clock.js via Intl.DateTimeFormat with
   timeZone: 'Asia/Hong_Kong'.
   ============================================================ */
.hk-clock {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-3);
  font-family: var(--font-mono, ui-monospace, "SF Mono", Menlo, Consolas, monospace);
  font-feature-settings: "tnum";
  font-variant-numeric: tabular-nums;
  color: var(--color-text);
  line-height: 1;
}

.hk-clock__label,
.hk-clock__zone {
  font-size: var(--fs-xs);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  line-height: 1;
}

.hk-clock__time {
  font-size: var(--fs-md);
  letter-spacing: 0.05em;
  line-height: 1;
  color: var(--color-text);
}

.hk-clock__sep {
  color: var(--color-text-muted);
  margin-inline: 0.05em;
}

/* The center colon (between minutes and seconds) blinks once per
   second as the "live" indicator — same idea as a tower-clock pulse. */
/* Blinking separator colon — driven by JS class toggle (on the
   [data-hk-clock] root) so its on/off flip is perfectly in sync
   with the seconds-digit tick. CSS keyframe removed because animation
   start time depends on parse order, drifting out of sync with the
   setInterval-driven digit update. */
.hk-clock__sep--blink {
  color: var(--color-brand);
  opacity: 0.3;
  transition: opacity 80ms ease-out;
}
[data-hk-clock].is-tick-on .hk-clock__sep--blink {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .hk-clock__sep--blink {
    opacity: 1 !important;
    transition: none;
  }
}

/* Footer variant — slightly smaller time, sits opposite the legal
   line in the bottom row. All digits stay white; only the blinking
   colon and the HKT zone label carry the brand red. */
.hk-clock--footer .hk-clock__time {
  font-size: var(--fs-sm);
  letter-spacing: 0.06em;
}

/* HKT zone label in brand red — quiet but unmistakable timezone
   signal pinned to the right of the digits. */
.hk-clock--footer .hk-clock__zone {
  color: var(--color-brand);
}

/* Footer bottom row: legal copyright on the left, clock on the right.
   Stacks on mobile with gap. */
.site-footer__bottom {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
}

@media (max-width: 640px) {
  .site-footer__bottom {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ============================================================
   Hong Kong clock — special variant for the Contact page.

   Editorial-dateline treatment, more presence than the footer
   variant. Three lines stacked tight:

     [pulse] HONG KONG  ·  GMT+8         ← mono uppercase eyebrow
     16:42                      · 18      ← display serif HH:MM, mono small ·SS
     Sunday, 10 May 2026                  ← italic display serif date

   The pulse dot breathes once per 2s as the live indicator. The
   colon between HH and MM blinks once per second.
   ============================================================ */
.hk-clock--special {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
  margin-top: var(--space-5);
  /* Override the base inline-flex layout. */
  align-items: flex-start;
}

.hk-clock--special > * { margin: 0; }

.hk-clock--special .hk-clock__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono, ui-monospace, "SF Mono", Menlo, Consolas, monospace);
  font-size: var(--fs-xs);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  line-height: 1;
}

/* Live indicator — radar-style pulse. Solid red center dot with
   strong inner+outer glow, plus two hollow ring outlines that
   emanate outward continuously (offset 0.75s for a tight rhythm).
   Visually distinct from the on/off binary blink of the seconds
   colon — this reads as analog "transmitting", that reads as
   digital tick. */
/* Live indicator — warm-grey center with a glowing red halo. The
   center stays quiet so it doesn't compete with the seconds colon
   (which is solid brand red); the red glow IS the live signal,
   waxing and waning each cycle. Two faint hollow rings emanate
   outward on offset for a "transmitting" feel. */
.hk-clock--special .hk-clock__pulse {
  position: relative;
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  /* Warm-grey center — same hue family as the eyebrow text. Quiet. */
  background: rgba(255, 255, 255, 0.55);
  /* Two-stop red glow: tight bloom + diffuse halo. The glow is the
     visual story; the dot is just its source point. */
  box-shadow:
    0 0 6px  rgba(58, 77, 110, 0.85),
    0 0 14px rgba(58, 77, 110, 0.45);
  animation: hk-clock-pulse-core 1.8s ease-in-out infinite;
}

/* Hollow ring outlines (red border + transparent fill) — read more
   like radar than filled circles, line stays crisp as it expands. */
.hk-clock--special .hk-clock__pulse::before,
.hk-clock--special .hk-clock__pulse::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: 50%;
  border: 1.5px solid var(--color-brand);
  background: transparent;
  box-sizing: border-box;
  animation: hk-clock-pulse-ring 1.8s cubic-bezier(0, 0, 0.3, 1) infinite;
  pointer-events: none;
}

.hk-clock--special .hk-clock__pulse::after {
  animation-delay: 0.9s;
}

@keyframes hk-clock-pulse-core {
  0%, 100% {
    transform: scale(1);
    background: rgba(255, 255, 255, 0.55);
    box-shadow:
      0 0 6px  rgba(58, 77, 110, 0.85),
      0 0 14px rgba(58, 77, 110, 0.45);
  }
  50% {
    transform: scale(1.13);
    /* Center brightens slightly at peak — picks up reflected red
       from the surrounding glow. */
    background: rgba(255, 230, 232, 0.85);
    box-shadow:
      0 0 10px rgba(58, 77, 110, 1),
      0 0 22px rgba(58, 77, 110, 0.7);
  }
}

@keyframes hk-clock-pulse-ring {
  0%   { transform: scale(1);   opacity: 0.6; border-width: 1.5px; }
  75%  {                        opacity: 0;   border-width: 1px;   }
  100% { transform: scale(3);   opacity: 0;   border-width: 1px;   }
}

.hk-clock--special .hk-clock__display {
  display: flex;
  align-items: baseline;
  gap: 0.45em;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.75rem, 5vw, 4.25rem);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--color-text);
}

.hk-clock--special .hk-clock__hm {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

/* Smaller mono seconds floated next to the big HH:MM. The `·`
   separator visually divides them without a hard punctuation feel.
   The seconds digits themselves are brand red — paired with the
   blinking colon above as the live-tick indicators. */
.hk-clock--special .hk-clock__seconds {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-family: var(--font-mono, ui-monospace, "SF Mono", Menlo, Consolas, monospace);
  font-size: 0.32em;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.hk-clock--special .hk-clock__seconds [data-s] {
  color: var(--color-brand);
}

.hk-clock--special .hk-clock__sep-dot {
  color: var(--color-text-muted);
  opacity: 0.6;
}

.hk-clock--special .hk-clock__colon {
  margin-inline: 0.05em;
  color: var(--color-text-muted);
}

/* Blinking colon between HH and MM — brand red, driven by JS class
   toggle on the [data-hk-clock] root so it's perfectly in sync with
   the seconds-digit update each second. CSS keyframe removed
   because animation start time drifts independent of the digit tick. */
.hk-clock--special .hk-clock__colon--blink {
  color: var(--color-brand);
  opacity: 0.3;
  transition: opacity 80ms ease-out;
}
[data-hk-clock].is-tick-on .hk-clock--special .hk-clock__colon--blink,
.hk-clock--special[data-hk-clock].is-tick-on .hk-clock__colon--blink {
  opacity: 1;
}

.hk-clock--special .hk-clock__date {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: var(--fs-md);
  line-height: 1.3;
  color: var(--color-text-muted);
  letter-spacing: 0.005em;
}

/* Day name itself is brand red — pulls the eye to the day-of-week
   as the most temporal piece of information on the dateline. The
   surrounding ", 10 May 2026" stays in muted italic. */
.hk-clock--special .hk-clock__date [data-day] {
  color: var(--color-brand);
}

/* CN typography swap on the italic serif date — the CN font has no
   italic, so we drop the italic style and let the family handle it. */
body.lang-cn .hk-clock--special .hk-clock__date {
  font-family: var(--font-cn);
  font-style: normal;
}

@media (prefers-reduced-motion: reduce) {
  .hk-clock--special .hk-clock__pulse,
  .hk-clock--special .hk-clock__pulse::before,
  .hk-clock--special .hk-clock__pulse::after,
  .hk-clock--special .hk-clock__colon--blink {
    animation: none;
    opacity: 1;
  }
  /* Hide the radar rings entirely under reduced motion — they
     have no purpose without their expansion animation. */
  .hk-clock--special .hk-clock__pulse::before,
  .hk-clock--special .hk-clock__pulse::after {
    display: none;
  }
}
