/* ============================================================================
   Mindprint — the full-screen weave view (D83), shared by /patterns and /p/{key}.

   The pattern tiled edge to edge — the one place the repeat is allowed to run
   forever, because that endless field is what "seamless" means. Above everything,
   including the browser's sheet. Markup: Pages/Shared/_PatternZoom.cshtml; logic:
   js/pattern-zoom.js.
   ========================================================================== */

.pb-zoom {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: var(--mp-black);
  /* The open/close animation scales from the invoking artwork's rect, whose math
     assumes the top-left corner is the origin. */
  transform-origin: 0 0;
}

.pb-zoom[hidden] { display: none; }

.pb-zoom-field {
  position: absolute;
  inset: 0;
  background-repeat: repeat;
  cursor: move;
  outline: none;
  touch-action: none;
}

/* Doubled with the shell class because .hbtn.icon's own position: relative outranks a
   single class — the circle must pin to the corner, not flow. */
.pb-zoom .pb-zoom-close {
  position: absolute;
  top: max(14px, env(safe-area-inset-top));
  right: 14px;
  z-index: 2;
  background: rgba(12, 12, 16, .72);
  backdrop-filter: blur(6px);
}

/* The nameplate and the bottom instrument share one voice: the weave lens's own glass pill. */
.pb-zoom-name,
.pb-zoom-hint {
  z-index: 2;
  margin: 0;
  padding: 8px 14px;
  border: 1px solid var(--mp-line-soft);
  border-radius: var(--mp-r-pill);
  background: rgba(16, 16, 19, .76);
  color: var(--mp-dim);
  font-family: var(--mp-mono);
  font-size: 9px;
  letter-spacing: .1em;
  text-align: center;
  text-transform: uppercase;
  pointer-events: none;
  backdrop-filter: blur(7px);
}

.pb-zoom-name {
  position: absolute;
  top: max(14px, env(safe-area-inset-top));
  left: 14px;
  max-width: min(60vw, 420px);
  overflow: hidden;
  color: var(--mp-ink);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pb-zoom-name[hidden] { display: none; }

.pb-zoom-nav {
  position: absolute;
  z-index: 3;
  bottom: max(18px, env(safe-area-inset-bottom));
  left: 50%;
  display: flex;
  width: max-content;
  max-width: calc(100vw - 24px);
  align-items: center;
  gap: 8px;
  transform: translateX(-50%);
  /* Only the three controls take the pointer. The transparent rectangle around
     them must never steal the full field's pan/pinch gesture. */
  pointer-events: none;
}

.pb-zoom-hint {
  position: relative;
  display: flex;
  min-width: 0;
  min-height: 40px;
  max-width: calc(100vw - 28px);
  align-items: center;
  justify-content: center;
  line-height: 1.6;
  pointer-events: none;
}

.pb-zoom-nav[data-navigable="true"] .pb-zoom-hint {
  max-width: min(540px, calc(100vw - 124px));
  /* Room under the copy for the position track. */
  padding-bottom: 14px;
  cursor: ew-resize;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  pointer-events: auto;
}

.pb-zoom-nav.is-scrubbing .pb-zoom-hint {
  border-color: var(--mp-pink);
  color: var(--mp-ink);
  cursor: grabbing;
}

.pb-zoom-hint .solo,
.pb-zoom-hint .multi,
.pb-zoom-hint .coarse { display: none; }

.pb-zoom-nav[data-navigable="false"] .pb-zoom-hint .fine.solo,
.pb-zoom-nav[data-navigable="true"] .pb-zoom-hint .fine.multi { display: inline; }

/* Where in the sequence this pattern sits, drawn along the pill's own foot. It is the
   scrubbable width, so the fill is literally the distance the hand has left to travel. */
.pb-zoom-track {
  position: absolute;
  right: 12px;
  bottom: 5px;
  left: 12px;
  height: 2px;
  border-radius: 2px;
  background: var(--mp-line-soft);
  pointer-events: none;
}

.pb-zoom-nav[data-navigable="false"] .pb-zoom-track { display: none; }

.pb-zoom-track::after {
  position: absolute;
  border-radius: inherit;
  background: var(--mp-pink);
  content: "";
  inset: 0 auto 0 0;
  /* --at is the 0…1 position the shell writes after every move. */
  width: calc(var(--at, 0) * 100%);
  min-width: 2px;
  transition: width 120ms linear;
}

.pb-zoom-nav.is-scrubbing .pb-zoom-track::after { transition: none; }

@media (prefers-reduced-motion: reduce) {
  .pb-zoom-track::after { transition: none; }
}

/* The live position, over the instruction copy — see the note in _PatternZoom.cshtml. */
.pb-zoom-position {
  position: absolute;
  display: none;
  align-items: center;
  justify-content: center;
  color: var(--mp-ink);
  font-variant-numeric: tabular-nums;
  inset: 0;
  /* Matches the copy's own optical centre, which the track's clearance shifted up. */
  padding-bottom: 6px;
  pointer-events: none;
}

.pb-zoom-nav.is-scrubbing .pb-zoom-position { display: flex; }

.pb-zoom-nav.is-scrubbing .pb-zoom-hint .fine,
.pb-zoom-nav.is-scrubbing .pb-zoom-hint .coarse { visibility: hidden; }

/* The icon circles are the ordinary button system, with the same glass as the
   label they bracket. Disabled ends keep their space so the bar never jumps. */
.pb-zoom .pb-zoom-step {
  position: relative;
  flex: 0 0 40px;
  z-index: 1;
  background: rgba(16, 16, 19, .76);
  backdrop-filter: blur(7px);
  pointer-events: auto;
}

.pb-zoom .pb-zoom-step[hidden] { display: none; }

.pb-zoom .pb-zoom-step:disabled {
  opacity: .38;
  cursor: default;
}

.pb-zoom .pb-zoom-step svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

@media (hover: none), (max-width: 900px) {
  .pb-zoom-hint { min-height: 44px; }
  .pb-zoom .pb-zoom-step {
    width: 44px;
    height: 44px;
    flex-basis: 44px;
  }
  .pb-zoom-hint .fine { display: none !important; }
  .pb-zoom-nav[data-navigable="false"] .pb-zoom-hint .coarse.solo,
  .pb-zoom-nav[data-navigable="true"] .pb-zoom-hint .coarse.multi { display: inline; }
}

/* The page must not scroll behind the field — a wheel that zooms here and scrolls
   the wall there is two answers to one gesture. */
html.pb-zoom-open,
html.pb-zoom-open body { overflow: hidden; }
