:root {
  --navy: #123a6b;
  --navy-dark: #0d2a4d;
  --navy-light: #1d4f8c;
  /* The navy at a whisper: table headings, menu hovers, the top of the page. */
  --navy-tint: #e8eef7;
  --accent: #f0b429;
  --ink: #1a2230;
  --muted: #5d6b7f;
  --line: #dfe4ec;
  --bg: #f3f5f9;
  --panel: #ffffff;
  --good: #12805c;
  --good-bg: #e6f6f0;
  --bad: #c0392b;
  --bad-bg: #fdecea;
  --warn: #8a6100;
  --warn-bg: #fff6e0;
  --radius: 12px;
  --shadow: 0 1px 2px rgba(16, 32, 56, .05), 0 6px 18px rgba(16, 32, 56, .06);

  /* Two faces. The body is the system's own sans, which every device has and
     renders best. Headings, the brand and anything quoted are a serif — the
     club's pages should read like an almanack, not an admin panel — from a
     stack that is on every Mac, Windows and Android device without a font
     file to download. Nothing on the page ever waits for a font. */
  --font-body: "Segoe UI", system-ui, -apple-system, Roboto, Helvetica, Arial, sans-serif;
  --font-display: "Palatino Linotype", Palatino, "Book Antiqua", "Iowan Old Style",
                  Georgia, "Noto Serif", "Times New Roman", serif;
}

* { box-sizing: border-box; }

html { height: 100%; }

body {
  margin: 0;
  /* Column, so the footer sits at the foot of a short page rather than a
     third of the way down it with grey underneath. */
  min-height: 100%; display: flex; flex-direction: column;
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.55;
  color: var(--ink);
  background-color: var(--bg);
  /* A little light behind the top of every page, so the bar sits on
     something rather than on a flat grey. */
  background-image: linear-gradient(180deg, #e7ecf5 0, var(--bg) 300px);
  background-repeat: no-repeat;
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--accent); color: var(--navy-dark); }

a { color: var(--navy-light); text-underline-offset: 2px; }
a:hover { color: var(--navy); }

/* Off-screen until it is focused, which is the only time it is any use. */
.skip-link {
  position: absolute; left: .5rem; top: -3rem; z-index: 100;
  padding: .5rem .85rem; background: var(--panel); color: var(--navy);
  font-weight: 600; text-decoration: none;
  border-radius: 0 0 7px 7px; box-shadow: var(--shadow);
}
.skip-link:focus { top: 0; }
/* main takes focus when the skip link is followed, but it is not a control
   and should never show a focus ring for it. */
main:focus { outline: none; }

h1, h2, h3 { line-height: 1.2; margin: 0 0 .5rem; }
h1, h2 { font-family: var(--font-display); font-weight: 700; }
h1 { font-size: 2.1rem; letter-spacing: -.01em; }
h2 { font-size: 1.35rem; }
h3 { font-size: 1.05rem; }
@media (max-width: 640px) {
  h1 { font-size: 1.7rem; }
}

.wrap { max-width: 1120px; margin: 0 auto; padding: 0 1rem; }

/* ---------- nav ---------- */
/* The club's colours as a band: navy, with the gold as a stripe along the
   bottom edge, which is how a cap or a blazer wears them. */
.nav {
  background: linear-gradient(180deg, #17447c 0%, var(--navy) 100%);
  color: #fff;
  border-bottom: 3px solid var(--accent);
  box-shadow: 0 2px 10px rgba(6, 20, 40, .18);
}
.nav a { color: #dce6f4; text-decoration: none; }
.nav a:hover { color: #fff; }
.nav-inner {
  display: flex; align-items: center; gap: 1rem;
  min-height: 58px; flex-wrap: wrap;
}
.brand {
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: var(--font-display); font-weight: 700; font-size: 1.12rem;
  color: #fff !important; margin-right: auto; white-space: nowrap;
}
.brand-text span { color: var(--accent); }
/* The same P as the favicon, so the tab and the bar agree. */
.brand-mark { width: 26px; height: 26px; flex: none; border-radius: 6px; box-shadow: 0 1px 3px rgba(0, 0, 0, .3); }
.nav-links { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; }
/* Pinned in pixels rather than rem: the bar has to fit its widest set of
   links in one row above the 960px fold, whatever the body size does. */
.nav-links a { padding: .35rem 0; font-size: 14px; }
.nav-links a.active,
.nav-group > summary.active { color: #fff; box-shadow: inset 0 -2px 0 var(--accent); }
.nav form { margin: 0; }

/* A group of nav links under one heading, built on <details>. The summary is
   the tab; the menu is what drops out of it. */
.nav-group { position: relative; }
.nav-group > summary {
  padding: .35rem 0; font-size: 14px; color: #dce6f4;
  cursor: pointer; user-select: none;
  /* Both are needed to lose the default disclosure triangle: the standard
     property, and the one Safari still wants. */
  list-style: none;
}
.nav-group > summary::-webkit-details-marker { display: none; }
.nav-group > summary::after {
  content: "";
  display: inline-block; margin-left: .34rem; vertical-align: .12em;
  border: .28rem solid transparent; border-top-color: currentColor;
  /* The triangle is drawn from borders, so it sits half a border too low. */
  transform: translateY(.14rem);
}
.nav-group[open] > summary::after { transform: translateY(-.14rem) rotate(180deg); }
.nav-group > summary:hover, .nav-group[open] > summary { color: #fff; }
.nav-group > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.nav-menu {
  position: absolute; top: 100%; left: -.85rem; z-index: 40;
  display: flex; flex-direction: column; gap: .1rem;
  min-width: 11rem; padding: .5rem .85rem .6rem;
  background: var(--navy-light); border-radius: 0 0 10px 10px;
  border-top: 2px solid var(--accent);
  box-shadow: 0 8px 22px rgba(6, 20, 40, .35);
}
.nav-menu a { padding: .4rem 0; white-space: nowrap; font-size: 14px; }
.nav-user {
  display: flex; align-items: center; gap: .55rem;
  padding-left: 1rem; border-left: 1px solid rgba(255,255,255,.18);
}
/* `.nav a` colours every link in the bar for the navy; a white button in
   it needs its own text colour back or the label vanishes into the button. */
.nav .btn-light { color: var(--navy); }
.nav .btn-light:hover { color: var(--navy-dark); }
.avatar {
  width: 30px; height: 30px; border-radius: 50%; object-fit: cover;
  background: var(--navy-light); color: #fff; display: grid; place-items: center;
  font-size: .78rem; font-weight: 600; flex: none;
}
.nav-toggle {
  display: none; background: none; border: 0; color: #fff;
  font-size: 1.4rem; cursor: pointer; padding: .2rem .4rem;
}

/* The bar needs just under 1000px to lay out in one row for a manager, who
   sees the most links — measured, not guessed: brand, links and the user
   block plus the gaps between them. Below that the menu button takes over.
   The fold has to sit above what the bar needs, or there is a band of widths
   where neither happens and the bar quietly sits on two rows, which is what
   a 1024px screen got when the fold was at 960. */
@media (max-width: 1040px) {
  .nav-toggle { display: block; }
  .nav-links, .nav-user { display: none; width: 100%; }
  .nav-links { flex-direction: column; align-items: flex-start; gap: .2rem; padding-bottom: .6rem; }
  .nav-links a { padding: .5rem 0; width: 100%; }

  /* No room to float a menu over a column of links, so the group just opens
     in place and the rule down the left says what belongs to it. */
  .nav-group { width: 100%; }
  .nav-menu {
    position: static; min-width: 0; padding: 0 0 .25rem .85rem;
    background: none; border-radius: 0; box-shadow: none; border-top: 0;
    border-left: 1px solid rgba(255, 255, 255, .22);
  }
  .nav-user { padding: .6rem 0 .8rem; border-left: 0; border-top: 1px solid rgba(255,255,255,.18); }

  /* Stacked, an underline would read as a rule between two links, so the
     mark moves to the side. The padding goes on every link, not just the
     current one, so nothing shifts as you move between pages. */
  .nav-links > a, .nav-group > summary { padding-left: .6rem; }
  .nav-links > a.active, .nav-group > summary.active {
    box-shadow: inset 3px 0 0 var(--accent);
  }
  .nav.open .nav-links, .nav.open .nav-user { display: flex; }
}

/* ---------- layout ---------- */
/* Grows to push the footer down; the width comes from .wrap. */
main { flex: 1 0 auto; width: 100%; padding: 2rem 1rem 3rem; }

.card {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 1.35rem 1.4rem; margin-bottom: 1.25rem;
}
.card > :last-child { margin-bottom: 0; }
/* A sub-heading part-way down a card starts a new section, and needs the
   room above it to say so. */
.card > h3 { margin-top: 1.25rem; }
.card > h3:first-child { margin-top: 0; }
/* A form does not need the whole page. One width for all of them, so the
   login, profile and feedback cards stop being three different shapes. */
.card.narrow { max-width: 34rem; }
/* A whole card that is a link: no underline, no link colour, but it lifts
   under the pointer so it still reads as something you can click. */
a.card {
  color: inherit; text-decoration: none; display: block;
  transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease;
}
a.card:hover {
  border-color: #b7c6dd; transform: translateY(-2px);
  box-shadow: 0 2px 4px rgba(16, 32, 56, .07), 0 12px 26px rgba(16, 32, 56, .11);
}
a.card:focus-visible { outline: 2px solid var(--navy-light); outline-offset: 2px; }
/* Someone who has asked their system to keep still gets the colour change
   and nothing that moves. */
@media (prefers-reduced-motion: reduce) {
  a.card { transition: none; }
  a.card:hover { transform: none; }
}

.card-head {
  display: flex; justify-content: space-between; align-items: center;
  gap: 1rem; flex-wrap: wrap; margin-bottom: .9rem;
}
.card-head h2, .card-head h1 { margin: 0; }

/* Every page opens the same way: the title, a short gold rule under it, and
   a line of muted copy. The rule is what makes the title a heading rather
   than the first line of the page. */
.page-head { margin-bottom: 1.5rem; }
.page-head h1::after {
  content: ""; display: block; width: 2.75rem; height: 4px;
  margin-top: .55rem; border-radius: 2px; background: var(--accent);
}
.page-head p { color: var(--muted); margin: .6rem 0 0; font-size: 1.05rem; max-width: 62ch; }

.grid { display: grid; gap: 1rem; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }

.muted { color: var(--muted); }
.small { font-size: .85rem; }
.right { text-align: right; }
.stack > * + * { margin-top: .75rem; }

/* ---------- forms ---------- */
label { display: block; font-weight: 600; font-size: .88rem; margin-bottom: .25rem; }
input[type=text], input[type=email], input[type=password], input[type=number],
input[type=date], select, textarea {
  width: 100%; padding: .5rem .6rem; font: inherit; color: var(--ink);
  background: #fff; border: 1px solid var(--line); border-radius: 7px;
}
/* A control as wide as the card is harder to use, not easier: the eye has to
   travel from the label to a value that may be most of a metre away, and a
   date is eight characters. Textareas are left out of this — they hold prose,
   which wants the room. Inside a grid the cell is already narrower, so this
   simply never binds. */
input[type=text], input[type=email], input[type=password], input[type=number],
input[type=date], select { max-width: 34rem; }
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--navy-light); outline-offset: -1px; border-color: var(--navy-light);
}
textarea { resize: vertical; }
.field { margin-bottom: .85rem; }
.field .helptext { display: block; font-size: .8rem; color: var(--muted); margin-top: .2rem; }
.check { display: flex; align-items: center; gap: .5rem; }
.check label { margin: 0; font-weight: 400; }
.check input { width: auto; }

.btn {
  display: inline-block; padding: .5rem 1rem; font: inherit; font-weight: 600;
  border: 1px solid transparent; border-radius: 8px; cursor: pointer;
  background: var(--navy); color: #fff; text-decoration: none;
  transition: background .12s ease, box-shadow .12s ease, transform .06s ease;
}
.btn:hover { background: var(--navy-dark); color: #fff; }
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.btn-light { background: #fff; color: var(--ink); border-color: var(--line); }
.btn-light:hover { background: #f2f5f9; color: var(--ink); border-color: #c6d2e4; }
/* The club's gold, for the one thing on a navy panel you are meant to press. */
.btn-gold { background: var(--accent); color: var(--navy-dark); }
.btn-gold:hover { background: #e3a81f; color: var(--navy-dark); }
/* An outline on a dark panel, for the second choice beside a gold one. */
.btn-ghost { background: transparent; color: #fff; border-color: rgba(255, 255, 255, .55); }
.btn-ghost:hover { background: rgba(255, 255, 255, .12); color: #fff; }
.btn-danger { background: var(--bad); }
.btn-danger:hover { background: #a5322a; }
.btn-success { background: var(--good); }
.btn-success:hover { background: #0e6649; }
.btn-info { background: var(--navy-light); }
.btn-info:hover { background: var(--navy); }
.btn-sm { padding: .28rem .6rem; font-size: .82rem; }
.btn-row { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }

.errors {
  background: var(--bad-bg); border: 1px solid #f5c6c2; color: var(--bad);
  border-radius: 7px; padding: .55rem .7rem; margin-bottom: .85rem;
  font-size: .87rem;
}
.errors ul { margin: 0; padding-left: 1.1rem; }
.field .errors { margin: .3rem 0 0; }

/* ---------- messages ---------- */
.messages { margin-bottom: 1.25rem; }
.msg {
  padding: .65rem .9rem; border-radius: 8px; margin-bottom: .5rem;
  border: 1px solid var(--line); border-left-width: 4px; border-left-color: var(--navy-light);
  background: var(--panel); font-size: .9rem; box-shadow: var(--shadow);
}
.msg.success { background: var(--good-bg); border-color: #b8e5d4; border-left-color: var(--good); color: var(--good); }
.msg.error { background: var(--bad-bg); border-color: #f5c6c2; border-left-color: var(--bad); color: var(--bad); }
.msg.warning { background: var(--warn-bg); border-color: #f2ddab; border-left-color: var(--accent); color: var(--warn); }

/* ---------- tables ---------- */
.table-scroll { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: .89rem; }
th, td { padding: .5rem .6rem; text-align: left; border-bottom: 1px solid var(--line); }
th {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--navy); background: var(--navy-tint); white-space: nowrap;
  border-bottom-color: #cfd9e8;
}
tbody tr:hover { background: #f5f7fb; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
/* A column of underlined names is a column of noise. The colour still says
   the name is a link; the underline comes back under the pointer. */
td a { text-decoration: none; }
td a:hover { text-decoration: underline; }
.zero { color: #b6c0ce; }
.total { font-weight: 700; }

/* A table with a column per fine category is wider than any screen, and the
   two columns that matter sit at opposite ends of it: whose row this is, and
   what they owe. Pinning the name means you can scroll out to the total and
   still know who you are looking at. The cells need their own background —
   without one, the scrolled cells show through. */
.table-sticky th:first-child,
.table-sticky td:first-child {
  position: sticky; left: 0; z-index: 1; background: var(--panel);
  /* A name on one line: the column is pinned so it can afford the width. */
  white-space: nowrap;
  /* Drawn rather than a border, so it does not move the column by a pixel. */
  box-shadow: 1px 0 0 var(--line);
}
.table-sticky thead th:first-child { background: var(--navy-tint); z-index: 2; }
.table-sticky tbody tr:hover td:first-child { background: #f5f7fb; }
/* A slimmer scrollbar under the table, so the one bit of chrome saying
   "there is more to the right" does not crowd the last row. */
.table-scroll { scrollbar-width: thin; }

/* ---------- pills ---------- */
.pill {
  display: inline-block; padding: .12rem .5rem; border-radius: 999px;
  font-size: .74rem; font-weight: 600; background: #eef2f7; color: var(--muted);
  white-space: nowrap;
}
.pill.good { background: var(--good-bg); color: var(--good); }
.pill.bad { background: var(--bad-bg); color: var(--bad); }
.pill.warn { background: var(--warn-bg); color: var(--warn); }
.pill.open { background: var(--good-bg); color: var(--good); }

/* ---------- quotes ---------- */
.quote { padding: .95rem 0; border-bottom: 1px solid var(--line); }
.quote:last-child { border-bottom: 0; }
.quote blockquote {
  margin: 0 0 .4rem; font-family: var(--font-display); font-style: italic;
  font-size: 1.15rem; line-height: 1.45;
  border-left: 3px solid var(--accent); padding-left: .8rem;
}
.quote .by { display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.quote .by cite { font-style: normal; font-weight: 600; }

/* ---------- goals ---------- */
.bar { height: 8px; background: #e8edf4; border-radius: 999px; overflow: hidden; }
.bar > span { display: block; height: 100%; background: var(--navy-light); }
.bar.done > span { background: var(--good); }
.goal-card { border-left: 3px solid var(--navy-light); }
.goal-card.done { border-left-color: var(--good); }
.goal-card.overdue { border-left-color: var(--bad); }

/* ---------- misc ---------- */
.empty {
  text-align: center; padding: 2rem 1rem; color: var(--muted);
  border: 1px dashed var(--line); border-radius: var(--radius);
}
.chart-box { position: relative; height: 340px; }
.tabs { display: flex; gap: .4rem; border-bottom: 1px solid var(--line); margin-bottom: 1rem; flex-wrap: wrap; }
.tabs button {
  background: none; border: 0; border-bottom: 2px solid transparent;
  padding: .5rem .75rem; font: inherit; font-weight: 600; font-size: .9rem;
  color: var(--muted); cursor: pointer;
}
.tabs button[aria-selected="true"] { color: var(--navy); border-bottom-color: var(--accent); }

dialog {
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1.25rem; max-width: 460px; width: calc(100% - 2rem);
  box-shadow: 0 12px 40px rgba(16,32,56,.22);
}
dialog::backdrop { background: rgba(16, 32, 56, .45); }

/* The bar again, in the dark navy, so the page is bound top and bottom in
   the same colours. */
footer {
  margin-top: 2rem; border-top: 3px solid var(--accent);
  background: var(--navy-dark); color: #b3c2d8;
  padding: 1.4rem 0; font-size: .85rem;
}
footer .wrap {
  display: flex; justify-content: space-between; align-items: center;
  gap: .4rem 1.5rem; flex-wrap: wrap;
}
footer a { color: #dce6f4; }
footer a:hover { color: #fff; }
.footer-brand { font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; color: #fff; }
.footer-links { display: flex; gap: 1rem; }

.htmx-request .htmx-hide { opacity: .5; }

/* ---------- manage page ---------- */
/* Keeps the up/down and open/close buttons on one line inside a table cell. */
form.inline { display: inline; }
.nowrap { white-space: nowrap; }

.comment-list { list-style: none; margin: 0; padding: 0; }
.comment-list li {
  border-left: 3px solid var(--accent); background: var(--panel);
  padding: .6rem .85rem; margin-bottom: .5rem; border-radius: 0 var(--radius) var(--radius) 0;
}
.comment-list li:last-child { margin-bottom: 0; }

/* ---------- match reports ---------- */
.avatar-lg { width: 52px; height: 52px; font-size: 1rem; }

.report-title { margin: 0 0 .4rem; }
.report-intro { font-size: 1.02rem; margin-bottom: 1.4rem; }

/* Across the full card a report runs to about 130 characters a line, which is
   roughly twice what the eye tracks comfortably: the sweep back to the left
   starts landing on the line it just read. Only the prose is capped — the
   headings, avatars and tables above still use the whole width. */
.report-intro, .report-section > p, .report-fine p { max-width: 68ch; }

.report-section { padding: 1rem 0; border-bottom: 1px solid var(--line); }
.report-section:last-of-type { border-bottom: 0; }
.report-section > p { margin: .6rem 0 0; }
.report-who { display: flex; align-items: center; gap: .8rem; }
.report-who h3 { margin: 0; }
.report-who p { margin: 0; }

.report-fines-head { margin-top: 1.6rem; }
.report-fine {
  display: flex; align-items: flex-start; gap: .8rem;
  padding: .8rem 0; border-bottom: 1px solid var(--line);
}
.report-fine:last-child { border-bottom: 0; }
.report-fine p { margin: .35rem 0 0; }
.report-fine .pill { margin-left: .5rem; }

.report-player { display: inline-flex; align-items: center; gap: .5rem; }
.report-player .avatar-lg { width: 30px; height: 30px; font-size: .78rem; }

.section-edit { margin-top: .6rem; }
.section-edit summary {
  cursor: pointer; font-size: .8rem; color: var(--muted); font-weight: 600;
}
.section-edit form { margin-top: .5rem; }

.run-detail { padding: 0; background: #f7f9fc; }
.run-detail:empty { display: none; }
table.runs { font-size: .82rem; }
table.runs th { background: #eef2f7; }
.header-edit { margin: 0 0 1.2rem; }
.header-edit input, .header-edit textarea { width: 100%; max-width: 46rem; }

.player-picker > div { display: flex; flex-wrap: wrap; gap: .3rem .9rem; margin: .5rem 0 .8rem; }
.player-picker > div > div { flex: 0 0 auto; min-width: 11rem; }
.player-picker label { font-weight: 400; display: inline-flex; align-items: center; gap: .35rem; }
/* The field's own label, as opposed to the sixteen player labels inside it. */
.player-picker > label { display: block; font-weight: 600; margin-bottom: .1rem; }

.fines-date { margin-top: .9rem; padding-top: .8rem; border-top: 1px solid var(--line); }
.fines-date label { font-size: .85rem; color: var(--muted); }

.report-section h3 .rank { color: var(--muted); font-weight: 600; margin-right: .15rem; }

/* --- The batting game ---------------------------------------------------- */

.reward-head { margin: 1.6rem 0 .6rem; }
.reward-head h2, .reward-head h3 { margin: 0; }

.game-card .card-head { margin-bottom: .6rem; }

/* The Ruffle player is sized by the box, not the other way round: the SWF's
   stage is 590 x 384, and the aspect ratio here keeps the card from jumping
   while 14 MB of emulator is still on its way. */
.pitch-wrap { position: relative; }
.pitch-wrap ruffle-player {
  /* Ruffle's own stylesheet gives the element a fixed height, which would
     beat the aspect ratio; `auto` hands the decision back. */
  display: block; width: 100%; height: auto; aspect-ratio: 590 / 384;
  border-radius: var(--radius); border: 1px solid var(--line);
  background: #eef2f7; overflow: hidden;
}

.game-hint { margin: .6rem 0 0; }
#innings-note { margin-top: .6rem; }

/* Your own row on the leaderboard. */
tr.mine td { background: var(--warn-bg); }

/* Everybody on the roster gets a row, so the ones who haven't batted step
   back a little. Not so far that a name is hard to find — the point of
   listing them is that they can see themselves on it. Your own row keeps its
   highlight either way, which is why this sets colour and not background. */
tr.unplayed td { color: var(--muted); }
tr.unplayed td:nth-child(2) { color: inherit; }

/* --- PlayHQ scorecards ----------------------------------------------- */
.innings.collapsed { opacity: .8; }
.innings .card-head { flex-wrap: wrap; gap: .3rem 1rem; }
.innings-pick { display: inline-flex; align-items: center; gap: .5rem; font-weight: 600; cursor: pointer; }
.innings-pick input { width: auto; }
.used-by { color: var(--warn); }
table.scorecard { font-size: .85rem; }
table.scorecard td { padding: .3rem .4rem; }
table.scorecard input[type=text] { width: auto; padding: .25rem .4rem; font-size: .85rem; }
table.scorecard tr.sub td { background: #f7f9fc; }
table.scorecard tr.total td { font-weight: 600; }
table.scorecard tr.notout td:first-child { font-weight: 600; }
.extra { display: inline-flex; align-items: center; gap: .25rem; margin-right: .6rem; font-size: .8rem; color: var(--muted); }
.fow { color: var(--muted); font-size: .85rem; margin: .4rem 0 0; }
.reconcile { color: var(--warn); font-size: .85rem; margin: .5rem 0 0; }
.alias-row { display: flex; flex-wrap: wrap; gap: .4rem 1.2rem; align-items: center; margin-top: .6rem; }
.alias-row select { width: auto; padding: .25rem .4rem; font-size: .85rem; }
.scorecard-view h4 { margin: 1rem 0 .3rem; font-size: .95rem; }
/* The global label rule makes every label a bold block; these sit inline. */
.extra, .alias-row label { font-weight: 400; margin: 0; }
.alias-row label { display: inline-flex; align-items: center; gap: .3rem; }
.caveat { background: var(--warn-bg); border: 1px solid #f2ddab; color: var(--warn); border-radius: 7px; padding: .55rem .7rem; font-size: .87rem; }
/* Other people's notes on a player, beside your own box. */
.other-notes { margin: .4rem 0 0; font-size: .82rem; }
.other-notes > summary {
  cursor: pointer; color: var(--muted); font-weight: 600;
  /* Closed, this line is the only sign anyone else has written, so it needs
     to look like something you can open rather than a caption. */
  display: list-item; list-style-position: inside;
}
.other-notes > summary:hover { color: var(--navy-light); }
.other-notes[open] > summary { margin-bottom: .25rem; }
.other-notes ul { list-style: none; margin: 0; padding: 0 0 0 .9rem; }
.other-notes li { color: var(--muted); margin-bottom: .2rem; }
.other-notes .who { font-weight: 600; color: var(--ink); }
.other-notes .who::after { content: ":"; }

.signup-prompt { margin-top: 1rem; }

/* --- the gusto committee's mark -------------------------------------- */
/* Shown at half its pixel width, which is what keeps it crisp on a 2x
   screen — see templates/_gusto_mark.html. */
.gusto-mark { width: 160px; height: auto; flex: none; }

/* A page heading with the mark out to its right, using space the heading was
   leaving empty. Wraps underneath on a narrow screen rather than shrinking
   the title to make room. */
.page-head-mark {
  display: flex; align-items: center; justify-content: space-between;
  gap: .5rem 1.5rem; flex-wrap: wrap;
}
.page-head-mark > div { flex: 1 1 18rem; }

/* On a report it is a masthead, not an ornament: centred over the title with
   a rule under it, the way the thing is actually published. */
.report-masthead {
  text-align: center; padding-bottom: .9rem; margin-bottom: 1.1rem;
  border-bottom: 1px solid var(--line);
}

/* --- the front page ---------------------------------------------------- */
/* The voting prompt. The accent edge is the only one on the page, which is
   what makes it read as the thing to deal with first. */
.callout { border-left: 4px solid var(--accent); }
.callout .card-head { margin-bottom: .4rem; }

/* A panel that is a link and carries a number. Its heading is a small
   caption rather than a heading, because the number under it is the thing
   being read — the grid already stretches the tiles in a row to a common
   height. */
.tile h2 {
  font-family: var(--font-body); font-size: .78rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em; color: var(--muted);
  margin-bottom: .55rem;
}

.tile-figure {
  font-family: var(--font-display); font-size: 2.5rem; font-weight: 700;
  color: var(--navy); line-height: 1.1;
  margin: .1rem 0 .3rem; font-variant-numeric: tabular-nums lining-nums;
}
.tile-lead { font-family: var(--font-display); font-size: 1.25rem; font-weight: 700; margin: .1rem 0 .2rem; }

.tile-rank { list-style: none; margin: .2rem 0 0; padding: 0; counter-reset: rank; }
.tile-rank li {
  display: flex; align-items: baseline; gap: .5rem;
  padding: .22rem 0; border-bottom: 1px solid var(--line);
}
.tile-rank li:last-child { border-bottom: 0; }
/* The medal colours the awards use, so first place looks the same everywhere
   on the site. Fourth place onwards never renders — the panel stops at three. */
.tile-rank li::before {
  counter-increment: rank; content: counter(rank);
  flex: none; width: 1.35rem; height: 1.35rem; border-radius: 50%;
  display: grid; place-items: center;
  font-size: .72rem; font-weight: 700; color: #5a4708; background: #e8edf4;
}
.tile-rank li:nth-child(1)::before { background: #f2d675; }
.tile-rank li:nth-child(2)::before { background: #dfe4ec; }
.tile-rank li:nth-child(3)::before { background: #e6c39a; }
.tile-rank-name { flex: 1; font-weight: 600; }
.tile-rank-pts { font-weight: 700; font-variant-numeric: tabular-nums; }

.tile-quote {
  margin: .2rem 0 .35rem; font-family: var(--font-display); font-style: italic;
  font-size: 1.15rem; line-height: 1.4;
  border-left: 3px solid var(--accent); padding-left: .7rem;
}

/* The front page for anyone not signed in. The one dark panel on the site:
   the club's colours as a welcome, with the two things they can do on it.
   The glow in the corner is the gold, faintly, so the panel is not a flat
   slab. */
.hero {
  position: relative; overflow: hidden; isolation: isolate;
  padding: 2.2rem 2rem; max-width: 46rem;
  border-radius: var(--radius); box-shadow: 0 10px 30px rgba(6, 20, 40, .22);
  background: linear-gradient(135deg, var(--navy-dark) 0%, var(--navy) 60%, #1f5aa0 100%);
  color: #dbe5f3;
}
.hero::after {
  content: ""; position: absolute; z-index: -1; right: -90px; top: -110px;
  width: 300px; height: 300px; border-radius: 50%;
  background: radial-gradient(circle, rgba(240, 180, 41, .3), transparent 66%);
}
.hero-hat {
  margin: 0 0 .3rem; font-size: .78rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--accent);
}
.hero h2 { color: #fff; font-size: 1.8rem; margin: 0 0 .55rem; max-width: 24ch; }
.hero p { margin: 0 0 1.3rem; max-width: 46ch; font-size: 1.05rem; }
.hero .btn-row { margin: 0; }
@media (max-width: 640px) {
  .hero { padding: 1.6rem 1.25rem; }
  .hero h2 { font-size: 1.5rem; }
}

/* Log in and sign up: one card, centred, with the title over it. */
.auth { max-width: 34rem; margin: 1rem auto 0; }
.auth .page-head { text-align: center; }
.auth .page-head h1::after { margin-left: auto; margin-right: auto; }
.auth .card.narrow { max-width: none; }

/* --- profile ----------------------------------------------------------- */
.profile-photo {
  width: 96px; height: 96px; border-radius: 50%;
  object-fit: cover; margin-bottom: 1rem;
}

/* --- awards ----------------------------------------------------------- */
/* A rosette: metal disc over two ribbon tails. The four colours come in as
   custom properties from the category, so the shape is written once. */
.award-wall { display: flex; flex-wrap: wrap; gap: 1.1rem .9rem; }
.award-badge { width: 104px; text-align: center; }
.award-medal-wrap { position: relative; width: 68px; height: 100px; margin: 0 auto .35rem; }
.award-ribbon {
  /* Starts well up behind the disc so the visible tail is long enough to
     read as a ribbon rather than a leg. */
  position: absolute; top: 30px; width: 19px; height: 66px;
  background: linear-gradient(100deg,
              var(--medal-ribbon, var(--navy)) 55%, var(--medal-shade, #0d2a4d));
  /* The notch at the bottom is what makes it read as a ribbon end. */
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 76%, 0 100%);
}
.award-ribbon.left { left: 10px; transform: rotate(-14deg); transform-origin: top center; }
.award-ribbon.right { right: 10px; transform: rotate(14deg); transform-origin: top center; }
.award-medal {
  position: absolute; top: 0; left: 0; width: 68px; height: 68px; border-radius: 50%;
  display: grid; place-items: center;
  background:
    radial-gradient(circle at 34% 28%, var(--medal-light, #f7e3a1), var(--medal, #d9a827) 58%,
                    var(--medal-shade, #9a6f0d) 100%);
  box-shadow:
    inset 0 0 0 3px rgba(255, 255, 255, .38),
    inset 0 -5px 10px rgba(0, 0, 0, .22),
    0 2px 7px rgba(16, 32, 56, .3);
  color: var(--medal-text, #fff);
  text-shadow: var(--medal-glow, 0 1px 2px rgba(0, 0, 0, .4));
}
.award-medal-year { font-weight: 700; font-size: .95rem; letter-spacing: .01em; }
.award-badge-name {
  display: block; font-size: .78rem; font-weight: 600; line-height: 1.25;
  color: var(--ink);
}
.award-badge-sub { display: block; font-size: .74rem; color: var(--muted); }

/* A smaller one for tables and lists, where the wall would be too much. */
.award-wall.small { gap: .8rem .6rem; }
.award-wall.small .award-badge { width: 78px; }
.award-wall.small .award-medal-wrap { width: 48px; height: 72px; }
.award-wall.small .award-medal { width: 48px; height: 48px; }
.award-wall.small .award-medal-year { font-size: .72rem; }
.award-wall.small .award-ribbon { top: 21px; width: 13px; height: 48px; }
.award-wall.small .award-ribbon.left { left: 7px; }
.award-wall.small .award-ribbon.right { right: 7px; }
.award-wall.small .award-badge-name { font-size: .7rem; }

/* --- game trophies ------------------------------------------------------ */
/* The same rosette as an award, marked as something that can be taken off
   you. A notch out of the disc rather than a different colour: the colour is
   already saying which trophy it is. */
.award-badge.trophy .award-medal {
  /* A thin ring inside the rim, so the disc reads as a token rather than a
     medal struck for one person. */
  box-shadow:
    inset 0 0 0 2px rgba(255, 255, 255, .5),
    inset 0 0 0 4px rgba(0, 0, 0, .12),
    inset 0 -5px 10px rgba(0, 0, 0, .22),
    0 2px 7px rgba(16, 32, 56, .3);
}
.award-badge.trophy .award-ribbon {
  /* Ribbons cut square instead of notched, so a trophy and an award are
     still told apart at a glance in greyscale or at badge size. */
  clip-path: polygon(0 0, 100% 0, 100% 88%, 50% 100%, 0 88%);
}

/* On a profile, under the award wall in the same card. */
.trophy-case { margin-top: 1.3rem; padding-top: 1.1rem; border-top: 1px solid var(--line); }
.trophy-case > .card-head { margin-bottom: .7rem; }
.trophy-case h3 { font-size: .95rem; margin: 0; }

/* On the awards page, a game at a time. */
.trophy-row { margin-bottom: 1.3rem; }
.trophy-row:last-child { margin-bottom: 0; }
.trophy-row > h3 {
  font-size: .95rem; margin: 0 0 .6rem; padding-bottom: .25rem;
  border-bottom: 2px solid var(--accent); display: inline-block;
}

/* The honour board: a year at a time. */
.honour-year { margin-bottom: 1.6rem; }
.honour-year:last-child { margin-bottom: 0; }
.honour-year > h3 {
  font-size: 1rem; margin: 0 0 .7rem; padding-bottom: .3rem;
  border-bottom: 2px solid var(--accent); display: inline-block;
}
.award-swatch {
  display: inline-block; width: 14px; height: 14px; border-radius: 50%;
  vertical-align: -2px; margin-right: .4rem;
  background: radial-gradient(circle at 34% 28%, var(--medal-light), var(--medal) 60%,
                              var(--medal-shade));
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .45);
}

/* --- Seasons: games, stats and profiles ---------------------------------- */

/* The games list. Two tables on one page, and the second one deliberately
   does not look clickable: there is no scorecard behind an unplayed game.

   The min-width is what makes it read on a phone. Without it the browser
   squeezes six columns into 375px and every cell wraps — "Ron Payne Reserve"
   over three lines, rows four deep. With it the table keeps a legible width
   and .table-scroll slides it sideways, which is how a scoreboard is read. */
table.games { min-width: 40rem; }
table.games td { vertical-align: top; }
table.games td .muted { white-space: nowrap; }
tr.upcoming td { color: var(--muted); }
tr.upcoming td:first-child { color: var(--ink); }

/* The W/L/D letter. A disc rather than a coloured word, so a column of them
   reads as a form guide at a glance and so colour is never the only signal —
   W, L and D say it too, for anyone who cannot tell green from red. */
.result {
  display: inline-block; min-width: 1.45rem; padding: .1rem 0;
  border-radius: 999px; text-align: center;
  font-size: .78rem; font-weight: 700; line-height: 1.35;
}
.result.won { background: var(--good-bg); color: var(--good); }
.result.lost { background: var(--bad-bg); color: var(--bad); }
.result.drew { background: #eef2f7; color: var(--muted); }
.result.abandoned { background: #eef2f7; color: var(--muted); }

.form-guide { display: flex; gap: .35rem; flex-wrap: wrap; margin: .2rem 0 0; }
.form-guide a { text-decoration: none; }
.form-guide a:hover .result { box-shadow: 0 0 0 2px var(--accent); }

/* The headline numbers above a stats table. Wraps to two rows on a phone
   rather than shrinking the figures to nothing. */
.stat-row {
  display: flex; flex-wrap: wrap; gap: .6rem 1.8rem;
  margin: .2rem 0 1rem;
}
.stat { min-width: 4.5rem; }
.stat-value {
  display: block; font-size: 1.6rem; font-weight: 700;
  line-height: 1.1; font-variant-numeric: tabular-nums;
}
.stat-label {
  display: block; font-size: .78rem; color: var(--muted);
  text-transform: uppercase; letter-spacing: .04em;
}

/* Leaderboards. Tighter than a default table because they are mostly digits,
   and the name column holds its width so the numbers line up down the page. */
table.stats { font-size: .86rem; }
table.stats td, table.stats th { padding: .4rem .55rem; }
table.stats td:first-child { min-width: 9rem; }
table.stats tbody tr:hover { background: #f7f9fc; }

/* The season filter, which is one control and should not look like a form. */
.season-picker { padding: .7rem .9rem; margin-bottom: 1rem; }
.season-picker label { font-weight: 600; margin-right: .4rem; }

.d-block { display: block; }
ul.plain { list-style: none; padding: 0; margin: 0 0 .8rem; }
ul.plain li { padding: .2rem 0; }

/* --- the LBW game ------------------------------------------------------- */
/* The Park on the home page is a door, and looks like nothing at all until
   it has been opened. Cursor stays default: a pointer would give it away. */
/* The committee's mark on the home page is a door, and looks like nothing at
   all until it has been opened. The cursor stays default: a pointer would
   give it away.

   Dragging and selection are off because repeated clicks on an image
   otherwise start a drag or leave it highlighted, which is what made the
   first version of this — three clicks on a word in the heading — fight the
   browser instead of counting. */
.mark-egg {
  user-select: none; -webkit-user-select: none;
  -webkit-user-drag: none;
}
.mark-egg.egg-found {
  filter: drop-shadow(0 0 10px var(--accent));
  transition: filter .25s ease;
}

/* 16:9 without a wrapper hack, and capped so a tall phone doesn't put the
   answer buttons below the fold — the ten seconds start whether or not you
   have scrolled. */
.u-stage {
  position: relative; width: 100%; aspect-ratio: 16 / 9;
  max-height: 52vh; margin: .8rem 0;
  background: #0b1a2e; border-radius: 10px; overflow: hidden;
}
.u-frame, .u-frame iframe, .u-video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  border: 0; display: block;
}
.u-video { object-fit: contain; background: #0b1a2e; }

/* Big enough to hit without looking, because you are watching the video and
   have ten seconds. Side by side on a phone, not stacked: a stacked pair puts
   Not out under the fold. */
.u-buttons { display: flex; gap: .7rem; margin-top: .8rem; }
.u-buttons .btn { flex: 1 1 0; min-height: 60px; font-size: 1.15rem; }
.u-out { background: #c0392b; }
.u-not-out { background: #18a06f; }
.btn-lg { min-height: 52px; font-size: 1.05rem; padding: .7rem 1.4rem; }

.u-clock-wrap {
  display: flex; align-items: baseline; gap: .4rem;
  justify-content: center; margin-top: .6rem;
}
.u-clock {
  font-size: 2.2rem; font-weight: 700; line-height: 1;
  font-variant-numeric: tabular-nums; color: var(--ink);
}
/* The last three seconds. Colour and weight rather than a flash, which at
   this size is unpleasant and, for some people, worse than unpleasant. */
.u-clock-wrap.urgent .u-clock { color: #c0392b; }

.u-reveal { margin-top: 1rem; padding-top: .9rem; border-top: 1px solid var(--line); }
.u-reveal h3 { margin: 0 0 .35rem; font-size: 1.05rem; }
.u-reveal p { margin: .2rem 0; }

.u-rules { margin: .4rem 0 1rem; padding-left: 1.1rem; }
.u-rules li { margin-bottom: .45rem; }
.u-total { font-size: 2rem; font-weight: 700; margin: .2rem 0 .8rem; }
.u-summary { margin: 0 0 .8rem; padding-left: 1.2rem; }
.u-summary li { margin-bottom: .3rem; }
.u-today { margin: .2rem 0 .8rem; padding-left: 1.2rem; }
.u-today li { margin-bottom: .25rem; }

.preview-buttons { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .7rem; }

@media (max-width: 480px) {
  .u-stage { max-height: 40vh; }
  .u-buttons .btn { min-height: 66px; }
  .u-clock { font-size: 2.6rem; }
}

/* --- the games room ------------------------------------------------------ */

/* The card that says a game has just been earned. Sits above the page you
   landed on, once, and is deliberately louder than a message: the accent bar
   and the size are what make it read as something happening rather than as
   another line of feedback. */
.unlocked {
  margin-bottom: 1.1rem; padding: 1.1rem 1.2rem;
  background: var(--panel); border: 1px solid var(--line);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.unlocked-hat {
  margin: 0 0 .15rem; font-size: .78rem; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--warn);
}
.unlocked h2 { margin: 0 0 .35rem; font-size: 1.25rem; }
.unlocked p { margin: 0 0 .6rem; }
.unlocked-links {
  display: flex; gap: .8rem; align-items: center; flex-wrap: wrap;
  margin-bottom: 0;
}

/* The riddle page. A riddle is set apart from the ordinary run of copy —
   italic, a touch larger, and indented behind a rule — so it reads as a
   clue to be puzzled over rather than as an instruction to be followed. A
   found door drops to muted, because it is no longer the point. */
.riddle {
  margin: .2rem 0 0; padding: .2rem 0 .2rem 1rem;
  border-left: 3px solid var(--accent);
  font-family: var(--font-display); font-size: 1.2rem; font-style: italic;
  line-height: 1.5;
}
.riddle-card.found h2 { color: var(--muted); }

/* --- the quizzes --------------------------------------------------------- */

.q-text { font-size: 1.15rem; font-weight: 600; margin: .5rem 0 1rem; }

/* One button per choice rather than radios and a submit: a quiz answer is a
   single decision, and making it two actions only invites half-submitted
   forms. Stacked, because four option texts side by side wrap into a mess on
   a phone. */
.q-choices { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
.btn-choice {
  width: 100%; text-align: left; padding: .8rem .9rem;
  background: #fff; color: var(--ink); border: 1px solid var(--line);
  font-size: 1rem; font-weight: 500;
}
.btn-choice:hover { background: #f2f5f9; border-color: var(--navy-light); }

.q-verdict { font-size: 1.1rem; font-weight: 700; margin: .3rem 0; }
.q-verdict.right { color: var(--good); }
.q-verdict.wrong { color: var(--bad); }

.q-total { font-size: 2rem; font-weight: 700; margin: .2rem 0 .8rem; }
.q-rules { margin: .4rem 0 1rem; padding-left: 1.1rem; }
.q-rules li { margin-bottom: .45rem; }
.q-summary { margin: 0 0 .8rem; padding-left: 1.2rem; }
.q-summary li { margin-bottom: .35rem; }

@media (max-width: 640px) {
  .btn-choice { padding: .9rem .8rem; }
}
