/* Compact Equipment Sales — 360° viewer (app/viewer.js). Every class is prefixed "v-". Dark, rounded-square controls (see styles.css).
   Reads the shell's tokens when present and falls back to the design direction's values. */

/* ===== DESIGN TOKENS — viewer constants ===== */
:root {
  --v-btn: 44px;          /* dock buttons */
  --v-hot: 34px;          /* hotspot "+" */
  --v-xfade: 140ms;       /* frame crossfade */
  --v-plate: #ecebe8;     /* soft light plate behind legacy photos shot on white (~#f9f9f9 backgrounds) */
}

/* ===== DESIGN TOKENS — mapped from the shell (resolved where the viewer sits) ===== */
.v-root {
  --v-accent: var(--accent, #ff0000);
  --v-text: var(--text, #f5f5f4);
  --v-muted: var(--text-muted, #a1a1aa);
  --v-raised: var(--raised, #232326);
  --v-raised-hi: var(--raised-hi, #34343a);
  --v-line: var(--hairline, rgba(255, 255, 255, .06));
  --v-dur: var(--dur, 180ms);
  --v-ease: var(--ease, cubic-bezier(.2, .7, .2, 1));
  --v-font: var(--font-sans, system-ui, -apple-system, "Segoe UI", sans-serif);
}

/* ===== LAYOUT ===== */
.v-root {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  min-height: 0;
  font-family: var(--v-font);
  color: var(--v-text);
  -webkit-tap-highlight-color: transparent;
}
.v-view {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.v-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;      /* JS sets exact px; this keeps the shape before the first measure */
  flex: none;
  touch-action: pan-y;      /* horizontal drags rotate, vertical swipes still scroll the page */
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
.v-measure .v-stage { position: absolute; }
.v-grab .v-stage { cursor: grab; }
.v-grab.is-dragging .v-stage { cursor: grabbing; }

/* ===== FRAMES ===== */
.v-frame { position: absolute; inset: 0; }
.v-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  pointer-events: none;
  -webkit-user-drag: none;
  transition: opacity var(--v-xfade) ease-out;
}
.v-img:not([src]) { visibility: hidden; }
.v-img.is-on { opacity: 1; z-index: 2; }
.v-img.is-out { z-index: 1; transition-delay: 50ms; }   /* old frame lingers a beat so cutouts never dip */
/* Spin frames carry ~20% margin; zoom them so the machine fills the stage (app/viewer.js maps hotspots the same way). */
.v-spin .v-frame { transform: scale(var(--v-zoom, 1.32)); transform-origin: 50% 54%; }
.v-spin .v-shadow { top: 96%; width: 96%; }
.v-spin .v-view { overflow: clip; }     /* the zoomed frame layer must never widen the page */

/* Ground: a faint pool of light with a dark contact shadow, so cutouts sit on something. */
.v-shadow {
  position: absolute;
  left: 50%;
  top: 87%;
  width: 84%;
  height: 14%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  opacity: 0;
  transition: opacity 250ms ease-out;
  background:
    radial-gradient(34% 22% at 50% 50%, rgba(0, 0, 0, .9), rgba(0, 0, 0, .45) 55%, transparent 100%),
    transparent;
}
.v-spin.is-ready .v-shadow { opacity: 1; }

/* Legacy photos on white: a soft light plate; "darken" keeps the plate wherever the JPG is lighter, so no seam. */
.v-photos .v-frame {
  inset: 2% 3%;
  border-radius: 14px;
  background: var(--v-plate);
  overflow: hidden;
  isolation: isolate;
  box-shadow: 0 24px 48px -28px rgba(0, 0, 0, .8);
  transition: opacity 250ms ease-out;
}
.v-photos:not(.is-ready) .v-frame { opacity: .06; }
.v-photos .v-img { mix-blend-mode: darken; }

/* Attachments without photos: the line drawing, large and centered. */
.v-icon { display: none; }
.v-icon-mode .v-icon {
  display: block;
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(44%, 240px);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  color: var(--v-muted);
}
.v-icon-mode .v-icon::before {
  content: "";
  position: absolute;
  inset: -30%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 255, 255, .06), transparent);
}
.v-icon svg { position: relative; display: block; width: 100%; height: 100%; }

/* Quiet loading state (no spinner). */
.v-skel {
  position: absolute;
  left: 50%;
  top: 56%;
  width: 54%;
  height: 44%;
  transform: translate(-50%, -50%);
  border-radius: 14px;
  background: linear-gradient(100deg, rgba(255, 255, 255, .025) 35%, rgba(255, 255, 255, .07) 50%, rgba(255, 255, 255, .025) 65%) 0 0 / 300% 100%;
  animation: v-shimmer 1.8s linear infinite;
  transition: opacity 250ms ease-out, visibility 0s linear 250ms;
}
.is-ready .v-skel, .v-icon-mode .v-skel, .v-empty .v-skel { opacity: 0; visibility: hidden; animation: none; }
@keyframes v-shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }

/* ===== HOTSPOTS ===== */
.v-hots {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  transition: opacity var(--v-dur) var(--v-ease), visibility 0s;
}
.v-root:not(.is-ready) .v-hots, .v-hots-off .v-hots, .is-dragging .v-hots, .is-spinning .v-hots {
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--v-dur) var(--v-ease), visibility 0s linear var(--v-dur);
}
.v-hot {
  position: absolute;
  width: var(--v-hot);
  height: var(--v-hot);
  margin: calc(var(--v-hot) / -2) 0 0 calc(var(--v-hot) / -2);
  padding: 0;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .45);
  background: rgba(16, 16, 18, .38);
  color: #fff;
  opacity: .85;             /* see-through enough to keep the machine visible under it */
  box-shadow: 0 4px 12px rgba(0, 0, 0, .25);
  cursor: pointer;
  pointer-events: auto;
  touch-action: manipulation;
  transition: opacity var(--v-dur) var(--v-ease), visibility 0s, background-color var(--v-dur), color var(--v-dur), border-color var(--v-dur), transform var(--v-dur) var(--v-ease);
}
.v-hot::before {            /* bigger invisible hover target: pointing near the part is enough */
  content: "";
  position: absolute;
  inset: -16px;
  border-radius: 50%;
}
.v-hot::after {             /* soft pulse ring */
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .4);
  pointer-events: none;
  animation: v-pulse 2.6s ease-out infinite;
}
.v-hot.is-open::after { animation: none; opacity: 0; }
.v-hot-i { display: grid; place-items: center; transition: transform var(--v-dur) var(--v-ease); }
.v-hot svg { width: 15px; height: 15px; }
.v-hot:focus-visible { opacity: 1; }
.v-hot.is-open { opacity: 1; background: var(--v-text); color: #0a0a0b; border-color: var(--v-text); }
.v-hot.is-open .v-hot-i { transform: rotate(45deg); }        /* "+" turns into "×" */
.v-hot.is-off { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity var(--v-dur), visibility 0s linear var(--v-dur); }
@media (hover: hover) {
  .v-hot:hover { opacity: 1; transform: scale(1.08); border-color: #fff; }
  .v-hot:not(.is-open):hover { background: rgba(40, 40, 44, .75); }
}
@keyframes v-pulse { 0% { transform: scale(1); opacity: .7; } 70%, 100% { transform: scale(1.65); opacity: 0; } }

.v-pop {
  position: absolute;
  z-index: 4;
  left: 0;
  top: 0;
  width: max-content;
  max-width: min(260px, calc(100% - 16px));
  padding: 12px 14px 13px;
  border-radius: 12px;
  background: rgba(28, 28, 31, .97);
  border: 1px solid rgba(255, 255, 255, .09);
  box-shadow: 0 18px 40px -12px rgba(0, 0, 0, .75);
  color: var(--v-text);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: scale(.96);
  transition: opacity var(--v-dur) var(--v-ease), transform var(--v-dur) var(--v-ease), visibility 0s linear var(--v-dur);
}
.v-pop.is-open { opacity: 1; visibility: visible; pointer-events: auto; transform: none; transition-delay: 0s; }
.v-pop-t { display: block; font-size: 14px; font-weight: 700; line-height: 1.3; letter-spacing: -.005em; }
.v-pop-x { margin: 4px 0 0; font-size: 13px; line-height: 1.45; color: var(--v-muted); }
/* The numbers behind the highlight (from the spec sheet; rounded, or exact when Exact is on). */
.v-pop-f { display: grid; gap: 5px; margin: 10px 0 0; padding-top: 10px; border-top: 1px solid rgba(255, 255, 255, .09); }
.v-pop-f[hidden] { display: none; }
.v-pop-f > div { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
.v-pop-f dt { font-size: 12.5px; color: var(--v-muted); }
.v-pop-f dd { margin: 0; font-size: 14px; font-weight: 700; color: var(--v-text); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ===== HINT ===== */
.v-hint {
  position: absolute;
  left: 50%;
  top: 1.5%;                /* above the machine — the zoomed frames reach low in the stage */
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 12px 6px 10px;
  border-radius: 10px;
  background: rgba(16, 16, 18, .78);
  border: 1px solid rgba(255, 255, 255, .1);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .01em;
  white-space: nowrap;
  pointer-events: none;
  transform: translateX(-50%);
  opacity: 0;
  visibility: hidden;
  transition: opacity 250ms ease-out, visibility 0s linear 250ms;
}
.v-hint svg { width: 16px; height: 16px; color: var(--v-accent); }
.is-ready.v-has-hint:not(.is-hinted) .v-hint { opacity: 1; visibility: visible; transition-delay: 0s; }

/* ===== DOCK ===== */
.v-dock {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding-top: 14px;
}
.v-ctrls { display: flex; gap: 10px; }
.v-btn {
  width: var(--v-btn);
  height: var(--v-btn);
  padding: 0;
  display: grid;
  place-items: center;
  border-radius: 10px;
  border: 1px solid var(--hairline-2, rgba(255, 255, 255, .13));
  background: var(--v-raised);
  color: var(--v-text);
  cursor: pointer;
  transition: background-color var(--v-dur) var(--v-ease), color var(--v-dur), transform 150ms var(--v-ease);
}
.v-btn svg { width: 20px; height: 20px; }
.v-btn:active { transform: translateY(1px); }
.v-btn[aria-pressed="true"] { background: var(--v-accent); border-color: var(--v-accent); color: #fff; }
.v-btn[aria-pressed="false"] { color: var(--v-muted); }
@media (hover: hover) { .v-btn:hover { background: var(--v-raised-hi); color: #fff; } }

.v-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 2px 10px;
  font-size: 12px;
  line-height: 1.2;
  color: var(--v-muted);
  font-variant-numeric: tabular-nums;
}
.v-read-l { color: var(--v-text); font-weight: 600; }
.v-dots { display: flex; flex-wrap: wrap; justify-content: center; }
.v-dot {
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  display: grid;
  place-items: center;
  cursor: pointer;
}
.v-dot::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .42);
  transition: background-color var(--v-dur), transform var(--v-dur) var(--v-ease);
}
.v-dot[aria-current="true"]::before { background: var(--v-accent); transform: scale(1.4); }
@media (hover: hover) { .v-dot:hover::before { background: #fff; } }

.v-single .v-rot, .v-nohots .v-hotbtn, .v-nodock .v-dock { display: none; }

/* ===== FOCUS ===== */
.v-root :focus { outline: none; }
.v-root :focus-visible { outline: 2px solid var(--v-accent); outline-offset: 3px; }
.v-dot:focus-visible { outline-offset: -2px; }

/* ===== REDUCED MOTION (system setting, or <html data-motion="reduce">) ===== */
/* Phones: smaller "+" so four hotspots don't crowd a small machine. */
@media (max-width: 560px) {
  .v-root { --v-hot: 28px; }
  .v-hot svg { width: 13px; height: 13px; }
}
@media (prefers-reduced-motion: reduce) {
  .v-root *, .v-root *::before, .v-root *::after {
    animation: none !important;
    transition-duration: 0s !important;
    transition-delay: 0s !important;
  }
}
:root[data-motion="reduce"] .v-root *, :root[data-motion="reduce"] .v-root *::before, :root[data-motion="reduce"] .v-root *::after {
  animation: none !important;
  transition-duration: 0s !important;
  transition-delay: 0s !important;
}
