/* style.css — Pikmin Bloom themed mushroom calculator */

/* ── Design tokens ──────────────────────────────────────────────── */
:root {
  --bg:        #dff5c8;
  --surface:   #f4fced;
  --s2:        #eaf8d8;
  --s3:        #d8f0c0;
  --border:    #a8d880;
  --border2:   #78bc48;
  --pri:       #4a9e30;
  --pri-dk:    #286018;
  --pri-lt:    #c8edb0;
  --pri-glow:  rgba(74,158,48,.14);
  --amb:       #e88010;
  --amb-dk:    #a04808;
  --amb-lt:    #fdebd0;
  --pur:       #7040c8;
  --pur-lt:    #ecddf8;
  --pur-dk:    #4a1890;
  --blu:       #2878c8;
  --blu-lt:    #d0e8f8;
  --txt:       #102810;
  --txt2:      #2a5020;
  --txt3:      #588038;
  --txt4:      #90b068;
  --red:       #c02020;
  --red-lt:    #fce4e4;
  --ok:        #209840;
  --gold:      #e8b020;
  /* Neutral grey for "planned" (not-yet-joined) data — distinct from --gold (ticket ring) and
     --amb (which reads too close to gold at a glance, per feedback). */
  --grey:      #8a8a8a;
  --grey-dk:   #565656;
  --grey-lt:   #e2e2e2;
  /* User-picked coral/maroon outline for "reachable via bonus, not earned outright yet" hint stars */
  --hint-outline: #fb686e;
  --mono:      'JetBrains Mono', 'Fira Mono', monospace;
  --sans:      'Nunito', 'Segoe UI', sans-serif;
  --r:         14px;
  --rs:        8px;
  --shadow:    0 2px 12px rgba(20,60,10,.10);
  --shadow-md: 0 6px 28px rgba(20,60,10,.16);
}

/* ── Reset ──────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  background:    var(--bg);
  color:         var(--txt);
  font-family:   var(--sans);
  font-size:     15px;
  min-height:    100vh;
  padding-bottom: 60px;
  background-image: radial-gradient(ellipse 80% 60% at 50% -10%, rgba(120,210,60,.18) 0%, transparent 70%);
  overflow-x:    hidden; /* safety net so a stray wide element can't force a page-level h-scroll */
}

/* ── Under-construction banner (shown only if a source file changed within the last 10 min) ──
   position:fixed + a matching body padding-top (added only while shown) instead of sticky — the
   navbar is ALSO sticky, and a sticky element's "stick point" is its own `top` value, not
   anything about ancestor padding — so the navbar ALSO needs its `top` pushed down to 30px
   (below the fixed banner) whenever the banner is showing, or it sticks right back underneath
   the banner the moment you scroll, even though its initial (unscrolled) position looked fine. */
/* ── v5 -> v6 import banner (mushroom list card) ─────────────────── */
.v5-import-banner {
  display:      flex;
  align-items:  center;
  gap:          8px;
  flex-wrap:    wrap;
  background:   var(--amb-lt);
  border:       1.5px dashed var(--amb);
  border-radius: var(--rs);
  padding:      8px 10px;
  margin-bottom: 10px;
  font-size:    12px;
}
.v5-import-banner span { flex: 1 1 auto; }

/* ── Floating clock (bottom-right; js/clock.js) ──────────────────── */
.floating-clock {
  position:      fixed;
  bottom:        16px;
  right:         16px;
  z-index:       150;
  display:       flex;
  align-items:   baseline;
  gap:           6px;
  background:    var(--pri-dk);
  color:         #fff;
  padding:       6px 12px;
  border-radius: 20px;
  box-shadow:    var(--shadow-md);
  font-size:     13px;
  font-weight:   800;
  font-variant-numeric: tabular-nums;
}
.clock-zone {
  font-size:   10px;
  font-weight: 700;
  color:       var(--pri-lt);
  cursor:      help;
  white-space: nowrap;
}

.uc-banner {
  position: fixed; top: 0; left: 0; right: 0; z-index: 200; height: 30px;
  display: flex; align-items: center; justify-content: center;
  background: repeating-linear-gradient(135deg, var(--amb) 0 14px, var(--amb-dk) 14px 28px);
  color: #fff; text-align: center; font-weight: 900; font-size: 11px;
  letter-spacing: .04em; padding: 0 10px; text-shadow: 0 1px 2px rgba(0,0,0,.4);
}
body.has-uc-banner { padding-top: 30px; }
body.has-uc-banner .navbar { top: 30px; }

/* ── Navbar ─────────────────────────────────────────────────────── */
.navbar {
  background:   var(--pri-dk);
  display:      flex;
  align-items:  center;
  gap:          10px;
  min-height:   52px;
  padding:      8px 16px;
  position:     sticky;
  top:          0;
  z-index:      100;
  box-shadow:   0 2px 14px rgba(0,0,0,.22);
}
.navbar h1 {
  font-size: 17px; font-weight: 900; color: #fff; letter-spacing: .04em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; flex-shrink: 1;
}
.navbar-right { margin-left: auto; display: flex; gap: 8px; align-items: center; flex-shrink: 0; }
.offline-indicator {
  font-size:      11px;
  font-weight:    800;
  color:          var(--amb-lt);
  background:     var(--amb-dk);
  padding:        3px 8px;
  border-radius:  12px;
  white-space:    nowrap;
}
.lbl-icon { display: none; }
.btn-icon-gear {
  background: transparent; border: 1.5px solid rgba(255,255,255,.4); border-radius: var(--rs);
  color: #fff; font-size: 16px; padding: 6px 10px; cursor: pointer; line-height: 1; transition: all .12s;
}
.btn-icon-gear:hover { background: rgba(255,255,255,.12); border-color: #fff; }

/* ── Layout ─────────────────────────────────────────────────────── */
.main { max-width: 820px; margin: 0 auto; padding: 16px 12px; }
.section-gap { margin-bottom: 14px; }

/* ── Card ───────────────────────────────────────────────────────── */
.card {
  background:    var(--surface);
  border:        1.5px solid var(--border);
  border-radius: var(--r);
  padding:       16px;
  box-shadow:    var(--shadow);
}
.card-title {
  font-size:       11px;
  font-weight:     800;
  letter-spacing:  .14em;
  text-transform:  uppercase;
  color:           var(--txt3);
  margin-bottom:   14px;
  display:         flex;
  align-items:     center;
  gap:             8px;
}
.card-title::after { content: ''; flex: 1; height: 1.5px; background: linear-gradient(90deg, var(--border), transparent); }

/* ── Form elements ──────────────────────────────────────────────── */
.field { display: flex; flex-direction: column; gap: 4px; }
.field label { font-size: 10px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--txt3); }

select, input[type=number], input[type=text] {
  background:    var(--s2);
  border:        1.5px solid var(--border);
  border-radius: var(--rs);
  color:         var(--txt);
  font-family:   var(--mono);
  font-size:     13px;
  padding:       8px 10px;
  width:         100%;
  outline:       none;
  transition:    border-color .15s, box-shadow .15s;
}
select:focus, input[type=number]:focus, input[type=text]:focus {
  border-color: var(--pri);
  box-shadow:   0 0 0 3px var(--pri-glow);
}
select {
  background-image:    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23588038'/%3E%3C/svg%3E");
  background-repeat:   no-repeat;
  background-position: right 10px center;
  padding-right:       28px;
  cursor:              pointer;
  -webkit-appearance:  none;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; }

.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

/* ── Buttons ────────────────────────────────────────────────────── */
.btn {
  display:         inline-flex;
  align-items:     center;
  justify-content: center;
  gap:             6px;
  font-family:     var(--sans);
  font-size:       12px;
  font-weight:     800;
  letter-spacing:  .06em;
  padding:         9px 16px;
  border-radius:   var(--rs);
  border:          1.5px solid transparent;
  cursor:          pointer;
  transition:      all .15s;
  white-space:     nowrap;
  user-select:     none;
  -webkit-user-select: none;
}
.btn-pri     { background: var(--pri);    border-color: var(--pri);    color: #fff; }
.btn-pri:hover   { background: var(--pri-dk); border-color: var(--pri-dk); }
.btn-amb     { background: var(--amb);    border-color: var(--amb);    color: #fff; }
.btn-amb:hover   { background: var(--amb-dk); border-color: var(--amb-dk); }
.btn-red     { background: var(--red);    border-color: var(--red);    color: #fff; }
.btn-red:hover   { background: #900; border-color: #900; }
.btn-ghost   { background: transparent;   border-color: var(--border2); color: var(--txt2); }
.btn-ghost:hover { border-color: var(--pri); color: var(--pri); }
.btn-ghost.active { background: var(--pri-lt); border-color: var(--pri); color: var(--pri-dk); }
.btn-xs  { padding: 4px 8px;   font-size: 11px; }
.btn-sm  { padding: 6px 12px;  font-size: 11px; }
.btn-full { width: 100%; }
.btn-icon-del { background: transparent; border: none; cursor: pointer; font-size: 15px; color: var(--txt4); padding: 2px 4px; border-radius: 4px; transition: color .12s; }
.btn-icon-del:hover { color: var(--red); }

/* ── Event threshold edit ───────────────────────────────────────── */
.thresh-edit-row { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 6px; }
.thresh-pair { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; }
.thresh-edit-row label { font-size: 10px; font-weight: 800; color: var(--txt3); white-space: nowrap; }
.thresh-edit-row input { width: 90px; text-align: center; font-size: 12px; padding: 5px 8px; }
.event-badge  { font-size: 10px; background: var(--amb-lt); color: var(--amb-dk); border: 1px solid var(--amb); border-radius: 5px; padding: 3px 7px; font-weight: 800; }

/* ── Copy field ─────────────────────────────────────────────────── */
.copy-field {
  width:       100%;
  background:  var(--s3);
  border:      1.5px solid var(--border2);
  border-radius: var(--rs);
  font-family: var(--mono);
  font-size:   11px;
  color:       var(--txt2);
  padding:     7px 10px;
  resize:      none;
  cursor:      text;
  line-height: 1.6;
}
.copy-field:focus { outline: none; border-color: var(--pri); }
.copy-hint { font-size: 10px; color: var(--txt4); margin-bottom: 3px; letter-spacing: .03em; }
.warn-note { font-size: 11px; color: var(--red); background: var(--red-lt); border: 1px solid var(--red); border-radius: var(--rs); padding: 6px 10px; margin-top: 6px; }

/* ── Time machine ───────────────────────────────────────────────── */
.tm-card { background: linear-gradient(135deg, var(--s2) 0%, var(--pri-lt) 100%); }
.tm-label-row { display: flex; justify-content: space-between; align-items: center; font-size: 11px; color: var(--txt3); font-family: var(--mono); margin-bottom: 6px; }
.vt-label-wrap { position: relative; display: inline-flex; }
.tm-label-row .vt-label {
  color:          var(--pri-dk);
  font-weight:    700;
  cursor:         pointer;
  border:         1.5px dashed var(--border2);
  border-radius:  var(--rs);
  padding:        2px 8px;
  background:     rgba(255,255,255,.35);
}
.tm-date-popover { left: 50%; transform: translateX(-50%); width: min(90vw, 320px); }
.tm-info { font-family: var(--mono); font-size: 11px; color: var(--txt3); margin-top: 6px; text-align: center; }
.tm-offset { background: var(--amb-lt); color: var(--amb-dk); border-radius: 4px; padding: 1px 6px; font-weight: 700; }
.tm-nowrap-row { flex-wrap: nowrap !important; }

/* Current/Planned reference bars — share the scrubber's own timeline scale (see tmScaleEndVT).
   The scrubber input is wrapped in the SAME .tm-bar-row/fixed-width-label-spacer structure as the
   two bars below it, purely so all three tracks render at the exact same width — a fixed width
   (not min-width) on the label column, matched by an invisible spacer on the scrubber's own row,
   is what keeps them aligned regardless of how long each end-time label's text happens to be. */
.tm-bar-row { display: flex; align-items: center; gap: 8px; margin-top: 7px; }
input[type=range].tm-scrubber-input { flex: 1; width: auto; min-width: 0; margin: 0; }
.tm-bar-label-spacer { width: 92px; flex-shrink: 0; }
.tm-bar-track {
  flex:           1;
  height:         16px;
  border-radius:  999px;
  background:     var(--s3);
  border:         1px solid var(--border2);
  overflow:       hidden;
}
/* Solid ramp the full width of the fill: full height at the far left, sloping straight down to a
   point (zero height) at the right edge — the fill's right edge still lands exactly at its normal
   width (set inline by JS), only the cross-section shape changed. Flat solid colors, no gradient —
   the track's own rounded/overflow:hidden left edge is what rounds the ramp's left corners, so no
   border-radius is needed on the fill itself. */
.tm-bar-fill {
  height:     100%;
  transition: width .25s ease;
  /* Bottom points overshoot 1px past the box edge so the ramp's own anti-aliased bottom line
     always fully covers down to the track's border — the track's overflow:hidden crops the
     overshoot, leaving no hairline gap between the ramp and the bottom border. */
  clip-path:  polygon(0 0, 0 calc(100% + 1px), 100% calc(100% + 1px));
}
.tm-bar-fill.current  { background: var(--red); }
.tm-bar-fill.planned  { background: var(--grey); }
/* Width is set inline by JS (syncTMBarLabelWidths in timemachine.js) to the wider of the two
   labels' natural content width, so neither ever gets clipped regardless of date format/length —
   a fixed CSS width previously truncated longer dates. max-width is just a sane upper safety net. */
.tm-bar-label {
  display:      inline-block;
  font-family:  var(--mono);
  font-size:    11px;
  font-weight:  700;
  color:        var(--txt3);
  white-space:  nowrap;
  overflow:     hidden;
  text-overflow: ellipsis;
  max-width:    180px;
  text-align:   right;
  flex-shrink:  0;
}
.tm-bar-label-wrap { position: relative; display: inline-flex; flex-shrink: 0; max-width: 180px; }
.tm-bar-label-wrap .tm-bar-label.clickable {
  cursor:         pointer;
  color:          var(--grey-dk);
  border:         1.5px dashed var(--grey);
  border-radius:  var(--rs);
  padding:        2px 8px;
  background:     rgba(255,255,255,.35);
  width:          100%;
  box-sizing:     border-box;
}
.planned-end-popover { left: auto; right: 0; width: min(90vw, 320px); }
.tm-bar-legend {
  display:        flex;
  gap:            14px;
  justify-content: center;
  font-size:      10px;
  color:          var(--txt3);
  font-family:    var(--mono);
  margin-top:     6px;
}
.tm-swatch { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 4px; vertical-align: middle; }
.tm-swatch.current { background: var(--red); }
.tm-swatch.planned { background: var(--grey); }

input[type=range] {
  width:              100%;
  height:             6px;
  appearance:         none;
  -webkit-appearance: none;
  border-radius:      3px;
  outline:            none;
  cursor:             pointer;
  background:         var(--border2);
  /* Fully capture touch input on the slider itself — pan-y (the old setting) let the browser
     treat a slight vertical wobble mid-drag as a page pan, which on mobile triggers
     pull-to-refresh when the page is scrolled to the top. none stops that from ever firing
     while a finger is down on the slider. */
  touch-action:       none;
}
input[type=range]::-webkit-slider-thumb {
  width:              24px;
  height:             24px;
  border-radius:      50%;
  background:         var(--pri-dk);
  border:             3px solid #fff;
  box-shadow:         0 2px 6px rgba(0,0,0,.25);
  -webkit-appearance: none;
  cursor:             pointer;
}
input[type=range]::-moz-range-thumb {
  width:         20px;
  height:        20px;
  border-radius: 50%;
  background:    var(--pri-dk);
  border:        3px solid #fff;
  cursor:        pointer;
}

/* ── Date picker row (reused by the player-edit modal's join-time calendar mode and the Time
   Machine's exact-date popover) — always 3-per-row (Month/Day/Year, then Hour/Minute/AM-PM)
   rather than letting flex:1 divide all 6 evenly across whatever width the container happens to
   be, which on a wide popover left each select comically thin. */
.date-picker-row { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 10px; }
.date-picker-row select { font-size: 12px; padding: 6px 22px 6px 7px; min-width: 0; flex: 0 1 calc(33% - 4px); }
.offset-row { display: flex; gap: 8px; }
.offset-row .field { flex: 1; }

/* ── Generic inline colors ──────────────────────────────────────── */
.dim  { color: var(--txt3); }
.warn { color: var(--red); }
.ok   { color: var(--ok);  font-weight: 600; }

/* ── Checkbox row ───────────────────────────────────────────────── */
.check-row { display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; -webkit-user-select: none; padding: 6px 0; }
.check-row input[type=checkbox] { width: 16px; height: 16px; accent-color: var(--pri); cursor: pointer; flex-shrink: 0; }
.check-row span { font-size: 12px; color: var(--txt2); }

/* ── Mushroom list (sortable, column-configurable table) ─────────── */
.mush-table-wrap { overflow-x: auto; border-radius: var(--rs); border: 1.5px solid var(--border); }
.mush-table { width: 100%; border-collapse: collapse; font-size: 12px; white-space: nowrap; }
.mush-table th, .mush-table td { padding: 8px 10px; text-align: left; }
.mush-table thead th {
  font-size:      10px;
  font-weight:    800;
  letter-spacing: .05em;
  text-transform: uppercase;
  color:          var(--txt3);
  background:     var(--s2);
  border-bottom:  1.5px solid var(--border);
  position:       relative;
}
.mush-th-sortable { cursor: pointer; user-select: none; }
.mush-th-sortable:hover { color: var(--pri-dk); }
.mush-th-sortable.sorted { color: var(--pri-dk); }
.mush-th-actions { width: 1%; text-align: center; }
.mush-td-actions { white-space: nowrap; text-align: right; }
.mush-td-actions button { margin-left: 4px; }
.mush-table tbody tr { border-bottom: 1px solid var(--border); cursor: pointer; transition: background .12s; }
.mush-table tbody tr:last-child { border-bottom: none; }
.mush-table tbody tr:hover  { background: var(--s2); }
.mush-table tbody tr.active { background: var(--pri-lt); }
.mush-td-name { font-weight: 800; max-width: 160px; overflow: hidden; text-overflow: ellipsis; }
.mush-name-input {
  background: transparent; border: none; font-family: var(--sans);
  font-size: 12px; font-weight: 800; color: var(--txt); width: 100%; outline: none; padding: 0;
}
.mush-name-input:focus { background: var(--surface); border-radius: 4px; padding: 2px 4px; }
.mush-pill { font-size: 10px; font-weight: 700; background: var(--s3); border: 1px solid var(--border); border-radius: 5px; padding: 2px 6px; white-space: nowrap; color: var(--txt2); }
.btn-icon-pencil { background: none; border: none; cursor: pointer; font-size: 12px; color: var(--txt3); padding: 2px 4px; border-radius: 4px; }
.btn-icon-pencil:hover { color: var(--pri-dk); background: var(--pri-lt); }
.column-picker-popover { top: calc(100% + 4px); right: 0; left: auto; width: 180px; text-transform: none; text-align: left; }
.column-picker-popover .check-row { padding: 4px 0; }
.col-abbr { display: none; }

/* ── Export / import ────────────────────────────────────────────── */
.ei-textarea {
  width:         100%;
  font-family:   var(--mono);
  font-size:     11px;
  background:    var(--s3);
  border:        1.5px solid var(--border);
  border-radius: var(--rs);
  padding:       8px 10px;
  resize:        vertical;
  min-height:    80px;
  color:         var(--txt);
}
.ei-textarea:focus { outline: none; border-color: var(--pri); }

/* Single-line copy-only fields for the raw Discord timestamp codes — same look as .ei-textarea
   but sized for one line, since these are meant to be tapped-and-copied as-is into a message the
   user writes elsewhere, not edited. */
.discord-ts-input {
  width:         100%;
  font-family:   var(--mono);
  font-size:     12px;
  background:    var(--s3);
  border:        1.5px solid var(--border);
  border-radius: var(--rs);
  padding:       8px 10px;
  color:         var(--txt);
  cursor:        pointer;
}
.discord-ts-input:focus { outline: none; border-color: var(--pri); }

/* ── Utility ────────────────────────────────────────────────────── */
.sep    { height: 1px; background: var(--border); margin: 12px 0; }
.mt6    { margin-top:  6px; }
.mt10   { margin-top:  10px; }
.mt12   { margin-top:  12px; }
.flex-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* ── Pikmin roster → AP builder (now scoped inside the player-edit modal) ────── */
.roster-grid { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
/* --pk-bg/--pk-border-lt/--pk-color are set inline per card (renderPmRoster) from that Pikmin
   color's trio in PIKMIN_TYPES (pikmin.js) — falls back to the old flat green theme if unset. */
.roster-item { background: var(--pk-bg, var(--s2)); border: 1.5px solid var(--pk-border-lt, var(--border)); border-radius: var(--rs); padding: 8px 10px; }
.roster-item.has-count { border-color: var(--pk-color, var(--pri)); box-shadow: inset 0 0 0 1px var(--pk-color, var(--pri)); }
.roster-item-hdr { display: flex; justify-content: space-between; align-items: baseline; font-size: 12px; font-weight: 700; margin-bottom: 6px; }
.roster-item-row { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.roster-item-row select { flex: 1 1 120px; min-width: 100px; font-size: 12px; padding: 6px 8px; }
.count-stepper { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.count-stepper input[type=number] { width: 44px; text-align: center; padding: 6px 2px; flex-shrink: 0; }
.count-step-btn { width: 24px; height: 24px; font-size: 13px; }
.roster-decor { flex-shrink: 0; padding: 0; gap: 4px; }
.roster-decor span { font-size: 11px; white-space: nowrap; }
/* Only rendered for Event mushrooms with Decor checked (see renderPmRoster) — wide enough that
   "Primary Event Decor (+300)" doesn't clip inside the select's own closed width. */
.roster-event-tier { flex: 1 1 100%; min-width: 100%; font-size: 12px; padding: 6px 8px; }
.roster-item-actions { display: flex; gap: 12px; margin-top: 6px; }
.roster-action-btn { background: none; border: none; padding: 2px 0; font-size: 11px; font-weight: 700; color: var(--pk-color, var(--pri-dk)); cursor: pointer; opacity: .8; }
.roster-action-btn:hover { opacity: 1; text-decoration: underline; }
.roster-action-remove { color: var(--red); }
.roster-total-row {
  display:         flex;
  align-items:     center;
  justify-content: space-between;
  gap:             8px;
  font-size:       12px;
  color:           var(--txt2);
  flex-wrap:       wrap;
}
.roster-total-row strong { font-family: var(--mono); color: var(--pri-dk); font-size: 14px; }

/* ══════════════════════════════════════════════════════════════════
   Battle Card
   ══════════════════════════════════════════════════════════════════ */
.battle-card {
  background:     var(--surface);
  border:         1.5px solid var(--border);
  border-radius:  var(--r);
  /* Deliberately NOT overflow:hidden — the HP/strength popovers are descendants of .battle-green
     and need to spill past the card's own bottom edge (they can be taller than the white section
     below them). Clipping happened here previously even though .battle-green itself allowed
     overflow, because a hidden ancestor clips descendants regardless of intermediate elements'
     own overflow setting. Each section below rounds its own corners instead, so the card still
     reads as one rounded shape without needing to clip anything. */
  box-shadow:     var(--shadow-md);
}

.battle-green {
  position:   relative;
  min-height: 210px;
  background: linear-gradient(180deg, #7bc850 0%, #4a9e30 100%);
  border-radius: var(--r) var(--r) 0 0;
  /* no overflow:hidden here on purpose — the HP/strength popovers open below their triggers and
     need to spill past this section's bottom edge into the white section below; the mushroom
     art itself is clipped by .battle-svg's own overflow instead. */
  display:    flex;
  flex-direction: column;
}
/* height-driven sizing on purpose: the art should stay the same visual scale and stay centered
   as the card gets wider, with the green background simply showing more grass on either side —
   not stretch/zoom to cover the full width (that used to make the mushrooms look like they grew
   taller as the window widened). */
.battle-svg { position: absolute; inset: 0; display: flex; justify-content: center; overflow: hidden; }
.battle-svg svg { display: block; height: 100%; width: auto; }

.battle-name-row { position: relative; z-index: 2; padding: 12px 14px 0; }
.battle-name-input {
  background:    rgba(20,40,10,.42);
  border:        1.5px solid rgba(255,255,255,.5);
  border-radius: 999px;
  color:         #fff;
  font-family:   var(--sans);
  font-weight:   800;
  font-size:     15px;
  padding:       7px 16px;
  max-width:     70%;
  text-shadow:   0 1px 3px rgba(0,0,0,.4);
}
.battle-name-input:focus { box-shadow: 0 0 0 3px rgba(255,255,255,.35); border-color: #fff; }

.battle-green-foot {
  position:        relative;
  z-index:         2;
  margin-top:      auto;
  display:         flex;
  align-items:     flex-end;
  justify-content: space-between;
  gap:             10px;
  padding:         10px 14px 14px;
}

.hp-block { position: relative; display: flex; flex-direction: column; gap: 2px; cursor: pointer; }
.hp-pie-row { display: flex; align-items: center; gap: 8px; }
.hp-pie-col { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.hp-pie {
  width:  30px;
  height: 30px;
  border-radius: 50%;
  background: conic-gradient(var(--red) 0% var(--hp-pct, 100%), #ffffff var(--hp-pct, 100%) 100%);
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(0,0,0,.35);
  flex-shrink: 0;
}
/* Planned HP pie — same shape/size, grey wipe, only shown while the Time Machine is scrubbed into
   the future (see refreshBattleDynamic in ui-setup.js); hidden at real "now" since it'd be an
   exact duplicate of the current pie by construction (plannedHpAtVT in calc.js). */
.hp-pie.planned {
  background: conic-gradient(var(--grey) 0% var(--hp-pct, 100%), #ffffff var(--hp-pct, 100%) 100%);
}
.hp-number-col { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.hp-number {
  display:       inline-block;
  font-family:   var(--sans);
  font-weight:   900;
  font-size:     28px;
  color:         var(--red);
  -webkit-text-stroke: 2px #fff;
  paint-order:   stroke fill;
  line-height:   1;
  padding:       2px 10px;
}
.hp-time { font-size: 12px; color: #fff; font-weight: 700; text-shadow: 0 1px 3px rgba(0,0,0,.5); margin-left: 38px; }

/* Planned total (all players, incl. auto/not-yet-real) shown directly above the Current number —
   same font treatment as .hp-number (size/weight/stroke), just grey, matching the grey used
   everywhere else for auto/planned data (player circles' "Planned" tag, TM's grey bar). */
.hp-number-planned {
  display:       inline-block;
  font-family:   var(--sans);
  font-weight:   900;
  font-size:     28px;
  color:         var(--grey);
  -webkit-text-stroke: 2px #fff;
  paint-order:   stroke fill;
  line-height:   1;
  border:        1.5px dashed rgba(255,255,255,.6);
  border-radius: var(--rs);
  padding:       2px 10px;
}

.strength-badge { position: relative; text-align: right; cursor: pointer; }
.strength-top { display: flex; align-items: center; gap: 6px; justify-content: flex-end; }
.strength-icon-col { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.strength-icon { font-size: 20px; filter: drop-shadow(0 1px 2px rgba(0,0,0,.4)); }

/* Individual star glyphs (★ filled / ☆ hollow) built by ui-setup.js's buildStarsHtml, replacing
   the old plain-text ⭐/☆ string — needed so filled stars can carry the badge's own tier color and
   the "reachable via bonus %" hint star can get its own smaller/outlined treatment. */
.star-glyph { font-size: 20px; line-height: 1; }
.star-glyph.filled.t1 { color: #4a9e30; }
.star-glyph.filled.t2 { color: #d0a018; }
.star-glyph.filled.t3 { color: #d0701c; }
.star-glyph.filled.t4 { color: #c85a1c; text-shadow: 0 0 6px #4ac8ff, 0 0 10px #4ac8ff; }
.star-glyph.filled.grey { color: var(--grey); }
/* Hint star: "the bonus % alone would reach the next tier" — same eventual color as that tier,
   just smaller, plus a thin coral/maroon outline so it never reads as a plain filled star. Once
   the RAW total (no bonus) crosses that threshold this exact slot just becomes .filled instead —
   not a separate indicator. */
.star-glyph.hint {
  font-size: 13px;
  -webkit-text-stroke: 1.5px var(--hint-outline);
  paint-order: stroke fill;
}
.star-glyph.hint.t2 { color: #d0a018; }
.star-glyph.hint.t3 { color: #d0701c; }
.star-glyph.hint.t4 { color: #c85a1c; }
.star-glyph.hint.grey { color: var(--grey); }
.star-glyph.hollow { color: inherit; opacity: .75; }
.star-glyph + .star-glyph { margin-left: 1px; }
.strength-number {
  display:       inline-block;
  font-family:   var(--sans);
  font-weight:   900;
  font-size:     26px;
  line-height:   1;
  -webkit-text-stroke: 2px #fff;
  paint-order:   stroke fill;
  color:         #4a9e30;
  padding:       2px 10px;
}
.strength-number.tier-2 { color: #d0a018; }
.strength-number.tier-3 { color: #d0701c; }
.strength-number.tier-4 { color: #c85a1c; text-shadow: 0 0 10px #4ac8ff, 0 0 18px #4ac8ff; }
.strength-label { font-size: 11px; color: #fff; font-weight: 700; text-shadow: 0 1px 3px rgba(0,0,0,.5); }
.strength-number-col { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }

/* Planned total (all players, incl. auto/not-yet-real) shown directly above the Current number —
   same font treatment as .strength-number (size/weight/stroke), just grey, matching
   .hp-number-planned's treatment. */
.strength-number-planned {
  display:       inline-block;
  font-family:   var(--sans);
  font-weight:   900;
  font-size:     26px;
  color:         var(--grey);
  -webkit-text-stroke: 2px #fff;
  paint-order:   stroke fill;
  line-height:   1;
  border:        1.5px dashed rgba(255,255,255,.6);
  border-radius: var(--rs);
  padding:       2px 10px;
}

/* Shared popover shell, opens BELOW its trigger (not above) so it never covers the mushroom art */
.popover {
  position:      absolute;
  top:           calc(100% + 10px);
  background:    var(--surface);
  border:        1.5px solid var(--border);
  border-radius: var(--rs);
  box-shadow:    var(--shadow-md);
  padding:       12px;
  width:         220px;
  z-index:       20;
  text-align:    left;
  cursor:        default;
}
.star-popover  { right: 0; }
.hp-popover    { left: 0; }
.share-popover { right: 0; width: 260px; }

/* Unlike the other popovers (anchored via a position:relative ancestor), this one is shared across
   every row of every list card, so it's positioned with fixed top/left set directly in JS
   (openMoveCopyPopover) relative to whichever row's icon was actually clicked. */
.move-copy-popover { position: fixed; top: auto; width: 200px; }
.move-copy-popover select { width: 100%; margin-top: 6px; }

/* ── List cards: home list header + connected-list cards (sharing/access) ── */
.list-card-hdr {
  display:        flex;
  align-items:    center;
  justify-content: space-between;
  gap:            10px;
  margin-bottom:  14px;
  position:       relative; /* anchors connected-list cards' own share/remove popovers, if any */
}
.list-card-hdr .card-title { margin-bottom: 0; flex: 1 1 auto; min-width: 0; }
.list-name-title { display: flex; align-items: center; gap: 6px; }
.list-name-input {
  background:   transparent;
  border:       none;
  outline:      none;
  padding:      2px 4px;
  font:         inherit;
  font-size:    12px;
  letter-spacing: .1em;
  color:        var(--txt3);
  text-transform: uppercase;
  width:        100%;
  min-width:    0;
}
.list-name-input:focus { background: var(--s3); border-radius: 4px; }
.share-btn-wrap { position: relative; flex: 0 0 auto; }

.codes-list { display: flex; flex-direction: column; gap: 6px; max-height: 180px; overflow-y: auto; }
.code-row {
  display:      flex;
  align-items:  center;
  gap:          6px;
  font-size:    11px;
}
.code-text {
  flex:         1 1 auto;
  font-family:  var(--mono);
  font-weight:  700;
  letter-spacing: .04em;
  user-select:  all;
  overflow-wrap: anywhere;
}
.code-level-badge {
  font-size:      9px;
  font-weight:    800;
  text-transform: uppercase;
  letter-spacing: .04em;
  padding:        2px 6px;
  border-radius:  5px;
  white-space:    nowrap;
  flex:           0 0 auto;
}
.code-level-badge.lvl-limited { background: var(--amb-lt); color: var(--amb-dk); }
.code-level-badge.lvl-read    { background: var(--s3);     color: var(--txt2); }
.code-level-badge.lvl-write   { background: var(--pri-lt); color: var(--pri-dk); }
.code-level-badge.lvl-full    { background: var(--pur-lt); color: var(--pur-dk); }
.star-popover-title { font-size: 10px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--txt3); margin-bottom: 8px; }

.collapse-toggle {
  display:         flex;
  align-items:     center;
  justify-content: space-between;
  width:           100%;
  background:      none;
  border:          none;
  padding:         4px 0;
  margin:          0;
  cursor:          pointer;
  text-align:      left;
  font:            inherit;
  color:           var(--txt2);
}
.collapse-chevron { transition: transform .15s ease; font-size: 12px; color: var(--txt3); }
.collapse-toggle.open .collapse-chevron { transform: rotate(180deg); }
.collapse-body {
  overflow:   hidden;
  max-height: 300px;
  transition: max-height .2s ease;
}
.collapse-body.collapsed { max-height: 0; }

.ap-stepper-row { display: flex; align-items: center; gap: 6px; }
.ap-stepper-row input[type=number] { text-align: center; }
.ap-step-btn {
  flex-shrink:   0;
  width:         30px;
  height:        30px;
  border-radius: 50%;
  border:        1.5px solid var(--border2);
  background:    var(--s2);
  color:         var(--txt2);
  font-size:     16px;
  font-weight:   800;
  line-height:   1;
  cursor:        pointer;
  transition:    all .12s;
}
.ap-step-btn:hover, .ap-step-btn:active { background: var(--pri-lt); border-color: var(--pri); color: var(--pri-dk); }
.ap-step-btn:disabled { opacity: .4; cursor: not-allowed; background: var(--s2); border-color: var(--border2); color: var(--txt2); }
.ap-step-btn:disabled:hover { background: var(--s2); border-color: var(--border2); color: var(--txt2); }
.ap-log-slider { margin-top: 8px; height: 4px; }
.ap-log-slider::-webkit-slider-thumb { width: 18px; height: 18px; }
.ap-log-slider::-moz-range-thumb { width: 16px; height: 16px; }

.battle-white { padding: 16px; }
.battle-title-row { display: flex; align-items: baseline; gap: 4px; flex-wrap: wrap; margin-bottom: 8px; }
.title-edit-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
  border: 1.5px dashed var(--border2);
  border-radius: var(--rs);
  padding: 0 18px 0 4px;
}
.title-edit-wrap::after {
  content: '✎';
  position: absolute;
  right: 3px; top: 2px;
  font-size: 9px;
  color: var(--txt3);
  pointer-events: none;
}
.title-select {
  background:      transparent;
  background-image: none; /* the wrapper's dashed box + pencil is the edit affordance here instead */
  border:          none;
  box-shadow:       none !important;
  font-family:      var(--sans);
  font-weight:      900;
  font-size:        22px;
  color:            var(--txt);
  padding:          2px 2px 2px 2px;
  width:            auto;
}
.title-static { font-family: var(--sans); font-weight: 900; font-size: 22px; color: var(--txt); }


@keyframes guidePulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,255,255,0); }
  50%      { box-shadow: 0 0 0 6px rgba(255,235,120,.65); }
}
.guide-pulse { animation: guidePulse 1s ease-in-out 3; border-radius: 999px; }

/* Persistent (not one-shot) highlight for "Set Join Time" when the scrubbed preview shows the
   mushroom already at 0 HP under the current plan — keeps pulsing as long as that's true. */
@keyframes tmHighlightPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(232,128,16,.5); }
  50%      { box-shadow: 0 0 0 7px rgba(232,128,16,.22); }
}
.tm-highlight { animation: tmHighlightPulse 1.3s ease-in-out infinite; border-color: var(--amb) !important; }

.players-hdr-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.players-hdr-label { font-size: 11px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--txt3); }

.player-row { display: flex; gap: 10px; margin-bottom: 10px; }

/* Ticket rows (slot 6+) collapse behind a peek-and-fade + expand toggle to save vertical space —
   only the first (regular, non-ticket) row renders ungated. */
.player-rows-extra-wrap { position: relative; }
.player-rows-extra { overflow: hidden; max-height: 1000px; transition: max-height .25s ease; }
.player-rows-extra-wrap.collapsed .player-rows-extra { max-height: 30px; }
.player-rows-fade {
  position:   absolute;
  left: 0; right: 0; bottom: 0;
  height:     30px;
  background: linear-gradient(to bottom, rgba(244,252,237,0), var(--surface) 80%);
  pointer-events: none;
  opacity:    0;
  transition: opacity .2s ease;
}
.player-rows-extra-wrap.collapsed .player-rows-fade { opacity: 1; }
.player-rows-expand-btn {
  display:        block;
  width:          26px;
  height:         26px;
  margin:         -13px auto 0;
  border-radius:  50%;
  background:     var(--surface);
  border:         1.5px solid var(--border);
  box-shadow:     var(--shadow);
  color:          var(--txt3);
  font-size:      14px;
  line-height:    1;
  cursor:         pointer;
  position:       relative;
  z-index:        2;
}
.player-rows-expand-btn:hover { border-color: var(--pri); color: var(--pri-dk); }

.player-slot { width: 54px; display: flex; flex-direction: column; align-items: center; gap: 3px; }
.player-circle {
  width:          54px;
  height:         54px;
  border-radius:  50%;
  background:     var(--s3);
  border:         2px solid var(--border2);
  display:        flex;
  align-items:    center;
  justify-content: center;
  font-size:      20px;
  color:          var(--txt3);
  cursor:         pointer;
  transition:     all .12s;
  position:       relative;
}
.player-circle:hover { border-color: var(--pri); }
.player-circle.filled { background: var(--pri-lt); border-color: var(--pri); color: var(--pri-dk); font-weight: 800; font-size: 15px; }
.player-circle.ticket { border-color: var(--gold); box-shadow: 0 0 0 2px var(--gold) inset; }
.player-circle.empty-dim { opacity: .35; border-style: dashed; cursor: default; }
.player-circle.overcap { background: var(--red-lt); border-color: var(--red); }
/* Not yet joined (Planned) as of the Time Machine's current position — grey, matching every other
   "planned" indicator (the Time Machine's planned bar/label) so planned data reads consistently
   at a glance. Reverts to normal color on its own once virtualNow() passes this player's joinVT. */
.player-circle.pending { background: var(--grey-lt); border-color: var(--grey); color: var(--grey-dk); }
.player-slot-label { font-size: 10px; color: var(--txt3); font-family: var(--mono); text-align: center; line-height: 1.3; max-width: 64px; }
/* Manual AP is a real, hand-confirmed number — shown bold at full color. Auto-split AP is a
   derived/transient estimate (auto-balancing isn't fully fleshed out yet) — shown dimmer and
   at normal weight so the two are easy to tell apart at a glance. */
.ap-label.manual { font-weight: 800; color: var(--txt2); }
.ap-label.auto   { font-weight: 400; color: var(--txt4); }
.join-label { color: var(--txt4); }
/* Planned slot's AP/join text also reads grey, matching the circle above it. */
.player-slot.pending .ap-label,
.player-slot.pending .join-label { color: var(--grey-dk); }

/* ══════════════════════════════════════════════════════════════════
   Modals (player-edit, advanced-settings)
   ══════════════════════════════════════════════════════════════════ */
.modal-overlay {
  position: fixed; inset: 0; background: rgba(10,30,5,.55);
  display: flex; align-items: center; justify-content: center;
  z-index: 200; padding: 16px;
}
.modal-card {
  background: var(--surface); border: 1.5px solid var(--border); border-radius: var(--r);
  box-shadow: var(--shadow-md); padding: 18px; width: 100%; max-width: 420px;
  max-height: 88vh; overflow-y: auto;
}
.modal-hdr {
  display: flex; align-items: center; justify-content: space-between;
  font-weight: 900; font-size: 15px; color: var(--txt); margin-bottom: 14px;
}
.modal-x { background: none; border: none; font-size: 16px; color: var(--txt4); cursor: pointer; padding: 2px 6px; }
.modal-x:hover { color: var(--red); }

.pm-planned-toggle {
  display: flex; align-items: center; gap: 5px; cursor: pointer; user-select: none;
  font-size: 11px; font-weight: 700; color: var(--txt3); text-transform: none;
  margin-left: auto; margin-right: 10px;
}
.pm-planned-toggle input[type=checkbox] { width: 15px; height: 15px; accent-color: var(--grey); cursor: pointer; }
.pm-ap-label-row { display: flex; align-items: center; justify-content: space-between; }
.check-inline { display: flex; align-items: center; gap: 4px; cursor: pointer; user-select: none; text-transform: none; font-weight: 700; font-size: 11px; color: var(--txt3); }
.check-inline input[type=checkbox] { width: 14px; height: 14px; accent-color: var(--pri); cursor: pointer; }

/* ── Scrollbar ──────────────────────────────────────────────────── */
::-webkit-scrollbar       { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: var(--s2); }
::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 3px; }

/* ── Responsive ─────────────────────────────────────────────────── */
@media (max-width: 550px) {
  .grid2     { grid-template-columns: 1fr; }
  .lbl-full  { display: none; }
  .lbl-icon  { display: inline; }
  .btn.btn-amb.btn-sm { padding: 8px 12px; }
  .strength-number, .hp-number,
  .strength-number-planned, .hp-number-planned { font-size: 22px; }
  .title-select, .title-static { font-size: 18px; }
  .col-full { display: none; }
  .col-abbr { display: inline; }
}
