/* Trail Log — Glass Dock theme. Dark chrome (Alpine Dusk tokens) with
   liquid glass. Detail panel opens inline inside the left drawer
   (app-controller.js's inlineDetail mode), not as a separate panel. */
:root {
  --paper:   #1a2030;
  --paper-2: #222a3c;
  --paper-3: #2a3245;
  --ink:     #fdfaf1;
  --ink-2:   #e6dcc1;
  --ink-3:   #a2957c;
  --line:    #3c4560;
  --accent:  #E5F53B;
  /* Fixed heart-rate color — deliberately not --accent or any sport color,
     since it needs to read the same way regardless of which activity or
     sport type is selected. Used for the HR chart trace and its toggle. */
  --hr:      #7fb0d9;

  --bg: var(--paper);
  --page-bg: var(--paper);
  --surface: var(--paper-2);
  --surface-2: var(--paper-3);
  --text-1: var(--ink);
  --text-2: var(--ink-2);
  --text-3: var(--ink-3);
  --border: var(--line);

  --glass-bg: rgba(24, 29, 44, 0.84);
  --glass-border: rgba(120, 132, 168, 0.38);
  --glass-blur: 22px;
  --glass-sat: 1.4;

  --select-bg: rgba(229, 245, 59, 0.10);
  --row-hover-bg: rgba(246, 239, 223, 0.055);
  --thumb-bg: rgba(246, 239, 223, 0.07);
  --radius: 18px;
  --radius-sm: 12px;
}

body { background: var(--page-bg); }

.year-check { background: var(--paper-3); }
.year-option.checked .year-check::after { border-color: #1a2030; }
.replay-btn { background: var(--accent); color: #1a2030; }
.detail-close { color: var(--ink-2); }

/* Selection is background-only — no left-edge bar, which previously
   borrowed the sport's own colour and read as an unwanted focus ring. */
.activity-item.selected::before { content: none; }
.activity-item.selected { background: var(--select-bg); }

.activity-meta { font-size: 13.9px; }

/* .activity-name is a <span> (inline) — text-overflow:ellipsis never
   actually applies to inline elements, so a long title just overflowed
   uncontained. display:block + wrap instead of truncate. */
.activity-name {
  display: block;
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  line-height: 1.3;
}
.activity-item { align-items: flex-start; padding-top: 10px; padding-bottom: 10px; }
.activity-thumb { margin-top: 1px; }
/* overflow-anchor:none: without it, the detail panel expanding above the
   scroll position makes the browser auto-scroll to compensate, fighting
   app-controller.js's own scrollIntoView(). */
.activity-list { overflow-x: hidden; overflow-anchor: none; }

/* Specular rim + deep drop shadow — most of what reads as "glass". */
.brand-island, .drawer, .hover-label, .year-select-panel {
  box-shadow:
    0 24px 60px rgba(0,0,0,0.55),
    inset 0 1px 0 rgba(255,255,255,0.14),
    inset 0 0 0 1px rgba(255,255,255,0.05);
}
.clear-filters-btn, .year-select-trigger, .drawer-toggle,
.leaflet-control-zoom a, .leaflet-control-recenter a, .replay-btn, .detail-close {
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.12);
}

/* ── Title island, width-matched to the drawer below it ───────*/
.brand-island {
  position: fixed;
  top: 16px; left: 16px;
  width: 372px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  padding: 0 24px;
  z-index: 1500;
}
.brand-island .brand {
  display: flex; align-items: center; gap: 14px;
  font-family: var(--display); font-size: 15.5px; font-weight: 700;
  letter-spacing: 0.5em; text-transform: uppercase; color: var(--ink);
  text-decoration: none;
}
.brand-island .brand svg { width: 18px; height: 18px; color: var(--accent); flex-shrink: 0; }

/* ── Search: activity-title filter, one row above the sport/year
   filters. Same 6px horizontal inset as .drawer-filters below it (its
   own 6px padding), so both rows share the same left/right edge. ───*/
.drawer-search {
  display: flex; align-items: center; gap: 8px;
  height: 32px;
  margin: 0 6px 14px;
  padding: 0 12px;
  background: var(--paper-2);
  border: 1.5px solid var(--line);
  border-radius: 20px;
  color: var(--ink-3);
  transition: border-color 0.15s, color 0.15s;
}
.drawer-search:focus-within { border-color: var(--accent); color: var(--ink); }
.drawer-search svg { width: 14px; height: 14px; flex-shrink: 0; opacity: 0.7; }
.drawer-search input {
  all: unset; flex: 1; min-width: 0;
  color: var(--ink); font-family: var(--body); font-size: 13.8px;
}
.drawer-search input::placeholder { color: var(--ink-3); }

/* ── Filters: activity/year dropdowns + Clear filters, one row
   under the search field. ─────────────────────────────────────*/
.drawer-filters {
  display: flex; align-items: center; gap: 8px;
  padding: 0 6px 14px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--glass-border);
}
.drawer-filters > div { flex: 1; min-width: 0; }
.drawer-filters .year-select-trigger {
  width: 100%; justify-content: space-between;
  height: 32px;
  padding: 0 10px; font-size: 13.9px;
}
.drawer-filters .year-select-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drawer-filters .clear-filters-btn {
  flex-shrink: 0;
  height: 32px;
  display: flex; align-items: center; justify-content: center;
  padding: 0 12px; font-size: 13.4px;
}

/* ── Drawer: flex column so the stats header has a fixed height
   and the list takes the rest. ───────────────────────────────*/
.drawer {
  width: 372px;
  /* dashboard-layout.css's default (86px) assumed the old 58px-tall island
     plus a 12px gap; this variant's island is 44px, same 12px gap. */
  top: 72px;
  display: flex;
  flex-direction: column;
  /* Nearly opaque, decoupled from --glass-bg — the drawer is the main
     reading surface and needs to stay solid regardless of the map behind it. */
  background: rgba(15, 18, 28, 0.96);
}
.activity-list { flex: 1; min-height: 0; height: auto; }
/* Offset accounts for Leaflet's own 10px control-corner margin plus the
   1px width difference (30px toggle vs 32px controls), so centers align. */
/* dashboard-layout.css's default top (106px) tracks its own default
   drawer top (86px) — offset by the same 14px this variant's .drawer
   shifted up when the island shrank. */
.drawer-toggle { top: 92px; left: 415px; }
body.drawer-collapsed .drawer-toggle { left: 27px; }

.drawer-stats {
  display: flex;
  padding: 8px 6px 14px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--glass-border);
}
.drawer-stats .dstat2 { flex: 1; text-align: center; }
.drawer-stats .figure { font-size: 29.5px; display: block; color: var(--ink); }
.drawer-stats .label { font-size: 12.3px; display: block; margin-top: 4px; color: var(--ink-3); text-transform: uppercase; letter-spacing: 0.06em; }

/* ── Detail panel: inline inside the drawer, under the selected
   row. Height animates from 0 as a normal-flow list item. ────*/
.detail-panel {
  position: static;
  width: 100%;
  left: auto; right: auto; bottom: auto;
  transform: none;
  opacity: 1;
  pointer-events: auto;
  /* flex-shrink:0: overflow:hidden zeroes this item's normal "don't
     shrink below content" floor (flexbox auto-min-size spec) — without
     it, flexbox crushes the panel to a sliver to fit the visible height
     instead of letting .activity-list scroll. */
  flex-shrink: 0;
  height: 0;
  padding: 0 4px;
  margin: 0;
  border-radius: 14px;
  overflow: hidden;
  box-shadow: none;
  background: rgba(255,255,255,0.03);
  transition: height 0.42s var(--ease-out), padding 0.42s var(--ease-out), margin 0.42s var(--ease-out);
  /* One spacing system for every row inside the panel — see the rows
     below, which are tokenized off this same value instead of carrying
     their own ad-hoc margins/padding. */
  --detail-gap: 12px;
  gap: var(--detail-gap);
}
.detail-panel.open {
  /* app-controller.js measures the panel's real content height and sets
     it inline (content is now variable — some activities have no HR/
     calorie row at all) — this is only a fallback in case that ever fails. */
  height: 400px;
  padding: 16px 14px;
  margin: 2px 0 8px;
}

.detail-top { align-items: flex-start; }
.detail-id { flex: 1 1 0; min-width: 0; }
.detail-actions { flex-shrink: 0; }
.detail-stats {
  justify-content: space-between;
  /* Matches --detail-gap so the space above this border (the panel's own
     flex gap) and below it (this padding) are the same number. */
  padding-top: var(--detail-gap);
  border-top: 1px solid var(--glass-border);
}
/* Second, quieter tier: HR/calories, only rendered when an activity
   actually has that data (see secondaryStatBlock() in app-controller.js). */
.detail-stats-secondary { display: flex; justify-content: space-between; }
.detail-stats-secondary:empty { display: none; }
.dstat2nd { text-align: center; }
.dstat2nd-v {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  font-size: 14px; font-weight: 700; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.dstat2nd-v svg { flex-shrink: 0; opacity: 0.85; }
.dstat2nd-v .hr-icon { color: var(--hr); }
.dstat2nd-v .cal-emoji { font-size: 12px; line-height: 1; }
.dstat2nd-l {
  font-size: 10.5px; color: var(--ink-3); opacity: 0.85;
  text-transform: uppercase; letter-spacing: 0.05em; margin-top: 2px;
}

/* HR chart toggle — label and switch live in one control, sized to its
   own content (not spread across the row), hidden entirely when the
   selected activity has no HR data at all. */
.hr-toggle-row {
  display: none;
  align-items: center; gap: 8px;
  align-self: flex-start;
  background: none; border: none;
  /* Padding grows the actual tap target; the equal negative margin cancels
     it back out for layout/visual purposes, so the row still sits and
     spaces exactly as if the padding weren't there. */
  padding: 10px 8px;
  margin: -10px -8px;
  cursor: pointer;
}
.hr-toggle-row.visible { display: inline-flex; }
.hr-toggle-row:hover .hr-toggle-label { color: var(--ink-2); }
.hr-toggle-row:focus-visible { outline: 2px solid var(--hr); outline-offset: 2px; border-radius: 8px; }
.hr-toggle-label {
  font: 600 12.5px var(--label);
  letter-spacing: 0.01em;
  color: var(--ink-3);
  transition: color 0.15s;
}
.hr-toggle-row.on .hr-toggle-label { color: var(--ink); }
.hr-switch {
  position: relative;
  width: 32px; height: 18px;
  border-radius: 999px;
  background: var(--paper-3);
  border: 1px solid var(--line);
  flex-shrink: 0;
  transition: background 0.18s, border-color 0.18s;
}
.hr-switch-knob {
  position: absolute;
  top: 1px; left: 1px;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--ink-3);
  transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1), background 0.18s;
}
.hr-toggle-row.on .hr-switch { background: var(--hr); border-color: var(--hr); }
.hr-toggle-row.on .hr-switch-knob { transform: translateX(14px); background: #1a2030; }

.detail-title { max-width: 230px; }
.detail-chart-wrap { min-height: 170px; }

/* The drawer is the only real map occlusion; controls sit in the gap
   to its right, tracked via --controls-left-offset. */
body.proto-v2 {
  --occlusion-left: 404px;
  /* 16px top offset + 44px island height + 16px gap to the drawer below it. */
  --occlusion-top: 76px;
  --occlusion-right: 40px;
  --occlusion-bottom: 56px;
  --controls-left-offset: 404px;
}
body.proto-v2.drawer-collapsed {
  --occlusion-left: 40px;
  --controls-left-offset: 16px;
}

@media (max-width: 980px) {
  .brand-island { width: min(320px, calc(100vw - 32px)); }
  .drawer { width: min(320px, calc(100vw - 32px)); }
  .drawer-toggle { left: min(352px, calc(100vw - 16px)); }
  body.proto-v2 { --controls-left-offset: 16px; }
}

/* ── Map/list toggle — only ever visible at the phone breakpoint below.
   Hidden here so it never appears at wider widths where the partial-
   collapse .drawer-toggle already does that job. ───────────────────── */
.mobile-view-toggle {
  display: none;
  position: fixed;
  bottom: 20px; left: 50%;
  transform: translateX(-50%);
  z-index: 2100;
  align-items: center; gap: 7px;
  padding: 12px 18px;
  border-radius: 999px;
  font: 700 13px var(--label);
  letter-spacing: 0.03em;
  color: var(--ink);
  cursor: pointer;
}
.miv-icon-list, body.mobile-view-map .miv-icon-map { display: none; }
body.mobile-view-map .miv-icon-list { display: block; }

/* ── Phone layout: the drawer becomes the whole screen (list-first) and
   the map is reached through the toggle above, instead of both sharing
   a viewport too narrow for either to be genuinely usable — a 320px-wide
   drawer over a 375px phone leaves a ~55px sliver of map that isn't a
   preview of anything. ─────────────────────────────────────────────── */
@media (max-width: 640px) {
  .brand-island {
    left: 0; right: 0; top: 0;
    width: 100%;
    border-radius: 0;
    border-left: none; border-right: none; border-top: none;
  }
  .drawer {
    top: 44px; left: 0; right: 0; bottom: 0;
    width: 100%;
    border-radius: 0;
    border-left: none; border-right: none; border-bottom: none;
  }
  /* The partial-collapse control doesn't make sense once the drawer is
     full-width — there's no "narrow map strip" state to collapse into. */
  .drawer-toggle { display: none; }
  .mobile-view-toggle { display: flex; }

  /* List view (default): the drawer already covers the whole screen, so
     the map underneath is fully hidden regardless of occlusion — these
     values only matter once mobile-view-map switches it to the front.
     visibility, not display: a trail tapped on the map while the drawer
     is hidden still needs its detail panel to lay out correctly (it
     measures its own real height in app-controller.js's onSelect), and
     display:none would zero out every dimension in that subtree. */
  body.mobile-view-map .drawer,
  body.mobile-view-map .brand-island {
    visibility: hidden;
  }
  body.mobile-view-map.proto-v2 {
    --occlusion-left: 16px;
    --occlusion-top: 16px;
    --occlusion-right: 16px;
    --occlusion-bottom: 90px; /* clears the map/list toggle pill */
    --controls-left-offset: 16px;
  }
}
