* { box-sizing: border-box; }

:root {
  --mbc-purple: #4a1942;
  --mbc-purple-light: #7a3f6d;
  --mbc-purple-pale: #f1e6ee;
  --mbc-cream: #faf7f2;
  --mbc-text: #3a1f35;
}

/* The page background color lives on <html>, not <body> -- if it's set on
   body instead, some browsers "promote" it to paint the whole viewport
   canvas, which then paints on top of (or gets confused with) a
   z-index: -1 pseudo-element on body. Keeping it on html avoids that. */
html {
  background-color: var(--mbc-cream);
}

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  color: var(--mbc-text);
}

/* Tennis court line art that stays put while the page scrolls.
   iOS Safari has never reliably supported background-attachment: fixed
   (it scrolls with the page there instead of staying put), so this uses a
   position: fixed pseudo-element instead -- that's genuinely fixed on every
   browser, including iOS, since the bug is specific to the background-attachment
   property and not to fixed positioning in general. Court is drawn in portrait
   orientation (net running horizontally). preserveAspectRatio='none' is required
   because SVGs otherwise letterbox themselves to preserve their internal aspect
   ratio regardless of the background-size box, which silently ate the "+100px"
   width request as invisible internal margin instead of actually stretching.
   Strokes are fully opaque -- if they instead carried their own stroke-opacity,
   every corner/intersection where two lines overlap would stack that opacity
   and render as a visibly darker patch than the single lines elsewhere. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 600' preserveAspectRatio='none'%3E%3Cg fill='none' stroke='%237a3f6d' stroke-width='4'%3E%3Crect x='2' y='2' width='296' height='596'/%3E%3Crect x='39' y='2' width='222' height='596'/%3E%3Cline x1='2' y1='300' x2='298' y2='300'/%3E%3Cline x1='39' y1='138' x2='261' y2='138'/%3E%3Cline x1='39' y1='462' x2='261' y2='462'/%3E%3Cline x1='150' y1='138' x2='150' y2='300'/%3E%3Cline x1='150' y1='300' x2='150' y2='462'/%3E%3C/g%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: calc(50vh + 100px) 100%;
  opacity: 1;
}

/* On narrow screens, height-based sizing can make the court wider than the
   actual viewport (since preserveAspectRatio="none" no longer holds it back).
   Switch to a width-relative size instead. Height is spelled out explicitly
   as 2x the width (matching the SVG's 300:600 viewBox ratio) rather than
   relying on "auto" -- preserveAspectRatio="none" makes some browsers treat
   the image as having no usable intrinsic ratio for background-size auto
   resolution, which was producing badly distorted proportions on mobile. */
@media (max-width: 600px) {
  body::before {
    background-size: 80vw 160vw;
  }
}

.page {
  position: relative;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 24px;
}

.page:not(.events-page) {
  justify-content: center;
  text-align: center;
}

/* Events list doesn't center vertically (it can run much taller than the
   viewport), but it inherited the same top padding as every other page
   anyway, pushing the header row down further than it needs to be when
   there's no reason to leave that space at the top here. */
.events-page {
  padding-top: 8px;
}

h1 {
  font-size: 2.5rem;
  margin-bottom: 8px;
  text-align: center;
  color: var(--mbc-purple);
  overflow-wrap: break-word;
}

h2, h3 {
  color: var(--mbc-purple);
}

.button {
  display: inline-block;
  margin-top: 24px;
  padding: 12px 28px;
  background: var(--mbc-purple);
  color: #fff;
  border-radius: 999px;
  text-decoration: none;
  font-weight: 600;
}

.hidden {
  display: none;
}

/* Standalone page/section headers (title, description, dates, etc.) need
   their own opaque card -- otherwise that text sits directly on the
   court-line background and becomes hard to read where lines cross it. */
.page-header-card {
  background: #fff;
  border: 1px solid var(--mbc-purple-pale);
  box-shadow: 0 1px 4px rgba(74, 25, 66, 0.08);
  border-radius: 12px;
  padding: 20px;
  width: 100%;
  max-width: 480px;
  text-align: center;
  margin-bottom: 16px;
}

/* Compact variant for title cards that only hold a short title (and maybe
   one button) -- the shared .page-header-card padding/width is sized for
   pages with a description/date/etc underneath, which looks oversized on
   pages that don't have that extra content. Renamed from an earlier
   --home-only version now that the events list uses it too. */
.page-header-card--compact {
  width: fit-content;
  max-width: none;
  padding: 6px 16px;
}

/* Zero out h1's default top/bottom margin entirely -- with any margin left
   in place the padding above/below the text stops being the only thing
   controlling the gap, which makes it effectively impossible to get the
   visual space above and below the title text to match. */
.page-header-card--compact h1 {
  margin: 0;
}

/* Second line inside a compact title card (e.g. registered-teams' "event
   name, then event date" title) -- much smaller/lighter than the h1 text
   around it so it reads as metadata rather than a second heading. */
.page-header-subtitle {
  display: block;
  font-size: 1rem;
  font-weight: 400;
  opacity: 0.75;
  margin-top: 4px;
}

/* Home page panel: title on white up top, one or more solid-purple action
   bars stacked underneath as a distinct footer -- replaced an earlier
   layout that had a small standalone pill button floating loose below (or
   briefly, inside) the title card. That version made it genuinely unclear
   how much of the page was clickable: either the whole card looked like
   one link when it wasn't, or the real link was a tiny target easy to
   miss entirely. Giving the action row its own solid fill makes it
   unmistakable at a glance without needing a second visual language --
   still one cohesive panel, just clearly two zones within it. Built to
   hold more than one link (.home-cta + .home-cta gets a divider) since
   the home page will likely grow past a single "View events" action. */
.home-panel {
  width: fit-content;
  background: #fff;
  border: 1px solid var(--mbc-purple-pale);
  box-shadow: 0 1px 4px rgba(74, 25, 66, 0.08);
  border-radius: 16px;
  overflow: hidden;
  text-align: center;
}

.home-panel-top {
  padding: 22px 40px 20px;
}

.home-tagline {
  margin: 0 0 2px;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--mbc-purple-light);
}

.home-panel-top h1 {
  margin: 0;
}

.home-cta {
  display: block;
  padding: 16px;
  background: var(--mbc-purple);
  color: #fff;
  text-decoration: none;
  font-weight: 600;
  font-size: 1rem;
  text-align: center;
}

.home-cta:hover {
  background: var(--mbc-purple-light);
}

.home-cta + .home-cta {
  border-top: 1px solid rgba(255, 255, 255, 0.15);
}

/* Club crest on the home page, pinned near the top of the viewport
   (independent of the vertically-centered header card below it) rather than
   flowing inline with the rest of the page content. .page has
   position: relative so this anchors to the page itself, not the viewport --
   still effectively "near the top of the screen" since .page starts at the
   very top. The source jpg is a square with a plain white fill outside the
   circle -- border-radius: 50% clips that away since the circle art already
   fills the frame edge-to-edge at its widest points, so nothing gets cut
   off, it just removes the white square corners that would otherwise show
   as an odd box floating on the purple/cream background. */
.site-logo {
  position: absolute;
  top: 15px;
  left: 50%;
  transform: translateX(-50%);
  width: 140px;
  height: 140px;
  object-fit: cover;
  border-radius: 50%;
  box-shadow: 0 2px 10px rgba(74, 25, 66, 0.25);
}

/* Event list */

#events-list {
  width: 100%;
  max-width: 480px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: 16px;
}

.event-card {
  background: #fff;
  border: 1px solid var(--mbc-purple-pale);
  box-shadow: 0 1px 4px rgba(74, 25, 66, 0.08);
  border-radius: 12px;
  padding: 20px;
  text-align: center;
}

.event-card h2 {
  margin: 0 0 4px;
  font-size: 1.4rem;
}

/* Empty/error state (e.g. "No upcoming events.") reuses the same card look
   as a real event, just with a single centered line and no default
   paragraph margin so it doesn't add extra space beyond the card's own
   padding. */
.event-card-message {
  margin: 0;
}

.event-link {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: background 0.15s ease;
}

.event-link:hover {
  background: var(--mbc-purple-pale);
}

/* Back-navigation links styled as small rounded pill buttons, matching the
   site's general card treatment instead of bare text sitting directly on
   the court-line background. Positioned like .site-logo (absolute,
   anchored to .page's viewport-top-based coordinate system) rather than
   flowing inline with the title card -- see .page-header-row .back-link
   below for the actual placement. */
.back-link {
  display: inline-block;
  flex-shrink: 0;
  white-space: nowrap;
  background: #fff;
  border: 1px solid var(--mbc-purple-pale);
  box-shadow: 0 1px 4px rgba(74, 25, 66, 0.08);
  border-radius: 999px;
  padding: 8px 16px;
  color: var(--mbc-purple);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9rem;
}

/* Header area: back button pinned near the top-left, title card centered
   independently below it. Earlier attempts put both on one CSS-grid row
   (back flush left, title centered via a mirrored invisible spacer
   column) but that coupled the two together -- a nowrap back button plus
   a long title could force the whole row wider than its own max-width and
   overflow. Decoupling them removes that failure mode entirely: the back
   button is absolutely positioned off in its own corner, and the title
   card is just a normal centered flow child, so neither can squeeze or
   overflow because of the other.

   0.667vh below is the top court-line border's own thickness expressed as
   a fraction of viewport height: the background SVG draws that rect's
   stroke from y:0 to y:4 inside a 600-unit-tall viewBox, and
   background-size scales that viewBox to exactly 100vh (see body::before),
   so (4 / 600) * 100vh = 0.667vh is the line's real bottom edge at any
   viewport height -- not just the one it happened to be measured at. */
.page-header-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  margin-bottom: 16px;
}

/* Absolute against .page (the nearest positioned ancestor), not against
   .page-header-row, so "top" lines up with the viewport-anchored
   court-line regardless of .page-header-row's own position in the flow.
   Left edge matches the left edge of the site's standard centered 480px
   content column (480 / 2 = 240px each side of center) -- but ONLY once
   the viewport is wide enough for that math to stay positive. Below 528px
   wide (480px content + 2*24px .page padding), `50% - 240px` goes
   negative and pushes the pill off-screen to the left -- clipped/cut off
   on every phone, since phones are always narrower than that. Fixed
   2026-07-12 (caught via visual mobile-viewport check in Chrome) by
   clamping to .page's own 24px padding as a floor, so the pill never
   goes past the same left inset every other page element already respects. */
.page-header-row .back-link {
  position: absolute;
  top: calc(0.667vh + 3px);
  left: max(24px, calc(50% - 240px));
}

/* Normal flow child -- .page-header-row's own align-items: center handles
   horizontal centering, so this needs no special positioning of its own.
   margin-top clears the vertical space the (now absolutely positioned,
   so no longer in-flow) back button used to occupy: back button's top
   offset (0.667vh + 3px) + its fixed single-line height (38px) + the
   requested 5px gap, minus .events-page's own 8px top padding which
   already pushes this row down before this margin is added. */
.page-header-row .page-header-card {
  margin-top: calc(0.667vh + 38px);
  margin-bottom: 0;
}

.back-link:hover {
  background: var(--mbc-purple-pale);
}

#event-detail,
#roster-detail {
  width: 100%;
  max-width: 480px;
}

.event-description,
.event-date,
.event-registration {
  margin: 2px 0;
  opacity: 0.85;
  font-size: 0.95rem;
}

.countdown {
  font-size: 1.6rem;
  font-variant-numeric: tabular-nums;
  margin-top: 8px;
  color: var(--mbc-purple);
}

.registration-countdown {
  text-align: center;
  margin-top: 8px;
}

/* Flights (within an event, once registration is open) */

.flights-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 16px;
}

.flight-card {
  background: #fff;
  border: 1px solid var(--mbc-purple-pale);
  box-shadow: 0 1px 4px rgba(74, 25, 66, 0.06);
  border-radius: 10px;
  padding: 14px;
  text-align: center;
}

.flight-card h3 {
  margin: 0 0 4px;
  font-size: 1.1rem;
}

.flight-ranking,
.flight-availability {
  margin: 2px 0;
  opacity: 0.85;
  font-size: 0.9rem;
}

.flight-full {
  font-weight: 600;
  margin-top: 8px;
  opacity: 0.9;
}

.entry-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 12px;
}

.entry-name,
.entry-member-id,
.entry-guest-name,
.entry-ranking {
  padding: 10px 14px;
  border-radius: 8px;
  border: 1px solid var(--mbc-purple-pale);
  background: #fff;
  color: var(--mbc-text);
  font-size: 1rem;
}

.entry-form button {
  padding: 10px 20px;
  border-radius: 8px;
  border: none;
  background: var(--mbc-purple);
  color: #fff;
  font-weight: 600;
  cursor: pointer;
}

.entry-form button:hover {
  background: var(--mbc-purple-light);
}

.entry-form button:disabled {
  background: #d8d3d6;
  color: #8a7f87;
  opacity: 0.8;
  cursor: not-allowed;
}

.entry-form button:hover:disabled {
  background: #d8d3d6;
}

.form-message {
  margin-top: 8px;
  font-size: 0.9rem;
  color: var(--mbc-purple);
}

.button-secondary {
  padding: 10px 20px;
  border-radius: 8px;
  border: 1px solid var(--mbc-purple);
  background: transparent;
  color: var(--mbc-purple);
  font-weight: 600;
  cursor: pointer;
}

.button-secondary:hover {
  background: var(--mbc-purple-pale);
}

.flight-block {
  display: flex;
  flex-direction: column;
  gap: 8px;
  border-top: 1px solid var(--mbc-purple-pale);
  padding-top: 12px;
  margin-top: 4px;
}

.flight-block-remove {
  align-self: flex-start;
  background: transparent;
  border: none;
  color: var(--mbc-purple-light);
  text-decoration: underline;
  cursor: pointer;
  font-size: 0.85rem;
  padding: 0;
}

/* Manage page sections (New Event, New Flight, Existing Events & Flights) */
.manage-section {
  background: #fff;
  border: 1px solid var(--mbc-purple-pale);
  box-shadow: 0 1px 4px rgba(74, 25, 66, 0.06);
  border-radius: 12px;
  padding: 20px;
  width: 100%;
  max-width: 480px;
  margin-bottom: 20px;
  text-align: left;
}

.manage-section:last-child {
  margin-bottom: 0;
}

.manage-event-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.manage-event-card-header h3 {
  margin: 0;
}

.icon-button {
  background: transparent;
  border: none;
  color: var(--mbc-purple-light);
  cursor: pointer;
  font-size: 1.1rem;
  line-height: 1;
  padding: 4px;
}

.icon-button:hover {
  color: var(--mbc-purple);
}

.manage-event-card-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.visibility-toggle {
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--mbc-purple-pale);
  background: transparent;
  color: var(--mbc-purple-light);
  font-size: 0.75rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}

.visibility-toggle:hover {
  background: var(--mbc-purple-pale);
}

/* Filled/tinted when the event is currently hidden -- flags the special
   state at a glance in a list of otherwise-identical cards, rather than
   relying on the button label text alone. */
.visibility-toggle--hidden {
  background: var(--mbc-purple-pale);
  color: var(--mbc-purple);
  border-color: var(--mbc-purple);
}

.manage-event-card {
  background: #fff;
  border: 1px solid var(--mbc-purple-pale);
  box-shadow: 0 1px 4px rgba(74, 25, 66, 0.06);
  border-radius: 12px;
  padding: 16px 20px;
  margin-bottom: 16px;
  text-align: left;
}

.manage-event-card:last-child {
  margin-bottom: 0;
}

.hidden-badge {
  display: inline-block;
  background: var(--mbc-purple);
  color: #fff;
  border-radius: 999px;
  padding: 1px 8px;
  font-size: 0.75rem;
  font-weight: 600;
}

/* Shared by the event-level and flight-level inline edit forms -- swapped
   in via x-show alongside the read-only view (not a separate page/route),
   so the fields double as a lightweight preview of what's being changed
   without navigating away from the list. */
.edit-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}

.edit-actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}

.flight-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.flight-row-main {
  flex: 1;
}

.flight-row-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.entries-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 8px 0 4px;
  padding: 10px 12px;
  background: var(--mbc-cream);
  border-radius: 8px;
}

.entry-row {
  font-size: 0.85rem;
}

.entry-row-main {
  display: flex;
  align-items: center;
  gap: 8px;
}

.entry-row-main span:first-child {
  flex: 1;
}

/* Inline "remove?" confirmation, swapped in for the row's normal content --
   this is an admin screen, so this replaces a native confirm() popup rather
   than using one. */
.entry-row-confirm {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--mbc-purple);
}

.entry-row-confirm span {
  flex: 1;
}

.entry-row-confirm-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}

.entry-row-confirm-actions .button-secondary,
.entry-row-confirm-actions button:not(.button-secondary) {
  padding: 4px 10px;
  font-size: 0.8rem;
}

.manage-event-card ul {
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.manage-event-card li {
  border-top: 1px solid var(--mbc-purple-pale);
  padding-top: 10px;
}

.manage-event-card li:first-child {
  border-top: none;
  padding-top: 0;
}

.entry-member-id::-webkit-outer-spin-button,
.entry-member-id::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.entry-member-id {
  -moz-appearance: textfield;
}

.event-flights {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 12px;
}

.flight-subcard {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  background: var(--mbc-purple-pale);
  border-radius: 8px;
  padding: 10px 14px;
  text-decoration: none;
  color: var(--mbc-text);
  font-size: 0.9rem;
  transition: background 0.15s ease, color 0.15s ease;
}

.flight-subcard:hover {
  background: var(--mbc-purple);
  color: #fff;
}

.flight-subcard-range {
  font-weight: 600;
  color: var(--mbc-purple);
}

.flight-subcard:hover .flight-subcard-range {
  color: #fff;
}

.no-flights {
  opacity: 0.7;
  font-size: 0.9rem;
  margin-top: 8px;
}

.roster-flights {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 16px;
  width: 100%;
  max-width: 480px;
}

.roster-card {
  text-align: left;
}

.roster-list {
  list-style: decimal;
  margin: 8px 0 0;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.9rem;
}

.roster-list .no-flights {
  list-style: none;
  margin-left: -20px;
}

.roster-waitlist-tag {
  display: inline-block;
  background: var(--mbc-purple-pale);
  color: var(--mbc-purple);
  border-radius: 999px;
  padding: 1px 8px;
  font-size: 0.75rem;
  font-weight: 600;
}

.signup-sheet-link {
  display: block;
  text-align: center;
  margin-top: 12px;
  color: var(--mbc-purple);
  font-weight: 600;
  font-size: 0.9rem;
  text-decoration: none;
  border-top: 1px solid var(--mbc-purple-pale);
  padding-top: 10px;
}

.signup-sheet-link:hover {
  text-decoration: underline;
}

/* Admin passphrase gate: a modal overlay rather than an inline page
   section, so it pops up wherever the admin currently is (e.g. deep inside
   an expanded flight's entries list) instead of forcing a scroll away from
   -- and then back to -- whatever they were doing. Pairs with
   requireUnlock()'s pending-action replay in manage/shared.js: once
   unlocked, the action that triggered the prompt resumes automatically in
   place, so nothing needs to be re-found or re-clicked. */
.admin-unlock-overlay {
  position: fixed;
  inset: 0;
  background: rgba(58, 31, 53, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 100;
}

.admin-unlock-modal {
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 4px 24px rgba(74, 25, 66, 0.25);
  padding: 20px;
  width: 100%;
  max-width: 360px;
  text-align: left;
}
