/* Visible wild monsters - overworld HUD, notice stack and touch controls (OVM.ui).
 *
 * Loaded after styles.css. Styles ONLY the elements built by shared/overworld-monsters/ui.js:
 * #ovmLayer (inside .playfield) with #ovmHud and #ovmNotices, and the touch charm button #ovmThrow
 * with its charm tray #ovmTray inside `#touchControls .tc-actions`. No existing game element is
 * restyled (the cluster geometry lives in styles.css "Actions - right thumb cluster").
 *
 * Stacking: the layer sits inside .playfield between the toast (z 12) and #touchControls (z 15).
 * The touch buttons live inside #touchControls and inherit its stacking context, its felt skin
 * (.tc-btn) and its hide rules (battle / modal / wide-art speech / portrait rotate hint).
 * Desktop: HUD pill in the bottom-left corner of the picture just above the toast lane, notices
 *          (max 2) stacked above it on the left - the throw zone below the player stays free.
 * Touch:   no HUD pill once the charm button is attached (the ring marks the target); status chips
 *          top-right (below .online-hud on online hosts); notices and the catch cards (one at a time) top-left inside the
 *          picture below the canvas nameplate; the charm button where the right thumb rests
 *          (styles.css "Actions - right thumb cluster"), its tray opening to its left.
 */

#ovmLayer {
  --ovm-ink: #f2ece0;
  --ovm-ink-dim: #d3cab8;
  --ovm-gold: #e6d1a0;
  --ovm-keyline: rgba(230, 209, 160, 0.44);
  --ovm-warn: #ffc979;
  --ovm-success: #9be3a6;
  --ovm-felt-top: rgba(30, 24, 20, 0.95);
  --ovm-felt-bottom: rgba(10, 8, 6, 0.96);
  --ovm-charm-a: #78ead7;
  --ovm-charm-b: #245d68;
  --ovm-charm-c: #ffd36a;
  /* Bottom-left corner of the picture: flush with the toast's left edge (left 18px) and just
     above the toast lane (toast: bottom 18px, min-height 48px). The width stays left of the
     picture centre (= the player's column), so monsters below the player are never covered. */
  position: absolute;
  z-index: 13;
  left: 18px;
  bottom: 78px;
  transform: none;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  width: max-content;
  max-width: max(250px, calc(50% - 84px));
  pointer-events: none;
  color: var(--ovm-ink);
  font-family: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 14px;
  line-height: 1.3;
  -webkit-font-smoothing: antialiased;
}

#ovmLayer[hidden],
#ovmLayer [hidden] {
  display: none !important;
}

/* ---- notice stack (role=log, max 2, never interactive) ---------------------------------- */
#ovmNotices {
  order: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  max-width: 100%;
  pointer-events: none;
}

#ovmNotices:empty {
  display: none;
}

#ovmLayer .ovm-notice {
  max-width: 100%;
  box-sizing: border-box;
  padding: 8px 14px;
  border: 1px solid rgba(240, 232, 214, 0.22);
  border-left: 3px solid var(--ovm-gold);
  border-radius: 10px;
  background: linear-gradient(179deg, var(--ovm-felt-top), var(--ovm-felt-bottom));
  box-shadow: inset 0 1px 0 rgba(240, 232, 214, 0.12), 0 8px 20px rgba(0, 0, 0, 0.42);
  font-size: 14px;
  font-weight: 650;
  letter-spacing: 0.01em;
  text-align: left;
  overflow-wrap: anywhere;
  animation: ovm-notice-in 180ms ease-out both;
}

#ovmLayer .ovm-notice.ovm-tone-success { border-left-color: var(--ovm-success); }
#ovmLayer .ovm-notice.ovm-tone-warn { border-left-color: var(--ovm-warn); color: #fff3df; }
/* Swarm and Holo-signal notices (OVM.swarm / OVM.holoSignal through ui.notify tones). */
#ovmLayer .ovm-notice.ovm-tone-swarm { border-left-color: #f0a94e; }
#ovmLayer .ovm-notice.ovm-tone-holo {
  border-left-color: #a9f0ff;
  background:
    linear-gradient(90deg, rgba(255, 243, 166, 0.13), rgba(169, 240, 255, 0.1) 30%, rgba(255, 194, 241, 0.06) 60%, transparent),
    linear-gradient(179deg, var(--ovm-felt-top), var(--ovm-felt-bottom));
}
#ovmLayer .ovm-notice.ovm-tone-blackHolo {
  border-left-color: #8a6bd6;
  background:
    linear-gradient(90deg, rgba(122, 92, 214, 0.22), rgba(214, 190, 120, 0.06) 45%, transparent),
    linear-gradient(179deg, var(--ovm-felt-top), var(--ovm-felt-bottom));
}

@keyframes ovm-notice-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

/* ---- dock: HUD pill + status chips ----------------------------------------------------------- */
/* Desktop: the dock does not box anything - the chips (order 1) and the pill (order 2) are items of
   the layer column, so the chips sit right above the pill (and in its place while it is hidden). */
#ovmLayer .ovm-dock { display: contents; }

/* ---- status chips (ui.setStatusChip, e.g. the swarm) ----------------------------------------- */
#ovmStatus {
  order: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  max-width: 100%;
  pointer-events: none;
}

#ovmLayer .ovm-status-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: 100%;
  box-sizing: border-box;
  padding: 4px 12px 4px 9px;
  border: 1px solid var(--ovm-keyline);
  border-radius: 999px;
  background: linear-gradient(179deg, var(--ovm-felt-top), var(--ovm-felt-bottom));
  box-shadow: inset 0 1px 0 rgba(240, 232, 214, 0.1), 0 6px 16px rgba(0, 0, 0, 0.4);
  color: var(--ovm-ink);
  font-size: 13px;
  font-weight: 750;
  line-height: 1.25;
  font-variant-numeric: tabular-nums;
}
#ovmLayer .ovm-status-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#ovmLayer .ovm-status-dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ovm-gold);
}
/* Swarm: warm amber, a slow beat on the dot. */
#ovmLayer .ovm-status-chip.is-swarm { border-color: rgba(240, 169, 78, 0.75); }
#ovmLayer .ovm-status-chip.is-swarm .ovm-status-dot { background: #f0a94e; box-shadow: 0 0 6px rgba(240, 169, 78, 0.8); }
/* Swarm bonus (Holo x2): holo tint and a rainbow dot. */
#ovmLayer .ovm-status-chip.is-swarm-bonus {
  border-color: rgba(201, 184, 255, 0.85);
  background:
    linear-gradient(90deg, rgba(255, 243, 166, 0.16), rgba(169, 240, 255, 0.14), rgba(255, 194, 241, 0.14), rgba(189, 255, 210, 0.12)),
    linear-gradient(179deg, var(--ovm-felt-top), var(--ovm-felt-bottom));
  background-size: 220% 100%, 100% 100%;
}
#ovmLayer .ovm-status-chip.is-swarm-bonus .ovm-status-dot {
  background: conic-gradient(#fff3a6, #a9f0ff, #ffc2f1, #bdffd2, #fff3a6);
  box-shadow: 0 0 6px rgba(201, 184, 255, 0.9);
}
@media (prefers-reduced-motion: no-preference) {
  #ovmLayer .ovm-status-chip { animation: ovm-notice-in 180ms ease-out both; }
  #ovmLayer .ovm-status-chip.is-swarm .ovm-status-dot { animation: ovm-pulse 1.6s ease-in-out infinite; }
  #ovmLayer .ovm-status-chip.is-swarm-bonus { animation: ovm-notice-in 180ms ease-out both, ovm-holo-sheen 3.2s ease-in-out infinite alternate; }
}
@keyframes ovm-holo-sheen {
  from { background-position: 0% 0, 0 0; }
  to { background-position: 100% 0, 0 0; }
}

/* ---- HUD pill ------------------------------------------------------------------------------ */
#ovmHud {
  order: 2;
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: 100%;
  padding: 8px 8px 8px 16px;
  border: 1px solid var(--ovm-keyline);
  border-radius: 18px;
  background: linear-gradient(179deg, var(--ovm-felt-top), var(--ovm-felt-bottom));
  box-shadow:
    inset 0 1px 0 rgba(240, 232, 214, 0.12),
    0 10px 26px rgba(0, 0, 0, 0.45);
  /* No backdrop blur: the felt is ~95 % opaque anyway, and blurring the moving map behind it
     costs a full re-blur every frame (worst on phones). */
  pointer-events: none;
}

#ovmLayer .ovm-hud-info {
  display: grid;
  gap: 3px;
  min-width: 0;
}

#ovmLayer .ovm-hud-line {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  white-space: nowrap;
}

#ovmLayer .ovm-hud-name {
  overflow: hidden;
  text-overflow: ellipsis;
  color: #fffaf0;
  font-size: 15px;
  font-weight: 800;
}

#ovmLayer .ovm-hud-level {
  color: var(--ovm-gold);
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

#ovmLayer .ovm-hud-empty {
  color: var(--ovm-ink-dim);
  font-size: 14px;
  font-weight: 600;
}

/* Species stars badge on the target line: "New!" for a species never caught, "×N" otherwise
   (a small charm ring before the count). */
/* Compact (the HUD stays left of the picture centre, the name keeps its room). */
#ovmLayer .ovm-hud-stars {
  flex: none;
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-left: -2px;
  padding: 0 5px;
  border: 1px solid rgba(230, 209, 160, 0.42);
  border-radius: 999px;
  color: var(--ovm-gold);
  font-size: 10px;
  font-weight: 800;
  line-height: 15px;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
}
#ovmLayer .ovm-hud-stars:not(.is-new)::before {
  content: "";
  width: 6px;
  height: 6px;
  box-sizing: border-box;
  border: 1.5px solid currentColor;
  border-radius: 50%;
  opacity: 0.85;
}
#ovmLayer .ovm-hud-stars.is-new {
  border-color: rgba(255, 240, 190, 0.85);
  background: linear-gradient(90deg, #ffe58a, #b9f0c2);
  color: #1a1308;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}
@media (prefers-reduced-motion: no-preference) {
  #ovmLayer .ovm-hud-stars.is-new { animation: ovm-stars-pop 420ms cubic-bezier(0.2, 1.4, 0.4, 1) both; }
}
@keyframes ovm-stars-pop {
  from { opacity: 0; transform: scale(0.6); }
  to { opacity: 1; transform: none; }
}

#ovmLayer .ovm-hud-status {
  font-size: 14px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: normal;
}

#ovmLayer .ovm-hud-status.ovm-warn { color: var(--ovm-warn); }

#ovmLayer .ovm-hud-charm {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 30px;
  margin: 0;
  padding: 2px 11px 2px 5px;
  border: 1px solid rgba(230, 209, 160, 0.3);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.05);
  color: inherit;
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  pointer-events: auto;
}

/* Small desktop windows keep the HUD narrow (left of the picture centre): the pill may shrink,
   the charm name gets an ellipsis instead of pushing the count and the C badge out of the pill. */
#ovmLayer .ovm-hud-charm { min-width: 0; max-width: 100%; }
#ovmLayer .ovm-hud-charm-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#ovmLayer .ovm-hud-charm .ovm-orb,
#ovmLayer .ovm-hud-count { flex: none; }

#ovmLayer .ovm-hud-charm:hover { border-color: rgba(230, 209, 160, 0.66); }
#ovmLayer .ovm-hud-charm.ovm-static { cursor: default; pointer-events: none; }
#ovmLayer .ovm-hud-charm.ovm-warn { color: var(--ovm-warn); }

#ovmLayer .ovm-hud-count {
  color: var(--ovm-gold);
  font-variant-numeric: tabular-nums;
}

#ovmLayer .ovm-hud-extra {
  flex-wrap: wrap;
  gap: 2px 12px;
  color: var(--ovm-ink-dim);
  font-size: 13px;
  font-weight: 600;
  white-space: normal;   /* the long Safari drain line wraps inside the pill */
}

#ovmLayer .ovm-hud-pending::before {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 7px;
  border-radius: 50%;
  background: var(--ovm-gold);
  vertical-align: 1px;
  animation: ovm-pulse 1.1s ease-in-out infinite;
}

#ovmLayer .ovm-hud-drain { color: var(--ovm-warn); }

#ovmLayer .ovm-hud-hint {
  color: var(--ovm-ink-dim);
  font-size: 13px;
  letter-spacing: 0.02em;
}

#ovmLayer .ovm-hud-throw {
  flex: none;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-width: 68px;
  min-height: 64px;
  margin: 0;
  padding: 7px 10px 6px;
  border: 1px solid rgba(230, 209, 160, 0.56);
  border-radius: 14px;
  background: linear-gradient(179deg, #2d241e 0%, #100c0a 100%);
  box-shadow:
    inset 0 0 0 4px rgba(11, 8, 7, 0.9),
    inset 0 0 0 5px rgba(230, 209, 160, 0.2);
  color: var(--ovm-gold);
  font: inherit;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.04em;
  cursor: pointer;
  pointer-events: auto;
}

#ovmLayer .ovm-hud-throw:hover { border-color: rgba(230, 209, 160, 0.9); color: #fff3d0; }
#ovmLayer .ovm-hud-throw:active { transform: translateY(1px); }
#ovmHud.ovm-blocked .ovm-hud-throw { opacity: 0.72; }

#ovmLayer .ovm-hud-btn:focus-visible {
  outline: 2px solid var(--ovm-gold);
  outline-offset: 2px;
}

#ovmLayer .ovm-kbd {
  min-width: 18px;
  padding: 1px 5px;
  border: 1px solid rgba(230, 209, 160, 0.45);
  border-radius: 5px;
  color: var(--ovm-ink-dim);
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
}

/* Permanent key badges: R (next target) on the target line, C (change charm) in the pill. */
#ovmLayer .ovm-kbd-target,
#ovmLayer .ovm-kbd-charm {
  flex: none;
  align-self: center;
  min-width: 16px;
  padding: 0 4px;
  font-size: 11px;
  line-height: 16px;
}
#ovmLayer .ovm-kbd-charm { margin-left: 1px; }

/* Charm orb, tinted from the game's own charm colours (set by ui.js as custom properties). */
.ovm-orb {
  display: inline-block;
  flex: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 34% 28%, rgba(255, 255, 255, 0.85) 0 11%, transparent 12%),
    linear-gradient(180deg,
      var(--ovm-charm-a, #78ead7) 0 44%,
      var(--ovm-charm-c, #ffd36a) 44% 57%,
      var(--ovm-charm-b, #245d68) 57% 100%);
  box-shadow: inset 0 0 0 1.5px rgba(0, 0, 0, 0.55), 0 1px 3px rgba(0, 0, 0, 0.5);
}

.ovm-orb.ovm-orb-lg { width: 24px; height: 24px; }
.ovm-orb.ovm-orb-sm { width: 14px; height: 14px; }

/* With the game's charm art available (ui.js sets --ovm-charm-art = the battle capture sheet of the
   selected charm kind): show frame 0, the closed charm, with the battle's radial edge fade. */
[data-charm-art] .ovm-orb {
  border-radius: 0;
  background: var(--ovm-charm-art) 0 0 / 2400% 100% no-repeat;
  box-shadow: none;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6));
  -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 52%, transparent 92%);
  mask-image: radial-gradient(circle at 50% 50%, #000 52%, transparent 92%);
  transform: scale(1.25);
}

@keyframes ovm-pulse {
  0%, 100% { opacity: 0.45; transform: scale(0.85); }
  50% { opacity: 1; transform: scale(1.1); }
}

/* ---- touch layout (mobile.js adds html.is-touch) ------------------------------------------- */
/* The layer becomes a full-screen, click-through overlay: HUD top-right (safe-area aware),
   notices top-left inside the 4:3 picture just below the canvas nameplate. The picture box uses
   the same fit as styles.css (`html.is-touch #game`): min(100vw, 100dvh*4/3) x min(100dvh, 100vw*3/4). */
html.is-touch #ovmLayer {
  --ovm-canvas-w: min(100vw, 100dvh * 4 / 3);
  --ovm-canvas-h: min(100dvh, 100vw * 3 / 4);
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  transform: none;
  display: block;
  width: auto;
  max-width: none;
  font-size: 13px;
}

/* The dock is the top-right column: HUD pill first, status chips below it (or in its place while
   the pill is hidden). */
html.is-touch #ovmLayer .ovm-dock {
  position: absolute;
  top: max(8px, env(safe-area-inset-top));
  right: max(10px, env(safe-area-inset-right));
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 5px;
  max-width: min(42vw, 320px);
  pointer-events: none;
}

html.is-touch #ovmHud {
  max-width: 100%;
  box-sizing: border-box;
  gap: 10px;
  padding: 7px 12px;
  border-radius: 14px;
}

/* Touch: compact chips under the pill (the pill keeps its corner when a chip comes). The next-target /
   change-charm buttons - and on narrow phones the bike button - sit right below the dock in the right
   letterbox margin, so the chips keep their right edge 6 px inside the picture: shifted (position:
   relative, the dock width stays), never under those buttons however tall the pill gets (pending line,
   the 46 px .online-hud offset of the private build). At most half the picture minus 20 px wide, so they
   stay right of the player and of the notice column. 17 px each: two chips below the tallest pill still
   end above the bike button at 667x375 with .online-hud (qa_species_stars.cjs layout run). */
html.is-touch #ovmStatus {
  order: 3;
  position: relative;
  right: max(0px, calc((100vw - var(--ovm-canvas-w)) / 2 + 6px - max(10px, env(safe-area-inset-right))));
  align-items: flex-end;
  gap: 2px;
}
html.is-touch #ovmLayer .ovm-status-chip {
  gap: 5px;
  max-width: min(100%, calc(var(--ovm-canvas-w) / 2 - 20px));
  padding: 1px 9px 1px 7px;
  font-size: 10.5px;
}
html.is-touch #ovmLayer .ovm-status-dot { width: 6px; height: 6px; }

html.is-touch #ovmNotices {
  /* x of the column; the joystick indent below a catch card is measured from it */
  --ovm-notices-left: max(calc(env(safe-area-inset-left) + 8px), calc((100vw - var(--ovm-canvas-w)) / 2 + var(--ovm-canvas-w) * 0.016));
  position: absolute;
  top: calc((100dvh - var(--ovm-canvas-h)) / 2 + var(--ovm-canvas-h) * 0.135);
  left: var(--ovm-notices-left);
  /* Narrow column on the left of the picture: two notices end above/left of the player. */
  max-width: min(34vw, 300px);
  align-items: flex-start;
}

html.is-touch #ovmLayer .ovm-notice {
  padding: 7px 12px;
  font-size: 13px;
  text-align: left;
}

html.is-touch #ovmLayer .ovm-hud-name { font-size: 14px; }
html.is-touch #ovmLayer .ovm-hud-stars { line-height: 14px; }
html.is-touch #ovmLayer .ovm-hud-status,
html.is-touch #ovmLayer .ovm-hud-empty { font-size: 13px; }
html.is-touch #ovmLayer .ovm-hud-hint,
html.is-touch #ovmLayer .ovm-kbd { display: none; }
html.is-touch #ovmLayer.ovm-touch-attached .ovm-hud-throw { display: none; }
html.is-touch #ovmLayer.ovm-touch-attached .ovm-hud-charm { pointer-events: none; cursor: default; }
/* Touch with the charm button attached: no target pill at all - the ring under the monster marks the
   target, the charm button shows the charm and how many are left, a catch shows its card. */
html.is-touch #ovmLayer.ovm-touch-attached #ovmHud { display: none !important; }

/* Private/online hosts pin .online-hud to the same corner: the status chips drop below it. */
html.is-touch body:has(.online-hud) #ovmLayer .ovm-dock {
  top: calc(max(8px, env(safe-area-inset-top)) + 46px);
}

/* ---- touch charm button + charm tray (2026-10-11) ------------------------------------------
   #ovmThrow lives in `.tc-actions` (styles.css: a 0x0 anchor in the bottom-right corner) where the
   right thumb rests: --tc-throw-cx / --tc-throw-cy are its centre from the right / bottom screen edge.
   It reuses .tc-btn (felt skin) and is its own touch target, so a second finger throws while the
   first holds the joystick. Content: the selected charm's art (frame 0 of its capture sheet, the
   Prismatic Charm's frame 7 - its frame 0 is a flash), the count left as a pill on the rim, and the
   hold ring (fills from 0.3 s, the tray opens at 2 s). */
html.is-touch #touchControls .tc-actions #ovmThrow {
  position: absolute;
  right: calc(var(--tc-throw-cx, 55px) - var(--tc-throw-size, 74px) / 2);
  bottom: calc(var(--tc-throw-cy, 71px) - var(--tc-throw-size, 74px) / 2);
  width: var(--tc-throw-size, 74px);
  height: var(--tc-throw-size, 74px);
  display: grid;
  place-items: center;
  margin: 0;
  padding: 0;
  min-width: 0;
  min-height: 0;
  overflow: visible;
  pointer-events: auto;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  transition: box-shadow 160ms ease;
}
html.is-touch #touchControls .tc-actions #ovmThrow[hidden] { display: none !important; }
html.is-touch #touchControls #ovmThrow.is-ready {
  box-shadow:
    inset 0 0 0 5px rgba(11, 8, 7, 0.92),
    inset 0 0 0 7px var(--ovm-charm-a, #78ead7),
    0 0 16px var(--ovm-charm-a, #78ead7),
    0 8px 18px rgba(0, 0, 0, 0.5);
}
html.is-touch #touchControls .ovm-throw-art {
  position: absolute;
  inset: 9%;
  border-radius: 50%;
  pointer-events: none;
  /* fallback while the sheet loads: the charm colours as an orb */
  background:
    radial-gradient(circle at 36% 28%, rgba(255, 255, 255, 0.85) 0 9%, transparent 10%),
    radial-gradient(circle at 50% 42%, var(--ovm-charm-a, #78ead7), var(--ovm-charm-b, #245d68) 70%, transparent 72%);
  transition: transform 110ms ease-out, opacity 160ms ease, filter 160ms ease;
}
html.is-touch #touchControls #ovmThrow[data-charm-art] .ovm-throw-art {
  inset: 5%;
  border-radius: 0;
  background: var(--ovm-charm-art) 0 0 / 2400% 100% no-repeat;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.6));
  -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 54%, transparent 90%);
  mask-image: radial-gradient(circle at 50% 50%, #000 54%, transparent 90%);
}
html.is-touch #touchControls #ovmThrow[data-charm-art][data-kind="prismatic"] .ovm-throw-art { background-position-x: 30.4348%; }
/* No monster in reach: the charm rests a little dimmer (the button stays, never pops in and out). */
html.is-touch #touchControls #ovmThrow:not(.is-ready) .ovm-throw-art { opacity: 0.74; filter: saturate(0.8) drop-shadow(0 2px 3px rgba(0, 0, 0, 0.6)); }
html.is-touch #touchControls #ovmThrow.is-empty .ovm-throw-art { opacity: 0.45; filter: grayscale(1) drop-shadow(0 2px 3px rgba(0, 0, 0, 0.6)); }
html.is-touch #touchControls #ovmThrow.is-pressed .ovm-throw-art { transform: scale(0.92); }
html.is-touch #touchControls #ovmThrow.is-kick .ovm-throw-art { transform: translate(-5px, -7px) rotate(-14deg) scale(0.9); }
html.is-touch #touchControls #ovmThrow.is-nope { animation: ovm-nope 280ms ease-in-out; }
@keyframes ovm-nope {
  20% { translate: -4px 0; }
  45% { translate: 4px 0; }
  70% { translate: -2px 0; }
  100% { translate: 0 0; }
}
html.is-touch #touchControls .ovm-throw-count {
  position: absolute;
  left: 50%;
  bottom: -7px;
  transform: translateX(-50%);
  min-width: 28px;
  box-sizing: border-box;
  padding: 2px 7px 3px;
  border-radius: 999px;
  background: #15110c;
  box-shadow: inset 0 0 0 1.5px rgba(230, 209, 160, 0.82), 0 2px 5px rgba(0, 0, 0, 0.55);
  color: #fbeec9;
  font: 900 13px/1 "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  letter-spacing: 0;
  text-align: center;
  font-variant-numeric: tabular-nums;
  text-shadow: none;
  pointer-events: none;
}
html.is-touch #touchControls .ovm-throw-count.is-low { color: #ffc28f; }
html.is-touch #touchControls #ovmThrow.is-empty .ovm-throw-count { color: #ff9b86; }
/* Hold ring: r 47 in a 100 box -> circumference 295.3. It fills while the finger stays (from 0.3 s,
   1.7 s long - the tray opens when it closes) and rewinds when the finger lifts early. */
html.is-touch #touchControls .ovm-hold-ring {
  position: absolute;
  inset: -7px;
  transform: rotate(-90deg);
  pointer-events: none;
  opacity: 0;
  transition: opacity 120ms ease;
}
html.is-touch #touchControls .ovm-hold-ring svg { display: block; width: 100%; height: 100%; overflow: visible; }
html.is-touch #touchControls .ovm-hold-ring circle {
  fill: none;
  stroke: #f3d987;
  stroke-width: 4.5;
  stroke-linecap: round;
  stroke-dasharray: 295.3;
  stroke-dashoffset: 295.3;
  transition: stroke-dashoffset 140ms ease-out;
}
html.is-touch #touchControls #ovmThrow.is-charging .ovm-hold-ring { opacity: 1; }
html.is-touch #touchControls #ovmThrow.is-charging .ovm-hold-ring circle {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1700ms linear;
}
html.is-touch #touchControls #ovmThrow.is-tray-open {
  box-shadow:
    inset 0 0 0 5px rgba(11, 8, 7, 0.92),
    inset 0 0 0 7px #f3d987,
    0 8px 18px rgba(0, 0, 0, 0.5);
}

/* Charm tray: left of the charm button, vertically centred on it, over A / harpoon while open. */
html.is-touch #touchControls .ovm-tray {
  position: absolute;
  right: calc(var(--tc-throw-cx, 55px) + var(--tc-throw-size, 74px) / 2 + 12px);
  bottom: calc(var(--tc-throw-cy, 71px) - 44px);
  z-index: 3;
  display: grid;
  gap: 5px;
  padding: 8px 10px 7px;
  border-radius: 16px;
  border: 1px solid rgba(230, 209, 160, 0.58);
  background: linear-gradient(179deg, #241d18 0%, #0c0908 100%);
  box-shadow: inset 0 0 0 4px rgba(11, 8, 7, 0.9), 0 12px 28px rgba(0, 0, 0, 0.62);
  pointer-events: auto;
  touch-action: none;
  transform-origin: 100% 50%;
  animation: ovm-tray-in 160ms cubic-bezier(.2, 1.2, .4, 1) both;
}
html.is-touch #touchControls .ovm-tray[hidden] { display: none !important; }
@keyframes ovm-tray-in {
  from { opacity: 0; transform: translateX(12px) scale(0.88); }
  to { opacity: 1; transform: none; }
}
html.is-touch #touchControls .ovm-tray-slots { display: flex; gap: 5px; }
html.is-touch #touchControls .ovm-tray-slot {
  position: relative;
  display: grid;
  justify-items: center;
  align-content: start;
  width: 50px;
  height: 62px;
  margin: 0;
  padding: 4px 0 0;
  border: 0;
  border-radius: 11px;
  background: rgba(255, 255, 255, 0.04);
  color: #f2ece0;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}
html.is-touch #touchControls .ovm-tray-art {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 42%, #78ead7, #245d68 70%, transparent 72%);
  pointer-events: none;
}
html.is-touch #touchControls .ovm-tray-slot[data-charm-art] .ovm-tray-art {
  border-radius: 0;
  background: var(--ovm-slot-art) 0 0 / 2400% 100% no-repeat;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6));
  -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 54%, transparent 90%);
  mask-image: radial-gradient(circle at 50% 50%, #000 54%, transparent 90%);
}
html.is-touch #touchControls .ovm-tray-slot[data-charm-art][data-kind="prismatic"] .ovm-tray-art { background-position-x: 30.4348%; }
html.is-touch #touchControls .ovm-tray-count {
  margin-top: 2px;
  font: 900 12px/1 "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
html.is-touch #touchControls .ovm-tray-slot.is-selected { background: rgba(243, 217, 135, 0.12); box-shadow: inset 0 0 0 2px #f3d987; }
html.is-touch #touchControls .ovm-tray-slot.is-hover { background: rgba(120, 234, 215, 0.16); box-shadow: inset 0 0 0 2px #78ead7; }
html.is-touch #touchControls .ovm-tray-slot.is-empty .ovm-tray-art { filter: grayscale(1) brightness(0.55); }
html.is-touch #touchControls .ovm-tray-slot.is-empty .ovm-tray-count { color: #8a8071; }
html.is-touch #touchControls .ovm-tray-slot.is-locked .ovm-tray-art { filter: grayscale(0.85) brightness(0.5); }
html.is-touch #touchControls .ovm-tray-slot.is-locked .ovm-tray-count { color: #8a8071; }
html.is-touch #touchControls .ovm-tray-lock {
  position: absolute;
  top: 15px;
  left: 50%;
  width: 16px;
  height: 16px;
  margin-left: -8px;
  pointer-events: none;
}
html.is-touch #touchControls .ovm-tray-lock svg {
  display: block;
  width: 100%;
  height: 100%;
  fill: rgba(20, 16, 10, 0.85);
  stroke: #f1dfb2;
  stroke-width: 1.6;
}
html.is-touch #touchControls .ovm-tray-slot.is-refused { animation: ovm-nope 240ms ease-in-out; }
html.is-touch #touchControls .ovm-tray-caption {
  min-height: 14px;
  color: #f1dfb2;
  font: 700 12px/1.2 "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  text-align: center;
  white-space: nowrap;
}
html.is-touch #touchControls .ovm-tray-caption.is-locked { color: #ffc28f; }
/* Small phones (568-600px wide): narrower slots keep the open tray right of the joystick ring. */
@media (max-width: 600px) {
  html.is-touch #touchControls .ovm-tray { padding: 7px 8px 6px; }
  html.is-touch #touchControls .ovm-tray-slots { gap: 4px; }
  html.is-touch #touchControls .ovm-tray-slot { width: 42px; height: 56px; }
  html.is-touch #touchControls .ovm-tray-art { width: 34px; height: 34px; }
  html.is-touch #touchControls .ovm-tray-lock { top: 12px; }
}

html.is-touch body.mobile-menu-open #touchControls .ovm-tc-btn,
html.is-touch body.mobile-debug-open #touchControls .ovm-tc-btn,
html.is-touch body.mobile-menu-open #touchControls .ovm-tray,
html.is-touch body.mobile-debug-open #touchControls .ovm-tray {
  display: none !important;
}

/* ---- hide rules ---------------------------------------------------------------------------- */
body:has(#battle:not(.hidden)) #ovmLayer,
body:has(#modal:not(.hidden)) #ovmLayer,
body:has(#speechBubble:not(.hidden)) #ovmLayer,
body:has(#tacticsLayer:not(.hidden)) #ovmLayer,
body.speech-wide-art-open #ovmLayer,
body.mobile-menu-open #ovmLayer,
body.mobile-debug-open #ovmLayer,
body.reedfen-scan-open #ovmLayer,
body.online-trade-open #ovmLayer,
body.online-trade-fx-open #ovmLayer,
body.online-player-action-open #ovmLayer,
body.online-duel-open #ovmLayer,
body.online-profile-open #ovmLayer,
body.online-gift-open #ovmLayer,
body.online-leaderboard-open #ovmLayer {
  display: none !important;
}

/* Portrait phones show the rotate hint instead of controls. */
@media (max-width: 960px) and (orientation: portrait), (pointer: coarse) and (orientation: portrait) {
  html.is-touch #ovmLayer { display: none !important; }
}

/* Narrow desktop windows. */
@media (max-width: 700px) {
  html:not(.is-touch) #ovmLayer {
    left: 10px;
    bottom: 70px;
    max-width: calc(100% - 20px);
  }
  html:not(.is-touch) #ovmHud {
    gap: 8px;
    padding-left: 12px;
  }
}

/* Reduced motion: system setting and the game's own switch (ui.js adds .ovm-reduced).
   Pseudo-elements included (the pending dot is a ::before). */
@media (prefers-reduced-motion: reduce) {
  #ovmLayer,
  #ovmLayer *,
  #ovmLayer *::before,
  #ovmLayer *::after,
  #touchControls .ovm-tc-btn,
  #touchControls .ovm-tc-btn *,
  #touchControls .ovm-tc-btn::before,
  #touchControls .ovm-tc-btn::after,
  #touchControls .ovm-tray,
  #touchControls .ovm-tray * {
    animation: none !important;
    transition: none !important;
  }
}

#ovmLayer.ovm-reduced *,
#ovmLayer.ovm-reduced *::before,
#ovmLayer.ovm-reduced *::after,
#touchControls .ovm-tc-btn.ovm-reduced,
#touchControls .ovm-tc-btn.ovm-reduced::before,
#touchControls .ovm-tc-btn.ovm-reduced::after,
#touchControls .ovm-tc-btn.ovm-reduced *,
#touchControls .ovm-tray.ovm-reduced,
#touchControls .ovm-tray.ovm-reduced * {
  animation: none !important;
  transition: none !important;
}

/* ---- partner picker and partner controls (built by shared/overworld-monsters/partner.js) ----
 * Lives inside the game's own modal (.modal-card, party layout); only layout is added here, the
 * card, typography and buttons keep the game's existing skin. Rows are real <button>/<div>
 * elements with >= 44 px targets.
 * Layout: title, intro and the action row keep their height (flex: none); ONE scroll container
 * (.ovm-partner-scroll) takes the rest and holds "No partner" plus both sections, whose lists
 * have no scrolling of their own - on 390 px tall phones every row is reachable in one list. */
.ovm-partner-picker {
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-sizing: border-box;
  min-height: 0;
  max-height: min(86vh, 860px);
  max-height: min(86dvh, 860px);
}
.ovm-partner-picker > h2,
.ovm-partner-picker > .ovm-partner-intro,
.ovm-partner-picker > .ovm-partner-actions { flex: 0 0 auto; }
.ovm-partner-picker h2 { margin: 0; }
.ovm-partner-intro { margin: 0; }
.ovm-partner-picker > .ovm-partner-actions { margin-top: 0; }
.ovm-partner-scroll {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  /* room for the 3px focus outline (offset 2px) inside the scroller */
  padding: 5px 6px 5px 5px;
  margin: -5px -6px -5px -5px;
}
.ovm-partner-section {
  flex: 0 0 auto;
  margin: 6px 0 0;
  font-size: 0.86rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.82;
}
.ovm-partner-list {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
  gap: 8px;
}
/* The picker card must stay inside the room's padding box instead of spilling past the viewport
   edge. On touch the game makes every .modal-card a 100vw x 100dvh sheet while the party room
   (#modal.clean-world-modal.party-full-modal) keeps a clamp(12px, 2vw, 24px) padding; the card is
   a grid item in an auto track there, so max-width: 100% alone cannot limit it - the touch rule
   sizes it to the padding box explicitly. */
#modal.party-full-modal .ovm-partner-picker {
  box-sizing: border-box;
  max-width: 100%;
  max-height: 100%;
}
@media (max-width: 960px), (pointer: coarse) {
  html.is-touch #modal.party-full-modal .ovm-partner-picker {
    width: calc(100vw - 2 * clamp(12px, 2vw, 24px));
    height: calc(100dvh - 2 * clamp(12px, 2vw, 24px));
    max-width: calc(100vw - 2 * clamp(12px, 2vw, 24px));
    max-height: calc(100dvh - 2 * clamp(12px, 2vw, 24px));
  }
}
.ovm-partner-row {
  display: grid;
  grid-template-columns: 52px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  min-height: 56px;
  padding: 6px 10px;
  border: 1px solid rgba(127, 127, 127, 0.36);
  border-radius: 12px;
  background: rgba(127, 127, 127, 0.1);
  color: inherit;
  text-align: left;
  font: inherit;
}
button.ovm-partner-row { cursor: pointer; width: 100%; }
.ovm-partner-row--none {
  flex: 0 0 auto;
  grid-template-columns: minmax(0, 1fr);
  box-sizing: border-box;
  height: auto;
}
.ovm-partner-row.is-locked .ovm-partner-thumb { filter: grayscale(1); opacity: 0.6; }
.ovm-partner-row.is-locked .ovm-partner-name { opacity: 0.75; }
.ovm-partner-row.is-current {
  border-color: rgba(64, 160, 92, 0.9);
  background: rgba(64, 160, 92, 0.16);
  box-shadow: inset 0 0 0 1px rgba(155, 227, 166, 0.35);
}
.ovm-partner-row:focus-visible,
.ovm-partner-choose:focus-visible { outline: 3px solid #ead79a; outline-offset: 2px; }
.ovm-partner-thumb-well {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 10px;
  background: radial-gradient(circle at 50% 60%, rgba(255, 244, 214, 0.16), rgba(0, 0, 0, 0) 70%);
}
.ovm-partner-thumb { width: 48px; height: 48px; object-fit: contain; image-rendering: auto; }
.ovm-partner-name {
  min-width: 0;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow-wrap: anywhere;
  line-height: 1.25;
}
.ovm-partner-choose { min-height: 44px; min-width: 44px; padding: 6px 12px; white-space: nowrap; }
.ovm-partner-chip {
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid rgba(64, 160, 92, 0.85);
  color: inherit;
  font-size: 0.82rem;
  white-space: nowrap;
}
.ovm-partner-chip--locked {
  border-color: rgba(127, 127, 127, 0.6);
  white-space: normal;
  text-align: right;
}
.ovm-partner-empty { margin: 4px 0; }
/* >= 44px targets. The game's dialogue-action rules (e.g. .modal.party-full-modal .party-modal
   .dialogue-actions button) set smaller heights, so these rules carry the #modal id. */
#modal button.ovm-partner-open,
#modal button.ovm-partner-detail,
#modal button.ovm-partner-detail-head-btn,
#modal button.ovm-partner-choose,
#modal .ovm-partner-actions > button,
#modal button.ovm-partner-row--none {
  min-height: 44px;
}
/* Compact partner control right below the details head (no scrolling to the bottom needed). */
.ovm-partner-detail-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  margin: 10px 0 6px;
}
.ovm-partner-detail-head-btn { padding: 6px 14px; white-space: nowrap; }
.ovm-partner-detail-head-btn:focus-visible,
.ovm-partner-detail:focus-visible,
.ovm-partner-open:focus-visible { outline: 3px solid #ead79a; outline-offset: 2px; }
html.is-touch .ovm-partner-list { grid-template-columns: minmax(0, 1fr); }
@media (prefers-reduced-motion: reduce) {
  .ovm-partner-row, .ovm-partner-choose, .ovm-partner-detail-head-btn { transition: none !important; }
}

/* Size chip for unusually large / small specimens (render.js specimen(): about 3 % per tail).
   Used in the capture HUD target line and in the game's monster details heading. */
.ovm-size-chip {
  display: inline-flex;
  align-items: center;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  font: 700 11px/1.4 inherit;
  letter-spacing: 0.04em;
  vertical-align: middle;
  white-space: nowrap;
  border: 1px solid rgba(255, 255, 255, 0.28);
}
.ovm-size-chip.is-giant { background: rgba(214, 150, 54, 0.92); color: #1d1204; border-color: rgba(255, 220, 150, 0.7); }
.ovm-size-chip.is-tiny { background: rgba(92, 164, 196, 0.92); color: #06161e; border-color: rgba(190, 236, 255, 0.7); }
.ovm-size-chip[hidden] { display: none; }
#modal .monster-detail .detail-head h2 .ovm-detail-size { font-size: 12px; }
/* Size with percent ("Größe 104 %"): neutral unless it is a giant / tiny specimen. */
.ovm-size-chip.ovm-size-pct:not(.is-giant):not(.is-tiny) { background: rgba(255, 255, 255, 0.12); color: inherit; }

/* Battle catch ceremony: the size sits in the lineage row next to level / type / gender. A normal
   specimen reads like the other entries (text + separator), giant / tiny keep their coloured pill. */
.catch-ceremony .catch-lineage > .ovm-catch-size { margin-left: 0; font: inherit; letter-spacing: 0; }
.catch-ceremony .catch-lineage > .ovm-catch-size:not(.is-giant):not(.is-tiny) {
  background: none;
  border-width: 0 0 0 1px;
  border-radius: 0;
  color: #d6dfd8;
}
.catch-ceremony .catch-lineage > .ovm-catch-size.is-giant,
.catch-ceremony .catch-lineage > .ovm-catch-size.is-tiny { border-left-width: 1px; padding: 0 9px; }

/* ---- Catch card: a field catch shows a small card instead of a ceremony (the run goes on). It
   lives in the notice column (desktop: bottom-left above the HUD; touch: top-left under the map
   name), never takes input and fades after ~4 s. */
#ovmLayer .ovm-catch-card {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 230px;
  max-width: 330px;
  padding: 8px 12px 8px 8px;
  border-left-color: var(--ovm-success);
}
#ovmLayer .ovm-catch-card.is-practice { border-left-color: var(--ovm-gold); }
#ovmLayer .ovm-cc-art {
  flex: 0 0 54px;
  width: 54px;
  height: 54px;
  object-fit: contain;
  object-position: center bottom;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.55));
}
#ovmLayer .ovm-cc-body { display: grid; gap: 2px; min-width: 0; }
#ovmLayer .ovm-cc-title { font-size: 11px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ovm-success); }
#ovmLayer .is-practice .ovm-cc-title { color: var(--ovm-gold); }
#ovmLayer .ovm-cc-head { display: flex; flex-wrap: wrap; align-items: center; gap: 3px 6px; }
#ovmLayer .ovm-cc-name { font-size: 15px; font-weight: 750; }
#ovmLayer .ovm-cc-meta { font-size: 12px; font-weight: 600; color: var(--ovm-ink-dim); }
#ovmLayer .ovm-cc-head .ovm-size-chip { margin-left: 0; font-size: 10.5px; }
#ovmLayer .ovm-cc-holo {
  padding: 0 6px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 800;
  color: #1a1308;
  background: linear-gradient(90deg, #fff3a6, #a9f0ff, #ffc2f1, #bdffd2);
}
#ovmLayer .is-black-holo .ovm-cc-holo { color: #f1ecff; background: linear-gradient(90deg, #1b1430, #3b2a6e, #1b1430); border: 1px solid rgba(214, 200, 255, 0.6); }
#ovmLayer .ovm-cc-dv { display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 700; color: var(--ovm-gold); font-variant-numeric: tabular-nums; }
#ovmLayer .ovm-cc-bars { display: inline-flex; align-items: flex-end; gap: 2px; height: 14px; }
#ovmLayer .ovm-cc-bars i { display: block; width: 5px; height: calc(3px + 11px * var(--v, 0)); border-radius: 1px; background: linear-gradient(180deg, #f3df9f, #b98d3a); }
#ovmLayer .ovm-cc-place { font-size: 11.5px; font-weight: 600; color: var(--ovm-ink-dim); }
/* Touch: compact, so the card stays in the upper-left quarter of the picture (the player is in the
   middle). */
html.is-touch #ovmLayer .ovm-catch-card { min-width: 0; max-width: min(30vw, 236px); gap: 7px; padding: 5px 9px 5px 5px; }
html.is-touch #ovmLayer .ovm-cc-art { flex-basis: 34px; width: 34px; height: 34px; }
html.is-touch #ovmLayer .ovm-cc-body { gap: 1px; }
html.is-touch #ovmLayer .ovm-cc-title { font-size: 9.5px; }
html.is-touch #ovmLayer .ovm-cc-name { font-size: 12.5px; }
html.is-touch #ovmLayer .ovm-cc-meta,
html.is-touch #ovmLayer .ovm-cc-dv { font-size: 10.5px; }
html.is-touch #ovmLayer .ovm-cc-head .ovm-size-chip { font-size: 9.5px; padding: 0 5px; }
html.is-touch #ovmLayer .ovm-cc-bars { height: 11px; }
html.is-touch #ovmLayer .ovm-cc-bars i { width: 4px; height: calc(2px + 9px * var(--v, 0)); }
html.is-touch #ovmLayer .ovm-cc-place { font-size: 10px; line-height: 1.25; }

/* Species stars on the catch card: one line (reached star + first reward, new species, progress to
   the next star, all stars); DVs the stars just set to the cap glow on the bars. */
#ovmLayer .ovm-cc-stars {
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1.3;
  color: #efd893;
  font-variant-numeric: tabular-nums;
}
#ovmLayer .ovm-cc-stars.is-new { color: #b9f0c2; }
#ovmLayer .ovm-cc-stars.is-reached { color: #fff0b8; text-shadow: 0 0 8px rgba(255, 214, 110, 0.55); }
#ovmLayer .ovm-cc-stars.is-max { color: #ffe9a8; }
#ovmLayer .ovm-cc-bars i.is-raised {
  background: linear-gradient(180deg, #fffbe0, #ffd36a);
  box-shadow: 0 0 5px rgba(255, 214, 110, 0.85);
}
html.is-touch #ovmLayer .ovm-cc-stars { font-size: 10px; line-height: 1.25; }
/* Touch: a notice below a catch card (the star reward, a swarm bonus ...) ends left of the player (picture
   centre - 18 px, at most the card's 236 px), so the taller stack never covers the middle of the picture.
   On narrow phones (667x375, 740x360) that stack reaches down past the joystick ring (132 px at the
   bottom-left): those notices are indented to start 2 px right of the ring (0 where the column already
   starts there, e.g. 844x390), so even the long German ★5 reward never runs under it. */
html.is-touch #ovmLayer .ovm-catch-card ~ .ovm-notice:not(.ovm-catch-card) {
  --ovm-pad-indent: max(0px, calc(max(16px, env(safe-area-inset-left)) + 134px - var(--ovm-notices-left)));
  margin-left: var(--ovm-pad-indent);
  max-width: min(236px, calc(50vw - 18px - var(--ovm-notices-left) - var(--ovm-pad-indent)));
  font-size: 12px;
  line-height: 1.3;
}
/* Narrow, short phones: the indented column is narrow - a little more text per line keeps the card + two
   notices inside the screen. */
@media (max-width: 799px) and (max-height: 400px) {
  html.is-touch #ovmLayer .ovm-catch-card ~ .ovm-notice:not(.ovm-catch-card) { padding: 6px 10px; font-size: 11px; }
}

/* Battle catch ceremony: the stars chip ends the lineage row (level · type · gender · size · stars);
   a reached star or a new species gets one line below it. */
.catch-ceremony .catch-lineage > .ovm-catch-stars {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: #e9dcae;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.catch-ceremony .ovm-catch-stars-glyphs { color: #f3d27a; font-weight: 400; letter-spacing: 0.06em; }
.catch-ceremony .ovm-catch-stars-tag {
  padding: 0 6px;
  border: 1px solid rgba(243, 210, 122, 0.55);
  border-radius: 3px;
  color: #f3d27a;
  font-size: 0.82em;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.catch-ceremony .ovm-catch-stars.is-master .ovm-catch-stars-tag {
  border-color: rgba(201, 184, 255, 0.8);
  background: linear-gradient(90deg, rgba(255, 243, 166, 0.2), rgba(169, 240, 255, 0.2), rgba(255, 194, 241, 0.2));
  color: #fff6d8;
}
#modal .catch-ceremony .ovm-catch-stars-line {
  margin: 8px 0 0;
  color: #f6e3a3;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.4;
}
#modal .catch-ceremony .ovm-catch-stars-line.is-new { color: #bfeccb; }
@media (prefers-reduced-motion: no-preference) {
  #modal .catch-ceremony .ovm-catch-stars-line.is-reached { animation: ovm-notice-in 360ms ease-out 420ms both; }
}
@media (max-height: 600px) and (min-aspect-ratio: 1/1) {
  #modal .catch-ceremony .ovm-catch-stars-line { margin-top: 5px; font-size: 11px; line-height: 1.3; }
}
@media (max-aspect-ratio: 1/1) {
  #modal .catch-ceremony .ovm-catch-stars-line { text-align: center; font-size: 12px; }
}

/* Catch card queue: "+N" while N more catches wait for their card. */
#ovmLayer .ovm-catch-card { position: relative; }
#ovmLayer .ovm-cc-more {
  position: absolute;
  top: 6px;
  right: 7px;
  padding: 2px 6px;
  border-radius: 999px;
  background: var(--ovm-gold);
  color: #1a140b;
  font-size: 11px;
  font-weight: 900;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
html.is-touch #ovmLayer .ovm-cc-more { top: 4px; right: 5px; font-size: 10px; }
