/* ============================================================================
   menu.css — THE MENU OVERLAY
   Card state `seal` #E3E8EE, filling the card's bounds (spec §6 "Menu overlay").

   There is NO horizontal nav bar anywhere on this site. Navigation is a
   full-card overlay, and the overlay IS the button: the Menu pill's own rect
   grows into the card.

   Markup contract, exactly as index.html ships it:

     <div class="menu" id="menu" hidden role="dialog" aria-modal="true" …>
       <nav aria-label="Site navigation">
         <button class="pill pill--close" id="menu-close">Close</button>
         <ul class="index">  <li><a><span class="num"><span class="name">
                                  <span class="desc"></a></li> ×10 </ul>
         <ul class="links">  <li><a> ×3 </ul>
         <span class="mark-rotated">this side up</span>
       </nav>
     </div>

   OPEN-STATE CONTRACT. js/menu.js removes `hidden`, then sets the open flag on
   the next frame; on close it clears the flag and re-applies `hidden` after
   --d-menu-close. Both `[data-live]` (the vocabulary the leaves use) and
   `[data-open]` are honoured so this file cannot be desynchronised from
   js/menu.js by a naming choice.

   Scroll is suppressed by ScrollEngine.suspend() — never by `overflow:hidden`,
   so there is no layout shift and no scrollbar-width jump.

   NOT OWNED HERE: `.pill` itself (css/chrome.css), `.mark-rotated`'s type and
   rotation (css/chrome.css). This file only places them on the tint.
   ========================================================================== */

.menu {
  /* The card's own rect, matching css/card.css. The overlay never lays out:
     it exists at final geometry from the first frame and grows by clip-path. */
  position: fixed;
  inset: 4.4svh 4.6vw;
  z-index: 5;

  /* Closed clip = the Menu pill's rect in the top-right corner. js/menu.js
     overwrites these four with the pill's measured rect; the fallbacks are the
     pill at --card-pad from the card's top and right edges, at its resting
     size, so the growth starts from the right place even before measurement. */
  --p-top: var(--card-pad);
  --p-right: var(--card-pad);
  --p-bottom: calc(100% - var(--card-pad) - 34px);
  --p-left: calc(100% - var(--card-pad) - 92px);

  /* Corner radius the growth lands on. Stated as 18px in the spec, which is
     the card's own radius at and below 1279px; expressed against --card-r so
     the overlay's corners agree with the card's at every breakpoint. */
  --menu-r: var(--card-r, 18px);

  background-color: var(--plate-carbon);
  color: var(--stencil);
  overflow: hidden;
  pointer-events: none;

  clip-path: inset(
    var(--p-top) var(--p-right) var(--p-bottom) var(--p-left) round 999px
  );

  /* Closing: 420 ms --e-fall, decisive. */
  transition:
    clip-path calc(var(--d-menu-close) * 1) var(--e-fall),
    background-color calc(var(--d-menu-close) * 1) var(--e-fall);
}

.menu[hidden] {
  display: none;
}

/* ── Open — the pill's rect grows into the card ─────────────────────────────
   border-radius 999px → 18px and the rect to the card's bounds over 620 ms
   --e-lay; background cross-fades #14161A → --plate-seal starting at 260 ms,
   i.e. 360 ms of colour inside 620 ms of geometry. */

.menu:is([data-live], [data-open]) {
  pointer-events: auto;
  background-color: var(--plate-seal);
  clip-path: inset(0 0 0 0 round var(--menu-r));
  transition:
    clip-path calc(var(--d-menu-open) * 1) var(--e-lay),
    background-color calc(var(--d-menu-open) * 1 - 260ms) var(--e-grade) 260ms;
}

/* Seal is one of the light grounds, so the overlay's ink is the light set. */
.menu {
  --on-plate: var(--stencil);
  --on-soft: var(--stencil-2);
  --on-rule: var(--rule);
}

/* ── Interior ────────────────────────────────────────────────────────────────
   Corner logic survives inside the overlay: close control top-right, the
   numbered index filling the middle, the three large links under a hairline,
   the number bottom-left, the rotated mark bottom-right. */

.menu nav {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  grid-template-areas:
    ".     close"
    "index index"
    "links links"
    "phone mark";
  align-content: start;
  padding: var(--card-pad);
  gap: var(--card-gap);
}

.menu .pill--close {
  grid-area: close;
  justify-self: end;
  align-self: start;
}

/* ── The numbered index of the ten product lines ───────────────────────────── */

.menu .index {
  grid-area: index;
  list-style: none;
  margin: 0;
  padding: 0;
  align-self: stretch;
  width: 100%;
  border-bottom: 1px solid var(--on-rule);

  /* The index row is minmax(0, 1fr). Nine rows are taller than that box on a
     short card, and a grid item does NOT clip to its area — so the list spilled
     downward and drew straight through the three large links beneath it.
     min-height:0 lets the track actually shrink, and the scroll keeps every
     line reachable instead of hidden under the links. */
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}

.menu .index > li {
  border-top: 1px solid var(--on-rule);
}

.menu .index a {
  display: grid;
  grid-template-columns: 2.9em minmax(0, auto) minmax(0, 1fr);
  align-items: baseline;
  column-gap: var(--s-4);
  padding-block: clamp(0.32rem, 0.55cqw, 0.6rem);
  text-decoration: none;
  color: var(--on-plate);
}

.menu .index .num {
  font-family: var(--f-label);
  font-variation-settings: "wdth" 76, "wght" 500;
  font-weight: 500;
  font-size: var(--t-num);
  letter-spacing: 0;
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--on-soft);
}

.menu .index .name {
  font-family: var(--f-display);
  font-variation-settings: "opsz" 16;
  font-weight: 400;
  font-size: var(--t-row);
  line-height: 1.14;
  letter-spacing: 0;
}

.menu .index .desc {
  font-family: var(--f-label);
  font-variation-settings: "wdth" 108, "wght" 400;
  font-size: var(--t-body);
  line-height: 1.3;
  color: var(--on-soft);
  text-align: right;
}

.menu .index a:hover .name,
.menu .index a:focus-visible .name {
  color: var(--seal-blue);
}

/* ── The three large Bodoni links ───────────────────────────────────────────
   Below the hairline the index already draws. --t-menu at "opsz" 72. */

.menu .links {
  grid-area: links;
  list-style: none;
  margin: 0;
  padding-block-start: clamp(0.75rem, 1.6cqw, 1.75rem);
  padding-inline: 0;
  display: grid;
  gap: 0;
  justify-items: start;
}

.menu .links a {
  display: inline-block;
  font-family: var(--f-display);
  font-variation-settings: "opsz" 72;
  font-weight: 400;
  font-size: var(--t-menu);
  line-height: 1.02;
  letter-spacing: -0.014em;
  color: var(--on-plate);
  text-decoration: none;
}

/* PHONE: THE ROWS HAVE TO BE THUMB-SIZED. --t-menu is capped against svh, so on
   a short phone the five rows came out 32px tall — under any reasonable target
   size, and this is the site's only navigation once the card fills the screen.
   Padding rather than a bigger type size: the display face is already as large
   as the viewport can carry, and what a thumb needs is the hit area, not the
   letters. `inline-block` above means vertical padding does add to the box.

   The hairline under each row is drawn by ::after on the same element, so it
   follows the padding down and keeps sitting under the word. */
@media (max-width: 560px), (max-height: 620px){
  .menu .links a{ padding-block: 7px }
}

/* The asymmetric hairline: grows from left-centre over 340 ms on hover,
   collapses from right-centre over 680 ms on leave — twice as long to withdraw
   as to offer. */
.menu .links a::after {
  content: "";
  display: block;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 680ms var(--e-roll);
}

.menu .links a:hover::after,
.menu .links a:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left center;
  transition-duration: 340ms;
}

/* ── The phone number ────────────────────────────────────────────────────────
   Bottom-left, set large as a `tel:` link. Currently withheld from index.html
   because content.company.js carries no digits — there is nothing honest to
   render — so these rules wait for the client's confirmation.

   NO LIVE DOT HERE. --film-red has exactly two uses on the entire site and
   both are on the carbon leaf. The overlay gets the number, not the dot. */

.menu .phone {
  grid-area: phone;
  align-self: end;
  margin: 0;
}

.menu .phone a {
  font-family: var(--f-label);
  font-variation-settings: "wdth" 76, "wght" 500;
  font-weight: 500;
  font-size: var(--t-quote);
  line-height: 1;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--on-plate);
  text-decoration: none;
}

.menu .phone a:hover {
  color: var(--seal-blue);
}

/* ── The mark persists on the tint, still upside down ───────────────────────
   Wholly aria-hidden: the card's own instance already carries the .sr-only
   clarification, and one joke read aloud once is enough. Type and rotation are
   css/chrome.css's; only the placement is decided here. */

.menu .mark-rotated {
  grid-area: mark;
  justify-self: end;
  align-self: end;
}

/* ── Row arrival ─────────────────────────────────────────────────────────────
   The ten index rows arrive opacity 0→1, blur(8px)→0 at --d-menu-stagger
   (34 ms), --d-menu-row (480 ms) each. The three large links follow at
   +140 ms behind the last row. Blur-into-focus, zero translate — the same
   signature the leaves use, so opening the menu belongs to the same system. */

@keyframes menu-row-in {
  from {
    opacity: 0;
    filter: blur(8px);
  }
  to {
    opacity: 1;
    filter: blur(0);
  }
}

.menu .index > li,
.menu .links > li,
.menu .phone {
  opacity: 0;
}

.menu:is([data-live], [data-open]) :is(.index, .links) > li,
.menu:is([data-live], [data-open]) .phone {
  animation: menu-row-in calc(var(--d-menu-row) * 1) var(--e-lay) both;
}

.menu .index > li:nth-child(1)  { animation-delay: calc(var(--d-menu-stagger) * 0) }
.menu .index > li:nth-child(2)  { animation-delay: calc(var(--d-menu-stagger) * 1) }
.menu .index > li:nth-child(3)  { animation-delay: calc(var(--d-menu-stagger) * 2) }
.menu .index > li:nth-child(4)  { animation-delay: calc(var(--d-menu-stagger) * 3) }
.menu .index > li:nth-child(5)  { animation-delay: calc(var(--d-menu-stagger) * 4) }
.menu .index > li:nth-child(6)  { animation-delay: calc(var(--d-menu-stagger) * 5) }
.menu .index > li:nth-child(7)  { animation-delay: calc(var(--d-menu-stagger) * 6) }
.menu .index > li:nth-child(8)  { animation-delay: calc(var(--d-menu-stagger) * 7) }
.menu .index > li:nth-child(9)  { animation-delay: calc(var(--d-menu-stagger) * 8) }
.menu .index > li:nth-child(10) { animation-delay: calc(var(--d-menu-stagger) * 9) }

/* last row starts at 9 × 34 ms; the links pick up 140 ms after it */
.menu .links > li:nth-child(1) { animation-delay: calc(var(--d-menu-stagger) * 9 + 140ms) }
.menu .links > li:nth-child(2) { animation-delay: calc(var(--d-menu-stagger) * 10 + 140ms) }
.menu .links > li:nth-child(3) { animation-delay: calc(var(--d-menu-stagger) * 11 + 140ms) }
.menu .phone                   { animation-delay: calc(var(--d-menu-stagger) * 12 + 140ms) }

/* ── Short and narrow viewports ─────────────────────────────────────────────
   Ten rows, three display links, a number and a mark do not fit a 600px-tall
   card. The descriptors are the first thing to go — every row is still a real
   link with a numeral and a name. Below that, the overlay is allowed to scroll
   itself; it is a dialog, not the card, and an unreachable tenth line is a
   worse failure than a scroll region. */

@media (max-width: 767px) {
  .menu {
    inset: 1.8svh 2.6vw;
    --menu-r: var(--card-r, 15px);
  }
  .menu .index a {
    grid-template-columns: 2.4em minmax(0, 1fr);
  }
  .menu .index .desc {
    display: none;
  }
}

@media (max-height: 660px) {
  .menu .index .desc {
    display: none;
  }
  .menu nav {
    grid-template-rows: auto auto auto auto;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}
