/* The furniture. Fixed to the viewport, built once, never rebuilt. */

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- the name ---------- */

/* Two layers, both fixed and the size of the viewport — so every measurement
   inside them is in viewport pixels and the maths in wordmark.js needs no
   conversion.

   They are split by the glass. The rows sit *under* the bands, so the glyphs
   that leave are refracted on their way out; the lockup they leave behind comes
   to rest inside the top band, and under the glass it would be bent for good,
   so the three that gather are drawn again above. */
.wordmark,
.wordmark-lockup {
  position: fixed;
  inset: 0;
  pointer-events: none;
  color: var(--ink);
  font-size: var(--wordmark-size);
  line-height: var(--wordmark-leading);
  letter-spacing: var(--wordmark-track);
}

.wordmark { z-index: 9980; }          /* under the glass (9990) */
.wordmark-lockup { z-index: 9999; }   /* over it */

/* The originals stay in the flow, holding the rows' measure open, while their
   copies above the glass do the moving. visibility rather than display: the box
   has to keep its size or the line closes up around the hole. */
.wordmark-glyph.is-kept { visibility: hidden; }

.lock-glyph {
  position: absolute;
  display: inline-block;
  will-change: transform;
}
.lock-glyph.is-drawn { display: inline-flex; align-items: center; }

/* The three lines, centred on the screen. The middle one is the mark, and it is
   the line the other two close onto. */
.wordmark-stack {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--wordmark-gap);
  will-change: transform;
}

.wordmark-row {
  display: inline-flex;
  white-space: pre;
}

/* Cap height to baseline, which is how the design measures type: the box is the
   letter, with no room above the capitals or below the baseline. It is why the
   design's glyph boxes are 26px — the cap height of this face at 36px is 26.1 —
   and it is what lets a box centred in the bar put the *letter* in the middle
   rather than the letter plus its leading.

   Where it is not supported the boxes keep their leading and the lockup sits a
   pixel or two off centre in the bar; the mark below stays right either way,
   because it is hung from the baseline rather than centred in the box. */
.wordmark-glyph,
.lock-glyph {
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}

.wordmark-glyph {
  display: inline-block;
  will-change: transform, opacity;
}

/* The word space carries no glyph and is not one of the things that can be
   kept — it goes with the rest of the line. */
.wordmark-glyph.is-space { letter-spacing: 0; }

/* The drawn glyph hangs from the baseline rather than being centred in its box.
   Centred, it sat 1.8px below the letters beside it — the box it was centred in
   carries the descender space, and the letters do not use it. An empty
   inline-block takes its baseline from its bottom edge, so this puts the mark's
   foot on the line the letters stand on and its top at their cap height. */
.wordmark-glyph.is-drawn,
.lock-glyph.is-drawn { display: inline-block; vertical-align: baseline; }
.wordmark-glyph.is-drawn img,
.lock-glyph.is-drawn img {
  display: block;
  height: var(--cap);
  width: auto;
  /* The mark is a black drawing, and the layer it sits in is differenced. Type
     gets there by being painted white; an image has to be turned white first,
     or difference hands back white-on-white and the mark disappears. */
  filter: invert(1);
}

html[data-chrome="plain"] .wordmark-glyph.is-drawn img,
html[data-chrome="plain"] .lock-glyph.is-drawn img { filter: none; }

/* The case's name lives here rather than in the section: it has to travel from
   the middle of the opening screen to the top edge, and only something fixed
   can hold still while the page moves under it. */
.wordmark-case {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  will-change: transform, opacity;
}

.wordmark-case-text {
  white-space: nowrap;
  transform-origin: 50% 50%;
}

/* ---------- the face ---------- */

/* The whole navigation, at the bottom edge on the page's centre line. The
   drawing is injected by engine/face.js; everything that moves in it moves
   there, because a blink landing mid-glance has to blend with it. */
.face {
  position: fixed;
  left: 50%;
  bottom: calc(var(--face-bottom) + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  z-index: 10000;
  width: var(--face-size);
  height: var(--face-size);
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.face svg { display: block; width: 100%; height: 100%; }
/* The drawing paints itself black; letting it inherit instead is what lets the
   whole face invert over a dark frame with everything else. */
.face svg circle, .face svg ellipse, .face svg path { stroke: currentColor; }
.face svg ellipse { fill: currentColor; }
.face svg circle, .face svg path { fill: none; }

/* The drawing did not load. The button still works and still says what it is,
   so leave something round there rather than an empty square. */
.face.is-bare {
  border: 2px solid currentColor;
  border-radius: 50%;
}

/* ---------- the names ---------- */

/* Above the face, not along the top: the page's own lockup is up there, and the
   list is something you reach for at the bottom where your hand already is. */
.menu {
  position: fixed;
  left: 0; right: 0;
  bottom: calc(var(--face-bottom) + var(--face-size) + var(--menu-stand) + env(safe-area-inset-bottom, 0px));
  z-index: 9998;
  pointer-events: none;
}

.menu ul {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--line-gap);
  margin: 0; padding: 0;
  list-style: none;
}

.menu li {
  opacity: 0;
  transform: translateY(0.3em);
  transition: opacity 380ms var(--ease-out), transform 380ms var(--ease-out);
}

/* They arrive from the bottom up — the list grows out of the face, so the one
   nearest it is the one that lands first. */
html[data-menu="open"] .menu { pointer-events: auto; }
html[data-menu="open"] .menu li { opacity: 1; transform: none; }
.menu li:nth-last-child(1) { transition-delay: 40ms; }
.menu li:nth-last-child(2) { transition-delay: 80ms; }
.menu li:nth-last-child(3) { transition-delay: 120ms; }
.menu li:nth-last-child(4) { transition-delay: 160ms; }
.menu li:nth-last-child(5) { transition-delay: 200ms; }
.menu li:nth-last-child(n+6) { transition-delay: 240ms; }

.menu a {
  display: block;
  font-size: var(--wordmark-size);
  line-height: var(--wordmark-leading);
  letter-spacing: var(--wordmark-track);
  text-transform: uppercase;
  color: var(--ink);
}

/* While the names are up the lockup would sit among them. */
.wordmark,
.wordmark-lockup { transition: opacity 240ms var(--ease-out); }
html[data-menu="open"] .wordmark,
html[data-menu="open"] .wordmark-lockup { opacity: 0; }

/* ---------- glass ---------- */

/* Pure vertical refraction along both edges. The filter itself is built in
   engine/glass.js, which sizes the displacement map to the viewport. */
.glass {
  position: fixed;
  left: 0;
  width: 100%;
  height: var(--band-h, 8vh);
  /* Under the furniture, above everything the page draws. */
  z-index: 9990;
  pointer-events: none;
}

.glass--top { top: 0; }
.glass--bottom { bottom: 0; }

/* Safari path: no SVG displacement available, so soften the band towards the
   page instead of leaving a hard-edged blurred rectangle. */
.glass--fallback.glass--top {
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 30%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 0%, #000 30%, transparent 100%);
}
.glass--fallback.glass--bottom {
  -webkit-mask-image: linear-gradient(to top, #000 0%, #000 30%, transparent 100%);
          mask-image: linear-gradient(to top, #000 0%, #000 30%, transparent 100%);
}

#glass-defs { position: absolute; width: 0; height: 0; pointer-events: none; }

/* ---------- over whatever is underneath ---------- */

/* Every piece of furniture reads its own colour off what is behind it, and does
   so continuously rather than being told.

   White differenced against the backdrop is black over a light field and white
   over a dark one — and everything in between, per pixel, as the page moves
   under it. There is no threshold to keep in step with the artwork and no state
   to set: a letter lying half over a white margin and half over a photograph is
   right on both halves at once.

   Over the page's own #fafafa this lands at #050505 instead of the --ink
   #161616 — five values darker, which nobody can see. */
/* The blend goes on whichever element owns the stacking context, never on the
   text inside it. .menu is fixed and has a z-index, so it owns one: a link
   blending in there differences against its own group's backdrop, which is
   nothing at all, and comes back white on every background. The other three
   below are each the context-owning element already. */
.menu { mix-blend-mode: difference; }

.wordmark,
.wordmark-lockup,
.menu a,
.face {
  color: #fff;
  /* Type is not always painted through `color`: anything that sets
     -webkit-text-fill-color wins over it, and the rule is then ignored with no
     sign that it was. */
  -webkit-text-fill-color: #fff;
}

.wordmark,
.wordmark-lockup,
.face { mix-blend-mode: difference; }

/* Left as the way out: a layer that must not do this sets data-chrome="plain"
   and the furniture goes back to reading the ink token. */
html[data-chrome="plain"] .wordmark,
html[data-chrome="plain"] .wordmark-lockup,
html[data-chrome="plain"] .menu a,
html[data-chrome="plain"] .face {
  color: var(--ink);
  -webkit-text-fill-color: var(--ink);
}

html[data-chrome="plain"] .menu,
html[data-chrome="plain"] .wordmark,
html[data-chrome="plain"] .wordmark-lockup,
html[data-chrome="plain"] .face { mix-blend-mode: normal; }
