/* ---------- floating / expandable bottom menu ---------- */

.menu, .menu *{
  box-sizing: border-box;
}
.menu a{
  color: inherit;
  text-decoration: none;
}

.menu{
  --menu-open-dur: 700ms;
  --menu-close-dur: 600ms;
  --menu-open-ease: cubic-bezier(.76,0,.24,1);
  --menu-content-delay: 130ms;
  --menu-item-stagger: 40ms;

  position: fixed;
  bottom: max(24px, env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%);
  z-index: 50;
  width: min(606px, calc(100vw - 32px));
  background: var(--menu-bg);
  border: 1px solid var(--menu-border);
  box-shadow: 0 20px 50px var(--menu-shadow);
  border-radius: 100px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  max-height: calc(100dvh - 24px - max(24px, env(safe-area-inset-bottom)));
  transition: border-radius var(--menu-open-dur) var(--menu-open-ease);
  font-family: var(--font-body);
}
.menu.is-open{
  border-radius: 24px;
  transition: border-radius var(--menu-close-dur) var(--menu-open-ease);
}

.menu-trigger{
  display: flex;
  width: 100%;
  align-items: center;
  gap: 12px;
  padding: 12px 20px;
  height: 48px;
  flex-shrink: 0;
  background: none;
  border: none;
  margin: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
  transition: height 0.2s ease, padding 0.2s ease;
}
.menu-trigger:focus-visible{
  outline: 2px solid var(--menu-accent);
  outline-offset: -2px;
}

.menu-logo, .menu-greeting{
  position: relative;
  overflow: hidden;
}
.menu-logo{
  display: flex;
  width: 24px;
  height: 24px;
  padding: 4px 0 5px 0;
  justify-content: center;
  align-items: center;
  flex-shrink: 0;
  aspect-ratio: 1/1;
  color: var(--menu-text);
}
.menu-greeting{
  flex: 1 1 0;
  min-width: 0;
  height: 20px;
}

/* icon swap: transform-only, full travel of its own wrapper height,
   logo/arrow move opposite direction to the text (up, vs text's down) */
.roll-face{
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  transform: translateY(0);
  transition: transform 400ms cubic-bezier(.76,0,.24,1);
  will-change: transform;
}
.menu-logo .roll-face{justify-content: center; inset: 4px 0 5px 0;}
.menu-logo .roll-face svg{width: 100%; height: 100%; display: block;}
.menu-logo .roll-face-hover{inset: 0;}
.roll-face-hover{transform: translateY(24px);}

.menu:not(.is-open) .menu-trigger:hover .roll-face-default,
.menu:not(.is-open) .menu-trigger:focus-visible .roll-face-default{
  transform: translateY(-24px);
}
.menu:not(.is-open) .menu-trigger:hover .roll-face-hover,
.menu:not(.is-open) .menu-trigger:focus-visible .roll-face-hover{
  transform: translateY(0);
}

/* text swap: each visible character gets its own clip + independent
   transform transition with a per-character stagger delay, producing
   a wave across the label instead of moving it as one rigid block.
   Direction is opposite to the icon: characters travel vertically
   within their own clip, default row exits downward, incoming row
   enters from above. */
.char-row{
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 500;
  line-height: normal;
  color: var(--menu-text);
  white-space: nowrap;
}
.char-clip{
  display: inline-block;
  overflow: hidden;
  height: 20px;
}
.char{
  display: inline-block;
  transform: translateY(0);
  transition: transform 350ms cubic-bezier(.76,0,.24,1);
  transition-delay: calc(var(--i, 0) * 20ms);
  will-change: transform;
}
.char-row-hover .char{transform: translateY(-100%);}

.menu:not(.is-open) .menu-trigger:hover .char-row-default .char,
.menu:not(.is-open) .menu-trigger:focus-visible .char-row-default .char{
  transform: translateY(100%);
}
.menu:not(.is-open) .menu-trigger:hover .char-row-hover .char,
.menu:not(.is-open) .menu-trigger:focus-visible .char-row-hover .char{
  transform: translateY(0);
}

.menu-current{
  display: flex;
  height: 24px;
  padding: 4px 12px;
  justify-content: center;
  align-items: center;
  gap: 10px;
  background: var(--menu-current-bg);
  color: var(--menu-current-text);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 500;
  line-height: 16px;
  border-radius: 100px;
  flex-shrink: 0;
  white-space: nowrap;
}

.menu-toggle{
  position: relative;
  width: 24px; height: 24px;
  flex-shrink: 0;
  color: var(--menu-text);
  transition: opacity 0.2s ease;
}
.menu.is-open .menu-trigger:hover .menu-toggle{opacity: 0.7;}
.menu-toggle svg{
  position: absolute;
  inset: 0;
  width: 24px; height: 24px;
  margin: auto;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.menu-toggle .icon-plus{opacity: 1; transform: rotate(0deg);}
.menu-toggle .icon-minus{opacity: 0; transform: rotate(-45deg);}
.menu.is-open .menu-toggle .icon-plus{opacity: 0; transform: rotate(45deg);}
.menu.is-open .menu-toggle .icon-minus{opacity: 1; transform: rotate(0deg);}

/* ---- open/close panel: JS measures natural content height vs the
   available viewport space and animates .menu-panel-wrap's height to
   that target. If content fits, height is released to 'auto' after
   the animation so it just hugs content with no scroll. If content
   doesn't fit, .menu-panel-wrap stays capped and .menu-panel-inner
   (the ONLY scrolling region) scrolls internally. ---- */
.menu-panel-wrap{
  height: 0;
  overflow: hidden;
  flex-shrink: 0;
  transition: height var(--menu-open-dur) var(--menu-open-ease);
}
.menu.is-open .menu-panel-wrap{
  transition: height var(--menu-close-dur) var(--menu-open-ease);
}
.menu-panel-inner{
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.menu-panel{
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 20px 20px 20px;
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.menu.is-open .menu-panel{
  opacity: 1;
  transform: translateY(0);
  transition-delay: var(--menu-content-delay);
}

.menu-panel-header{
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
}
.menu-panel-title{
  font-family: var(--font-body);
  font-size: 22px;
  font-weight: 500;
  color: var(--menu-text);
  line-height: normal;
}
.menu-talk-btn{
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  background: var(--menu-current-bg);
  color: var(--menu-current-text);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 500;
  line-height: 16px;
  padding: 4px 12px;
  border-radius: 100px;
  border: none;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
}
.talk-label{
  display: inline-block;
  transform: translateX(0);
  transition: transform 150ms ease-out;
}
.talk-icon-clip{
  position: relative;
  width: 0;
  height: 16px;
  margin-left: 0;
  overflow: hidden;
  flex-shrink: 0;
  transition: width 150ms ease-out, margin-left 150ms ease-out;
}
.talk-icon{
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 150ms ease-out, transform 150ms ease-out;
}

/* stage 1 (0-150ms) — box widens to 12px, gap appears, icon still hidden */
.menu-talk-btn.talk-stage-1 .talk-label,
.menu-talk-btn.talk-stage-2 .talk-label{
  transform: translateX(-4px);
}
.menu-talk-btn.talk-stage-1 .talk-icon-clip,
.menu-talk-btn.talk-stage-2 .talk-icon-clip{
  width: 12px;
  margin-left: 2px;
}
/* stage 2 (150-300ms) — holds at 12px, the pause before the icon reveals */

/* stage 3 (300ms+) — the icon reveals straight into its final resting
   spot: gap tightens to 2px (same margin-left the hidden stages were
   already at, so there's no back-and-forth) and the button's own
   padding-right is left alone at its resting 12px the whole time —
   one continuous motion instead of landing wide and correcting
   afterward, which read as two separate, jarring steps. The label's
   -4px shift also releases back to 0 here in the same motion. */
.menu-talk-btn.talk-stage-3 .talk-icon-clip{
  width: 8px;
  margin-left: 2px;
}
.menu-talk-btn.talk-stage-3 .talk-icon{
  opacity: 1;
  transform: translateY(0);
}
.menu-talk-btn:focus-visible{
  outline: 2px solid var(--menu-accent);
  outline-offset: 2px;
}

.menu-list{
  display: flex;
  flex-direction: column;
  padding: 8px 0;
}
.menu-list-item{
  position: relative;
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 8px 8px;
  margin: 0 -8px;
  border-top: 1px solid var(--menu-divider);
  border-bottom: 1px solid var(--menu-divider);
  margin-top: -1px;
  text-align: left;
  opacity: 0;
  transform: translateY(8px);
  /* opacity/transform here are the menu-open reveal animation, unrelated
     to hover (see the ::before below for the hover highlight itself) */
  transition: opacity 0.3s ease, transform 0.3s ease;
}
/* hover highlight as a separate layer, faded via opacity instead of
   animating background-color directly: background-color is a repaint
   on every frame, while opacity (like the label's transform below) is
   handled on the compositor — mixing a repainted property with a
   composited one caused stutter no matter the duration/easing.
   Duration/easing themselves are the actual Figma interaction spec
   (While hovering -> Smart animate, Gentle, 800ms), read from the
   prototype's inspector — see --menu-item-hover-* in variables.css. */
.menu-list-item::before{
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1; /* sits behind the (non-positioned) thumb/label content */
  background: var(--menu-hover-bg);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--menu-item-hover-duration) var(--menu-item-hover-ease);
}
.menu-list-item:not(.is-current):hover::before,
.menu-list-item:not(.is-current):focus-visible::before{
  opacity: 1;
}
.menu.is-open .menu-list-item{opacity: 1; transform: translateY(0);}
/* the hover highlight now lives on ::before (its own element, own
   transition, unaffected by this), so .menu-list-item's own
   transition list is just the reveal's opacity+transform — a single
   delay value is enough here again */
.menu.is-open .menu-list-item:nth-child(1){transition-delay: calc(var(--menu-content-delay) + var(--menu-item-stagger) * 1);}
.menu.is-open .menu-list-item:nth-child(2){transition-delay: calc(var(--menu-content-delay) + var(--menu-item-stagger) * 2);}
.menu.is-open .menu-list-item:nth-child(3){transition-delay: calc(var(--menu-content-delay) + var(--menu-item-stagger) * 3);}
.menu.is-open .menu-list-item:nth-child(4){transition-delay: calc(var(--menu-content-delay) + var(--menu-item-stagger) * 4);}
.menu-list-item .thumb{
  width: 64px;
  height: 48px;
  flex-shrink: 0;
  background-size: cover;
  background-position: center;
}
.menu-list-item .label{
  font-family: var(--font-body);
  font-size: 24px;
  font-weight: 400;
  line-height: normal;
  color: var(--menu-text);
  flex: 1 1 0;
  transform: translateX(0);
  /* matches the row highlight's timing above — both sourced from the
     same Figma interaction (Smart animate, Gentle, 800ms) */
  transition: color var(--menu-item-hover-duration) var(--menu-item-hover-ease),
              transform var(--menu-item-hover-duration) var(--menu-item-hover-ease);
}
.menu-list-item.is-current .label{color: var(--menu-text-muted);}

/* hover: the thumbnail stays put at 64x48 — the label just nudges
   12px right (same move as the footer social links). Excludes the
   current-page item entirely — it's not a navigable action, so it
   gets no hover feedback at all, same as its background above. */
.menu-list-item:not(.is-current):hover .label,
.menu-list-item:not(.is-current):focus-visible .label{
  transform: translateX(12px);
  color: var(--menu-text);
}

/* section thumbnails — real image where we have one, gradient
   placeholder otherwise until the rest come in */
.menu-list-item[data-section="hero"] .thumb{background-image: url('../img/menu-thumb-homepage.jpg');}
.menu-list-item[data-section="work"] .thumb{background-image: url('../img/menu-thumb-works.jpg');}
.menu-list-item[data-section="experiments"] .thumb{background-image: url('../img/menu-thumb-experiments.jpg');}
.menu-list-item[data-section="about"] .thumb{background-image: url('../img/menu-thumb-about.jpg');}

.menu-footer{
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
}
.menu-social{
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.menu-social a{
  display: inline-block;
  font-family: var(--font-body);
  font-size: 15px;
  color: var(--menu-text);
  padding: 4px 0;
  transform: translateX(0);
  /* matches the Figma interaction: While hovering -> Smart animate, Linear, 300ms */
  transition: color 300ms linear, transform 300ms linear;
}
.menu-social a:hover,
.menu-social a:focus-visible{
  color: var(--menu-text-muted);
  transform: translateX(12px); /* the 12px nudge shown in the hover-state redline */
}
.menu-close-btn{
  flex-shrink: 0;
  width: 24px; height: 24px;
  display: flex; align-items: center; justify-content: center;
  background: none;
  border: none;
  color: var(--menu-text);
  cursor: pointer;
  padding: 0;
}
.menu-close-btn svg{width: 24px; height: 24px;}
.menu-close-btn:hover{opacity: 0.7;}

/* the top trigger bar disappears once open — the close control lives
   at the bottom next to the last social link, matching the design */
.menu.is-open .menu-trigger{
  height: 0;
  padding-top: 0;
  padding-bottom: 0;
  overflow: hidden;
  pointer-events: none;
}

@media (max-width: 720px){
  .menu-panel-title{font-size: 17px;}
  .char-row{font-size: 14px;}
}

@media (prefers-reduced-motion: reduce){
  .menu, .menu *{
    transition: none !important;
    animation: none !important;
  }
}
