/* Fixed viewer + independent sliding panel + native content scroller. */
:root {
  color-scheme: light;
  font-family: system-ui, sans-serif;
  color: #222;
  background: #e9e9e9;
  --viewport-left: 0px;
  --viewport-top: 0px;
  --viewport-width: 100vw;
  --viewport-height: 100dvh;
  --viewport-min: min(var(--viewport-width), var(--viewport-height));
  --edge: clamp(20px, calc(var(--viewport-width) * .03), 48px);
  --inset-left: max(var(--edge), env(safe-area-inset-left));
  --inset-right: max(var(--edge), env(safe-area-inset-right));
  --header-top: max(12px, env(safe-area-inset-top));
  --control-size: 44px;
  --handle-label-height: 21px;
  /* The handle's empty lower padding already separates its label from the
     screen edge. Count it toward the safe area instead of adding both gaps. */
  --bottom-inset: max(0px, calc(env(safe-area-inset-bottom, 0px) - (var(--control-size) - var(--handle-label-height)) / 2));
  --header-controls: var(--control-size);
  --footer-controls: var(--control-size);
  --handle-width: 88px;
  --reveal: 0;
  --line: #ccc;
  --muted: #555;
}
* { box-sizing: border-box; }
html, body { width: 100%; height: 100%; overflow: hidden; overscroll-behavior: none; }
body { position: fixed; inset: 0; margin: 0; font-size: 16px; line-height: 1.5; }
a { color: inherit; text-underline-offset: 4px; }
a, button { -webkit-tap-highlight-color: transparent; }
a:focus-visible, button:focus-visible { outline: 2px solid #222; outline-offset: 5px; }
h1, h2, h3, p, figure { margin: 0; }
h1 { line-height: 1.2; }
h2 { font-size: 18px; font-weight: 500; }
h3 { font-size: 16px; font-weight: 500; }

/* One viewport-sized scene, with small independent overlays. */
.viewer-shell, .content-panel {
  position: fixed;
  left: var(--viewport-left);
  top: var(--viewport-top);
  width: var(--viewport-width);
  height: var(--viewport-height);
}
.viewer-shell { overflow: hidden; }
.viewer-shell:focus { outline: none; }
.viewer-stage, .viewer-preview, .viewer-scene { position: absolute; inset: 0; }
/* The canvas owns camera gestures at 1×. Its ancestors must also permit native
   pinch when navigation yields a magnified page back to the browser. */
.viewer-stage { touch-action: pan-x pan-y pinch-zoom; }
.viewer-preview {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 90px;
  color: #606060;
  background: #e9e9e9;
  text-align: center;
  font-size: 14px;
}
.viewer-scene { pointer-events: none; opacity: 0; }
.viewer-scene canvas { display: block; width: 100%; height: 100%; }
.scene-slot { position: absolute; inset: 0; opacity: 0; pointer-events: none; }
.scene-slot[data-active="true"] { opacity: 1; pointer-events: auto; }
/* Keep full scene dimensions while preparing its first useful frame. */
.viewer-scene[data-ready="true"] { pointer-events: auto; touch-action: pan-x pan-y pinch-zoom; opacity: 1; }
.viewer-stage[data-state="ready"] .viewer-preview { visibility: hidden; }
.viewer-stage.has-scene .viewer-preview { visibility: hidden; }
/* Keep the sparse caption and controls legible over close-up imagery. */
.viewer-stage::after {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: calc(var(--header-top) + 150px);
  background: linear-gradient(#e9e9e9f2, #e9e9e9b3 60%, #e9e9e900);
  pointer-events: none;
}
.viewer-retry, [data-viewer-retry] { border: 0; padding: 10px; background: none; color: inherit; font: inherit; text-decoration: underline; cursor: pointer; pointer-events: auto; }
.viewer-notice-action, .project-feedback { font-size: 12px; color: var(--muted); }
.viewer-notice-action, .project-feedback [data-viewer-retry] { min-height: 44px; padding: 8px 0; }
.project-info {
  position: absolute;
  top: var(--header-top);
  left: var(--inset-left);
  max-width: min(380px, calc(100% - var(--inset-left) - var(--inset-right)));
  text-align: left;
  pointer-events: none;
}
/* Only the title shares a row with Contact. The point count and view choices can use
   the full width below it without wrapping into the scene on small phones. */
.project-info h1 { display: flex; align-items: center; min-height: var(--control-size); max-width: calc(var(--viewport-width) - var(--inset-left) - var(--inset-right) - 80px); font-size: 16px; font-weight: 500; overflow-wrap: anywhere; }
.project-info p { margin-top: 4px; color: var(--muted); font-size: 12px; }
.project-info .project-count {
  display: block;
  margin-top: 2px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.6;
}
.project-count[hidden] { display: none; }
.viewer-options, .project-output-links { display: flex; flex-wrap: wrap; gap: 0 16px; pointer-events: auto; }
.viewer-options { margin-top: 8px; }
.viewer-options[hidden] { display: none; }
.viewer-options button, .project-output-links button {
  padding: 8px 0;
  border: 0;
  background: none;
  color: inherit;
  font: 12px/1.5 system-ui, sans-serif;
  cursor: pointer;
  text-underline-offset: 5px;
}
.viewer-options button { min-height: var(--control-size); font-size: 14px; }
.viewer-options button[aria-pressed="true"], .viewer-options button:hover,
.project-output-links button:hover { text-decoration: underline; }
.viewer-options button[aria-busy="true"], .project-output-links button[aria-busy="true"] {
  text-decoration: underline dotted;
  color: var(--muted);
}
.project-info .viewer-notice { margin-top: 2px; }
.contact-link {
  position: fixed;
  z-index: 5;
  top: calc(var(--viewport-top) + var(--header-top) + var(--header-controls) - var(--control-size));
  right: calc(100% - var(--viewport-left) - var(--viewport-width) + var(--inset-right));
  width: max-content;
  display: inline-flex;
  align-items: center;
  min-height: var(--control-size);
  font-size: 14px;
}
.viewer-footer {
  position: absolute;
  inset: auto 0 0;
  min-height: 160px;
  background: linear-gradient(#ffffff00, #ffffffb3 45%, #ffffffed);
  pointer-events: none;
}
.handle-track {
  position: fixed;
  z-index: 5;
  left: var(--viewport-left);
  top: calc(var(--viewport-top) + var(--header-top));
  width: var(--viewport-width);
  height: calc(var(--viewport-height) - var(--header-top) - var(--bottom-inset));
  pointer-events: none;
}
.more-handle {
  position: absolute;
  left: 50%;
  top: calc((100% - var(--control-size)) * (1 - var(--reveal)));
  transform: translateX(-50%);
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: inherit;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: var(--handle-width);
  height: var(--control-size);
  text-decoration: none;
  font: 14px/var(--handle-label-height) ui-monospace, SFMono-Regular, Consolas, monospace;
  pointer-events: auto;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  cursor: ns-resize;
}
.more-handle:hover { text-decoration: underline; text-underline-offset: 4px; }
.more-handle.is-dragging { cursor: grabbing; text-decoration: none; }
html[data-input="pointer"] .more-handle:focus { outline: none; }
html[data-input="keyboard"] .more-handle:focus { outline: 2px solid #222; outline-offset: 5px; }
.handle-arrow { display: block; flex-shrink: 0; overflow: visible; }
.handle-arrow polyline { fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.handle-label { display: grid; width: 6ch; height: var(--handle-label-height); overflow: hidden; text-align: left; }
.handle-label > span { grid-area: 1 / 1; }
.handle-label-more { clip-path: inset(0 0 0 0); }
.handle-label-viewer { clip-path: inset(0 100% 0 0); }
.skip-link { position: absolute; left: 20px; top: -100px; z-index: 2; padding: 12px; background: #fff; }
.skip-link:focus { top: 12px; }

/* Reveal progress is controlled by app.js, never by document scroll position. */
.content-panel {
  z-index: 3;
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: #fff;
  transform: translate3d(0, calc((1 - var(--reveal)) * 100%), 0);
  visibility: hidden;
}
.panel-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
  touch-action: pan-x pan-y pinch-zoom;
}
.panel-scroll:focus { outline: none; }
.panel-header {
  flex-shrink: 0;
  padding-block: var(--header-top) 8px;
  background: #fff;
  border-bottom: 1px solid var(--line);
  display: grid;
  /* Equal sides keep the return control centered even with unequal safe areas. */
  grid-template-columns: minmax(0, 1fr) var(--handle-width) minmax(0, 1fr);
  align-items: center;
}
.panel-name { grid-column: 1; grid-row: 1; min-width: 0; margin-left: var(--inset-left); margin-right: 12px; font-size: 16px; font-weight: 500; overflow-wrap: anywhere; }
.panel-handle-space { grid-column: 2; height: var(--control-size); }

/* The capture/reconstruction process, project examples, and contact details. */
.panel-body {
  width: min(1120px, 100%);
  margin: auto;
  padding: 48px var(--inset-right) max(40px, env(safe-area-inset-bottom)) var(--inset-left);
}
.panel-body > section { scroll-margin-top: 24px; }
.panel-body > section + section { margin-top: 72px; }
.panel-body h2 { margin-bottom: 20px; }
.section-intro { max-width: 62ch; margin-bottom: 24px; }
.section-intro h2 { margin-bottom: 8px; }
.section-intro p { color: var(--muted); font-size: 15px; }
.introduction { display: grid; gap: 48px; font-size: 16px; }
.intro-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-areas: "copy image"; column-gap: clamp(28px, 4vw, 56px); row-gap: 12px; align-items: center; min-width: 0; }
.intro-row:nth-child(even) { grid-template-areas: "image copy"; }
.intro-example { grid-template-areas: "heading image" "copy image"; row-gap: 16px; }
.intro-example:nth-child(even) { grid-template-areas: "image heading" "image copy"; }
.intro-heading { grid-area: heading; align-self: end; max-width: 48ch; }
.intro-example > .intro-copy { align-self: start; }
.intro-copy { grid-area: copy; max-width: 48ch; font-size: inherit; line-height: 1.6; }
.intro-copy h2, .intro-heading { font-size: 22px; line-height: 1.3; text-wrap: balance; }
.intro-copy h2 { margin-bottom: 16px; }
.intro-copy p + p { margin-top: 12px; }
.intro-image { grid-area: image; min-width: 0; }
.intro-image > img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; }
.intro-image .image-placeholder { display: grid; place-items: center; aspect-ratio: 3 / 2; background: #f2f3f1; color: var(--muted); font-size: 14px; }
.intro-image.court-image img { object-position: 50% 45%; }
.intro-image figcaption { margin-top: 8px; color: var(--muted); font-size: 13px; }
.photo-comparison-frame { position: relative; aspect-ratio: 3 / 2; overflow: hidden; user-select: none; --comparison-position: 50%; }
.photo-comparison-frame > img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 45%; }
.photo-comparison-frame > .photo-comparison-cloud { position: absolute; inset: 0; clip-path: inset(0 0 0 var(--comparison-position)); }
.photo-comparison-frame[data-ready="false"] > .photo-comparison-cloud { opacity: 0; }
.photo-comparison-labels { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
.photo-comparison-divider { position: absolute; top: 0; bottom: 0; left: var(--comparison-position); width: 1px; transform: translateX(-50%); pointer-events: none; }
.photo-comparison-divider::before, .photo-comparison-divider::after { content: ""; position: absolute; width: 100%; height: calc(50% - 12px); background: #fff; box-shadow: 0 0 2px #0005; }
.photo-comparison-divider::before { top: 0; }
.photo-comparison-divider::after { bottom: 0; }
.photo-comparison-grip { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); display: grid; place-items: center; width: 32px; height: 24px; color: #fff; }
.photo-comparison-grip svg { display: block; filter: drop-shadow(0 1px 1px #000b); }
/* Only the thumb over the arrows takes pointer input. Its track lets gestures
   reach the image and article, while the native range keeps keyboard support.
   Extend by the thumb width so its endpoints match the image edges. */
.photo-comparison-range { position: absolute; top: calc(50% - 22px); left: -22px; width: calc(100% + 44px); height: 44px; margin: 0; padding: 0; border: 0; appearance: none; background: transparent; opacity: 0; pointer-events: none; cursor: ew-resize; touch-action: pan-y pinch-zoom; }
.photo-comparison-range::-webkit-slider-thumb { appearance: none; width: 44px; height: 44px; border: 0; pointer-events: auto; }
.photo-comparison-range::-moz-range-thumb { width: 44px; height: 44px; border: 0; pointer-events: auto; }
.photo-comparison-frame:has(.photo-comparison-range:focus-visible) { outline: 2px solid #222; outline-offset: 4px; }
.photo-comparison [hidden] { display: none; }
.lesson-entry { margin-top: 12px; }
.lesson-entry button, .lesson-entry > a { display: inline-block; padding: 10px 0; min-height: 44px; border: 0; background: none; color: inherit; font: inherit; text-decoration: underline; text-underline-offset: 4px; cursor: pointer; }
.lesson-entry button[aria-busy="true"] { color: var(--muted); }
.lesson-entry [role="status"] { font-size: 14px; }
.lesson-entry [role="status"]:empty { display: none; }
.project-image { aspect-ratio: 4 / 3; overflow: hidden; }
.project-image:empty { display: none; }
.project-thumbnail { display: block; width: 100%; height: 100%; object-fit: cover; object-position: var(--preview-position, 50% 50%); transform: scale(var(--preview-scale, 1)); }
/* Crop inside each orthomosaic's irregular data boundary. */
.project-tile[data-project="aaronson"] { --preview-position: 50% 28%; --preview-scale: 1.1; }
.project-tile[data-project="haikey-hole-17"] { --preview-scale: 1.35; }
.project-tile[data-project="chase-colosseum"] { --preview-position: 50% 1.5%; --preview-scale: 1.45; }

.project-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 32px 24px; }
.project-grid:focus-visible { outline: 2px solid #222; outline-offset: 6px; }
.project-tile { min-width: 0; }
.project-tile figcaption { margin-top: 14px; }
.project-open { display: block; text-decoration: none; }
.project-open:hover h3 { text-decoration: underline; }
.project-output-links { color: var(--muted); }
.contact-section {
  border-top: 1px solid var(--line);
  /* Extend the arrival highlight into the page gutters without indenting text. */
  margin-left: calc(-1 * var(--inset-left));
  margin-right: calc(-1 * var(--inset-right));
  padding: 24px var(--inset-right) 24px var(--inset-left);
}
.contact-invitation { margin-bottom: 16px; }
.contact-section h2 { margin: 0 0 12px; font-size: 18px; }
.contact-name { font-weight: 500; }
.contact-details { display: grid; gap: 4px; justify-items: start; min-width: 0; margin: 0; font-style: normal; }
.contact-location { color: var(--muted); }
.contact-email { max-width: 100%; overflow-wrap: anywhere; }

@container (max-width: 760px) {
  .intro-row, .intro-row:nth-child(even) { grid-template-columns: 1fr; grid-template-areas: "copy" "image"; gap: 20px; }
  .intro-example, .intro-example:nth-child(even) { grid-template-areas: "heading" "image" "copy"; }
  .intro-copy { max-width: 60ch; }
  .introduction { gap: 40px; }
  .project-grid { gap: 24px 16px; }
}
@media (max-width: 600px) {
  :root { --edge: 20px; }
  .viewer-preview { padding-inline: 76px; font-size: 12px; }
}
@container (max-width: 600px) {
  .panel-name { font-size: 14px; }
  .panel-body { padding-top: 28px; }
  .panel-body > section + section { margin-top: 44px; }
  .intro-copy h2, .intro-heading { font-size: 20px; }
  .project-grid { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: 86%; gap: 16px; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity; padding-bottom: 8px; scrollbar-width: thin; }
  .project-tile { scroll-snap-align: start; }
}
@media (max-height: 450px) and (orientation: landscape) {
  :root { --edge: 16px; }
  .viewer-footer { min-height: 100px; }
}
/* Magnification can leave less room than a phone media query reports. Keep
   full-size navigation targets on separate rows when they would overlap. */
:root[data-compact-viewport="true"] {
  --header-controls: calc(2 * var(--control-size));
  --footer-controls: calc(2 * var(--control-size));
}
[data-compact-viewport="true"] .panel-header {
  display: block;
  padding-top: calc(var(--header-top) + var(--control-size));
}
[data-compact-viewport="true"] .panel-name { margin-right: calc(var(--inset-right) + 70px); }
[data-compact-viewport="true"] .panel-handle-space { display: none; }
/* Contact occupies the second header row at this width. Reserve that row
   before the output choices, rather than letting their links overlap it. */
[data-compact-viewport="true"] .project-info h1 { max-width: 100%; margin-bottom: var(--control-size); }
