/* Panels anchored to a label icon in the pano: the read-only hover card and the editable context menu it opens
   into. They are two states of one panel, so they share this shell — a white card with a neutral hairline, an 8px
   radius, and a tail aimed at the label icon — and are positioned by the same routine (util.anchorPanelToLabel),
   which sets --panel-tail-top and the --flipped modifier. Each panel's own stylesheet adds its size and contents. */
.label-anchored-panel {
  position: absolute;
  box-sizing: border-box;
  background: var(--color-neutral-white);
  border: 1px solid var(--color-neutral-300);
  border-radius: calc(8px * var(--ui-scale));
}

/* The tail is a true triangle drawn as two stacked clip-path layers — a neutral-300 backing triangle with a white
   fill triangle offset 1.5px toward the panel — so it keeps the panel's hairline along its slanted edges and joins
   the panel edge with no seam. (A border+rotate diamond leaves gaps at the base corners; don't reintroduce it.) */
.label-anchored-panel::before,
.label-anchored-panel::after {
  content: "";
  position: absolute;
  top: var(--panel-tail-top, 50%);
  width: calc(8px * var(--ui-scale));
  height: calc(16px * var(--ui-scale));
  margin-top: calc(-8px * var(--ui-scale));
  clip-path: polygon(100% 0, 0 50%, 100% 100%);
}

.label-anchored-panel::before {
  left: calc(-8px * var(--ui-scale));
  background: var(--color-neutral-300);
}

.label-anchored-panel::after {
  left: calc(-6.5px * var(--ui-scale));
  background: var(--color-neutral-white);
}

/* Flipped: the panel sits to the left of the label icon, so the tail moves to the panel's right edge. */
.label-anchored-panel--flipped::before,
.label-anchored-panel--flipped::after {
  left: auto;
  clip-path: polygon(0 0, 100% 50%, 0 100%);
}

.label-anchored-panel--flipped::before {
  right: calc(-8px * var(--ui-scale));
}

.label-anchored-panel--flipped::after {
  right: calc(-6.5px * var(--ui-scale));
}
/* The read-only label card, shared by Explore and Validate. The shell — white card, neutral hairline, 8px radius,
   tail at the icon — comes from .label-anchored-panel, shared in turn with Explore's context menu (the card's
   editable state). What's specific here is the caption scale and the absence of any form affordance, so it stays
   unmistakably read-only. The label color lives in the type icon rather than the card surface: white text on a raw
   label color runs 1.68-2.75:1, under the 4.5:1 AA floor for every label type (#4719, #4726).

   Populated by Explore's Label.js #updateHoverCard() and Validate's LabelCard, positioned by both through
   util.anchorPanelToLabel. Each tool sets its own stacking position and hosts its own footer actions: Explore
   Delete/Edit, Validate a single Hide-label toggle. */
.label-hover-card {
  left: 0;
  top: 0;
  visibility: hidden;
  width: max-content;
  max-width: calc(240px * var(--ui-scale));
  box-shadow: 0 calc(2px * var(--ui-scale)) calc(10px * var(--ui-scale)) rgb(45 42 63 / 28%);
}

.label-hover-card__header {
  display: flex;
  align-items: center;
  gap: calc(7px * var(--ui-scale));
  padding: calc(6px * var(--ui-scale)) calc(10px * var(--ui-scale));
}

.label-hover-card__icon {
  width: calc(20px * var(--ui-scale));
  height: calc(20px * var(--ui-scale));
}

.label-hover-card__type {
  flex: 1;
  font: var(--text-caption-semibold);
  color: var(--color-neutral-black);
  white-space: nowrap;
}

/* Share, in the header rather than the footer: the footer is where a panel's actions on *this* label live (Explore's
   Delete/Edit, Validate's Hide), and at the card's 240px width a third button there would leave all three too narrow
   to read. Icon-only for the same reason — the label beside it would double the header's width. Its accessible name
   comes from aria-label, and the popover it opens says "Share this label" at the top. */
.label-hover-card__share.label-detail__share-trigger {
  flex: none;
  gap: 0;
  padding: calc(3px * var(--ui-scale));
  background: none;
  border: none;
  border-radius: calc(5px * var(--ui-scale));
  color: var(--color-neutral-700);
}

.label-hover-card__share.label-detail__share-trigger:hover {
  background: var(--color-neutral-100);
  border: none;
  color: var(--color-neutral-black);
}

.label-hover-card__share svg {
  width: calc(14px * var(--ui-scale));
  height: calc(14px * var(--ui-scale));
}

.label-hover-card__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(6px * var(--ui-scale));
  padding: calc(7px * var(--ui-scale)) calc(10px * var(--ui-scale)) calc(8px * var(--ui-scale));
  border-top: 1px solid var(--color-neutral-200);
}

/* The severity, not-rated, tags, and description rows are shown/hidden per label by the populating JS.

   Severity and not-rated are drawn as filled chips that enclose their icon and text, so the rating reads as one
   object instead of a loose icon-plus-sentence row. They match the tag chips below in height, type, and text color
   and differ only by their fill, which keeps the body one uniform stack of read-only chips rather than a ladder of
   competing sizes. The fill stays neutral: the level's color already comes from the smiley asset, and a
   level-to-color map in CSS would be a hardcoded copy of it. */
.label-hover-card__severity,
.label-hover-card__not-rated {
  display: none;
  align-items: center;
  gap: calc(4px * var(--ui-scale));

  /* Tighter on the icon side so the icon sits just inside the chip's edge. */
  padding: calc(2px * var(--ui-scale)) calc(7px * var(--ui-scale)) calc(2px * var(--ui-scale))
    calc(3px * var(--ui-scale));
  border-radius: 200px;
  background: var(--level-wash, var(--color-neutral-100));
  font: var(--text-tiny-medium);

  /* neutral-800, not the neutral-700 the tag chips use: on a level wash rather than flat neutral-100 this text
     falls to 4.35-4.42:1 for levels 2 and 3, under the AA floor. neutral-800 holds 7.5-8.7:1 on every level. */
  color: var(--color-neutral-800);
}

.label-hover-card__severity-icon {
  flex: none;
  width: calc(12px * var(--ui-scale));
  height: calc(12px * var(--ui-scale));

  /* The smiley is the same asset the context menu uses as a rating button, so it's held back here to read as a
     status glyph rather than something to click. */
  opacity: 0.75;
}

/* Mirrors the red "?" alert drawn on the canvas next to unrated labels (see Label.js #showSeverityAlert). Unlike the
   severity smiley this one keeps its full strength — it's flagging something still to do. Explore only: a validator
   can't rate from this card, so Validate leaves the chip out of its markup rather than nudging about a gap it
   offers no way to close. */
.label-hover-card__not-rated-icon {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: calc(12px * var(--ui-scale));
  height: calc(12px * var(--ui-scale));
  border-radius: 50%;
  background: var(--color-error-200);
  color: var(--color-neutral-white);
  font: var(--text-tiny-semibold);
}

.label-hover-card__tags {
  display: none;
  flex-wrap: wrap;
  gap: calc(4px * var(--ui-scale));
}

/* A hairline between the rating and the tags, when there is a rating above them to separate from. The two rows are
   both chips, so without it they read as one wrapped set rather than two different kinds of fact. The JS adds the
   class, because the rating is hidden with an inline display:none that no sibling selector can see. */
.label-hover-card__tags--divided {
  align-self: stretch;
  padding-top: calc(7px * var(--ui-scale));
  border-top: 1px solid var(--color-neutral-200);
}

/* The shared pill shape, shrunk and quieted down: these tags are read-only metadata, so they must not carry the
   context menu's tappable-button look (dark outline, roomy padding). The hairline stays — several tags sit side by
   side and need an edge to tell them apart — but drops to neutral-300 with 10px gray text. */
.label-hover-card__tags .tag-pill {
  padding: calc(2px * var(--ui-scale)) calc(7px * var(--ui-scale));
  outline-color: var(--color-neutral-300);
}

.label-hover-card__tags .tag-pill__label {
  font: var(--text-tiny-medium);
  color: var(--color-neutral-700);
}

/* Tiny, matching the chips above it — at caption size it was the largest thing in a body made of 10px chips, so
   the least important field read as the most prominent. The token's own 12px line-height is too tight for a
   description that wraps, so only that is overridden. */
.label-hover-card__description {
  display: none;
  font: var(--text-tiny-regular);
  line-height: 1.45;
  font-style: italic;
  color: var(--color-neutral-700);
  overflow-wrap: anywhere;
}

/* Empty state: no rating, no tags, no description. Validate always has a body to fill because it names the label it
   is asking about; Explore collapses the body instead, since a label with nothing in it is one the user just placed
   and is about to fill in. */
.label-hover-card__no-info {
  display: none;
  font: var(--text-tiny-regular);
  color: var(--color-neutral-700);
}

/* Footer action buttons (design-system button-ps/button--tiny). */
.label-hover-card__actions {
  display: flex;
  gap: calc(6px * var(--ui-scale));
  padding: calc(6px * var(--ui-scale)) calc(10px * var(--ui-scale)) calc(8px * var(--ui-scale));
  border-top: 1px solid var(--color-neutral-200);
}

.label-hover-card__action-button {
  flex: 1;
  justify-content: center;
  gap: calc(5px * var(--ui-scale));
}

.label-hover-card__action-button svg,
.label-hover-card__action-button img {
  flex: none;
  width: calc(12px * var(--ui-scale));
  height: calc(12px * var(--ui-scale));
}
.tool-ui {
  /* === Validate layout dimensions ===
     * --ui-scale is a single uniform scale factor for the whole tool, like browser zoom. JS sets it from the available
     * viewport size (see util.applyToolScale); every dimension below is expressed as base-size * var(--ui-scale) so
     * the pano, validation menu, and text all grow and shrink together in proportion. */
  --ui-scale: 1; /* The single scale knob. Overridden inline by util.applyToolScale() on load and resize. */

  /* Base sizes at --ui-scale = 1. util.applyToolScale() reads these to compute the tool's reference footprint,
     * so they must stay plain px values (no var()/calc()). */
  --pano-base-width: 720px;   /* Pano display size at --ui-scale = 1 (3:2, matching Explore). */
  --pano-base-height: 480px;
  --menu-base-width: 300px;   /* Right-hand validation menu column. */
  --menu-base-gap: 16px;      /* Horizontal gap between the pano and the validation menu. */
  --header-base-height: 80px; /* Mission title + progress bar sitting above the pano. */

  --pano-width: calc(var(--pano-base-width) * var(--ui-scale));
  --pano-height: calc(var(--pano-base-height) * var(--ui-scale));
  --menu-width: calc(var(--menu-base-width) * var(--ui-scale));
  --menu-gap: calc(var(--menu-base-gap) * var(--ui-scale));
  --header-height: calc(var(--header-base-height) * var(--ui-scale));

  /* Derived positions — these keep the rest of the layout in sync with the pano size automatically. */
  --menu-left: calc(var(--pano-width) + var(--menu-gap)); /* Left edge of the validation menu column. */
  --app-width: calc(var(--pano-width) + var(--menu-gap) + var(--menu-width));

  /* Base text size for the whole tool. */
  font: var(--text-body-regular);

  width: var(--app-width); /* Overrides bootstrap .container media queries to keep a consistent width. */
  padding: 0; /* Drop bootstrap .container's 15px side padding so the app-width holder inside stays centered. */
}

#svv-application-holder {
  background: var(--color-neutral-white);
  margin: 0 auto;
  position: relative;
  height: calc(var(--header-height) + var(--pano-height));
  width: var(--app-width);
}

.normal { font-weight: normal; }

/* Scale Bootstrap tooltips (reason-button examples, button hints, etc.) with the UI. They render on <body>, so they
   read --ui-scale from :root. Font/padding are scaled rather than transformed so Bootstrap positioning still works. */
.tooltip-inner {
  font: var(--text-caption-regular);
  padding: calc(3px * var(--ui-scale)) calc(8px * var(--ui-scale));
  max-width: calc(200px * var(--ui-scale));
}

/* Overwriting jquery tooltip styling. */
.tooltip.in {
  opacity: 1;
}
#modal-mission-holder {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  text-align: justify;
  visibility: hidden;
}

#modal-mission-foreground {
  padding: calc(100px * var(--ui-scale)) calc(20px * var(--ui-scale)) calc(10px * var(--ui-scale));
  visibility: hidden;
}

.modal-foreground {
  top: var(--header-height);
  left: 0;
  right: 0;
  padding: calc(10px * var(--ui-scale));
  height: var(--pano-height);
  background: var(--color-neutral-white);
  color: var(--color-neutral-800);
  font: var(--text-subtitle-regular);
  position: absolute;
  overflow: hidden;
  border: calc(4px * var(--ui-scale)) solid var(--color-neutral-black);
  border-radius: calc(5px * var(--ui-scale));
  z-index: 10;
}

.modal-foreground h1 {
  font: var(--text-h3-medium);
}

.modal-background {
  position: absolute;
  left: calc(-60px * var(--ui-scale));
  top: 0;
  background: rgb(from var(--color-neutral-white) r g b / 50%);
  height: 100%;
  width: 110%;
}

#modal-mission-close-button {
  display: block;
  width: 40%;
  margin: calc(30px * var(--ui-scale)) auto 0;
}

#modal-mission-instruction {
  text-align: center;
}

#modal-mission-background {
  position: absolute;
  left: 0;
  top: 0;
  background: rgb(from var(--color-neutral-white) r g b / 50%);
  visibility: hidden;
  height: 100%;
  width: 110%;
}

#modal-mission-complete-holder {
  visibility: hidden;
}

#modal-mission-complete-foreground {
  visibility: hidden;
  top: var(--header-height);
}

#modal-mission-complete-title {
  margin-top: calc(70px * var(--ui-scale));
  text-align: center;
}

#modal-mission-complete-message {
  text-align: center;
}

#modal-mission-complete-table {
  height: calc(190px * var(--ui-scale));
  padding-left: calc(175px * var(--ui-scale));
}

.modal-foreground .btn-primary {
  color: var(--color-neutral-white);
  background: var(--color-link-100);
  cursor: pointer;
  border: 1px solid transparent;
  font: var(--text-subtitle-regular);
  opacity: 1.0;
}

.modal-foreground .btn-secondary {
  color: var(--color-neutral-black);
  background: var(--color-neutral-white);
  cursor: pointer;
  border: 1px solid var(--color-neutral-black);
  font: var(--text-subtitle-regular);
  opacity: 1.0;
}

.modal-foreground .btn-loading {
  color: var(--color-neutral-white);
  background: var(--color-neutral-600);
  cursor: wait;
  border: 1px solid transparent;
  font: var(--text-subtitle-regular);
  opacity: 0.35;
}
/* Container for the panorama and its overlay controls (zoom, date, speed limit, etc.). */
#svv-panorama-holder {
  position: absolute;
  top: var(--header-height);
  width: var(--pano-width);
  height: var(--pano-height);
}

/* The panorama viewport. It fills the full pano area (no border) so the marker layer, which is the same size,
   overlays the imagery exactly. The colored frame is drawn on top by #pano-border-frame instead. */
#svv-panorama {
  position: absolute;
  left: 0;
  top: 0;
  height: var(--pano-height);
  width: var(--pano-width);
  border-radius: calc(4px * var(--ui-scale));
  background-color: var(--color-asphalt-400);
  overflow: hidden;
}

/* Colored frame on top of the pano and marker layers. Drawing it above the marker (rather than as the pano's own
   border underneath) means a label at the very edge is clipped by the frame instead of rendering on top of it. */
#pano-border-frame {
  position: absolute;
  left: 0;
  top: 0;
  height: var(--pano-height);
  width: var(--pano-width);
  z-index: 3;
  pointer-events: none;
  box-sizing: border-box;
  border: calc(3px * var(--ui-scale)) solid var(--color-asphalt-400);
  border-radius: calc(4px * var(--ui-scale));
}

#view-control-layer {
  position: absolute;
  width: var(--pano-width);
  height: var(--pano-height);
  left: 0;
  top: 0;
  overflow: hidden;
  cursor: url("/assets/images/icons/openhand.cur") 4 4, move;
  z-index: 2;

  /* http://stackoverflow.com/questions/8942805/chrome-bug-cursor-changes-on-mouse-down-move */
  -webkit-user-select: none;
  user-select: none;
}

/* The label marker (created by PanoMarker with a base px size that is multiplied by the UI scale in JS).

   The type icon is drawn by ::before from --label-icon rather than as the marker's own background, so that hiding
   the label can fade the icon independently of the ring around it. PanoManager writes both custom properties. */
#validate-pano-marker::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background-image: var(--label-icon);
  background-size: 100% 100%;
  transition: opacity 0.5s ease;
}

/* Pointer-target floor. The marker is what opens the label card — on desktop by hover and as a keyboard stop
   (PanoMarker, #4729), on mobile by touch — but the mark itself is 22px at --ui-scale 1 and shrinks to 14px at the
   0.65x end.

   This is about *acquisition*, not conformance. WCAG 2.5.8 Target Size (Minimum), AA, sizes targets for pointer
   activation, and desktop has no pointer activation here: nothing binds click to the marker (#4843). So the SC does
   not actually reach it, and mobile — which does activate by pointer — is already well past 24px at 52px. But a
   hover target is if anything the harder case, since it has to be found and then held, and 14px is small for that.
   24px is still the right number to floor at: it is what 2.5.8 asks of every other target on the page, and it is
   what Explore's placed-label target already uses.

   A transparent ::after widens only the *target*, so the mark stays the size it was drawn: growing the element
   instead would move the marker (PanoMarker positions it from its own size) and push the label card away from it
   (LabelVisibilityControl anchors on offsetWidth).

   max(), not a fixed size, so this only ever adds area — above ~1.09x the mark is already past 24px and the target
   is exactly the mark. Round, matching the mark: browsers hit-test through border-radius, and at every size the
   *desktop* marker is drawn at (22px base, 38px ceiling) .icon-outline's 25px radius clamps to 50%, so its target
   is a circle today. Squaring it off here would change that at every scale rather than only flooring it where it is
   too small — opening the card on a hover several px off the visible marker. (Mobile's 52px marker is the one size
   where that radius does not clamp, but there the mark is already wider than this floor, so nothing below applies.)
   z-index keeps it under the icon and the AI badge; it takes the pointer for the marker either way, since all three
   are the same element as far as the hover handlers are concerned. */
#validate-pano-marker::after {
  /* Mirrors util.LABEL_MIN_SCREEN_TARGET (public/js/common/utilities.js), which floors Explore's label target. One
     WCAG number for both tools, so keep the two in step — CSS can't read the JS constant. */
  --label-min-target: 24px;

  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: max(100%, var(--label-min-target));
  height: max(100%, var(--label-min-target));
  transform: translate(-50%, -50%);
  border-radius: 50%;
  z-index: -1;
}

/* Hidden state (the H key / either Hide-label toggle). The point of hiding is to see the sidewalk the marker is
   sitting on, so the icon goes away entirely — even at low opacity it still tints the very pixels the validator
   asked to look at. What remains is a dashed ring in the label type's own colour, which says where the label is
   and which type it belongs to without covering anything. It crossfades rather than cutting, so the label reads as
   stepping aside rather than being replaced by a different object.

   This replaced Label_Outline.svg, an Illustrator export whose artwork mostly sat outside its own viewBox (#4726). */
#validate-pano-marker {
  transition: border-color 0.5s ease, outline-color 0.5s ease, outline-width 0.5s ease;
}

#validate-pano-marker.label-marker--hidden::before {
  opacity: 0;
}

/* The ring is an outline, not the border, so it takes no part in layout and can't nudge the icon it surrounds.
   .icon-outline's black border goes transparent rather than away: it belongs to the solid marker, and leaving it
   would keep drawing a hard edge around something that is supposed to have receded. What's left is the label type's
   own colour at 70% — held back enough to read as receded, but the only cue left now that the icon is gone
   entirely, so it can't go as faint as it would if it were merely outlining something. */
#validate-pano-marker.label-marker--hidden {
  border-color: transparent;
  outline: calc(2px * var(--ui-scale)) dashed rgb(from var(--label-color, #ffffff) r g b / 70%);
  outline-offset: calc(1px * var(--ui-scale));
}

/* Sits in the top-right just left of the stacked zoom control, scaled down to match its height. transform-origin keeps
   the top-right corner pinned so the scaled sign still lines up with the zoom buttons. */
.speed-limit-sign {
  display: none;
  width: calc(60px * var(--ui-scale));
  height: calc(70px * var(--ui-scale));
  padding: calc(3px * var(--ui-scale));
  top: calc(7px * var(--ui-scale));
  right: calc(36px * var(--ui-scale));
  border-radius: calc(5px * var(--ui-scale));
  position: absolute;
  z-index: 3;

  /* Hover must reach the sign for its title tooltip; `auto` also guards against a no-pointer-events ancestor. */
  pointer-events: auto;
  cursor: help;
  transform: scale(0.657);
  transform-origin: top right;
  background: rgb(from var(--color-neutral-white) r g b / 75%);
}

.speed-limit-sign[data-design-style="non-us-canada"] {
  width: calc(75px * var(--ui-scale));
  height: calc(75px * var(--ui-scale));
  padding: 0;
  border-radius: 100%;
  transform: scale(0.613);
}

.speed-limit-holder {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: calc(5px * var(--ui-scale));
  border: calc(3px * var(--ui-scale)) solid var(--color-neutral-black);
}

.speed-limit-sign[data-design-style="non-us-canada"] .speed-limit-holder {
  border-radius: 100%;
  border: calc(7px * var(--ui-scale)) solid var(--color-error-200);
}

.speed-limit-text {
  display: flex;
  flex-direction: column;
  font: var(--text-small-bold);
  text-align: center;
}

#speed-limit {
  font: var(--text-h3-bold);
  font-size: calc(30px * var(--ui-scale));
}

/* Shared button look in pano-overlay-buttons.css; this rule only positions the holder in the top-right of the pano. */
#zoom-buttons-holder {
  position: absolute;
  z-index: 3;
  top: calc(7px * var(--ui-scale));
  right: calc(7px * var(--ui-scale));
}

#svv-panorama-date-holder {
  display: flex;
  justify-content: flex-start;
  height: calc(28px * var(--ui-scale));
  position: absolute;
  bottom: 0;

  /* Sits 8px right of wherever the imagery-source logo's pixels end. How far that is varies by source (Mapillary's
     wordmark is the widest), so the offset tracks the logo through --pano-logo-width, which PanoViewerLogo measures
     and publishes. The fallback covers GSV, which draws its own logo instead of going through that overlay: 66px is
     where Google's Street View logo ends. */
  left: calc((var(--pano-logo-width, 66px) + 8px) * var(--ui-scale));
  z-index: 2;
  font: var(--text-small-medium);
  text-shadow:
    calc(1px * var(--ui-scale)) calc(1px * var(--ui-scale)) calc(1px * var(--ui-scale)) var(--color-neutral-black);
  color: var(--color-neutral-white);
}

/* No left padding — the holder's left offset above owns the whole gap to the imagery-source logo. */
#svv-panorama-date {
  padding: calc(3px * var(--ui-scale)) calc(3px * var(--ui-scale)) calc(3px * var(--ui-scale)) 0;
}

#pano-info-button {
  margin-left: calc(4px * var(--ui-scale));
  margin-top: calc(4.5px * var(--ui-scale));
  height: calc(16px * var(--ui-scale));
}

/* Modify Google's terms / report an issue buttons' color to match our own buttons. */
.gm-style-cc div { background-color: var(--color-asphalt-400); }
.gm-style-cc div div { background-color: var(--color-asphalt-400) !important; }

/* Scale Google's terms / report-a-problem links (bottom-right) with the UI. They're Google's own elements with no
   scale hooks, so we scale them visually, anchored to the bottom-right corner they sit in. Must stay scoped to
   #view-control-layer (where PanoManager relocates them): unscoped, it also matches a wrapper inside GSV's own DOM
   and transform-scales the entire street view scene. */
#view-control-layer div:has(> .gmnoprint) {
  bottom: calc(3px * var(--ui-scale)) !important;
  right: calc(2px * var(--ui-scale)) !important;
  transform: scale(var(--ui-scale));
  transform-origin: bottom right;
}

/* Scale Google's own Street View logo with the UI, anchored to its corner. */
#svv-panorama div:has(> a[aria-label*="Google"]) {
  left: calc(2px * var(--ui-scale)) !important;
  bottom: calc(2px * var(--ui-scale)) !important;
  transform: scale(var(--ui-scale));
  transform-origin: bottom left;
}

/* Scale Mapillary's attribution links with the UI. */
#view-control-layer .mapillary-attribution-container {
  bottom: calc(3px * var(--ui-scale)) !important;
  right: calc(2px * var(--ui-scale)) !important;
  transform: scale(var(--ui-scale));
  transform-origin: bottom right;
}

/* Top-left of the pano, where Explore keeps its stuck/sound/feedback controls — and now with the same look, from the
   shared .pano-overlay-button (css/pano-overlay-buttons.css). It used to carry a Validate-only .button-on-pano style
   (white fill, 1.5px neutral-800 hairline, asphalt-500 text) that matched nothing else on the page (#4726). */
#label-visibility-control-holder {
  position: absolute;
  z-index: 2;
  top: calc(7px * var(--ui-scale));
  left: calc(7px * var(--ui-scale));
}

/* Sized to sit with the type beside it in both homes: the dark overlay pill above, and the label card's tiny
   footer button. currentColor, so it takes each one's text colour. */
.hide-label-button-icon {
  flex-shrink: 0;
  width: calc(14px * var(--ui-scale));
  height: calc(14px * var(--ui-scale));
}

.label-hover-card__action-button .hide-label-button-icon {
  width: calc(12px * var(--ui-scale));
  height: calc(12px * var(--ui-scale));
}

/* Validate's copy of the read-only label card (css/common/label-hover-card.css). Unlike Explore's it is not a click
   target — a validator judges the label, they don't edit it — so it carries no cursor and no Delete/Edit row, only
   the Hide-label toggle. Above #pano-border-frame (z-index: 3), which is drawn over the marker layer. */
#label-card {
  z-index: 4;
}
#mission-title {
  width: var(--app-width);
  position: absolute;
  top: calc(20px * var(--ui-scale));
  font: var(--text-body-bold);
  letter-spacing: 5%;
}

/* The mission progress bar uses the shared .ps-progress-bar component; this positions it and sets its slim height. */
#mission-progress-bar-section {
  --ps-progress-bar-height: calc(7px * var(--ui-scale));
  position: absolute;
  top: calc(50px * var(--ui-scale));
  width: var(--pano-width);
  gap: calc(12px * var(--ui-scale));
}

#mission-progress-bar-text {
  font: var(--text-small-regular);
  padding-bottom: calc(2px * var(--ui-scale));
}

#admin-info-section {
  display: none;
  position: absolute;
  top: calc(43px * var(--ui-scale));
  left: var(--menu-left);
}

/* The popover renders on <body> (so it reads --ui-scale from :root); override Bootstrap's 276px max-width. */
.admin-info-popover {
  max-width: calc(450px * var(--ui-scale));
}

#admin-info-content h1 {
  font: var(--text-title-bold);
  margin-top: 0;
  margin-bottom: 0;
}

#admin-info-content h2 {
  font: var(--text-body-bold);
  margin-top: calc(8px * var(--ui-scale));
  margin-bottom: 0;
}

#admin-info-content p {
  font: var(--text-caption-regular);
  margin-bottom: 0;
}
#validation-menu-holder {
  margin: 0;
  position: absolute;
  left: var(--menu-left);
  top: var(--header-height);
  width: var(--menu-width);
  height: var(--pano-height);
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: calc(20px * var(--ui-scale));
}

.validate-disabled {
  opacity: 0.6;
  pointer-events: none;
  cursor: not-allowed;
}

.validation-menu-section {
  display: none; /* Initially hidden, sections shown when validation buttons are clicked. */
}

#main-validate-section {
  display: block;
}

#validate-submit-section {
  display: flex;
  justify-content: space-between;
  margin-top: auto; /* Pushes the section to the bottom of the validation-menu-holder. */
}

.validation-menu-section-header {
  font: var(--text-small-bold);
  margin-bottom: calc(10px * var(--ui-scale));
}

#validation-button-holder {
  display: flex;
  justify-content: space-between;
}

/* Overriding some of our design system tokens, though we could likely bring them more in line with DST. */
.validate-page-button {
  display: inline-block;
  width: calc(86px * var(--ui-scale));
  height: calc(32px * var(--ui-scale));
  border: 1px solid var(--color-asphalt-500);
  text-align: center;

  background-color: var(--color-neutral-white);
  outline: none; /* Removes focus outline that shows up when I press shift after clicking on a button. */
}

.validate-button:hover {
  border: none;
}

.validate-button.chosen {
  border: none;
}

#validate-yes-button.chosen {
  background: var(--color-pine-500);
}

#validate-no-button.chosen {
  background: var(--color-orange-400);
}

#validate-unsure-button.chosen {
  background: var(--color-neutral-900);
  color: var(--color-neutral-white);
}

/* Only show hover states on non-touch devices. */
@media (hover: hover) {
  #validate-yes-button:hover {
    background: var(--color-pine-300);
  }

  #validate-yes-button.chosen:hover {
    background: var(--color-pine-500);
  }

  #validate-no-button:hover {
    background: var(--color-orange-300);
  }

  #validate-no-button.chosen:hover {
    background: var(--color-orange-400);
  }

  #validate-unsure-button:hover {
    background: var(--color-neutral-700);
    color: var(--color-neutral-white);
  }

  #validate-unsure-button.chosen:hover {
    background: var(--color-neutral-900);
  }
}

#sidewalk-ai-suggestions-block {
  margin-top: calc(15px * var(--ui-scale));
  margin-bottom: calc(15px * var(--ui-scale));
}

.sidewalk-ai-suggestions-header {
  font: var(--text-tiny-semibold);
  margin-bottom: calc(6px * var(--ui-scale));
}

.ai-icon {
  width: calc(16px * var(--ui-scale));
  height: calc(16px * var(--ui-scale));
}

.sidewalk-ai-suggestions-list-holder {
  display: flex;
  gap: calc(5px * var(--ui-scale));
  flex-wrap: wrap;
}

/* Shared pill look from tag-pills.css; these modifiers add the AI add/remove color semantics. The pill text is set
   directly on the element (no label span), so the pill font lives here. */
.sidewalk-ai-suggested-tag {
  font: var(--text-tiny-semibold);
  cursor: pointer;
  transition: all 0.3s;
}

.sidewalk-ai-suggested-tag.to-add {
  outline-color: var(--color-pine-700);
  color: var(--color-pine-700);
}

.sidewalk-ai-suggested-tag.to-remove {
  outline-color: var(--color-orange-500);
  color: var(--color-orange-500);
}

.sidewalk-ai-suggested-tag.to-add:hover {
  background: rgb(from var(--color-pine-500) r g b / 21%);
  outline-color: var(--color-pine-600);
}

.sidewalk-ai-suggested-tag.to-remove:hover {
  background: rgb(from var(--color-orange-500) r g b / 15%);
  outline-color: var(--color-orange-500);
}

.validate-text-input {
  width: 100%;
  margin-top: calc(10px * var(--ui-scale));
}

/* Bootstrap is getting loaded after this file hence overriding this. To avoid it, I am adding important but ideally the
  order of inclusion should be flipped. */
.validate-text-input input, .selectize-input {
  display: flex !important;
  width: 100% !important;
  height: calc(36px * var(--ui-scale)) !important;
  padding: calc(8px * var(--ui-scale)) calc(18px * var(--ui-scale)) !important;
  align-items: center !important;
  gap: calc(4px * var(--ui-scale)) !important;
  flex-shrink: 0 !important;
  border-radius: calc(6px * var(--ui-scale)) !important;
  border: calc(1px * var(--ui-scale)) solid var(--color-neutral-500) !important;
  background: var(--color-neutral-white) !important;
  font: var(--text-tiny-semibold) !important;

}

.selectize-input.focus.input-active.has-options {
  border-radius: calc(6px * var(--ui-scale)) calc(6px * var(--ui-scale)) 0 0;
}

.selectize-dropdown {
  border-radius: 0 0 calc(6px * var(--ui-scale)) calc(6px * var(--ui-scale)) !important;
}

.selectize-input input {
  font: var(--text-tiny-semibold);
  width: 100% !important; /* Text was getting cut off by default. */
}

#current-tags-list {
  display: flex; /* display:none when there are no tags, display: flex when there are; updated in JS. */
  flex-wrap: wrap;
  gap: calc(5px * var(--ui-scale));
  margin-bottom: calc(10px * var(--ui-scale));
}

/* Shared pill look (including the active green background) from tag-pills.css; this only adds the X-to-remove gap. */
.current-tag.tag-pill {
  cursor: default;
}

.remove-tag-x {
  cursor: pointer;
  width: calc(9px * var(--ui-scale));
  height: calc(9px * var(--ui-scale));
  fill: var(--color-neutral-black);
}

.remove-tag-x svg {
  display: block;
  width: 100%;
  height: 100%;
}

.selectize-dropdown-content {
  display: flex;
  width: calc(285px * var(--ui-scale));
  height: fit-content;
  max-height: calc(200px * var(--ui-scale)); /* Selectize's own stylesheet caps this at a fixed 200px. */
  padding: calc(12px * var(--ui-scale));
  align-items: center;
  align-content: center;
  gap: calc(6px * var(--ui-scale));
  flex-wrap: wrap;
}

/* Selectize renders its own .option nodes; DesktopValidationMenu adds the tag-pill classes so they pick up the
   shared pill look. These rules out-rank selectize's own stylesheet, which is more specific than .tag-pill. */
.selectize-dropdown .option.tag-pill {
  padding: calc(5px * var(--ui-scale)) calc(10px * var(--ui-scale));
  font: var(--text-tiny-semibold);
  text-align: center;
  transition: all 0.3s;

  /* Selectize wraps the matched search substring in a <span class="highlight">, splitting the option's text into
     separate children. The shared .tag-pill class is an inline-flex container with a gap, which would then insert a
     visible space around the highlight span (#4523). Zero the gap here to fix the issue. */
  gap: 0;
}

/* Removing default styling for "active" options in dropdown. Would be left over after hover. */
.selectize-dropdown .option.active {
  background: inherit;
  color: inherit;
}

.selectize-dropdown .option.tag-pill:hover {
  background: var(--color-pine-200);
  outline: none;
}

#severity-radio-holder {
  display: flex;
  align-items: center;
  gap: calc(16px * var(--ui-scale));
}

#optional-comment-input {
  margin-top: 0; /* Overrides .validate-text-input margin, since the textbox for agreeing looks different. */
}

#no-reason-options, #unsure-reason-options {
  display: flex;
  flex-direction: column;
  gap: calc(10px * var(--ui-scale));
}

.validation-reason-button {
  display: flex;
  height: calc(36px * var(--ui-scale));
  justify-content: center;
  align-items: center;
  border: calc(1px * var(--ui-scale)) solid var(--color-neutral-700);
  background-color: var(--color-neutral-white);
}

/* Matching style of 'No' and 'Unsure' button for now. */
#no-reason-options .validation-reason-button.chosen {
  background: var(--color-orange-400);
  border: none;
  color: var(--color-neutral-white);
}

#add-disagree-comment.chosen {
  border-color: var(--color-orange-400) !important;
}

#unsure-reason-options .validation-reason-button.chosen {
  background: var(--color-neutral-900);
  border: none;
  color: var(--color-neutral-white);
}

#add-unsure-comment.chosen {
  border-color: var(--color-orange-900) !important;
}

/* Only show hover states on non-touch devices. Same CSS as for chosen state. */
@media (hover: hover) {
  #no-reason-options .validation-reason-button:hover {
    background: var(--color-orange-300);
    border: none;
    color: var(--color-neutral-white);
  }

  #no-reason-options .validation-reason-button.chosen:hover {
    background: var(--color-orange-400);
  }

  #add-disagree-comment:hover {
    border-color: var(--color-orange-300) !important;
  }

  #add-disagree-comment.chosen:hover {
    border-color: var(--color-orange-400) !important;
  }

  #unsure-reason-options .validation-reason-button:hover {
    background: var(--color-neutral-700);
    border: none;
    color: var(--color-neutral-white);
  }

  #unsure-reason-options .validation-reason-button.chosen:hover {
    background: var(--color-neutral-900);
  }

  #add-unsure-comment:hover {
    border-color: var(--color-neutral-700) !important;
  }

  #add-unsure-comment.chosen:hover {
    border-color: var(--color-neutral-900) !important;
  }
}

/* Tooltip example images (reason buttons, tags, severity) are sized by JS via this class so they scale with the UI. */
.validate-tooltip-img {
  height: calc(140px * var(--ui-scale));
}
.disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.noselect {
  -webkit-touch-callout: none; /* iOS Safari */
  -webkit-user-select: none; /* Safari */
}

.mission-start-tutorial-overlay {
  position: absolute;
  height: calc(100% - var(--navbar-height));
  width: 100%;
  background: var(--color-neutral-white);
  z-index: 11;
  display: none; /* Will be later set to flex by JS after rendering. */
  flex-shrink: 0;
  justify-content: flex-start;
  overflow: auto;
  flex-direction: column;

  --arrow-button-width: calc(30px * var(--ui-scale, 1));
  --arrow-button-margin: calc(30px * var(--ui-scale, 1));

  --mst-base-width: 1095px;
  --mst-h-margin: 40px;
}

.mst-content {
  width: calc(var(--mst-base-width) * var(--ui-scale, 1));
  margin: 0 auto;
}

.mst-instruction-1 {
  font: var(--text-title-bold);
  margin-top: calc(8px * var(--ui-scale, 1));
  padding: 0 calc(70px * var(--ui-scale, 1));
  width: 100%;
  height: fit-content;
}


.mst-instruction-2 {
  font: var(--text-subtitle-bold);
  margin: calc(5px * var(--ui-scale, 1)) 0;
  padding: 0 calc(70px * var(--ui-scale, 1));
  width: 100%;
}

.mst-carousel {
  display: flex;
  flex-shrink: 0;
  width: 100%;
  height: calc(436px * var(--ui-scale, 1));
  margin-top: calc(10px * var(--ui-scale, 1));
}

.previous-slide-button, .next-slide-button {
  height: 100%;
  width: var(--arrow-button-width);
  display: flex;
  fill: var(--color-neutral-700);
  cursor: pointer;
}

.previous-slide-button:not(.disabled):hover, .next-slide-button:not(.disabled):hover {
  fill: var(--color-neutral-black);
}

.previous-slide-button {
  margin-right: var(--arrow-button-margin);
}

.next-slide-button {
  margin-left: var(--arrow-button-margin);
}

.mst-slide {
  height: 100%;
  display: flex;
  flex-shrink: 0;
  flex-wrap: wrap;
  width: calc(100% - 2 * (var(--arrow-button-width) + var(--arrow-button-margin)));
  justify-content: space-between;
}

.mst-text-area {
  width: calc(290px * var(--ui-scale, 1));
  display: flex;
  flex-shrink: 0;
  flex-flow: column wrap;
  position: relative;
}

.label-type-title {
  font: var(--text-title-bold);
  text-align: left;
  margin-bottom: calc(15px * var(--ui-scale, 1));
  padding: 0 calc(10px * var(--ui-scale, 1));
}

.label-type-subtitle {
  font: var(--text-body-bold);
  padding: 0 calc(10px * var(--ui-scale, 1));
}

.label-type-description {
  font: var(--text-body-regular);
  text-align: left;
  padding: 0 calc(10px * var(--ui-scale, 1));
  margin-top: calc(10px * var(--ui-scale, 1));
}

.mission-start-tutorial-overlay-footer {
  margin-top: calc(15px * var(--ui-scale, 1));
  width: 100%;
}

.mission-start-tutorial-done-btn {
  font: var(--text-small-bold);
  position: absolute;
  bottom: 0;
  right: 0;
}

.msts-image-area {
  width: calc(658px * var(--ui-scale, 1));
  height: calc(436px * var(--ui-scale, 1));
  float: right;
  background: var(--color-neutral-300);
  display: flex;
  position: relative;
  border-radius: calc(10px * var(--ui-scale, 1));
  overflow: hidden;
}

.msts-image {
  height: 100%;
  width: 100%;
  object-fit: contain;
}

.label-on-image {
  display: none;
  position: absolute;
  background: var(--color-neutral-white);
  border: calc(3px * var(--ui-scale, 1)) solid;
  border-radius: calc(10px * var(--ui-scale, 1));
  box-sizing: content-box;
  min-height: calc(80px * var(--ui-scale, 1));
  max-height: calc(90px * var(--ui-scale, 1));
  min-width: calc(160px * var(--ui-scale, 1));
  max-width: calc(220px * var(--ui-scale, 1));
}

/* correct/incorrect classes are added to the slide element */
.correct .label-on-image {
  border-color: var(--color-pine-700);
}

/* correct/incorrect classes are added to the slide element */
.incorrect .label-on-image {
  border-color: var(--color-error-200);
}

.label-on-image-type {
  margin: calc(10px * var(--ui-scale, 1));
  display: flex;
  align-items: center;
}

.label-on-image-type-icon {
  height: calc(24px * var(--ui-scale, 1));
  width: calc(24px * var(--ui-scale, 1));
  fill: none;
  display: flex;
  margin-right: calc(3px * var(--ui-scale, 1));
}

.correct .label-on-image-type-icon {
  stroke: var(--color-pine-700);
}

.incorrect .label-on-image-type-icon {
  stroke: var(--color-error-200);
}

.label-on-image-type-title {
  display: flex;
  font: var(--text-body-bold);
  margin-left: calc(3px * var(--ui-scale, 1));
}

.correct .label-on-image-type-title {
  color: var(--color-pine-700);
}

.incorrect .label-on-image-type-title {
  color: var(--color-error-200);
}

.label-on-image-description {
  font: var(--text-body-regular);
  margin: 0 calc(12px * var(--ui-scale, 1));
}

.example-type-area {
  display: flex;
  padding: calc(10px * var(--ui-scale, 1));
  margin-bottom: calc(20px * var(--ui-scale, 1));
  position: relative;
}

.example-type-area::after {
  background: #30785D;
  background: var(--color-pine-700);
  width: calc(100% - 20px * var(--ui-scale, 1));
  height: calc(8px * var(--ui-scale, 1));
  position: absolute;
  bottom: calc(-6px * var(--ui-scale, 1));
  content: "";
  left: 50%;
  transform: translateX(-50%);
}

.correct .example-type-area::after {
  background: var(--color-pine-700);
}

.incorrect .example-type-area::after {
  background: var(--color-error-200);
}

.example-type-icon {
  height: calc(24px * var(--ui-scale, 1));
  width: calc(24px * var(--ui-scale, 1));
  display: inline-block;
  margin-right: calc(5px * var(--ui-scale, 1));
  fill: none;
}

.correct .example-type-icon {
  stroke: var(--color-pine-700);
}

.incorrect .example-type-icon {
  stroke: var(--color-error-200);
}

.example-type-label {
  font: var(--text-title-bold);
  display: inline-block;
  margin-left: calc(5px * var(--ui-scale, 1));
}

.correct .example-type-label {
  color: var(--color-pine-700);
}

.incorrect .example-type-label {
  color: var(--color-error-200);
}

.mst-carousel-location-indicator-area {
  height: calc(12px * var(--ui-scale, 1));
  width: 100%;
  padding: calc(5px * var(--ui-scale, 1));
  margin-top: calc(25px * var(--ui-scale, 1));
  display: flex;
  justify-content: center;
  align-items: center;
}

.mst-carousel-location-indicator {
  height: calc(7px * var(--ui-scale, 1));
  width: calc(40px * var(--ui-scale, 1));
  margin: 0 calc(3.5px * var(--ui-scale, 1));
  background: var(--color-neutral-400);
  transition: all 0.4s;
  border-radius: 100px;
}

.mst-carousel-location-indicator.current-location {
  background: var(--color-asphalt-500);
}

/*
 * Explore mission screen tab bar styling
 */
.explore-mission-start-tab-bar {
  width: 100%;
  height: calc(50px * var(--ui-scale, 1));
  display: flex;
  justify-content: space-between;
  margin: calc(5px * var(--ui-scale, 1)) 0;
  padding: 0 calc(2 * var(--arrow-button-margin));
}

.explore-mission-start-tab-content {
  margin: 0 calc(12px * var(--ui-scale, 1));
  display: flex;
  align-items: center;
}

.explore-mission-start-tab.label {
  border-radius: calc(4px * var(--ui-scale, 1)) calc(4px * var(--ui-scale, 1)) 0 0;
  height: 100%;
  width: 100%;
  color: var(--color-neutral-black);
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
  font: var(--text-tiny-semibold);
  text-align: left;
  border-bottom: calc(3px * var(--ui-scale, 1)) solid var(--color-neutral-200);
  padding: 0 calc(3px * var(--ui-scale, 1));
  filter: saturate(0);
  transition: all 0.25s;
}

.explore-mission-start-tab.label:hover, .explore-mission-start-tab.label.active {
  filter: saturate(1);
}

.explore-mission-start-tab.label[data-label-type="CurbRamp"]:hover {
  background: rgb(from var(--color-label-curb-ramp) r g b / 15%);
}

.explore-mission-start-tab.label[data-label-type="NoCurbRamp"]:hover {
  background: rgb(from var(--color-label-no-curb-ramp) r g b / 15%);
}

.explore-mission-start-tab.label[data-label-type="Obstacle"]:hover {
  background: rgb(from var(--color-label-obstacle) r g b / 15%);
}

.explore-mission-start-tab.label[data-label-type="SurfaceProblem"]:hover {
  background: rgb(from var(--color-label-surface-problem) r g b / 15%);
}

.explore-mission-start-tab.label[data-label-type="NoSidewalk"]:hover {
  background: rgb(from var(--color-label-no-sidewalk) r g b / 15%);
}

.explore-mission-start-tab.label[data-label-type="Crosswalk"]:hover {
  background: rgb(from var(--color-label-crosswalk) r g b / 15%);
}

.explore-mission-start-tab.label[data-label-type="Signal"]:hover {
  background: rgb(from var(--color-label-signal) r g b / 15%);
}


/* Selected tabs */
.explore-mission-start-tab.label[data-label-type="CurbRamp"].active {
  background: rgb(from var(--color-label-curb-ramp) r g b / 15%);
  border-bottom-color: var(--color-label-curb-ramp);
}

.explore-mission-start-tab.label[data-label-type="NoCurbRamp"].active {
  background: rgb(from var(--color-label-no-curb-ramp) r g b / 15%);
  border-bottom-color: var(--color-label-no-curb-ramp);
}

.explore-mission-start-tab.label[data-label-type="Obstacle"].active {
  background: rgb(from var(--color-label-obstacle) r g b / 15%);
  border-bottom-color: var(--color-label-obstacle);
}

.explore-mission-start-tab.label[data-label-type="SurfaceProblem"].active {
  background: rgb(from var(--color-label-surface-problem) r g b / 15%);
  border-bottom-color: var(--color-label-surface-problem);
}

.explore-mission-start-tab.label[data-label-type="NoSidewalk"].active {
  background: rgb(from var(--color-label-no-sidewalk) r g b / 15%);
  border-bottom-color: var(--color-label-no-sidewalk);
}

.explore-mission-start-tab.label[data-label-type="Crosswalk"].active {
  background: rgb(from var(--color-label-crosswalk) r g b / 15%);
  border-bottom-color: var(--color-label-crosswalk);
}

.explore-mission-start-tab.label[data-label-type="Signal"].active {
  background: rgb(from var(--color-label-signal) r g b / 15%);
  border-bottom-color: var(--color-label-signal);
}


.explore-mission-start-tab-icon {
  width: calc(30px * var(--ui-scale, 1));
  height: calc(30px * var(--ui-scale, 1));
  margin-right: calc(7px * var(--ui-scale, 1));
  flex-shrink: 0; /* Keep the icon at full size when the tab row gets squeezed, so it isn't clipped. */
  display: flex;
  justify-content: center;
  align-items: center;
}

/* Let the SVG overflow rather than clip. When floating point widths, they can slightly flow outside the box. */
.explore-mission-start-tab-icon svg {
  width: 100%;
  height: 100%;
  overflow: visible;
}

.explore-mission-start-tab-text {
  width: 70%;
  white-space: initial;
}
