/* Filter fields as underlined inputs rather than full boxes — lighter, reads as
   a form line, consistent with the de-boxed list below. */
.input-wrapper {
  /* A little horizontal breathing room so the caret/placeholder doesn't sit flush
     on the field edge; the underline still spans the full width. */
  padding: var(--gap-small) var(--gap-small);
  border-bottom: var(--border-width) solid var(--field-border-color);
  line-height: var(--filter-input-line-height);
  position: relative;
}

/* Neutral at rest; the underline lights accent when the field is focused — same
   language as the account-form fields. */
.input-wrapper:focus-within {
  border-bottom-color: var(--theme-accent-color);
}

/* Filter field handle glyph (search / where / when): GREEN — each field opens a
   dropdown/picker, so the glyph reads as an interactive affordance ("click to
   open"), consistent with green = interaction. */
.filter-icon {
  font-size: 1.5rem;
  display: flex;
  align-items: center;
  color: var(--theme-accent-color);
}

.filter-button {
  line-height: var(--filter-input-line-height);
}

.searchbar {
  gap: 5vw;
}

.filter-select {
  line-height: var(--filter-input-line-height);
}

/* Date group heading: a single hairline rule instead of the old 5px double
   border — a quiet section divider, not a decorative slab. */
.date {
  align-items: baseline;
  gap: var(--gap-small);
  color: var(--theme-fg-color);
  font-weight: bold;
  padding-bottom: var(--gap-small);
  border-bottom: var(--border-width) solid var(--rule-color);
}

/* Per-day relevance counts sitting just after a date header's date: a saved (♥)
   tally and an interest (★) tally, each hidden when zero. Same glyph language as the
   calendar markers — raspberry heart = saved, green star = interest — just carried
   as counts. Normal weight + small so they support the date rather than compete.
   Collapses entirely (no trailing gap) on a day with neither, so the date keeps its
   flush-left place; :has lets a live follow/save bring it back without the
   controller touching the wrapper. */
.day-summary {
  display: none;
  align-items: center;
  gap: 0.8ch;
  flex: none;
  font-size: var(--font-size-small);
  font-weight: normal;
}

.day-summary:has(.day-summary__count:not([hidden])) {
  display: flex;
}

.day-summary__count {
  display: inline-flex;
  align-items: center;
  gap: 0.3ch;
  line-height: 1;
}

.day-summary__count::before {
  content: "";
  display: inline-block;
  width: 1em;
  height: 1em;
  background-color: currentColor;
}

.day-summary__count--saved {
  color: var(--theme-saved-color);
}

.day-summary__count--saved::before {
  -webkit-mask: var(--heart-fill) center / contain no-repeat;
  mask: var(--heart-fill) center / contain no-repeat;
}

.day-summary__count--interest {
  color: var(--theme-accent-color);
}

.day-summary__count--interest::before {
  -webkit-mask: var(--star-fill) center / contain no-repeat;
  mask: var(--star-fill) center / contain no-repeat;
}

/* Venue-led row, zero boxes. Hierarchy comes from structure — the venue anchor on
   its own line, a quiet metadata line (city/canton) beneath it — so the list reads
   the same logged in or out. Colour is an enhancement, not the separator: green
   now marks a tag you *follow* (your stuff), plus true links and the external-link
   arrow; muted grey = passive info; black = the event itself. */
.event {
  display: flex;
  justify-content: space-between;
  gap: var(--gap-medium);
}

.event-body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--gap-xsmall);
}

/* Plain informational tags: genres, and tags for logged-out visitors who can't
   follow. Muted; the venue stays foreground as the headline. */
.event-tag {
  color: var(--theme-fg-muted);
}

.event-tag.venue {
  color: var(--theme-fg-color);
}

/* Followable tags (logged-in): the whole tag IS the follow toggle. Colour no
   longer marks "followable" — at rest a followable tag inherits its neighbours'
   colour (venue = fg, city/canton = muted, styles = muted bold), identical to the
   logged-out plain tags, so the page reads the same either way. The follow
   affordance is the trailing heart; following lights the tag accent (see
   .event-tag.fav.followed). font:inherit keeps the button matching the row. */
.event-tag.fav {
  border: 0;
  padding: 0;
  background: none;
  font: inherit;
  cursor: pointer;
}

/* A tag you follow — "this is yours" — lights GREEN, the dominant accent. Follows
   are frequent, so green stays present across the page (the rare saved heart is
   the raspberry highlight). The green STAR glyph distinguishes a follow from a
   plain green link/arrow. Three classes outrank .event-tag.venue and the base
   .event-tag, so a followed venue/city/style lights up regardless of its rest. */
.event-tag.fav.followed {
  color: var(--theme-accent-color);
}

.event-tag.fav:hover .fav-label {
  text-decoration: underline;
}

/* Read-only link back into the filtered list (notification digests only, where
   there's no filter form). */
.filter-link {
  border: 0;
  padding: 0;
  background: none;
  font: inherit;
  color: var(--theme-accent-color);
  cursor: pointer;
}

.filter-link:hover {
  text-decoration: underline;
}

/* Venue is the headline: the largest, boldest thing in the row, alone on its line
   so it reads as the anchor (not one oversized token in a mixed-size row). */
.event-where .venue {
  font-size: var(--font-size-lg);
  font-weight: bold;
}

/* City / canton: a quiet metadata line beneath the venue. Small + muted so it
   informs without competing — and still followable (each is a tag). */
.event-where-meta {
  font-size: var(--font-size-small);
  color: var(--theme-fg-muted);
}

.event-title {
  font-weight: bold;
  overflow-wrap: anywhere;
}

.event-title a {
  color: var(--theme-fg-color);
  text-decoration: none;
}

/* The title is an external link (off-site, marked by the green ↗ which carries
   the clickable signal at rest). It stays black for headline hierarchy; hover
   just underlines, so the headline never changes colour. */
.event-title a:hover {
  text-decoration: underline;
}

.event-link-marker {
  /* The only link signal on the (black) title, so give it a touch more presence
     than the title text — but stay typographic, not icon-sized. line-height:1
     keeps the larger glyph from inflating the title's line. */
  font-size: 1.2em;
  line-height: 1;
  color: var(--theme-accent-color);
  font-weight: normal;
}

/* Time leads the title at full size but in muted grey, so it reads before the
   act without competing with the venue headline above it. */
.event-time {
  margin-right: 0.8ch;
  color: var(--theme-fg-muted);
  font-weight: normal;
}

.event-subtitle {
  color: var(--theme-fg-muted);
  font-size: var(--font-size-small);
}

.event-subtitle p {
  margin: 0;
}

.event-styles,
.event-genres {
  font-size: var(--font-size-small);
}

/* Styles are the primary, followable descriptor — bold AND full foreground colour
   so they assert a clear tier above the muted, regular-weight subtitle and genres
   they sit between, without adding another font size to the row. The fg colour
   lives on the tags themselves (not the container) so it beats the base .event-tag
   muted; a followed style still wins to the favorite colour via .event-tag.fav.followed. */
.event-styles {
  font-weight: bold;
}

.event-styles .event-tag {
  color: var(--theme-fg-color);
}

/* Genres are display-only (not filters): muted, so the colour alone says
   "not clickable". */
.event-genres {
  color: var(--theme-fg-muted);
}

/* A genre matched by the active free-text query. Emphasise it so it stands out
   from its muted siblings — but stay in the text vocabulary (un-muted + bold),
   never the accent colour, which in this UI means "interactive/clickable". The
   match is information, not a link. */
.event-genres .genre.active {
  color: var(--theme-fg-color);
  font-weight: bold;
}

/* The genre tag's inline edit gear (an .icon-button); only the inline layout is
   local — colour, hover, and the underline reset come from the shared role. The
   gear is a baseline-aligned icon glyph, so centre it to the text's middle
   (otherwise it sits low, dipping below the tag's baseline). */
.meta-edit {
  margin-left: 0.4ch;
  vertical-align: middle;
}

/* The follow STAR trails its tag and inherits the tag's font-size, so the big
   venue header gets a big star and a small style tag a small one. It's the sole
   "you can follow this" signal, so it stays visible — mobile-first, no hover to
   hide behind. (Class still named .fav-star for now — glyph swapped heart→star;
   rename is non-visual cleanup.) */
.fav-star {
  margin-left: 0.4ch;
}

/* A masked Phosphor star: the mask is the shape, background-color paints it, so
   it inherits a theme colour and the tag's em size. */
.fav-star::before {
  content: "";
  display: inline-block;
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  background-color: var(--theme-fg-muted);
  -webkit-mask: var(--star-outline) center / contain no-repeat;
  mask: var(--star-outline) center / contain no-repeat;
}

/* Not-yet-followed: a faint outline star — present enough to be discoverable and
   tappable on touch, quiet enough not to clutter the row. */
.event-tag.fav:not(.followed) .fav-star {
  opacity: 0.4;
}

/* Followed: solid green star at full strength, so your follows are the dominant
   accent across the page. */
.event-tag.fav.followed .fav-star::before {
  background-color: var(--theme-accent-color);
  -webkit-mask-image: var(--star-fill);
  mask-image: var(--star-fill);
}

/* Real, inert separator between terms — a sibling element, not a pseudo on the
   button, so only the link text is hoverable/clickable, never the dot. */
.sep {
  margin: 0 0.5ch;
  color: var(--theme-fg-muted);
  font-weight: normal;
}

/* Admin actions column: the edit gear and delete trash sit together, top-aligned
   with the event title. The icons use the shared .icon-button role; the delete is
   a button_to, so flatten its wrapping form to a zero-margin flex box that
   shrink-wraps the button and lines up with the bare anchor gear. */
.event-actions {
  display: flex;
  align-items: flex-start;
  gap: var(--gap-small);
}

.event-actions form {
  margin: 0;
  display: flex;
}

/* In the row-action column the gear (<a>) and trash (<button>) must line up, so
   give each a tight centred box (the icon-button base is layout-free) plus a
   small symmetric pad for a comfortable tap target. */
.event-actions .icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  padding: var(--gap-xsmall);
}

/* Past events recede but stay legible. */
.event.past,
.date-events.past .date {
  opacity: 0.5;
}

/* Cancelled events stay listed (so a follower sees the show was called off) but
   the title is struck through and prefixed with a warning-coloured badge. */
.event.cancelled .event-title a {
  text-decoration: line-through;
}

.event-cancelled {
  font-weight: bold;
  text-transform: uppercase;
  color: var(--theme-warn-color);
}

/* Toolbar row above the programme: the favorites/notify shortcuts and the empty
   message on the left, the view switcher on the right. Allow it to wrap so a
   visible "Meine Favoriten" shortcut (plus the view switcher) doesn't overflow on
   narrow screens, and let the left cluster shrink so a long empty message flows
   onto the next line instead of pushing the row past the viewport. */
.events-toolbar {
  flex-wrap: wrap;
}

.events-toolbar__left {
  flex: 1 1 auto;
  min-width: 0;
  flex-wrap: wrap;
}

/* The two toolbar actions (interests, notify) collapse to icon-only below the
   tablet breakpoint, so the interests/notify/view-switcher row stays on one line
   on mobile instead of wrapping when both actions are present. Mobile-first: the
   label is hidden by default and returns on desktop. Each link keeps an
   aria-label, so the accessible name is stable when the text is hidden. */
.toolbar-action__label {
  display: none;
}

@media (min-width: 600px) {
  .toolbar-action__label {
    display: inline;
  }
}

/* Empty-result message: its own line under the toolbar so a long sentence can't
   wrap the favorites/notify cluster or push the view switcher around. */
.events-empty {
  margin: 0;
}

/* List / Calendar as a plain text toggle, not filled buttons: the active view
   is bold accent, the other a muted link. Its own class (was the generic
   .button, which now means a real boxed button). */
.view-switcher {
  gap: var(--gap-medium);

  .view-switch__item {
    border: 0;
    padding: 0;
    background: none;
    color: var(--theme-fg-muted);
    text-decoration: none;
  }

  .view-switch__item:hover {
    text-decoration: underline;
  }

  .view-switch__item.active {
    color: var(--theme-accent-color);
    font-weight: bold;
    background: none;
  }
}

/* "My favorites" filter shortcut, sitting in the view-switcher row. A flat, muted
   text link with a leading heart (its own class — was .button.favorites-filter-link,
   borrowing the bare .button). The heart is outline + muted when off; when the
   favorites filter is applied the label bolds and the heart fills in the favorite
   accent — echoing the follow-heart language used elsewhere. */
.favorites-filter-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4ch;
  border: 0;
  padding: 0;
  background: none;
  color: var(--theme-fg-muted);
  text-decoration: none;
}

/* The display above overrides the UA [hidden] rule, so re-assert it (at matching
   specificity) — the shortcut renders hidden until the user follows something. */
.favorites-filter-link[hidden] {
  display: none;
}

.favorites-filter-link:hover {
  text-decoration: underline;
}

.favorites-filter-link .fav-star {
  margin-left: 0;
}

.favorites-filter-link.active {
  color: var(--theme-accent-color);
  font-weight: bold;
}

.favorites-filter-link.active .fav-star::before {
  background-color: var(--theme-accent-color);
  -webkit-mask-image: var(--star-fill);
  mask-image: var(--star-fill);
}

.simple-calendar {
  .table {
    table-layout: fixed;
    width: 100%;
    border-collapse: collapse;
  }

  .calendar-heading {
    margin-bottom: var(--gap-small);
  }

  /* The month anchors the calendar — bold, but no taller than the toolbar so the
     view switcher stays pinned to the same spot as in list view. */
  .calendar-title {
    font-size: var(--font-size-lg);
    font-weight: bold;
  }

  th {
    padding: var(--gap-small);
    text-align: center;
    font-weight: normal;
    color: var(--theme-fg-muted);
    /* A neutral rule under the weekday header, mirroring the list date divider
       (both now use the prominent neutral --rule-color, not green). */
    border-bottom: var(--border-width) solid var(--rule-color);
  }

  /* A defined hairline grid (no fills) keeps cells distinguishable without the
     heavy filled boxes of before. */
  .day {
    position: relative;
    border: var(--calendar-border-width) solid var(--calendar-border-color);
    /* Minimum height; busy cells grow to fit their in-flow .day-content. On a
       narrow (mobile) column 7rem reads as a tall, empty, squashed box, so the
       cells shrink to a more square proportion below the calendar breakpoint. */
    height: 4.25rem;
    vertical-align: top;

    /* Adjacent-month days recede instead of being filled differently. */
    &.prev-month, &.next-month {
      opacity: 0.4;
    }

    /* Hover: the same muted-background wash as the dropdown's highlighted option
       (--theme-bg-muted / --hw-active-bg-color), so picking a day and picking a
       combobox option feel like one interaction language. */
    &:has(.calendar-day-link:hover) {
      background-color: var(--theme-bg-muted);
    }

    /* Selected: the same wash plus an inset accent frame that ties the day to its
       drawer below (the frame, not the colour, marks it as selected vs hovered). */
    &:has(.calendar-day-link.selected) {
      background-color: var(--theme-bg-muted);
      box-shadow: inset 0 0 0 var(--border-width) var(--theme-accent-color);
    }
  }

  /* Sits above the busyness meter but below the click target, so the date/count
     read clearly while taps still fall through to the day link. */
  .day-content {
    position: relative;
    z-index: 1;
    padding: var(--gap-small);
  }

  /* Desktop-only relevance headline: the day's top-priority venue (saved >
     interest). Hidden on mobile — the marker carries the signal there and a name
     won't fit. One line, truncated to the cell width. Muted so it supports the
     date + marker rather than competing; click-through (sits below the day link). */
  .day-headline {
    display: none;
    margin-top: var(--gap-xsmall);
    font-size: var(--font-size-small);
    line-height: 1.2;
    color: var(--theme-fg-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* Transparent click target covering the cell's full (row) height. */
  .calendar-day-link {
    position: absolute;
    inset: 0;
    z-index: 2;
    cursor: pointer;
  }

  .calendar-day-number {
    display: block;
    text-align: left;
    /* The cell's anchor: a step larger than the muted venue line below it, so the
       date clearly leads and the cell doesn't read as two competing small numbers. */
    font-size: var(--font-size-base);
    font-weight: bold;

    /* No events that day: fade the date right back (and the cell has no click
       target). Full date = "something's on, tap me", faded = "nothing here" — a
       strong opacity contrast, not a subtle colour shift, so clickable days are
       obvious. Declared before &.today so today keeps its badge even when empty. */
    &.empty {
      opacity: 0.35;
      font-weight: normal;
    }

    /* Today: a filled accent badge so it can't get lost in the grid. Stays
       display:block (shrink-wrapped) so it keeps the same line height as plain
       day numbers — an inline-block badge would push the cell's venues down. */
    &.today {
      width: fit-content;
      font-weight: bold;
      padding: 0 0.45em;
      /* Sand badge (not green): green is for interaction/follows, so a green today
         pill clashed with the green interest stars. Uses --theme-bg-emphasis (a
         stronger sand than the muted wash) so it stays clearly readable on the dark
         theme and on a hovered/selected cell, while staying calm and on-palette. */
      color: var(--theme-fg-color);
      background-color: var(--theme-bg-emphasis);
    }
  }

  /* Personal markers tucked into the cell's top-right corner: a saved-show
     bookmark and/or a followed-tag dot, laid out in one slot. Decorative and
     click-through, so the full-cell day link underneath still receives the tap. */
  /* Mobile: the marker sits BOTTOM-right so it never crowds the date's top row —
     the today badge (a padded green pill) otherwise collides with it on a narrow
     cell. Desktop moves it back up to top-right (see the breakpoint block), where
     the wider cell has room beside the date. */
  .day-markers {
    position: absolute;
    z-index: 3;
    bottom: var(--gap-small);
    right: var(--gap-small);
    display: flex;
    align-items: center;
    gap: 0.3rem;
    pointer-events: none;
  }

  /* You've saved a show playing this day: a solid HEART in the favorite colour —
     the same fill = "saved" language as the per-event save button. The heart is
     the strong, rare signal (saved), so it leads the slot and pops above the
     quieter follow dot. Raspberry, never green (green = interaction/state). */
  .day-saved-marker {
    display: flex;
    align-items: center;
    gap: 0.15rem;
    font-size: var(--font-size-small);
    line-height: 1;
    color: var(--theme-saved-color);

    &::before {
      content: "";
      display: block;
      width: 1em;
      height: 1em;
      background-color: currentColor;
      -webkit-mask: var(--heart-fill) center / contain no-repeat;
      mask: var(--heart-fill) center / contain no-repeat;
    }
  }

  /* Only shown when more than one show is saved that day. */
  .day-saved-count {
    font-size: 0.7rem;
    font-weight: bold;
  }

  /* A followed location or style plays this day: a green STAR — the same
     interest=star glyph used in the list/tags, so the marker's meaning is
     self-evident (★ = your interest) rather than an unlabelled dot. Sized to
     match the saved heart so the two markers read as one family (green star =
     interest, raspberry heart = saved). Carries the day's keys so the favorite
     controller can flip it live. */
  .day-favorite-marker {
    display: block;
    /* Smaller than the saved heart: interest is the frequent signal, so a field of
       these should stay quiet; the rarer heart is left a touch larger to pop. */
    width: 0.6rem;
    height: 0.6rem;
    background-color: var(--theme-accent-color);
    -webkit-mask: var(--star-fill) center / contain no-repeat;
    mask: var(--star-fill) center / contain no-repeat;
  }

  /* When a show is also saved that day, the bookmark already flags it as yours —
     the dot would just be noise, so it gives way. */
  .day-markers:has(.day-saved-marker) .day-favorite-marker {
    display: none;
  }

  /* Inline expanding row: the day-detail frame rendered full-width beneath the
     week of the clicked day. The lighter page background (vs. the muted cells)
     plus bold accent rules top and bottom frame it as a distinct drawer lifted
     out of the calendar grid, rather than blending in as just another cell. */
  .day-detail-row td {
    border: 0;
    border-block: var(--border-width) solid var(--rule-color);
    /* Full-width horizontally so the drawer's events line up with the List view
       (same partial) and the page's left/right edges; the bold accent rules and
       lighter background still read it as lifted out of the grid. */
    padding-block: var(--gap-large);
    padding-inline: 0;
    background-color: var(--theme-bg-color);
  }
}

.day-detail {
  border-top: var(--border-width) solid var(--rule-color);
  padding-top: var(--gap-medium);
}

/* Inside the inline row the cell already supplies the frame; the accent divider
   and padding above would be redundant. */
.day-detail-row .day-detail {
  border-top: 0;
  padding-top: 0;
}

.day-detail-header {
  /* Bottom-align so the close button sits down on the date's double rule,
     capping the end of the line instead of floating in the vertical middle. */
  align-items: flex-end;
  gap: var(--gap-small);
}

/* The date keeps its full-width double underline; the close button caps it. */
.day-detail-header .date {
  flex: 1;
}

.day-detail-close {
  flex: none;
  border: 0;
  padding: 0;
  background: none;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--theme-accent-color);
  text-decoration: none;
  cursor: pointer;
}

.day-detail-close:hover,
.day-detail-close:focus-visible {
  color: var(--theme-fg-color);
}

/* ─────────────────────────────────────────────────────────────────────────
   Mobile filter sheets (_filter_sheets.html.erb). Mobile-first: the sheet UI is
   the default; the inline combobox filter (wrapped in .filter-desktop) takes over
   at the tablet breakpoint — 600px, matching the calendar breakpoint above.
   ───────────────────────────────────────────────────────────────────────── */
.filter-desktop { display: none; }

/* Reserve one chip-row of height in the events filter so applying the FIRST
   filter doesn't shove the toolbar + programme down (the row otherwise goes
   0 → 1 line). Chip box = 0.75rem text + 5px×2 padding + 1px×2 border (see
   .filter .tag / .tag). Wrapping to a second line still grows the row — an
   accepted, rarer jump. */
.filter .chips {
  min-height: calc(0.75rem + 12px);
}

@media (min-width: 600px) {
  .filter-desktop { display: block; }
  .filter-sheets { display: none; }
  /* Wider columns can carry the taller cell without looking squashed; restore the
     roomier desktop calendar height (mobile keeps the compact 4.25rem above). */
  .simple-calendar .day { height: 7rem; }
  /* Room for the venue headline only at desktop width. */
  .simple-calendar .day-headline { display: block; }
  /* Wider cell: the marker rides up beside the date (no today-badge crowding here). */
  .simple-calendar .day-markers { top: var(--gap-small); bottom: auto; }
}

/* ── Trigger bar ── three underlined rows echoing the inline filter, but each
   whole row is a tap target opening its sheet. */
.filter-sheets__bar {
  display: flex;
  flex-direction: column;
  gap: var(--gap-medium);
}

.filter-trigger {
  display: flex;
  align-items: center;
  gap: var(--gap-small);
  width: 100%;
  padding: var(--gap-small) 0;
  border: 0;
  border-bottom: var(--border-width) solid var(--field-border-color);
  background: none;
  color: var(--theme-fg-color);
  font: inherit;
  line-height: var(--filter-input-line-height);
  text-align: left;
  cursor: pointer;
}

/* Accent underline when the trigger is focused (keyboard) — matches the inline
   filter fields' focus language. */
.filter-trigger:focus-visible {
  outline: none;
  border-bottom-color: var(--theme-accent-color);
}

.filter-trigger__icon {
  font-size: var(--filter-icon-size);
  /* Green: the trigger opens a sheet — an interactive affordance (matches the
     inline .filter-icon). */
  color: var(--theme-accent-color);
}

.filter-trigger__label {
  flex-grow: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Empty field reads as a muted prompt — this is the search affordance for What. */
.filter-trigger__label.is-empty { color: var(--theme-fg-muted); }

.filter-trigger__more { color: var(--theme-fg-muted); }

/* The applied-filter count uses the shared .badge (layout.css). */

.filter-trigger__chevron {
  flex-shrink: 0;
  color: var(--theme-fg-muted);
}

/* ── Applied-filter chips ── mirror the inline filter's .tag.active. */
.filter-sheets__summary {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-small);
  margin-top: var(--gap-medium);
}

.filter-sheets__summary:empty { display: none; }

.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-small);
  padding: 5px;
  border: 0;
  background: var(--theme-accent-color);
  color: var(--theme-on-accent);
  font: inherit;
  font-size: 75%;
  line-height: 1;
  cursor: pointer;
}

/* Tapping/clicking the chip removes that filter — give it a hover/focus cue so
   the "× to remove" affordance reads (it had none before). */
.filter-chip:hover,
.filter-chip:focus-visible {
  opacity: 0.82;
}

.filter-chip__remove { font-size: 1.1em; }

/* ── The sheet ── full-screen, slides up from the bottom. */
body.filter-sheet-open { overflow: hidden; }

.sheet {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  background: var(--theme-bg-color);
  transform: translateY(100%);
  visibility: hidden;
  transition: transform 0.22s ease, visibility 0.22s;
}

.sheet--open {
  transform: translateY(0);
  visibility: visible;
}

.sheet__header {
  display: grid;
  grid-template-columns: 2.5rem 1fr auto;
  align-items: center;
  gap: var(--gap-small);
  padding: var(--gap-medium) var(--content-padding);
  border-bottom: var(--border-width) solid var(--rule-color);
}

.sheet__title {
  margin: 0;
  font-size: var(--font-size-base);
  font-weight: bold;
  text-align: center;
}

.sheet__close {
  justify-self: start;
  padding: 0;
  border: 0;
  background: none;
  color: var(--theme-fg-color);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
}

.sheet__clear {
  justify-self: end;
  padding: 0;
  border: 0;
  background: none;
  color: var(--theme-fg-muted);
  font: inherit;
  font-size: var(--font-size-small);
  cursor: pointer;
}

.sheet__search {
  display: flex;
  align-items: center;
  gap: var(--gap-small);
  padding: var(--gap-small) var(--content-padding);
  border-bottom: var(--tag-border-width) solid var(--border-color);
}

.sheet__search-icon {
  font-size: 1.3rem;
  color: var(--theme-fg-muted);
}

.sheet__search-input {
  flex-grow: 1;
  min-width: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
}

.sheet__search-input:focus { outline: none; }

.sheet__body {
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--gap-small) 0;
}

.sheet__footer {
  padding: var(--gap-medium) var(--content-padding);
  border-top: var(--tag-border-width) solid var(--border-color);
}

.sheet__apply {
  width: 100%;
  padding: var(--gap-medium);
  border: 0;
  background: var(--theme-accent-color);
  color: var(--theme-on-accent);
  font: inherit;
  font-weight: bold;
  cursor: pointer;
}

/* ── Option rows ── a checkable row; native box hidden, custom box drawn. */
.opt {
  display: flex;
  align-items: center;
  gap: var(--gap-medium);
  padding: var(--gap-medium) var(--content-padding);
  cursor: pointer;
}

.opt--hidden { display: none; }

/* `.opt { display: flex }` is an author rule, so it would beat the UA's
   `[hidden] { display: none }` (equal specificity) and leave a `hidden` row
   visible. Re-assert hiding at higher specificity so both the initial state and
   the JS-toggled `hidden` (the free-text row) actually hide. */
.opt[hidden] { display: none; }

.opt input[type="checkbox"] {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
}

.opt__box {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  border: var(--border-width) solid var(--border-color);
}

.opt input:checked ~ .opt__box {
  background: var(--theme-accent-color);
  border-color: var(--theme-accent-color);
}

.opt input:checked ~ .opt__box::before {
  content: "";
  width: 0.8rem;
  height: 0.8rem;
  background-color: var(--theme-on-accent);
  -webkit-mask: var(--check-mask) center / contain no-repeat;
  mask: var(--check-mask) center / contain no-repeat;
}

.opt__label {
  flex-grow: 1;
  min-width: 0;
}

.opt__type {
  flex-shrink: 0;
  color: var(--theme-fg-muted);
  font-size: 75%;
}

.opt__count {
  flex-shrink: 0;
  color: var(--theme-fg-muted);
  font-size: var(--font-size-small);
}

/* Tree depth: cities indent one step, venues two; venues read a touch quieter. */
.opt--city  { padding-left: calc(var(--content-padding) + 1.5rem); }
.opt--venue { padding-left: calc(var(--content-padding) + 3rem); }
.opt--venue .opt__label { font-size: var(--font-size-small); }

/* ── Location group ── canton row + expand toggle; collapsed hides its body. */
.loc-group--hidden { display: none; }

.loc-group__head { display: flex; align-items: center; }

.loc-group__head .opt { flex-grow: 1; }

.loc-group__toggle {
  display: flex;
  align-items: center;
  gap: var(--gap-small);
  align-self: stretch;
  padding: 0 var(--content-padding);
  border: 0;
  background: none;
  color: var(--theme-fg-muted);
  font: inherit;
  cursor: pointer;
}

.loc-group__count { font-size: var(--font-size-small); }

.loc-group__chevron { transition: transform 0.15s ease; }

.loc-group:not(.collapsed) .loc-group__chevron { transform: rotate(180deg); }

.loc-group.collapsed .loc-group__body { display: none; }

.loc-group__body { border-bottom: var(--tag-border-width) solid var(--theme-bg-muted); }

/* ── Free-text "search for X" row ── the thing a fixed list can't do. */
.opt--newquery {
  width: 100%;
  border: 0;
  background: var(--theme-bg-muted);
  font: inherit;
  text-align: left;
}

/* The search-glyph box marks this as a search action, not a checkable option;
   keep it neutral (green = selection/state in this UI, which this row is not). */
.opt--newquery .opt__box {
  border-color: var(--border-color);
  color: var(--theme-fg-muted);
}

.opt--query .opt__type { color: var(--theme-accent-color); }

/* Desktop counterpart of .opt--newquery: the free-text "search for «X»" row at
   the top of the What dropdown (tag_picker prepends it). Reuses the gem's
   .hw-combobox__option base (padding + hover). It reads like the plain options —
   neutral text, no leading icon — distinguished only by its label ("Search for
   «X»") and the faint active ground when it's the highlighted row. No top border:
   the row sits flush at the top of the listbox now, so a border there just drew a
   stray grey line under the field's focus underline. */
.filter-searchfor {
  display: flex;
  align-items: center;
  gap: var(--gap-small);
  width: 100%;
  border: 0;
  background: none;
  color: var(--theme-fg-color);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.filter-searchfor[hidden] { display: none; }

.filter-searchfor__label {
  flex-grow: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The What field drives its OWN single highlight across the free-text row and the
   options (tag_picker_controller#applyNav): typing lights the free-text row,
   arrowing moves it into the list. The gem's auto-highlight of the soft-selected
   first option is cleared in JS (not suppressed here — that also killed hover/nav
   on that one option), so this is the only highlight, alongside the gem's :hover. */
.filter-searchfor--active,
.hw-combobox__option--nav-active {
  background-color: var(--hw-active-bg-color);
}

/* ── Custom date range ── two native (OS) date pickers → one range. */
.opt--custom {
  flex-direction: column;
  align-items: stretch;
  gap: var(--gap-small);
  cursor: default;
}

.custom-range {
  display: flex;
  align-items: center;
  gap: var(--gap-medium);
}

.custom-range__input {
  flex: 1;
  min-width: 0;
  padding: var(--gap-small) 0;
  border: 0;
  border-bottom: var(--border-width) solid var(--field-border-color);
  background: none;
  color: inherit;
  font: inherit;
}

.custom-range__sep { color: var(--theme-fg-muted); }

/* "Save this show" toggle in the event-actions cluster — the HEART now (the rare,
   powerful signal). A faint outline at rest, a SOLID fill when saved (fill =
   active). In the favorite colour (raspberry), never green. The follow STAR and
   this save HEART share the raspberry family but differ in shape, so the two
   personal signals never rely on colour alone. Masked SVG because Phosphor
   Regular has no fill weight. (Class still named .save-heart — glyph swapped
   bookmark→heart; rename is non-visual cleanup.) */
.save-heart {
  display: inline-block;
  line-height: 0;
}

.save-heart::before {
  content: "";
  display: inline-block;
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  background-color: var(--theme-fg-muted);
  -webkit-mask: var(--heart-outline) center / contain no-repeat;
  mask: var(--heart-outline) center / contain no-repeat;
}

.event-save:hover .save-heart::before {
  background-color: var(--theme-saved-color);
}

/* Saved: solid fill, favorite colour — a filled heart = "saved". */
.event-save.saved .save-heart::before {
  background-color: var(--theme-saved-color);
  -webkit-mask-image: var(--heart-fill);
  mask-image: var(--heart-fill);
}
