/* The walkable 3D view of a parcel (the viewer plan). One frame holding the
   canvas, a message that stands in for it while loading or when it cannot be
   drawn, and a joystick zone that only a touch screen sees. */

.viewer {
  margin: 0 0 2.5rem;
}

.viewer__heading {
  font-size: 1.1rem;
  margin: 0 0 0.75rem;
}

.viewer__frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
}

@media (max-width: 40rem) {
  .viewer__frame {
    aspect-ratio: 4 / 5;
  }
}

.viewer__canvas {
  display: block;
  width: 100%;
  height: 100%;
  /* The scene owns every touch on it: one finger orbits and two zoom, and the
     page must not scroll underneath (OrbitControls sets this inline too). */
  touch-action: none;
  outline: none;
  cursor: grab;
}

/* An outline, drawn inward: an inset box-shadow is painted under a canvas's
   own content, and the scene is opaque, so it never showed. */
.viewer__canvas:focus-visible {
  outline: 3px solid var(--sand);
  outline-offset: -3px;
}

.viewer__frame[data-viewer-state="ready"] .viewer__canvas:active {
  cursor: grabbing;
}

/* The message covers the canvas while there is nothing to see (R14): a
   loading placeholder, or the sentence that says the view could not be drawn.
   Hidden once the scene is ready. */
.viewer__message {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  margin: 0;
  padding: 1rem 2rem;
  text-align: center;
  color: var(--ink-muted);
  background: var(--surface-raised);
}

.viewer__frame[data-viewer-state="loading"] .viewer__message::before {
  content: "";
  display: block;
  width: 2rem;
  height: 2rem;
  margin: 0 auto 0.75rem;
  border: 3px solid var(--border);
  border-top-color: var(--sand);
  border-radius: 50%;
  animation: viewer-spin 1s linear infinite;
}

@keyframes viewer-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .viewer__frame[data-viewer-state="loading"] .viewer__message::before {
    animation: none;
  }
}

.viewer__frame[data-viewer-state="ready"] .viewer__message {
  display: none;
}

/* The joystick zone: a corner of the frame that only a touch screen gets, and
   only once there is a scene to steer (U6 of the viewer plan). Sits beside the
   canvas in the stacking order so a finger on it never reaches OrbitControls. */
.viewer__joystick {
  display: none;
  position: absolute;
  left: 0;
  bottom: 0;
  width: 45%;
  height: 45%;
  touch-action: none;
}

@media (pointer: coarse) {
  .viewer__frame[data-viewer-state="ready"] .viewer__joystick {
    display: block;
  }
}

/* The instruments over the canvas: compass across the top, the readout in the
   bottom-right corner (the joystick has the bottom-left on a phone), and the
   ground button in the top-right. All of them wait for the scene, like the
   joystick does, so nothing floats over the loading message. Pointer events
   pass through the compass and the readout to the canvas beneath. */
.viewer__compass,
.viewer__coordinates,
.viewer__ground {
  display: none;
  position: absolute;
  font-family: ui-monospace, "Cascadia Mono", "Roboto Mono", Menlo, Consolas, monospace;
  font-size: 0.85rem;
  color: #f2e2d6;
}

.viewer__frame[data-viewer-state="ready"] .viewer__compass,
.viewer__frame[data-viewer-state="ready"] .viewer__coordinates {
  display: block;
  pointer-events: none;
}

.viewer__frame[data-viewer-state="ready"] .viewer__ground:not([hidden]) {
  display: inline-block;
}

.viewer__compass {
  top: 0.75rem;
  left: 50%;
  width: min(460px, 60%);
  transform: translateX(-50%);
  text-align: center;
}

.viewer__compass-strip {
  position: relative;
  height: 2.1rem;
  overflow: hidden;
  background: rgba(28, 18, 15, 0.65);
  border-radius: 6px;
}

.viewer__cardinal {
  position: absolute;
  top: 0;
  left: 50%;
  width: 3.2rem;
  height: 100%;
  margin-left: -1.6rem;
  line-height: 2.1rem;
  font-size: 0.85rem;
  color: #c4967e;
  text-align: center;
}

.viewer__cardinal--major {
  font-size: 1.15rem;
  font-weight: 600;
  color: #f2e2d6;
}

.viewer__cardinal[hidden] {
  display: none;
}

.viewer__compass-tick {
  position: absolute;
  top: 0;
  left: 50%;
  width: 2px;
  height: 100%;
  margin-left: -1px;
  background: #f2e2d6;
}

.viewer__bearing {
  display: inline-block;
  margin-top: 0.3rem;
  padding: 0.1rem 0.5rem;
  color: #f2e2d6;
  background: rgba(28, 18, 15, 0.65);
  border-radius: 4px;
}

.viewer__coordinates {
  right: 0.75rem;
  bottom: 0.75rem;
  max-width: calc(100% - 1.5rem);
  padding: 0.5rem 0.75rem;
  background: rgba(28, 18, 15, 0.75);
  border-radius: 6px;
  text-align: right;
}

.viewer__coordinates-place {
  display: block;
  font-family: inherit;
  font-weight: 600;
}

/* A holder's name is a name, not a reading, so it is set in the page's face. */
.viewer__coordinates-ownership {
  display: block;
  font-family: system-ui, sans-serif;
  overflow-wrap: anywhere;
}

/* Shared ground has no holder, and the next block's ground has no label. */
.viewer__coordinates-place:empty,
.viewer__coordinates-ownership:empty {
  display: none;
}

.viewer__coordinates-offset {
  display: block;
  /* The two readings are set apart by spaces the way a bearing is padded with
     zeros: the columns stay put as the numbers change. */
  white-space: pre;
}

.viewer__ground {
  top: 0.75rem;
  right: 0.75rem;
  padding: 0.4rem 0.7rem;
  font-family: inherit;
  font-size: 0.85rem;
  color: #f2e2d6;
  background: rgba(28, 18, 15, 0.75);
  border: 1px solid rgba(242, 226, 214, 0.35);
  border-radius: 6px;
  cursor: pointer;
}

.viewer__ground:hover,
.viewer__ground:focus-visible {
  border-color: #f2e2d6;
}

.viewer__ground[disabled] {
  cursor: progress;
  opacity: 0.7;
}

/* Under 40rem the frame is 4:5 and the compass, the button and the readout
   would meet: the button drops under the compass and the compass narrows. */
@media (max-width: 40rem) {
  .viewer__compass {
    width: min(300px, 55%);
    left: 0.75rem;
    transform: none;
  }

  .viewer__ground {
    /* Below the compass strip and the bearing under it. */
    top: 4.75rem;
    font-size: 0.75rem;
  }
}

.viewer__caption {
  margin: 0.75rem 0 0;
  font-size: 0.9rem;
  color: var(--ink-muted);
}

.viewer__help {
  margin: 0.5rem 0 0;
  font-size: 0.9rem;
  color: var(--ink-muted);
}

.viewer__help summary {
  color: var(--sand);
  cursor: pointer;
  font-weight: 600;
  width: fit-content;
}

.viewer__help p {
  margin: 0.5rem 0 0;
  max-width: 46rem;
}

/* Touch help where the pointer is coarse, key help where it is fine; a device
   with both kinds shows both. */
.viewer__help-touch {
  display: none;
}

@media (any-pointer: coarse) {
  .viewer__help-touch {
    display: block;
  }
}

@media not (any-pointer: fine) {
  .viewer__help-keys {
    display: none;
  }
}

/* The fence colours, stated once here and once in fences.js: the same three
   the catalog uses for the same three statuses. */
.viewer__key {
  padding: 0 0.35em;
  border-bottom: 2px solid;
  white-space: nowrap;
}

.viewer__key--available { border-color: rgba(242, 236, 231, 0.6); }
.viewer__key--held { border-color: rgba(226, 122, 76, 0.95); }
.viewer__key--company-held { border-color: rgba(216, 161, 92, 0.95); }
