/* ---------- View toggle + map ---------- */

/* Moved from a fixed floating pill into #side-menu's "View" section
   2026-08-22 (Malte: only show it there) - now a normal in-flow
   segmented control, same visual pattern as .filter-type. */
.view-toggle {
  display: flex;
  border: 1px solid var(--black);
}

.view-toggle-btn,
.cluster-tap-toggle-btn {
  flex: 1;
  font-family: inherit;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 10px 18px;
  border: none;
  background: transparent;
  color: var(--black);
  cursor: pointer;
}

.view-toggle-btn + .view-toggle-btn,
.cluster-tap-toggle-btn + .cluster-tap-toggle-btn {
  border-left: 1px solid var(--black);
}

.view-toggle-btn.active,
.cluster-tap-toggle-btn.active {
  background: var(--black);
  color: var(--white);
}

/* ---------- flatpickr theme override (issue #58) ----------
   Default flatpickr is a white rounded card with a blue accent - retuned
   to this app's monochrome, sharp-cornered, hairline-bordered language
   (see the "Design decisions" section of AI-HANDOFF.md: no color accents,
   no rounded corners) rather than living as a visibly bolted-on widget. */
.flatpickr-calendar {
  font-family: "Inter", sans-serif;
  border-radius: 0;
  border: 1px solid var(--black);
  box-shadow: none;
}

.flatpickr-calendar.arrowTop:before,
.flatpickr-calendar.arrowTop:after {
  display: none; /* the little pointer triangle - redundant with the hairline border above */
}

.flatpickr-months .flatpickr-month,
.flatpickr-current-month,
.flatpickr-weekdays,
span.flatpickr-weekday {
  background: var(--white);
  color: var(--black);
}

.flatpickr-months .flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month {
  color: var(--black);
  fill: var(--black);
}

.flatpickr-day {
  /* position:relative already comes from flatpickr's own base CSS; z-index:0
     turns it into a real stacking context so the ::after density fill
     below (issue #90) can't paint in front of this element's own
     background - .selected/.inRange set that background on this same
     element, so they naturally win over the density fill once a day is
     actually picked. */
  z-index: 0;
  border-radius: 0;
  color: var(--black);
}

/* Issue #90: "je mehr Fotos/Videos, desto deutlicher, je weniger desto
   blasser und transparenter" - graded opacity on --black (the monochrome
   rule allows alpha, not a new hue), read from a CSS custom property so
   JS never touches box-shadow/background directly and fights the rules
   above. --density defaults to 0 (no entries that date = invisible). */
.flatpickr-day::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(17, 17, 17, var(--density, 0));
  pointer-events: none;
}

/* A video that date is a distinguishable FORM (a dot), not a second hue -
   currentColor so it's black normally and turns white for free once
   .selected/.startRange/.endRange set color:var(--white) above. */
.flatpickr-day.has-video::before {
  content: "";
  position: absolute;
  bottom: 3px;
  left: 50%;
  transform: translateX(-50%);
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: currentColor;
  pointer-events: none;
}

.flatpickr-day.flatpickr-disabled,
.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay {
  color: var(--grey-light);
}

/* Selected day / range endpoints: solid black, same "active" treatment
   .filter-type button.active already uses - one consistent selected-state
   language across the filter panel. The :hover/:focus variants are not
   redundant - flatpickr's own default CSS bundles them into the SAME
   higher-specificity rule as .selected/.startRange/.endRange (3 selector
   components vs. these 2), so without matching that here, the moment a
   real cursor sits on the day it just selected (i.e. immediately after
   every click) it would revert to flatpickr's default blue - caught by
   screenshotting the actual clicked state, not just reading the CSS. */
.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.endRange,
.flatpickr-day.selected:hover,
.flatpickr-day.startRange:hover,
.flatpickr-day.endRange:hover,
.flatpickr-day.selected:focus,
.flatpickr-day.startRange:focus,
.flatpickr-day.endRange:focus {
  background: var(--black);
  border-color: var(--black);
  color: var(--white);
}

.flatpickr-day.inRange {
  background: var(--off-white);
  border-color: var(--off-white);
  box-shadow: -5px 0 0 var(--off-white), 5px 0 0 var(--off-white);
}

.flatpickr-day.today {
  border-color: var(--grey-light);
}

.flatpickr-day:hover {
  background: var(--off-white);
}

.map-view {
  position: fixed;
  inset: 0;
  z-index: 30;
  background: var(--off-white);
}

.map-view[hidden] {
  display: none;
}

#map {
  width: 100%;
  height: 100%;
  /* Leaflet's own panes/controls (leaflet.css) reach z-index up to 1000 -
     without this, #map-empty's sibling z-index:40 (issue #92) has to
     out-rank those internal values directly and loses. Leaflet already
     sets position:relative on this element; z-index:0 turns that into a
     real stacking context, so everything inside it - however high its
     internal z-index climbs - is contained below any sibling with a
     higher z-index than 0, like #map-empty. */
  z-index: 0;
}

/* menuToggle (fixed, top:18px/left:18px, 38x38px, see .menu-toggle above)
   stays visible over the map now (issue #33) - it's the only way back to
   the timeline. Leaflet's default top-left zoom control would otherwise
   sit in the exact same spot, so push it down below the button instead
   of letting them overlap. */
.map-view .leaflet-top.leaflet-left {
  top: 68px;
}

.map-empty {
  position: absolute;
  inset: 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  background: var(--off-white);
  text-align: center;
  padding: 20px;
}

.map-empty[hidden] {
  display: none;
}

.map-empty p {
  font-family: "Inter", sans-serif;
  font-size: 0.85rem;
  color: var(--grey-light);
}

.photo-marker-thumb {
  position: relative; /* anchor for .photo-marker-date, issue #146 */
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background-color: var(--off-white);
  background-size: cover;
  background-position: center;
  border: 2px solid var(--white);
  box-shadow: 0 0 0 1.5px var(--black), 0 4px 10px -4px rgba(17, 17, 17, 0.5);
  cursor: pointer;
}

/* Issue #146 (Malte: date/time next to each photo once it's shown
   individually, i.e. no longer merged into a cluster bubble - "any side
   of them, avoid other markers, clearly connected, readability is KEY").
   map.js's updateMarkerDateLabels() picks one of the 4 .label-* positions
   below per marker, steering it away from whichever neighboring bubble
   would otherwise sit closest to it. Solid monochrome pill (not a
   translucent one) so it stays legible over any tile color underneath -
   same reasoning as .photo-cluster's solid fill. pointer-events:none: this
   is a legend, not a second tap target - taps always land on the thumb
   itself, consistent with "tapping a marker/cluster always opens photos". */
.photo-marker-date {
  position: absolute;
  padding: 3px 7px;
  border-radius: 4px;
  background: var(--black);
  color: var(--white);
  font-family: "Inter", sans-serif;
  font-size: 0.68rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  white-space: nowrap;
  box-shadow: 0 0 0 1px var(--black), 0 2px 6px -2px rgba(17, 17, 17, 0.5);
  pointer-events: none;
}

/* Small triangular tail pointing back at the thumb - keeps an offset label
   (chosen to dodge a neighbor, so not always immediately adjacent) reading
   as clearly connected to THIS photo rather than a loose floating label. */
.photo-marker-date::after {
  content: "";
  position: absolute;
  width: 0;
  height: 0;
  border: 4px solid transparent;
}

.photo-marker-date.label-right { left: 100%; top: 50%; margin-left: 8px; transform: translateY(-50%); }
.photo-marker-date.label-right::after { right: 100%; top: 50%; margin-top: -4px; border-right-color: var(--black); }

.photo-marker-date.label-left { right: 100%; top: 50%; margin-right: 8px; transform: translateY(-50%); }
.photo-marker-date.label-left::after { left: 100%; top: 50%; margin-top: -4px; border-left-color: var(--black); }

.photo-marker-date.label-bottom { top: 100%; left: 50%; margin-top: 8px; transform: translateX(-50%); }
.photo-marker-date.label-bottom::after { bottom: 100%; left: 50%; margin-left: -4px; border-bottom-color: var(--black); }

.photo-marker-date.label-top { bottom: 100%; left: 50%; margin-bottom: 8px; transform: translateX(-50%); }
.photo-marker-date.label-top::after { top: 100%; left: 50%; margin-left: -4px; border-top-color: var(--black); }

.photo-cluster {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--black);
  color: var(--white);
  font-family: "Inter", sans-serif;
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  border: 2px solid var(--white);
  box-shadow: 0 0 0 1px var(--black);
}

.leaflet-popup-content-wrapper {
  border-radius: 0;
}

/* Issue #123: chronological route line - thin/monochrome/unobtrusive per
   AI-HANDOFF.md's map design decisions, not a competing visual to the
   photo markers. stroke via a CSS class (not Leaflet's `color` option) so
   it reads from the same --black token as the rest of the app instead of
   a hardcoded hex living in JS. */
.route-line {
  stroke: var(--black);
  stroke-opacity: 0.35;
}

/* Small triangle, CSS-only (no image asset) - JS only sets which way it
   points (inline transform:rotate, computed in pure.js's routeArrows). */
.route-arrow {
  width: 0;
  height: 0;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  border-left: 6px solid var(--black);
  opacity: 0.45;
}

