/* Nine Jobs — navy and orange, with red reserved for the ball. */

:root {
  /* --- West Toronto Baseball brand --- */
  --wt-navy:  #0c2340;   /* the crest navy */
  --wt-white: #ffffff;
  --orange:   #ff8442;   /* Claude orange, pushed brighter and more saturated */
  --orange-lt:#ffa172;   /* the same orange lifted, for text on dark navy */
  --red:      #ff4757;   /* the ball: who has it, and where it went */

  /* The page is the darkest surface. Cards sit LIGHTER than it and carry no
     border — the lift alone separates them, so nothing needs a stroke. */
  --bg:      #030a14;    /* very dark navy */
  --panel:   #0c1f38;    /* cards, header, AND the field backdrop */
  --inset:   #142c4e;    /* strips and rows inside a card */
  --panel2:  #1b3c68;    /* button faces */
  --line:    #2a4d80;
  --ink:     #eaf0fb;
  --dim:     #93a7cc;
  --accent:  var(--orange);

  /* One-screen budget. --chrome is header + page padding + footer; the trims
     are each card's own padding and furniture, so the tallest column can be
     told exactly how much room is left. Measured, not guessed. */
  --chrome:   170px;
  --cardtrim:  62px;   /* fieldwrap padding + the hint/button bar below the svg */
  --listtrim:  58px;   /* assignments card padding + its "ASSIGNMENTS" heading */

  /* Keelesdale turf and clay — deep and saturated so it holds up on navy */
  --grass:   #16501f;   /* park grass, foul side of the lines */
  --grass2:  #1b6127;   /* fair territory */
  --grass3:  #22732f;   /* the infield octagon */
  --dirt:    #a8511c;   /* clay */
  --track:   #86400f;   /* warning track */
  --chalk:   #f2f4f7;
  --pole:    #ffd23f;   /* foul poles */

  /* role colours — all chosen to hold up against navy */
  --field:   var(--red);   /* has the ball */
  --cut:     #f2b233;
  --cover:   #5fa8ff;
  --backup:  #9c7bff;
  --trail:   #ff8a3d;
  --hold:    #5a6e92;
}

* { box-sizing: border-box; }

/* Stop iOS Safari inflating text when the phone turns landscape. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.5 ui-sans-serif, system-ui, "Segoe UI", Roboto, sans-serif;
}

/* logo | centred brand | patch. The 1fr side columns are what keep the title
   optically centred no matter how wide the badge on the right gets. */
header {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center; gap: 12px;
  padding: 10px 22px;
  padding-left: max(22px, env(safe-area-inset-left));
  padding-right: max(22px, env(safe-area-inset-right));
  background: var(--panel);       /* same surface as the cards */
}
.logo { width: 46px; height: 46px; justify-self: start; }
.logo-text {
  text-anchor: middle;
  /* Geometric sans to match the mark; falls back through the system stack. */
  font-family: Futura, "Century Gothic", "Avenir Next", "Trebuchet MS", system-ui, sans-serif;
  font-weight: 600; font-size: 56px; letter-spacing: -1px;
}
/* Two-tone: the 9 in the site orange, the J's in white. Splitting the colours
   is what keeps the mark readable down at favicon size. */
.logo-9      { fill: var(--orange); }
.logo-j      { fill: var(--wt-white); }
.logo-suffix { fill: var(--wt-white); font-size: 0.52em; }

.brand { text-align: center; }
header h1 { font-size: 19px; margin: 0; letter-spacing: .2px; }
header .sub { display: block; margin: 1px 0 0; font-weight: 400; font-size: 12.5px; color: var(--dim); }

.headright { justify-self: end; display: flex; align-items: center; gap: 10px; }
.headright .patch { width: 56px; height: 56px; }

/* ---------- memorial patch ----------
   A club wears one of these on the sleeve for the season after losing someone.
   Navy disc, orange ring, orange lettering — the app's own colours, no club
   marks. The viewBox is fixed, so it stays centred at any rendered size. */
.patch { width: 44px; height: 44px; flex: 0 0 auto; }
/* The header is navy too, so the disc needs its own edge or the patch reads as
   a floating ring. Darker fill plus a defined rim gives it a physical edge. */
.patch-disc { fill: #061428; stroke: #2b4a7a; stroke-width: 1.5; }
.patch-ring { fill: none; stroke: var(--orange); stroke-width: 2; }
.patch-name, .patch-num {
  fill: var(--orange); text-anchor: middle;
  font-family: "Arial Narrow", Impact, Haettenschweiler, system-ui, sans-serif;
  font-weight: 800;
}
.patch-name { font-size: 20px; letter-spacing: 2px; }
.patch-num  { font-size: 46px; }

footer {
  text-align: center;
  padding: 2px 22px 16px;
  padding-bottom: max(16px, env(safe-area-inset-bottom));
  font-size: 12px; color: var(--dim);
}

/* settings | field | assignments */
main {
  display: grid;
  grid-template-columns: 310px minmax(0, 1fr) 350px;
  gap: 16px;
  padding: 16px 20px 20px;
  padding-left: max(20px, env(safe-area-inset-left));
  padding-right: max(20px, env(safe-area-inset-right));
  align-items: start;
}
@media (max-width: 1400px) { main { grid-template-columns: 290px minmax(0, 1fr) 310px; } }
@media (max-width: 1120px) {
  main { grid-template-columns: 300px minmax(0, 1fr); }
  .panel.right { grid-column: 1 / -1; }
  .panel.right .assign { max-height: none; }
}
/* Tablets in portrait (iPad is 810px) go single-column too. Held at two
   columns they gave the field only ~438px, which squeezed the diamond and made
   the on-field labels unreadable; full width takes it to ~770px. */
@media (max-width: 900px) {
  main { grid-template-columns: 1fr; }
  .panel.right { grid-column: auto; }

  /* Field first. Stacked, the Situation card sits above the diamond and its
     buttons rewrap as options are toggled, which shoves the field up and down
     the page under your thumb. Putting the field on top pins it in place and
     the controls move instead. */
  .fieldwrap  { order: -1; }
  .panel.left { order: 0; }
  .panel.right{ order: 1; }
}

/* Side-by-side layout only: cap every column at the space actually left over,
   so the page itself never scrolls and the tribute is always on screen. The
   assignments list already worked this way; the settings card now matches. On a
   720p window its content genuinely cannot fit, so it scrolls inside its own
   card rather than pushing the footer off the bottom. */
@media (min-width: 901px) {
  .panel.left .group {
    max-height: calc(100vh  - var(--chrome));
    max-height: calc(100dvh - var(--chrome));
    overflow-y: auto;
  }
}

/* Short laptop screens: on a 1366x768 the settings card, not the field, is the
   tallest thing on the page. Tighten the spacing so the tribute stays on screen
   instead of forcing a scroll. Width-gated so phones keep their roomier touch
   spacing. */
@media (min-width: 901px) and (max-height: 850px) {
  /* Everything below shrinks the chrome, so the budget shrinks with it. */
  :root { --chrome: 150px; }
  header { padding-top: 7px; padding-bottom: 7px; }
  header h1 { font-size: 17px; }
  main { padding-top: 12px; padding-bottom: 14px; }
  .group { padding: 11px; }
  .group h2 { margin-bottom: 7px; }
  .lbl { margin: 8px 0 5px; }
  .seg { gap: 5px; }
  button { padding: 5px 10px; }
  .statestrip { margin-top: 6px; padding: 5px 9px; }
  .callout { margin-top: 9px; padding: 8px 10px; }
  footer { padding-bottom: 10px; }
}

/* ---------- field ---------- */
.fieldwrap {
  background: var(--panel);
  border-radius: 12px;
  padding: 8px;
}
svg#field {
  width: 100%;
  height: auto;
  /* The whole app is meant to fit one screen, tribute included. --chrome is
     everything above and below the columns (header, page padding, footer) and
     --cardtrim is the card's own padding plus the button bar under the field.
     iOS Safari counts the URL bar inside 100vh, so the dvh line is the real
     one; the vh line above it is the fallback for browsers without dvh. */
  max-height: calc(100vh  - var(--chrome) - var(--cardtrim));
  max-height: calc(100dvh - var(--chrome) - var(--cardtrim));
  display: block;
  touch-action: none;             /* dragging the ball must never scroll the page */
  cursor: crosshair;
  border-radius: 6px;
  /* Long-pressing to drag otherwise raises the iOS copy/share sheet. */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

/* The backdrop behind the diamond is the SAME fill as the settings and
   assignments cards, so the field reads as artwork sitting on the card
   rather than as a separate blue panel. */
.foulground { fill: var(--panel); }
.grass      { fill: var(--grass2); }   /* fair outfield */
.infgrass   { fill: var(--grass3); }   /* inside the base paths */
.track      { fill: var(--track); }
.dirt       { fill: var(--dirt); }
.basepath   { stroke: var(--dirt); stroke-width: 5; fill: none; opacity: .95; }
.mound      { fill: var(--dirt); }
.foulline   { stroke: var(--chalk); stroke-width: 1.6; opacity: .9; fill: none; }
.fence      { stroke: #06101f; stroke-width: 3; fill: none; }
/* Yellow markers standing where each foul line ends at the wall. */
.foulpole   { fill: var(--pole); }
.bag        { fill: #fff; }

/* Where the ball went — red, matching the fielder who has to go get it. */
.hitpath { stroke: var(--red); stroke-width: 1.8; stroke-dasharray: 5 4; fill: none; opacity: .95; }
.throw   { stroke: #fff; stroke-width: 1.8; stroke-dasharray: 2 3; fill: none; opacity: .75; }

/* Position nodes: small, navy-filled, white ring. Role colour rides on the
   ring so the node itself stays navy in every state. */
.player circle { fill: var(--wt-navy); stroke: var(--wt-white); stroke-width: 2; }
.player .plabel   { fill: #fff; font-size: 9.5px; font-weight: 700; text-anchor: middle; }
.player .rolelabel{ fill: #fff; font-size: 8px; font-weight: 700; text-anchor: middle;
                    paint-order: stroke; stroke: var(--wt-navy); stroke-width: 3; }
.player { transition: none; }

.player.r-field  circle { stroke: var(--field);  }
.player.r-cut    circle { stroke: var(--cut);    }
.player.r-cover  circle { stroke: var(--cover);  }
.player.r-backup circle { stroke: var(--backup); }
.player.r-trail  circle { stroke: var(--trail);  }
.player.r-hold   circle { stroke: var(--hold);   opacity: .8; }

/* The ball marker reads as a baseball: white with a red stitch ring, so the
   ball, its path and the fielder chasing it are all the same colour. */
.marker circle { fill: var(--wt-white); stroke: var(--red); stroke-width: 2; }
.marker .halo  { fill: var(--red); opacity: .22; stroke: none; }

.fieldbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 10px; }
.hint { color: var(--dim); font-size: 12.5px; flex: 1 1 240px; }
.hint b { color: var(--ink); }
.btnrow { display: flex; gap: 8px; }

button {
  font: inherit; font-size: 12.5px;
  background: var(--panel2); color: var(--ink);
  border: 1px solid var(--line); border-radius: 7px;
  padding: 7px 11px; cursor: pointer;
}
button:hover { border-color: #3d63a8; }
button.on { background: var(--wt-navy); border-color: var(--orange); color: #fff; }
button.primary { background: var(--orange); border-color: var(--orange); color: var(--wt-navy); font-weight: 700; }
button.primary:hover { filter: brightness(1.1); }

/* ---------- panel ---------- */
.panel { display: flex; flex-direction: column; gap: 14px; }
.group {
  background: var(--panel);
  border-radius: 12px; padding: 14px;
}
.group h2 { margin: 0 0 10px; font-size: 12px; text-transform: uppercase;
            letter-spacing: 1.1px; color: var(--dim); }
.lbl { display: block; font-size: 11px; color: var(--dim); margin: 12px 0 6px;
       text-transform: uppercase; letter-spacing: .6px; }
.lbl:first-of-type { margin-top: 0; }

.seg { display: flex; gap: 6px; flex-wrap: wrap; }
.seg.wrap button { flex: 1 1 auto; text-align: left; }

.statestrip {
  margin-top: 8px; padding: 7px 10px; border-radius: 7px;
  background: var(--inset); border: 1px solid var(--line);
  font-size: 13px; font-weight: 600; color: var(--orange-lt);
}

.callout {
  margin-top: 12px; padding: 10px 12px; border-radius: 8px;
  background: var(--inset); border: 1px solid var(--line);
  font-size: 12.5px; color: var(--dim);
}
.callout b { color: var(--ink); font-size: 13px; }
.callout ul { margin: 7px 0 0; padding-left: 16px; }
.callout li { margin: 3px 0; }
.callout p  { margin: 6px 0 0; }

.assign {
  display: flex; flex-direction: column; gap: 6px;
  max-height: calc(100vh  - var(--chrome) - var(--listtrim));
  max-height: calc(100dvh - var(--chrome) - var(--listtrim));
  overflow-y: auto;
}
.arow {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 8px 10px; border-radius: 8px;
  background: var(--inset); border-left: 3px solid var(--hold);
}
.arow .chip {
  flex: 0 0 34px; text-align: center; font-weight: 800; font-size: 11.5px;
  background: var(--panel2); border-radius: 5px; padding: 3px 0;
}
.arow .role { font-size: 12px; font-weight: 700; letter-spacing: .3px; }
.arow .detail { font-size: 12px; color: var(--dim); }

.arow.r-field  { border-left-color: var(--field);  } .arow.r-field .role  { color: var(--field); }
.arow.r-cut    { border-left-color: var(--cut);    } .arow.r-cut .role    { color: var(--cut); }
.arow.r-cover  { border-left-color: var(--cover);  } .arow.r-cover .role  { color: var(--cover); }
.arow.r-backup { border-left-color: var(--backup); } .arow.r-backup .role { color: var(--backup); }
.arow.r-trail  { border-left-color: var(--trail);  } .arow.r-trail .role  { color: var(--trail); }
.arow.r-hold   { opacity: .68; }

/* ================= touch and small screens ================= */

/* Keyed on the pointer, not the width: a desktop browser dragged narrow keeps
   the compact controls, while an iPad at 1080px still gets real touch targets.
   44px is Apple's minimum and these buttons are the whole interface. */
@media (pointer: coarse) {
  button {
    min-height: 44px;
    padding: 11px 14px;
    font-size: 14px;
  }
  .seg { gap: 8px; }
  svg#field { cursor: default; }
}

/* The labels are drawn in viewBox units against a 550-unit-wide canvas, so what
   a reader actually sees is (units x fieldWidth / 550). The narrower the column,
   the bigger the units have to be. Measured render sizes drive these numbers:
   left alone, an 8-unit role label lands near 5px on a 390px phone. */
@media (max-width: 1120px) {          /* two columns, field ~544-764px */
  .player .plabel    { font-size: 11px; }
  .player .rolelabel { font-size: 9.5px; }
}
@media (max-width: 640px) {           /* phones, field ~300-600px */
  .player .plabel    { font-size: 16px; }
  .player .rolelabel { font-size: 14px; }
}
@media (max-width: 900px) {
  main { padding-bottom: 20px; }

  /* Because the field swallows touches (touch-action: none), it must never
     fill the viewport — otherwise there is nothing left to scroll the page by. */
  svg#field {
    max-height: 70vh;
    max-height: 70dvh;
  }

  header { padding: 12px 16px; gap: 10px; }
  header h1 { font-size: 17px; }
  header .sub { display: block; margin-left: 0; font-size: 12px; }
  .patch { width: 34px; height: 34px; }

  /* Readable at arm's length in a dugout. */
  .arow .role   { font-size: 13px; }
  .arow .detail { font-size: 13px; }
  .hint { font-size: 13px; }
  .callout { font-size: 13px; }
}
