/* ==========================================================================
   COMPONENTS
   Buttons · Navigation · Cards · Accordion · Forms · Viewer UI · Badges
   ========================================================================== */

/* --------------------------------------------------------------------------
   BUTTONS
   -------------------------------------------------------------------------- */

.btn {
  --btn-bg: transparent;
  --btn-fg: var(--c-text);
  --btn-bd: var(--c-line-strong);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.625rem;
  padding: 0.9375rem 1.5rem;
  min-height: 48px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-bd);
  border-radius: var(--r-sm);
  font-family: var(--f-sans);
  font-size: var(--t-sm);
  font-weight: 500;
  letter-spacing: -0.005em;
  text-align: center;
  cursor: pointer;
  overflow: hidden;
  transition:
    background-color var(--d-base) var(--ease-out),
    border-color var(--d-base) var(--ease-out),
    color var(--d-base) var(--ease-out),
    transform var(--d-fast) var(--ease-out);
}

.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn:not(:disabled):active { transform: translateY(1px); }

.btn svg { width: 1.15em; height: 1.15em; }

.btn__arrow {
  display: inline-block;
  transition: transform var(--d-base) var(--ease-tech);
}
.btn:hover .btn__arrow { transform: translateX(4px); }
.btn--down:hover .btn__arrow { transform: translateY(3px); }

/* Primary — the single strongest element on any given screen */
.btn--primary {
  --btn-bg: var(--c-accent);
  --btn-fg: var(--c-accent-ink);
  --btn-bd: var(--c-accent);
  font-weight: 600;
}
.btn--primary:hover { --btn-bg: var(--c-accent-hover); --btn-bd: var(--c-accent-hover); }
.btn--primary:active { --btn-bg: var(--c-accent-press); }

/* Sweep highlight on hover — subtle, one pass */
.btn--primary::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 30%, rgba(255,255,255,0.28) 50%, transparent 70%);
  transform: translateX(-120%);
  transition: transform var(--d-slow) var(--ease-tech);
  pointer-events: none;
}
.btn--primary:hover::after { transform: translateX(120%); }

/* Secondary — outlined */
.btn--ghost:hover {
  --btn-bd: var(--c-accent);
  --btn-fg: var(--c-accent);
  background: var(--c-accent-soft);
}

/* Tertiary — quiet text button with an underline rule */
.btn--text {
  padding-inline: 0;
  min-height: auto;
  border: 0;
  border-bottom: 1px solid var(--c-line-strong);
  border-radius: 0;
  padding-bottom: 0.375rem;
  color: var(--c-text-muted);
}
.btn--text:hover { color: var(--c-accent); border-bottom-color: var(--c-accent); }

.btn--sm { padding: 0.625rem 1rem; min-height: 40px; font-size: var(--t-xs); }
.btn--block { width: 100%; }

@media (max-width: 480px) {
  .btn--responsive-block { width: 100%; }
}

/* --------------------------------------------------------------------------
   NAVIGATION
   -------------------------------------------------------------------------- */

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-nav);
  height: var(--nav-h);
  display: flex;
  align-items: center;
  border-bottom: 1px solid transparent;
  transition:
    background-color var(--d-base) var(--ease-out),
    border-color var(--d-base) var(--ease-out),
    transform var(--d-base) var(--ease-out);
}

.nav.is-scrolled {
  background: rgba(8, 9, 11, 0.82);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  border-bottom-color: var(--c-line);
}

/* Auto-hide on downward scroll, reveal on upward scroll */
.nav.is-hidden { transform: translateY(-100%); }

.nav__inner {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-left: var(--gutter-l);
  padding-right: var(--gutter-r);
  display: flex;
  align-items: center;
  gap: var(--s-5);
}

.nav__brand {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  margin-right: auto;
  flex-shrink: 0;
}

/* Logo artwork is navy on transparent: it always sits on a light plate so it
   stays legible against the dark page. */
.brand-plate {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  border-radius: var(--r-md);
}
.brand-plate img { display: block; height: auto; }

.nav__mark { padding: 4px 6px; }
.nav__mark img { width: 52px; }

.nav__wordmark {
  font-family: var(--f-display);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

/* Phones: logo + name + language + menu have to share ~280px at 320 wide. */
@media (max-width: 599px) {
  .nav__inner { gap: var(--s-3); }
  .nav__brand { gap: 0.5rem; }
  .nav__mark img { width: 44px; }
}
@media (max-width: 359px) {
  .nav__actions { gap: var(--s-2); }
}

/* While the drawer is open the bar must stay above it, or its close button is
   buried under the very menu it closes. */
body.is-locked .nav { z-index: calc(var(--z-drawer) + 1); }

.nav__links {
  display: none;
  align-items: center;
  gap: clamp(0.75rem, 0.2rem + 1.4vw, 2rem);
}

.nav__link {
  position: relative;
  padding: 0.5rem 0;
  font-size: var(--t-xs);
  font-weight: 450;
  color: var(--c-text-muted);
  white-space: nowrap;
  transition: color var(--d-fast) var(--ease-out);
}
.nav__link::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--c-accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--d-base) var(--ease-tech);
}
.nav__link:hover { color: var(--c-text); }
.nav__link:hover::after,
.nav__link.is-active::after { transform: scaleX(1); }
.nav__link.is-active { color: var(--c-text); }

.nav__actions {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-left: auto;
}

/* Language switch */
.lang-switch {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--c-line);
  border-radius: var(--r-sm);
  overflow: hidden;
}
.lang-switch__item {
  padding: 0.375rem 0.5rem;
  font-family: var(--f-mono);
  font-size: var(--t-micro);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-text-dim);
  transition: color var(--d-fast), background-color var(--d-fast);
}
.lang-switch__item:hover { color: var(--c-text); background: var(--c-surface-2); }
.lang-switch__item[aria-current='true'] {
  color: var(--c-text);
  background: var(--c-surface-3);
}

/* Touch-sized targets wherever the bar collapses to the hamburger layout. */
@media (max-width: 1023px), (pointer: coarse) {
  .lang-switch__item {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.5rem;
    min-height: 2.5rem;
    padding: 0 0.25rem;
  }
}
@media (max-width: 359px) {
  .lang-switch__item { min-width: 2.25rem; }
}

.nav__cta { display: none; }

/* Hamburger */
.nav__toggle {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  padding: 0 10px;
  border: 1px solid var(--c-line);
  border-radius: var(--r-sm);
}
.nav__toggle span {
  display: block;
  height: 1.5px;
  width: 100%;
  background: var(--c-text);
  transition: transform var(--d-base) var(--ease-tech), opacity var(--d-fast);
}
.nav__toggle[aria-expanded='true'] span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.nav__toggle[aria-expanded='true'] span:nth-child(2) { opacity: 0; }
.nav__toggle[aria-expanded='true'] span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

@media (min-width: 1024px) {
  .nav__links { display: flex; }
  .nav__cta { display: inline-flex; }
  .nav__toggle { display: none; }
}

/* Scroll progress hairline */
.nav__progress {
  position: absolute;
  left: 0; bottom: -1px;
  height: 1.5px;
  width: 100%;
  transform: scaleX(var(--progress, 0));
  transform-origin: left;
  background: var(--c-accent);
  opacity: 0;
  transition: opacity var(--d-base);
}
.nav.is-scrolled .nav__progress { opacity: 1; }

/* --- Mobile drawer -------------------------------------------------------- */
.drawer {
  position: fixed;
  inset: 0;
  z-index: var(--z-drawer);
  background: var(--c-void);
  display: flex;
  flex-direction: column;
  padding: var(--gutter);
  padding-left: var(--gutter-l);
  padding-right: var(--gutter-r);
  padding-top: calc(var(--nav-h) + var(--s-6));
  padding-bottom: max(var(--gutter), env(safe-area-inset-bottom, 0px));
  /* Short screens (landscape phones) must be able to reach the last link. */
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--d-base) var(--ease-out), visibility var(--d-base);
}
.drawer.is-open { visibility: visible; opacity: 1; }
/* The class sets display:flex, which would otherwise defeat the attribute. */
.drawer[hidden] { display: none; }

.drawer__nav { display: grid; gap: var(--s-1); }

.drawer__link {
  display: flex;
  align-items: baseline;
  gap: var(--s-4);
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--c-line-soft);
  font-family: var(--f-display);
  font-size: clamp(1.5rem, 1.1rem + 2vw, 2.25rem);
  font-weight: 500;
  letter-spacing: var(--ls-head);
  opacity: 0;
  transform: translateY(14px);
}
.drawer.is-open .drawer__link {
  animation: drawer-in var(--d-base) var(--ease-out) forwards;
  animation-delay: calc(var(--i, 0) * 45ms + 80ms);
}
.drawer__link span {
  font-family: var(--f-mono);
  font-size: var(--t-micro);
  letter-spacing: var(--ls-tech);
  color: var(--c-accent);
}

@keyframes drawer-in {
  to { opacity: 1; transform: translateY(0); }
}

.drawer__footer {
  margin-top: auto;
  display: grid;
  gap: var(--s-4);
  padding-top: var(--s-6);
}
.drawer__contact {
  display: grid;
  gap: var(--s-2);
  font-size: var(--t-sm);
  color: var(--c-text-muted);
}

/* Landscape phones: a single column of large links is taller than the screen,
   so the links and the contact block sit side by side instead. */
@media (max-height: 560px) and (max-width: 1023px) {
  .drawer { padding-top: calc(var(--nav-h) + var(--s-3)); }
  .drawer__link { padding: 0.625rem 0; font-size: 1.25rem; }
}
@media (max-height: 560px) and (min-width: 600px) and (max-width: 1023px) {
  .drawer {
    display: grid;
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
    column-gap: var(--s-7);
    align-content: start;
  }
  .drawer__footer { margin-top: 0; padding-top: 0; align-self: center; }
}

@media (min-width: 1024px) {
  .drawer { display: none; }
}

/* --------------------------------------------------------------------------
   CARDS
   -------------------------------------------------------------------------- */

.card {
  position: relative;
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  transition: border-color var(--d-base) var(--ease-out), background-color var(--d-base) var(--ease-out);
}
.card:hover { border-color: var(--c-line-strong); background: var(--c-surface-2); }

/* Corner ticks — engineering drawing cue */
.card--ticks::before,
.card--ticks::after {
  content: '';
  position: absolute;
  width: 8px; height: 8px;
  border-color: var(--c-accent);
  opacity: 0;
  transition: opacity var(--d-base) var(--ease-out);
}
.card--ticks::before { top: -1px; left: -1px; border-top: 1px solid; border-left: 1px solid; }
.card--ticks::after  { bottom: -1px; right: -1px; border-bottom: 1px solid; border-right: 1px solid; }
.card--ticks:hover::before,
.card--ticks:hover::after { opacity: 1; }

/* --------------------------------------------------------------------------
   BADGES / PILLS
   -------------------------------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.375rem 0.75rem;
  border: 1px solid var(--c-line);
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.02);
  font-family: var(--f-mono);
  font-size: var(--t-micro);
  letter-spacing: var(--ls-tech);
  text-transform: uppercase;
  color: var(--c-text-muted);
}

.badge--accent {
  border-color: var(--c-accent-line);
  background: var(--c-accent-soft);
  color: var(--c-accent);
}

.badge__dot {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 18%, transparent);
}

.badge__dot--live { animation: pulse-dot 2.4s var(--ease-in-out) infinite; }

@keyframes pulse-dot {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, currentColor 40%, transparent); }
  50%      { box-shadow: 0 0 0 5px color-mix(in srgb, currentColor 0%, transparent); }
}

@media (prefers-reduced-motion: reduce) {
  .badge__dot--live { animation: none; }
}

/* --------------------------------------------------------------------------
   ACCORDION (FAQ + service detail)
   -------------------------------------------------------------------------- */

.accordion { border-top: 1px solid var(--c-line); }

.accordion__item { border-bottom: 1px solid var(--c-line); }

.accordion__trigger {
  display: flex;
  align-items: flex-start;
  gap: var(--s-5);
  width: 100%;
  padding: clamp(1.25rem, 1rem + 0.6vw, 1.75rem) 0;
  text-align: left;
  color: var(--c-text);
  transition: color var(--d-fast) var(--ease-out);
}
.accordion__trigger:hover { color: var(--c-accent); }

.accordion__num {
  flex-shrink: 0;
  font-family: var(--f-mono);
  font-size: var(--t-micro);
  letter-spacing: var(--ls-tech);
  color: var(--c-text-faint);
  padding-top: 0.4em;
  min-width: 2.25rem;
}
.accordion__trigger[aria-expanded='true'] .accordion__num { color: var(--c-accent); }

.accordion__q {
  flex: 1;
  font-family: var(--f-display);
  font-size: clamp(1.0625rem, 1rem + 0.4vw, 1.3125rem);
  font-weight: 500;
  letter-spacing: -0.015em;
  line-height: 1.35;
}

.accordion__icon {
  flex-shrink: 0;
  position: relative;
  width: 20px; height: 20px;
  margin-top: 0.25em;
}
.accordion__icon::before,
.accordion__icon::after {
  content: '';
  position: absolute;
  left: 50%; top: 50%;
  background: currentColor;
  transition: transform var(--d-base) var(--ease-tech), opacity var(--d-base);
}
.accordion__icon::before { width: 14px; height: 1.5px; transform: translate(-50%, -50%); }
.accordion__icon::after  { width: 1.5px; height: 14px; transform: translate(-50%, -50%); }
.accordion__trigger[aria-expanded='true'] .accordion__icon::after { transform: translate(-50%, -50%) rotate(90deg); opacity: 0; }

.accordion__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--d-base) var(--ease-tech);
}
.accordion__panel.is-open { grid-template-rows: 1fr; }
.accordion__panel > div { overflow: hidden; }

.accordion__body {
  padding: 0 0 var(--s-6) calc(2.25rem + var(--s-5));
  max-width: var(--maxw-text);
  color: var(--c-text-muted);
  line-height: 1.7;
}

@media (max-width: 600px) {
  .accordion__body { padding-left: 0; }
  .accordion__trigger { gap: var(--s-3); }
  .accordion__num { min-width: 1.75rem; }
}

/* --------------------------------------------------------------------------
   FORM
   -------------------------------------------------------------------------- */

.field { display: grid; gap: 0.5rem; }

.field__label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  font-family: var(--f-mono);
  font-size: var(--t-micro);
  letter-spacing: var(--ls-tech);
  text-transform: uppercase;
  color: var(--c-text-muted);
}

.field__flag { color: var(--c-text-faint); text-transform: none; letter-spacing: 0.04em; }
.field__req { color: var(--c-accent); }

.input,
.textarea,
.select {
  width: 100%;
  padding: 0.875rem 1rem;
  min-height: 50px;
  background: var(--c-surface);
  color: var(--c-text);
  border: 1px solid var(--c-line);
  border-radius: var(--r-sm);
  font-size: var(--t-sm);
  transition: border-color var(--d-fast) var(--ease-out), background-color var(--d-fast) var(--ease-out), box-shadow var(--d-fast);
  appearance: none;
}

.input::placeholder,
.textarea::placeholder { color: var(--c-text-faint); }

/* iOS Safari zooms the whole page into any field under 16px when it gains
   focus, and does not zoom back out. */
@media (max-width: 900px), (pointer: coarse) {
  .input, .textarea, .select { font-size: 1rem; }
}

.input:hover, .textarea:hover, .select:hover { border-color: var(--c-line-strong); }

.input:focus, .textarea:focus, .select:focus {
  outline: none;
  border-color: var(--c-accent);
  background: var(--c-surface-2);
  box-shadow: 0 0 0 3px var(--c-accent-soft);
}

.textarea { min-height: 148px; resize: vertical; line-height: 1.6; }

.select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%236E7781' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  padding-right: 2.5rem;
  cursor: pointer;
}
.select option { background: var(--c-surface); color: var(--c-text); }

.field.has-error .input,
.field.has-error .textarea,
.field.has-error .select { border-color: var(--c-error); }

.field__error {
  display: none;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--t-xs);
  color: var(--c-error);
}
.field.has-error .field__error { display: flex; }

.field__help {
  font-size: var(--t-xs);
  color: var(--c-text-dim);
  line-height: 1.5;
}

/* Checkbox group for "services required" */
.checks {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 0.5rem;
}

.check {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.6875rem 0.875rem;
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: var(--r-sm);
  font-size: var(--t-xs);
  color: var(--c-text-muted);
  cursor: pointer;
  transition: border-color var(--d-fast), background-color var(--d-fast), color var(--d-fast);
}
.check:hover { border-color: var(--c-line-strong); color: var(--c-text); }

.check input {
  position: absolute;
  opacity: 0;
  width: 1px; height: 1px;
}

.check__box {
  position: relative;
  flex-shrink: 0;
  width: 16px; height: 16px;
  border: 1px solid var(--c-line-strong);
  border-radius: var(--r-xs);
  transition: background-color var(--d-fast), border-color var(--d-fast);
}
.check__box::after {
  content: '';
  position: absolute;
  left: 4.5px; top: 1px;
  width: 4px; height: 8px;
  border: solid var(--c-accent-ink);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg) scale(0);
  transition: transform var(--d-fast) var(--ease-tech);
}

.check input:checked ~ .check__box { background: var(--c-accent); border-color: var(--c-accent); }
.check input:checked ~ .check__box::after { transform: rotate(45deg) scale(1); }
.check input:checked ~ .check__text { color: var(--c-text); }
.check:has(input:checked) { border-color: var(--c-accent-line); background: var(--c-accent-soft); }
.check:has(input:focus-visible) { outline: 2px solid var(--c-accent); outline-offset: 2px; }

/* Consent uses the same control at full width */
.check--wide { width: 100%; align-items: flex-start; }
.check--wide .check__box { margin-top: 2px; }
.check--wide .check__text { line-height: 1.5; }

/* Honeypot: hidden from humans, reachable by naive bots */
.hp-field {
  position: absolute !important;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

/* Form states */
.form-status {
  display: none;
  gap: var(--s-4);
  padding: var(--s-5);
  border-radius: var(--r-md);
  border: 1px solid var(--c-line);
  background: var(--c-surface);
}
.form-status.is-visible { display: flex; }
.form-status--ok    { border-color: rgba(78, 216, 138, 0.35); background: rgba(78, 216, 138, 0.07); }
.form-status--error { border-color: rgba(255, 92, 92, 0.35); background: var(--c-error-soft); }

.form-status__icon { flex-shrink: 0; width: 22px; height: 22px; margin-top: 2px; }
.form-status--ok .form-status__icon { color: var(--c-ok); }
.form-status--error .form-status__icon { color: var(--c-error); }
.form-status__title { font-family: var(--f-display); font-size: var(--t-h4); margin-bottom: 0.35rem; }
.form-status__body { font-size: var(--t-sm); color: var(--c-text-muted); line-height: 1.6; }

/* Submit button loading state */
.btn.is-loading { pointer-events: none; }
.btn.is-loading .btn__label { opacity: 0.55; }

.spinner {
  width: 15px; height: 15px;
  border: 1.75px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 640ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 1800ms; }
}

/* --------------------------------------------------------------------------
   POINT-CLOUD VIEWER UI
   -------------------------------------------------------------------------- */

.viewer {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 10;
  min-height: 340px;
  max-height: 78vh;
  max-height: 78svh;
  background:
    radial-gradient(ellipse 70% 55% at 50% 55%, #0E1319 0%, #07080A 70%),
    var(--c-void);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  overflow: hidden;
  contain: layout paint;
}

.viewer:fullscreen { aspect-ratio: auto; max-height: none; border-radius: 0; }

.viewer__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity var(--d-slow) var(--ease-out);
  touch-action: none;
  cursor: grab;
}
.viewer__canvas.is-ready { opacity: 1; }
.viewer__canvas:active { cursor: grabbing; }

/* On a touch screen a full-width canvas that claims every gesture is a scroll
   trap: a thumb that lands on it can never leave. Vertical swipes stay with the
   page; horizontal drags orbit and two fingers pinch, which the script handles. */
@media (pointer: coarse) {
  .viewer__canvas { touch-action: pan-y; }
  .viewer:fullscreen .viewer__canvas { touch-action: none; }
}

/* Static SVG scene shown before boot, on failure, and behind the canvas. */
.viewer__fallback {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  transition: opacity var(--d-slow) var(--ease-out);
}
.viewer__fallback svg { width: 100%; height: 100%; }
.viewer.is-ready .viewer__fallback { opacity: 0; }

.viewer__scrim {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  gap: var(--s-4);
  text-align: center;
  padding: var(--s-6);
  background: rgba(5, 6, 7, 0.72);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  transition: opacity var(--d-base) var(--ease-out), visibility var(--d-base);
}
.viewer.is-ready .viewer__scrim,
.viewer__scrim[hidden] { opacity: 0; visibility: hidden; }

.viewer__scrim-inner { display: grid; gap: var(--s-3); justify-items: center; max-width: 42ch; }
.viewer__scrim-title { font-family: var(--f-display); font-size: var(--t-h4); }
.viewer__scrim-text { font-size: var(--t-xs); color: var(--c-text-dim); line-height: 1.6; }

/* Determinate loading bar */
.viewer__bar {
  width: 180px; height: 2px;
  background: var(--c-surface-3);
  overflow: hidden;
  border-radius: var(--r-pill);
}
.viewer__bar span {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--c-accent);
  transform: scaleX(var(--p, 0));
  transform-origin: left;
  transition: transform 220ms linear;
}

/* HUD corner brackets */
.viewer__brackets { position: absolute; inset: 12px; pointer-events: none; }
.viewer__brackets i {
  position: absolute;
  width: 14px; height: 14px;
  border: 0 solid var(--c-line-strong);
}
.viewer__brackets i:nth-child(1) { top: 0; left: 0; border-top-width: 1px; border-left-width: 1px; }
.viewer__brackets i:nth-child(2) { top: 0; right: 0; border-top-width: 1px; border-right-width: 1px; }
.viewer__brackets i:nth-child(3) { bottom: 0; left: 0; border-bottom-width: 1px; border-left-width: 1px; }
.viewer__brackets i:nth-child(4) { bottom: 0; right: 0; border-bottom-width: 1px; border-right-width: 1px; }

/* Control panel */
.viewer__controls {
  position: absolute;
  left: var(--s-4);
  top: var(--s-4);
  display: grid;
  gap: var(--s-4);
  padding: var(--s-4);
  width: min(190px, 42vw);
  background: rgba(10, 12, 14, 0.72);
  backdrop-filter: blur(14px) saturate(130%);
  -webkit-backdrop-filter: blur(14px) saturate(130%);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
}

/* Layout-neutral on desktop, so the groups stay children of the panel grid. On
   phones it becomes the scroller (see the 860px block). */
.viewer__controls-scroll { display: contents; }

.ctrl-group { display: grid; gap: 0.5rem; }

.ctrl-group__label {
  font-family: var(--f-mono);
  font-size: var(--t-micro);
  letter-spacing: var(--ls-tech);
  text-transform: uppercase;
  color: var(--c-text-faint);
}

.ctrl-row { display: flex; flex-wrap: wrap; gap: 3px; }

/* Equal-width presets, and a stacked list for the colour modes — their labels
   are too long to share a row without ragged wrapping. */
.ctrl-row--split { display: grid; grid-template-columns: repeat(3, 1fr); }
.ctrl-row--stack { display: grid; grid-template-columns: 1fr; }

.ctrl {
  flex: 1 1 auto;
  padding: 0.4375rem 0.5rem;
  min-height: 32px;
  background: var(--c-surface-2);
  border: 1px solid transparent;
  border-radius: var(--r-xs);
  font-family: var(--f-mono);
  font-size: var(--t-micro);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-text-dim);
  white-space: nowrap;
  transition: color var(--d-fast), background-color var(--d-fast), border-color var(--d-fast);
}
.ctrl:hover { color: var(--c-text); background: var(--c-surface-3); }
.ctrl[aria-pressed='true'],
.ctrl.is-active {
  color: var(--c-accent);
  background: var(--c-accent-soft);
  border-color: var(--c-accent-line);
}

.ctrl--icon {
  flex: 0 0 auto;
  display: inline-grid;
  place-items: center;
  width: 32px;
  padding: 0;
}
.ctrl--icon svg { width: 14px; height: 14px; }
.ctrl[hidden] { display: none; }

@media (pointer: coarse) {
  .ctrl { min-height: 40px; min-width: 40px; }
  .ctrl--icon { width: 40px; }
  .ctrl--icon svg { width: 16px; height: 16px; }
}

/* Point-size slider */
.ctrl-range {
  width: 100%;
  height: 20px;
  background: transparent;
  appearance: none;
  cursor: pointer;
}
.ctrl-range::-webkit-slider-runnable-track {
  height: 2px;
  background: var(--c-surface-3);
  border-radius: var(--r-pill);
}
.ctrl-range::-webkit-slider-thumb {
  appearance: none;
  width: 12px; height: 12px;
  margin-top: -5px;
  background: var(--c-accent);
  border-radius: 50%;
}
.ctrl-range::-moz-range-track { height: 2px; background: var(--c-surface-3); border-radius: var(--r-pill); }
.ctrl-range::-moz-range-thumb { width: 12px; height: 12px; background: var(--c-accent); border: 0; border-radius: 50%; }

/* HUD readouts */
.viewer__hud {
  position: absolute;
  right: var(--s-4);
  top: var(--s-4);
  display: grid;
  gap: 0.5rem;
  padding: var(--s-4);
  text-align: right;
  background: rgba(10, 12, 14, 0.6);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  pointer-events: none;
}

.hud-row {
  display: grid;
  gap: 1px;
  font-family: var(--f-mono);
  font-size: var(--t-micro);
  letter-spacing: 0.08em;
}
.hud-row dt { color: var(--c-text-faint); text-transform: uppercase; }
.hud-row dd { color: var(--c-text); margin: 0; }

/* Legend (elevation ramp / classes) */
.viewer__legend {
  position: absolute;
  left: var(--s-4);
  bottom: var(--s-4);
  display: grid;
  gap: 0.5rem;
  padding: 0.75rem;
  background: rgba(10, 12, 14, 0.68);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  pointer-events: none;
  max-width: min(230px, 60vw);
}
.viewer__legend[hidden] { display: none; }

.legend__title {
  font-family: var(--f-mono);
  font-size: var(--t-micro);
  letter-spacing: var(--ls-tech);
  text-transform: uppercase;
  color: var(--c-text-faint);
}

.legend__ramp {
  height: 6px;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg,
    var(--c-data-1) 0%, var(--c-data-2) 28%, var(--c-data-3) 50%, var(--c-data-4) 74%, var(--c-data-5) 100%);
}

.legend__scale {
  display: flex;
  justify-content: space-between;
  font-family: var(--f-mono);
  font-size: var(--t-micro);
  color: var(--c-text-dim);
}

.legend__classes { display: grid; gap: 3px; }
.legend__class[hidden] { display: none; }
.legend__class {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--f-mono);
  font-size: var(--t-micro);
  color: var(--c-text-muted);
}
.legend__swatch { width: 8px; height: 8px; border-radius: 1px; flex-shrink: 0; }

/* Interaction hint, fades after first interaction */
.viewer__hint {
  position: absolute;
  right: var(--s-4);
  bottom: var(--s-4);
  font-family: var(--f-mono);
  font-size: var(--t-micro);
  letter-spacing: 0.05em;
  color: var(--c-text-faint);
  pointer-events: none;
  transition: opacity var(--d-base);
  text-align: right;
  max-width: 45%;
}
.viewer.has-interacted .viewer__hint { opacity: 0; }

@media (max-width: 860px) {
  .viewer { aspect-ratio: 4 / 3; }

  /* A stacked panel would cover most of a phone-sized viewer, so the groups
     become one short horizontally-scrollable strip along the bottom edge. The
     panel keeps the frosted background; the inner wrapper scrolls and fades. */
  .viewer__controls {
    left: var(--s-3);
    right: var(--s-3);
    top: auto;
    bottom: var(--s-3);
    width: auto;
    display: block;
    padding: 0.625rem 0;
    overflow: hidden;
  }
  .viewer__controls-scroll {
    display: flex;
    align-items: flex-end;
    gap: var(--s-4);
    padding-inline: 0.75rem;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    scroll-snap-type: x proximity;
    scroll-padding-inline: 0.75rem;
  }
  .viewer__controls-scroll::-webkit-scrollbar { display: none; }

  .viewer__controls .ctrl-group { flex: 0 0 auto; scroll-snap-align: start; }
  .viewer__controls .ctrl-row,
  .viewer__controls .ctrl-row--split,
  .viewer__controls .ctrl-row--stack {
    display: flex;
    flex-wrap: nowrap;
  }
  /* Point size is a fine-tuning control; touch users get the tuned default. */
  .viewer__controls .ctrl-range { display: none; }
  .viewer__hud { left: var(--s-3); right: var(--s-3); top: var(--s-3); grid-auto-flow: column; text-align: left; justify-content: space-between; }
  .viewer__legend, .viewer__hint { display: none; }
}

/* Portrait phones: a taller frame leaves the survey room between the readout
   above and the control strip below (the camera backs off to match). */
@media (max-width: 520px) {
  .viewer { aspect-ratio: 4 / 5; }
}

@media (max-width: 420px) {
  .viewer__hud .hud-row:nth-child(n + 3) { display: none; }
}

/* --------------------------------------------------------------------------
   SCROLL FADE — edge hint on horizontally scrollable strips. The classes are
   toggled by modules/scroll-fade.js only while there is more to scroll to.
   -------------------------------------------------------------------------- */

.scroll-fade { --fade-l: 0px; --fade-r: 0px; }
.scroll-fade.has-more-left,
.scroll-fade.has-more-right {
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--fade-l), #000 calc(100% - var(--fade-r)), transparent 100%);
          mask-image: linear-gradient(to right, transparent 0, #000 var(--fade-l), #000 calc(100% - var(--fade-r)), transparent 100%);
}
.scroll-fade.has-more-left  { --fade-l: 28px; }
.scroll-fade.has-more-right { --fade-r: 28px; }
