/* Make padding/border included in element width (not added on top).
   This is the modern default reset — without it sizing gets confusing. */
*, *::before, *::after {
  box-sizing: border-box;
}

/* Turn the page into a vertical flex container so the header sticks to
   the top and main content fills the rest of the viewport height. */
body {
  margin: 0;
  font-family: sans-serif;
  background: #e8e8e8;
  color: #222;

  height: 100vh;          /* exactly the viewport — no page-level scrolling */
  overflow: hidden;
  display: flex;
  flex-direction: column; /* stack children vertically */
}

/* Fixed header bar at the top. */
header {
  background: #1a1a2e;
  color: #eee;
  padding: 1rem 2rem;     /* rem = relative to root font size (~16px) */
}

/* Lay out header contents horizontally, vertically centered.
   center keeps the title and info block vertically centered relative to each
   other, which looks good on desktop and avoids the title sitting at the
   bottom when the info block wraps to multiple lines on mobile. */
header {
  position: relative; /* anchor for .home-link absolute positioning */
  display: flex;
  align-items: center;
  gap: 1.5rem;
}

/* Remove default top/bottom margin so the h1 doesn't push outside the header. */
header h1 {
  margin: 0;
  font-size: 1.5rem;
}

/* Count + legend stacked vertically next to the title. */
.header-info {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.header-counts {
  color: #aaa;
  font-size: 0.9rem;
}

.header-mini-counts {
  color: #888;
  font-size: 0.8rem;
}

.header-legend {
  color: #999;
  font-size: 0.75rem;
}

/* Site footer — shown on mobile only (hidden on desktop via display:none below).
   Contains the same "Generated with" link as .home-link in the header. */
.site-footer {
  display: none;
}

/* Top-right corner of the header: lang switcher pinned to top, home link pinned to bottom. */
.header-end {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0.75rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: flex-end;
  padding: 0.35rem 0;
}

.lang-switcher {
  display: flex;
}
.lang-switcher button {
  font-size: 0.7rem;
  color: #777;
  background: #2a2a4e;
  border: 1px solid #555;
  padding: 1px 0;
  width: 1.8rem;
  text-align: center;
  cursor: pointer;
  line-height: 1.4;
}
.lang-switcher button:first-child {
  border-radius: 3px 0 0 3px;
}
.lang-switcher button:last-child {
  border-radius: 0 3px 3px 0;
  border-left: none;
}
.lang-switcher button:hover {
  background: #3a3a6e;
  color: #ccc;
}
.lang-switcher button.lang-active {
  color: #eee;
  background: #3a3a6e;
  font-weight: bold;
}

.home-link {
  font-size: 0.7rem;
  color: #666;
}
.home-link a {
  color: #777;
}
.home-link a:hover {
  color: #aaa;
}

/* Main content area fills remaining viewport height and splits into two columns. */
main {
  flex: 1;
  display: flex;
  min-height: 0; /* needed for flex children to scroll independently */
  max-width: 1200px;
  width: 100%;
  margin: 0 auto;
}

/* Left column: search + scrollable event listing.
   flex: 65 and flex: 35 below are grow ratios — the columns split available space 65/35.
   (flex shorthand with one value sets flex-grow; shrink defaults to 1, basis to 0.) */
.left-col {
  flex: 65;
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 2rem;
  overflow-y: auto;
  overflow-x: hidden; /* overflow-y:auto implicitly enables overflow-x:auto; suppress it */
}

/* Right column: sticky stats panel. */
.right-col {
  flex: 35;
  padding: 2rem;
  border-left: 1px solid #bbb;
  overflow-y: auto;
  overflow-x: hidden; /* overflow-y:auto implicitly enables overflow-x:auto; suppress it */
}

/* Search area: input + mini toggle + search mode note, grouped as a filter unit. */
.search-area {
  margin-bottom: 1rem;
}

/* Wrapper positions the clear button relative to the input. */
.search-wrap {
  position: relative;
  margin-bottom: 0.5rem;
}

/* Full-width search input above the event list. */
.search-box {
  display: block;
  width: 100%;
  padding: 0.5rem 2.5rem 0.5rem 0.75rem; /* right padding leaves room for clear button */
  font-size: 1rem;
  border: 1px solid #ccc;
  border-radius: 4px;
  background: #fff;
  /* Hide the browser's native clear button */
  -webkit-appearance: none;
}
.search-box::-webkit-search-cancel-button {
  display: none;
}

/* Pulsing glow while search debounce is pending.
   Animates box-shadow (not border) so it's visible even when the input is focused.
   outline: none suppresses the browser focus ring so the glow isn't hidden under it. */
@keyframes search-pulse {
  0%, 100% { box-shadow: 0 0 0 2px transparent; }
  50%       { box-shadow: 0 0 0 3px #7a9cc0; }
}
.search-pending {
  outline: none;
  animation: search-pulse 0.7s ease-in-out infinite;
}

/* Clear button overlaid on the right side of the input. */
.search-clear {
  position: absolute;
  right: 0;
  top: 0;
  height: 100%;
  padding: 0 0.75rem;
  background: none;
  border: none;
  cursor: pointer;
  color: #999;
  font-size: 0.85rem;
}
.search-clear:hover {
  color: #333;
}

/* Note shown below the search area when a search is active — describes how the query was matched. */
.search-mode-note {
  margin: 0.3rem 0 0 0;
  font-size: 0.8rem;
  color: #777;
}

/* Warning shown when a search matches multiple categories. */
.mixed-search-note {
  margin: 0.2rem 0 0 0;
  font-size: 0.8rem;
  color: #9a5000;
}

/* Shown on mobile when a search returns no results, in place of the stats summary + toolbar. */
.no-match-note {
  margin: 0 0 0.5rem 0;
  font-size: 1rem;
  font-weight: 600;
  color: #333;
}

/* Hint shown in place of collapsed content: "· · · 42 hidden · · ·" */
.collapsed-hint {
  margin: 0 0 0.75rem 0;
  text-align: center;
  color: #bbb;
  font-size: 0.8rem;
}

/* Stats panel heading — clickable to collapse/expand its section. */
.stats-heading {
  margin: 0 0 0.75rem 0;
  font-size: 1rem;
  color: #444;
  padding-top: 1.5rem;
  border-top: 1px solid #bbb;
  cursor: pointer;
  user-select: none;
}

.stats-heading:hover {
  color: #222;
}

/* Collapse chevron inside the heading. */
.stats-chevron {
  font-size: 0.8rem;
  color: #888;
}

/* Space between sections; the heading already has padding-top. */
.stats-section {
  margin-bottom: 0.5rem;
}


/* Inline label appended to the event count in the toolbar: how the query was interpreted. */
.search-mode-label {
  font-size: 0.75rem;
  color: #aaa;
}

/* When a search is active, lift the whole count line and its mode label. */
.event-count.search-active {
  color: #444;
}
.event-count.search-active .search-mode-label {
  color: #777;
}

/* Summary block at the top of the stats panel. Always visible, reacts to search. */
.stats-summary {
  margin: 0 0 1.5rem 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr auto; /* label left, value right */
  gap: 0.2rem 1rem;
  font-size: 0.85rem;
}

/* Mobile listing summary: concerts headline + detail line. Hidden on desktop. */
.listing-summary {
  display: none;
}

.listing-summary-concerts {
  margin: 0 0 0.15rem 0;
  font-size: 1rem;
  font-weight: 600;
  color: #333;
}

.listing-summary-detail {
  margin: 0;
  font-size: 0.8rem;
  color: #888;
}

.listing-summary-concerts.stat-active {
  color: #000;
}

.listing-summary-detail.stat-active {
  color: #111;
  font-weight: 600;
}

/* Each row is itself a grid item spanning both columns via subgrid. */
.stats-summary-row {
  display: contents; /* lets dt and dd participate directly in the parent grid */
}

.stats-summary dt {
  color: #888;
  font-weight: normal;
}

.stats-summary dd {
  margin: 0;
  text-align: right;
  font-variant-numeric: tabular-nums; /* keep numbers from shifting width as they change */
}

/* Emphasised summary row: active when search mode matches (Events or Performances). */
.stats-summary dt.stat-active,
.stats-summary dd.stat-active {
  color: #222;
  font-weight: 600;
}

/* Wrapper for year table — limits height so performer table stays visible. */
.stats-table-scroll {
  max-height: 12rem;
  overflow-y: auto;
  margin-bottom: 0.5rem;
}

/* Performer stats table. */
.stats-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

.stats-table th {
  padding: 0;
  font-weight: normal;
  border-bottom: none;
}

/* Column header row: static label text + inline sort button. */
.sort-row th {
  padding-bottom: 0.25rem;
  text-align: left;
  font-size: 0.85rem;
  color: #555;
  white-space: nowrap;
}

.sort-btn {
  font-size: 0.75rem;
  color: #777;
  background: #f5f5f5;
  border: 1px solid #bbb;
  border-radius: 3px;
  cursor: pointer;
  padding: 0;
  width: 1.4em;
  height: 1.4em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
}

.sort-btn:hover {
  background: #e8e8e8;
  border-color: #999;
  color: #333;
}

/* Active sort: non-reversible columns — show state but don't invite interaction. */
.sort-btn.sort-active.sort-locked {
  background: #d8d8d8;
  border-color: #aaa;
  color: #444;
  cursor: default;
}

.sort-btn.sort-active.sort-locked:hover {
  background: #d8d8d8;
  border-color: #aaa;
  color: #444;
}

/* Active sort: reversible column — invite re-click to flip direction. */
.sort-btn.sort-active:not(.sort-locked) {
  background: #d8d8d8;
  border-color: #aaa;
  color: #444;
  font-weight: 600;
}


.stats-table td {
  padding: 0.2rem 0.5rem;
  border-bottom: 1px solid #eee;
}

/* Count column: fixed width, tabular numbers, left-aligned, no wrapping. */
.stats-table td:nth-child(2) {
  width: 5rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}


/* Toolbar above the event list: count on the left, sort on the right (desktop).
   On mobile the count is hidden and replaced by a collapse button. */
.listing-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
}

/* Collapse button — mobile only, hidden on desktop via x-show. */
.collapse-btn {
  font-size: 1rem;
  font-weight: 600;
  color: #333;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  user-select: none;
}


.event-count {
  font-size: 0.85rem;
  color: #888;
}

.mini-toggle {
  font-size: 0.8rem;
  color: #555;
  cursor: pointer;
  user-select: none;
}

.mini-toggle.mini-toggle-disabled {
  color: #bbb;
  cursor: default;
}

/* Reserve fixed space for the mini count so the toggle width stays stable
   as the count changes with filtering. */
.mini-toggle-count {
  display: inline-block;
  min-width: 3.2em;
  margin-left: 0.25em;
  font-variant-numeric: tabular-nums;
}

.sort-toggle {
  font-size: 0.8rem;
  color: #555;
  background: #efefef;
  border: 1px solid #bbb;
  border-radius: 4px;
  cursor: pointer;
  padding: 2px 8px;
}

.sort-toggle:hover {
  background: #e2e2e2;
  border-color: #999;
  color: #222;
}

/* Scroll-to-top button: sticky in the bottom-right corner of the left column.
   align-self: flex-end pushes it to the right edge within the flex column. */
.scroll-top-btn {
  position: sticky;
  bottom: 0.1rem;
  align-self: flex-end;
  margin-right: -1.5rem;
  font-size: 0.85rem;
  color: #fff;
  background: #333;
  border: 1px solid #222;
  border-radius: 4px;
  cursor: pointer;
  padding: 4px 10px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.35);
}

.scroll-top-btn:hover {
  background: #111;
  border-color: #000;
  color: #fff;
}

/* Each event is a horizontal row of fields. gap adds space between them. */
.event-row {
  display: flex;
  gap: 0.75rem;
  padding: 0.4rem 0;
  border-bottom: 1px solid #ddd;
  align-items: flex-start; /* date/venue sit at the top when title spans multiple lines */
}

/* Fixed-width date column so all titles align vertically.
   flex: 0 0 7rem = don't grow, don't shrink, always exactly 7rem wide. */
.event-date {
  flex: 0 0 6rem;
  color: #666;
  font-size: 0.9rem;
}

/* Title takes all remaining space; stacks performers vertically. */
.event-title {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

/* Optional festival/event name shown above performers. */
.event-name-prefix {
  color: #888;
  font-size: 0.85rem;
}

/* Muted parenthetical detail after performer name, e.g. "acoustic". */
.performer-detail {
  color: #888;
  font-size: 0.85rem;
  white-space: normal;
}

/* One performer per line, with optional inline mini badge. */
.event-performer {
  white-space: nowrap;
}

/* Performer name that matches the current search query. */
.performer-match {
  font-weight: 600;
}

/* Mini-concert badge: small, bordered, muted. */
.mini-badge {
  font-size: 0.7rem;
  color: #888;
  background: #eef3fb;
  border-radius: 3px;
  padding: 0 3px;
  line-height: 1.5;
  vertical-align: middle;
}

/* Custom tooltip for the mini-badge when a data-tooltip attribute is present.
   Using CSS ::after instead of the native title attribute because the browser's
   built-in tooltip delay (~1s) is too slow for comfortable discoverability. */
.mini-badge[data-tooltip] {
  position: relative;
  cursor: help;
}
.mini-badge[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  top: calc(100% + 5px);
  left: 0;
  width: 260px;
  white-space: normal;
  background: #333;
  color: #fff;
  font-size: 0.75rem;
  line-height: 1.4;
  padding: 5px 8px;
  border-radius: 4px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.15s ease;
  transition-delay: 0.25s;
  z-index: 10;
}
.mini-badge[data-tooltip]:hover::after {
  opacity: 1;
}

/* Venue name before first comma stays on one line. The rest uses non-breaking
   spaces so wrapping only occurs at ", " boundaries (see venueRest in app.js). */
.venue-main {
  white-space: nowrap;
}

/* Venue is muted, doesn't need to dominate. */
.event-venue {
  color: #666;
  font-size: 0.9rem;
  text-align: right;
  min-width: 0;
  overflow-wrap: break-word;
}

/* Muted event comment appended after venue, e.g. " · 2". */
.event-comment {
  color: #aaa;
  font-size: 0.85rem;
}


/* ---- Mobile layout (max-width: 768px) ----
   Everything above this point is the desktop layout — unchanged.
   The rules below override only what needs to change on narrow screens. */
@media (max-width: 768px) {
  /* Unlock the viewport so the whole page scrolls naturally.
     Desktop locks it (height: 100vh; overflow: hidden) so each column
     scrolls independently; on mobile we want one unified scroll. */
  body {
    height: auto;
    overflow: visible;
  }

  /* Stack the two columns vertically instead of side by side. */
  main {
    flex-direction: column;
  }

  /* Each column becomes full-width and stops scrolling on its own. */
  .left-col {
    overflow-y: visible;
    padding: 1rem;
  }

  /* On mobile, pin scroll-to-top to the bottom-right corner of the screen so it remains
     visible as the user scrolls through both columns (not just while inside .left-col). */
  .scroll-top-btn {
    position: fixed;
    bottom: 1rem;
    right: 1rem;
    align-self: unset;
    margin-right: 0;
  }

  .right-col {
    flex: none;
    overflow-y: visible;
    border-left: none;
    border-top: 1px solid #bbb;
    padding: 1rem;
  }

  /* On mobile the listing summary lives in .left-col; hide the desktop stats copy. */
  .stats-summary-desktop {
    display: none;
  }

  /* Show the mobile listing summary (hidden by default on desktop). */
  .listing-summary {
    display: block;
    margin-bottom: 0.75rem;
  }


  /* Two-row header on mobile: h1 + lang buttons on row 1 (sharing the full
     width), counts + legend on row 2 (full width, no overlap risk).
     flex-wrap: wrap enables the two-row split; header-info flex-basis: 100%
     forces it onto its own row. */
  header {
    flex-wrap: wrap;
    align-items: center;
    padding-right: 0.75rem;
  }
  .header-end {
    position: static;
    padding: 0;
    align-self: flex-start;
    margin-left: auto;
    order: 2;
  }
  .header-info {
    flex-basis: 100%;
    order: 3;
  }

  /* Hide the "Generated with eventslist" text in the header on mobile;
     keep only the version tag. The full link is in the footer instead. */
  .home-link-text {
    display: none;
  }


  .site-footer {
    display: block;
    padding: 0.75rem 1rem;
    text-align: right;
    font-size: 0.7rem;
    background: #1a1a2e;
    color: #aaa;
    border-top: none;
  }

  .site-footer a {
    color: #bbb;
  }

  /* Stats tables: remove the fixed-height scroll cap — let them expand fully
     so the page scroll (not a nested scrollbar) handles long tables. */
  .stats-table-scroll {
    max-height: none;
    overflow-y: visible;
  }

  /* Match stats chevrons to the listing chevron size on mobile. */
  .stats-chevron {
    font-size: 1rem;
  }

  /* Toolbar on mobile: collapse button (left) + sort button (right). */
  .listing-toolbar {
    gap: 0;
  }

  /* Search row: input and mini-toggle side by side. */
  .search-row {
    display: flex;
    align-items: stretch;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
  }

  .search-row .search-wrap {
    flex: 1;
    margin-bottom: 0;
  }

  /* Mini-toggle: checkbox vertically centred beside the text. */
  .search-row .mini-toggle {
    display: flex;
    align-items: center;
    gap: 0.3rem;
  }

  /* Gap already handles spacing between flex items; remove the margin used on desktop. */
  .search-row .mini-toggle-count {
    margin-left: 0;
  }
}
