/* === RESET & VARIABLES === */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

/* Stops mobile Safari/Chrome resizing text on their own after an orientation change or
   when they judge a column too narrow. Left unset, that adjustment can drop a 16px field
   below the threshold that triggers iOS's zoom-on-focus (see the form-control rule at the
   end of this file). */
html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

:root {
    /* Light theme (default) — classic country club: cream + forest green */
    --accent:        #2f5d3f;
    --accent-hover:  #244a32;
    /* Solid fills that carry white text (buttons, close icons, selected chips). Kept apart
       from --accent because that token has to stay light enough to read as text on a dark
       page, which makes it too light to sit behind white — in dark mode --accent gives only
       3.31:1. These are tuned for white text instead. Light mode matches --accent exactly,
       so nothing changes here. */
    --btn-fill:       #2f5d3f;
    --btn-fill-hover: #244a32;
    --accent-active: #1f3f2a;
    --accent-dim:    rgba(47, 93, 63, 0.10);
    --accent-border: rgba(47, 93, 63, 0.30);
    --bg-page:       #f7f3ea;
    --bg-surface:    #efe8d8;
    --bg-card:       #ffffff;
    --footer-bg:     #ece3cf;
    --text-primary:  #262b22;
    /* Darkened from #6e6a5c, which measured 4.44:1 against the page-header band (#efe8d8)
       and so missed WCAG AA's 4.5 for normal text. Now clears it on every light surface:
       4.78 on the header band, 5.26 on the page, 5.83 on white cards. */
    --text-muted:    #696558;
    --text-dim:      rgba(38, 43, 34, 0.62);
    --text-faint:    rgba(38, 43, 34, 0.42);
    --border-subtle: rgba(38, 43, 34, 0.12);
    --overlay-faint: rgba(38, 43, 34, 0.035);
    --overlay-medium:rgba(38, 43, 34, 0.08);
    --overlay-strong:rgba(38, 43, 34, 0.15);
    --border-strong: rgba(38, 43, 34, 0.28);
    --surface-translucent: rgba(247, 243, 234, 0.94);
    --accent-shadow: rgba(47, 93, 63, 0.35);
    --accent-dim-strong: rgba(47, 93, 63, 0.22);
    --font-serif:    Georgia, 'Times New Roman', serif;
    --font-sans:     system-ui, -apple-system, 'Segoe UI', sans-serif;
}

[data-theme="dark"] {
    /* Dark theme — charcoal + forest green */
    --accent:        #5a9b6f;
    --accent-hover:  #72b888;
    --accent-active: #4a8a5e;
    /* Deeper than --accent so white text clears AA: 5.65:1 at rest, 4.92:1 on hover.
       Hover still lightens, matching the light theme's direction of travel. */
    --btn-fill:       #387349;
    --btn-fill-hover: #3f7d52;
    --accent-dim:    rgba(90, 155, 111, 0.14);
    --accent-border: rgba(90, 155, 111, 0.35);
    --bg-page:       #11150f;
    --bg-surface:    #171c15;
    --bg-card:       #1d231a;
    --footer-bg:     #0b0e09;
    --text-primary:  #eef0e8;
    --text-muted:    #97a092;
    --text-dim:      rgba(238, 240, 232, 0.68);
    --text-faint:    rgba(238, 240, 232, 0.48);
    --border-subtle: rgba(255, 255, 255, 0.07);
    --overlay-faint: rgba(255, 255, 255, 0.04);
    --overlay-medium:rgba(255, 255, 255, 0.12);
    --overlay-strong:rgba(255, 255, 255, 0.18);
    --border-strong: rgba(238, 240, 232, 0.28);
    --surface-translucent: rgba(17, 21, 15, 0.94);
    --accent-shadow: rgba(90, 155, 111, 0.35);
    --accent-dim-strong: rgba(90, 155, 111, 0.26);
}

html { scroll-behavior: smooth; }

[hidden] { display: none !important; }

body {
    background-color: var(--bg-page);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 16px;
    line-height: 1.6;
    overflow-x: hidden;
    transition: background-color 0.25s ease, color 0.25s ease;
}

/* Subtle background pattern */
body::before {
    content: '';
    position: fixed;
    inset: 0;
    background-image:
        url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23000000' fill-opacity='0.025'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/svg%3E");
    pointer-events: none;
    z-index: 0;
}

[data-theme="dark"] body::before {
    background-image:
        url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23ffffff' fill-opacity='0.025'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/svg%3E");
}

.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 24px;
}

h1, h2, h3, h4 {
    font-family: var(--font-serif);
    font-weight: 600;
    line-height: 1.2;
}

/* === NAVBAR === */
.navbar {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 1000;
    padding: 20px 0;
    transition: padding 0.3s ease;
}

.navbar::before {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--surface-translucent);
    -webkit-backdrop-filter: blur(16px);
    backdrop-filter: blur(16px);
    border-bottom: 1px solid var(--border-subtle);
    z-index: -1;
    pointer-events: none;
}

.navbar.scrolled {
    padding: 14px 0;
}

.nav-container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 24px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.nav-brand {
    display: flex;
    align-items: center;
    gap: 12px;
    text-decoration: none;
    color: inherit;
}

.nav-logo {
    height: 40px;
    width: auto;
    object-fit: contain;
    filter: brightness(0);
}

[data-theme="dark"] .nav-logo {
    filter: brightness(0) invert(1);
}

/* Set on the <img> via layout.js's brand() helper when the footer wants a larger mark.
   Overrides .nav-logo's fixed 40px height, which would otherwise win over the element's
   own width/height attributes. Unused while the footer shows the full lockup. */
.footer-logo {
    height: 88px;
}

@media (max-width: 640px) {
    .footer-logo { height: 68px; }
}

.nav-title {
    display: flex;
    flex-direction: column;
}

.nav-title-main {
    font-family: var(--font-serif);
    font-size: 17px;
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1.1;
}

.nav-title-sub {
    font-size: 10px;
    color: var(--accent);
    letter-spacing: 0.18em;
    text-transform: uppercase;
}

.nav-right {
    display: flex;
    align-items: center;
    gap: 32px;
}

.nav-actions {
    display: flex;
    align-items: center;
    gap: 12px;
}

/* Current conditions at the course: a quiet chip, but a real button — tapping it opens the
   detail panel, since a phone can't show the title attribute on hover. */
.nav-weather-wrap {
    position: relative;
    display: flex;
}

.nav-weather {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 5px 11px 5px 9px;
    background: none;
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 13px;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    transition: border-color 0.2s, color 0.2s;
}

.nav-weather:hover,
.nav-weather[aria-expanded="true"] {
    border-color: var(--accent-border);
    color: var(--accent);
}

/* Hangs below the chip, pinned to its right edge so it can't run off the screen on a
   phone — the chip sits close to the right side of the navbar. */
.nav-weather-detail {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    z-index: 1;
    min-width: 172px;
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 12px 14px;
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
    font-family: var(--font-sans);
    font-size: 13px;
    color: var(--text-muted);
    white-space: nowrap;
    text-align: left;
}

.nav-weather-detail strong {
    color: var(--text-primary);
    font-size: 14px;
    font-weight: 700;
}

.nav-weather-where {
    color: var(--text-faint);
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-top: 2px;
}

.nav-weather i {
    color: var(--accent);
    font-size: 13px;
}

@media (max-width: 359px) {
    /* Only on the genuinely tiny screens, where the brand, the chip and two buttons stop
       fitting on one line. The temperature is the part worth keeping; the icon gives way.
       Measured: the full chip still fits at 360px and 390px, so the cut-off sits below both. */
    .nav-weather { padding: 5px 9px; font-size: 12px; }
    .nav-weather i { display: none; }
}

.theme-toggle {
    background: none;
    border: none;
    color: var(--text-primary);
    width: 36px;
    height: 36px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    cursor: pointer;
    transition: border-color 0.2s, color 0.2s;
}

.theme-toggle:hover {
    color: var(--accent);
}

.nav-links {
    display: flex;
    align-items: center;
    gap: 28px;
    list-style: none;
}

/* Guards against the mobile drill-down JS leaving an inline height on
   #navLinks if the viewport grows past the breakpoint without a refresh */
@media (min-width: 641px) {
    .nav-links {
        height: auto !important;
    }
}

.nav-links a {
    text-decoration: none;
    color: var(--text-muted);
    font-size: 13.5px;
    font-weight: 500;
    letter-spacing: 0.04em;
    transition: color 0.2s;
}

.nav-links a:hover { color: var(--text-primary); }

.nav-dropdown > a:focus-visible,
.nav-toggle:focus-visible,
.theme-toggle:focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 3px;
}

/* === DROPDOWN === */
.nav-dropdown {
    position: relative;
}

.nav-chevron {
    font-size: 10px;
    margin-left: 4px;
    transition: transform 0.2s;
}

.dropdown-menu {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    padding-top: 12px;
    background: transparent;
    list-style: none;
    min-width: 150px;
}

.dropdown-menu::before {
    content: '';
    position: absolute;
    inset: 12px 0 0 0;
    background: var(--surface-translucent);
    border: 1px solid var(--border-subtle);
    border-radius: 6px;
    box-shadow: 0 12px 32px rgba(0,0,0,0.5);
    z-index: -1;
}

/* hover only on non-touch devices, and only at desktop widths — below 640px the
   nav switches to the click-driven mobile drill-down, which must be the sole
   trigger for showing a dropdown (otherwise a mouse/trackpad on a narrow
   viewport reveals a submenu via hover independent of the drill-down state). */
@media (hover: hover) and (min-width: 641px) {
    .nav-dropdown:hover > a .nav-chevron {
        transform: rotate(180deg);
    }
    .nav-dropdown:hover > .dropdown-menu {
        display: block;
    }
}

.dropdown-menu li a {
    display: block;
    padding: 12px 20px;
    color: var(--text-muted) !important;
    font-size: 13.5px;
    white-space: nowrap;
    transition: background 0.15s, color 0.15s;
}

.dropdown-menu li a:hover {
    background: var(--accent-dim);
    color: var(--text-primary) !important;
}

.nav-toggle {
    display: none;
    background: none;
    border: none;
    color: var(--text-primary);
    font-size: 22px;
    cursor: pointer;
    z-index: 1001;
}

/* Also expose a submenu while keyboard focus is within it. Safe to apply at every width:
   this bar is hidden outright on mobile, which has its own flat slide-over menu. */
.nav-dropdown:focus-within > .dropdown-menu {
    display: block;
}
.nav-dropdown.dropdown-open > .dropdown-menu {
    display: block;
}

.form-status { margin-top: 14px; color: var(--text-muted); }

/* === TOURNAMENTS: FEATURED EVENT + LIST ===
   Every element here takes its accent from an --ev custom property set per event in
   tournaments.html, so one rule set serves all three categories. */
.tourney-featured {
    display: grid;
    grid-template-columns: 1fr;
    gap: 28px;
    align-items: center;
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-top: 4px solid var(--ev);
    border-radius: 14px;
    padding: 30px 32px;
    margin-bottom: 34px;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.07);
}

@media (min-width: 760px) {
    .tourney-featured:has(.tourney-featured-media) { grid-template-columns: 1fr auto; }
}

.tourney-featured-eyebrow {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 10px;
}

.tourney-featured-type {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ev-text, var(--ev));
    margin-bottom: 8px;
}

.tourney-featured-title {
    font-family: var(--font-serif);
    font-size: clamp(1.5rem, 3.4vw, 2.1rem);
    line-height: 1.15;
    margin-bottom: 8px;
}

.tourney-featured-date { color: var(--text-muted); font-size: 15px; margin-bottom: 14px; }

.tourney-featured-info {
    color: var(--text-muted);
    font-size: 14.5px;
    line-height: 1.6;
    margin: 14px 0 0;
    /* Long flyer text belongs in the modal, not spilling down the hero card. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* .btn-pill (defined later in this file, same specificity) sets inline-flex — the
   compound selector here is needed to reliably win regardless of source order. */
.tourney-featured-btn.btn-pill { display: flex; width: fit-content; margin-top: 20px; }

/* Holds the featured card's actions in a row when an event has an online sign-up, so
   Register sits beside View Details rather than under it. The buttons keep their own
   margin-top, which is what spaces the row off the text above — the High School card has
   a bare button with no wrapper and must stay unaffected. */
.tourney-featured-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
}

.tourney-featured-media img {
    display: block;
    width: min(230px, 42vw);
    height: auto;
    border-radius: 10px;
    border: 1px solid var(--border-subtle);
}

.tourney-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 22px;
}

.tourney-filter {
    background: none;
    border: 1px solid var(--border-strong);
    border-radius: 999px;
    padding: 8px 16px;
    /* Not --text-muted: on the page background that lands at 3.9:1, under AA for 12.5px. */
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    transition: color 0.2s, border-color 0.2s, background 0.2s;
}

.tourney-filter:hover { border-color: var(--ev, var(--accent)); color: var(--ev-text, var(--accent)); }

/* Selected state is a tint plus a doubled border, not a solid fill. White on the vivid
   category colours fails AA — #4285f4 gives 3.56:1 — and darkening the fill enough to fix
   that in light mode would make it unreadable in dark. The tint sidesteps the whole
   problem: it reuses --ev-text, already contrast-checked against a card background. */
.tourney-filter.is-active {
    background: var(--ev-soft, var(--accent-dim));
    border-color: var(--ev, var(--accent));
    box-shadow: inset 0 0 0 1px var(--ev, var(--accent));
    color: var(--ev-text, var(--accent));
    font-weight: 700;
}

.tourney-month-heading {
    font-family: var(--font-sans);
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin: 26px 0 12px;
}

.tourney-month-heading:first-child { margin-top: 0; }
.tourney-month-heading--past { padding-top: 18px; border-top: 1px solid var(--border-subtle); }

.tourney-row {
    display: flex;
    align-items: center;
    gap: 18px;
    width: 100%;
    text-align: left;
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-left: 4px solid var(--ev);
    border-radius: 10px;
    padding: 14px 18px;
    margin-bottom: 10px;
    cursor: pointer;
    font-family: var(--font-sans);
    color: var(--text-primary);
    transition: border-color 0.2s, transform 0.2s, box-shadow 0.2s;
}

.tourney-row:hover {
    border-color: var(--ev);
    border-left-color: var(--ev);
    transform: translateX(2px);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}


.tourney-row-date {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    min-width: 52px;
    padding: 6px 4px;
    border-radius: 8px;
    background: var(--overlay-faint);
}

.tourney-row-month { font-size: 10px; font-weight: 700; letter-spacing: 0.1em; color: var(--ev-text, var(--ev)); }
.tourney-row-day   { font-family: var(--font-serif); font-size: 20px; font-weight: 700; line-height: 1.1; }

.tourney-row-main { flex: 1; min-width: 0; }

.tourney-row-title {
    display: block;
    font-family: var(--font-serif);
    font-size: 16.5px;
    font-weight: 700;
    margin-bottom: 5px;
}

.tourney-row-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 14px;
    font-size: 12.5px;
    color: var(--text-muted);
}

.tourney-row-type { display: inline-flex; align-items: center; gap: 6px; color: var(--ev-text, var(--ev)); font-weight: 600; }
.tourney-row-type i { font-size: 11px; }

/* Modal category line, on all three event pages. */
.tourney-modal-type[class*="cal-ev--"] { color: var(--ev-text, var(--ev)); }

/* Keep past events visually quieter through their surface, not by reducing the text's
   opacity: inherited opacity dropped the dark-theme metadata below WCAG AA contrast. */
.tourney-row--past { background: var(--bg-surface); }

/* The event list is fetched, so the container is empty at first paint and the footer sits
   high on the page until it lands — a large layout shift. Reserving height removes it. */
#tournamentsCalendar, #hsCalendar, #courseCalendar { min-height: 70vh; }

.tourney-row-arrow { color: var(--text-muted); font-size: 12px; flex-shrink: 0; }

@media (max-width: 560px) {
    .tourney-featured { padding: 24px 20px; }
    .tourney-row { gap: 12px; padding: 12px 14px; }
    .tourney-row-arrow { display: none; }
}

/* A flyer attached to a calendar event. Removed from the DOM by an onerror handler if it
   fails to load, so an unshared Drive file leaves no broken-image placeholder behind. */
.tourney-flyer {
    display: block;
    width: 100%;
    max-width: 420px;
    height: auto;
    margin: 18px auto 0;
    border-radius: 10px;
    border: 1px solid var(--border-subtle);
}

/* On a wide screen, sit the flyer beside the event text instead of under it — the same
   arrangement the featured "Upcoming Event" card uses — so a poster-shaped image doesn't
   push everything below it into a long scroll. Everything except the flyer stays in the
   reading column; the flyer takes column two, top-aligned.
   :has() means no per-page markup change, and it degrades to the stacked layout it
   replaces. The card only widens when there is actually a flyer, so a text-only event
   keeps its comfortable reading measure. */
@media (min-width: 861px) {
    .tourney-modal-card:has(.tourney-flyer) { max-width: 900px; }

    /* The flyer is lifted out of the flow and pinned to the top-right of the scrolling
       body, with the text given a matching right inset to sit beside it.
       Grid looked like the obvious tool, but the flyer would have to span every row, and
       grid distributes a spanning item's surplus height across the rows it covers — which
       pulls the paragraphs apart whenever the poster is taller than the text, as it
       usually is. Positioning avoids that: the text keeps its natural rhythm, and the
       flyer still extends the scroll area when it is the taller of the two.
       The offsets match .tourney-modal-inner's own 44px/36px padding. */
    .tourney-modal-inner:has(.tourney-flyer) {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        /* Rows 1-7 take the event text (type, title, date, gender, format, info, spare),
           row 8 is an empty flexible spacer, and rows 9-12 hold the trailing actions in
           their DOM order. The flyer spans all twelve.
           The spacer is the whole trick: grid hands a spanning item's surplus height to
           flexible tracks, so a poster taller than the text pushes the actions down
           instead of stretching the gaps between the paragraphs beside it. Unused
           min-content rows collapse to zero. */
        grid-template-rows: repeat(7, min-content) 1fr repeat(4, min-content);
        column-gap: 28px;
    }

    .tourney-modal-inner:has(.tourney-flyer) > * { grid-column: 1; }

    /* The format tag is an inline <span> in the stacked layout; as a grid item it would
       stretch to fill the column and read as a full-width bar. */
    .tourney-modal-inner:has(.tourney-flyer) > .tourney-format-tag { justify-self: start; }

    .tourney-modal-inner:has(.tourney-flyer) > .tourney-flyer {
        grid-column: 2;
        grid-row: 1 / -1;
        align-self: start;
        width: 340px;
        max-width: none;
        margin: 0;
    }

    /* The trailing actions are pinned to the last three rows, below the spacer, so they
       gather at the bottom-left in line with the foot of the flyer. Assigned explicitly
       rather than left to auto-placement so the painted order still matches the DOM order
       — otherwise the More Info row would render above a button that precedes it in the
       markup, and tab order would disagree with what is on screen. */
    .tourney-modal-inner:has(.tourney-flyer) > .tourney-register-btn { grid-row: 9; }
    .tourney-modal-inner:has(.tourney-flyer) > #addToCalendarBtn { grid-row: 10; }
    /* The results pill is the other <a> wearing this class, so it is matched by exclusion. */
    .tourney-modal-inner:has(.tourney-flyer) > a.add-to-calendar-btn:not(.tourney-register-btn) { grid-row: 11; }
    .tourney-modal-inner:has(.tourney-flyer) > .tourney-links { grid-row: 12; }

    /* The flyer's top edge starts at the body's 44px padding and its right edge at the
       36px one, which put it straight under the close button. Tucking the button into the
       corner clears it without shrinking the poster. */
    .tourney-modal-card:has(.tourney-flyer) .tourney-modal-close {
        top: 8px;
        right: 8px;
    }
}

/* === MOBILE SLIDE-OVER MENU ===
   A single flat panel: every dropdown becomes a headed section, so there is no drilling
   in and back out on a phone. Deliberately dark in both themes — it reads as a surface
   sitting above the page rather than part of it, and keeps one set of contrast choices
   instead of two. Markup is generated in layout.js from the desktop nav's own links. */
.mobile-menu {
    --menu-bg:     #161d17;
    --menu-text:   #f2f4ee;
    --menu-muted:  rgba(242, 244, 238, 0.48);
    --menu-rule:   rgba(242, 244, 238, 0.14);
    --menu-accent: #7fb994;

    position: fixed;
    inset: 0;
    z-index: 1100;
    visibility: hidden;
    pointer-events: none;
}

.mobile-menu.open {
    visibility: visible;
    pointer-events: auto;
}

.mobile-menu-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(10, 14, 10, 0.32);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    opacity: 0;
    transition: opacity 0.35s ease;
}

.mobile-menu.open .mobile-menu-backdrop { opacity: 1; }

.mobile-menu-panel {
    position: absolute;
    top: 0;
    right: 0;
    width: min(86vw, 340px);
    height: 100%;
    /* dvh keeps the panel clear of mobile browser chrome that grows and shrinks. */
    height: 100dvh;
    display: flex;
    flex-direction: column;
    background: var(--menu-bg);
    color: var(--menu-text);
    padding: 26px 0 0;
    box-shadow: -18px 0 50px rgba(0, 0, 0, 0.4);
    transform: translateX(100%);
    transition: transform 0.38s cubic-bezier(0.22, 0.61, 0.36, 1);
    overflow-y: auto;
    overscroll-behavior: contain;
}

.mobile-menu.open .mobile-menu-panel { transform: translateX(0); }

.mobile-menu-close {
    display: flex;
    align-items: center;
    gap: 12px;
    background: none;
    border: none;
    padding: 0 26px;
    margin-bottom: 26px;
    color: var(--menu-muted);
    font-family: inherit;
    font-size: 14px;
    cursor: pointer;
    transition: color 0.2s ease;
}

.mobile-menu-close i { font-size: 17px; }
.mobile-menu-close:hover { color: var(--menu-text); }

.mobile-menu-brand {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 0 26px 16px;
    text-decoration: none;
    color: inherit;
}

.mobile-menu-brand img {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: rgba(242, 244, 238, 0.08);
    padding: 6px;
    object-fit: contain;
    /* Knock the mark to white so it reads against the dark panel. */
    filter: brightness(0) invert(1);
}

.mobile-menu-club {
    font-family: var(--font-serif);
    font-size: 17px;
    font-weight: 700;
    line-height: 1.2;
}

/* The panel's one primary action, so it gets the site's pill button treatment rather
   than sitting as another line of text. Filled with the light accent and dark label:
   the site's dark-green button would sink into this near-black panel. */
.mobile-menu-cta {
    /* Sized to its label, but starting at the same left gutter as the headings and nav
       items below so the panel keeps one clean left edge. */
    display: inline-flex;
    align-self: flex-start;
    align-items: center;
    gap: 7px;
    margin: 0 26px 22px;
    padding: 8px 15px;
    border-radius: 999px;
    background: var(--menu-accent);
    color: #12180f;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    text-decoration: none;
    box-shadow: 0 4px 12px rgba(127, 185, 148, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.28);
    transition: background 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}

.mobile-menu-cta i { font-size: 11px; }

.mobile-menu-cta:hover {
    background: #96c9a8;
    box-shadow: 0 8px 22px rgba(127, 185, 148, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.34);
}

.mobile-menu-cta:active { transform: scale(0.98); }

.mobile-menu-nav {
    flex: 1;
    padding: 0 26px;
}

.mobile-menu-group {
    padding-bottom: 22px;
    opacity: 0;
    transform: translateX(16px);
    transition: opacity 0.35s ease, transform 0.35s ease;
    /* --i is set per group in layout.js so the sections arrive in sequence. */
    transition-delay: calc(var(--i, 0) * 55ms + 110ms);
}

.mobile-menu.open .mobile-menu-group {
    opacity: 1;
    transform: none;
}

.mobile-menu-heading {
    font-size: 12px;
    font-weight: 500;
    color: var(--menu-muted);
    padding-bottom: 9px;
    margin-bottom: 5px;
    border-bottom: 1px solid var(--menu-rule);
}

.mobile-menu-nav ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

.mobile-menu-nav a {
    display: block;
    padding: 9px 0;
    color: var(--menu-text);
    font-size: 16px;
    font-weight: 700;
    text-decoration: none;
    transition: color 0.2s ease;
}

.mobile-menu-nav a:hover,
.mobile-menu-nav a.is-current { color: var(--menu-accent); }

.mobile-menu-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 26px calc(20px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--menu-rule);
}

.mobile-menu-foot a,
.mobile-menu-theme {
    display: flex;
    align-items: center;
    gap: 8px;
    background: none;
    border: none;
    padding: 0;
    color: var(--menu-muted);
    font-family: inherit;
    font-size: 13px;
    text-decoration: none;
    cursor: pointer;
    transition: color 0.2s ease;
}

.mobile-menu-foot a:hover,
.mobile-menu-theme:hover { color: var(--menu-text); }

.mobile-menu :focus-visible {
    outline: 2px solid var(--menu-accent);
    outline-offset: 3px;
    border-radius: 3px;
}

body.menu-open {
    position: fixed;
    left: 0;
    right: 0;
    width: 100%;
    overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
    .mobile-menu-panel,
    .mobile-menu-backdrop,
    .mobile-menu-group {
        transition: none;
        transition-delay: 0s;
    }
}

/* === HERO === */
.hero {
    position: relative;
    /* Full-height on phones/short windows, but capped so it doesn't dominate large desktop monitors. */
    min-height: min(100vh, 820px);
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    overflow: hidden;
}

/* The hero photo used to be a CSS background here; it is now a <picture> element
   (see "Homepage hero" below), which lets the markup pick the mobile crop and lets
   the preload in index.html start it before CSS is parsed. Only the positioning
   this element needs to sit behind the hero content is left. */
.hero-bg {
    position: absolute;
    inset: 0;
}

.hero-content {
    position: relative;
    z-index: 1;
    max-width: 820px;
    padding: 0 24px;
}

.hero-eyebrow {
    font-size: 12px;
    letter-spacing: 0.32em;
    text-transform: uppercase;
    color: #5a9b6f;
    margin-bottom: 20px;
}

.hero-title {
    font-size: clamp(3rem, 7vw, 5.5rem);
    font-weight: 700;
    color: #fff;
    margin-bottom: 24px;
    text-shadow: 0 4px 48px rgba(0,0,0,0.6);
}

.hero-subtitle {
    font-size: 18px;
    color: rgba(240, 237, 232, 0.65);
    max-width: 560px;
    margin: 0 auto 44px;
    font-weight: 300;
    line-height: 1.75;
}

.hero-actions {
    display: flex;
    gap: 16px;
    justify-content: center;
    flex-wrap: wrap;
}

.hero-scroll {
    position: absolute;
    bottom: 36px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    color: rgba(240, 237, 232, 0.35);
    font-size: 10px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
}

.hero-scroll-line {
    width: 1px;
    height: 30px;
    background: linear-gradient(#b6d7be, transparent);
    animation: scroll-line 2.2s ease-in-out infinite;
}

/* Phones in landscape: the viewport is too short for min-height: 100vh to
   leave room for the full title/stats/buttons stack, so the content grows
   past it and collides with the absolutely-positioned scroll cue. Let the
   hero size itself to its content instead, and drop the scroll cue — it
   isn't meaningful on a screen this short anyway. */
@media (max-height: 500px) and (orientation: landscape) {
    .hero {
        min-height: 0;
        padding: 90px 0 50px;
    }
    .hero-scroll { display: none; }
}
@keyframes scroll-line {
    0% { transform: scaleY(0); transform-origin: top; }
    45% { transform: scaleY(1); transform-origin: top; }
    55% { transform: scaleY(1); transform-origin: bottom; }
    100% { transform: scaleY(0); transform-origin: bottom; }
}

/* Homepage hero — responsive image, cinematic overlay, and subtle ambient glow. */
.hero-bg {
    display: block;
    overflow: hidden;
    background: #10170f;
}
.hero-bg > img {
    position: absolute;
    inset: 0;
    z-index: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center 38%;
    animation: hero-zoom 32s ease-in-out infinite alternate;
}
.hero-bg::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    background: linear-gradient(to bottom, rgba(4, 12, 6, 0.58), rgba(7, 13, 7, 0.48) 45%, rgba(7, 13, 7, 0.78));
}
@keyframes hero-zoom { to { transform: scale(1.055); } }
/* The slow zoom is decorative; honor a request for reduced motion. */
@media (prefers-reduced-motion: reduce) {
    .hero-bg > img { animation: none; }
    .hero-scroll-line { animation: none; }
}
.hero-glow {
    position: absolute;
    z-index: 0;
    width: min(54vw, 700px);
    aspect-ratio: 1;
    left: 50%; top: 47%;
    transform: translate(-50%, -50%);
    background: radial-gradient(circle, rgba(47, 93, 63, 0.34), rgba(47, 93, 63, 0.1) 42%, transparent 70%);
    filter: blur(8px);
    pointer-events: none;
}
.hero-content { max-width: 900px; padding-top: 62px; }
.hero-eyebrow { color: #b6d7be; font-weight: 600; text-shadow: 0 2px 12px rgba(0,0,0,.7); }
/* Takes the eyebrow's colour, weight and shadow rather than the base 65%-opacity
   treatment, which was hard to read over the hero photo. Not the eyebrow's uppercase
   or 0.32em tracking — that's sized for three words, not a full sentence. */
.hero-subtitle {
    color: #b6d7be;
    font-weight: 600;
    text-shadow: 0 2px 12px rgba(0,0,0,.7);
    margin-bottom: 32px;
}
.hero-stats {
    width: fit-content;
    margin: 0 auto 38px;
    padding: 13px 16px;
    border: 1px solid rgba(255,255,255,.1);
    border-radius: 999px;
    background: rgba(8, 18, 9, .48);
    box-shadow: 0 14px 36px rgba(0,0,0,.24);
    backdrop-filter: blur(10px);
}
.hero-stat { flex-direction: row; padding: 0 22px; }
.hero-stat-text { display: flex; flex-direction: column; text-align: left; }
.hero-stat-value { font-family: var(--font-sans); font-size: .82rem; font-weight: 600; line-height: 1.3; white-space: nowrap; }
.hero-stat-label { font-size: 9px; margin-top: 0; }
.hero-actions { gap: 14px; }
.hero-actions .btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 200px;
    min-height: 48px;
    padding: 14px 24px;
    overflow: hidden;
    border-radius: 999px;
}
.hero-actions .btn-primary { box-shadow: 0 8px 28px rgba(47, 93, 63, .38); }
.hero-actions .btn-primary:hover { box-shadow: 0 10px 32px rgba(47, 93, 63, .52); }
.hero-actions .btn-outline {
    color: #fff;
    background: rgba(8, 18, 9, .45);
    border: 1px solid rgba(255,255,255,.28);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
}
.hero-actions .btn-outline:hover {
    transform: translateY(-2px);
    color: #d5eedb;
    background: rgba(8, 18, 9, .62);
    border-color: #b6d7be;
    box-shadow: 0 8px 28px rgba(47, 93, 63, .38);
}
.hero-actions .btn::after {
    content: '';
    position: absolute;
    top: 0;
    left: -130%;
    width: 60%;
    height: 100%;
    background: linear-gradient(105deg, transparent, rgba(255,255,255,.28), transparent);
    transform: skewX(-20deg);
    pointer-events: none;
    transition: left .55s ease;
}
.hero-actions .btn:hover::after { left: 170%; }
.hero-actions .btn:active { transform: translateY(0) scale(.97); }
@media (max-width: 640px) {
    .hero { min-height: 720px; }
    .hero-bg > img { object-position: center center; }
    .hero-content { padding-top: 42px; }
    .hero-subtitle { margin-bottom: 30px; font-size: 16px; }
    .hero-stats { padding: 18px 8px; margin-bottom: 30px; }
    .hero-stat { padding: 0 12px; }
    .hero-stat-value { font-size: .8rem; }
    .hero-stat-label { font-size: 8px; }
    .hero-actions .btn { width: min(100%, 260px); }
}

@keyframes hero-reveal {
    from { opacity: 0; transform: translateY(20px); }
    to { opacity: 1; transform: translateY(0); }
}

.hero-title { animation: hero-reveal 0.7s ease-out 0.1s both; }
.hero-subtitle { animation: hero-reveal 0.6s ease-out 0.18s both; }
.hero-stats { animation: hero-reveal 0.6s ease-out 0.28s both; }
.hero-actions { animation: hero-reveal 0.6s ease-out 0.34s both; }

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
    .hero-scroll-line { animation: none; transform: scaleY(1); }
}

/* Backdrop blurs require expensive compositing on many phones. The visual
   treatment remains on desktop, while small screens get the same contrast
   from opaque backgrounds and avoid a continuously animated hero image. */
@media (max-width: 640px) {
    .navbar,
    .hero-stats,
    .hero-actions .btn-outline {
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }
    .hero-bg > img { animation: none; }
}

/* Large result and scorecard views do not need layout/paint work until close
   to the viewport. The intrinsic size prevents a scroll-bar jump. */
.page-hero ~ section, .page-hero ~ main {
    content-visibility: auto;
    contain-intrinsic-size: auto 800px;
}

@keyframes float {
    0%, 100% { transform: translateY(0); }
    50%       { transform: translateY(7px); }
}

/* === BUTTONS === */
.btn {
    display: inline-block;
    padding: 14px 32px;
    font-family: var(--font-sans);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    text-decoration: none;
    border-radius: 4px;
    border: none;
    cursor: pointer;
    transition: all 0.22s ease;
}

.btn-primary {
    background: var(--btn-fill);
    color: #fff;
}

.btn-primary:hover {
    background: var(--btn-fill-hover);
    transform: translateY(-2px);
    box-shadow: 0 8px 28px var(--accent-shadow);
}

.btn-outline {
    background: transparent;
    color: var(--text-primary);
    border: 1px solid var(--border-strong);
}

.btn-outline:hover {
    border-color: var(--accent);
    color: var(--accent);
    transform: translateY(-2px);
}

/* The hero photo backdrop is always dark regardless of site theme, so its
   buttons stay on fixed light colors instead of the theme-aware defaults. */
.hero .btn-outline {
    color: #fff;
    border-color: rgba(255, 255, 255, 0.35);
}

.hero .btn-outline:hover {
    border-color: #5a9b6f;
    color: #5a9b6f;
}

/* The hero's pill treatment — shape, lift and shine sweep — for buttons outside
   the hero. The backdrop blur the hero pills use is left out: these sit on opaque
   sections, where there is nothing behind them to blur. The glass read comes from
   the top highlight and hairline edge each variant adds instead. */
.btn-pill {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 48px;
    overflow: hidden;
    border-radius: 999px;
}

.btn-pill::after {
    content: '';
    position: absolute;
    top: 0;
    left: -130%;
    width: 60%;
    height: 100%;
    background: linear-gradient(105deg, transparent, rgba(255, 255, 255, .28), transparent);
    transform: skewX(-20deg);
    pointer-events: none;
    transition: left .55s ease;
}

.btn-pill:hover::after { left: 170%; }
.btn-pill:active { transform: translateY(0) scale(.97); }

/* .btn-block's `display: block` would otherwise beat the pill's inline-flex and drop
   the label to the top of its 48px min-height. Block-level flex keeps both: full
   width from the block, centring from the pill. */
.btn-block.btn-pill { display: flex; }

.btn-primary.btn-pill {
    border: 1px solid rgba(255, 255, 255, 0.16);
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0) 48%), var(--btn-fill);
    box-shadow: 0 8px 28px var(--accent-shadow), inset 0 1px 0 rgba(255, 255, 255, 0.22);
}

.btn-primary.btn-pill:hover {
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0) 48%), var(--btn-fill-hover);
    border-color: rgba(255, 255, 255, 0.26);
    box-shadow: 0 10px 32px var(--accent-shadow), inset 0 1px 0 rgba(255, 255, 255, 0.26);
}

.btn-facebook {
    border: 1px solid rgba(255, 255, 255, 0.22);
    /* Facebook's #1877F2 gives white text only 4.23:1. A shade deeper reads as the same
       brand blue and clears AA at 5.41:1. */
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0) 48%), #1565d8;
    color: #fff;
    box-shadow: 0 8px 28px rgba(24, 119, 242, 0.30), inset 0 1px 0 rgba(255, 255, 255, 0.26);
}

.btn-facebook:hover {
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0) 48%), #145cc4;
    color: #fff;
    border-color: rgba(255, 255, 255, 0.34);
    transform: translateY(-2px);
    box-shadow: 0 10px 32px rgba(24, 119, 242, 0.46), inset 0 1px 0 rgba(255, 255, 255, 0.3);
}

/* === SECTION SHARED === */
.section-header {
    text-align: center;
    margin-bottom: 80px;
}

.section-eyebrow {
    font-size: 11px;
    letter-spacing: 0.32em;
    text-transform: uppercase;
    color: var(--accent);
    margin-bottom: 12px;
}

.section-title {
    font-size: clamp(2rem, 4vw, 3rem);
    color: var(--text-primary);
    margin-bottom: 16px;
}

.section-subtitle {
    color: var(--text-muted);
    max-width: 540px;
    margin: 0 auto;
    font-size: 16px;
    line-height: 1.72;
}

/* === COURSE + ANNOUNCEMENTS (side by side) === */
.course-announce-section {
    padding: 140px 0;
    position: relative;
    z-index: 1;
}

.course-announce-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 100px;
    align-items: start;
}

/* These once sat in a half-width column beside the announcements, where a single
   vertical list read best. That section is gone and they now run the full page
   width, where one item per row left most of each row empty — so they sit 3-up
   as compact cards, matching the card rows elsewhere on the site. */
.features-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
}

.feature-card {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    padding: 26px 24px;
    position: relative;
    overflow: hidden;
    transition: border-color 0.3s, transform 0.3s;
}

.feature-card::after { display: none; }

.feature-card:hover {
    border-color: var(--accent-border);
    transform: translateY(-3px);
    box-shadow: none;
}

.feature-icon {
    display: flex;
    align-items: center;
    margin-bottom: 14px;
    font-size: 17px;
    color: var(--accent);
}

.feature-card h3 {
    font-size: 17px;
    color: var(--text-primary);
    margin-bottom: 10px;
}

.feature-card p {
    color: var(--text-muted);
    font-size: 14px;
    line-height: 1.65;
}

/* === CONTACT === */
.contact-grid {
    display: grid;
    grid-template-columns: 1fr 1.6fr;
    gap: 80px;
    align-items: start;
}

.contact-info {
    display: flex;
    flex-direction: column;
    gap: 30px;
}

.contact-item {
    display: flex;
    gap: 18px;
    align-items: flex-start;
}

.contact-item > i {
    color: var(--accent);
    font-size: 17px;
    margin-top: 2px;
    min-width: 20px;
}

/* h3, not h4: these follow the section's h2 with nothing in between, and the level should
   reflect that. The small uppercase treatment is what makes them read as labels. */
.contact-item h3 {
    font-family: var(--font-sans);
    font-size: 11px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 4px;
    font-weight: 600;
}

.contact-item p {
    color: var(--text-primary);
    font-size: 15px;
    line-height: 1.5;
}

.contact-item p a {
    color: var(--accent);
    text-decoration: none;
}

.contact-form {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
}

/* Honeypot: present in the DOM (display:none is skipped by some bots) but invisible
   and unreachable to real visitors via mouse, tab, or screen reader. */
.hp-field {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    left: -9999px;
}

.form-group input,
.form-group textarea {
    width: 100%;
    background: var(--overlay-faint);
    border: 1px solid var(--overlay-medium);
    border-radius: 6px;
    padding: 16px 20px;
    color: var(--text-primary);
    font-family: var(--font-sans);
    /* 16px is the iOS Safari threshold below which focusing the field auto-zooms the page
       (and it doesn't reliably zoom back out on blur) — keep every form field at or above it. */
    font-size: 16px;
    transition: border-color 0.2s, background 0.2s;
    resize: vertical;
}

.form-group input::placeholder,
.form-group textarea::placeholder { color: var(--text-muted); }

.form-group input:focus,
.form-group textarea:focus {
    outline: none;
    border-color: var(--accent);
    background: var(--accent-dim);
}

/* The contact and review forms sit directly on the page instead of inside a card, so a
   translucent field lets the body's "+" motif show through and the input reads as
   see-through. Laying the same overlay down as an opaque gradient over --bg-page keeps
   the exact colour these fields already had while making them solid. Fields inside modals
   deliberately keep the plain rule above — an opaque card is already behind them. */
.contact-form .form-group input,
.contact-form .form-group textarea,
.review-form .form-group input,
.review-form .form-group textarea {
    background: linear-gradient(var(--overlay-faint), var(--overlay-faint)), var(--bg-page);
}

.contact-form .form-group input:focus,
.contact-form .form-group textarea:focus,
.review-form .form-group input:focus,
.review-form .form-group textarea:focus {
    background: linear-gradient(var(--accent-dim), var(--accent-dim)), var(--bg-page);
}

.contact-form-eyebrow {
    text-align: left;
    margin-bottom: 32px;
}

.form-label {
    display: block;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 12px;
}

/* === FOOTER === */
.footer {
    background: var(--footer-bg);
    border-top: 1px solid var(--border-subtle);
    /* Tightened from 80px/56px: with the hours collapsed to a single line, the old spacing
       left the columns floating in a band far taller than their content. */
    padding: 56px 0 28px;
    position: relative;
    z-index: 1;
}

.footer-grid {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1fr;
    gap: 48px;
    margin-bottom: 36px;
    align-items: start;
}

.footer-brand p a {
    color: var(--accent);
    text-decoration: none;
}

.footer-brand p {
    color: var(--text-muted);
    font-size: 14px;
    line-height: 1.72;
    margin-top: 16px;
    max-width: 280px;
}

.footer-hours h2,
.footer-links h2,
.footer-contact h2 {
    font-family: var(--font-sans);
    font-size: 11px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--accent);
    margin-bottom: 18px;
    font-weight: 600;
}

/* The Contact Us heading doubles as the link to that page. Inherits the heading's colour
   and tracking so the column headers still read as a matched set; the underline appears on
   hover, which is what distinguishes it from the two headings that aren't clickable. */
.footer-contact h2 a {
    color: inherit;
    text-decoration: none;
}

.footer-contact h2 a:hover,
.footer-contact h2 a:focus-visible {
    text-decoration: underline;
    text-underline-offset: 3px;
}

.footer-contact p {
    margin-bottom: 14px;
}

.footer-contact p a {
    color: var(--accent);
    text-decoration: none;
    font-size: 14px;
}

.social-links a img {
    display: block;
}


/* The inline Facebook mark (see FACEBOOK_ICON in layout.js). Vertically centred the way
   the Font Awesome <i> it replaced was, so the button and the social circle are unchanged. */
.icon-facebook {
    display: inline-block;
    vertical-align: -0.15em;
}

.social-links .social-link--facebook {
    background: #1565d8;
    border-color: #1565d8;
    color: #fff;
}

.social-links .social-link--facebook:hover {
    background: #145cc4;
    border-color: #145cc4;
    color: #fff;
}

.footer-links ul {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.footer-links a {
    text-decoration: none;
    color: var(--text-muted);
    font-size: 14px;
    transition: color 0.2s;
}

.footer-links a:hover { color: var(--text-primary); }

.footer-hours ul {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 9px;
}

.footer-hours li {
    display: flex;
    gap: 14px;
    font-size: 13.5px;
    color: var(--text-muted);
}

/* Sized to its content rather than a fixed 34px: a collapsed row's label is a range
   ("Sun – Sat"), not a three-letter day, and would have been clipped. */
.footer-hours li span:first-child {
    flex: 0 0 auto;
    min-width: 34px;
    color: var(--text-primary);
    white-space: nowrap;
}

.social-links {
    display: flex;
    gap: 10px;
}

.social-links a {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 1px solid var(--overlay-medium);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
    text-decoration: none;
    font-size: 14px;
    transition: border-color 0.2s, color 0.2s;
}

.social-links a:hover {
    border-color: var(--accent);
    color: var(--accent);
}

.footer-bottom {
    border-top: 1px solid var(--border-subtle);
    padding-top: 24px;
    text-align: center;
}

.footer-bottom p {
    color: var(--text-muted);
    font-size: 13px;
}

.footer-bottom a {
    color: var(--text-muted);
    text-decoration: none;
}

.footer-bottom a:hover,
.footer-bottom a:focus-visible {
    color: var(--accent);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.footer-sep {
    margin: 0 8px;
    opacity: 0.5;
}

/* === HERO STATS === */
.hero-stats {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0;
    margin-bottom: 40px;
    flex-wrap: wrap;
}

.hero-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 0 32px;
}

.hero-stat-value {
    font-family: var(--font-serif);
    font-size: 2.2rem;
    font-weight: 700;
    color: #fff;
    text-shadow: 0 2px 16px rgba(0,0,0,0.5);
    line-height: 1;
}

.hero-stat-label {
    font-size: 11px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: rgba(240, 237, 232, 0.5);
    margin-top: 6px;
}

.hero-stat-divider {
    width: 1px;
    height: 40px;
    background: rgba(255, 255, 255, 0.15);
    flex-shrink: 0;
}

/* === RATES SECTION === */
.rates-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
    align-items: start;
}

.rates-card {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 8px;
    padding: 36px 32px;
}

.rates-card--highlight {
    border-color: var(--accent-border);
    background: linear-gradient(160deg, var(--accent-dim) 0%, var(--bg-card) 60%);
    text-align: center;
}

.rates-card h3 {
    font-size: 16px;
    color: var(--text-primary);
    margin-bottom: 20px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--border-subtle);
}

.rates-tag {
    font-family: var(--font-sans);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--accent);
    background: var(--accent-dim);
    padding: 3px 8px;
    border-radius: 20px;
    vertical-align: middle;
    margin-left: 8px;
}

.rates-list {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.rates-list li {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 14.5px;
    color: var(--text-muted);
}

.rates-list .rate {
    font-family: var(--font-serif);
    font-size: 17px;
    font-weight: 600;
    color: var(--accent);
    flex-shrink: 0;
}

.rates-note {
    font-size: 12px;
    color: var(--text-muted);
    margin-top: 12px;
    line-height: 1.6;
    font-style: italic;
}

.rates-punch-desc {
    color: var(--text-muted);
    font-size: 14.5px;
    line-height: 1.6;
    margin-bottom: 20px;
}

.rates-punch-price {
    font-family: var(--font-serif);
    font-size: 4rem;
    font-weight: 700;
    color: var(--accent);
    line-height: 1;
    margin: 16px 0;
}

/* === MEMBERSHIP SECTION === */
.membership-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
}

.membership-card {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 8px;
    padding: 32px 28px;
    position: relative;
    transition: border-color 0.3s, transform 0.3s;
}

.membership-card:hover {
    border-color: var(--accent-border);
    transform: translateY(-3px);
}

/* Same solid surface as every other card — the badge and accent border carry the
   emphasis. The old translucent accent tint let the section's pattern show through. */
.membership-card--featured {
    border-color: var(--accent-border);
}

.membership-card--wide {
    grid-column: 1 / -1;
}

.membership-card--wide .rates-list .rate {
    color: var(--accent);
}

.membership-badge {
    display: inline-block;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--accent);
    background: var(--accent-dim);
    border: 1px solid var(--accent-border);
    padding: 4px 10px;
    border-radius: 20px;
    margin-bottom: 12px;
}

.membership-card h3 {
    font-size: 18px;
    color: var(--text-primary);
    margin-bottom: 8px;
}

.membership-price {
    font-family: var(--font-serif);
    font-size: 2.6rem;
    font-weight: 700;
    color: var(--accent);
    line-height: 1.1;
    margin: 12px 0;
}

.membership-desc {
    font-size: 13.5px;
    color: var(--text-muted);
    line-height: 1.62;
}

.membership-footer {
    text-align: center;
    margin-top: 48px;
    padding-top: 36px;
    border-top: 1px solid var(--border-subtle);
}

.membership-footer p {
    color: var(--text-muted);
    font-size: 14px;
}

/* Sits below other content on both pages, never first, so the top margin is safe. */
.member-benefits { margin-top: 72px; }

/* 80px under a section header is right for a page's opening block; this is a
   subsection, and the full gap left the cards floating away from their heading. */
.member-benefits .section-header { margin-bottom: 44px; }

/* Member benefits. Shared verbatim by membershiprates.html and becomeamember.html —
   edit both together. One card, not one per category: split five ways the shorter
   groups were mostly empty space and the whole thing read as five sparse boxes. */
.benefit-card {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    padding: 32px 34px;
}

/* Multi-column rather than a two-column grid. Both read top-to-bottom down the left
   then down the right, but a grid shares its rows across columns, so the one item that
   wraps to two lines stretched its whole row and knocked the two columns out of step.
   Columns pack independently and balance their own height. */
.benefit-list {
    list-style: none;
    columns: 2;
    column-gap: 44px;
}

/* Indent-and-absolute rather than flex + gap: these items contain inline <strong>,
   and in a flex row each <strong> becomes its own flex item — the discount amounts
   broke out into their own columns. Padding keeps the wrap hanging under the text. */
.benefit-list li {
    position: relative;
    padding-left: 25px;
    margin-bottom: 15px;
    font-size: 15px;
    line-height: 1.6;
    color: var(--text-muted);
    /* Without this a two-line item can be split across the column break. */
    break-inside: avoid;
}

.benefit-list li:last-child { margin-bottom: 0; }

/* Check drawn in CSS so the benefits don't pull another icon-font glyph, and so the
   marker stays pinned to the first line when an item wraps. */
.benefit-list li::before {
    content: '';
    position: absolute;
    left: 1px;
    top: 6px;
    width: 11px;
    height: 6px;
    border-left: 2px solid var(--accent);
    border-bottom: 2px solid var(--accent);
    transform: rotate(-45deg);
}

.benefit-list strong { color: var(--text-primary); font-weight: 600; }

/* === EMPLOYMENT (employment) === */
.job-card {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    padding: 30px 28px;
}

.job-eyebrow {
    font-family: var(--font-sans);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--accent);
    margin-bottom: 10px;
}

.job-card h2 {
    font-family: var(--font-serif);
    font-size: 1.5rem;
    color: var(--text-primary);
    margin-bottom: 16px;
}

.job-card h3 {
    font-size: 15px;
    color: var(--text-primary);
    margin-bottom: 10px;
}

.job-card p {
    font-size: 14.5px;
    line-height: 1.7;
    color: var(--text-muted);
}

.job-tags {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 22px;
}

.job-tags li {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 5px 12px;
    border: 1px solid var(--accent-border);
    border-radius: 999px;
    font-size: 12px;
    color: var(--text-muted);
}

.job-tags i { color: var(--accent); font-size: 11px; }

.job-resume {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid var(--border-subtle);
}

.job-resume a {
    color: var(--accent);
    font-weight: 600;
    text-decoration: none;
    word-break: break-word;
}

.job-resume a:hover { text-decoration: underline; }

.form-optional {
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    color: var(--text-muted);
}

/* === COURSE RULES (courserules) === */
.course-rules {
    max-width: 860px;
    margin: 0 auto;
}

.rules-card {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    padding: 30px 32px;
}

.rules-card + .rules-card { margin-top: 20px; }

.rules-card h2 {
    display: flex;
    align-items: center;
    gap: 12px;
    font-family: var(--font-serif);
    font-size: 1.3rem;
    color: var(--text-primary);
    margin-bottom: 20px;
}

/* Links inside a rules card. Without this they fall back to the browser's default link
   blue (#0000EE), which measures 1.7:1 on the dark card — unreadable — and is off-palette
   in light mode. The privacy policy's phone and email links were the first to hit this. */
.rules-note a,
.rules-list a {
    color: var(--accent);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.rules-note a:hover,
.rules-list a:hover { color: var(--accent-active); }

[data-theme="dark"] .rules-note a:hover,
[data-theme="dark"] .rules-list a:hover { color: var(--text-primary); }

.rules-card h2 i {
    font-size: 15px;
    color: var(--accent);
}

.rules-list {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.rules-list li {
    display: flex;
    gap: 14px;
    font-size: 15px;
    color: var(--text-muted);
    line-height: 1.7;
}

/* Dot drawn in CSS rather than an icon font — these are neutral rules, not a
   checklist of features, and it keeps the marker aligned to the first line. */
.rules-list li::before {
    content: '';
    flex-shrink: 0;
    width: 5px;
    height: 5px;
    margin-top: 10px;
    border-radius: 50%;
    background: var(--btn-fill);
}

.rules-list strong { color: var(--text-primary); }

.rules-note {
    margin-top: 20px;
    padding: 14px 18px;
    border-left: 3px solid var(--accent);
    border-radius: 0 8px 8px 0;
    background: var(--accent-dim);
    font-size: 14px;
    line-height: 1.65;
    color: var(--text-muted);
}

.rules-note strong { color: var(--text-primary); }

.rules-footer {
    margin-top: 36px;
    padding-top: 30px;
    border-top: 1px solid var(--border-subtle);
    text-align: center;
}

.rules-footer p {
    font-size: 14.5px;
    color: var(--text-muted);
}

.rules-footer a {
    color: var(--accent);
    text-decoration: none;
    font-weight: 600;
}

.rules-footer a:hover { text-decoration: underline; }

@media (max-width: 640px) {
    .rules-card { padding: 26px 22px; }
}

/* === EVENT PACKAGES (bookevent) === */
.event-packages {
    max-width: 900px;
    margin: 0 auto;
}

.package-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
}

.package-card {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    padding: 32px 30px;
}

.package-card h2 {
    font-family: var(--font-serif);
    font-size: 1.3rem;
    color: var(--text-primary);
    margin-bottom: 20px;
}

.package-list {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.package-list li {
    display: flex;
    gap: 12px;
    font-size: 15px;
    color: var(--text-muted);
    line-height: 1.6;
}

.package-list i {
    color: var(--accent);
    font-size: 12px;
    margin-top: 6px;
}

.package-cta {
    text-align: center;
    margin-top: 44px;
    padding-top: 38px;
    border-top: 1px solid var(--border-subtle);
}

.package-cta p {
    max-width: 620px;
    margin: 0 auto 22px;
    font-size: 15px;
    line-height: 1.7;
    color: var(--text-muted);
}

@media (max-width: 900px) {
    .package-grid { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
    .package-cta .btn { width: 100%; font-size: 12px; }
}

/* === MEMBERSHIP FORM DOWNLOAD (becomeamember) === */
.member-join {
    max-width: 820px;
    margin: 0 auto;
}

.form-download {
    display: flex;
    align-items: center;
    gap: 24px;
    flex-wrap: wrap;
    padding: 28px 32px;
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
}

.form-download-icon {
    font-size: 2rem;
    color: var(--accent);
    line-height: 1;
}

.form-download-body {
    flex: 1;
    min-width: 220px;
}

.form-download-body h3 {
    font-family: var(--font-serif);
    font-size: 1.25rem;
    color: var(--text-primary);
    margin-bottom: 6px;
}

.form-download-body p {
    font-size: 14px;
    color: var(--text-muted);
    line-height: 1.6;
}

.form-download-btn { white-space: nowrap; }

.form-return {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 32px;
    margin-top: 44px;
}

.form-return-item {
    display: flex;
    gap: 14px;
}

.form-return-item i {
    color: var(--accent);
    font-size: 15px;
    margin-top: 4px;
}

.form-return-item h4 {
    font-family: var(--font-sans);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-primary);
    margin-bottom: 8px;
}

.form-return-item p,
.form-return-item a {
    font-size: 14px;
    line-height: 1.7;
    color: var(--text-muted);
    text-decoration: none;
}

.form-return-item a:hover { color: var(--accent); }

@media (max-width: 900px) {
    .form-return { grid-template-columns: 1fr; gap: 26px; }
}

@media (max-width: 640px) {
    .form-download { padding: 24px 22px; }
    .form-download-btn { width: 100%; text-align: center; }
}

/* === SUBPAGE LAYOUT === */
.page-header {
    padding: 140px 0 60px;
    background: var(--bg-surface);
    border-bottom: 1px solid var(--border-subtle);
    position: relative;
    z-index: 1;
}

.page-header h1 {
    font-size: clamp(2.2rem, 5vw, 3.5rem);
    color: var(--text-primary);
    margin-top: 8px;
}

.page-header-sub {
    margin-top: 14px;
    font-size: 1rem;
    color: var(--text-muted);
    max-width: 600px;
    line-height: 1.6;
}

/* A tagline line above .page-header-sub, for headers that open with a short pitch before
   the explanation. Heavier and in the primary colour so it reads as a statement rather
   than a first sentence of the paragraph under it. */
.page-header-lead {
    margin-top: 16px;
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--text-primary);
    max-width: 600px;
    line-height: 1.5;
}

/* The lead already supplies the gap under the h1, so the paragraph following it only
   needs the smaller space between the two. */
.page-header-lead + .page-header-sub { margin-top: 10px; }

.page-header-actions { margin-top: 28px; }

.page-content {
    padding: 80px 0;
    position: relative;
    z-index: 1;
    min-height: 40vh;
}

/* === NESTED (SUB) DROPDOWN === */
.nav-subdropdown > a {
    display: flex !important;
    justify-content: space-between;
    align-items: center;
}

.nav-chevron-sub {
    font-size: 10px;
    color: var(--text-muted);
    flex-shrink: 0;
    margin-left: 8px;
}

.dropdown-submenu {
    left: 100% !important;
    top: 0 !important;
    transform: none !important;
    padding-top: 0 !important;
    padding-left: 6px;
}

.dropdown-submenu::before {
    inset: 0 0 0 6px !important;
}

@media (hover: hover) and (min-width: 641px) {
    .nav-subdropdown:hover > .dropdown-submenu {
        display: block;
    }
    .nav-subdropdown:hover .nav-chevron-sub {
        color: var(--accent);
    }
}

/* === SCORECARD === */

.hole-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
}

.hole-card {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 8px;
    overflow: hidden;
}


.hole-card-body {
    padding: 22px 24px 24px;
}

.hole-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--border-subtle);
    margin-bottom: 16px;
}

.hole-number {
    font-family: var(--font-serif);
    font-size: 2rem;
    font-weight: 700;
    color: var(--accent);
    line-height: 1;
}

.hole-par {
    font-family: var(--font-sans);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.hole-yardages {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 14px;
}

.hole-yardages li {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 14px;
    color: var(--text-muted);
}

.tee-label {
    display: flex;
    align-items: center;
    gap: 7px;
}

.tee-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex-shrink: 0;
}

.tee-dot--black  { background: #1a1a1a; border: 1px solid var(--border-subtle); }
.tee-dot--white  { background: #d8dce4; border: 1px solid var(--border-subtle); }
.tee-dot--orange { background: #CA3F00; }

.yardage-val {
    font-family: var(--font-serif);
    font-weight: 600;
    color: var(--accent);
    font-size: 15px;
}

.hole-hdcp-grid {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 5px 12px;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--border-subtle);
    font-size: 12px;
    color: var(--text-muted);
    font-style: italic;
}
.hole-hdcp-val {
    font-family: var(--font-serif);
    font-style: normal;
    font-weight: 600;
    color: var(--accent);
    font-size: 13px;
    text-align: right;
}

.tee-rating-table {
    display: inline-grid;
    grid-template-columns: auto repeat(3, 80px);
    gap: 8px 0;
    margin-top: 28px;
    font-family: var(--font-sans);
    font-size: 13px;
    color: var(--text-dim);
}
.tee-rating-table .trt-head {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-faint);
    text-align: center;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--overlay-medium);
}
.tee-rating-table .trt-head:first-child { text-align: left; }
.tee-rating-table .trt-tee {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-right: 24px;
    color: var(--text-primary);
}
.tee-rating-table .trt-val {
    text-align: center;
    font-family: var(--font-serif);
    font-weight: 600;
    color: var(--text-primary);
    font-size: 14px;
}

/* === ANNOUNCEMENTS === */
.announce-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0;
}
.announce-card {
    display: flex;
    gap: 40px;
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--border-subtle);
    border-radius: 0;
    padding: 32px 0;
    transition: color 0.2s;
}
.announce-card:first-child {
    border-top: 1px solid var(--border-subtle);
}
.announce-card:hover { border-color: var(--border-subtle); }
.announce-card:hover .announce-body p { color: var(--text-primary); }
.announce-date {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: 52px;
    padding-top: 2px;
}
.announce-month {
    font-family: var(--font-sans);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--accent);
}
.announce-day {
    font-family: var(--font-serif);
    font-size: 2.2rem;
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1.1;
}
.announce-body {
    flex: 1;
    min-width: 0;
}
.announce-body p {
    font-size: 14px;
    color: var(--text-muted);
    line-height: 1.65;
    margin-bottom: 14px;
    transition: color 0.2s;
}
/* Long Facebook posts render in full but stay clamped until pressed. */
.announce-text { white-space: pre-line; }
.announce-text.is-clamped {
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.announce-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 18px;
}
.announce-link,
.announce-toggle {
    font-size: 13px;
    font-weight: 500;
    color: var(--accent);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.announce-toggle {
    font-family: inherit;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
}
.announce-link:hover,
.announce-toggle:hover { text-decoration: underline; }
.announce-card:has(.announce-toggle:not([hidden])) .announce-text.is-clamped { cursor: pointer; }

.announce-thumb {
    width: 72px;
    height: 72px;
    border-radius: 8px;
    object-fit: cover;
    flex-shrink: 0;
    align-self: center;
    cursor: pointer;
    transition: opacity 0.2s;
}

.announce-thumb-button {
    display: block;
    flex-shrink: 0;
    align-self: center;
    padding: 0;
    border: 0;
    border-radius: 8px;
    background: none;
    cursor: pointer;
}

.announce-thumb-button:focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 3px;
}

.announcements-section {
    padding: 140px 0;
    position: relative;
    z-index: 1;
}
.announcements-section .announce-col {
    max-width: 820px;
    margin: 0 auto;
}
/* The Facebook button belongs to the header, so it sits close under the
   subtitle and the larger gap falls between it and the posts — the section-wide
   80px header margin put the big gap in the middle of that group instead. */
.announcements-section .section-header { margin-bottom: 36px; }
.announcements-section .events-footer { margin-bottom: 64px; }
.about-course { padding: 24px 0 64px; }

.announce-thumbs {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 8px;
    max-width: 152px;
    flex-shrink: 0;
    align-self: center;
}

.announce-thumb:hover { opacity: 0.85; }

@media (max-width: 640px) {
    /* Desktop's 140px top/bottom padding is meant to balance a section sitting between
       other full-size sections — on mobile it's stacked directly under a near-full-height
       hero, which reads as a big empty gap rather than intentional breathing room. */
    .announcements-section { padding: 64px 0; }
    .announce-card { gap: 18px; }
    .announce-thumb { width: 52px; height: 52px; }
}

.announce-lightbox {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.88);
    z-index: 2000;
    align-items: center;
    justify-content: center;
    /* Padding reserves the gutter the controls sit in. They hang outside the photo, so the
       image has to be inset far enough that they still land on screen: 60px clears a 44px
       arrow plus its gap, 64px clears the 40px close button above the top edge. */
    padding: 64px 60px;
}
.announce-lightbox.open { display: flex; }

/* Shrink-wraps the image so the close and next/prev buttons can be anchored to the photo
   instead of the screen edges — on a tall portrait shot the old fixed buttons sat far out
   in the empty backdrop. Keeping it fit-content is what makes that work: the stage box is
   exactly the rendered image, so a negative offset lands just outside the picture. */
.announce-lightbox-stage {
    position: relative;
    width: fit-content;
    /* The display cap lives here rather than on the image. On the image it was written as
       min(640px, 100%), and a percentage is indefinite while the browser works out the
       shrink-to-fit width — so the cap was ignored and the stage sized to the photo's full
       intrinsic width, leaving the buttons stranded out in the backdrop. */
    max-width: min(640px, 100%);
    margin: auto;
    line-height: 0;   /* no inline-image descender gap under the photo */
}

.announce-lightbox-img {
    display: block;
    max-width: 100%;
    /* Leaves room for the overlay's vertical padding plus the close button above the photo,
       so a tall image can't push the controls off the top or bottom of the screen. */
    max-height: calc(100vh - 150px);
    width: auto;
    height: auto;
    border-radius: 6px;
    box-shadow: 0 24px 80px rgba(0,0,0,0.6);
    cursor: zoom-in;
}

/* Tap/click the image to view it at full size (text in a posted results table, etc. can be
   too small to read at the default fit-to-screen size) — scrollable rather than centered,
   since centering a flex item bigger than its container clips the far side unreachably. */
.announce-lightbox.is-zoomed {
    align-items: flex-start;
    justify-content: flex-start;
    overflow: auto;
    padding: 12px;
}
.announce-lightbox.is-zoomed .announce-lightbox-img {
    max-width: none;
    max-height: none;
    cursor: zoom-out;
    margin: auto;
}
/* Negative offsets put the controls in the gutter just outside the photo rather than over
   it, so nothing in the picture is covered. The overlay's padding is sized to match. */
.announce-lightbox-close {
    position: absolute;
    top: -50px;
    right: 0;
    width: 40px;
    height: 40px;
    background: var(--btn-fill);
    color: #fff;
    border: none;
    border-radius: 50%;
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2001;
    box-shadow: 0 2px 12px rgba(0,0,0,0.5);
    transition: background 0.2s;
}
.announce-lightbox-close:hover { background: var(--accent-active); }
.announce-lightbox-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 44px;
    height: 44px;
    border: 0;
    border-radius: 50%;
    /* Nearly solid rather than a light wash: on phones these sit over the photo itself, so
       they have to hold up against whatever is behind them. */
    background: rgba(0, 0, 0, 0.78);
    color: #fff;
    cursor: pointer;
    font-size: 18px;
    z-index: 2001;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.5);
}
.announce-lightbox-prev { left: -52px; }
.announce-lightbox-next { right: -52px; }
.announce-lightbox-nav:hover { background: var(--btn-fill); }
/* On a phone there isn't width to spare for side gutters — reserving them cost the photo
   ~50px. The arrows go back over the image here and the padding drops to 16px, so the
   picture gets the full screen width. They stay outside on desktop, where there is room.
   The close button keeps its spot above the photo: that costs vertical space, which a
   phone has plenty of, and none of the width. */
@media (max-width: 640px) {
    .announce-lightbox { padding: 58px 16px; }
    .announce-lightbox-nav { width: 38px; height: 38px; }
    .announce-lightbox-prev { left: 10px; }
    .announce-lightbox-next { right: 10px; }
    .announce-lightbox-close { top: -46px; }
}

/* Zoomed, the image is deliberately larger than the screen and the overlay scrolls, so a
   control pinned to the photo's corner would sit somewhere off-screen. Pin them back to the
   viewport for that state only, so there is always a reachable way out. */
.announce-lightbox.is-zoomed .announce-lightbox-stage { max-width: none; }
.announce-lightbox.is-zoomed .announce-lightbox-close {
    position: fixed;
    top: 16px;
    right: 20px;
}
.announce-lightbox.is-zoomed .announce-lightbox-nav { position: fixed; }
.announce-lightbox.is-zoomed .announce-lightbox-prev { left: 18px; }
.announce-lightbox.is-zoomed .announce-lightbox-next { right: 18px; }

/* === REVIEWS === */
.reviews-stars-display {
    display: flex;
    gap: 4px;
    font-size: 20px;
    color: var(--accent);
}

.reviews-count {
    font-size: 12px;
    letter-spacing: 0.1em;
    color: var(--text-muted);
    text-transform: uppercase;
}

.reviews-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0;
    border-top: 1px solid var(--border-subtle);
    border-left: 1px solid var(--border-subtle);
}

.review-card {
    border-right: 1px solid var(--border-subtle);
    border-bottom: 1px solid var(--border-subtle);
    padding: 40px 40px;
    transition: background 0.2s;
}

.review-card:hover {
    background: var(--overlay-faint);
}

.review-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: 16px;
    gap: 16px;
}

.review-meta {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.review-author {
    font-family: var(--font-serif);
    font-size: 16px;
    font-weight: 600;
    color: var(--text-primary);
}

.review-date {
    font-size: 12px;
    color: var(--text-muted);
    letter-spacing: 0.06em;
}

.review-stars {
    display: flex;
    gap: 3px;
    font-size: 13px;
    color: var(--accent);
    flex-shrink: 0;
}

.review-text {
    font-size: 14.5px;
    color: var(--text-muted);
    line-height: 1.72;
}

.rating-summary {
    display: flex;
    align-items: center;
    gap: 20px;
    padding-bottom: 48px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--border-subtle);
}

.rating-avg-number {
    font-family: var(--font-serif);
    font-size: 3.6rem;
    font-weight: 700;
    color: var(--accent);
    line-height: 1;
}

.reviews-loading,
.reviews-empty {
    grid-column: 1 / -1;
    padding: 60px 0;
    text-align: center;
    color: var(--text-muted);
    font-size: 15px;
}

.review-success {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 24px 28px;
    border: 1px solid var(--accent-border);
    border-radius: 6px;
    background: var(--accent-dim);
    color: var(--text-primary);
    font-size: 15px;
    max-width: 780px;
    margin: 0 auto;
}

.review-success i {
    font-size: 24px;
    color: var(--accent);
    flex-shrink: 0;
}

.review-success a {
    color: var(--accent);
    text-decoration: underline;
}

/* Submit Review Section */
/* This section sits outside <main class="page-content">, so it needs its own stacking
   context the way .page-content, .hero and .announcements-section each have one. Without
   it, body::before (position: fixed; z-index: 0) paints its "+" motif ON TOP of everything
   here — positioned elements paint above non-positioned in-flow content — and the form
   fields look see-through even though their own background is opaque. */
.submit-review-section {
    padding: 120px 0;
    border-top: 1px solid var(--border-subtle);
    margin-top: 0;
    position: relative;
    z-index: 1;
}

.review-form {
    max-width: 780px;
    margin: 0 auto;
}

#reviewFields {
    display: flex;
    flex-direction: column;
    gap: 40px;
}

/* Star Picker */
.star-picker {
    display: flex;
    gap: 6px;
    padding: 10px 0 4px;
}

.star-btn {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 28px;
    color: var(--overlay-strong);
    padding: 0 2px;
    line-height: 1;
    transition: color 0.15s, transform 0.15s;
}

.star-btn:hover,
.star-btn.hovered,
.star-btn.selected {
    color: var(--accent);
}

.star-btn:hover {
    transform: scale(1.15);
}

@media (max-width: 900px) {
    .reviews-grid { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
    .review-card { padding: 28px 20px; }
    .review-header { flex-direction: column; gap: 8px; }
}

/* === SCORECARD MODAL === */
.scorecard-modal {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.88);
    z-index: 2000;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.scorecard-modal.open { display: flex; }
.scorecard-modal-inner {
    position: relative;
    max-width: min(860px, 100%);
    max-height: 90vh;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 2px;
    border-radius: 6px;
    box-shadow: 0 24px 80px rgba(0,0,0,0.6);
}
.scorecard-modal-img {
    display: block;
    width: 100%;
    height: auto;
}
.scorecard-modal-close {
    position: fixed;
    top: 16px;
    right: 20px;
    width: 40px;
    height: 40px;
    background: var(--btn-fill);
    color: #fff;
    border: none;
    border-radius: 50%;
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2001;
    box-shadow: 0 2px 12px rgba(0,0,0,0.5);
    transition: background 0.2s;
}
.scorecard-modal-close:hover { background: var(--accent-active); }

/* Same fixed treatment as the close button, opposite corner. A pill rather than a circle
   because it carries a label, and the label is what makes the PDF discoverable at all. */
.scorecard-modal-download {
    position: fixed;
    top: 16px;
    left: 20px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 40px;
    padding: 0 18px;
    background: var(--btn-fill);
    color: #fff;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    text-decoration: none;
    z-index: 2001;
    box-shadow: 0 2px 12px rgba(0,0,0,0.5);
    transition: background 0.2s;
}

.scorecard-modal-download:hover { background: var(--accent-active); color: #fff; }

@media (max-width: 640px) {
    .scorecard-modal-download {
        left: 16px;
        padding: 0 14px;
        font-size: 11px;
        letter-spacing: 0.06em;
    }
}

/* === TOURNAMENTS CALENDAR === */
.cal-header {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 24px;
    margin-bottom: 8px;
}

.cal-month-label {
    font-size: 1.6rem;
    color: var(--text-primary);
    min-width: 220px;
    text-align: center;
}

.cal-nav {
    background: var(--bg-card);
    border: 1px solid var(--border-strong);
    color: var(--text-primary);
    width: 40px;
    height: 40px;
    border-radius: 50%;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: border-color 0.2s, color 0.2s;
}

.cal-nav:hover {
    border-color: var(--accent);
    color: var(--accent);
}

.cal-legend {
    display: flex;
    justify-content: center;
    gap: 28px;
    margin: 20px 0 36px;
    flex-wrap: wrap;
}

.cal-legend-item {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12.5px;
    color: var(--text-muted);
}

.cal-legend-item i {
    color: var(--accent);
    font-size: 12px;
    width: 14px;
    text-align: center;
}

/* Course Calendar category colours. Each class sets three custom properties — the accent
   itself plus a soft fill and a border tint — rather than deriving them at paint time, so
   the chips work without color-mix() support. Applied to event chips, day-modal rows, and
   legend swatches alike, which is what makes a category recognisable at a glance. */
/* --ev-on is the text colour for League's solid chip (see below); the other categories
   keep their tinted fill and inherit the normal text colour. */
/* --ev paints bars, borders, badges and icons. --ev-text is a separate, contrast-corrected
   variant used wherever the category colour becomes readable text: several of these vivid
   hexes fall below WCAG AA (4.5:1) at body size — #4285f4 on white is only 3.56:1 — and
   the shift has to flip direction between themes. */
.cal-ev--league        { --ev: #000000; --ev-soft: rgba(0, 0, 0, 0.10);       --ev-line: rgba(0, 0, 0, 0.38); --ev-on: #ffffff; --ev-text: #000000; }
.cal-ev--private       { --ev: #d81b60; --ev-soft: rgba(216, 27, 96, 0.12);   --ev-line: rgba(216, 27, 96, 0.45);  --ev-text: #c2185b; }
.cal-ev--highschool    { --ev: #f6bf26; --ev-soft: rgba(246, 191, 38, 0.16);  --ev-line: rgba(246, 191, 38, 0.55); --ev-text: #7a5c00; }
.cal-ev--shotguns      { --ev: #0b8043; --ev-soft: rgba(11, 128, 67, 0.12);   --ev-line: rgba(11, 128, 67, 0.45);  --ev-text: #0b8043; }
.cal-ev--playanytime   { --ev: #4285f4; --ev-soft: rgba(66, 133, 244, 0.12);  --ev-line: rgba(66, 133, 244, 0.45); --ev-text: #1a5fbf; }
.cal-ev--girls         { --ev: #b8923f; --ev-soft: rgba(184, 146, 63, 0.14);  --ev-line: rgba(184, 146, 63, 0.45); --ev-text: #7d6120; }
.cal-ev--boys          { --ev: #4a6f8a; --ev-soft: rgba(74, 111, 138, 0.14);  --ev-line: rgba(74, 111, 138, 0.45); --ev-text: #3b5a72; }
.cal-ev--girlsboys     { --ev: #8b3a52; --ev-soft: rgba(139, 58, 82, 0.14);   --ev-line: rgba(139, 58, 82, 0.45);  --ev-text: #8b3a52; }
.cal-ev--other         { --ev: var(--text-muted); --ev-soft: var(--overlay-faint); --ev-line: var(--border-subtle); --ev-text: var(--text-muted); }

[data-theme="dark"] .cal-ev--private     { --ev-text: #f48fb1; }
[data-theme="dark"] .cal-ev--highschool  { --ev-text: #f6bf26; }
[data-theme="dark"] .cal-ev--shotguns    { --ev-text: #5cbe86; }
[data-theme="dark"] .cal-ev--playanytime { --ev-text: #8ab4f8; }
[data-theme="dark"] .cal-ev--girls       { --ev-text: #d9b465; }
[data-theme="dark"] .cal-ev--boys        { --ev-text: #9fc2d9; }
[data-theme="dark"] .cal-ev--girlsboys   { --ev-text: #dd93a8; }

/* Pure black disappears against the dark theme's near-black page, so League flips to a
   light neutral there. The other four have enough luminance to read either way. */
[data-theme="dark"] .cal-ev--league { --ev: #cdd3c9; --ev-soft: rgba(205, 211, 201, 0.12); --ev-line: rgba(205, 211, 201, 0.42); --ev-on: #12180f; }

.cal-event[class*="cal-ev--"] {
    background: var(--ev-soft);
    border-color: var(--ev-line);
}

.cal-event[class*="cal-ev--"] i { color: var(--ev); }

.cal-event[class*="cal-ev--"]:hover {
    background: var(--ev-soft);
    border-color: var(--ev);
}

/* League is the one category whose colour has no hue to carry a tint — 10% black on a cream
   page just reads as grey. It gets a solid fill instead, which is the only way a neutral
   competes with the saturated categories. Must follow the generic rules above: same
   specificity, so source order decides. */
.cal-event.cal-ev--league,
.cal-event.cal-ev--league:hover {
    background: var(--ev);
    border-color: var(--ev);
    color: var(--ev-on);
}

.cal-event.cal-ev--league i { color: var(--ev-on); }

.cal-legend-item[class*="cal-ev--"] i { color: var(--ev); }

/* Day-modal rows carry the category as a colour bar down their leading edge. */
.tourney-modal-list-item[class*="cal-ev--"] {
    border-left: 4px solid var(--ev);
}

.cal-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 1px;
    background: var(--border-subtle);
    border: 1px solid var(--border-subtle);
    border-radius: 8px;
    overflow: hidden;
}

/* The 1px gaps are painted by this element's own background. --border-subtle is only
   7% white in dark mode, which all but erases the gridlines against near-black cells. */
[data-theme="dark"] .cal-grid {
    background: rgba(255, 255, 255, 0.13);
    border-color: rgba(255, 255, 255, 0.13);
}

.cal-weekday {
    background: var(--bg-surface);
    color: var(--text-muted);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    text-align: center;
    padding: 12px 4px;
}

.cal-day {
    background: var(--bg-card);
    min-height: 108px;
    padding: 8px 6px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

/* Opaque, not a translucent overlay: the page behind the grid carries a repeating motif,
   and any see-through cell fill lets it show inside the calendar as speckle. */
.cal-day--outside {
    background: var(--bg-surface);
}

.cal-day--outside .cal-day-num {
    color: var(--text-faint);
}

/* Same reason — the accent tint is layered over an opaque card rather than replacing it,
   so today's cell doesn't become a window onto the page pattern. */
.cal-day--today {
    background: linear-gradient(var(--accent-dim), var(--accent-dim)), var(--bg-card);
}

.cal-day-num {
    font-family: var(--font-serif);
    font-size: 13px;
    font-weight: 600;
    color: var(--text-muted);
    padding: 0 2px;
}

.cal-day--today .cal-day-num {
    color: var(--accent);
}

.cal-day-events {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.cal-event {
    display: flex;
    align-items: flex-start;
    gap: 5px;
    background: var(--accent-dim);
    border: 1px solid var(--accent-border);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 10.5px;
    text-align: left;
    padding: 4px 6px;
    border-radius: 4px;
    cursor: pointer;
    line-height: 1.3;
    transition: background 0.15s, border-color 0.15s;
    white-space: normal;
    word-break: break-word;
}

.cal-event i {
    color: var(--accent);
    font-size: 9px;
    flex-shrink: 0;
    margin-top: 2px;
}

.cal-event:hover {
    background: var(--accent-dim-strong);
    border-color: var(--accent);
}

.cal-event-more {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 10.5px;
    text-align: left;
    padding: 2px 6px;
    cursor: pointer;
    text-decoration: underline;
}

.cal-event-more:hover {
    color: var(--accent);
}

/* === TOURNAMENT DETAILS MODAL === */
.tourney-modal {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.88);
    z-index: 2000;
    align-items: center;
    justify-content: center;
    padding: 24px;
    /* Without this, a touch-scroll that reaches the backdrop's edge (there's nothing to
       scroll here) chains through to the page underneath instead of just stopping. */
    overscroll-behavior: contain;
}

.tourney-modal.open {
    display: flex;
}

/* .tourney-modal-card is the visible card: fixed in place, never scrolls. Its child
   .tourney-modal-inner holds the actual content and scrolls internally when that content
   is taller than the card — which keeps .tourney-modal-close (a sibling, not a descendant
   of .tourney-modal-inner) pinned at the card's corner regardless of scroll position,
   instead of scrolling out of view with the content beneath it. */
.tourney-modal-card {
    position: relative;
    max-width: 540px;
    width: 100%;
    max-height: 85vh;
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    box-shadow: 0 24px 80px rgba(0, 0, 0, 0.6);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.tourney-modal-inner {
    /* Overrides flex items' default min-height:auto, which would otherwise let this grow
       past its flex parent's max-height instead of scrolling internally. */
    min-height: 0;
    overflow-y: auto;
    /* Stops scrolling this element, once it hits its top/bottom, from chaining into a
       scroll of the page behind the modal — the exact symptom being fixed here. */
    overscroll-behavior-y: contain;
    padding: 44px 36px 36px;
}

.tourney-modal-close {
    position: absolute;
    top: 14px;
    right: 14px;
    width: 36px;
    height: 36px;
    background: var(--btn-fill);
    color: #fff;
    border: none;
    border-radius: 50%;
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s;
    z-index: 1;
}

.tourney-modal-close:hover {
    background: var(--accent-active);
}

.tourney-modal-type {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--accent);
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    gap: 6px;
}

.tourney-modal-inner h3 {
    font-family: var(--font-serif);
    font-size: 1.5rem;
    color: var(--text-primary);
    margin-bottom: 10px;
}

.tourney-modal-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-top: 14px;
}

.tourney-modal-list-item {
    background: var(--overlay-faint);
    border: 1px solid var(--border-subtle);
    border-radius: 6px;
    padding: 12px 16px;
    text-align: left;
    color: var(--text-primary);
    font-size: 14px;
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s;
}

.tourney-modal-list-item:hover {
    border-color: var(--accent);
    background: var(--accent-dim);
}

/* Pill shape, lift and shine sweep to match the site's primary buttons. Styled here rather
   than by adding .btn.btn-pill in markup, because this button is generated inside three
   separate pages' modals. The filled treatment is what makes the sweep work: the highlight
   is white, which needs a saturated fill behind it to read at all. */
.add-to-calendar-btn {
    position: relative;
    display: flex;
    width: fit-content;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: 18px;
    min-height: 44px;
    padding: 10px 24px;
    overflow: hidden;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0) 48%), var(--btn-fill);
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 999px;
    box-shadow: 0 8px 28px var(--accent-shadow), inset 0 1px 0 rgba(255, 255, 255, 0.22);
    color: #fff;
    font-family: var(--font-sans);
    font-size: 13.5px;
    font-weight: 600;
    /* This style started life on the Add to Calendar <button> and is now reused for
       "View Results" <a> links too. There is no global anchor reset, so without this the
       link renders underlined inside the pill. .btn carries the same declaration. */
    text-decoration: none;
    cursor: pointer;
    transition: background 0.2s ease, border-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}

.add-to-calendar-btn::after {
    content: '';
    position: absolute;
    top: 0;
    left: -130%;
    width: 60%;
    height: 100%;
    background: linear-gradient(105deg, transparent, rgba(255, 255, 255, .28), transparent);
    transform: skewX(-20deg);
    pointer-events: none;
    transition: left .55s ease;
}

.add-to-calendar-btn:hover {
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0) 48%), var(--btn-fill-hover);
    border-color: rgba(255, 255, 255, 0.26);
    transform: translateY(-2px);
    box-shadow: 0 10px 32px var(--accent-shadow), inset 0 1px 0 rgba(255, 255, 255, 0.26);
}

.add-to-calendar-btn:hover::after { left: 170%; }
.add-to-calendar-btn:active { transform: translateY(0) scale(.97); }

.add-to-calendar-btn i {
    font-size: 12px;
}

.tourney-format-tag {
    font-family: var(--font-sans);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--accent);
    background: var(--accent-dim);
    border: 1px solid var(--accent-border);
    padding: 3px 10px;
    border-radius: 20px;
}

/* --accent is intentionally muted in dark mode, which is too low-contrast for the
   small format tag text against its tinted fill. */
[data-theme="dark"] .tourney-format-tag { color: #c6e7ce; }

.tourney-date-range {
    font-size: 13.5px;
    color: var(--text-muted);
    margin-bottom: 10px;
}

.tourney-info {
    font-size: 14.5px;
    color: var(--text-muted);
    line-height: 1.62;
    margin-bottom: 14px;
}

/* Emails, phone numbers and web addresses inside an event description, linked by
   linkifyText() in public/csv-utils.js. Underlined as well as coloured: these sit inside a
   paragraph, where colour alone is not a reliable signal that something is clickable. */
.tourney-info a,
.tourney-featured-info a {
    color: var(--accent);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.tourney-info a:hover,
.tourney-featured-info a:hover { color: var(--accent-active); }

[data-theme="dark"] .tourney-info a:hover,
[data-theme="dark"] .tourney-featured-info a:hover { color: var(--text-primary); }

.tourney-links {
    display: flex;
    gap: 20px;
    flex-wrap: wrap;
    /* Matches the pill buttons' own top margin. Without it this row butts straight up
       against an Add to Calendar / View Results pill rendered above it, and the pill's
       drop shadow bleeds over the link text. */
    margin-top: 18px;
}

.tourney-link {
    font-size: 13px;
    font-weight: 500;
    color: var(--accent);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.tourney-link:hover { text-decoration: underline; }
.tourney-link i { font-size: 11px; }

/* === RECENT NEWS POPUP === */
/* The list below scrolls internally. On a phone the scrollbar is an overlay that only
   appears once you are already scrolling, so a long popup looked like it simply ended
   mid-sentence. This fade sits over the last stretch of the list and switches off the
   moment it is scrolled to the bottom — see syncNewsScrollHint() in index.html. */
.news-scroll {
    position: relative;
}

.news-scroll-hint {
    position: absolute;
    left: 0;
    right: 6px;   /* clears .news-list's own scrollbar gutter */
    bottom: 0;
    height: 52px;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding-bottom: 4px;
    background: linear-gradient(to bottom, rgba(0, 0, 0, 0), var(--bg-card) 72%);
    color: var(--accent);
    font-size: 13px;
    opacity: 0;
    /* Never intercepts a tap or a scroll gesture — it is a hint, not a control. */
    pointer-events: none;
    transition: opacity 0.18s ease;
}

.news-scroll.has-more .news-scroll-hint { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
    .news-scroll-hint { transition: none; }
}

.news-list {
    list-style: none;
    margin: 18px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 14px;
    /* Scrolls internally once the list gets long, instead of growing the modal past a
       comfortable height — the heading and close button above stay put either way. */
    max-height: min(50vh, 420px);
    overflow-y: auto;
    padding-right: 6px;
}

.news-item {
    position: relative;
    padding-left: 20px;
    color: var(--text-primary);
    font-size: 14.5px;
    line-height: 1.55;
}

.news-item::before {
    content: '';
    position: absolute;
    left: 0;
    top: 9px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--btn-fill);
}

.news-item--important::before {
    content: '★';
    top: 0;
    left: -1px;
    width: auto;
    height: auto;
    border-radius: 0;
    background: none;
    color: var(--accent);
    font-size: 15px;
    line-height: 1;
}

.news-item-title {
    display: block;
    font-family: var(--font-sans);
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 2px;
}

.news-item-text { display: block; }

/* Pipe-separated tail of a news row (see newsBody() in index.html). Indented past the
   news item's own bullet dot so the two levels don't sit on the same axis. */
.news-item-bullets {
    list-style: none;
    margin: 8px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.news-item-bullets li {
    position: relative;
    padding-left: 16px;
    font-size: 13.5px;
    color: var(--text-muted);
    line-height: 1.5;
}

.news-item-bullets li::before {
    content: '';
    position: absolute;
    left: 3px;
    top: 8px;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--btn-fill);
    opacity: 0.75;
}

.news-item-link {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-top: 6px;
    color: var(--accent);
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
}

.news-item-link:hover { text-decoration: underline; }
.news-item-link i { font-size: 10px; }

.news-league-block {
    margin-top: 6px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.news-league-row {
    font-size: 13px;
    color: var(--text-muted);
    line-height: 1.5;
}

.news-league-row strong {
    color: var(--text-primary);
    font-weight: 600;
}

.news-league-label {
    font-family: var(--font-sans);
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-primary);
    margin: 4px 0 2px;
}

.news-league-list {
    margin: 0;
    padding-left: 18px;
    font-size: 13px;
    color: var(--text-muted);
    line-height: 1.55;
}

.news-league-list li { break-inside: avoid; }

.news-league-list--cols {
    columns: 2;
    column-gap: 16px;
}

.news-fab {
    position: fixed;
    right: 24px;
    bottom: 24px;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: var(--btn-fill);
    color: #fff;
    border: none;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
    font-size: 19px;
    cursor: pointer;
    z-index: 900;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s, transform 0.2s;
}

.news-fab[hidden] { display: none; }

.news-fab:hover {
    background: var(--accent-active);
    transform: translateY(-2px);
}

@media (max-width: 640px) {
    .news-fab {
        right: 16px;
        bottom: 16px;
        width: 46px;
        height: 46px;
        font-size: 17px;
    }
}

.tourney-loading,
.tourney-empty {
    padding: 60px 0;
    text-align: center;
    color: var(--text-muted);
    font-size: 15px;
}

/* === TEE TIMES === */
.teetime-datebar {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    margin-bottom: 32px;
}

.teetime-date-input {
    font-family: var(--font-sans);
    /* 16px avoids iOS Safari's auto-zoom-on-focus (see .form-group input above). */
    font-size: 16px;
    padding: 10px 14px;
    border-radius: 8px;
    border: 1px solid var(--border-strong);
    background: var(--bg-card);
    color: var(--text-primary);
}

.teetime-filterbar {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    margin-bottom: 28px;
}

.teetime-filter-label {
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: var(--font-sans);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.teetime-filter-select {
    font-family: var(--font-sans);
    /* 16px avoids iOS Safari's auto-zoom-on-focus (see .form-group input above). */
    font-size: 16px;
    padding: 8px 12px;
    border-radius: 8px;
    border: 1px solid var(--border-strong);
    background: var(--bg-card);
    color: var(--text-primary);
}

/* Sits between the filters and the list, because it sets expectations about the times a
   golfer is about to pick from — it belongs next to them rather than up in the page header. */
.teetime-note {
    max-width: 560px;
    margin: 0 auto 22px;
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--text-muted);
    text-align: center;
}

.teetime-note i {
    color: var(--accent);
    margin-right: 6px;
}

.teetime-note a {
    color: var(--accent);
    font-weight: 600;
    text-decoration: none;
}

.teetime-note a:hover { text-decoration: underline; }

/* The same warning as the page's note, restated inside the booking modal — this is the
   moment someone commits, and by then the note above has scrolled out of sight. Left
   aligned and boxed rather than centred like .teetime-note: it sits above form fields
   here, not between page sections. */
.teetime-modal-note {
    display: flex;
    gap: 9px;
    margin: 14px 0 20px;
    padding: 11px 13px;
    background: var(--accent-dim);
    border-left: 3px solid var(--accent);
    border-radius: 6px;
    font-size: 13px;
    line-height: 1.55;
    color: var(--text-primary);
}

.teetime-modal-note i {
    color: var(--accent);
    margin-top: 3px;
    flex: none;
}

/* Player-count filter: the same picker language as the booking modal's .players-option,
   but round and a touch smaller, since here it filters the list rather than entering a value. */
.teetime-filter-options {
    display: flex;
    gap: 8px;
}

.teetime-filter-option {
    width: 40px;
    height: 40px;
    flex: 0 0 auto;
    border-radius: 50%;
    border: 1px solid var(--border-strong);
    background: var(--bg-card);
    color: var(--text-primary);
    font-family: var(--font-serif);
    font-size: 1.05rem;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s, color 0.15s;
}

.teetime-filter-option--any {
    font-family: var(--font-sans);
    font-size: 12px;
    font-weight: 600;
}

.teetime-filter-option:hover { border-color: var(--accent); }

.teetime-filter-option--selected {
    border-color: var(--accent);
    background: var(--btn-fill);
    color: #fff;
}

/* Staff tools benefit from a denser, task-first header than public pages. */
.page-header--dashboard {
    padding: 34px 0 28px;
}

.page-header--dashboard h1 {
    font-size: clamp(1.7rem, 3vw, 2.25rem);
    margin-top: 5px;
}

.page-header--dashboard .section-eyebrow {
    margin-bottom: 0;
}

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Off-screen until focused, so keyboard/screen-reader users can jump past the navbar's
   ~20 links without affecting sighted mouse users. Sits above .navbar's z-index (1000)
   so it's never hidden behind the fixed header once focused. */
.skip-link {
    position: fixed;
    top: 12px;
    left: 12px;
    z-index: 1100;
    padding: 12px 20px;
    background: var(--btn-fill);
    color: #fff;
    font-family: var(--font-sans);
    font-size: 14px;
    font-weight: 600;
    border-radius: 6px;
    text-decoration: none;
    transform: translateY(-150%);
    transition: transform 0.15s ease;
}

.skip-link:focus {
    transform: translateY(0);
}

.teetime-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
    max-height: 65vh;
    overflow-y: auto;
    padding-right: 6px; /* keep the scrollbar from touching the row edges */
}

.teetime-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    width: 100%;
    padding: 18px 22px;
    background: var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    cursor: pointer;
    font-family: inherit;
    text-align: left;
    transition: border-color 0.15s, background 0.15s;
}

.teetime-row:hover:not(:disabled) {
    border-color: var(--accent);
    background: var(--accent-dim);
}

.teetime-row-time {
    font-family: var(--font-serif);
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--text-primary);
}

.teetime-row-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13.5px;
    color: var(--accent);
    white-space: nowrap;
}

.teetime-row--full,
.teetime-row:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

.teetime-row--full .teetime-row-meta {
    color: var(--text-muted);
}

@media (max-width: 640px) {
    .teetime-row { padding: 14px 16px; }
    .teetime-row-time { font-size: 1.05rem; }
}

.teetime-honeypot {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    opacity: 0;
}

.players-picker {
    display: flex;
    gap: 8px;
}

/* Square 44px box, so a full 50% radius gives a true circle for the single-character
   options (1-4, and Holes' 18/9). */
.players-option {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: 1px solid var(--border-strong);
    background: var(--bg-card);
    color: var(--text-primary);
    font-family: var(--font-serif);
    font-size: 1.1rem;
    font-weight: 700;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s, color 0.15s, transform 0.15s;
}

.players-option:hover { border-color: var(--accent); }
.players-option:active { transform: scale(0.94); }

.players-option--selected {
    border-color: var(--accent);
    background: var(--btn-fill);
    color: #fff;
}

/* Word options ("Yes"/"No", "Day"/"Week") grow with their label, so a circle would
   distort — 999px keeps the same fully-rounded end caps at any width. */
.players-option--text {
    width: auto;
    min-width: 44px;
    padding: 0 18px;
    border-radius: 999px;
    font-family: var(--font-sans);
    font-size: 14px;
}

/* === TEE TIME DASHBOARD === */
.dash-day-heading {
    font-family: var(--font-serif);
    font-size: 1.3rem;
    color: var(--text-primary);
    margin: 32px 0 14px;
}

.dash-day-heading:first-child { margin-top: 0; }

.dash-slot-list {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.dash-slot {
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    background: var(--bg-card);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    overflow: hidden;
}

.dash-slot-header {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 18px;
    background: var(--accent-dim);
    flex-wrap: wrap;
}

.dash-slot-time {
    font-family: var(--font-serif);
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--text-primary);
}

.dash-slot-capacity {
    font-size: 13px;
    color: var(--accent);
    flex: 1;
}

/* Sits inline on a slot row, so it stays compact — .btn-pill's 48px min-height would
   stretch every row it appears in. Keeps the pill shape and the hover sweep. */
.dash-add-btn {
    padding: 8px 16px;
    font-size: 12.5px;
    min-height: 0;
}

.dashboard-header-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 20px;
}

.dashboard-header-actions {
    display: flex;
    align-items: center;
    gap: 8px;
}

.dashboard-theme-toggle {
    margin-top: 4px;
    background: var(--bg-card);
    border: 1px solid var(--border-strong);
}

.dash-today-btn {
    font-family: var(--font-sans);
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    background: var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    padding: 9px 12px;
    cursor: pointer;
}

.dash-today-btn:hover { border-color: var(--accent); color: var(--accent); }

#dashPrint { margin-left: auto; }

.dash-confirm-actions {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    margin-top: 24px;
}

.dash-booking-list {
    padding: 4px 18px;
}

.dash-booking {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 0;
    border-bottom: 1px solid var(--border-subtle);
    flex-wrap: wrap;
}

.dash-booking:last-child { border-bottom: none; }

.dash-booking-info {
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: 13.5px;
    color: var(--text-muted);
}

.dash-booking-info strong {
    font-size: 14.5px;
    color: var(--text-primary);
}

.dash-booking-actions {
    display: flex;
    gap: 10px;
    flex-shrink: 0;
}

.dash-edit-btn,
.dash-cancel-btn {
    font-family: var(--font-sans);
    font-size: 12.5px;
    font-weight: 600;
    background: none;
    border: 1px solid var(--border-strong);
    border-radius: 6px;
    padding: 6px 12px;
    cursor: pointer;
    color: var(--text-primary);
    transition: border-color 0.15s, color 0.15s;
}

.dash-edit-btn:hover { border-color: var(--accent); color: var(--accent); }
.dash-cancel-btn:hover { border-color: #b13b3b; color: #b13b3b; }

.dash-booking-empty {
    padding: 12px 0;
    font-size: 13.5px;
    color: var(--text-muted);
}

/* === DASHBOARD PRINT SHEET === */
.print-only { display: none; }

@media print {
    /* A zero page margin leaves no reserved space for Chrome's own printed
       header (date/title) and footer (URL/page number), so it omits them —
       the visual margin below comes from .print-only's own padding instead. */
    @page { margin: 0; }
    body * { visibility: hidden; }
    .print-only, .print-only * { visibility: visible; }
    .print-only {
        display: block;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        background: #fff;
        color: #111;
        padding: 0.4in 0.5in;
    }
    .print-only h1 {
        font-family: Georgia, 'Times New Roman', serif;
        font-size: 20px;
        margin: 0 0 4px;
    }
    .print-only h2 {
        font-family: Arial, Helvetica, sans-serif;
        font-size: 14px;
        font-weight: 600;
        color: #444;
        margin: 0 0 16px;
    }
    .print-sheet {
        width: 100%;
        border-collapse: collapse;
        font-family: Arial, Helvetica, sans-serif;
        font-size: 12px;
    }
    .print-sheet th,
    .print-sheet td {
        border: 1px solid #999;
        padding: 6px 10px;
        text-align: left;
        color: #111;
    }
    .print-sheet th {
        background: #eee;
        font-weight: 700;
        text-transform: uppercase;
        font-size: 11px;
        letter-spacing: 0.04em;
    }
    .print-sheet .print-open {
        color: #888;
        font-style: italic;
    }
}

/* === TOURNAMENT RESULTS === */
.results-filter {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 40px;
    max-width: 460px;
}

.results-filter label {
    font-family: var(--font-sans);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.results-select-wrap {
    position: relative;
}

.results-select-wrap i {
    position: absolute;
    top: 50%;
    right: 16px;
    transform: translateY(-50%);
    color: var(--accent);
    font-size: 13px;
    pointer-events: none;
}

.results-select-wrap select {
    width: 100%;
    appearance: none;
    -webkit-appearance: none;
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 15px;
    padding: 14px 44px 14px 20px;
    cursor: pointer;
    transition: border-color 0.2s;
}

.results-select-wrap select:hover:not(:disabled) {
    border-color: var(--accent-border);
}

.results-select-wrap select:focus {
    outline: none;
    border-color: var(--accent);
}

.results-select-wrap select:disabled {
    opacity: 0.6;
    cursor: default;
}

/* Custom combobox that replaces the <select> above once public/custom-select.js runs —
   see that file for why. Sized/colored to match .results-select-wrap select exactly, so
   there's no visible jump when the enhancement kicks in. */
.custom-select-trigger {
    width: 100%;
    display: flex;
    align-items: center;
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 15px;
    text-align: left;
    padding: 14px 44px 14px 20px;
    cursor: pointer;
    transition: border-color 0.2s;
}

.custom-select-trigger:hover:not(.is-disabled) {
    border-color: var(--accent-border);
}

.custom-select-trigger:focus-visible {
    outline: none;
    border-color: var(--accent);
}

.custom-select-trigger.is-disabled {
    opacity: 0.6;
    cursor: default;
}

.custom-select-trigger[aria-expanded="true"] ~ i {
    transform: translateY(-50%) rotate(180deg);
}

.custom-select-list {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    right: 0;
    z-index: 20;
    margin: 0;
    padding: 8px;
    list-style: none;
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 20px;
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.25);
    max-height: 280px;
    overflow-y: auto;
}

.custom-select-list li {
    padding: 10px 16px;
    border-radius: 999px;
    font-size: 14.5px;
    color: var(--text-primary);
    cursor: pointer;
}

.custom-select-list li.is-active {
    background: var(--accent-dim);
}

.custom-select-list li.is-selected {
    color: var(--accent);
    font-weight: 600;
}

.results-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: 12px 24px;
    padding-bottom: 20px;
    margin-bottom: 28px;
    border-bottom: 1px solid var(--border-subtle);
}

.results-title {
    font-family: var(--font-serif);
    font-size: 1.6rem;
    color: var(--text-primary);
    margin: 0 0 6px;
}

.results-date {
    font-size: 13.5px;
    color: var(--text-muted);
    margin: 0;
}

.results-details-link {
    font-family: var(--font-sans);
    font-size: 13px;
    font-weight: 500;
    color: var(--accent);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    white-space: nowrap;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
}

.results-details-link:hover { text-decoration: underline; }
.results-details-link i { font-size: 11px; }

.results-external {
    padding: 40px 0;
    text-align: center;
}

.results-external p {
    color: var(--text-muted);
    font-size: 15px;
    margin-bottom: 20px;
}

.results-flight-title {
    font-family: var(--font-serif);
    font-size: 1.15rem;
    color: var(--text-primary);
    margin: 32px 0 14px;
}

.results-flight-title:first-of-type {
    margin-top: 0;
}

/* Heading and share button on one line above each flight's table. The empty <span> the
   renderer emits when there is no heading keeps the button on the right either way. */
.results-section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin: 32px 0 14px;
}

.results-section:first-child .results-section-head { margin-top: 0; }
.results-section-head .results-flight-title { margin: 0; }

/* Flight/division filter chips and the (single) share button on one row, instead of the
   button sitting alone on its own line below them. */
.results-filters-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 22px;
}

.results-filters-row .tourney-filters { margin-bottom: 0; flex: 1 1 auto; }

/* More than 3 flights and chips wrap into a crowded multi-row block, so a dropdown takes
   over past that — capped rather than growing to fill the row, so it doesn't stretch into
   an oddly wide pill next to the (fixed-size) share button on a wide screen. */
.results-filters-row .results-select-wrap { flex: 0 1 280px; }

/* Icon-only circle, quieter than the filter chips above it — a secondary action beside the
   standings, not a way of navigating them. Sized at 38px so it stays a comfortable tap
   target once the label is gone. */
.results-share-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 38px;
    height: 38px;
    background: none;
    border: 1px solid var(--border-strong);
    border-radius: 50%;
    color: var(--text-primary);
    cursor: pointer;
    transition: color 0.2s, border-color 0.2s, background 0.2s;
}

.results-share-btn:hover:not(:disabled) {
    border-color: var(--accent);
    color: var(--accent);
    background: var(--accent-dim);
}

.results-share-btn:disabled {
    opacity: 0.65;
    cursor: default;
}

.results-share-btn i { font-size: 14px; }

/* The generated card, shown in the modal before it is shared or saved. Capped by height as
   well as width: the image is a tall portrait card, and a width-only cap would push the
   Share and Download buttons below the fold on a phone — exactly where they are needed. */
.share-preview {
    display: block;
    width: 100%;
    /* High enough that a wide/short card (tournamentresults.html) never hits it — width
       stays the binding constraint there — but a taller one (leagueresults.html's weekly
       recap) can still render at full width instead of being height-capped, shrunk, and
       letterboxed by object-fit: contain. The modal's own scroll (.tourney-modal-inner)
       covers whatever doesn't fit above the fold. */
    max-height: 75vh;
    object-fit: contain;
    object-position: top;
    margin: 16px 0 0;
    border: 1px solid var(--border-subtle);
    border-radius: 8px;
    background: #f7f3ea;   /* matches the card it is previewing, so letterboxing blends in */
}

.share-preview-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 18px;
}

.share-preview-actions .btn { display: inline-flex; align-items: center; }

.results-table-wrap {
    overflow-x: auto;
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
}

.results-table {
    width: 100%;
    border-collapse: collapse;
    font-family: var(--font-sans);
    font-size: 14.5px;
    min-width: 480px;
    background: var(--bg-card);
}

.results-table thead th {
    text-align: left;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
    background: var(--bg-surface);
    padding: 13px 18px;
    border-bottom: 1px solid var(--border-subtle);
    white-space: nowrap;
}

.results-table tbody td {
    padding: 13px 18px;
    color: var(--text-primary);
    border-bottom: 1px solid var(--border-subtle);
    vertical-align: top;
}

.results-table tbody td[rowspan] {
    vertical-align: middle;
}

.results-table tbody tr:last-child td {
    border-bottom: none;
}

.results-table tbody tr:hover {
    background: var(--overlay-faint);
}

.results-place {
    font-weight: 600;
    white-space: nowrap;
    width: 1%;
}

.results-place i {
    color: var(--accent);
    margin-right: 2px;
}

.results-score {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.results-credit {
    color: var(--text-muted);
    white-space: nowrap;
}

.results-row--winner td {
    background: var(--accent-dim);
}

.results-row--winner .results-team {
    font-weight: 600;
}

@media (max-width: 600px) {
    .results-head { align-items: flex-start; }
    .results-title { font-size: 1.35rem; }
}

/* === LEAGUE RESULTS === */
/* Pill row matching .tourney-filter on the tournaments page, so the two results pages
   offer their choices the same way. Deliberately the same measurements — 999px radius,
   8px 16px padding, 12.5px/600 type — rather than an approximation. */
.league-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 36px;
}

.league-tab {
    background: none;
    border: 1px solid var(--border-strong);
    border-radius: 999px;
    padding: 8px 16px;
    /* Not --text-muted: on the page background that lands at 3.9:1, under AA for 12.5px. */
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    transition: color 0.2s, border-color 0.2s, background 0.2s;
}

.league-tab:hover {
    border-color: var(--accent);
    color: var(--accent);
}

/* Tint plus a doubled border rather than a solid fill — the same treatment the tournament
   filters use, and it keeps the label on a background whose contrast is already checked. */
.league-tab.is-active {
    background: var(--accent-dim);
    border-color: var(--accent);
    box-shadow: inset 0 0 0 1px var(--accent);
    color: var(--accent);
    font-weight: 700;
}

.results-filter--row {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 18px 24px;
    max-width: none;
}

.results-field {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 160px;
    flex: 1 1 160px;
    max-width: 220px;
}

.league-caption,
.league-subhead {
    color: var(--text-muted);
    margin: 0 0 18px;
}

.league-caption {
    font-size: 14px;
}

.league-subhead {
    font-family: var(--font-serif);
    font-size: 1.2rem;
    color: var(--text-primary);
    margin: 36px 0 14px;
}

.league-narrow {
    max-width: 460px;
}

/* .results-table sets min-width: 480px so a wide table keeps its columns legible inside a
   scrolling wrapper. This variant caps the wrapper at 460px, so the floor sat 20px above
   the ceiling and these small tables always overflowed — a scrollbar with nothing to
   scroll to. They have few enough columns to fit on their own. */
.league-narrow .results-table {
    min-width: 0;
}

.league-row--top td {
    background: var(--accent-dim);
}

.league-row--top td:nth-child(2),
.league-row--top .results-place {
    font-weight: 600;
}

/* Plain (non-matrix) league tables that can still run to a full season roster — e.g. the
   Leaderboard — get the same height cap and vertical scroll as .league-matrix, just
   without the horizontal-scroll pieces that table alone needs. */
.league-scroll-y {
    max-height: 60vh;
    overflow-y: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.league-scroll-y::-webkit-scrollbar {
    display: none;
}

.league-scroll-y thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--bg-surface);
}

/* Wide week-by-week matrices: horizontal scroll with a frozen player column. Height is
   capped with its own vertical scroll too — with a full season roster this table can run
   well past the viewport, which pushed the horizontal scroll buttons (centered on the
   wrap) far enough down to scroll past unnoticed. */
.league-matrix {
    overflow-x: auto;
    overflow-y: auto;
    max-height: 60vh;
    /* Scrolling is available via the arrow buttons, drag/swipe, and the wheel — the
       scrollbar track itself is redundant chrome next to the buttons. */
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.league-matrix::-webkit-scrollbar {
    display: none;
}

.league-matrix thead th {
    position: sticky;
    top: 0;
    /* Below the frozen Rank/Player/Total header corners (z-index 2, via the more specific
       .league-matrix thead .league-sticky[-right] rules), so those stay on top of a plain
       weekly-column header cell passing underneath them during a horizontal scroll. */
    z-index: 1;
    background: var(--bg-surface);
    /* .results-table thead th sets text-align: left globally and, cell for cell, outranks
       .league-matrix th's text-align: center (same class count, but one more element in
       its selector) — headers were left-aligned while their data centered under them.
       Matching selector shape here ties that specificity and wins on source order instead. */
    text-align: center;
}

.league-matrix .results-table {
    width: auto;
}

.league-matrix th,
.league-matrix td {
    width: 1%;
}

.league-matrix .league-sticky--2 {
    width: auto;
    max-width: 200px;
    white-space: normal;
    overflow-wrap: break-word;
}

/* Responsive table headers: full label on desktop, short label on mobile. */
.hdr-sm { display: none; }

/* Player snapshot stat cards */
.player-stats {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 14px;
    margin: 4px 0 32px;
}

.player-stat {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 10px;
    padding: 20px 14px;
    text-align: center;
}

.player-stat-num {
    display: block;
    font-family: var(--font-serif);
    font-size: 1.7rem;
    font-weight: 600;
    color: var(--accent);
    line-height: 1.1;
}

.player-stat-label {
    display: block;
    margin-top: 8px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
}

@media (max-width: 600px) {
    .player-stats { grid-template-columns: repeat(2, 1fr); gap: 10px; }
    .player-stat { padding: 16px 10px; }
    .player-stat-num { font-size: 1.45rem; }
}

.league-matrix th,
.league-matrix td {
    padding: 11px 14px;
    white-space: nowrap;
    text-align: center;
}

.league-matrix th:first-child,
.league-matrix td:first-child {
    text-align: left;
}

.league-sticky {
    position: sticky;
    left: 0;
    background: var(--bg-card);
    z-index: 1;
}

.league-matrix thead .league-sticky {
    background: var(--bg-surface);
    z-index: 2;
}

/* Second frozen column (player name) sits to the right of the rank column. The rank
   column's width is auto-sized by the browser from its content (a bare digit or two), so
   a hardcoded guess here drifts out of sync with it — leaving a gap, or worse, an overlap
   once this column "sticks" during a scroll. --rank-col-w is measured and set in JS from
   the rank column's actual rendered width; the pixel value here only covers the instant
   before that JS runs. */
.league-sticky--2 {
    left: var(--rank-col-w, 64px);
    box-shadow: 1px 0 0 var(--border-subtle);
}

.league-zero {
    color: var(--text-muted);
    opacity: 0.5;
}

.league-total {
    font-weight: 600;
    color: var(--text-primary);
}

/* Total column stays pinned to the right of the matrix, mirroring the frozen Rank/Player
   columns on the left, so only the weekly columns scroll out of view. */
.league-sticky-right {
    position: sticky;
    right: 0;
    background: var(--bg-card);
    box-shadow: -1px 0 0 var(--border-subtle);
    z-index: 1;
}

.league-matrix thead .league-sticky-right {
    background: var(--bg-surface);
    z-index: 2;
}

.league-matrix-scroll {
    display: flex;
    align-items: center;
    gap: 8px;
}

.league-matrix-scroll .league-matrix {
    flex: 1 1 auto;
    min-width: 0;
}

.league-scroll-btn {
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    border: 1px solid var(--border-strong);
    background: var(--bg-card);
    color: var(--text-primary);
    font-size: 13px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: color 0.2s, border-color 0.2s, opacity 0.2s;
}

.league-scroll-btn:hover:not(:disabled) {
    border-color: var(--accent);
    color: var(--accent);
}

.league-scroll-btn:disabled {
    opacity: 0.3;
    cursor: default;
}

@media (max-width: 600px) {
    .league-tab { padding: 7px 13px; font-size: 12px; }

    /* Swap to short column headers and tighten tables to avoid horizontal scrolling. */
    .hdr-lg { display: none; }
    .hdr-sm { display: inline; }

    /* Drop the desktop min-width so tables can shrink to fit the screen. */
    .results-table { font-size: 12px; min-width: 0; }
    .results-table thead th { padding: 8px 7px; letter-spacing: 0.03em; }
    .results-table tbody td { padding: 8px 7px; }

    /* League Week / Flight side by side instead of stacked full-width — narrower and a
       bit more compact so both fit on one line on a phone. */
    .results-filter--row { flex-wrap: nowrap; gap: 10px; }
    .results-filter--row .results-field { min-width: 0; max-width: none; flex: 1 1 0; }
    .results-filter--row .results-select-wrap select,
    .results-filter--row .custom-select-trigger { font-size: 13.5px; padding: 11px 32px 11px 14px; }
    .results-filter--row .results-select-wrap i { right: 12px; }

    /* Weekly flighted table (7 columns): fit phone width by fixing the layout and
       wrapping long player names, instead of scrolling sideways. The wide season
       matrix keeps its horizontal scroll, since that many weeks can't fit on a phone. */
    .results-table--flight { table-layout: fixed; width: 100%; }
    .results-table--flight th,
    .results-table--flight td { padding: 7px 4px; }
    .results-table--flight th:nth-child(1), .results-table--flight td:nth-child(1) { width: 10%; }
    .results-table--flight th:nth-child(2), .results-table--flight td:nth-child(2) { width: 27%; white-space: normal; word-break: break-word; }
    .results-table--flight th:nth-child(3), .results-table--flight td:nth-child(3) { width: 9%; }
    .results-table--flight th:nth-child(4), .results-table--flight td:nth-child(4) { width: 12%; }
    .results-table--flight th:nth-child(5), .results-table--flight td:nth-child(5) { width: 12%; }
    .results-table--flight th:nth-child(6), .results-table--flight td:nth-child(6) { width: 14%; }
    .results-table--flight th:nth-child(7), .results-table--flight td:nth-child(7) { width: 16%; }

    .league-matrix th,
    .league-matrix td { padding: 7px 6px; font-size: 11.5px; }
    .league-matrix thead th { padding: 8px 6px; }
    .league-matrix .league-sticky--2 { max-width: 104px; }
    .league-sticky--2 { left: var(--rank-col-w, 40px); }

    /* The flanking arrows cost ~84px of table width on a phone, where every column is
       already fighting for space. Move them above the table instead, right-aligned,
       rather than sacrificing width from the (already frozen) Rank/Player/Total columns. */
    .league-matrix-scroll {
        display: grid;
        grid-template-columns: 1fr auto auto;
        grid-template-areas: "spacer prev next" "table table table";
        gap: 6px 8px;
    }
    .league-matrix-scroll .league-matrix { grid-area: table; }
    .league-scroll-btn--prev { grid-area: prev; }
    .league-scroll-btn--next { grid-area: next; }
}

@media (max-width: 430px) {
    .results-table { font-size: 11px; }
    .results-table thead th { padding: 7px 5px; }
    .results-table tbody td { padding: 7px 5px; }

    .league-matrix th,
    .league-matrix td { padding: 6px 5px; font-size: 11px; }
    .league-matrix .league-sticky--2 { max-width: 88px; }
    .league-sticky--2 { left: var(--rank-col-w, 34px); }
}

/* === STAFF DIRECTORY === */
.staff-section {
    padding-top: 100px;
    margin-top: 100px;
    border-top: 1px solid var(--border-subtle);
}

.staff-group {
    margin-bottom: 56px;
}

.staff-group:last-child {
    margin-bottom: 0;
}

.staff-group-title {
    font-size: 1.3rem;
    color: var(--text-primary);
    margin-bottom: 24px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--border-subtle);
}

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

.staff-card {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 8px;
    padding: 28px 24px;
    text-align: center;
    transition: border-color 0.25s, transform 0.25s;
}

.staff-card:hover {
    border-color: var(--accent-border);
    transform: translateY(-3px);
}

.staff-icon {
    width: 52px;
    height: 52px;
    margin: 0 auto 16px;
    border-radius: 50%;
    background: var(--accent-dim);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 19px;
    color: var(--accent);
}

.staff-card h4 {
    font-family: var(--font-serif);
    font-size: 1.05rem;
    color: var(--text-primary);
    margin-bottom: 6px;
}

.staff-card-title {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--accent);
    margin-bottom: 14px;
}

.staff-links {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.staff-link {
    font-size: 13px;
    color: var(--text-muted);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}

.staff-link:hover {
    color: var(--accent);
}

.staff-loading,
.staff-empty {
    padding: 40px 0;
    text-align: center;
    color: var(--text-muted);
    font-size: 15px;
}

.policy-desc {
    font-size: 13.5px;
    color: var(--text-muted);
    line-height: 1.6;
    margin-bottom: 14px;
    text-align: left;
}

/* === UTILITY MODIFIERS === */
.btn-block   { display: block; text-align: center; margin-top: 24px; }
.btn-spaced  { margin-top: 20px; }
.rates-subheading { margin-top: 28px; }
.events-footer { text-align: center; margin-bottom: 40px; }

/* === RESPONSIVE === */
@media (max-width: 900px) {
    .contact-grid      { grid-template-columns: 1fr; gap: 48px; }
    .footer-grid       { grid-template-columns: 1fr 1fr 1fr; gap: 48px; }
    .footer-brand      { grid-column: 1 / -1; }
    .rates-grid        { grid-template-columns: 1fr; }
    .features-grid     { grid-template-columns: 1fr; }
    .membership-grid   { grid-template-columns: 1fr 1fr; }
    .hole-grid         { grid-template-columns: 1fr 1fr; }
    .course-announce-grid { grid-template-columns: 1fr; gap: 64px; }
    /* Announcements reads first on mobile, even though Course comes first in the markup. */
    .course-col    { order: 2; }
    .announce-col  { order: 1; }
}

/* Nav breakpoint for the hamburger vs. the full desktop link row — kept separate from the
   general @media(max-width:640px) mobile-layout block below (grids, forms, and other
   unrelated layout rules that are fine staying at 640px) because this one needs a wider
   threshold. layout.js's resize listener already assumes desktop starts at 993px when
   deciding whether to auto-close an open mobile menu; the CSS breakpoint was still 640px,
   so tablet/landscape-phone widths (641-992px) showed the full link row crammed into a
   viewport that wasn't really desktop-width yet. This matches the two up. */
@media (max-width: 992px) {
    .nav-links { display: none; }
    .nav-toggle { display: block; }
}

@media (max-width: 640px) {
    /* Below this width the desktop bar is replaced wholesale by the slide-over panel
       (see "MOBILE SLIDE-OVER MENU" below), which layout.js builds from this same list. */
    .form-row          { grid-template-columns: 1fr; }

    /* Hours and Quick Links pair up rather than stacking: they are the two tall columns,
       and side by side they cost one column's height instead of both. Brand and Contact Us
       keep the full width — the brand needs it for the lockup, and Contact Us is short
       enough that splitting it would just leave a half-empty row. */
    .footer-grid       { grid-template-columns: 1fr 1fr; gap: 34px 22px; }
    .footer-brand,
    .footer-contact    { grid-column: 1 / -1; }
    .benefit-list      { columns: 1; }
    .membership-grid   { grid-template-columns: 1fr; }
    .hole-grid         { grid-template-columns: 1fr; }
    /* The nav is fixed and overlays the hero, and the hero centres its content in
       min(100vh, 820px). Adding the subtitle made that content taller than the space,
       so the centred block rose until the eyebrow sat against the nav bar. Reserving
       the nav's height as hero padding re-centres what's left below it; the rest of
       this block buys the height back so the whole hero still fits one phone screen. */
    .hero              { padding-top: 112px; padding-bottom: 32px; }
    .hero-content      { padding-top: 0; }
    .hero-title        { font-size: clamp(2.5rem, 9.5vw, 3.25rem); margin-bottom: 18px; }
    .hero-subtitle     { font-size: 15px; margin-bottom: 24px; }
    .hero-stats        { margin-bottom: 24px; }
    /* Absolutely positioned 36px from the bottom, which put it behind the second
       button once the hero filled up. Nothing is lost — the page scrolls either way. */
    .hero-scroll       { display: none; }
    .hero-actions      { flex-direction: column; align-items: center; }
    .hero-stats {
        display: grid;
        grid-template-columns: 1fr 1fr;
        width: min(300px, 82vw);
        gap: 14px 0;
        border-radius: 20px;
    }
    .hero-stat         { padding: 0 16px; justify-content: center; }
    .hero-stat-text    { text-align: center; }
    .hero-stat-value   { font-size: .85rem; }
    .hero-stat-divider { display: none; }

    .cal-header        { gap: 12px; }
    .cal-month-label   { font-size: 1.2rem; min-width: unset; }
    .cal-legend        { gap: 14px 18px; }
    .cal-day           { min-height: 64px; padding: 5px 3px; }
    .cal-weekday       { font-size: 9px; padding: 8px 2px; }
    .cal-day-num       { font-size: 11px; }
    .cal-event         { font-size: 9px; padding: 3px 4px; gap: 3px; }
    .cal-event-more    { font-size: 9px; }
    .tourney-modal-inner { padding: 36px 22px 28px; }
}

/* === 404 PAGE === */
.error-actions {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 64px;
}

.error-links h2 {
    font-family: var(--font-serif);
    font-size: 1.2rem;
    color: var(--text-primary);
    margin-bottom: 22px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--border-subtle);
}

.error-links ul {
    list-style: none;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px 32px;
}

.error-links li a {
    color: var(--text-muted);
    text-decoration: none;
    font-size: 15px;
    transition: color 0.2s;
}

.error-links li a:hover {
    color: var(--accent);
}

@media (max-width: 640px) {
    .error-links ul { grid-template-columns: 1fr; }
}


/* === iOS ZOOM-ON-FOCUS GUARD ===
   Mobile Safari zooms the whole page when a focused text field's font-size is under 16px,
   and does not zoom back out afterwards. Every field on the site is already 16px, so this
   rule changes nothing today — it exists so a future field styled at 13-15px can't quietly
   reintroduce the behaviour. max() keeps it at least 16px while still honouring a visitor's
   larger default text size.

   Deliberately NOT solved with maximum-scale=1, user-scalable=no on the viewport meta:
   that does stop the zoom, but it also blocks pinch-zoom entirely, which people with low
   vision rely on. */
@media (max-width: 640px) {
    input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]),
    select,
    textarea {
        font-size: max(16px, 1rem);
    }
}

.scorecard-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    margin-bottom: 40px;
}

/* The round tracker is meant for keeping score on a phone during a round, not browsing
   from a desktop — the link only shows up at mobile widths. */
.round-tracker-cta { display: none; }
@media (max-width: 640px) {
    .round-tracker-cta { display: inline-flex; }
    /* At mobile widths this is the only row using .scorecard-actions — "View Scorecard" +
       "Keep Score" together are wider than a phone screen at the buttons' normal padding,
       which wrapped them onto separate rows. Shrinking padding/font and letting each button
       share the row equally keeps them side by side instead. */
    .scorecard-actions .btn {
        flex: 1 1 0;
        min-width: 0;
        padding-left: 12px;
        padding-right: 12px;
        font-size: 11px;
    }
}

/* Dark mode gets its own palette on this page only — true black instead of the site's
   usual charcoal, with a brighter, more saturated accent green so score data reads as
   vividly as possible against it (this page is meant to be glanced at outdoors, often in
   bright sunlight, more than read carefully like the rest of the site). Scoped to
   .round-page rather than touching the shared [data-theme="dark"] block, so every other
   page's dark mode is untouched. Custom properties inherit, so this also reaches the site
   nav mounted inside this same body — the whole page goes black together, not just the
   app content below the nav. Light mode is unaffected. */
[data-theme="dark"] .round-page {
    --accent:             #35d073;
    --accent-hover:       #4fe085;
    /* Lifted from #24a85c: white text on that fill measured 3.07:1, below WCAG AA's 4.5:1
       for normal text — used as the modal close button's hover fill. */
    --accent-active:      #1a7a41;
    /* Lifted from #1fae57/#29c765: white text on those measured 2.90:1 / 2.22:1 against
       WCAG AA's 4.5:1 minimum (confirmed via axe-core) — this is the solid fill behind
       every white-on-green button and pill on this page (Start Round, Next, the setup
       screen's active pills, the modal close button), so it needed real headroom, not a
       token darkening. Hover now goes darker than resting, which also reads as more
       conventional "press" feedback than the previous lighter hover did. */
    --btn-fill:           #15803d;
    --btn-fill-hover:     #166534;
    --accent-dim:         rgba(53, 208, 115, 0.16);
    --accent-border:      rgba(53, 208, 115, 0.45);
    --bg-page:            #000000;
    --bg-surface:         #0c0c0c;
    --bg-card:            #131313;
    --text-primary:       #ffffff;
    --text-muted:         #a6a6a6;
    --text-dim:           rgba(255, 255, 255, 0.7);
    --text-faint:         rgba(255, 255, 255, 0.48);
    --border-subtle:      rgba(255, 255, 255, 0.10);
    --overlay-faint:      rgba(255, 255, 255, 0.05);
    --overlay-medium:     rgba(255, 255, 255, 0.14);
    --overlay-strong:     rgba(255, 255, 255, 0.22);
    --border-strong:      rgba(255, 255, 255, 0.32);
    /* Fully opaque, not the site's usual translucent-blur (rgba(0,0,0,0.88) elsewhere) —
       used by the nav, this page's own topbar, and its bottom nav bar, all with
       backdrop-filter: blur() over scrolling content. At 88% opacity the round summary's
       light/cream share card was visibly bleeding through underneath while scrolling,
       which fought the whole point of this page's true-black dark palette. */
    --surface-translucent: #000000;
    --accent-shadow:      rgba(53, 208, 115, 0.45);
    --accent-dim-strong:  rgba(53, 208, 115, 0.3);
    /* #c0392b (the light-mode literal used below) measures 3.42:1 against this page's
       #131313 cards — under the 4.5:1 AA text minimum, though the same color is fine
       against light mode's near-white cards. */
    --danger:             #e05a4a;
}

/* .btn-outline's default border color (--border-strong) is a near-white gray, tuned for
   the site's normal dark theme. On this page's pure-black/neon-green palette that reads as
   a plain white outline instead of matching the accent, so it's overridden here rather than
   changing --border-strong itself (which other bordered elements on the page also use). */
[data-theme="dark"] .round-page .btn-outline { border-color: var(--accent); }

/* .btn-outline is transparent by default (site-wide) — fine on ordinary pages, but next to
   this page's filled cards it reads as a flat bordered rectangle rather than a button.
   Giving it a card-colored fill plus a soft shadow makes it feel raised/tappable instead —
   scoped to this page only, not the shared .btn-outline used everywhere else on the site. */
.round-page .btn-outline {
    background: var(--bg-card);
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.08);
}
.round-page .btn-outline:hover {
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
}
/* A black shadow reads as invisible against this page's pure-black dark background, so
   dark mode gets a faint accent-tinted glow instead for the same sense of depth. */
[data-theme="dark"] .round-page .btn-outline {
    box-shadow: 0 3px 10px rgba(53, 208, 115, 0.10);
}
[data-theme="dark"] .round-page .btn-outline:hover {
    box-shadow: 0 6px 18px rgba(53, 208, 115, 0.18);
}

/* The site nav's normal breakpoint (640px) switches to the full desktop link row well
   below where the horizontal scorecard kicks in (700px, see .round-h-wrap below) — between
   those two, the desktop nav had to cram into a viewport that isn't really desktop-width
   yet, which read as cramped/broken. This page is a focused, app-like tool that only needs
   a wayfinding icon anyway (see the comment on <body class="round-page"> in
   roundtracker.html), so it keeps the compact hamburger menu at every width instead of
   ever switching to the full link row. */
.round-page .nav-links { display: none; }
.round-page .nav-toggle { display: block; }

/* === ROUND TRACKER (roundtracker.html) ===
   Site nav but no footer (see that file) — so the layout is centered/capped rather than
   using .container, and needs its own top padding to clear the fixed .navbar (80px tall
   unscrolled — see .navbar in the NAV section above). Its own sticky top bar (back/exit +
   screen title) picks up right where the site nav leaves off. */
.round-app {
    /* Every other page's <main class="page-content"> sets this, which is what keeps
       body::before's fixed background pattern (z-index: 0) from painting over opaque
       cards instead of behind them — this page's <main> needs the same fix, once here,
       rather than repeating position: relative; z-index: 1 on every card class inside it. */
    position: relative;
    z-index: 1;
    max-width: 480px;
    min-height: 100vh;
    margin: 0 auto;
    padding-top: 80px;
    display: flex;
    flex-direction: column;
    /* Mobile Safari reads two quick taps on the same spot as "double-tap to zoom" — easy
       to trigger by accident on the strokes/putts steppers, which are meant to be tapped
       repeatedly and fast. manipulation drops just that gesture (and the ~300ms tap delay)
       while still leaving pinch-zoom available, unlike disabling zoom outright. */
    touch-action: manipulation;
}

.round-app > .tourney-loading { margin: 80px auto; }

/* Every other screen (setup, hole entry, finished) is a mobile-card layout that stays
   comfortably narrow even on a wide viewport — but the horizontal scorecard table wants to
   use that width instead of sitting in a 480px column with large empty gutters either
   side. Scoped to just the summary screen via :has() so nothing else on this page widens. */
@media (min-width: 700px) {
    .round-app:has(.round-summary) { max-width: 1100px; }
}

.round-topbar {
    position: sticky;
    top: 80px;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 16px;
    background: var(--surface-translucent);
    backdrop-filter: blur(8px);
    border-bottom: 1px solid var(--border-subtle);
    padding-top: max(14px, env(safe-area-inset-top));
}

/* The site nav shrinks from 80px to 68px tall once the page scrolls past 60px
   (see layout.js's `scrolled` class toggle). Left pinned at 80px, this topbar's
   sticky offset would sit 12px below the now-shorter nav, exposing a gap where
   whatever row just scrolled past peeks through underneath. Tracking the same
   class keeps the two flush at every scroll position. */
body:has(.navbar.scrolled) .round-topbar {
    top: 68px;
}

.round-topbar-exit {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    flex: none;
    border-radius: 50%;
    border: 1px solid var(--border-strong);
    background: var(--bg-card);
    color: var(--text-primary);
    text-decoration: none;
    cursor: pointer;
    transition: color 0.2s, border-color 0.2s;
}
.round-topbar-exit:hover { border-color: var(--accent); color: var(--accent); }

.round-topbar-title {
    font-family: var(--font-serif);
    font-weight: 700;
    font-size: 1.05rem;
    text-align: center;
    /* Now an <h1> (was a <span>) so screen readers have something to land on when the
       screen changes — margin:0 undoes the browser default that would otherwise blow out
       the topbar's flex layout. */
    margin: 0;
}
/* tabindex="-1" makes this a programmatic focus target (JS moves focus here on every
   screen change, see focusScreenTitle()) rather than a normal tab stop, so it doesn't need
   its own visible ring — the point is the screen-reader announcement, not a visual cue. */
.round-topbar-title:focus { outline: none; }
.round-topbar-sub { font-family: var(--font-sans); font-weight: 400; font-size: 0.8rem; color: var(--text-muted); }
.round-topbar-spacer { width: 38px; flex: none; }

.round-screen {
    flex: 1;
    padding: 20px 16px 100px;
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.round-card {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 14px;
    padding: 20px;
}

/* Holes and Track Stats sit side by side rather than each taking a full-width card. */
.round-card-row { display: flex; gap: 14px; }
.round-card-row .round-card { flex: 1; min-width: 0; }
.round-card--half { padding: 16px; }
.round-card--half .round-card-title { font-size: 1rem; }

.round-card-title {
    display: flex;
    align-items: center;
    gap: 10px;
    font-family: var(--font-serif);
    font-size: 1.1rem;
    color: var(--text-primary);
}
.round-card-title i { color: var(--accent); font-size: 0.9em; }
.round-card-sub { color: var(--text-muted); font-size: 14px; margin: 4px 0 16px; }

/* Pushed to the far right of .round-card-title via the auto margin, same trick as
   .round-wind-inline elsewhere on this page. Plain icon button, no border/background at
   rest, so it reads as a quiet "more info" affordance rather than competing with the
   Yes/No pills below it. */
.round-info-btn {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    border: none;
    background: none;
    color: var(--text-muted);
    font-size: 0.85rem;
    cursor: pointer;
}
.round-info-btn:hover,
.round-info-btn:focus-visible { color: var(--accent); }
/* .round-card-title i sets every icon in the title row (including this button's) to a
   fixed accent green, which would override the muted/hover states above outright — this
   restores that so the info icon actually reflects the button's own color. */
.round-card-title .round-info-btn i { color: inherit; }

/* Anchors .round-info-popover, which is positioned absolute against it. */
.round-card--relative { position: relative; }

.round-info-popover {
    position: absolute;
    top: 44px;
    right: 16px;
    z-index: 20;
    width: 168px;
    padding: 10px 12px;
    border-radius: 10px;
    border: 1px solid var(--border-subtle);
    background: var(--bg-card);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.18);
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--text-primary);
}
.round-info-popover p { margin: 0; }
.round-info-popover p + p { margin-top: 6px; }
.round-info-popover strong { color: var(--accent); margin-right: 4px; }

.round-pill-row { display: flex; flex-wrap: wrap; gap: 10px; }

.round-pill {
    min-width: 52px;
    padding: 10px 18px;
    border-radius: 999px;
    border: 1px solid var(--border-strong);
    background: var(--bg-surface);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-weight: 600;
    font-size: 14px;
    cursor: pointer;
    transition: color 0.2s, border-color 0.2s, background 0.2s;
}

/* Fixed equal width/height (not padding-driven) so "9" and "18" render as the same-size
   circle instead of "18"'s extra digit stretching it into an oval. */
.round-pill--circle {
    width: 38px;
    height: 38px;
    min-width: 0;
    padding: 0;
    font-size: 12.5px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* The Players section gets breathing room from .round-card-sub's own bottom margin
   ("Who's playing?"); Holes has no sub-line, so its pill row sat flush against the
   heading above it without one. */
.round-card-title + .round-pill-row { margin-top: 14px; }
.round-pill.is-active {
    background: var(--btn-fill);
    border-color: var(--btn-fill);
    color: #fff;
}

.round-players { display: flex; flex-direction: column; gap: 18px; margin-top: 18px; }

.round-field-label {
    display: block;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 6px;
}

.round-text-input {
    width: 100%;
    padding: 12px 16px;
    border-radius: 10px;
    border: 1px solid var(--border-subtle);
    background: var(--bg-surface);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 16px;
}
.round-text-input:focus { outline: none; border-color: var(--accent); }

.round-tee-row { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }

.round-tee-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 8px 14px;
    border-radius: 999px;
    border: 1px solid var(--border-strong);
    background: var(--bg-surface);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s;
}
.round-tee-btn.is-active { border-color: var(--accent); background: var(--accent-dim); color: var(--accent); }

.round-spaced { margin-top: 12px; }

.round-exit-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 6px; }

/* Same red as .round-summary-stat-icon--no, reused here so the destructive action
   in the exit dialog reads consistently with the rest of the round tracker. --danger
   isn't defined in light mode, so the literal hex (already AA-safe there) is the fallback. */
.btn-danger.btn-pill {
    background: transparent;
    color: var(--danger, #c0392b);
    border: 1px solid var(--danger, #c0392b);
}
.btn-danger.btn-pill:hover { background: var(--danger, #c0392b); color: #fff; }

.round-resume .round-card { text-align: center; }
.round-resume .round-card-title { justify-content: center; }

.round-hole-info {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}
.round-hole-par {
    font-family: var(--font-serif);
    font-weight: 700;
    font-size: 1.3rem;
    color: var(--accent);
}
/* The two handicaps stack instead of sharing a line separated by a dot — at 13px on a
   phone that ran together and was hard to scan. Still one flex item in .round-hole-info,
   so the wind readout's margin-left:auto keeps pushing it to the far right. */
.round-hole-meta {
    display: flex;
    flex-direction: column;
    line-height: 1.45;
    color: var(--text-muted);
    font-size: 13px;
}

/* Pushed to the far right of .round-hole-info via the auto margin, whatever else is
   in that row before it (an intentional flex trick, not a mistake). */
.round-wind-inline {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-left: auto;
    font-family: var(--font-sans);
    font-weight: 600;
    font-size: 13px;
    color: var(--text-muted);
    white-space: nowrap;
}
.round-wind-inline i { color: var(--accent); font-size: 12px; }

.round-player-cards { display: flex; flex-direction: column; gap: 14px; }

.round-player-card {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 14px;
    padding: 16px;
}

.round-player-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.round-player-name { font-family: var(--font-serif); font-weight: 700; font-size: 1.05rem; }
.round-player-thru { font-size: 12.5px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.round-player-tee-line { font-size: 12.5px; color: var(--text-muted); margin: 4px 0 14px; display: flex; align-items: center; gap: 6px; }

.round-stroke-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.round-stroke-row .round-field-label { margin-bottom: 0; }

.round-stepper { display: flex; align-items: center; gap: 12px; }
.round-stepper-btn {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    border: 1px solid var(--border-strong);
    background: var(--bg-surface);
    color: var(--text-primary);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
}
.round-stepper-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.round-stepper-btn:disabled { opacity: 0.35; cursor: default; }
.round-stepper-val {
    min-width: 28px;
    text-align: center;
    font-family: var(--font-serif);
    font-weight: 700;
    font-size: 1.2rem;
    font-variant-numeric: tabular-nums;
}

.round-quick-row { display: flex; gap: 6px; margin-bottom: 16px; flex-wrap: wrap; }
.round-quick-btn {
    flex: 1 1 0;
    padding: 7px 4px;
    border-radius: 999px;
    border: 1px solid var(--border-subtle);
    background: var(--bg-surface);
    color: var(--text-muted);
    font-family: var(--font-sans);
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s, color 0.2s;
}
.round-quick-btn.is-active { border-color: var(--accent); background: var(--accent-dim); color: var(--accent); }

.round-stat-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.round-stepper--sm .round-field-label { margin: 0 8px 0 0; }
.round-stepper--sm { gap: 8px; }
.round-stepper--sm .round-stepper-btn { width: 28px; height: 28px; font-size: 15px; }
.round-stepper--sm .round-stepper-val { font-size: 1rem; min-width: 18px; }

.round-toggle-group { display: flex; gap: 8px; }
.round-toggle {
    padding: 7px 14px;
    border-radius: 999px;
    border: 1px solid var(--border-strong);
    background: var(--bg-surface);
    color: var(--text-muted);
    font-family: var(--font-sans);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.04em;
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s, color 0.2s;
}
.round-toggle.is-active { border-color: var(--accent); background: var(--accent-dim); color: var(--accent); }

.round-nav-bar {
    position: sticky;
    bottom: 0;
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 16px;
    padding-bottom: max(14px, env(safe-area-inset-bottom));
    background: var(--surface-translucent);
    backdrop-filter: blur(8px);
    border-top: 1px solid var(--border-subtle);
}
.round-nav-bar .btn { flex: 1; }

/* The hole each button leads to, sitting outside its arrow — far left on Back, far right
   on Next. On one line rather than stacked under the word, which pushed "BACK"/"NEXT" off
   the button's vertical centre. Omitted entirely where there's no target (Back on the
   first hole, Finish on the last), so nothing needs to reserve empty space. */
.round-nav-target {
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.02em;
    text-transform: none;
    opacity: 0.72;
}

/* .btn is inline-block, so its contents sit on a shared text baseline — and the chevron
   glyph's box is taller than the label's, which left the arrow riding above the words.
   Flex with align-items:center centres each child on the row instead of hanging them off
   a baseline, and line-height:1 on the icon trims the leading that offset it. */
.round-nav-bar .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
}

/* Slightly larger than the label so the chevron overhangs the cap height a little at the
   top and drops just below the baseline, wrapping the word rather than sitting flush with
   it. Centred as a box (align-items above), so growing it extends both ends evenly. */
.round-nav-bar .btn i {
    display: block;
    line-height: 1;
    font-size: 1.3em;
    /* The chevron's ink sits high inside its own em box, so box-centring it left ~4.5px
       of overhang above the cap height and barely any below. Measured from the rendered
       pixels; this drops it to roughly equal overhang top and bottom. transform, not
       margin, so it can't disturb the flex row's sizing. */
    transform: translateY(2px);
}

/* On a 320px phone "NEXT > Hole 2" wraps the button to two lines. Dropping the word
   leaves the numeral, which still reads correctly next to the arrow and fits. */
@media (max-width: 360px) {
    .round-nav-target-word { display: none; }
    .round-nav-bar .btn { padding-left: 14px; padding-right: 14px; }
}

.round-summary-table th,
.round-summary-table td { text-align: center; white-space: nowrap; }
.round-summary-table th:first-child,
.round-summary-table td:first-child { text-align: left; }
/* .results-table thead th sets text-align: left globally and, cell for cell, outranks the
   two rules above for header cells specifically (same class count, but one more element in
   its selector — thead+th vs th alone) — the same trap already hit once on the season
   standings matrix. Matching selector shape here ties that specificity and wins on source
   order instead, so the header row actually follows the per-column alignment above it
   instead of sitting left for every column regardless. */
.round-summary-table thead th { text-align: center; }
.round-summary-table thead th:first-child { text-align: left; }
/* .results-table tbody td sets vertical-align: top — fine for the two-line Hole column
   (number + par), which already fills the row, but it pinned the single-line score cells
   to the top instead of centering them in that taller row. Same specificity-matching fix
   as the text-align rules above (tbody+td ties .results-table tbody td and wins on order). */
.round-summary-table tbody td { vertical-align: middle; }
.round-summary-par { display: block; font-size: 10px; color: var(--text-muted); font-weight: 400; }
.round-summary-subtotal td { background: var(--overlay-faint); font-weight: 600; }
.round-summary-total td { background: var(--accent-dim); font-weight: 700; color: var(--accent); }

/* Tap a hole's row to fix a wrong score — hover/focus feedback so it reads as tappable
   rather than just another table row. */
.round-summary-row--editable { cursor: pointer; transition: background 0.15s; }
.round-summary-row--editable:hover,
.round-summary-row--editable:focus-visible { background: var(--overlay-faint); }
.round-summary-row--editable:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ---- Horizontal (landscape/wide-viewport) scorecard ----
   Holes run across as columns instead of down as rows, with Score/FIR/GIR/Putts stacked
   underneath each player — closer to a real printed scorecard, and a better use of the
   extra width once the screen is wide enough for it. .round-v-wrap is the mobile "holes
   down" table built above; only one of the two is ever visible at a time. */
.round-h-wrap { display: none; }
@media (min-width: 700px) {
    .round-v-wrap { display: none; }
    .round-h-wrap { display: block; }
}

.round-h-table { min-width: 0; font-size: 13.5px; }
/* .results-table thead th / tbody td (global) match tighter selectors than a plain
   ".round-h-table th"/"td" would, so specificity — not source order — would decide the
   winner and the global 13px/18px padding would win. Matching their selector shape here
   ties the specificity and lets source order take over instead, same fix already used for
   .round-summary-table above. Every override below follows the same rule: match
   "thead th"/"tbody td"/"tbody th" plus a class, never a bare class alone, so it can't
   silently lose to these two on specificity. This needs thead td too — the Par row's plain
   value cells live in <thead> alongside the Hole header row, not <tbody> like every other
   row's cells, and without it they fell back to the browser's unstyled <td> default
   (left-aligned, no padding), which is what made Par look out of step with every row
   below it even though the cell boundaries themselves already lined up. */
.round-h-table thead th,
.round-h-table thead td,
.round-h-table tbody td,
.round-h-table tbody th {
    padding: 8px 10px;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
}

/* First column (row labels: Hole/Par/Score/FIR/GIR/Putts) stays put while the rest of an
   18-hole round's columns scroll past underneath it. */
.round-h-table thead th.round-h-corner,
.round-h-table tbody th[scope="row"] {
    position: sticky;
    left: 0;
    z-index: 1;
    text-align: left;
    background: var(--bg-card);
}
.round-h-table thead th.round-h-corner { z-index: 2; background: var(--bg-surface); }

.round-h-hole { cursor: pointer; transition: background 0.15s, color 0.15s; }
.round-h-hole:hover,
.round-h-hole:focus-visible { background: var(--overlay-faint); color: var(--accent); }
.round-h-hole:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.round-h-table thead th.round-h-sub,
.round-h-table thead td.round-h-sub-cell,
.round-h-table tbody td.round-h-sub-cell { background: var(--overlay-faint); font-weight: 600; }
.round-h-na { color: var(--text-faint); }

/* The player's name sits on the Score row's own label (th[scope=row]) instead of a
   separate full-width divider row — this just adds a separating line above that row, and
   above it only, so consecutive players' blocks still read as distinct groups. */
.round-h-table tbody tr.round-h-player-first th[scope="row"] {
    font-family: var(--font-serif);
    font-weight: 700;
    color: var(--accent);
    border-top: 1px solid var(--border-subtle);
}
.round-h-table tbody tr.round-h-player-first td { border-top: 1px solid var(--border-subtle); }
.round-h-table tbody tr:first-child th,
.round-h-table tbody tr:first-child td { border-top: none; }

/* Bands every other player's whole 4-row block so they're easy to tell apart once there's
   more than one — :not(.round-h-sub-cell) leaves the OUT/IN/TOTAL columns' own shading
   alone rather than fighting with it (both would otherwise apply to the same cell).
   --overlay-faint (the same token the OUT/IN/TOTAL columns already use) rather than
   --overlay-medium — medium read as too strong a contrast between players; matching the
   sub-cell tokens keeps every shaded element on this table at one consistent, subtle
   intensity instead of two different strengths. */
.round-h-table tbody tr.round-h-player-alt td:not(.round-h-sub-cell),
.round-h-table tbody tr.round-h-player-alt th[scope="row"] {
    background: var(--overlay-faint);
}

/* Standard scorecard marks — currentColor so each just matches whatever color the score
   text already is (birdie-or-better already renders in the accent green via .results-score
   rules elsewhere, this just adds the ring/box around it). outline draws outside the
   border without affecting layout size, which is what makes the "double" variants read as
   two concentric rings/boxes rather than one thick one. */
.score-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 30px;
    height: 30px;
    padding: 0 4px;
    font-size: 18px;
    font-weight: 700;
    border-radius: 4px;
}
.score-mark--circle,
.score-mark--dcircle { border-radius: 50%; }
.score-mark--circle,
.score-mark--square { border: 1.5px solid currentColor; }
.score-mark--dcircle,
.score-mark--dsquare {
    border: 1.5px solid currentColor;
    outline: 1.5px solid currentColor;
    outline-offset: 2px;
}

/* Score mark and its FIR/GIR/Putts side by side, not stacked — small enough that the
   three extra rows per cell don't blow out the table, since every player column repeats
   them. */
.round-summary-cell {
    display: inline-flex;
    align-items: center;
    gap: 12px;
}
.round-summary-cell-stats {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    font-size: 10px;
    font-weight: 600;
    color: var(--text-muted);
}
.round-summary-cell-stat {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    letter-spacing: 0.03em;
    text-transform: uppercase;
}
.round-summary-stat-icon--yes { color: #2f9e52; }
.round-summary-stat-icon--no { color: var(--danger, #c0392b); }

.round-summary-stats { margin-top: 4px; }
.round-stat-substats {
    display: flex;
    justify-content: center;
    gap: 10px;
    margin-top: 8px;
    font-size: 10.5px;
    color: var(--text-muted);
}
