/* Venue Hire's own styles. The club palette, type and top bar come from
   style.css, shared with Club Contacts and Team Sheets; everything here is the
   furniture this app needs on top - the venue strip, stat tiles, money columns
   and the bars that make a season's shape readable at a glance. */

.subnav {
  display: flex;
  gap: 4px;
  padding: 0 24px;
  background: #fff;
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
}
.subnav a {
  padding: 10px 14px;
  text-decoration: none;
  color: var(--muted);
  font-size: 0.88rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  border-bottom: 3px solid transparent;
  white-space: nowrap;
}
.subnav a:hover { color: var(--text); }
.subnav a.active { color: var(--primary); border-bottom-color: var(--gold); }

.impersonation-banner {
  background: #fff8e6;
  border-bottom: 1px solid #f0dfa8;
  padding: 8px 24px;
  font-size: 0.88rem;
  display: flex;
  gap: 12px;
  align-items: center;
}
.impersonation-banner form { margin: 0; }

/* A page's heading with something beside it - a season picker, a check
   page's way back - on one row that wraps. */
.title-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}
.title-row h1 { margin-bottom: 2px; }
.title-row .subtitle { margin: 0; }
/* A page's head (views/_page-head.ejs, the same in all four club apps): the
   heading and its key numbers always shown, and under them a folded "About
   this page and actions" holding the description and the buttons in their
   four groups - Go to, WhatsApp, Download, Send - each a row with its label
   at the left. */
.page-head { margin: 0 0 16px; }
.page-head > summary { cursor: pointer; color: var(--primary); font-size: 0.92rem; }
.page-head > summary .muted { margin-left: 4px; }
.page-head .subtitle { margin: 10px 0 12px; max-width: 760px; }
.page-head-numbers { color: var(--muted); margin: 0 0 6px; }
.page-head-groups { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.page-head-group { display: flex; gap: 6px 8px; align-items: center; flex-wrap: wrap; }
.page-head-group-label { flex: none; min-width: 84px; font-size: 0.78rem; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.03em; }
.page-head-group-name { text-transform: none; letter-spacing: 0; font-weight: 400; }
.page-head-group .inline-form { display: inline; margin: 0; }
/* What a hirer books with stays in plain sight beside the fold. */
.page-head-keep { display: flex; gap: 8px; flex-wrap: wrap; margin: 0 0 12px; }
.title-row .page-head { margin-bottom: 0; }

.season-picker { display: flex; align-items: flex-end; gap: 8px; }
.season-picker select { margin-bottom: 0; min-width: 180px; }
.season-picker label { margin-bottom: 6px; }

/* The headline numbers. Four tiles read as one row on a laptop and wrap to two
   columns on a phone rather than shrinking to illegibility. */
.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
  margin-bottom: 20px;
}
.stat {
  background: var(--card);
  border: 1px solid var(--border);
  border-left: 4px solid var(--primary);
  border-radius: 10px;
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.stat-label { color: var(--muted); font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.06em; }
.stat-value { font-size: 1.5rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.stat-attention { border-left-color: var(--gold); }
.stat-good { border-left-color: #2e7d4f; }

.two-col { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 20px; }

.card-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 12px; }
.card-head h2 { margin: 0; }

.actions { display: flex; gap: 10px; flex-wrap: wrap; margin: 0 0 20px; }

/* Money and hours line up on the decimal point, which is the whole point of a
   costs table - a column you can scan for the big number. */
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.nowrap { white-space: nowrap; }
.muted { color: var(--muted); }
.variance { color: var(--danger); font-weight: 600; }

/* A share-of-total bar drawn behind the figure, so the number stays readable
   and exact while the row still shows its size. */
.bar {
  display: inline-block;
  position: relative;
  padding: 2px 6px;
  border-radius: 4px;
  min-width: 70px;
  text-align: right;
}
.bar::before {
  content: '';
  position: absolute;
  inset: 0 0 0 auto;
  width: var(--share, 0%);
  background: rgba(156, 28, 23, 0.12);
  border-radius: 4px;
  z-index: 0;
}
.bar > * { position: relative; }

.badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 600;
  background: #eef1f6;
  color: var(--muted);
  text-transform: capitalize;
}
.badge-confirmed, .badge-agreed, .badge-paid { background: #eaf7ee; color: #1f6b3e; }
.badge-exported { background: #e8eefb; color: #274690; }
.badge-draft { background: #eef1f6; color: var(--muted); }
.badge-requested, .badge-received, .badge-warn { background: #fff4d9; color: #8a5a00; }
.badge-declined, .badge-cancelled, .badge-queried { background: #fdecea; color: var(--danger); }
.badge-venue { background: #e8eefb; color: #274690; }
/* The EDJBA round, as its own tag beside the date. Not capitalised the way the
   statuses are: these are "Round 12", "SF", "GF", "NO GAME". */
/* A booking's tag - OMC and the like - as a link that filters by it. */
.badge-tag { background: #e6f4f1; color: #1d6b5c; text-transform: none; text-decoration: none; margin-right: 4px; }
.badge-tag:hover { background: #d3ece6; }
.badge-round { background: #f0eef6; color: #4a4363; text-transform: none; font-weight: 500; }

/* Dense tables: a hairline above each new date groups a day's courts together
   without a heading row per date. */
.bookings-table tr.new-day td { border-top: 1px solid var(--border); }
.bookings-table tr.status-declined td, .bookings-table tr.status-cancelled td { opacity: 0.55; }
.bookings-table td { padding-top: 6px; padding-bottom: 6px; }

.row-actions a, .row-actions button.quiet { font-size: 0.85rem; margin-right: 8px; }
form.inline { display: inline; margin: 0; }
/* A venue's Decline / Stand down: a link that opens to ask for the reason. */
details.inline-action { display: inline-block; vertical-align: top; font-size: 0.85rem; }
details.inline-action summary {
  cursor: pointer; text-decoration: underline; list-style: none; color: var(--primary);
}
details.inline-action summary::-webkit-details-marker { display: none; }
details.inline-action summary.danger { color: var(--danger); }
details.inline-action form { display: flex; gap: 6px; align-items: center; margin: 4px 0 0; }
details.inline-action input[type="text"] { width: 12rem; margin: 0; padding: 4px 6px; font-size: 0.85rem; }

.filter-card { padding: 16px 20px; }

.field-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0 16px; }

label.check { display: flex; align-items: center; gap: 8px; font-weight: 400; margin-bottom: 10px; }
label.check input { width: auto; margin: 0; }


.code-input { letter-spacing: 0.4em; font-size: 1.3rem; text-align: center; }

@media (max-width: 640px) {
  .title-row { flex-direction: column; }
  .season-picker { width: 100%; }
  .season-picker select { width: 100%; }
}

/* The read-only side of the Venues screen: what the app knows about a venue
   that isn't editable, laid out as label and value rather than as a data table. */
.venue-facts th {
  text-align: left;
  vertical-align: top;
  width: 110px;
  color: var(--muted);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding-top: 10px;
}
.venue-facts td { padding-top: 8px; }
.venue-facts tr:first-child th, .venue-facts tr:first-child td { padding-top: 0; }
.venue-facts .check { margin: 4px 0 8px; font-size: 0.9rem; }

.venue-contact { display: flex; gap: 18px; flex-wrap: wrap; align-items: baseline; margin: 0 0 6px; }

/* style.css styles the input types Club Contacts uses - text, email, file and
   date. This app also uses time, number and tel, on the booking, rates, invoice
   and venue forms, which would otherwise fall back to the browser's own sizing
   and sit noticeably narrower than the fields beside them. */
input[type="time"],
input[type="number"],
input[type="tel"] {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 1rem;
  margin-bottom: 16px;
  background: var(--card);
  color: var(--text);
}

/* Narrower than a full-width field, and after the rule above so it wins: a bare
   class would lose to that rule's attribute selector. */
input.rate-input { width: 110px; margin-bottom: 0; text-align: right; }

/* "Back" goes to the page you came from, so it reads as a step in the trail
   rather than a fixed parent. Sits above the heading, out of the way. */
.back-link {
  display: inline-block;
  margin-bottom: 12px;
  color: var(--muted);
  text-decoration: none;
  font-size: 0.88rem;
}
.back-link:hover { color: var(--primary); text-decoration: underline; }

/* Switching between the flat list and the workbook-style calendar. */
.view-switch { display: flex; gap: 4px; align-items: center; margin-bottom: 16px; }
.view-switch a {
  padding: 6px 14px;
  border: 1px solid var(--border);
  background: var(--card);
  border-radius: 6px;
  text-decoration: none;
  color: var(--muted);
  font-size: 0.88rem;
  font-weight: 600;
}
.view-switch a.active { background: var(--primary); border-color: var(--primary); color: #fff; }
.view-switch .muted { font-size: 0.85rem; margin-left: 6px; }

/* The calendar: a venue's courts side by side, as the workbooks had them. Dense
   on purpose - a whole term should fit without scrolling past what matters.

   The header stays put while the grid scrolls. That needs its own scroll box
   rather than the page's: .table-scroll sets overflow-x, which makes an element
   a scroll container on BOTH axes, so a sticky header inside it would anchor to
   a container that never scrolls vertically and simply not move. Giving the box
   a height makes it a real viewport, and the header sticks to that.

   Each row carries its shading as --row-bg rather than setting a background on
   its cells, so the frozen Date and Round columns can paint the same colour and
   nothing shows through them when the grid scrolls sideways. */
.grid-scroll {
  max-height: calc(100vh - 230px);
  overflow: auto;
}
.grid-table { font-size: 0.85rem; border-collapse: separate; border-spacing: 0; }
.grid-table th, .grid-table td { padding: 4px 8px; border-bottom: 1px solid var(--border); }

.grid-table thead th {
  position: sticky;
  z-index: 2;
  background: #eef1f6;
  /* The header sits over the frozen columns, which are themselves raised. */
}
.grid-table thead tr:first-child th { top: 0; height: 30px; }
.grid-table thead tr:nth-child(2) th { top: 30px; }
/* Where the two header rows meet the grid, a line the sticky cells carry with
   them - a table border would scroll away underneath. */
.grid-table thead tr:last-child th { box-shadow: inset 0 -2px 0 var(--border); }

.grid-table .court-head {
  text-align: center;
  border-left: 2px solid var(--border);
  border-right: 2px solid var(--border);
  color: var(--primary);
}

/* Date and Round stay put when the grid scrolls sideways - BSC is five courts
   wide, and a row of times means nothing without its date. */
.grid-table .col-date, .grid-table .col-round {
  position: sticky;
  background: var(--row-bg, var(--card));
  z-index: 1;
}
.grid-table .col-date { left: 0; }
.grid-table .col-round { left: var(--col-date-w, 92px); box-shadow: inset -2px 0 0 var(--border); }
.grid-table thead .col-date, .grid-table thead .col-round { z-index: 3; background: #eef1f6; }

.grid-table tbody tr { --row-bg: var(--card); }
.grid-table tbody tr.new-day td { border-top: 1px solid var(--border); }
.grid-table tfoot th {
  position: sticky;
  bottom: 0;
  background: #eef1f6;
  border-top: 2px solid var(--border);
  z-index: 2;
}

/* Why a date reads the way it does, shaded the way the workbook shaded them. */
.grid-table tr.day-holiday { --row-bg: #fff4d9; }
.grid-table tr.day-blocked { --row-bg: #eceff3; }
.grid-table tr.day-stood-down { --row-bg: #fdecea; }
.grid-table tr.day-empty { --row-bg: #fbfbfc; }
/* A Saturday with no round: the games are off, which is why it's empty. */
.grid-table tr.day-no-game { --row-bg: #f0eef6; }
.day-holiday > td, .day-blocked > td, .day-stood-down > td, .day-empty > td, .day-no-game > td { background: var(--row-bg); }

/* The list view shades whole rows the same way, without the frozen columns. */
.bookings-table tr.day-holiday > td { background: #fff4d9; }

/* A run of empty no-round days, folded into one line. */
.grid-table tr.day-gap { --row-bg: #f4f6f8; }
.grid-table tr.day-gap td { background: var(--row-bg); color: var(--muted); font-size: 0.85rem; padding-top: 10px; padding-bottom: 10px; }
.grid-table tr.day-gap strong { color: var(--text); }

.day-note td {
  font-size: 0.8rem;
  font-style: italic;
  color: var(--muted);
  padding-top: 0;
  padding-bottom: 6px;
}
.struck { text-decoration: line-through; color: var(--muted); }
/* One court stood down on a date whose others went ahead. Shaded per cell, not
   per row, so it reads against its neighbours. */
.grid-table td.cell-stood-down { background: #fdecea; }
.grid-table td.cell-stood-down a { color: var(--danger); }
.grid-table td.cell-tagged { background: #e6f4f1; }
.badge-cell { font-size: 10px; padding: 1px 5px; vertical-align: 1px; margin: 0 0 0 5px; }

.grid-key { font-size: 0.8rem; color: var(--muted); margin: 12px 0 0; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.grid-key .key { width: 14px; height: 14px; border: 1px solid var(--border); border-radius: 3px; display: inline-block; margin-left: 10px; }
.grid-key .key:first-child { margin-left: 0; }
.key-holiday { background: #fff4d9; }
.key-blocked { background: #eceff3; }
.key-stood-down { background: #fdecea; }
.key-empty { background: #fbfbfc; }
.key-no-game { background: #f0eef6; }
.key-tagged { background: #e6f4f1; }
/* A one-field form sitting in a table cell - the Seasons screen's Xero Job. */
form.inline-row { display: flex; gap: 6px; align-items: center; margin: 0; }
form.inline-row input[type="text"] { width: 12rem; margin: 0; }
form.inline-row button { margin: 0; }

/* A bill's Mark paid: the button opens to ask for the date it was paid. */
details.mark-paid { position: relative; }
details.mark-paid summary { list-style: none; }
details.mark-paid summary::-webkit-details-marker { display: none; }
details.mark-paid form {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 5; width: 220px;
  background: var(--card); border: 1px solid var(--border); border-radius: 10px; padding: 12px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
}
details.mark-paid form button { width: 100%; }

/* A stat tile with an icon beside its figure - the Bills summary. */
.stat.stat-with-icon { flex-direction: row; align-items: center; gap: 14px; }
.stat-with-icon > div { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.stat-icon {
  flex: none; width: 40px; height: 40px; border-radius: 50%;
  display: grid; place-items: center; background: #f3e9e8; color: var(--primary);
}
.stat-attention .stat-icon { background: #fff4d9; color: #8a5a00; }
.stat-good .stat-icon { background: #eaf7ee; color: #1f6b3e; }
.stat-icon svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.stat-note { font-size: 0.8rem; }

/* The top bar holds more links than the shared style.css expected. On a
   laptop-width screen they wrap onto a second line rather than pushing Log out
   off the page; below 640px the menu collapses as before. */
@media (min-width: 641px) {
  header.topbar { gap: 16px; }
  header.topbar .brand { flex: none; }
  header.topbar nav { flex-wrap: wrap; justify-content: flex-end; gap: 6px 16px; min-width: 0; }
}

/* The top bar's dropdowns - Finances and Settings. The summary reads like the
   links beside it, with a caret; the menu opens as a card below it. */
header.topbar details.nav-menu { position: relative; }
header.topbar details.nav-menu summary {
  list-style: none; cursor: pointer; opacity: 0.85; display: flex; align-items: center; gap: 5px;
}
header.topbar details.nav-menu summary::-webkit-details-marker { display: none; }
header.topbar details.nav-menu summary::after {
  content: ''; width: 0; height: 0; margin-top: 2px;
  border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 5px solid currentColor;
}
header.topbar details.nav-menu[open] summary::after { transform: rotate(180deg); }
header.topbar details.nav-menu summary:hover,
header.topbar details.nav-menu[open] summary { opacity: 1; }
header.topbar nav .active { opacity: 1; font-weight: 600; }
header.topbar .nav-menu-items {
  position: absolute; top: calc(100% + 12px); left: -12px; z-index: 30; min-width: 220px;
  display: flex; flex-direction: column; padding: 6px;
  background: var(--card); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.18);
}
/* Help sits near the right edge, so its menu opens leftwards to stay on screen. */
header.topbar details.nav-menu-right .nav-menu-items { left: auto; right: -12px; }
header.topbar .nav-menu-items a {
  color: var(--text); opacity: 1; padding: 8px 10px; border-radius: 6px; font-size: 0.92rem;
}
header.topbar .nav-menu-items a:hover { background: #f4f1f0; text-decoration: none; }
header.topbar .nav-menu-items a.active { color: var(--primary); background: #f7eeed; }
header.topbar .nav-menu-items a span { display: block; color: var(--muted); font-size: 0.78rem; font-weight: 400; }

/* In the collapsed phone menu, a dropdown opens in place under its name. */
@media (max-width: 640px) {
  header.topbar .nav-menu-items {
    position: static; box-shadow: none; border: none; background: transparent; padding: 6px 0 0 12px; min-width: 0;
  }
  header.topbar .nav-menu-items a { color: #fff; padding: 6px 0; }
  header.topbar .nav-menu-items a:hover, header.topbar .nav-menu-items a.active { background: transparent; color: #fff; }
  header.topbar .nav-menu-items a span { color: rgba(255, 255, 255, 0.7); }
}

/* A stat tile that opens what it counts. */
a.stat-link { color: inherit; text-decoration: none; }
a.stat-link:hover { border-color: var(--primary); box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06); }
a.stat-link:hover .stat-label { text-decoration: underline; }

/* A row's actions in a "⋮" menu, as in Club Contacts and Team Sheets. The list is
   position:fixed (placed by _action-menu-script) so the scrolling table never
   clips it or widens for it. */
.row-menu-cell { width: 1%; text-align: right; }
.action-menu { position: relative; display: inline-block; }
.action-menu > summary { list-style: none; cursor: pointer; padding: 3px 9px; border: 1px solid var(--border); border-radius: 6px; font-size: 1.1rem; line-height: 1.4; color: var(--muted); user-select: none; }
.action-menu > summary::-webkit-details-marker { display: none; }
.action-menu > summary:hover, .action-menu[open] > summary { border-color: var(--primary); color: var(--primary); }
.action-menu-list { position: fixed; visibility: hidden; background: var(--card); border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15); min-width: 180px; z-index: 30; padding: 4px; text-align: left; }
.action-menu-item { display: block; padding: 8px 10px; border-radius: 6px; font-size: 0.88rem; color: var(--text); text-decoration: none; white-space: nowrap; }
.action-menu-item:hover { background: var(--bg); }
.action-menu-list form { margin: 0; }
button.action-menu-item { width: 100%; margin: 0; background: none; border: none; text-align: left; font: inherit; font-size: 0.88rem; color: var(--text); cursor: pointer; }
button.action-menu-item:hover { background: var(--bg); }
.action-menu-item.danger { color: var(--danger); }
tr.editing td { background: #fff8e6; }

/* The Users form, the width of the list below it: email, name, mobile and what
   they see on one line, the permissions under them. */
.user-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 0 16px; align-items: end; }
.user-fields input, .user-fields select { margin-bottom: 12px; }
.user-checks { display: flex; flex-wrap: wrap; gap: 4px 24px; }
.user-form.editing { border-color: var(--gold); }

/* Help Desk: a member's tickets and the conversation on one. The club's side
   sits left in the club's colour, the member's own right, like a chat. */
.help-card { max-width: 760px; }
.help-card textarea { width: 100%; }
.badge-help-new { background: #fff4d9; color: #8a5a00; }
.badge-help-open { background: #e8eefb; color: #274690; }
.badge-help-closed { background: #eef1f6; color: var(--muted); }
.badge-help-replied { background: #eaf7ee; color: #1f6b3e; text-transform: none; margin-left: 4px; }
.help-conversation { display: flex; flex-direction: column; gap: 12px; margin-bottom: 20px; }
.help-message { max-width: 85%; padding: 10px 14px; border-radius: 10px; border: 1px solid var(--border); }
.help-message-club { align-self: flex-start; background: #f7eeed; border-color: #ecd3d1; }
.help-message-member { align-self: flex-end; background: #f4f6fa; }
.help-message-meta { font-size: 0.78rem; color: var(--muted); margin-bottom: 4px; }
.help-message-body { white-space: pre-wrap; overflow-wrap: anywhere; }
/* Files on a ticket's message - a screenshot from the club, say. */
.help-files { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 8px; }
.help-file-thumb img { display: block; max-width: 220px; max-height: 160px; border: 1px solid var(--border, #ddd); border-radius: 6px; }

/* Ask BlazerBot: the question, the answer and its sources, and the club's
   list of what has been asked. The same classes as the other three apps'. */
.help-bot-docs { font-size: 0.85rem; }
.help-bot-docs .badge { margin: 2px 2px 2px 0; text-decoration: none; }
.help-bot-note { font-size: 0.85rem; margin-top: -4px; }
.help-bot-actions { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-top: 8px; }
.help-bot-sources { font-size: 0.88rem; margin-top: 0; padding-left: 1.2em; }
.help-list { list-style: none; margin: 0; padding: 0; }
.help-bot-asked { padding: 12px 0; border-top: 1px solid var(--border); }
.help-bot-asked:first-child { border-top: 0; }
.help-bot-asked details { font-size: 0.9rem; }
.help-list-top { display: flex; flex-wrap: wrap; gap: 8px; align-items: baseline; }
.help-list-desc { margin: 6px 0; overflow-wrap: anywhere; }
.help-when { font-size: 0.8rem; }
.badge.help-bot-down { background: #fdecec; color: #b91c1c; }
.badge.help-bot-up { background: #e7f6ec; color: #15803d; }
.badge.help-bot-warn { background: #fff1e0; color: #b45309; }

/* Ask BlazerBot as a chat (JPI-83, as in Club Volunteers): the asker's
   messages on the right, BlazerBot's answers on the left, then the box for
   the next message. */
.help-chat-turn { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
.help-chat-me { align-self: flex-end; max-width: 85%; background: var(--primary); color: #fff; border-radius: 14px 14px 4px 14px; padding: 8px 14px; }
.help-chat-me p { margin: 0; white-space: pre-line; overflow-wrap: anywhere; }
.help-chat-bot { align-self: flex-start; max-width: 92%; background: var(--bg); border: 1px solid var(--border); border-radius: 14px 14px 14px 4px; padding: 10px 14px; overflow-wrap: anywhere; }
.help-chat-bot > p:last-child, .help-chat-bot > ul:last-child, .help-chat-bot > form:last-child { margin-bottom: 0; }
.help-chat-who { margin: 0 0 4px; font-size: 0.8rem; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.help-chat-form { border-top: 1px solid var(--border); padding-top: 14px; }
.help-chat > p.muted + .help-chat-form { border-top: 0; padding-top: 0; }
@media (max-width: 640px) { .help-chat-bot { max-width: 100%; } }

/* Adding a passkey. The name box is a name, not an essay, and the buttons sit
   in a row under it with the lesser choice as a secondary - two full-strength
   buttons stacked read as two equal decisions, which they are not. */
.passkey-name, .passkey-code { max-width: 260px; }
.passkey-code { max-width: 140px; letter-spacing: 0.12em; }
.passkey-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin: 10px 0 0; }
.passkey-actions form { display: inline; margin: 0; }
.passkey-actions button { margin: 0; }

/* The honeypot on the "can't log in" form: off the page for people, present
   for a robot that fills in every box. Without this the box is visible, and a
   real question typed into it is thanked and thrown away. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* The filters every list page shares (JPI-3, Club Volunteers' block;
   views/_filters.ejs, lib/filters.js). The search box on its own line; what
   is on as chips with "Showing N of M"; the rest folded under More filters,
   tick lists in a grid, Apply and Clear all bottom right. The panel never
   widens the page: its columns may shrink to nothing and a long label
   wraps. */
.filters { padding: 14px 20px; }
.filters label, .filters input, .filters select { margin-bottom: 0; }
.filters-scope { display: flex; gap: 8px 12px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
.filters-scope label { margin: 0; }
.filters-scope select { margin: 0; width: auto; max-width: 100%; }
.filters-search { display: flex; gap: 8px; align-items: center; max-width: 560px; }
.filters-search input { margin: 0; flex: 1 1 auto; width: 100%; min-width: 0; }
.filters-search noscript { display: flex; }
input[type="search"] {
  width: 100%; padding: 10px 12px; border: 1px solid var(--border); border-radius: 6px;
  font-size: 1rem; background: var(--card); color: var(--text);
}
.filters-state { display: flex; gap: 6px 8px; align-items: center; flex-wrap: wrap; margin-top: 8px; min-height: 1.4em; }
.filters-state:empty { display: none; }
.filters-showing { font-size: 0.88rem; }
.chip { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; padding: 3px 8px 3px 10px; border: 1px solid var(--primary); border-radius: 999px; background: #fbf4f3; color: var(--primary); font-size: 0.82rem; text-decoration: none; line-height: 1.3; }
.chip:hover, .chip:focus-visible { background: var(--primary); color: #fff; text-decoration: none; }
.chip-x { font-weight: 700; font-size: 1rem; line-height: 1; }
.filters-more { margin-top: 10px; }
.filters-more > summary { cursor: pointer; color: var(--primary); font-size: 0.92rem; }
.filters-on { color: var(--muted); }
.filters-groups { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 12px 20px; margin-top: 12px; }
.filters-group { border: 0; margin: 0; padding: 0; min-width: 0; }
.filters-group legend, .filters-field label { padding: 0; margin: 0 0 4px; font-size: 0.78rem; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.03em; }
.filters-field input { margin: 0; min-width: 0; }
.filters-group .tick { display: flex; align-items: flex-start; gap: 8px; margin: 0; padding: 4px 0; font-weight: 400; font-size: 0.92rem; cursor: pointer; overflow-wrap: anywhere; }
.filters-group .tick input { margin: 3px 0 0; flex: none; width: auto; }
.filters-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
/* While the server is asked again for a search, the list fades a little. */
[data-swap].swapping { opacity: 0.55; transition: opacity 0.15s; }
@media (max-width: 640px) {
  .filters { padding: 12px 14px; }
  .filters-groups { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 12px; }
  .filters-actions { justify-content: stretch; }
  .filters-actions > * { flex: 1; text-align: center; }
}

/* Count cards (views/_count-cards.ejs): this app's tiles, smaller, as many
   as fit on a row. A card that is a filter is a switch - lit, it is red
   through, its labels white too. */
.count-cards { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; }
.count-cards .stat { padding: 12px 14px; }
.count-cards .stat-value { font-size: 1.3rem; }
.count-cards .stat-label { font-size: 0.72rem; letter-spacing: 0.03em; font-weight: 600; }
/* Tiles with an icon (Bills') are fewer and want the room, as they had. */
.count-cards:has(.stat-with-icon) { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; }
.count-cards .stat-with-icon .stat-value { font-size: 1.5rem; }
a.stat-on, a.stat-on:hover, a.stat-on:focus-visible { background: var(--primary); border-color: var(--primary); color: #fff; }
a.stat-on .stat-label, a.stat-on .stat-value, a.stat-on .stat-note { color: #fff; }
a.stat-on:hover .stat-label { text-decoration: none; }
a.stat-on .stat-icon { background: rgba(255, 255, 255, 0.18); color: #fff; }
@media (max-width: 640px) {
  .count-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
}

/* The x that empties a search box (public/search-clear.js, Club Volunteers'
   script): inside the box at its right, in the iPhone's shape, in place of
   the browser's own (hidden, so there are never two). Its height is set by
   the script, to the box's middle. */
.search-clear-wrap { position: relative; vertical-align: middle; }
.search-clear-wrap > input { padding-right: 40px; }
input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }
.search-clear { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); width: 22px; height: 22px; min-height: 0; padding: 0; margin: 0; border: 0; border-radius: 50%; background: var(--text); color: var(--card); font-size: 16px; font-weight: 700; line-height: 22px; text-align: center; cursor: pointer; box-shadow: none; }
.search-clear:hover { background: var(--text); color: var(--card); }
/* The shared button rule gives every button a display, which would beat the
   hidden attribute - an empty search box would show its x. Hidden is hidden,
   whatever else styles the element (Club Volunteers' rule). */
[hidden] { display: none !important; }
/* A bigger target than it looks, for a thumb. */
.search-clear::before { content: ''; position: absolute; inset: -10px; }

/* BlazerBot's face beside each of its answers (JPI-82): the avatar is the
   head in a cream badge, so it reads on a light bubble and in dark mode. */
.help-chat-who { display: flex; align-items: center; gap: 8px; }
.help-chat-avatar { width: 40px; height: 40px; flex: none; }
/* Faded where the documents didn't hold the answer. */
.help-chat-avatar.is-faded { opacity: 0.45; filter: grayscale(0.6); }
/* On Questions asked: the face beside what BlazerBot said. */
.help-asked-answer { display: flex; align-items: flex-start; gap: 12px; margin-top: 8px; }
.help-asked-answer > div { flex: 1; min-width: 0; }
.help-asked-answer > div > p:first-child { margin-top: 0; }

/* The full mascot on Ask BlazerBot: at the right of the title, standing down
   over the top edge of the chat's card below - only as far as that card's
   own padding, so it never covers the first message. It comes first in the
   page so that on a phone it can float beside the title with the words
   running round it; on a wider screen it is put last. */
.help-bot-head { display: flex; align-items: flex-end; gap: 24px; }
.help-bot-head-text { flex: 1; min-width: 0; }
.help-bot-head-text > p:last-child { margin-bottom: 0; }
.help-bot-mascot { order: 2; width: 150px; height: auto; flex: none; margin-bottom: -62px; position: relative; z-index: 1; }
@media (max-width: 640px) {
  .help-bot-head { display: block; }
  .help-bot-head::after { content: ''; display: block; clear: both; }
  .help-bot-mascot { float: right; width: 96px; margin: 0 0 6px 10px; }
}

/* The top bar's shortcut to BlazerBot (JPI-82): a pill with its face and
   "Ask BlazerBot", right after the app's name, outlined in gold on the Ask
   page. It is the logo's height, so the bar is no deeper for it. The words
   drop before the bar's links would wrap - sooner on the club's own long
   bar - and on a phone it is the face alone, a 44px round button beside the
   menu button. */
header.topbar .ask-bot {
  display: flex; align-items: center; gap: 8px; flex: none; box-sizing: border-box;
  height: 40px; padding: 3px 14px 3px 3px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.4);
  color: #fff; font-weight: 600; font-size: 0.92rem; white-space: nowrap;
}
header.topbar .ask-bot:hover { background: rgba(255, 255, 255, 0.22); text-decoration: none; }
header.topbar .ask-bot[aria-current] { border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold); }
header.topbar .ask-bot img { width: 32px; height: 32px; display: block; }
/* Measured as club staff: the long bar's links keep to one row beside the
   words down to about 1170px; a venue's or a hirer's bar is short. */
@media (max-width: 1199px) {
  header.topbar .ask-bot-long { padding: 3px; }
  header.topbar .ask-bot-long .ask-bot-words { display: none; }
}
@media (max-width: 899px) {
  header.topbar .ask-bot { padding: 3px; }
  header.topbar .ask-bot .ask-bot-words { display: none; }
}
/* It sits beside the app's name and the links keep to the right: the bar
   needn't spread its items. */
@media (min-width: 641px) {
  header.topbar { justify-content: flex-start; }
  header.topbar nav { margin-left: auto; }
}
@media (max-width: 640px) {
  header.topbar .ask-bot { width: 44px; height: 44px; justify-content: center; margin: 0 12px 0 auto; }
  header.topbar .ask-bot img { width: 38px; height: 38px; }
}
/* Its face beside the Help menu's own entry. */
header.topbar .nav-menu-items a.nav-bot { display: flex; align-items: center; gap: 10px; font-weight: 600; }
header.topbar .nav-menu-items a.nav-bot img { width: 30px; height: 30px; flex: none; }

/* The page's one Back (views/_back.ejs), at its head. */
p.back-line { margin: 0 0 10px; font-size: 0.92rem; }
