:root {
  --color-primary: #d94f4f;
  --color-secondary: #3f8f3f;
  --color-accent: #e8801a;
  --color-dark: #1a1a1a;
  --color-bg: #f7f7f4;
  --color-surface: #ffffff;
  --color-border: #ddd8cf;
  --color-text: #222;
  --color-muted: #6a6a6a;
}

* { box-sizing: border-box; }

/* Android Chrome's "font boosting" can silently inflate text (and anything sized around it) past
   what the same CSS renders as on desktop — it's tuned for readability on unstyled/text-heavy
   pages, not a deliberately-sized layout like this one. Without this reset, that inflation is
   invisible in desktop devtools' viewport emulation (it's a real-device-only behavior) but can
   push fixed/min-width elements (header controls, stepper buttons) wide enough to force page-level
   horizontal scroll on an actual phone. */
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  background: var(--color-bg);
  color: var(--color-text);
  min-height: 100vh;
  /* iOS/iPadOS Safari's 100vh is the height with the address-bar/toolbar chrome collapsed, taller
     than what's actually visible when it's showing — so the sticky footer below sat just out of
     view until you scrolled, even on a short page. 100dvh tracks the real visible viewport;
     browsers that don't support it ignore this line and keep the 100vh above. */
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  /* Safety net: nothing in this layout is meant to make the whole page scroll sideways — every
     intentionally-wide element (the rounds/matches tables, nav.tabs, .hole-scores) already has its
     own dedicated overflow-x:auto wrapper. This just guarantees a stray future overflow can't drag
     the entire viewport with it; it doesn't hide anything, since nothing should be relying on
     body-level scroll to reach content. */
  overflow-x: hidden;
}

main { flex: 1; }

.app-footer {
  padding: 16px 20px;
  text-align: center;
}

.app-footer p {
  margin: 2px 0;
  font-size: 0.85rem;
}

header.app-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 20px;
  background: var(--color-dark);
  color: #fff;
  flex-wrap: wrap;
}

header.app-header img.logo {
  height: 40px;
}

header.app-header a.back-link {
  color: #fff;
  text-decoration: none;
  font-size: 0.85rem;
  opacity: 0.85;
  white-space: nowrap;
}

header.app-header a.back-link:hover {
  opacity: 1;
  text-decoration: underline;
}

/* Overrides #login-status's default .muted styling while a login is in progress — the
   verification link/code are an active call-to-action at that moment, not secondary text, so
   they need real contrast against the dark header instead of blending into it. */
#login-status.login-active {
  color: #fff;
  font-size: 0.95rem;
  background: rgba(255, 255, 255, 0.12);
  padding: 8px 12px;
  border-radius: 6px;
  margin-top: 8px;
  line-height: 1.6;
}

#login-status.login-active a {
  color: #fff;
  font-weight: 600;
  text-decoration: underline;
}

#login-status.login-active #login-code {
  display: inline-block;
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  background: #fff;
  color: var(--color-dark);
  padding: 1px 8px;
  border-radius: 4px;
}

header.app-header h1 {
  font-size: 1.1rem;
  margin: 0;
  flex: 1;
  min-width: 140px;
}

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

button, .btn {
  font: inherit;
  padding: 6px 12px;
  border-radius: 6px;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  cursor: pointer;
}

button.primary {
  background: var(--color-accent);
  color: #fff;
  border-color: var(--color-accent);
}

nav.tabs {
  display: flex;
  gap: 4px;
  padding: 8px 20px 0;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

nav.tabs button {
  border: none;
  border-bottom: 3px solid transparent;
  border-radius: 0;
  background: none;
  padding: 10px 14px;
  color: var(--color-muted);
  white-space: nowrap;
  flex-shrink: 0;
}

nav.tabs button.active {
  color: var(--color-dark);
  border-bottom-color: var(--color-primary);
  font-weight: 600;
}

main {
  padding: 20px;
  max-width: 1100px;
  margin: 0 auto;
}

/* Tablet range (bigger than the phone breakpoint below, at or under iPad's widest landscape) gets
   tighter side padding so there's more real width for the .hole-scores row (9 fields fixed at
   ~112px each = ~1070px) to fit without horizontal scrolling — see GitHub issue #33. */
@media (min-width: 601px) and (max-width: 1366px) {
  main { padding: 20px 8px; }
  .card { padding: 16px 10px; }
}

.view { display: none; }
.view.active { display: block; }

.table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin-bottom: 12px;
}

table {
  width: 100%;
  min-width: 480px;
  border-collapse: collapse;
  background: var(--color-surface);
}

th, td {
  padding: 6px 8px;
  border-bottom: 1px solid var(--color-border);
  text-align: left;
  font-size: 0.9rem;
}

th { color: var(--color-muted); font-weight: 600; }

input[type="text"], input[type="number"], input[type="date"], select, textarea {
  font: inherit;
  padding: 5px 8px;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  max-width: 100%;
}

.course-import-textarea {
  display: block;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.8rem;
  margin-bottom: 8px;
  resize: vertical;
}

.section-heading {
  font-size: 1.1rem;
  font-weight: 700;
  cursor: pointer;
}

/* Safari (incl. iPadOS) gives flex items a default min-width: auto, which can force a
   .form-row to overflow instead of wrapping when a native <select>/<input type="date"> renders
   wider than in Chrome. min-width: 0 lets them shrink/wrap like every other browser already does. */
.form-row > * {
  min-width: 0;
}

.hole-input {
  width: 44px;
  text-align: center;
}

.badge {
  display: inline-block;
  font-size: 0.7rem;
  padding: 2px 6px;
  border-radius: 10px;
  background: #f0d9a0;
  color: #6b4e00;
}

.badge.win {
  background: var(--color-secondary);
  color: #fff;
}

.badge.medalist {
  background: #ffd700;
  color: #6b4e00;
}

.team-block {
  background: #fafaf6;
}

.team-block.winning-team {
  background: #e9f5e9;
  border: 2px solid var(--color-secondary);
}

.season-record {
  font-size: 1.1rem;
  margin: 0 0 16px;
}

.badge.warn {
  background: #f5c2c2;
  color: #7a1f1f;
}

.card.notice {
  background: #fff8e6;
  border: 1px solid #f0d9a0;
  border-left: 4px solid #c8960c;
}

.card.notice h2 {
  margin-top: 0;
}

.rank-highlight {
  background: #e9f5e9;
  font-weight: bold;
}

.rounds-red { background: #f5c2c2; }
.rounds-yellow { background: #fbe8a6; }
.rounds-green { background: #cdeecd; }

.round-row {
  cursor: pointer;
}

.round-detail td {
  background: #fafaf6;
}

/* Unlike round rows (clickable for everyone, to reveal hole detail), a player row only does
   something for admins — clicking loads it into the edit form — so the pointer cursor is scoped to
   admin mode to avoid promising an interaction viewers don't have. */
body.admin-mode .player-row {
  cursor: pointer;
}

.editable-name {
  cursor: pointer;
  text-decoration: underline;
  text-decoration-style: dotted;
}

/* Hidden by default (safe: viewer mode) until app.js confirms admin and adds .admin-mode to body. */
.admin-only { display: none; }
body.admin-mode .admin-only { display: revert; }
body.admin-mode .viewer-only { display: none; }

.icon {
  width: 20px;
  height: 20px;
  vertical-align: middle;
}

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  padding: 16px;
  margin-bottom: 16px;
}

.form-row {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
  flex-wrap: wrap;
  align-items: center;
}

.muted { color: var(--color-muted); font-size: 0.85rem; }

/* Utility classes replacing inline style="" attributes, so the CSP's style-src can stay
   'self' with no 'unsafe-inline' — inline style attributes and JS .style mutations are both
   blocked under a strict style-src. */
.hidden { display: none; }

/* icons.svg's own inline style="display:none" is blocked by the style-src 'self' CSP once it's
   injected into #icon-sprite via innerHTML (app.js) — hide the container instead. */
#icon-sprite { display: none; }
.hole-input { width: 56px; }

/* +/- buttons flanking a numeric-entry input. Since those fields are type="text" now (see
   docs/decisions.md), these are the only increment/decrement affordance on every platform — not
   just iOS/iPadOS, where the native <input type="number"> spinner was already absent (issue #33).
   The group is one inline-flex unit so .form-row's flex-wrap wraps whole hole/putts groups onto a
   new line together, never splitting a button from its input. */
.stepper {
  display: inline-flex;
  align-items: stretch;
  white-space: nowrap;
}

/* `.stepper input`, not `input[type="number"]` — the stepper's field is type="text"
   inputmode="numeric" now (see docs/decisions.md, "Why score-entry fields are type=text
   inputmode=numeric"). A `.stepper` only ever wraps this one input. */
.stepper input {
  border-radius: 0;
  border-left: none;
  border-right: none;
}

.stepper-btn {
  width: 28px;
  min-width: 28px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  line-height: 1;
  -webkit-user-select: none;
  user-select: none;
}

.stepper-btn.stepper-minus { border-radius: 4px 0 0 4px; }
.stepper-btn.stepper-plus { border-radius: 0 4px 4px 0; }

/* Bigger, easier-to-read entry fields on the round-log row specifically — scoped to #round-holes
   so it doesn't spill onto the match-entry row (ui-matches.js) or any table cell that happens to
   share .hole-input/.input-narrow elsewhere. */
/* `#round-holes input` covers the hole steppers and #round-putts — all type="text"
   inputmode="numeric" now (see the .stepper input note above); no <select> lives in this row. */
#round-holes input {
  font-size: 1.2rem;
  padding: 8px 6px;
}
#round-holes .stepper-btn {
  font-size: 1.2rem;
}
/* Narrowed just enough to fit all 9 fields on one line without horizontal scrolling — confirmed
   working on an actual iPad at this size. Rounds and Matches carry slightly different values since
   Matches' hole-score row shares its card's width budget with a longer preceding row (name +
   Starter). This is also the value inherited below the 1100px grid-wrap breakpoint (phones and
   portrait tablets), where the exact width doesn't affect scrolling — grid wrap always fits 3 per
   row regardless — so no separate narrow-width value is needed there.
   Trimmed a further 7px from each of these (and their ≥1101px overrides below) once type="number"
   was retired for good (see "Why score-entry fields are type=text inputmode=numeric" in
   docs/decisions.md) — that native spinner is what these widths used to leave headroom for; a
   plain text input showing at most 2 digits doesn't need it, and the on-one-line fit these were
   already tuned for can now only be easier, never at risk, since every value here only shrank. */
#round-holes .hole-input { width: 46px; }
.add-player-row .hole-input { width: 42px; }

/* Above the grid-wrap breakpoint, some iPads in landscape (Air 11", Pro 11", Pro 12.9" — all
   1180px+) share this single-line layout with desktop Chrome, so the iPad-tuned width above and
   desktop's own narrower need can't both be a single unscoped value — desktop Chrome needed these
   3-4px narrower to avoid scrolling at its own measured width. */
@media (min-width: 1101px) {
  #round-holes .hole-input { width: 44px; }
  .add-player-row .hole-input { width: 41px; }
}

/* Forces the match-entry row's flex-wrap to start a new line here, right after the Starter
   checkbox, so hole-score entry always begins on its own line instead of wherever it happens to
   wrap on a given screen width. */
.row-break {
  flex-basis: 100%;
  height: 0;
}

/* Everything past the player picker in an own-team "Add score" row (Starter, .row-break, the
   score fields, Putts, the button) — kept as its own flex/wrap context (mirrors .form-row) so
   .row-break above still forces score entry onto its own line within it. Hidden until a real
   player is chosen (ui-matches.js toggles this on .player-select's change) — an unattributed
   score is a mistake waiting to happen, same reasoning as #round-entry-fields in ui-rounds.js.
   The .hidden pairing is written explicitly (not left to rely on .hidden's own later position in
   this file) since this rule, unlike most .hidden targets, sets its own `display` too. */
.match-entry-fields {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.match-entry-fields.hidden {
  display: none;
}

/* All 9 hole-score fields stay together on one line — entering a round/match hole-by-hole reads
   left-to-right as one sequence, so wrapping mid-sequence onto a second line is more confusing
   than helpful. flex-wrap: nowrap keeps them from breaking; overflow-x: auto is the fallback on
   screens too narrow to fit all 9 (scrolls instead of squeezing digits unreadably). Putts is a
   sibling outside this group, so .form-row's own wrap is still free to drop it to the next line. */
.hole-scores {
  display: flex;
  flex-wrap: nowrap;
  gap: 8px;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 2px;
}

/* Wraps the scorecard-style Hole/Par reference rows directly above .hole-scores so the whole
   group stacks as one flex item within #round-holes / .add-player-row — same trick .hole-scores
   itself relies on, so the surrounding row's own flex-wrap still drops Putts/Add-score to the next
   line as a whole, never splitting mid-group. gap: 0 is deliberate — the scorecard rows below are
   meant to look like one continuous bordered grid, with no daylight between them. */
.hole-entry-group {
  display: flex;
  flex-direction: column;
  gap: 0;
  min-width: 0;
}
/* Below 1101px .hole-scores already claims the full line itself (flex-basis: 100%, further down)
   once .scorecard-score-row promotes it via display: contents, which drags .hole-entry-group along
   with it. Above 1101px nothing forced that until now — .hole-entry-group just shrank to its own
   content width (~952px for Rounds), which happened to leave enough room beside it for the 70px
   Putts field to squeeze onto the same line rather than wrap below, at exactly the window widths
   where main/.card's own padding is tightened (601–1366px, see that rule further up) — an iPad in
   landscape, concretely. Forcing the full line here removes that pixel-luck dependency instead of
   relying on it staying just barely too tight everywhere else. */
@media (min-width: 1101px) {
  .hole-entry-group {
    flex-basis: 100%;
  }
}

/* Traditional-scorecard-style reference block: a "Hole" row (actual hole numbers, side-aware) and
   a "Par" row sit directly above the live score-entry row, styled as one bordered grid — see
   GitHub issue discussion, "par row above hole entry". Desktop/iPad-landscape only (hidden below in
   the same max-width: 1100px switch .hole-scores makes to its 3-per-row grid, where a row of 9
   cells above no longer lines up with anything).

   Border technique: every cell carries its own right+bottom border; only the first row adds a top
   border and only the label column adds a left one — adjoining cells' shared edges are then a
   single 1px line rather than doubling up (the usual `border-collapse` trick, done by hand since
   this is flexbox, not a <table>). Value-cell widths mirror .hole-input's own ≥1101px width plus
   its two flanking 28px stepper buttons, so each header/par label centers directly over the score
   field for that hole. */
.scorecard-row {
  display: flex;
}
.scorecard-cell {
  border-right: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3px 0;
  font-size: 0.8rem;
}
.scorecard-label-cell {
  border-left: 1px solid var(--color-border);
  justify-content: flex-start;
  padding-left: 8px;
  font-weight: 700;
  white-space: nowrap;
}
.scorecard-hole-row .scorecard-cell { border-top: 1px solid var(--color-border); }
.scorecard-par-row .scorecard-cell { background: var(--color-bg); font-weight: 700; }
#round-holes .scorecard-cell:not(.scorecard-label-cell) { width: calc(44px + 56px); }
.add-player-row .scorecard-cell:not(.scorecard-label-cell) { width: calc(41px + 56px); }
.scorecard-label-cell { width: 52px; }
/* .hole-scores' own gap: 8px (further up) is still exactly what the mobile 3-per-row grid wants
   below 1101px (see the max-width: 1100px block below, which doesn't touch gap) — but in this
   bordered desktop layout it would widen the Score row 8px per column beyond the Hole/Par rows'
   butted-together cells above it, drifting further off with every hole (worst by hole 9) since
   nothing closes that gap back up column to column. Scoped to ≥1101px so mobile keeps its gap.

   The border+width rule just below is scoped here for the same reason, and for a second one: every
   .scorecard-cell above has an *explicit* width, so box-sizing: border-box (global, see :root)
   absorbs its border into that width with no change to the rendered box. .stepper has no width of
   its own — it auto-sizes to its 3 children (28+28+.hole-input) — so a border added to it the same
   way would sit *on top of* that auto width instead of being absorbed, overshooting the matching
   header cell by 1px per column (worst by hole 9 again, just far more subtle than the gap bug
   above). Giving it the same explicit width as its header cell fixes that the same way. */
@media (min-width: 1101px) {
  .scorecard-score-row .hole-scores {
    gap: 0;
  }
  #round-holes .scorecard-score-row .hole-scores .stepper {
    width: calc(44px + 56px);
  }
  .add-player-row .scorecard-score-row .hole-scores .stepper {
    width: calc(41px + 56px);
  }
  .scorecard-score-row .hole-scores .stepper {
    border-right: 1px solid var(--color-border);
    border-bottom: 1px solid var(--color-border);
  }
}

/* Below ~1100px there isn't room for all 9 fields plus surrounding chrome even with the narrowed
   per-page .hole-input widths above (measured: Rounds needs ~1080px, Matches ~1045px) — that's
   every phone in either orientation and any tablet in portrait. A horizontal scrollbar there is
   worse than just wrapping, so switch to a fixed 3-per-row grid instead (9 holes / 3 = exactly 3
   full rows, no partial row). Landscape tablets above this width keep the single-line layout. */
@media (max-width: 1100px) {
  .hole-scores {
    display: grid;
    grid-template-columns: repeat(3, max-content);
    justify-content: center;
    overflow-x: visible;
    padding-bottom: 0;
    /* Claims the full row in the surrounding flex container (#round-holes / .add-player-row), the
       same trick .row-break uses — otherwise Putts (the next flex item) sits in whatever space is
       left beside the grid, vertically centered next to one of its rows instead of below all of
       them. */
    flex-basis: 100%;
  }
  /* Doesn't line up with the 3-per-row grid above, so the Hole/Par reference rows are hidden
     rather than shown mismatched — this is the "screen formats large enough" cutoff for the
     scorecard block (computer/iPad landscape). .scorecard-score-row drops out via display: contents
     rather than display: none so its child .hole-scores still renders — see the .hole-entry-group
     comment above for why that specific display value matters here. */
  .scorecard-hole-row,
  .scorecard-par-row {
    display: none;
  }
  .scorecard-score-row {
    display: contents;
  }
  /* display: contents removes .scorecard-score-row's own box, but its "Score" label child is still
     one of the elements it was hiding for — without this it'd leak out as a stray flex item
     alongside the promoted .hole-scores grid. */
  .scorecard-score-row .scorecard-label-cell {
    display: none;
  }
}

.yardage-input { width: 76px; }
.input-narrow { width: 70px; }
.input-medium { width: 80px; }
.full-width { width: 100%; }
#season-name-input { min-width: 18em; }
.chart-secondary { margin-top: 12px; }
.hole-group { margin-bottom: 8px; }
.hole-input-row { margin-top: 4px; }

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

@media (min-width: 800px) {
  .charts-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 600px) {
  main { padding: 12px; }
  header.app-header { padding: 10px 12px; }
  header.app-header h1 { font-size: 1rem; }
  .card { padding: 12px; }
  .hole-input { width: 52px; }
  .yardage-input { width: 70px; }
}
