/* ── SHARED TOP STATUS BAR (Fraser 2026-06-01).
   Floating squared-off bar across the top of every page. Left: chrome
   blinking dot + live IP-localised clock. Centre: LOCKUP logo. Right:
   CONTACT mailto.

   This file is the SINGLE SOURCE OF TRUTH for the topbar styling.
   Any page that needs the topbar links this stylesheet + the
   lk-topbar.js companion (which injects the markup and ticks the
   clock). Update the visuals here and every page picks them up on
   next reload. */
.lk-topbar {
  position: fixed;
  top: calc(env(safe-area-inset-top) + 12px);
  left: 16px;
  right: 16px;
  height: 52px;
  z-index: 50;
  /* 3-col grid (1fr / auto / 1fr) so the LOCKUP logo sits exactly
     centred regardless of the clock/CONTACT widths. */
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 0 22px;
  box-sizing: border-box;
  background: rgba(0, 0, 0, 0.4);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  backdrop-filter: blur(20px) saturate(140%);
  border: 1px solid rgba(244, 240, 230, 0.14);
  border-radius: 6px;
  font-family: 'Courier New', Courier, monospace;
  color: #F4F0E6;
  user-select: none;
  -webkit-user-select: none;
  touch-action: manipulation;
}
.lk-topbar__time     { justify-self: start; }
.lk-topbar__logo     { justify-self: center; }
.lk-topbar__contact  { justify-self: end; }
.lk-topbar__right {
  justify-self: end;
  display: flex;
  align-items: center;
  /* Gap between CONTACT and the cart slot. When cart is hidden the
     slot collapses to width:0 and the gap is absorbed (flex gap is
     only painted between visible items). */
  gap: 14px;
}
.lk-topbar__cart {
  /* Hidden by default — slot collapses to width:0 so CONTACT sits
     flush with the topbar right padding. When .has-items is added
     (mirrored from the cart state — see lk-cart-ui.js), the slot
     transitions to its full width, sliding in from the right and
     pushing CONTACT to the left via the flex layout. */
  position: relative;
  display: flex; align-items: center; justify-content: center;
  background: transparent;
  border: 0;
  margin: 0; padding: 0;
  width: 0; height: 38px;
  overflow: hidden;
  color: inherit;
  opacity: 0;
  transform: translateX(14px);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition:
    width 0.36s cubic-bezier(0.22, 1, 0.36, 1),
    opacity 0.24s ease 0.04s,
    transform 0.36s cubic-bezier(0.22, 1, 0.36, 1);
}
.lk-topbar__cart svg {
  display: block;
  flex: 0 0 auto;
  opacity: 0.88;
  transition: opacity 0.18s ease;
}
.lk-topbar__cart:hover svg,
.lk-topbar__cart:focus-visible svg { opacity: 1; }
.lk-topbar__cart:focus-visible { outline: none; }
.lk-topbar__cart.has-items {
  /* Wider open width so the badge bubble has room above-right of the
     bag glyph without getting clipped by the topbar's rounded right
     corner or the right padding. (Fraser 2026-06-03.) */
  width: 32px;
  opacity: 1;
  transform: translateX(0);
}
.lk-topbar__cart-count {
  position: absolute;
  /* Tucked fully INSIDE the button bounds so neither the topbar's
     rounded corner nor the right padding can clip the badge. */
  top: 4px; right: 0;
  min-width: 14px; height: 14px;
  padding: 0 3px;
  border-radius: 999px;
  background: var(--ink-on-dark, #F4F0E6);
  color: #0a0a0a;
  font-family: 'Courier New', Courier, monospace;
  font-size: 9px;
  line-height: 14px;
  font-weight: bold;
  text-align: center;
  letter-spacing: 0;
  transform: scale(0);
  transform-origin: center;
  transition: transform 0.2s cubic-bezier(0.5, 1.8, 0.4, 1);
  box-sizing: border-box;
}
.lk-topbar__cart.has-items .lk-topbar__cart-count {
  transform: scale(1);
}
/* When the topbar is present, hide the legacy app-chrome cart icon so
   the cart only lives in the topbar slot. The legacy icon stays alive
   on pages that don't ship the topbar (the gate page, studio, etc.). */
body:has(.lk-topbar) .lk-appchrome-cart {
  display: none !important;
}
.lk-topbar__logo {
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  opacity: 0.92;
  transition: opacity 0.12s linear;
  -webkit-tap-highlight-color: transparent;
}
.lk-topbar__logo:hover,
.lk-topbar__logo:focus-visible {
  opacity: 1;
  outline: none;
}
.lk-topbar__logo img {
  height: 42px;
  width: auto;
  display: block;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6));
  transform-origin: center;
  transition: transform 0.25s cubic-bezier(.2,.8,.2,1);
}
/* Desktop + hover-capable only — logo scales up on hover. */
@media (min-width: 768px) and (hover: hover) {
  .lk-topbar__logo:hover img,
  .lk-topbar__logo:focus-visible img {
    transform: scale(1.14);
  }
}
@media (prefers-reduced-motion: reduce) {
  .lk-topbar__logo img { transition: none; }
}
.lk-topbar__time {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  letter-spacing: 0.18em;
  font-variant-numeric: tabular-nums;
}
.lk-topbar__clock {
  display: inline-block;
  min-width: 8ch;
}
.lk-topbar__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  /* Chrome — polished-metal radial gradient inside the 7px circle. */
  background:
    radial-gradient(circle at 30% 30%,
      #ffffff 0%,
      #d7dde5 38%,
      #6b7480 100%);
  box-shadow: 0 0 6px rgba(255, 255, 255, 0.55);
  animation: lkTopbarDotBlink 1.6s ease-in-out infinite;
}
@keyframes lkTopbarDotBlink {
  0%, 100% { opacity: 1;    transform: scale(1); }
  50%      { opacity: 0.35; transform: scale(0.85); }
}
.lk-topbar__contact {
  color: inherit;
  text-decoration: none;
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  padding: 8px 4px;
  -webkit-tap-highlight-color: transparent;
  transition: opacity 0.2s ease;
}
.lk-topbar__contact:hover,
.lk-topbar__contact:focus-visible {
  opacity: 0.7;
  outline: none;
}

/* ── PRODUCT-PAGE MOBILE PUSH ──────────────────────────────────────
   The topbar (top: safe-area + 12, height: 52) extends from
   safe-area + 12 to safe-area + 64. Add 16px gap and product
   content starts at safe-area + 80. Without this push, the topbar
   would overlap the framed print + product copy on phone widths.
   Desktop (≥561px) leaves the existing .product-page padding alone
   — there's plenty of vertical room and the topbar floats over the
   negative space at the top. */
/* Pulled tight to the topbar so the content (framed print + product
   info) is vertically centred between the topbar bottom and the X
   close button at the bottom-left. The topbar bottom edge sits at
   (safe-area + 64px); a 0px gap puts the content flush with it,
   matching the spacing left below the content above the X.
   Fraser 2026-06-01. */
@media (max-width: 560px) {
  .product-page {
    padding-top: calc(env(safe-area-inset-top) + 64px) !important;
  }
  /* Archive product pages — fewer spec rows than the store/print
     product pages, so MORE INFO ends up sitting higher than BUY does
     on the equivalent store page. Push the content down so the two
     CTAs land at the same vertical position. We identify archive
     product pages by the cmdbar's active index (2 = ARCHIVE);
     store/print pages have data-active="1". Fraser 2026-06-01.
     CLOSED state only (no .product-description.is-open) — when MORE
     INFO is expanded the page needs room to scroll the description
     into view above the X close button. */
  body:has(.lk-cmdbar[data-active="2"]):not(.lk-info-open) .product-page {
    padding-top: calc(env(safe-area-inset-top) + 85px) !important;
    padding-bottom: 0 !important;
  }
  /* OPEN state — MORE INFO expanded. Keep top push, but give bottom
     enough clearance for the last line to clear the X close button
     (which sits at cmdbar + safe + 20, height 44 → top at cmdbar +
     safe + 64). 110px buffer = X top + ~46px breathing gap. */
  body:has(.lk-cmdbar[data-active="2"]).lk-info-open .product-page {
    padding-top: calc(env(safe-area-inset-top) + 85px) !important;
    padding-bottom: calc(env(safe-area-inset-bottom) + var(--cmdbar-h, 52px) + 110px) !important;
  }
  /* Archive product pages on mobile: lock the page to the viewport
     so there's no scrollable area below the content, and disable
     iOS Safari's overscroll bounce so dragging up doesn't reveal
     an empty band underneath — but ONLY in the closed state. When
     MORE INFO is expanded, release the lock so the description can
     scroll. (Fraser 2026-06-01 / 2026-06-03 lock-release tweak —
     simplified from :has(.product-description.is-open) to body class
     so the cascade is unambiguous.) */
  html:has(body:has(.lk-cmdbar[data-active="2"]):not(.lk-info-open)),
  body:has(.lk-cmdbar[data-active="2"]):not(.lk-info-open) {
    height: 100vh !important;
    height: 100svh !important;
    overflow: hidden !important;
    overscroll-behavior: none !important;
  }
}
