/* The Path, in miniature: the header corner mark becomes a way into the Code page.
   A line draws itself onto the crosshair and the rust dot (you) pulses where it lands. */
body.portfolio-page .code-beacon {
  position: absolute;
  top: 0;
  right: -6px;
  width: 52px;
  height: 44px;
  display: grid;
  place-items: center;
  color: var(--ink);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.code-beacon svg {
  display: block;
  width: 40px;
  height: 24px;
  overflow: visible;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
}
.code-beacon .cb-ghost {
  stroke-width: 1;
  opacity: .22;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: cb-ghost 3.6s cubic-bezier(.55, 0, .25, 1) infinite;
}
.code-beacon .cb-ghost:nth-of-type(2) { animation-delay: -.35s; }
.code-beacon .cb-ghost:nth-of-type(3) { animation-delay: -.7s; }
.code-beacon .cb-cross { stroke-width: 1; stroke-linecap: butt; }
.code-beacon .cb-line {
  stroke-width: 1.4;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: cb-draw 3.6s cubic-bezier(.55, 0, .25, 1) infinite;
}
.code-beacon .cb-dot { fill: var(--accent); stroke: none; }
.code-beacon .cb-ring {
  stroke: var(--accent);
  stroke-width: 1;
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0;
  animation: cb-ring 3.6s ease-out infinite;
}
.code-beacon .cb-label {
  position: absolute;
  top: calc(100% - 2px);
  right: 6px;
  color: var(--accent);
  font: 500 10px/1 "Portfolio Mono", "IBM Plex Mono", ui-monospace, monospace;
  letter-spacing: .08em;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(-3px);
  transition: opacity 180ms ease, transform 180ms ease;
  pointer-events: none;
}
.code-beacon:hover .cb-label,
.code-beacon:focus-visible .cb-label { opacity: 1; transform: none; }
.code-beacon:hover .cb-line,
.code-beacon:focus-visible .cb-line { animation-duration: 1.8s; }
.code-beacon:hover .cb-ring,
.code-beacon:focus-visible .cb-ring,
.code-beacon:hover .cb-ghost,
.code-beacon:focus-visible .cb-ghost { animation-duration: 1.8s; }
.code-beacon:focus-visible { outline: 1px solid var(--ink); outline-offset: 2px; }

@keyframes cb-draw {
  0% { stroke-dashoffset: 1; opacity: 1; }
  45%, 82% { stroke-dashoffset: 0; opacity: 1; }
  96%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes cb-ghost {
  0% { stroke-dashoffset: 1; opacity: .22; }
  50%, 84% { stroke-dashoffset: 0; opacity: .22; }
  98%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes cb-ring {
  0%, 42% { transform: scale(1); opacity: 0; }
  46% { transform: scale(1); opacity: .9; }
  80%, 100% { transform: scale(3.6); opacity: 0; }
}

/* The click: the page's paths are drawn into the beacon, then the Code page opens out of it.
   Cross-document view transitions; js/code-beacon.js skips every one but the beacon's. */
@view-transition { navigation: auto; }
.code-beacon-trail {
  position: fixed;
  inset: 0;
  z-index: 2147483000;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

@media (min-width: 701px) {
  body.portfolio-page .header:has(.code-beacon) nav { padding-right: 64px; }
}
@media (max-width: 700px) {
  body.portfolio-page .code-beacon { top: -6px; right: -10px; }
}
@media (prefers-reduced-motion: reduce) {
  .code-beacon .cb-line { animation: none; stroke-dashoffset: 0; }
  .code-beacon .cb-ghost { animation: none; stroke-dashoffset: 0; }
  .code-beacon .cb-ring { animation: none; }
  .code-beacon .cb-label { transition: none; }
}
