/* Pyro Planet catalog viewer.
   Palette from PP_Catalog_Series_Playbook.md section 1. Do not introduce a
   new blue -- if a blue looks wrong, the hex is being overridden somewhere. */

.ppcat {
  --pp-navy: #123b64;
  --pp-red: #ea222a;
  --pp-yellow: #fad20a;
  --pp-blue: #2c75a9;
  --pp-ink: #f4f6f9;
  --pp-chrome: #0d2b49;
  --pp-bar: 52px;

  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--pp-navy);
  color: var(--pp-ink);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-tap-highlight-color: transparent;
}

.ppcat *,
.ppcat *::before,
.ppcat *::after { box-sizing: border-box; }

/* ---------- stage ---------- */

.ppcat__stage {
  position: relative;
  width: 100%;
  overflow: hidden;
  background: var(--pp-navy);
}

.ppcat__swiper { width: 100%; height: 100%; }

/* Every slide reserves its space from manifest.aspect before any image
   arrives, so nothing reflows as pages load in. */
.ppcat__page {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 8px;
}

/* ZoomPan transforms .ppcat__pages as one unit, so the page image and the
   hotspots pinned to it scale and pan together. transform-origin must stay at
   0 0 -- the anchoring maths in zoompan.js assumes it. */
.ppcat__pages {
  display: flex;
  height: 100%;
  transform-origin: 0 0;
}

.ppcat__pages.is-zoomed {
  cursor: grab;
  /* The browser must not claim the gesture; panning is ours once zoomed. */
  touch-action: none;
}

.ppcat__pages.is-zoomed:active { cursor: grabbing; }

/* The frame hugs the rendered image exactly -- no letterboxing. Hotspots are
   positioned as a percentage of this box, so any gap between frame and image
   would put a QR tap in the wrong place. The image's width/height attributes
   give the browser the ratio up front, so nothing reflows as pages arrive. */
.ppcat__frame {
  position: relative;
  display: block;
  height: 100%;
  background-position: center;
  background-size: contain;
  background-repeat: no-repeat;
  box-shadow: 0 2px 18px rgb(0 0 0 / 45%);
}

.ppcat__spread { gap: 0; }

/* Height is the definite dimension and width follows from the ratio, so the
   frame shrink-wraps the image exactly. sizeStage() caps the stage height so
   a spread still fits the width -- that is what keeps this from overflowing
   rather than a max-width here, which would reintroduce letterboxing. */
.ppcat__img {
  display: block;
  height: 100%;
  width: auto;
}

/* ---------- hotspots ---------- */

.ppcat__hotspot {
  position: absolute;
  display: block;
  border-radius: 3px;
  /* Faint but findable. A visitor should be able to see that the QR on the
     page is tappable without the marker fighting the artwork. */
  background: rgb(250 210 10 / 14%);
  outline: 1px solid rgb(250 210 10 / 45%);
  transition: background 120ms ease-out;
}

.ppcat__hotspot:hover { background: rgb(250 210 10 / 28%); }

.ppcat__hotspot:focus-visible {
  outline: 3px solid var(--pp-yellow);
  outline-offset: 2px;
}

/* ---------- chrome ---------- */

.ppcat__bar {
  display: flex;
  gap: 6px;
  align-items: center;
  min-height: var(--pp-bar);
  padding: 6px 8px;
  background: var(--pp-chrome);
}

.ppcat__btn {
  display: inline-flex;
  gap: 6px;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  min-height: 40px;
  padding: 0 10px;
  border: 1px solid rgb(255 255 255 / 16%);
  border-radius: 6px;
  background: transparent;
  color: var(--pp-ink);
  font: inherit;
  font-size: 14px;
  cursor: pointer;
}

.ppcat__btn:hover:not(:disabled) { background: rgb(255 255 255 / 10%); }
.ppcat__btn:focus-visible { outline: 3px solid var(--pp-yellow); outline-offset: 2px; }
.ppcat__btn:disabled { opacity: 0.35; cursor: default; }
.ppcat__btn[aria-pressed="true"] { background: var(--pp-blue); border-color: var(--pp-blue); }

.ppcat__btn--download {
  margin-left: auto;
  border-color: var(--pp-yellow);
  background: var(--pp-yellow);
  color: var(--pp-navy);
  font-weight: 600;
  text-decoration: none;
}

.ppcat__size { opacity: 0.75; font-weight: 400; font-size: 12px; }

/* The counter doubles as the jump-to-page control: click it and type. */
.ppcat__count {
  min-width: 84px;
  min-height: 40px;
  padding: 0 6px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: none;
  color: inherit;
  font: inherit;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  text-align: center;
  cursor: pointer;
}

.ppcat__count:hover { border-color: rgb(255 255 255 / 20%); }
.ppcat__count:focus-visible { outline: 3px solid var(--pp-yellow); outline-offset: 2px; }

.ppcat__goto {
  width: 84px;
  min-height: 40px;
  padding: 0 8px;
  border: 1px solid var(--pp-yellow);
  border-radius: 6px;
  background: rgb(0 0 0 / 25%);
  color: var(--pp-ink);
  font: inherit;
  font-size: 14px;
  text-align: center;
}

/* An explicit rule, because .ppcat__btn's display would win over [hidden]. */
.ppcat [hidden] { display: none !important; }

/* ---------- contents ---------- */

.ppcat__toc {
  position: absolute;
  z-index: 30;
  top: 0;
  bottom: 0;
  left: 0;
  width: min(420px, 88%);
  overflow-y: auto;
  padding: 8px;
  background: rgb(10 31 54 / 97%);
  box-shadow: 4px 0 24px rgb(0 0 0 / 45%);
}

.ppcat__toclist { margin: 0; padding: 0; list-style: none; }

.ppcat__tocitem {
  display: grid;
  gap: 10px;
  grid-template-columns: 34px 1fr auto;
  width: 100%;
  padding: 10px 8px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--pp-ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.ppcat__tocitem:hover { background: rgb(255 255 255 / 8%); }
.ppcat__tocitem:focus-visible { outline: 3px solid var(--pp-yellow); outline-offset: -2px; }

.ppcat__toccode {
  padding: 2px 0;
  border-radius: 4px;
  background: var(--pp-red);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  text-align: center;
}

.ppcat__toctitle { font-size: 14px; }
.ppcat__toctitle em { display: block; opacity: 0.65; font-size: 12px; font-style: normal; }
.ppcat__tocpage { opacity: 0.7; font-size: 13px; font-variant-numeric: tabular-nums; }

/* ---------- first-use hint ---------- */

.ppcat__hint {
  position: absolute;
  z-index: 25;
  bottom: 16px;
  left: 50%;
  max-width: 90%;
  margin: 0;
  padding: 9px 16px;
  transform: translateX(-50%);
  border-radius: 20px;
  opacity: 0;
  background: rgb(0 0 0 / 72%);
  color: #fff;
  font-size: 13px;
  text-align: center;
  pointer-events: none;
  transition: opacity 350ms ease-out;
  backdrop-filter: blur(6px);
}

.ppcat__hint.is-visible { opacity: 1; }

/* ---------- search ---------- */

.ppcat__search { position: relative; flex: 1 1 120px; max-width: 260px; }

.ppcat__input {
  width: 100%;
  min-height: 40px;
  padding: 0 10px;
  border: 1px solid rgb(255 255 255 / 16%);
  border-radius: 6px;
  background: rgb(0 0 0 / 25%);
  color: var(--pp-ink);
  font: inherit;
  font-size: 14px;
}

.ppcat__input:focus-visible { outline: 3px solid var(--pp-yellow); outline-offset: 1px; }
.ppcat__input::placeholder { color: rgb(244 246 249 / 55%); }

/* The bar is anchored to the bottom of the viewer, so results open upward.
   Opening downward puts them off the bottom edge where nobody can see them. */
.ppcat__results {
  position: absolute;
  z-index: 20;
  bottom: calc(100% + 4px);
  left: 0;
  width: min(340px, 78vw);
  max-height: 300px;
  margin: 0;
  padding: 4px;
  overflow-y: auto;
  border-radius: 8px;
  background: var(--pp-chrome);
  box-shadow: 0 8px 28px rgb(0 0 0 / 55%);
  list-style: none;
}

.ppcat__result {
  display: block;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: var(--pp-ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.ppcat__result:hover { background: rgb(255 255 255 / 10%); }
.ppcat__result:focus-visible { outline: 3px solid var(--pp-yellow); outline-offset: -2px; }
.ppcat__result b { color: var(--pp-yellow); font-size: 12px; letter-spacing: 0.04em; }
.ppcat__result span { display: block; margin-top: 2px; font-size: 13px; opacity: 0.8; }
.ppcat__empty { padding: 10px; font-size: 13px; opacity: 0.7; }

/* ---------- thumbnail strip ---------- */

.ppcat__thumbs {
  height: 0;
  overflow: hidden;
  background: #0a1f36;
  transition: height 160ms ease-out;
}

.ppcat__thumbs--open { height: 104px; }

.ppcat__thumbstrip {
  display: flex;
  gap: 6px;
  height: 100%;
  padding: 8px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

/* Real buttons rather than slider slides: keyboard and screen-reader
   support comes for free, and the strip stays a plain scroll container. */
.ppcat__thumb {
  flex: 0 0 auto;
  padding: 0;
  border: 0;
  background: none;
  opacity: 0.55;
  cursor: pointer;
}

.ppcat__thumb.is-active { opacity: 1; outline: 2px solid var(--pp-yellow); }
.ppcat__thumb:focus-visible { outline: 3px solid var(--pp-yellow); outline-offset: 2px; }
.ppcat__thumb img { display: block; height: 88px; width: auto; }

/* ---------- utility ---------- */

.ppcat__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  border: 0;
  clip-path: inset(50%);
  white-space: nowrap;
}

.ppcat[hidden] { display: none; }

/* ---------- immersive mode ---------- */

/* Fixed positioning rather than the Fullscreen API, because iOS Safari does
   not implement requestFullscreen on ordinary elements. This works on every
   phone; real fullscreen is layered on top where it exists. */
.ppcat--immersive {
  position: fixed;
  z-index: 99999;
  inset: 0;
  width: 100vw;
  height: 100dvh;
  background: #000;
}

.ppcat--immersive .ppcat__bar,
.ppcat--immersive .ppcat__thumbs { display: none; }

.ppcat--immersive .ppcat__stage { height: 100% !important; }

/* The only control left on screen. Kept clear of the notch and the home bar. */
.ppcat__exit {
  position: absolute;
  z-index: 10;
  top: max(12px, env(safe-area-inset-top));
  right: max(12px, env(safe-area-inset-right));
  min-height: 40px;
  padding: 0 16px;
  border: 0;
  border-radius: 20px;
  background: rgb(0 0 0 / 55%);
  color: #fff;
  font: inherit;
  font-size: 14px;
  backdrop-filter: blur(6px);
  cursor: pointer;
}

.ppcat__exit:focus-visible { outline: 3px solid var(--pp-yellow); outline-offset: 2px; }

/* ---------- zoom controls ---------- */

.ppcat__zoomgroup { display: inline-flex; gap: 4px; align-items: center; }

.ppcat__btn--level {
  min-width: 58px;
  font-variant-numeric: tabular-nums;
  font-size: 13px;
}

/* On a phone the bar cannot hold nav, thumbnails, search and a download
   button in one row. Search drops to its own full-width row rather than
   crushing the tap targets below 40px. */
/* The bar holds paging, contents, thumbnails, zoom, spread, full screen,
   search and a download button. Below roughly 900px they cannot share one
   row without crushing each other, so search takes a row of its own well
   before things actually collide. */
@media (max-width: 900px) {
  .ppcat__bar { flex-wrap: wrap; }
  .ppcat__search { order: 2; flex: 1 1 100%; max-width: none; }
  .ppcat__results { width: 100%; }
  .ppcat__btn--download { margin-left: auto; padding: 0 12px; }
}

/* Below this the labelled buttons stop fitting even on their own row. */
@media (max-width: 720px) {
  /* Pinch covers zoom on a phone; the readout is the first thing to go. */
  .ppcat__btn--level { display: none; }
  .ppcat__btn--spread { display: none; }
}

/* Never let the results panel run past the viewer, whatever the bar does. */
.ppcat__results { max-width: calc(100vw - 24px); }

@media (prefers-reduced-motion: reduce) {
  .ppcat__thumbs,
  .ppcat__hotspot { transition: none; }
}

/* Full bleed on the live site.
   The Hello Elementor child theme caps main.site-main at 1140px, which leaves
   white gutters either side of the viewer's dark ground. Widening only the
   main that actually contains a catalog keeps every other page untouched.
   No 100vw here on purpose: 100vw counts the scrollbar and would push a
   horizontal scrollbar onto the page. */
body:has(.pp-catalog-embed) main.site-main {
  max-width: none;
}
