:root {
  --cc-hero: linear-gradient(135deg, #0d4f3c 0%, #1a7a5e 55%, #2c9c76 100%);
}

.hero {
  background: var(--cc-hero);
  color: #fff;
}

.hero .form-control,
.hero .btn {
  height: 3.25rem;
}

.section-heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  /* Without this the heading and its "View all" link fight for room on a
     narrow screen and the link gets squeezed to one word per line. */
  flex-wrap: wrap;
  gap: .5rem;
  border-bottom: 2px solid var(--bs-primary);
  padding-bottom: .5rem;
  margin-bottom: 1.25rem;
}

.card-hover {
  transition: transform .15s ease, box-shadow .15s ease;
}

.card-hover:hover {
  transform: translateY(-3px);
  box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .1);
}

.badge-top {
  background: #b8860b;
}

.listing-highlight {
  border-left: 4px solid var(--bs-warning);
  background-color: #fffdf5;
}

.category-tile {
  display: block;
  padding: 1.25rem 1rem;
  text-align: center;
  border: 1px solid var(--bs-border-color);
  border-radius: .5rem;
  text-decoration: none;
  color: inherit;
  height: 100%;
  transition: background-color .15s ease, border-color .15s ease;
}

.category-tile:hover {
  background-color: var(--bs-primary-bg-subtle);
  border-color: var(--bs-primary);
}

.event-date {
  min-width: 4rem;
  text-align: center;
  line-height: 1.1;
}

.ratio-thumb {
  object-fit: cover;
  width: 100%;
  height: 100%;
}

/* Logos, unlike photos, must not be cropped: cover would cut the name off a
   wide wordmark. Fit the whole mark inside the square instead and pad it so
   it does not touch the card edges. */
.logo-thumb {
  object-fit: contain;
  width: 100%;
  height: 100%;
  padding: 1rem;
  background: #fff;
}

/* Quarter-area thumbnail (half the width and height) for the main business
   list. Centred so the card still reads as one unit. */
.thumb-quarter {
  width: 50%;
  margin: .75rem auto 0;
}

.placeholder-thumb {
  background: var(--bs-secondary-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--bs-secondary-color);
  font-size: .875rem;
}

/* ---------- Advertising slots ---------- */

/* The slot reserves its height whether or not it is sold, so selling or
   pulling a banner never shifts the content below it. */
.ad-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.ad-slot img {
  max-width: 100%;
  height: auto;
  display: block;
}

.ad-label {
  font-size: .625rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--bs-secondary-color);
  margin-bottom: .25rem;
}

.ad-placeholder {
  width: 100%;
  max-width: var(--ad-w);
  /* aspect-ratio rather than a fixed height so the placeholder shrinks in
     proportion on a phone instead of overflowing the viewport. */
  aspect-ratio: var(--ad-w) / var(--ad-h);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .25rem;
  text-align: center;
  padding: .5rem;
  border: 1px dashed var(--bs-border-color);
  border-radius: var(--bs-border-radius);
  background: var(--bs-body-bg);
  color: var(--bs-secondary-color);
}

.ad-placeholder-title {
  font-weight: 600;
  font-size: .875rem;
}

.ad-placeholder-size {
  font-size: .75rem;
}

/* Leaderboards are mostly wasted space on a phone, where a 728x90 becomes an
   unreadable sliver. Keep the sidebar unit, which scales down honestly. */
@media (max-width: 575.98px) {
  .ad-slot-top .ad-placeholder,
  .ad-slot-bottom .ad-placeholder {
    display: none;
  }
}

/* ---------- Mobile ---------- */

/* A long URL, email address or business name with no spaces in it will
   otherwise push its container wider than the screen and make the whole page
   scroll sideways. */
body {
  overflow-wrap: break-word;
}

/* Deliberately NOT using `overflow-x: hidden` on the body as a catch-all.
   It hides layout bugs rather than fixing them, and it silently breaks
   position: sticky on the navbar. Overflow is fixed at the source instead. */

@media (pointer: coarse) {
  /* iOS Safari zooms the entire page when a focused field renders below
     16px, leaving the visitor scrolled sideways on a page they now have to
     pinch back out of. Applies to any touch device regardless of width,
     which is why this is scoped by pointer type and not by breakpoint. */
  .form-control,
  .form-select,
  .form-control-sm,
  .form-select-sm,
  input[type="text"],
  input[type="search"],
  input[type="email"],
  input[type="url"],
  input[type="tel"],
  input[type="password"],
  input[type="number"],
  input[type="time"],
  input[type="date"],
  input[type="datetime-local"],
  textarea,
  select {
    font-size: 16px;
  }

  /* Apple and Google both put the minimum comfortable tap target at around
     44px. Bootstrap's default button is 38px and .btn-sm is 31px, which are
     comfortable with a mouse and fiddly with a thumb. */
  .btn,
  .nav-link,
  .page-link,
  .dropdown-item {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* The hamburger is the single most important control on a phone: miss it
     and the visitor cannot navigate at all. */
  .navbar-toggler {
    min-height: 44px;
    min-width: 44px;
  }

  /* Title links in a list row or a sidebar list are the primary way into a
     listing on a phone, but as plain inline links they are only as tall as
     their text - around 19px. Opted in by class rather than by a blanket
     rule on links, because inflating genuine inline links inside a
     paragraph would wreck the line spacing of body copy. */
  .tap-title {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* Section "View all" links are small text by design, so they get their
     tap area from padding rather than from a larger font. */
  .section-heading a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* The site name doubles as the "go home" button. */
  .navbar-brand {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* Category and tag pills are filter controls, not decoration, so they
     need to be hittable even though they render as small badges. */
  a.badge {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding-left: .75rem;
    padding-right: .75rem;
  }

  /* Checkboxes and radios are hard to hit at Bootstrap's 1em default. */
  .form-check-input {
    width: 1.25em;
    height: 1.25em;
  }

  .form-check-label {
    padding: .25rem 0;
  }
}

/* A button group of filter pills runs off the screen on a phone once there
   are more than three or four. Let it wrap instead of overflowing. */
@media (max-width: 575.98px) {
  .btn-group-wrap {
    flex-wrap: wrap;
  }
}

/* ---------- Events calendar ---------- */

/* A real month/week grid. Built with CSS Grid rather than a <table> so the
   seven columns can collapse to one on a phone; a table cannot reflow, and
   wrapping it in a horizontal scroller would mean swiping sideways to read
   a calendar, which defeats the point of having one. */
.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  border: 1px solid var(--bs-border-color);
  border-radius: .5rem;
  overflow: hidden;
  background: var(--bs-body-bg);
}

/* Rows exist for screen readers (role="row"); display:contents lets the
   day cells still participate in the parent grid. */
.cal-row {
  display: contents;
}

.cal-colhead {
  padding: .5rem .25rem;
  text-align: center;
  font-size: .75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--bs-secondary-color);
  background: var(--bs-tertiary-bg);
  border-bottom: 1px solid var(--bs-border-color);
}

.cal-day {
  min-height: 7.5rem;
  padding: .35rem;
  border-top: 1px solid var(--bs-border-color);
  border-left: 1px solid var(--bs-border-color);
  /* minmax(0,1fr) above plus this stops a long event title from forcing a
     column wider than its seventh of the grid. */
  min-width: 0;
  overflow: hidden;
  /* Anchors the stretched day link below. */
  position: relative;
}

/* The whole cell opens the day page. Laid over the cell rather than
   wrapped around it, because an anchor cannot contain the chip anchors. */
.cal-day-link {
  position: absolute;
  inset: 0;
  z-index: 0;
}

/* A calendar cell gives no hint that it is clickable - it reads as a static
   grid square. The affordance therefore has to be explicit: the date is
   styled as a link, and hovering lights the whole cell rather than tinting
   it so faintly that nobody notices. */
.cal-day:hover {
  background: var(--bs-primary-bg-subtle);
  box-shadow: inset 0 0 0 2px var(--bs-primary-border-subtle);
}

.cal-day:hover .cal-daynum {
  color: var(--bs-primary);
  text-decoration: underline;
}

.cal-day-link:focus-visible {
  outline: 2px solid var(--bs-primary);
  outline-offset: -2px;
}

/* The count of what is hidden, shown on every populated cell rather than
   only when events overflow. A day holding two events looked identical to
   a dead square, so there was nothing to suggest clicking it led anywhere. */
.cal-allday {
  position: relative;
  z-index: 1;
  pointer-events: none;
  display: block;
  margin-top: .15rem;
  font-size: .7rem;
  font-weight: 600;
  color: var(--bs-primary);
}

.cal-day:hover .cal-allday {
  text-decoration: underline;
}

/* Keyed on hover capability rather than width. A touch device has no
   hover, and applying these styles on tap leaves the cell stuck looking
   highlighted after the visitor has moved on. Scoping this by screen width
   instead would wrongly strip the feedback from a narrow desktop window. */
@media (hover: none) {
  .cal-day:hover {
    background: inherit;
    box-shadow: none;
  }

  .cal-day:hover .cal-daynum {
    color: inherit;
    text-decoration: none;
  }
}

/* Above the stretched link, so a click on an actual event still reaches
   that event rather than the day page.

   The containers themselves are made transparent to the mouse, or their
   boxes would swallow every click in the empty space around the chips and
   leave most of the cell looking clickable but doing nothing. Only the
   real links inside take pointer events back. */
.cal-daynum,
.cal-chips {
  position: relative;
  z-index: 1;
  pointer-events: none;
}

.cal-chip,
.cal-more {
  pointer-events: auto;
}

.cal-row .cal-day:first-child {
  border-left: 0;
}

/* Days from the previous or next month. Dimmed rather than blanked, so the
   grid still reads as a continuous run of dates. */
.cal-muted {
  background: var(--bs-tertiary-bg);
}

.cal-muted .cal-daynum {
  opacity: .45;
}

.cal-today {
  background: var(--bs-primary-bg-subtle);
}

.cal-daynum {
  display: flex;
  align-items: baseline;
  gap: .35rem;
  font-size: .8rem;
  font-weight: 600;
  margin-bottom: .2rem;
}

.cal-today .cal-daynum {
  color: var(--bs-primary);
}

.cal-dayname {
  font-weight: 400;
  text-transform: uppercase;
  font-size: .7rem;
  color: var(--bs-secondary-color);
}

.cal-chips {
  display: flex;
  flex-direction: column;
  gap: .15rem;
}

.cal-chip {
  display: block;
  padding: .15rem .35rem;
  border-radius: .25rem;
  font-size: .75rem;
  line-height: 1.25;
  background: var(--bs-primary-bg-subtle);
  color: var(--bs-emphasis-color);
  border-left: 3px solid var(--bs-primary);
  /* Titles vary wildly in length; clamp so one long name cannot push a
     cell taller than the rest of its row. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cal-chip-time {
  font-weight: 600;
  margin-right: .2rem;
}

/* Paid Spotlight/Premier placement. Marked with a star as well as a colour
   change so it is still distinguishable without colour vision, and carries
   a visually-hidden "Sponsored:" prefix so a screen reader is told the
   placement was bought rather than earned. */
.cal-chip-sponsored {
  background: var(--bs-warning-bg-subtle);
  border-left-color: var(--bs-warning-border-subtle);
  font-weight: 600;
}

.cal-chip-star {
  margin-right: .15rem;
}

.cal-more {
  font-size: .7rem;
  color: var(--bs-secondary-color);
  padding-left: .35rem;
}

/* The dot summary is the phone-sized month view; hidden on wider screens
   where the chips themselves fit. */
.cal-dots {
  display: none;
  align-items: center;
  gap: .2rem;
  text-decoration: none;
}

.cal-dot {
  width: .4rem;
  height: .4rem;
  border-radius: 50%;
  background: var(--bs-primary);
  display: inline-block;
}

.cal-count {
  font-size: .7rem;
  font-weight: 600;
  color: var(--bs-primary);
}

/* Week view: seven tall columns, one per day. */
.cal-grid-week .cal-day {
  min-height: 14rem;
}

.cal-grid-week .cal-chip {
  white-space: normal;
}

.cal-agenda-day:target h3 {
  color: var(--bs-primary);
}

@media (max-width: 767.98px) {
  /* Month view on a phone: seven columns of roughly 50px cannot show a
     title, so cells shrink to a date and a dot, and the "Day by Day"
     agenda underneath carries the actual detail. */
  .cal-day {
    min-height: 3.5rem;
    padding: .2rem;
  }

  .cal-chips {
    display: none;
  }

  /* A 50px cell has no room for "all 3 >". The dot carries the same
     meaning at phone width, and the cell is tappable either way. */
  .cal-allday {
    display: none;
  }

  /* The dot link is stretched over the whole cell, so the tap target is the
     full day square rather than a 6px dot. It duplicates the cell-wide day
     link underneath it - same destination, so whichever one the tap lands
     on goes to the same place. */
  .cal-dots {
    display: flex;
    position: absolute;
    inset: 0;
    align-items: flex-end;
    justify-content: center;
    padding-bottom: .3rem;
    z-index: 1;
  }

  /* Week view instead becomes a stacked day-by-day agenda, which is
     readable at phone width in a way that seven columns never is. */
  .cal-grid-week {
    grid-template-columns: 1fr;
  }

  .cal-grid-week .cal-colhead {
    display: none;
  }

  .cal-grid-week .cal-day {
    min-height: 0;
    border-left: 0;
  }

  .cal-grid-week .cal-chips {
    display: flex;
  }

  .cal-grid-week .cal-dots {
    display: none;
  }

  /* An empty Tuesday is worth a column on a desktop grid; stacked on a
     phone it is just a row of nothing between the days that matter. */
  .cal-grid-week .cal-day.cal-empty {
    display: none;
  }
}

@media (max-width: 767.98px) and (pointer: coarse) {
  /* Touch sizing is scoped to the phone layout on purpose. Applying it at
     any width would inflate every chip in the desktop month grid on a
     touchscreen laptop and wreck the row heights. */
  .cal-grid-week .cal-chip {
    min-height: 44px;
    display: flex;
    align-items: center;
    padding: .5rem .6rem;
    white-space: normal;
  }
}

/* ---------- Sponsorship tier picker ---------- */
/* The whole card is the label, so the entire card is a tap target rather
   than just the radio button - the radio alone is well under 44px. */
.tier-card {
  cursor: pointer;
  transition: border-color .12s ease-in-out;
}

.tier-card:hover {
  border-color: var(--bs-primary);
}

.tier-card:has(input:checked) {
  border-color: var(--bs-primary);
  box-shadow: 0 0 0 .2rem var(--bs-primary-bg-subtle);
}

/* :has() is not universal; keep a visible focus ring regardless. */
.tier-card:focus-within {
  outline: 2px solid var(--bs-primary);
  outline-offset: 2px;
}

/* ---------- Staff inbox deep links ---------- */
/* The dashboard links to a single message or report by id. Landing on a
   long list with no indication of which row you asked for makes the deep
   link almost useless, so the target row is highlighted on arrival.

   scroll-margin-top keeps the row clear of the sticky staff header, which
   would otherwise cover the very row being jumped to. */
.list-group-item[id^="message-"],
.list-group-item[id^="report-"] {
  scroll-margin-top: 5rem;
}

.list-group-item[id^="message-"]:target,
.list-group-item[id^="report-"]:target {
  background: var(--bs-primary-bg-subtle);
  box-shadow: inset 3px 0 0 var(--bs-primary);
}

/* Section headings are link targets too. */
.section-heading[id] {
  scroll-margin-top: 5rem;
}
