:root {
  --primary: #9c1c17;
  --gold: #f7941d;
  --bg: #f6f7f9;
  --card: #ffffff;
  --text: #1c2430;
  --muted: #667085;
  --border: #e3e7ed;
  --danger: #b3261e;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
}

header.topbar {
  background: var(--primary);
  color: #fff;
  padding: 10px 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 3px solid var(--gold);
  position: relative;
}

header.topbar a { color: #fff; text-decoration: none; }
header.topbar .brand { font-weight: 700; font-size: 1.1rem; display: flex; align-items: center; gap: 10px; }
header.topbar .brand-link { display: block; flex: none; }
header.topbar .brand-logo { height: 40px; width: auto; display: block; }
/* The version sits small under the title, inside the logo's height, so it
   adds nothing to the bar's width or its depth. */
header.topbar .brand-text { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.15; white-space: nowrap; }
header.topbar .brand-version { font-weight: 400; font-size: 0.68rem; opacity: 0.75; }
header.topbar .brand-version:hover { opacity: 1; text-decoration: underline; }
header.topbar nav { display: flex; gap: 18px; align-items: center; font-size: 0.92rem; }
header.topbar nav a { opacity: 0.85; }
header.topbar nav a:hover { opacity: 1; text-decoration: underline; }
header.topbar form { margin: 0; }
/* Log out is a quiet button in the bar's own white. */
header.topbar button.quiet { color: #fff; opacity: 0.85; text-decoration: none; }
header.topbar button.quiet:hover { opacity: 1; text-decoration: underline; }

/* Below the breakpoint, the nav collapses into a dropdown opened by a
   hamburger button - a checkbox drives it so it works with no JS. */
.nav-toggle { display: none; }
.nav-toggle-btn { display: none; cursor: pointer; font-size: 1.5rem; line-height: 1; padding: 2px 4px; }

.admin-group { margin-bottom: 28px; }
.admin-group > h2 { color: var(--primary); border-bottom: 2px solid var(--gold); padding-bottom: 6px; display: inline-block; margin-bottom: 14px; }
/* In case of Emergency: a closed <details>, so no JS; its heading reads like
   the others, with the marker kept so it plainly opens. */
.admin-group.emergency > summary { cursor: pointer; }
.admin-group.emergency > summary > h2 { display: inline-block; color: var(--primary); border-bottom: 2px solid var(--gold); padding-bottom: 6px; margin: 0 0 14px; }

.admin-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px; }
.admin-cards a.card { display: block; text-decoration: none; color: inherit; transition: border-color 0.15s; }
.admin-cards a.card:hover { border-color: var(--primary); }
.admin-cards h2 { color: var(--primary); margin-bottom: 6px; }
.admin-cards p { margin: 0; color: var(--muted); font-size: 0.88rem; }

main {
  max-width: 1100px;
  margin: 0 auto;
  padding: 32px 24px 64px;
}

/* Team sheets and admin pages carry wide tables (rosters, uniform lists,
   audit logs) that truncate or wrap awkwardly inside the standard reading
   width - let them use the full window instead. Narrow windows still work:
   .table-scroll scrolls its table horizontally rather than the page. */
main.main-wide {
  max-width: none;
}

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 24px;
  margin-bottom: 20px;
}

h1 { font-size: 1.5rem; margin: 0 0 4px; }
h2 { font-size: 1.15rem; margin: 0 0 12px; }
p.subtitle { color: var(--muted); margin: 0 0 20px; }

label { display: block; font-weight: 600; font-size: 0.85rem; margin-bottom: 6px; }
input[type="text"], input[type="email"], input[type="tel"], input[type="file"], input[type="date"], input[type="search"], input[type="number"], select, textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 1rem;
  font-family: inherit;
  margin-bottom: 16px;
  background: var(--card);
  color: var(--text);
}

/* Four kinds of button, one look - the same in all four apps (Jira JPI-4,
   the president, 3 October 2026: some were white with red text and some red
   with white, with nothing to say why). Primary is the one action a form or
   section is for - red, white text - and there is at most one in a form.
   Secondary is everything else: going to another page, a download, a copy,
   cancel, clear. Danger removes, reverses or unpublishes, and always asks
   first. Quiet is a small action on a table row or in the top bar, drawn as
   underlined text with no box. A <button> or .btn with no kind is drawn grey
   on purpose, so a missed one reads as plainly wrong rather than quietly
   primary - buttons.test.js fails it too. Both <button> and <a class="btn">
   take them, and .small is the size for a page head, a table row or a
   filter panel. */
button, .btn {
  display: inline-block;
  padding: 10px 18px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: #eef1f6;
  color: var(--text);
  font-size: 0.95rem;
  line-height: normal;
  cursor: pointer;
  text-decoration: none;
  text-align: center;
}
button.primary, .btn.primary { background: var(--primary); color: #fff; border-color: var(--primary); }
button.secondary, .btn.secondary { background: var(--card); color: var(--primary); border-color: var(--border); }
button.danger, .btn.danger { background: var(--card); color: #7a1510; border-color: #f4c7c3; }
button.quiet, .btn.quiet {
  background: none; border: none; border-radius: 0; padding: 0;
  color: var(--primary); text-decoration: underline; font: inherit; text-align: left;
}
button.small, .btn.small { padding: 5px 12px; font-size: 0.85rem; }
button.quiet.small, .btn.quiet.small { padding: 0; font-size: 0.85rem; }
/* The same hover, focus ring and disabled look whatever the kind. */
button:hover, .btn:hover { opacity: 0.92; }
button.secondary:hover, .btn.secondary:hover, button.danger:hover, .btn.danger:hover { background: var(--bg); opacity: 1; }
button.quiet:hover, .btn.quiet:hover { opacity: 1; text-decoration-thickness: 2px; }
button:focus-visible, .btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
button:disabled, button:disabled:hover, .btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }

/* A page's head (views/_page-head.ejs): 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; font-size: 0.85rem; }
.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; }

/* A yes/no question needing real, explicitly-labelled buttons rather than
   a native confirm()'s ambiguous OK/Cancel - see the scoring roster's
   coach question in team-sheet.ejs for why. */
.confirm-dialog { max-width: 380px; border: 1px solid var(--border); border-radius: 10px; padding: 20px; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18); }
.confirm-dialog::backdrop { background: rgba(28, 36, 48, 0.5); }
.confirm-dialog p { margin: 0 0 18px; }
.confirm-dialog-actions { display: flex; justify-content: flex-end; gap: 10px; }

.error { color: var(--danger); background: #fdecea; border: 1px solid #f4c7c3; padding: 10px 14px; border-radius: 6px; margin-bottom: 16px; font-size: 0.9rem; }
.notice { background: #fff8e6; border: 1px solid #f0dfa8; padding: 10px 14px; border-radius: 6px; margin-bottom: 16px; font-size: 0.9rem; }
.success { background: #eaf7ee; border: 1px solid #bfe6cb; padding: 10px 14px; border-radius: 6px; margin-bottom: 16px; font-size: 0.9rem; }

.season-group { margin-bottom: 24px; }
.season-group h2 { color: var(--primary); border-bottom: 2px solid var(--gold); padding-bottom: 6px; display: inline-block; }

table { width: 100%; border-collapse: collapse; margin-top: 8px; }
th, td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--border); font-size: 0.92rem; }
th { color: var(--muted); font-weight: 600; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; }

/* Sortable column headers - see sortable-tables.js, which adds/toggles
   these classes on click. */
th.sortable { cursor: pointer; user-select: none; }
th.sortable:hover { color: var(--primary); }
th.sortable.sort-asc::after { content: "\25B2"; margin-left: 5px; font-size: 0.7em; }
th.sortable.sort-desc::after { content: "\25BC"; margin-left: 5px; font-size: 0.7em; }

.team-list { list-style: none; padding: 0; margin: 0; }
.team-list li { padding: 12px 0; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; }
.team-list li:last-child { border-bottom: none; }
.team-list a { color: var(--primary); font-weight: 600; text-decoration: none; }
.team-list a:hover { text-decoration: underline; }

.badge { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 0.72rem; font-weight: 600; background: #eef1f6; color: var(--primary); }
.badge.player { background: #eaf2ff; color: #1d4ed8; }
.badge.coach { background: #fff1e0; color: #b45309; }
.badge.team_manager { background: #f1e8ff; color: #6d28d9; }
.badge.hidden-status { background: #fff8e6; color: #92620a; }

/* Count cards (views/_count-cards.ejs) - the same as Club Volunteers', so
   the apps' admin pages read the same way. A plain .stat-card is just a
   fact; a.stat-link is a switch on the page's own filter, lit (.stat-on) in
   red through, its labels white, while that filter is what is set. */
.stat-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; margin-bottom: 20px; }
.stat-card { background: var(--card); border: 1px solid var(--border); border-top: 3px solid var(--primary); border-radius: 8px; padding: 12px 14px; display: flex; flex-direction: column; }
.stat-label { color: var(--muted); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em; font-weight: 600; line-height: 1.25; min-height: 2.5em; }
.stat-value { font-size: 1.6rem; font-weight: 700; margin-top: 4px; }
a.stat-link { color: inherit; text-decoration: none; cursor: pointer; }
a.stat-link:hover, a.stat-link:focus-visible { border-color: var(--primary); background: #fbf4f3; }
a.stat-on { background: var(--primary); color: #fff; border-color: var(--primary); }
a.stat-on:hover, a.stat-on:focus-visible { background: var(--primary); }
a.stat-on .stat-label { color: #fff; }

.muted { color: var(--muted); }
/* A team sheet's per-parent lines (see team-sheet.ejs) - never wrapped, so
   parent 2's name, mobile and email stay level with each other across the
   row's cells. */
.parent-lines div { white-space: nowrap; }
.code-input { letter-spacing: 0.4em; font-size: 1.3rem; text-align: center; }

.admin-season { margin-bottom: 18px; }
.admin-season summary { cursor: pointer; font-weight: 600; color: var(--primary); padding: 8px 0; }

/* A row's actions collapsed behind a single "..." toggle instead of a run
   of buttons - <details> so it needs no JS to open/close; the small script
   next to its markup only repositions the list as position:fixed once
   open, so it escapes a scrolling table's clipping instead of getting cut
   off (a plain position:absolute would be clipped by .table-scroll's
   overflow), and closes any other open menu so only one shows at a time. */
.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 (and hidden) from the very first frame it exists, not
     just once the script below repositions it - otherwise it briefly
     renders in normal flow inside the table cell (widening the row) before
     JS can move it out, which is exactly the glitch/jump this was for. */
  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;
}
.action-menu-list form { margin: 0; }
.action-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: 8px 10px;
  border-radius: 6px;
  font: inherit;
  font-size: 0.88rem;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
}
.action-menu-item:hover { background: var(--bg); }
.action-menu-item.danger { color: var(--danger); }

.people-toolbar { display: flex; gap: 10px; margin-bottom: 16px; }
.people-toolbar input, .people-toolbar select { margin-bottom: 0; }

.fixtures-table { max-width: 620px; margin: 0 auto; border: 1px solid var(--border); }
.fixtures-table td { padding: 9px 14px; border-bottom: 1px solid var(--border); }
.fixtures-table tr:last-child td { border-bottom: none; }
.fixtures-table td:last-child { text-align: right; }
/* writing-mode + rowspan is inconsistently supported by print/PDF
   rendering engines (the year text can vanish in a printed/saved PDF while
   still showing fine on screen) - a plain 2D rotate on an inline-block
   span, independent of the cell's own text flow, renders reliably in
   both. */
.fixtures-year {
  text-align: center;
  vertical-align: middle;
  border-right: 1px solid var(--border);
  width: 1px;
  white-space: nowrap;
  position: relative;
}
.fixtures-year span {
  display: inline-block;
  transform: rotate(-90deg);
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--primary);
  white-space: nowrap;
}

.impersonation-banner {
  background: var(--gold);
  color: #1c2430;
  padding: 8px 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  font-size: 0.9rem;
  font-weight: 600;
}
.impersonation-banner form { margin: 0; }
.impersonation-banner button.quiet { color: inherit; }

.sheet-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; flex-wrap: wrap; }
/* The sheet's own buttons (Print, Email All, the vCard, the calendar, the
   scoring roster) wrap a row at a time on a phone's narrow card; a little
   room under each keeps the rows from touching. */
.sheet-top-name > button, .sheet-top-name > .btn { margin-bottom: 6px; }
.sheet-top-right { display: flex; flex-direction: column; align-items: flex-end; gap: 12px; }
.team-name { text-transform: uppercase; font-style: italic; }

.training-box { width: auto; min-width: 320px; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; margin-top: 0; }
.training-box thead tr th[colspan] { background: var(--primary); color: #fff; text-align: left; padding: 8px 12px; text-transform: none; font-size: 0.85rem; letter-spacing: 0; }
.training-box tbody tr:first-child th { background: #eef1f6; }
.training-box th, .training-box td { border-bottom: none; padding: 8px 12px; }

.training-form { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; margin-top: 10px; }
.training-form > div { flex: 1; min-width: 140px; }
.training-form input { margin-bottom: 0; }
.training-form button { height: 41px; }

.filter-grid { display: grid; grid-template-columns: repeat(4, minmax(140px, 1fr)); gap: 12px 16px; margin-top: 10px; }
.filter-grid label { margin-bottom: 4px; }
.filter-grid input, .filter-grid select { margin-bottom: 0; }
.filter-grid-actions { display: flex; gap: 10px; margin-top: 16px; }
@media (max-width: 640px) {
  .filter-grid { grid-template-columns: repeat(2, 1fr); }

  .nav-toggle-btn { display: block; }
  header.topbar nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
    padding: 16px 24px;
    background: var(--primary);
    border-bottom: 3px solid var(--gold);
    z-index: 20;
  }
  .nav-toggle:checked ~ nav { display: flex; }
}

.table-scroll { overflow-x: auto; }
.table-scroll table { min-width: 640px; }

/* No forced size here on purpose - it used to say `size: landscape`
   unconditionally, which only the wide team sheet table actually needs. Every
   other printed page (Scoring Roster, Season Fixtures) is a narrow, tall
   table that's naturally portrait-shaped, and browsers don't agree on what to
   do when the CSS demands landscape for content like that: some rotate it
   onto whatever paper the print dialog has, some ignore the hint and fall
   back to the printer's own default. Same page, different browsers, visibly
   different (and for one of them, sideways) results. The team sheet's own
   print button adds `size: landscape` just for that print instead - see
   logPrintThenPrint in team-sheet.ejs. */
@page {
  margin: 1.2cm;
}

.print-logo { display: none; }
.print-only { display: none; }

@media print {
  header.topbar, .no-print { display: none !important; }
  .print-only { display: inline; }
  body { background: #fff; }
  main { max-width: 100%; padding: 0; }
  .card { border: none; box-shadow: none; padding: 0; margin-bottom: 20px; }
  /* On screen, .sheet-top-right stacks the training box above the (hidden)
     logo in a right-hand column next to the team name. For print, the logo
     becomes visible and the training box needs to sit centered between the
     name and the logo on one row instead - `display: contents` un-nests
     .sheet-top-right so its children become direct grid items of
     .sheet-top, which a 1fr/auto/1fr grid then lays out as name (left),
     training (centered) and logo (right). */
  .sheet-top { break-inside: avoid; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 16px; }
  .sheet-top-name { grid-column: 1; }
  .sheet-top-right { display: contents; }
  .training-box { grid-column: 2; justify-self: center; margin: 0; }
  .print-logo { grid-column: 3; justify-self: end; display: block; height: 3cm; width: auto; }
  .table-scroll { overflow-x: visible; }
  .table-scroll table { min-width: 0; }
  a { color: inherit; text-decoration: none; }

  table { break-inside: auto; }
  tr { break-inside: avoid; break-after: auto; }
  thead { display: table-header-row-group; }
  h1, h2 { break-after: avoid; }

  /* The Players table can legitimately span pages (large squads), but Staff
     is only ever a handful of rows - keep it as one unbroken block, pushed
     to the next page whole rather than split, if it doesn't fit under the
     Players table on the first page. */
  .staff-card { break-inside: avoid; }
}

.club-message-dialog { width: min(480px, 92vw); max-width: none; }
.club-message-dialog select, .club-message-dialog textarea { width: 100%; box-sizing: border-box; }

/* Help Desk: a member's tickets and the conversation on one. The club's
   messages sit on the left in the club's colours, the member's own on the
   right, so it reads as a back-and-forth. */
.help-textarea { width: 100%; padding: 10px 12px; border: 1px solid var(--border); border-radius: 6px; font: inherit; font-size: 1rem; margin-bottom: 12px; background: var(--card); color: var(--text); }
.help-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
.help-list { list-style: none; padding: 0; margin: 0; }
.help-list li { border-bottom: 1px solid var(--border); }
.help-list li:last-child { border-bottom: none; }
.help-list-link { display: block; padding: 12px 0; color: inherit; text-decoration: none; }
.help-list-link:hover strong { color: var(--primary); text-decoration: underline; }
.help-list-top { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; font-size: 0.92rem; }
.help-when { margin-left: auto; font-size: 0.85rem; }
.help-list-desc { margin-top: 4px; font-size: 0.9rem; overflow-wrap: anywhere; }
.badge.help-status.new { background: #eaf2ff; color: #1d4ed8; }
.badge.help-status.open { background: #fff1e0; color: #b45309; }
.badge.help-status.closed { background: #eef1f6; color: var(--muted); }
/* A refund's status, from the Help Desk. */
.badge.refund-status { background: #eef1f6; color: var(--muted); }
.badge.refund-status.approved { background: #e7f6ec; color: #15803d; }
.badge.refund-status.paid { background: #e7f6ec; color: #15803d; }
.badge.refund-status.denied { background: #fdecec; color: #b91c1c; }
.badge.refund-status.submitted { background: #eaf2ff; color: #1d4ed8; }
.help-refund { border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; margin: 12px 0; }
.help-refund .badge { margin-left: 6px; }
.badge.help-replied { background: var(--primary); color: #fff; }
/* The help bot: Help > Ask a question, and Questions asked for the club. */
.help-bot { max-width: 760px; }
.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-bot-asked { padding: 12px 0; }
.help-bot-asked details { font-size: 0.9rem; }
.badge.help-bot-down { background: #fdecec; color: #b91c1c; }
.badge.help-bot-up { background: #e7f6ec; color: #15803d; }
.badge.help-bot-warn { background: #fff1e0; color: #b45309; }
.help-msg { max-width: 85%; margin: 0 0 12px; padding: 10px 14px; border-radius: 10px; border: 1px solid var(--border); }
.help-msg.club { background: #fff8e6; border-color: #f0dfa8; margin-right: auto; }
.help-msg.member { background: #eaf2ff; border-color: #c9dcff; margin-left: auto; }
.help-msg-meta { font-size: 0.78rem; color: var(--muted); margin-bottom: 4px; }
.help-msg-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; }
.help-reply { margin-top: 20px; }

/* The top bar's Help menu - the guides and the Help Desk under one name. The
   summary reads like the links beside it, with a caret; the menu opens as a
   card below it, from the right so it stays on screen. Venue Hire's pattern. */
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,
header.topbar details.nav-menu summary.active { opacity: 1; }
header.topbar .nav-menu-items {
  position: absolute; top: calc(100% + 12px); right: -12px; z-index: 30; min-width: 230px;
  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);
}
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 span { display: block; color: var(--muted); font-size: 0.78rem; font-weight: 400; }
/* In the collapsed phone menu, it 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 { background: transparent; }
  header.topbar .nav-menu-items a span { color: rgba(255, 255, 255, 0.7); }
}

/* 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;
}

/* "Request Refund" sits in a card heading and in the team sheet's button row -
   in a heading it must not take the heading's size. */
h2 > .btn { font-size: 0.8rem; padding: 5px 12px; margin-left: 10px; vertical-align: middle; }

/* The club's banner across the top of My Team Sheets (banner.js, _banner.ejs):
   a headline, a line and a link, with a × that puts it away on this device.
   The × is only shown once the page's script has marked the banner, so with
   scripts off there is no button that does nothing. */
.site-banner {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  background: #fff8e6;
  border: 1px solid #f0dfa8;
  border-left: 5px solid var(--gold);
  border-radius: 8px;
  padding: 14px 18px;
  margin: 0 0 24px;
}
.site-banner[hidden] { display: none; }
.site-banner-text { flex: 1; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.site-banner-headline { font-size: 1.05rem; }
.site-banner-line { font-size: 0.95rem; }
.site-banner-link { font-weight: 600; }
/* A quiet button, but drawn as a bare x: scoped to the banner so it
   outweighs button.quiet's underline and inherited font. */
.site-banner .site-banner-close {
  display: none;
  background: none;
  border: 0;
  padding: 0 4px;
  margin: -4px -6px 0 0;
  color: var(--muted);
  font-size: 1.6rem;
  line-height: 1;
  text-decoration: none;
}
.site-banner.has-script .site-banner-close { display: block; }
.site-banner .site-banner-close:hover { color: var(--text); opacity: 1; }
.site-banner-preview { margin-top: 4px; }

/* Admin > Banner's choices: a radio with its words beside it, and the
   write-your-own boxes indented under their radio. */
fieldset.choices { border: 1px solid var(--border); border-radius: 8px; padding: 12px 16px 4px; margin: 0 0 20px; }
fieldset.choices legend { font-weight: 600; font-size: 0.85rem; padding: 0 6px; }
.choice { display: flex; align-items: flex-start; gap: 10px; font-weight: 400; font-size: 0.95rem; margin-bottom: 10px; }
.choice input[type="radio"] { margin: 3px 0 0; flex: none; }
.choice-block { padding: 8px 0; }
.choice-fields { margin: 0 0 12px 28px; }

/* The filters every list page shares (Jira JPI-3, ported from Club
   Volunteers; views/_filters.ejs, 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. */
.filters { padding: 14px 20px; }
.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%; }
.filters-search noscript { display: flex; }
.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; 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; }
.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; }
.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; }
.filters-group .tick input { margin: 3px 0 0; flex: none; }
/* A long list of ticks (Activity's kinds of event) scrolls inside itself. */
.filters-group .filters-ticks { max-height: 260px; overflow-y: auto; }
.filters-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.stat-note { text-transform: none; letter-spacing: 0; font-weight: 400; margin-top: 2px; }
.stat-card > .stat-label.stat-note { min-height: 0; }
/* While the server is asked again for a search, the list fades a little. */
[data-swap].swapping { opacity: 0.55; transition: opacity 0.15s; }
/* A download link the search took away (no teams left to export). */
.btn[hidden] { display: none; }
@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; }
}

/* The x that empties a search box (public/search-clear.js, ported from Club
   Volunteers): 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); }
/* Shown once something is typed - a button's own display would otherwise
   win over the hidden attribute. */
.search-clear[hidden] { display: none; }
/* A bigger target than it looks, for a thumb. */
.search-clear::before { content: ''; position: absolute; inset: -10px; }
