*{box-sizing:border-box}
:root{--bg:#eee;--card:#fff;--ink:#222;--sub:#666;--line:#68C000;--head:#ddd}
body{margin:0;background:var(--bg);font-family:Arial,Helvetica,sans-serif;color:var(--ink)}
.app{width:100%;max-width:900px;margin:0 auto;padding:16px}
/* Fixed height, auto width — the mobile/desktop logo files swapped in by
   index.php's <picture> have different aspect ratios, so a fixed
   width+height box (the old plain <img>'s approach) would stretch one of
   them. display:block drops the small baseline gap an inline image gets
   under text content. */
.site-header-logo{display:block;height:84px;width:auto;margin-bottom:.5em}
.admin-bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:6px;font-size:13px;color:var(--sub);margin-bottom:10px}
.admin-bar-status{white-space:nowrap}
.admin-bar .admin-action{text-decoration:none;display:inline-block}
/* The account controls (login/logout) and the informational links
   (Rules of Play, Contact Bowlliards) are grouped in the markup so
   mobile can break them onto their own row each — see the <=600px rule
   below. On wider screens these groups are invisible: `display:contents`
   un-wraps them so their children lay out directly in .admin-bar's own
   flex row, exactly as if the grouping wasn't there. */
.admin-bar-group{display:contents}
.admin-note{font-size:13px;color:var(--sub)}
.admin-note a{color:var(--line);font-weight:bold}
.player-name-highlight{color:var(--line)}
.admin-panel{background:var(--head);border-radius:8px;padding:12px;margin-bottom:16px}
.admin-panel h3{margin-top:0}
/* Every non-scoring button in the app (admin-action links, the "Add
   Player"/"Add Team"/etc. row buttons, Reset/Undo, Save) shares the tab
   buttons' visual language: a bold, rounded, 2px outline that fills with
   a light tint on hover, rather than each control inventing its own
   look. Only .ball-button (the 0-10 scoring buttons on the Play tab)
   keeps its own solid-fill style — those get struck constantly during a
   game and need to read as big colorful keys, not nav-style controls. */
.admin-action,.admin-action-danger,.player-row button,.reset-button,.save-button{
  border:2px solid var(--line);
  border-radius:8px;
  background:none;
  color:var(--line);
  font-weight:bold;
  cursor:pointer;
  transition:background-color .15s ease,color .15s ease,border-color .15s ease;
}
@media (hover:hover) and (pointer:fine){
  .admin-action:hover:not(:disabled),.player-row button:hover:not(:disabled),.reset-button:hover:not(:disabled),.save-button:hover:not(:disabled){background:#cdeba3;color:#777}
}
.admin-action,.admin-action-danger{border-width:1px;border-radius:5px}
.action-row{white-space:nowrap}
.action-row:first-child{margin-bottom:4px}
.admin-action{padding:4px 8px;font-size:12px;margin:0 2px}
.admin-action-danger{border-color:#c0392b;color:#c0392b}
@media (hover:hover) and (pointer:fine){
  .admin-action-danger:hover:not(:disabled){background:#f6d9d3;color:#777}
}
.total-label{display:block;margin-bottom:3px;font-size:11px;font-weight:bold}
h1{margin:0 0 14px;text-align:center;font-size:26px}
.card{background:var(--card);border-radius:10px;box-shadow:0 3px 12px rgba(0,0,0,.15);padding:16px;margin-bottom:14px}
.tabs{display:flex;gap:8px;margin-bottom:14px}
.tab-btn{flex:1;padding:10px;border:2px solid var(--line);border-radius:8px;background:none;color:var(--line);font-weight:bold;font-size:15px;cursor:pointer;transition:background-color .15s ease,color .15s ease}
.tab-btn:hover{background:#cdeba3;color:#777}
.tab-btn.active{background:var(--line);color:#fff}
.tab-btn.active:hover{background:var(--line);color:#fff}
.panel{display:none}
.panel.active{display:block}

.player-row{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:14px}
.player-row select,.player-row input{padding:8px;border:1px solid #999;border-radius:5px;font-size:14px}
.player-row select{flex:1;min-width:140px}
.player-row input{flex:1;min-width:140px}
.player-row button{padding:8px 16px;font-size:14px}

/* play-layout is a grid so ball-buttons can be repositioned beside the
   scoresheet on mobile (see media query below) without changing the
   markup order — desktop just stacks everything in one column. */
.play-layout{width:100%;display:grid;grid-template-columns:1fr;grid-template-areas:"sheet" "title" "balls" "msg" "reset"}
.scoresheet{grid-area:sheet}
.controls-title{grid-area:title;margin-top:14px;margin-bottom:7px;text-align:center;font-size:15px;font-weight:bold}
.ball-buttons{grid-area:balls}
.message{grid-area:msg}
.reset-area{grid-area:reset}

/* Flat spreadsheet-style scoresheet (frame headers / innings / running
   score in one continuous grid, with a merged Handicap+Total box at the
   end of the row) — modeled after the reference scoresheet layout. */
.scoresheet{display:flex;align-items:stretch;border:1px solid #ccc;border-radius:6px;overflow:hidden;background:var(--card)}
.sheet-frames{flex:1;display:grid;grid-template-columns:repeat(5,1fr)}
.sheet-frames>*{border-right:1px solid #ccc;border-bottom:1px solid #ccc}
.sheet-frames>*:nth-child(5n){border-right:none}
.frame-header{padding:6px 2px;background:#e9e9e9;text-align:center;font-size:14px;font-weight:bold}
.frame-innings{display:flex;height:40px}
.inning{flex:1;display:flex;align-items:center;justify-content:center;border-right:1px solid #ddd;font-size:18px;font-weight:bold;transition:background-color .15s ease}
.inning:last-child{border-right:none}
.inning.active{background:#fff9c4}
/* A ball that's already been entered is clickable to change it — see
   selectInningToEdit() in app.js — so it gets a pointer cursor and a
   hover tint; :empty means nothing has been typed into it yet (no text
   node), which also correctly excludes the "you are here" active cell.
   Scoped to .scoresheet.editable (toggled by app.js's
   updateScoresheetEditableClass(), true only while the logged-in player
   still has an unsaved game) so a read-only/already-saved scoresheet
   doesn't show a misleading pointer cursor. */
.scoresheet.editable .inning:not(:empty){cursor:pointer}
@media (hover:hover) and (pointer:fine){.scoresheet.editable .inning:not(:empty):not(.active):hover{background:#eef7dc}}
/* A strike's 1st box is left empty (the X shows in the 2nd box — see
   updateDisplay() in app.js) but is still clickable to edit that strike,
   same as the box showing the X — so it needs the same cursor/hover cue
   even though :not(:empty) above doesn't catch it. */
.scoresheet.editable .inning.strike-empty{cursor:pointer}
@media (hover:hover) and (pointer:fine){.scoresheet.editable .inning.strike-empty:not(.active):hover{background:#eef7dc}}
.frame-score{height:40px;display:flex;align-items:center;justify-content:center;background:#f7f7f7;font-size:20px;font-weight:bold;color:#4a8f00;border-bottom:none}

.side-box{width:110px;flex:0 0 110px;border-left:2px solid #ccc;background:#fafafa;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:8px;gap:8px}
.side-pair{display:flex;flex-direction:column;align-items:center}
.side-label{font-size:11px;font-weight:bold;color:var(--sub);text-transform:uppercase;letter-spacing:.3px}
.side-value{font-size:22px;font-weight:bold;color:#4a8f00}

.ball-buttons{display:flex;align-items:center;justify-content:center;gap:6px;flex-wrap:wrap}
.ball-button{width:42px;height:38px;border:1px solid transparent;border-radius:5px;background:var(--line);color:#fff;font-size:16px;font-weight:bold;cursor:pointer;transition:background-color .15s,border-color .15s,color .15s,transform .1s}
@media (hover:hover) and (pointer:fine){.ball-button:hover:not(:disabled){background:none;border-color:var(--line);color:var(--line)}}
.ball-button:active:not(:disabled){transform:scale(.96)}
.ball-button:disabled{background:#aaa;color:#fff;cursor:not-allowed}
.message{min-height:22px;margin-top:8px;text-align:center;font-size:14px;font-weight:bold}
.reset-area{text-align:center;display:flex;flex-wrap:wrap;gap:10px;justify-content:center}
.reset-button{margin-top:12px;padding:8px 22px;font-size:14px}
.reset-button:disabled{background:#aaa;color:#fff;border-color:#aaa;cursor:not-allowed}
/* Save keeps its own blue accent (distinct from the green used
   everywhere else) so it still reads as the primary action on the
   scoresheet, but otherwise follows the same outline/hover language as
   every other button here. */
.save-button{margin-top:12px;padding:8px 22px;font-size:14px;border-color:#1b6fd1;color:#1b6fd1}
@media (hover:hover) and (pointer:fine){.save-button:hover:not(:disabled){background:#d7e9fb;color:#777}}
.save-button:disabled{background:#aaa;color:#fff;border-color:#aaa;cursor:not-allowed}

/* ============ MOBILE SCORESHEET (<=600px) ============
   Matches the reference: each frame becomes its own row (# | innings |
   score), the ball buttons form a vertical column running alongside the
   table instead of a row underneath, and Handicap/Total move to a
   single footer row below the table. */
@media (max-width: 600px) {
  /* Two clean, centered rows instead of the desktop single-line strip
     wrapping wherever it runs out of room (which, right-aligned, tended
     to leave an odd one- or two-item line stranded oddly on its own).
     Row 1: account controls (who's logged in / login links). Row 2: the
     informational links (Rules of Play, Contact Bowlliards). */
  .admin-bar{flex-direction:column;align-items:center;justify-content:center;gap:4px}
  .admin-bar-group{display:flex;flex-wrap:wrap;justify-content:center;gap:6px;width:100%}

  .play-layout{
    grid-template-columns:1fr 72px;
    /* Column 1 (1fr) always holds title/sheet/msg/reset, so they share
       one centered width with each other — title/msg don't span into
       column 2, unlike an earlier version of this layout, where they
       spanned the full row (buttons included) while reset only centered
       within the narrower column, so their centers didn't line up.
       "balls" only repeats in the sheet/msg/reset rows (not title) so
       the button column's top starts level with the scoresheet's top,
       not higher up alongside the title. */
    grid-template-areas:"title ." "sheet balls" "msg balls" "reset balls";
    column-gap:8px;
    align-items:start;
  }
  /* Both of these are confined to the left column now (see
     grid-template-areas above) — pinned to full width of that column and
     centered explicitly here so they can't end up hugging one side. */
  .controls-title{width:100%;text-align:center}
  .message{width:100%;text-align:center}
  .scoresheet{flex-direction:column}
  .sheet-frames{grid-template-columns:34px 1fr 56px}
  /* Reposition the 15 children (5 headers, then 5 innings, then 5
     scores, in that source order) into one row per frame. */
  .sheet-frames>*:nth-child(1){grid-row:1;grid-column:1}
  .sheet-frames>*:nth-child(2){grid-row:2;grid-column:1}
  .sheet-frames>*:nth-child(3){grid-row:3;grid-column:1}
  .sheet-frames>*:nth-child(4){grid-row:4;grid-column:1}
  .sheet-frames>*:nth-child(5){grid-row:5;grid-column:1}
  .sheet-frames>*:nth-child(6){grid-row:1;grid-column:2}
  .sheet-frames>*:nth-child(7){grid-row:2;grid-column:2}
  .sheet-frames>*:nth-child(8){grid-row:3;grid-column:2}
  .sheet-frames>*:nth-child(9){grid-row:4;grid-column:2}
  .sheet-frames>*:nth-child(10){grid-row:5;grid-column:2}
  .sheet-frames>*:nth-child(11){grid-row:1;grid-column:3}
  .sheet-frames>*:nth-child(12){grid-row:2;grid-column:3}
  .sheet-frames>*:nth-child(13){grid-row:3;grid-column:3}
  .sheet-frames>*:nth-child(14){grid-row:4;grid-column:3}
  .sheet-frames>*:nth-child(15){grid-row:5;grid-column:3}
  .sheet-frames>*:nth-child(n+11){border-right:none}
  /* The desktop-only "nth-child(5n){border-right:none}" rule above also
     matches frame 5's header (5) and innings (10) cells here, since the
     mobile layout repositions them into row 5 instead of column 5 —
     restore their dividers. */
  .sheet-frames>*:nth-child(5),.sheet-frames>*:nth-child(10){border-right:1px solid #ccc}
  .frame-innings{height:44px}
  .frame-score{height:44px;border-bottom:1px solid #ccc}

  .side-box{
    width:auto;flex:0 0 auto;
    flex-direction:row;justify-content:space-around;
    border-left:none;border-top:2px solid #ccc;
    padding:10px 4px;gap:0;
  }
  .side-pair{flex-direction:row;gap:6px;padding:0 14px}
  .side-pair+.side-pair{border-left:1px solid #ccc}

  .ball-buttons{
    grid-area:balls;
    flex-direction:column;flex-wrap:nowrap;align-items:center;
    gap:6px;
  }
  /* Same fixed size as the desktop/landscape buttons (width:42px;
     height:38px, set in the base .ball-button rule above) — just
     stacked in a column instead of wrapped in a row. */
  .ball-button{flex:none}
}

.final-score{margin-top:14px;text-align:center;font-size:16px;font-weight:bold}

/* Edit Game form (admin/player game correction) — styled to echo the Play
   tab's scoresheet grid (frame-numbered boxes across a row), but with its
   own classes: see the comment above buildEditGameFormHtml() in app.js for
   why this doesn't reuse .scoresheet/.sheet-frames/.frame-header/etc. */
/* display:inline-block (not the default block) so this box shrink-wraps
   to its content's width instead of stretching to fill (and clip) the
   .table-scroll ancestor it sits in — on a narrow screen that lets the
   480px-min-width grid below stick out past the box and become the thing
   .table-scroll's overflow-x:auto actually scrolls. A block box here,
   or overflow:hidden on it, would instead just cut the grid off flush at
   screen width with nothing to scroll. */
.edit-scoresheet{display:inline-block;min-width:100%}
.edit-sheet-frames{display:grid;grid-template-columns:repeat(5,1fr);min-width:600px;border:1px solid #ccc;border-radius:6px;overflow:hidden;background:var(--card)}
.edit-sheet-frames>*{border-right:1px solid #ccc;border-bottom:1px solid #ccc}
.edit-sheet-frames>*:nth-child(5n){border-right:none}
.edit-frame-header{padding:6px 2px;background:#e9e9e9;text-align:center;font-size:14px;font-weight:bold}
.edit-frame-innings{display:flex;align-items:center;justify-content:center;gap:5px;padding:10px 3px;border-bottom:none}
.edit-inning-input{width:52px;padding:4px 2px;text-align:center;font-size:15px;border:1px solid var(--line);border-radius:4px}
.edit-frame-innings-bonus{gap:4px}
.edit-frame-innings-bonus .edit-inning-input{width:42px;padding:4px 1px}

.table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:0 -16px;padding:0 16px}
.mobile-toast{
  position:fixed;left:50%;top:50%;transform:translate(-50%,-50%) scale(.95);
  width:220px;max-width:80vw;background:#dcdcdc;color:#111;
  padding:22px 18px 20px;border-radius:18px;box-shadow:0 8px 30px rgba(0,0,0,.35);
  opacity:0;transition:opacity .25s ease,transform .25s ease;z-index:1000;
  text-align:center;display:flex;flex-direction:column;align-items:center;gap:14px;
}
.mobile-toast.show{opacity:1;transform:translate(-50%,-50%) scale(1)}
.mobile-toast-icon{
  width:130px;height:130px;border-radius:50%;background:#c9c9c9;
  border:2px solid #fff;box-shadow:0 2px 6px rgba(0,0,0,.15);
  display:flex;align-items:center;justify-content:center;
}
.mobile-toast-text{font-size:17px;font-weight:bold;line-height:1.3}
table.standings-table{width:100%;min-width:560px;border-collapse:collapse;font-size:14px}
.standings-table th,.standings-table td{padding:8px 6px;text-align:center;border-bottom:1px solid #ccc}
.standings-table th{background:var(--head)}
.standings-table td:first-child,.standings-table th:first-child{text-align:left}
.standings-table tbody tr:nth-child(1) td:first-child{font-weight:bold;color:#4a8f00}
.standings-table th.sortable{cursor:pointer;user-select:none}
.standings-table th.sortable:hover{background:#e2e2e2}
.standings-table .sort-arrow{font-size:11px;color:#4a8f00;margin-left:2px}
.sort-indicator{font-size:13px;font-weight:bold;color:#4a8f00;margin:4px 0 10px}
.standings-table tr.stats-row td{text-align:left;padding:8px 6px 16px}
.standings-table tr.stats-row .admin-panel{margin-bottom:0}
.standings-table tr.edit-game-row td{text-align:left;padding:8px 6px 16px}
.standings-table tr.edit-game-row .admin-panel{margin-bottom:0}
h3{margin:16px 0 8px;font-size:16px}
#recent-games{list-style:none;padding:0;margin:0;font-size:14px}
#recent-games li{padding:6px 0;border-bottom:1px solid #ccc;display:flex;justify-content:space-between}
.recent-game-date{margin-left:14px}
.team-tag{color:var(--sub);font-size:12px}
.empty-note{color:var(--sub);font-size:13px;text-align:center;padding:10px}

.stats-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:10px;margin-top:10px}
.stat-tile{background:var(--card);border:1px solid #ddd;border-radius:8px;padding:10px;text-align:center}
.stat-tile .stat-value{font-size:20px;font-weight:bold;color:#4a8f00}
.stat-tile .stat-label{margin-top:2px;font-size:10px;font-weight:bold;color:var(--sub);text-transform:uppercase;letter-spacing:.3px}
