/* ══════════════════════════════════════════════════════════════════
   BOTTOM DOCK + SECTION HERO — shared by the interior pages
   (projects.html, about.html, ai-apps.html).

   The dock is the one index.html carries, minus the pieces that only make
   sense over the home hero: no notch (there is no framed stage edge to
   indent once these heroes have gone full bleed) and no hover preview (that
   is reserved for the home page — see js/dock.js).

   index.html still keeps its own inline copy, because its dock is wired into
   the hero's ambience, notch and handoff. Visual changes to the bar have to
   be made in both places.

   The frame tokens below match index's so the section hero opens from the
   exact rectangle the home stage occupies.
   ══════════════════════════════════════════════════════════════════ */
:root {
  --frame: 20px;
  --frame-bottom: 58px;
  --hero-bg: #2A3238;           /* index's frame colour */
  --stage-radius: var(--radius-xl);

  --dock-w-full: clamp(296px, 23vw, 352px);
  --dock-h-full: 48px;
  --dock-dur: 440ms;
  --dock-ease: cubic-bezier(0.4, 0, 0.2, 1);
  --dock-w-min: 120px;
  --dock-h-min: 24px;
  --ink-idle: rgba(255, 255, 255, 0.45);
  --ink-live: #fff;

  /* The section hero's open, from the framed stage out to full bleed. The
     same in-out curve as the blinds, so arriving by either route has the
     same weight. */
  --hero-bleed-dur: 1100ms;
  --hero-bleed-ease: cubic-bezier(0.65, 0.01, 0.3, 1);
}

@media (max-width: 767px) {
  :root {
    --frame: 12px;
    --frame-bottom: 64px;
    --dock-w-full: min(340px, calc(100vw - 2 * var(--frame) - 16px));
  }
}

/* ── DOCK ────────────────────────────────────────────────────────── */
.dock-wrap {
  /* Same screen position as on the home page, so the bar holds still across
     a navigation instead of jumping. Anchored by its centre: a percentage
     translate resolves against the live height, so collapsing never drifts. */
  position: fixed;
  left: 50%;
  bottom: var(--frame-bottom);
  translate: -50% 50%;
  z-index: 200;
  --dock-w: var(--dock-w-full);
  --dock-h: var(--dock-h-full);
  width: var(--dock-w);
  height: var(--dock-h);
  transition: width var(--dock-dur) var(--dock-ease),
              height var(--dock-dur) var(--dock-ease),
              border-radius var(--dock-dur) var(--dock-ease);
  border-radius: var(--radius-xl);
  overflow: hidden;
  background: linear-gradient(rgba(22, 22, 26, 0.72), rgba(10, 10, 12, 0.82));
  border: 1px solid;
  border-color: rgba(255, 255, 255, 0.34) rgba(255, 255, 255, 0.15)
                rgba(255, 255, 255, 0.07);
  box-shadow:
    inset 0 1px 0 0 rgba(255, 255, 255, 0.18),
    inset 0 -1px 0 0 rgba(255, 255, 255, 0.05),
    0 0 0 0.5px rgba(0, 0, 0, 0.25),
    0 24px 60px rgba(0, 0, 0, 0.3),
    0 6px 16px rgba(0, 0, 0, 0.16);
  /* Persistent chrome across navigations — see css/page-transition.css. */
  view-transition-name: site-dock;
}
.dock-wrap::before {
  content: '';
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 0;
  backdrop-filter: blur(14px) saturate(190%) brightness(0.9);
  -webkit-backdrop-filter: blur(14px) saturate(190%) brightness(0.9);
}
/* Specular sheen over the top edge. */
.dock-wrap::after {
  content: '';
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 50;
  background:
    radial-gradient(140% 70% at 50% -10%, rgba(255, 255, 255, 0.13), transparent 55%),
    linear-gradient(115deg, rgba(255, 255, 255, 0.07) 0%, transparent 20%,
                    transparent 80%, rgba(255, 255, 255, 0.04) 100%);
}

/* Scrolling down shrinks the bar to a pill; scrolling up or approaching it
   restores it. The buttons leave first and return last. */
.dock-wrap.is-collapsed {
  --dock-w: var(--dock-w-min);
  --dock-h: var(--dock-h-min);
  border-radius: calc(var(--dock-h-min) / 2 + 2px);
}
.dock-wrap.is-collapsed .dock {
  opacity: 0;
  pointer-events: none;
  transition: opacity 150ms var(--dock-ease);
}
.dock-wrap .dock { transition: opacity 260ms var(--dock-ease) 140ms; }

/* Holds the open size while the shell shrinks over it, so the row is laid
   out once rather than re-solved on every frame of the collapse. */
.dock {
  position: absolute;
  left: 50%; top: 50%;
  translate: -50% -50%;
  width: var(--dock-w-full);
  height: var(--dock-h-full);
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 3px;
  padding: 5px;
}

.dock-card {
  flex: 1 1 0;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  padding: 0 8px;
  border-radius: var(--radius-lg);
  border: 1px solid transparent;
  background: transparent;
  color: var(--ink-idle);
  font-family: inherit;
  text-decoration: none;
  cursor: pointer;
  overflow: hidden;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}
.dock-card:hover { background: rgba(255, 255, 255, 0.07); }
.dock-card:active { opacity: 0.7; transition-duration: 0.05s; }
.dock-card:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* Selected: the only white icon on the bar, and the only raised chip. */
.dock-card.is-active {
  color: var(--ink-live);
  background: rgba(255, 255, 255, 0.11);
  border-color: rgba(255, 255, 255, 0.25) rgba(255, 255, 255, 0.14)
                rgba(255, 255, 255, 0.14);
  box-shadow: inset 0 1px 0 0 rgba(255, 255, 255, 0.14);
}

.dock-icon {
  width: 18px; height: 18px;
  display: flex; align-items: center; justify-content: center;
  flex: none;
}
.dock-icon svg {
  width: 16px; height: 16px;
  stroke: currentColor; fill: none;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
/* A two-frame stutter on hover-in — a contact flicker, not an animation. */
.dock-icon.flicker { animation: dock-flicker 150ms steps(1, end) 1; }
@keyframes dock-flicker {
  0%, 100% { opacity: 1; }
  18%      { opacity: 0.25; }
  36%      { opacity: 1; }
  54%      { opacity: 0.45; }
  72%      { opacity: 1; }
}

.dock-label {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.01em;
  max-width: 0;
  opacity: 0;
  overflow: hidden;
  white-space: nowrap;
  color: currentColor;
}

/* The selected card is painted open from the FIRST frame, not when
   js/dock.js runs. That script loads after GSAP at the end of the body, so
   the page would otherwise paint all four cards closed and then pop the label
   out — a visible step right after arriving from the home page, whose dock is
   already showing this tab open. Values mirror EXPAND in js/dock.js, which
   takes over with the same numbers inline. */
.dock-card.is-active {
  flex-grow: 2.5;
  gap: 7px;
  padding-left: 14px;
  padding-right: 14px;
}
.dock-card.is-active .dock-label {
  max-width: none;
  opacity: 1;
}

/* ── SECTION HERO ────────────────────────────────────────────────────
   The destination photo the home dock previews on hover, opening from the
   home stage's framed rectangle out to full bleed, with the page title
   centred over it.

   clip-path, not a size or transform change on the box: it is paint-only,
   and it keeps object-fit:cover solved once against the final full-bleed
   size, so the photo never re-crops mid-open. The photo inside eases down
   from a slight zoom at the same time, which is what makes the open read as
   depth rather than a mask wipe.

   Arriving FROM the home hero (html.from-hero, stamped in <head>), index has
   already grown its stage to full bleed before navigating, so this starts
   where that ended and skips the open. */
.section-hero {
  background: var(--hero-bg);
}
.section-hero-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  clip-path: inset(0 0 0 0 round 0px);
  animation: section-hero-bleed var(--hero-bleed-dur) var(--hero-bleed-ease) 120ms both;
}
.section-hero-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  animation: section-hero-settle calc(var(--hero-bleed-dur) + 500ms) var(--ease-out) 120ms both;
}
/* The centred title sits over a bright photo (the Nepal sky, the whiteboards)
   and needs its own falloff; the bottom fades into the page ground so the
   content below does not start on a hard edge. */
.section-hero-veil {
  position: absolute;
  inset: 0;
  /* Measured against the whiteboard photo, the brightest of the three: the
     particle title only reads with an overall wash under the centre falloff. */
  background:
    radial-gradient(64% 54% at 50% 50%, rgba(2, 8, 12, 0.5), rgba(2, 8, 12, 0) 76%),
    linear-gradient(to bottom, rgba(2, 8, 12, 0.42) 0%, rgba(2, 8, 12, 0.5) 72%,
                    var(--color-bg) 100%);
}
/* The hero subtitle was set for a near-black wash; over a photo it needs full
   ink and a soft shadow to hold. */
.section-hero :is(.projects-sub, .about-sub, .page-sub) {
  color: var(--color-text-primary);
  text-shadow: 0 2px 24px rgba(0, 0, 0, 0.55);
}

@keyframes section-hero-bleed {
  from {
    clip-path: inset(var(--frame) var(--frame) var(--frame-bottom) var(--frame)
                     round var(--stage-radius));
  }
}
@keyframes section-hero-settle {
  from { transform: scale(1.06); }
}

.from-hero .section-hero-media,
.from-hero .section-hero-media img { animation: none; }

/* ── HOME RETURN OVERLAY ─────────────────────────────────────────────
   Built by js/dock.js when Home is tapped: this page's photo, full bleed,
   shrinking into the home stage's framed rect before navigating. Above all
   page content and the sticky tab bar, below the dock (200), which stays up
   through the move. The container is transparent until the photo is opaque,
   then takes the frame colour so the frame shows as the photo shrinks. */
.home-return {
  position: fixed;
  inset: 0;
  z-index: 150;
  pointer-events: none;
}
.home-return-media {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
.home-return-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* PAINT HOLDING — only for browsers without cross-document view transitions
   (html.hero-hold; Chrome and Safari use the hold-and-fade in
   css/page-transition.css instead). Arriving from the handoff, the old page's
   last frame is the photo at full bleed; painting before that photo is
   decoded would show the empty frame colour. Hiding the body leaves nothing
   contentful to paint, so the browser keeps the outgoing frame until the
   inline script by the hero image adds .hero-ready (decoded, or a 1.2s cap). */
.hero-hold:not(.hero-ready) body { visibility: hidden; }

@media (prefers-reduced-motion: reduce) {
  .section-hero-media,
  .section-hero-media img,
  .dock-icon.flicker { animation: none; }
  .dock-wrap, .dock-wrap .dock, .dock-card { transition-duration: 1ms; }
}
