/* ─────────────────────────────────────────────────────────────────────────
   admin-skins.css — appearance for the ONE admin page.

   There is a single admin template. This sheet is always loaded and does
   nothing until a class appears on <body>, so an admin change is made once
   and every appearance inherits it. Replaces admin-tv.css, whose rules keyed
   off body.tv-mode and only reached the left-hand board.

   One axis:

     body.theme-light  — a light board in the club's blue, with an
                         Apple-style palette: one accent, generous white
                         space, thin hairline borders, and type that carries
                         the contrast rather than heavy fills. Covers both
                         orientations and both sides of the landscape card.

   Shot box size is --shot-box. It is a real variable rather than a fixed
   number so Settings can offer a size slider, and so the TV skin is one
   value rather than a parallel set of rules.
   Operator, 2026-09-19: "If we can just use one admin page with switchable
   theme would be better — if we are making other admin changes we need to
   touch both."
   ───────────────────────────────────────────────────────────────────────── */

:root{
  --shot-box: 18px;   /* default; Settings can override per device */
  --shot-cols: 12;
  --shot-rows: 5;
}

/* ── Shot history: driven entirely by --shot-box ──────────────────────────── */
.ls-shot-history{
  grid-template-columns: repeat(var(--shot-cols, 12), var(--shot-box));
  grid-template-rows:    repeat(var(--shot-rows, 5),  var(--shot-box));
}
.ls-shot-box{
  width:  var(--shot-box);
  height: var(--shot-box);
  font-size: calc(var(--shot-box) * .30);
}
.ls-shot-box .shb{ font-size: calc(var(--shot-box) * .36); }
/* The free-ball star is positioned in px against the original 18px box. */
.ls-shot-box > span{
  font-size: calc(var(--shot-box) * .48) !important;
  top: calc(var(--shot-box) * .07) !important;
  right: calc(var(--shot-box) * .12) !important;
}

/* v5.10.334 — the separate big-screen layout is gone. 12x5 at an
   adjustable size serves a tablet and a TV alike, so there is nothing left
   for a second layout to do, and the amber fouls it carried are superseded
   by the drawn red X the page now uses everywhere.
   Operator: 'get rid of the Big Screen layout in Settings'. */

/* ═══════════════════════════════════════════════════════════════════════════
   theme-light — the blue board, Apple-style
   ═══════════════════════════════════════════════════════════════════════════
   One accent (systemBlue), near-black ink rather than pure black, hairline
   separators at low alpha, and cards that lift with a soft shadow instead of
   a drawn border. Both the scoring board (.ls-left) and the control side
   (.ls-right) sit on the same ground, which the TV skin never did.          */
body.theme-light{
  --ios-blue:   #0A84FF;
  --ios-indigo: #5E5CE6;
  --ios-green:  #30D158;
  --ios-red:    #FF3B30;
  --ios-amber:  #FF9F0A;
  --sky-1: #5AA9F8;   /* light, top-left */
  --sky-2: #2E7FE0;   /* mid, the card face */
  --sky-3: #1560C4;   /* deep, outer ground */
  --ink:      #FFFFFF;
  --ink-dim:  rgba(255,255,255,.78);
  --ink-mute: rgba(255,255,255,.58);
  --hair:     rgba(255,255,255,.22);
  --card:     rgba(255,255,255,.14);
  --card-hi:  rgba(255,255,255,.22);
}

/* The whole working surface, both sides. */
body.theme-light .ls-left,
body.theme-light .ls-right,
body.theme-light #lsMpScore,
body.theme-light #lsPracticePanel{
  background: linear-gradient(160deg, var(--sky-1) 0%,
                                      var(--sky-2) 45%,
                                      var(--sky-3) 100%);
  color: var(--ink);
  border-radius: 18px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.35);
}
body.theme-light .ls-card{ background: transparent; }

/* Cards on that ground: translucent white, hairline, soft lift. */
body.theme-light .ls-player-section,
body.theme-light .ls-panel .setting-row,
body.theme-light .det-vision{
  background: var(--card);
  border: 1px solid var(--hair);
  border-radius: 14px;
}
body.theme-light .ls-player-section{ padding: 10px 12px; }

/* The player at the table. The page marks the turn only on the avatar ring,
   which is easy to miss from across a room; :has() lifts that same state to
   the whole panel with no new markup. */
/* v5.11.300 — a soft sage green (operator: darker was too dark, mid green too lime on the TV): the translucent pale green washed out on a TV
   in light mode (operator: 'not noticeable on TV'). Dark text stays readable. */
body.theme-light .ls-player-section:has(.ls-avatar.active){
  background: linear-gradient(160deg, #A6D49A, #8EC283);
  border-color: #6FA864;
  box-shadow: 0 0 22px rgba(142,194,131,.45), inset 0 1px 0 rgba(255,255,255,.40);
}
body.theme-light .ls-player-section:has(.ls-avatar.active) .ls-pname,
body.theme-light .ls-player-section:has(.ls-avatar.active) .st-val,
body.theme-light .ls-player-section:has(.ls-avatar.active) .st-val-match,
body.theme-light .ls-player-section:has(.ls-avatar.active) .st-val-frame{
  color: #0A2109;
}
body.theme-light .ls-player-section:has(.ls-avatar.active) .st-lbl,
body.theme-light .ls-player-section:has(.ls-avatar.active) .st-col-hdr{
  color: rgba(10,33,9,.72);
}
body.theme-light .ls-player-section:has(.ls-avatar.active) .ls-stat-table td{
  border-color: rgba(10,33,9,.20);
}
body.theme-light #lsMpScore .mp-row.cur,
body.theme-light #lsMpScore .mp-player.cur{
  background: linear-gradient(160deg, rgba(155,227,106,.50), rgba(110,200,70,.34));
  color: #0A2109;
}

/* Type. */
body.theme-light .ls-pname,
body.theme-light .ls-clock,
body.theme-light .ls-left .st-val,
body.theme-light .ls-left .st-val-match,
body.theme-light .ls-left .st-val-frame,
body.theme-light .ls-right,
body.theme-light .sr-label{ color: var(--ink); }
body.theme-light .ls-left .st-lbl,
body.theme-light .ls-left .st-col-hdr,
body.theme-light .sr-sub,
/* v5.11.15 — the corner clock's average line. Its page default is a dim
   WHITE, which is invisible on the blue board; it needs the light skin's
   muted ink like every other secondary label here. Same class of miss as the
   foul badge in v5.10.335 — a new element styled only for the dark board. */
body.theme-light .ls-avg,
body.theme-light .section-hd{ color: var(--ink-dim); }
body.theme-light .ls-left .ls-stat-table td{ border-color: var(--hair); }

/* Score plate: black on white, with a hard edge so it does not dissolve into
   the light top of the gradient. */
body.theme-light .ls-score{
  color: #05070A;
  background: #FFFFFF;
  border: 3px solid rgba(0,0,0,.28);
  border-radius: 14px;
  box-shadow: 0 6px 20px rgba(0,0,0,.28);
  text-shadow: none;
}

/* Reds / Rem / Diff. Dark wells keep each pill's identity colour readable on
   a light ground; the colour lives in the numeral and the hairline. */
body.theme-light .ls-pill{
  background: rgba(6,12,22,.82);
  border-color: rgba(255,255,255,.22);
  color: #E8EDF3;
  box-shadow: 0 6px 18px rgba(0,0,0,.30);
}
body.theme-light .ls-pill .pill-lbl{ color: rgba(255,255,255,.75); opacity: 1; }
body.theme-light .ls-pill.reds{
  background: linear-gradient(135deg, rgba(120,16,16,.92), rgba(6,12,22,.92));
  border-color: rgba(255,96,96,.60); color: #FF8A8A;
}
body.theme-light .ls-pill.rem{
  background: linear-gradient(135deg, rgba(14,78,32,.92), rgba(6,12,22,.92));
  border-color: rgba(126,231,135,.55); color: #9AF0A2;
}
body.theme-light .ls-pill.diff{
  background: linear-gradient(135deg, rgba(92,66,6,.92), rgba(6,12,22,.92));
  border-color: rgba(255,213,74,.60); color: #FFDF7A;
}
/* v5.11.61 — SNOOKERS REQUIRED KEEPS ITS RED. This skin painted it the same
   dark navy as every other chip, and being a later stylesheet it won: the pill
   went red in the base sheet (v5.11.60/61) and still rendered navy on the
   light theme, which is the theme the tables run. Operator: "snookers is not
   in red background box". Same red, reversed letters, sized like the base.   */
body.theme-light .ls-snook{
  background: linear-gradient(180deg,#e53935 0%,#b3261e 100%);
  border: 1px solid rgba(255,255,255,.35);
  border-radius: 999px;
  color: #fff;
  padding: 10px 26px;
  font-size: 30px; line-height: 1.1; font-weight: 900;
  text-shadow: 0 1px 2px rgba(0,0,0,.35);
  box-shadow: 0 2px 12px rgba(200,30,30,.45);
}
body.theme-light .ls-snook b{ color:#fff; }

/* Shot history on blue: a faint white well reads better than a dark one. */
body.theme-light .ls-shot-box{
  border-color: rgba(255,255,255,.32);
  background: rgba(255,255,255,.10);
  color: rgba(255,255,255,.88);
}
body.theme-light .ls-shot-box.empty{
  border-color: rgba(255,255,255,.16);
  background: rgba(255,255,255,.04);
}
body.theme-light .ls-shot-box.t-miss{
  background: rgba(255,255,255,.16);
  border-color: rgba(255,255,255,.34);
  color: rgba(255,255,255,.82);
}
/* v5.10.335 — the foul badge, restated at this specificity ON PURPOSE.
   body.theme-light .ls-shot-box above sets a background for every box, and it
   wins over the page's own .ls-shot-box.t-foul rule (equal specificity, later
   sheet). That is why the red foul box rendered as a plain pale circle on the
   blue board. Restating the paint here, rather than only the colour tokens,
   is what keeps it. */
/* v5.11.16 — FRAME / MATCH timer boxes. The page paints these for the dark
   board: a faint gold/blue wash and #9ecbff digits. This skin's ground IS
   blue, so the match box would be blue-on-blue and its digits would all but
   vanish. Repainted with the skin's own card + hairline, gold for the frame
   box and plain white for the match box — two colours that both hold at a
   distance on this ground. */
body.theme-light .ls-tbox{
  background: var(--card);
  border-color: var(--hair);
}
body.theme-light .ls-tbox-m{
  background: var(--card);
  border-color: var(--hair);
}
body.theme-light .ls-tlbl{ color: var(--ink-dim); }
body.theme-light .ls-tbox-f .ls-tval{ color: #FFD54A; }
body.theme-light .ls-tbox-m .ls-tval{ color: var(--ink); }
/* v5.11.22 — Apply-handicap row on the blue board. */
body.theme-light .hcap-apply{
  border-color: var(--hair); background: var(--card); color: var(--ink);
}
body.theme-light .hcap-apply:has(input:checked){
  border-color: var(--ios-green); background: rgba(48,209,88,.22);
}
body.theme-light .hcap-apply .hcap-hint{ color: var(--ink-mute); }
/* v5.11.23 — New Match steppers / select on the blue board. */
body.theme-light .hcap-btn{ background: var(--card); border-color: var(--hair); color: var(--ink); }
body.theme-light .nm-select{ background: rgba(0,0,0,.35); color: var(--ink); border-color: var(--hair); }

body.theme-light .ls-shot-box.t-foul{
  --foul-fill: #E5342A;           /* systemRed, solid — holds against the blue */
  --foul-edge: rgba(255,255,255,.75);
  background: var(--foul-fill);
  border: 1px solid var(--foul-edge);
  border-radius: 22%;
  color: #fff;
  box-shadow: 0 0 0 1px rgba(0,0,0,.30), 0 2px 6px rgba(0,0,0,.35);
}

/* The detector strip keeps a dark ground — it is the one place where ball
   colour accuracy matters more than the theme. */
body.theme-light .det-vision{ background: rgba(0,0,0,.30); }
body.theme-light .det-vision .det-lbl{ color: var(--ink-dim); }

/* ── Controls: flat translucent keys, systemBlue accent ───────────────────── */
body.theme-light .ab,
body.theme-light .ls-btn,
body.theme-light .nav-btn,
body.theme-light .ls-tab{
  background: var(--card);
  border: 1px solid var(--hair);
  color: var(--ink);
  border-radius: 12px;
}
body.theme-light .ab:active,
body.theme-light .ls-btn:active{ background: var(--card-hi); }
body.theme-light .ls-tab.on{
  background: var(--ios-blue);
  border-color: rgba(255,255,255,.55);
  color: #fff;
}
body.theme-light .toggle.on{ background: var(--ios-green); }
body.theme-light select,
body.theme-light input[type=text],
body.theme-light input[type=number]{
  background: rgba(255,255,255,.16);
  color: var(--ink);
  border: 1px solid var(--hair);
  border-radius: 10px;
}
body.theme-light select option{ background: #1560C4; color: #fff; }


/* ── Portrait (v5.10.331) ──────────────────────────────────────────────────
   The landscape rules above key off .ls-left / .ls-right, which portrait
   does not use: it stacks .topbar, a .page and the bottom nav straight onto
   the body. So the ground goes on the body itself and the pages ride on top
   transparently. Landscape is unaffected — .ls-left paints its own gradient
   over this one. Operator, 2026-09-19: 'Can you also make the theme apply
   to portrait mode too?'                                                   */
body.theme-light{
  background: linear-gradient(170deg, var(--sky-1) 0%,
                                      var(--sky-2) 45%,
                                      var(--sky-3) 100%);
  background-attachment: fixed;
  color: var(--ink);
}
body.theme-light .page,
body.theme-light .p-settings,
body.theme-light .p-matches,
body.theme-light .p-ctrl{ background: transparent; color: var(--ink); }
body.theme-light .topbar{
  background: rgba(255,255,255,.12);
  border-bottom: 1px solid var(--hair);
  color: var(--ink);
}
body.theme-light .topbar-title{ color: var(--ink-dim); }
/* Settings rows read as grouped cards, the way an iOS list does. */
body.theme-light .setting-row{
  background: var(--card);
  border: 1px solid var(--hair);
  border-radius: 12px;
  margin-bottom: 8px;
  padding: 10px 12px;
}
body.theme-light .sr-label{ color: var(--ink); }
body.theme-light .sr-sub{ color: var(--ink-mute); }
body.theme-light .section-hd{
  color: var(--ink-dim);
  border-bottom: 1px solid var(--hair);
}
/* Portrait scoreboard. */
body.theme-light .sp-scores,
body.theme-light .sp-names{ color: var(--ink); }
/* Bottom navigation: a translucent bar with a systemBlue active tab. */
body.theme-light .nav-btn{ background: transparent; border: none; color: var(--ink-mute); }
body.theme-light .nav-btn.on{ color: #fff; background: var(--ios-blue); }

/* ── v5.11.38 — semantic button colours in PORTRAIT ────────────────────────
   Portrait showed flat grey F-4..F-7 while landscape kept brown/blue/pink/
   black. Nothing was wrong with the markup: the light theme's blanket
   `body.theme-light .ab` (specificity 0,2,1) outranks the base `.ab.f4`
   (0,2,0), and landscape only survived because it also has
   `.ls-right .ab.f4` (0,3,0). Operator: 'in the portrait view the F4-F7
   buttons lost their background color should match landscape mode'.
   Restore every semantic variant with the landscape values, at a
   specificity that wins in both layouts.                                  */
body.theme-light .ab.f4{ background:#7b4a2c; border-color:rgba(255,255,255,.30); color:#fff; }
body.theme-light .ab.f5{ background:#1f74d6; border-color:rgba(255,255,255,.30); color:#fff; }
body.theme-light .ab.f6{ background:#d85bb3; border-color:rgba(255,255,255,.35); color:#fff; }
body.theme-light .ab.f7{ background:#101010; border-color:rgba(255,255,255,.30); color:#fff; }
body.theme-light .ab.r { background:#c31111; border-color:rgba(255,255,255,.22); color:#fff; }
body.theme-light .ab.fr{ background:linear-gradient(180deg,#d97706 0%,#92400e 100%);
                         border-color:rgba(255,180,80,.60); color:#fff; }
body.theme-light .ab.dk{ background:linear-gradient(180deg,#b91c1c 0%,#6b0e0e 100%);
                         border-color:rgba(255,90,90,.60); color:#fff; }
body.theme-light .ab.ai-on { background:rgba(0,150,0,.22); border-color:#00a000; color:#0a6b0a; }
body.theme-light .ab.ai-off{ background:rgba(200,0,0,.18); border-color:#c00000; color:#8b0000; }

/* ── The three in-play actions ─────────────────────────────────────────────
   Touching Ball / Free Ball / F&M Re-Spot are the buttons pressed during a
   frame, and since v5.11.37 they have that row to themselves. Colour-code
   them so the right one is found without reading: yellow = declare a
   touching ball, green = give a free ball, red = restore after a foul and a
   miss. Light grounds with dark ink read on both themes, and the existing
   `:disabled` grayscale still washes Free Ball and F&M out until a foul
   makes them legal — so the colour appearing IS the cue that they apply.
   Operator: 'put different color background for the 3 big buttons ...
   light green for free ball, light yellow for touching, light red for F&M'.
   These selectors cover both layouts and both themes; this file loads after
   the inline <style>, so equal specificity resolves here.                 */
/* v5.11.39 — yellow and green swapped: the hand is itself yellow, so it was
   washing into the yellow ground; the target reads better on it. Operator:
   'light green for Touching ball since the hand is yellow, lighter yellow
   for Free ball'.                                                        */
.ab.act-touch, .ls-right .ab.act-touch, body.theme-light .ab.act-touch{
  background:linear-gradient(180deg,#c9f7d4 0%,#7fdf9e 100%);
  border:1px solid rgba(6,90,40,.45); color:#06331a; text-shadow:none; }
.ab.act-free, .ls-right .ab.act-free, body.theme-light .ab.act-free{
  background:linear-gradient(180deg,#fef3c7 0%,#f7d774 100%);
  border:1px solid rgba(120,85,0,.42); color:#3a2c00; text-shadow:none; }
/* v5.11.69 — Choose Colour: lavender, the one ground the row did not have. */
.ab.act-nom, .ls-right .ab.act-nom, body.theme-light .ab.act-nom{
  background:linear-gradient(180deg,#ece2ff 0%,#c4a8f6 100%);
  border:1px solid rgba(70,20,140,.45); color:#2a0a5c; text-shadow:none; }
.ab.act-fm, .ls-right .ab.act-fm, body.theme-light .ab.act-fm{
  background:linear-gradient(180deg,#fecaca 0%,#f59095 100%);
  border:1px solid rgba(110,10,10,.45); color:#4a0b0b; text-shadow:none; }
/* Bigger label on those three. !important is deliberate: the font size is set
   in four places (.ab.ab-multiline, .ls-right .ab.ab-multiline and two
   html[data-tier] rules), and matching each would need a rule per tier per
   layout — one honest override is clearer than nine selectors.            */
/* v5.11.39 — THE ICON IS ITS OWN COLUMN. The label is two lines, so an icon
   sitting inline with the first line reads as part of the word and stays
   small. Lay the button out as a row: icon at full button height on the
   left, the two-line label beside it. The label markup comes from i18n so
   every language gets the same shape. Operator: 'would it be possible to
   have the 3 button icons span 2 rows since text are 2 rows?'            */
/* v5.11.70 — THE ICON IS A LAYER BEHIND THE WORDS. Beside the label it took
   a third of the key and pinned the text small; as a big faded watermark it
   costs nothing, the label gets the whole width, and the key still reads by
   colour and picture from across the room. Same idea as the foul keys' X.
   Operator: 'Can those 4 buttons with icon have a large icon sitting in
   background as another layer so the text can be large?'                 */
.ab.act-big{ font-size:18px !important; line-height:1.08 !important;
             letter-spacing:.2px; font-weight:900;
             display:flex !important; align-items:center; justify-content:center;
             position:relative; overflow:hidden;
             padding-left:6px; padding-right:6px; }
.ab.act-big .act-ico{
  position:absolute; inset:0; z-index:0; pointer-events:none;
  display:flex; align-items:center; justify-content:center;
  font-size:56px; line-height:1; opacity:.30;
  filter:drop-shadow(0 1px 1px rgba(0,0,0,.25)); }
.ab.act-big .act-txt{ position:relative; z-index:1; flex:0 1 auto;
  text-align:center; white-space:normal;
  text-shadow:0 0 6px rgba(255,255,255,.75), 0 0 2px rgba(255,255,255,.9); }
/* Narrow phones: a little smaller, same shape. */
@media (max-width:420px){
  .ab.act-big{ font-size:14px !important; }
  .ab.act-big .act-ico{ font-size:40px; }
}

/* ── v5.11.41 — icon-first buttons on the bottom row ───────────────────
   Replay, Handicap and Sound sat as single 12px glyphs on a row whose other
   buttons carry two lines of text, so they read as half-height gaps between
   End Match and End Frame. Give the glyph the full height of the row, the
   same .act-ico span the three in-play buttons use. Operator: 'the Replay,
   Handicap and Speaker icons can span two rows too' and 'maybe the handicap
   button use icon and HC next to it'.                                      */
.ab.act-glyph, .ls-right .ab.act-glyph, body.theme-light .ab.act-glyph{
  display:flex; align-items:center; justify-content:center; gap:5px;
  padding-left:4px; padding-right:4px; }
.ab.act-glyph .act-ico{
  font-size:30px; line-height:1; flex:0 0 auto;
  display:flex; align-items:center; justify-content:center;
  filter:drop-shadow(0 1px 1px rgba(0,0,0,.25)); }
.ab.act-glyph .act-txt{
  font-size:15px; font-weight:900; letter-spacing:.4px; line-height:1;
  flex:0 1 auto; white-space:nowrap; }
@media (max-width:420px){
  .ab.act-glyph .act-ico{ font-size:25px; }
  .ab.act-glyph .act-txt{ font-size:13px; }
}

/* ── v5.11.64 — the handicap key: small icon, word underneath ──────────
   The other icon keys on that row are glyph-only, so .act-glyph lays them out
   as a single centred row. This one spells itself out, which needs a column
   and a smaller glyph so both lines fit the key height.                    */
.ab.act-glyph.act-stack{ flex-direction:column; gap:1px; padding:4px 2px; }
.ab.act-glyph.act-stack .act-ico{ font-size:19px; }
.ab.act-glyph.act-stack .act-txt{ font-size:12px; font-weight:900;
  letter-spacing:.2px; line-height:1.05; white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis; max-width:100%; }
@media (max-width:420px){
  .ab.act-glyph.act-stack .act-ico{ font-size:16px; }
  .ab.act-glyph.act-stack .act-txt{ font-size:10px; }
}
