/* ── Detail view ── */

/* When <main> is on an activity route, drop the feed column cap so the
   detail page can span the full viewport and host a side-by-side layout
   on wide screens. */
.activity-main {
  width: 100%;
}

.activity-detail {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
}

/* The wall→detail morph pairs the tapped card's thumbnail with this pane, so
   the card grows into the map instead of the page cutting. The pane rather
   than the placeholder inside it: a `view-transition-name` has to be in the
   DOM when the browser captures the new state, and the placeholder is not —
   it waits on the GPS trace, which the wall never loaded. Naming it produced
   an unpaired `::view-transition-old` and no morph at all. */
.activity-detail-map-pane {
  position: relative;
  height: 60vh;
  background: var(--surface-alt);
  overflow: hidden;
  view-transition-name: activity-hero;
}

/* ActivityMapDetail wraps the map in a relative div; make it fill the pane
   so the inner `.maplibre-map` (height: 100%) actually resolves to a real
   height. */
.activity-detail-map-pane > div,
.activity-detail-map-pane .maplibre-map,
.activity-detail-map-pane .map-no-gps {
  height: 100%;
}

/* Frame for the static map PNG held over the live map until it paints. Fills
   the pane and clips: the image inside is scaled up and offset to register
   against the live map's camera, so it overflows this box on nearly every
   route. */
.detail-map-placeholder {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 1;
  opacity: 1;
  transition: opacity 220ms ease-out;
}

.detail-map-placeholder.faded {
  opacity: 0;
}

/* `syncStaticOverlay` overwrites width/height/transform on every frame the
   live map draws, putting the image's route exactly where the live map's is,
   and reveals the image once it has. Hidden until then — the fallback framing
   below is a whole zoom step out, and showing it first would put back the
   jump this is here to remove. The same call reveals it unchanged if no map
   ever appears, so a failure degrades to the letterboxed framing rather than
   to nothing. */
.detail-map-placeholder-img {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  transform-origin: 0 0;
  opacity: 0;
}

/* The card side of the morph, set only while that card is opening — a
   `view-transition-name` must be unique in the document, and every other card
   carries the same class. */
.activity-card.opening .card-map-img {
  view-transition-name: activity-hero;
}

/* The card thumbnail is 3:1 and the pane it grows into is nearer square.
   Default `fill` would stretch the snapshot flat during the tween; `cover`
   crops it towards the centre instead, which is the direction the pane's own
   framing is already heading — so the whole open reads as one push into the
   route. */
::view-transition-old(activity-hero),
::view-transition-new(activity-hero) {
  object-fit: cover;
}

.activity-detail-content-pane {
  padding: 16px 16px 32px;
  max-width: 640px;
  margin: 0 auto;
  width: 100%;
  box-sizing: border-box;
  animation: detail-panel-in 320ms cubic-bezier(0.22, 0.8, 0.2, 1) both;
}

/* The panel arrives from the viewport edge it sits against while the map pane
   morphs out of the tapped card: from below on narrow screens, from the side
   on wide ones.
   A plain animation on the element rather than a `view-transition-name` and
   `::view-transition-new`: naming it makes it a containing block for its
   `position: fixed` descendants, which pins the photo lightbox and the menu
   backdrop to the panel instead of the viewport. This also gives the slide to
   browsers without view transitions, where the pane simply appears mid-slide
   with nothing to morph out of. */
@keyframes detail-panel-in {
  from {
    transform: translateY(24vh);
    opacity: 0;
  }
  to {
    transform: none;
    opacity: 1;
  }
}

@keyframes detail-panel-in-side {
  from {
    transform: translateX(100%);
    opacity: 0;
  }
  to {
    transform: none;
    opacity: 1;
  }
}

@media (min-width: 1024px) {
  .activity-detail {
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    align-items: start;
    min-height: calc(100vh - var(--chrome-h));
  }

  .activity-detail-map-pane {
    position: sticky;
    top: var(--chrome-h);
    height: calc(100vh - var(--chrome-h));
    border-right: 1px solid var(--border);
  }

  .activity-detail-content-pane {
    max-width: 560px;
    padding: 28px 24px 56px;
    animation-name: detail-panel-in-side;
  }
}

.back-btn {
  align-self: flex-start;
  background: none;
  border: none;
  color: var(--accent);
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  padding: 4px 0 16px;
  letter-spacing: 0.2px;
}

.back-btn:hover {
  text-decoration: underline;
}

.detail-top-bar {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}

.detail-menu-wrapper {
  position: relative;
}

.detail-menu-btn {
  background: none;
  border: none;
  font-size: 1.4rem;
  color: var(--text-muted);
  cursor: pointer;
  padding: 4px 8px;
  line-height: 1;
  border-radius: 6px;
  letter-spacing: 2px;
}

.detail-menu-btn:hover {
  background: var(--surface-alt);
}

.detail-menu-backdrop {
  position: fixed;
  inset: 0;
  z-index: 99;
}

.detail-menu {
  position: absolute;
  right: 0;
  top: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow-md);
  min-width: 200px;
  z-index: 100;
  padding: 4px 0;
}

.detail-menu-item {
  display: block;
  width: 100%;
  background: none;
  border: none;
  padding: 10px 16px;
  font-size: 0.9rem;
  font-family: inherit;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  color: var(--text);
}

.detail-menu-item:hover {
  background: var(--surface-alt);
}

.detail-menu-item.danger {
  color: var(--danger);
}

.detail-menu-item.danger:hover {
  background: var(--danger-soft);
}

.detail-header {
  background: var(--surface);
  padding: 16px 16px 12px;
  border-radius: 14px 14px 0 0;
}

.detail-title {
  font-size: 1.25rem;
  font-weight: 800;
  color: var(--text);
  line-height: 1.3;
}

.detail-title-editable {
  cursor: text;
  border-radius: 4px;
  margin: 0 -4px;
  padding: 0 4px;
  transition: background 0.1s;
}

.detail-title-editable:hover {
  background: var(--surface-alt);
}

.detail-title-input {
  font-size: 1.25rem;
  font-weight: 800;
  color: var(--text);
  line-height: 1.3;
  width: 100%;
  border: none;
  border-bottom: 2px solid var(--accent);
  border-radius: 0;
  background: transparent;
  outline: none;
  padding: 0;
  font-family: inherit;
}

/* ── Charts ── */

.chart-section {
  background: var(--surface);
  padding: 14px 16px 10px;
  border-top: 1px solid var(--border);
}

.chart-title {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--text-subtle);
  margin-bottom: 6px;
}

.line-chart {
  width: 100%;
  height: auto;
  display: block;
}

.chart-tick {
  font-size: 11px;
  fill: var(--text-subtle);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

/* ── Stats bar ── */

/* Wraps instead of overflowing: an activity with many metrics (HR,
   cadence, …) gets a second row rather than clipping at the pane edge. */
.activity-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
  border-top: 1px solid var(--border);
}

.stat-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 12px 8px;
  gap: 2px;
}

.stat-value {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text);
}

.stat-label {
  font-size: 0.68rem;
  color: var(--text-subtle);
  text-transform: uppercase;
  letter-spacing: 0.6px;
}

.detail-device {
  margin: 8px 16px 0;
  color: var(--text-muted);
  font-size: 0.8rem;
}

.detail-description {
  margin: 12px 16px 0;
  font-size: 0.9rem;
  line-height: 1.5;
  white-space: pre-wrap;
  cursor: text;
  border-radius: 4px;
  padding: 4px 6px;
  color: var(--text);
}

.detail-description-editable:hover {
  background: var(--surface-alt);
}

.detail-description-empty {
  color: var(--text-muted);
  font-style: italic;
}

.detail-description-empty:hover {
  background: var(--surface-alt);
}

.detail-description-textarea {
  display: block;
  margin: 12px 16px 0;
  width: calc(100% - 32px);
  min-height: 80px;
  font-size: 0.9rem;
  font-family: inherit;
  line-height: 1.5;
  padding: 4px 6px;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  resize: vertical;
  box-sizing: border-box;
  background: var(--surface);
  color: var(--text);
}

/* ── Gear Picker (Activity Detail) ── */

.gear-picker {
  margin: 8px 0 12px;
  position: relative;
}

.gear-picker-current {
  font-size: 0.9rem;
  color: var(--text-muted);
  cursor: pointer;
}

.gear-picker-current:hover {
  color: var(--text);
}

.gear-picker-empty {
  color: var(--text-subtle);
  font-style: italic;
}

.gear-picker-dropdown {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  box-shadow: var(--shadow-md);
  overflow: hidden;
  min-width: 200px;
}

.gear-picker-option {
  padding: 10px 14px;
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--text);
}

.gear-picker-option:hover {
  background: var(--surface-alt);
}

.gear-picker-option.selected {
  font-weight: 600;
}
