/* "DR Anno Ref": one-glyph web fonts (scripts/make-anno-font.py) that map
   U+25A3 — the ▣ opening an inline annotation reference (`▣n`) — to an EMPTY
   glyph. Prepended to a font stack they decide what the marker occupies, so a
   reference reads as its bracketed number [n] with no ▣ in sight: in rendered
   note bodies AND inside an editor textarea, whose glyph metrics no other CSS
   can reach (the highlight mirror behind it must stay metrically identical).
   Two advances, one per surface:
     "DR Anno Ref"       0     rendered bodies: the ▣ vanishes, `[`/`]` come
                               from ::before/::after around the real digits.
     "DR Anno Ref Edit"  U+E101-E163 (1.45em / 1.95em) + U+25A3 (0.9em):
                               editors hold each ref as ONE private-use
                               character (U+E100+n, review.js encodeRefs) so
                               the caret treats it as one unit; its advance
                               fits the painted `[n]` (600 10px mono, 6px a
                               glyph: 18px one digit, 24px two).
   unicode-range keeps both faces away from every other character, so
   line-box/strut metrics are still the real font's. Under 3 KB, inlined so
   the /vods staging and the desktop build need no extra asset. */
@font-face {
  font-family: "DR Anno Ref";
  src: url("data:font/woff;base64,d09GRgABAAAAAAKoAAoAAAAAA2QAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABWAAAAC0AAABgioJnP2NtYXAAAAGQAAAAKgAAADQADCX2Z2x5ZgAAAcQAAAABAAAAAQAAAABoZWFkAAAA9AAAADYAAAA2LNCevGhoZWEAAAEsAAAAFwAAACQDIf86aG10eAAAAYgAAAAGAAAABgAAAABsb2NhAAABvAAAAAYAAAAGAAAAAG1heHAAAAFEAAAAEwAAACAAAwACbmFtZQAAAcgAAADKAAABaMmatwxwb3N0AAAClAAAABMAAAApeAYCegABAAAAAQAArU7RqV8PPPUAAwPoAAAAAObdLu4AAAAA5t0u7gAAAAAAAAAAAAAAAwACAAAAAAAAeJxjYGRgYFb4b8GAAIwMqIARACjTAV4AeJxjYGRgYGBigAEECwoAAJcABgB4nGNgZmBgnMDAysDCQBRQgLPsgYCBQXWx6mJmhf8WDAzMCgwnMBUDAMZmBa8AAAAAAAAAAAAAAHicY2BgYGJgYGAGYhEgyQimWRgUgDQLEAL5qov//4eQt+LA8gwAXc8HJAAAAAAAAAAAAAAAAAAAeJxljTEKwkAQRV9MVEQRtBDLxVJQTGGVSggeYAsrmxSjREIiEfUmFp7CIzqJqyjOsMObP/+zQI8bHlV5dOtZVYO2bi/2GTN0HHx5mspTxy0GLNXpBR1VRqwdN+izdeyz4OA4+PI0le+OW0x4xNas8rwwVnZW9ucsKWORo5VLKtcottVNT1E4DzdSntIiN4offeYyxFgMK3LtQski7Oq550xGQuUR7WOtXkh1Xonq5Dv3SkWEzPVtdCs5qbPQq3Hqv3/2+88TvNI1+AAAeJxjYGLAD4DyjExMVeUAAgcA+wA=") format("woff");
  unicode-range: U+25A3;
  font-display: block;
}
@font-face {
  font-family: "DR Anno Ref Edit";
  src: url("data:font/woff;base64,d09GRgABAAAAAAQ8AAoAAAAACEwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABXAAAADEAAABgioM6ZmNtYXAAAAGsAAAANgAAADyc0mqiZ2x5ZgAAAfAAAAABAAAAAQAAAABoZWFkAAAA9AAAADYAAAA2LNCxzGhoZWEAAAEsAAAAGwAAACQDIgbjaG10eAAAAZAAAAAZAAAA4j4cAABsb2NhAAAB5AAAAAwAAADMAAAAAG1heHAAAAFIAAAAFAAAACAAZgACbmFtZQAAAfQAAADjAAABj/HUNWZwb3N0AAAC2AAAAWEAAANE0RSs+gABAAAAAQAA9DIPEV8PPPUAAwPoAAAAAObdOHYAAAAA5t04dgAAAAAAAAAAAAAAAwACAAAAAAAAeJxjYGRgYFb4b8HAwD6PAQIYGVABDwA5AgIOAHicY2BkYGBIZYABJgY0AAALCABpeJxjYGZPZ5zAwMrAwkAEEGBQgLPtgYCBQXXxw2Rmhf8WDAzMCgwn0JQDFQMAAFoGqQAAAHicY2BgYGBuYWBgXUUYs89jGIIAAL83B1QAAAB4nGNgYGBiYGBgBmIRIMkIplkYNIA0G5BmZGBSXfww+f9/BgYgzfj//604eUawKiAAALOACXYAAHicY2AYPgAAAMwAAQAAAAB4nHWPTWoCQRBG3zijISRINkk2WfQ6oKDZCAMBYbxAC+4Fy6FBemT8W+cSuYun8EqpnmlBF6mC7lf1fVVNA8/8khAi4aU5Q3R40KrllA/eI2c3ni5PfEXu8cq3OpPsUTuGeeQOfXaRUyb8RM5uPF3eOEfu8cmlsGbqfWWsrM1s5fZWysNmWRciWytHJ6e8sMGgepDz0XC8kHrnKm8U77RBnKXA6pNTvGalZBHWes9Y4dg3dcmBDUuCWzS3TfeounAib3ZcN7Tz1+mcEUPGLLRb64edOrxub7v/zw3u3/0DEmhAOAB4nH3Mx1qUQRRF0d5oK2bFnAUjmLrurfoBEzbQmBEVzFl5BN7fz+3cM9iDM1i9sd7/t9nrMcY2ttNnBzsZZxe72cNe9rGfAxzkEBMc5ghHOcZxTnCSU5zmDGc5x3kuMMkUF7nEZa5wlWtMM8N1bnCTW9xmQCFIKo2OWeaY5w53ucd9HrDAQ4YsssQyI1Z4xGOe8JRnPOcFq7xkjVe85g3rbPCWd7znAx/5xGe+8JVvfOcHP/nFbzb7W9GG2d8alUGxYf891Tbb2Vk7Z+ft0C7aJbtsR3blb8vA6hf9ol/0i37RL/pFv+gX/aJf9It+0S/6oR/6oR/6oR/6oR/6oR/6oR/6oR/6oR/6qZ/6qZ/6qZ/6qZ/6qZ/6qZ/6qZ/6qZ/6Vb/qV/2qX/WrftWv+lW/6lf9ql/1q37Vr/pNv+k3/abf9Jt+02/6Tb/pN/2m3/SbftNv+p1+p9/pd/kHAeKdCQAAAA==") format("woff");
  unicode-range: U+25A3, U+E101-E163;
  font-display: block;
}

:root {
  --bg: #0e1015;
  --panel: #161922;
  --panel-2: #1d2230;
  --border: #2a3142;
  --text: #e6e9ef;
  --muted: #8a93a6;
  --accent: #4ea1ff;
  --kill: #4dd17a;
  --assist: #f0c244;
  --death: #ff5d5d;
  --note: #b173ff;
}

* { box-sizing: border-box; }

/* Nothing outside an editable field is selectable (user rule): every surface
   is a click/drag target, shift-click is the ledger's range-select gesture,
   and the custom right-click menus offer nothing for selected text anyway.
   Editable fields (and anything marked .selectable) keep text selection. */
body { user-select: none; -webkit-user-select: none; }
input, textarea, [contenteditable="true"], [contenteditable=""], [contenteditable="plaintext-only"], .selectable, .selectable * { user-select: text; -webkit-user-select: text; }
html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 14px;
  height: 100%;
  overflow: hidden; /* lock the document; internal panels scroll on their own */
}

/* Site-themed scrollbar (WebKit + Firefox). Applies to every scrollable
   container in the app — there's no "default browser scrollbar" anywhere. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 6px;
  border: 2px solid var(--bg); /* inset so thumb looks ~6px wide */
}
*::-webkit-scrollbar-thumb:hover { background: #3a445c; }
*::-webkit-scrollbar-corner { background: transparent; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

button, .btn {
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 14px;
  font-size: 14px;
  cursor: pointer;
  transition: background 0.1s;
}
/* IMPORTANT: use background-COLOR (not shorthand). The shorthand `background:`
   resets background-size/position to initial, which breaks every icon drawn as
   a cover-sized background image (the Game Info portraits, item and rune tiles)
   on hover — the image jumps to natural size, anchored top-left. */
button:hover, .btn:hover { background-color: #252b3d; }
button.primary, .btn.primary { background: var(--accent); border-color: var(--accent); color: #0e1015; font-weight: 600; }
button.primary:hover, .btn.primary:hover { background: #6db4ff; }
button.danger { background: var(--panel-2); border-color: var(--border); color: var(--muted); }
button.danger:hover { background: #252b3d; color: var(--text); }

input, textarea, select {
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  font-size: 14px;
  font-family: inherit;
  width: 100%;
}
input:focus, textarea:focus, select:focus { outline: none; border-color: var(--accent); }

/* The index page's main wrapper. Body has `overflow: hidden` to keep
   in-app panels (review, clip viewer) sized to the viewport, but that also
   prevented the library and clips lists from scrolling when they exceeded
   the viewport. Give the container its own internal scroll so all the
   in-app behavior is preserved while long clip/review lists work. */
.container {
  max-width: 1100px;
  margin: 0 auto;
  padding: 24px;
  /* 54px header + 33px system strip (border-box, incl. its hairline). */
  height: calc(100dvh - 87px);
  overflow-y: auto;
  box-sizing: border-box;
}
.header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--border);
  /* Tighter vertical padding so the header doesn't push the rest of the page
     past the viewport. The review layout below assumes a header ≈ 52px. */
  padding: 8px 24px;
  background: var(--panel);
}
.header h1 { font-size: 18px; margin: 0; font-weight: 600; }

/* Library */
.library-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 14px;
  margin-top: 18px;
}
/* When the grid lives inside the clips-layout sidebar+main structure (as
   it now does for the Reviews tab too) the 18px top margin double-spaces
   it from the header. Drop the margin inside that context so review and
   clip grids feel equally tight. */
.clips-main .library-grid { margin-top: 0; }
.review-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px;
  cursor: pointer;
  transition: border-color 0.1s, background-color 0.1s;
  /* anchors the absolute-positioned select toggle (mirrors clip-card) */
  position: relative;
}
/* No translateY lift on hover: a card at the very bottom of the viewport
   would shift up out from under the cursor, un-hovering itself, which
   re-lowers it back under the cursor — an infinite hover/unhover flicker
   loop. Border + background feedback is enough (and matches clip-card). */
.review-card:hover { border-color: var(--accent); background-color: var(--panel); }
/* When the user has built a multi-select, highlight the cards that are
   part of it. Matches the clip-card selection state. */
.review-card.is-selected { border-color: var(--accent); background: rgba(78,161,255,0.10); }
/* The select-toggle shares its class with .clip-card so it inherits all
   the absolute-positioning / hover-reveal styles. We only need to make
   sure the review-card hover and selected states reveal it. */
.review-card:hover .clip-select-toggle,
.review-card.is-selected .clip-select-toggle { opacity: 1; }
.review-card .card-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
}
.review-card .card-head-text { flex: 1; min-width: 0; }
.champ-icon, .champ-icon-fallback {
  width: 44px;
  height: 44px;
  border-radius: 6px;
  flex: none;
  background: var(--panel-2);
  border: 1px solid var(--border);
}
.champ-icon-fallback { display: block; }
.review-card .title { font-weight: 600; margin-bottom: 4px; overflow: hidden; text-overflow: ellipsis; }
.review-card .meta { color: var(--muted); font-size: 12px; line-height: 1.6; }
.review-card .actions { display: flex; gap: 6px; margin-top: 10px; }
.review-card .refresh { padding: 8px 10px; }
.review-card .badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
}
.badge.win { background: #163a25; color: var(--kill); }
.badge.loss { background: #3a1f24; color: var(--death); }

.empty {
  text-align: center;
  padding: 60px 20px;
  color: var(--muted);
  background: var(--panel);
  border: 1px dashed var(--border);
  border-radius: 8px;
}

/* Form */
.form { max-width: 520px; margin: 0 auto; }
.form .field { margin-bottom: 14px; }
.form label {
  display: block;
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 4px;
  letter-spacing: 0.04em;
}
.form .help { font-size: 12px; color: var(--muted); margin-top: 4px; }
.form .actions { display: flex; gap: 10px; margin-top: 18px; }
.error {
  background: #3a1f24;
  border: 1px solid #5a2a32;
  color: #ff8a8a;
  padding: 10px;
  border-radius: 6px;
  margin-bottom: 12px;
  white-space: pre-wrap;
}

/* Review viewer */
.review-layout {
  display: grid;
  grid-template-columns: 1fr 360px;
  grid-template-rows: 1fr auto;
  gap: 10px;
  padding: 10px 12px 6px;
  /* Subtraction matches actual header height (8+8 padding + ~36 button height
     + 1 border ≈ 53px). Keeping a small slack so anti-aliasing/zoom rounding
     never produces a scrollbar. */
  height: calc(100dvh - 54px);
  min-height: 0;
  box-sizing: border-box;
}
.video-pane {
  background: #000;
  border-radius: 8px;
  overflow: hidden;
  position: relative;
  display: flex;
  flex-direction: column;
  contain: layout paint;
  isolation: isolate;
}
.video-pane:fullscreen { border-radius: 0; }
.video-stage {
  position: relative;
  flex: 1;
  min-height: 0;
}
/* Both videos are absolutely-positioned in the stage so they overlap. We swap
   between them with OPACITY (not display:none) so the inactive one keeps
   decoding in the background. That lets us seek the destination video and
   wait for its `seeked` event BEFORE flipping visibility — no wrong-frame
   flicker on transition. */
.video-stage { position: relative; }
.video-stage video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.video-stage #video { z-index: 0; opacity: 1; transition: opacity 0ms; }
/* Clip viewer: a second <video id="videoNext"> sits invisibly behind the
   primary so the next clip can preload + decode its first frame BEFORE we
   swap visibility. The .using-next class flips opacity instantly. */
.video-stage #videoNext { z-index: 0; opacity: 0; pointer-events: none; transition: opacity 0ms; }
.video-stage.using-next #video    { opacity: 0; pointer-events: none; }
.video-stage.using-next #videoNext { opacity: 1; pointer-events: auto; z-index: 1; }

.video-controls {
  flex: none;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px 10px;
  background: #0a0c11;
  border-top: 1px solid var(--border);
}
.vc-btn {
  background: transparent;
  border: 1px solid transparent;
  color: var(--text);
  border-radius: 4px;
  padding: 4px 10px;
  font-size: 13px;
  font-weight: 600;
  font-family: ui-monospace, Menlo, monospace;
  cursor: pointer;
  min-width: 38px;
  line-height: 1;
}
.vc-btn:hover { background: rgba(255,255,255,0.08); border-color: var(--border); }
.vc-btn.vc-play { font-size: 16px; min-width: 44px; }
.vc-spacer { flex: 1; }
.vc-time {
  color: var(--muted);
  font-size: 12px;
  font-family: ui-monospace, Menlo, monospace;
  font-variant-numeric: tabular-nums;
  margin-right: 8px;
}
.vc-select {
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 4px 6px;
  font-size: 12px;
  font-weight: 600;
  font-family: ui-monospace, Menlo, monospace;
  cursor: pointer;
  width: auto;
  min-width: 0;
  margin-right: 4px;
}
.video-stage { cursor: pointer; }

/* ── Drawing overlay (on the video stage) — absorbs the ruler ────────── */
.draw-layer { position: absolute; inset: 0; z-index: 5; display: none; }
.draw-layer.on { display: block; }
.draw-canvas { position: absolute; inset: 0; width: 100%; height: 100%; cursor: crosshair; touch-action: none; }
/* Ruler/circle live preview: drawn here per frame and committed to the main
   canvas on release, so the drag never blits a full-canvas snapshot back. */
.draw-preview { pointer-events: none; }
.draw-bar {
  position: absolute; left: 50%; top: 10px; transform: translateX(-50%);
  display: flex; align-items: center; gap: 8px; padding: 7px 9px;
  background: rgba(20,21,30,0.94); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: 0 16px 40px -16px rgba(0,0,0,0.8); z-index: 7;
}
.draw-bar .dgrp { display: flex; align-items: center; gap: 4px; }
.draw-bar .dsep { width: 1px; height: 20px; background: var(--border); margin: 0 2px; }
.dtool {
  height: 28px; min-width: 32px; padding: 0 9px; border: 1px solid var(--border);
  border-radius: 6px; background: var(--panel-2); color: var(--muted);
  font-size: 12px; font-weight: 600; cursor: pointer; display: inline-flex; align-items: center; gap: 5px;
}
.dtool:hover { color: var(--text); border-color: var(--muted); }
.dtool.on { color: var(--accent); border-color: var(--accent); background: rgba(78,161,255,0.12); }
.dtool.dsave { background: var(--accent); border-color: var(--accent); color: #0e1015; }
.dsw { width: 19px; height: 19px; border-radius: 5px; border: 1px solid rgba(255,255,255,0.18); cursor: pointer; }
.dsw.on { outline: 2px solid #fff; outline-offset: 1px; }
.draw-readout {
  position: absolute; transform: translate(-50%, -150%);
  font-family: ui-monospace, Menlo, monospace; font-size: 11px;
  color: var(--accent); background: rgba(12,13,19,0.85);
  border: 1px solid var(--accent); border-radius: 5px; padding: 2px 6px; pointer-events: none; z-index: 7;
}

button.tool-active {
  background: rgba(78,161,255,0.12);
  border-color: var(--accent);
  color: var(--accent);
}

/* Note image attachments (drawn annotations) + lightbox. */
.note-attachments { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.attach-chip {
  display: inline-flex; align-items: center; gap: 7px; padding: 4px 7px 4px 4px;
  border: 1px solid var(--accent); background: rgba(78,161,255,0.10);
  border-radius: 7px; cursor: pointer;
}
.attach-chip .attach-thumb { width: 34px; height: 20px; border-radius: 3px; object-fit: cover; border: 1px solid var(--border); }
.attach-chip .attach-label { font-size: 11px; color: var(--accent); font-weight: 600; }
.attach-chip .attach-del { background: none; border: none; color: var(--muted); cursor: pointer; font-size: 12px; padding: 0 2px; }
.attach-chip .attach-del:hover { color: var(--death); }
.lightbox-img { display: block; max-width: 78vw; max-height: 72vh; border-radius: 6px; }

/* ── Theater / fullscreen review mode ──────────────────────────────────── */
.theater { position: fixed; inset: 0; z-index: 200; display: none; flex-direction: column; background: #000; }
.theater.on { display: flex; }
.th-videohost { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.th-videohost video { width: 100%; height: 100%; object-fit: contain; background: #000; }
/* (.th-top / .th-title / .th-sub / .th-spacer removed with the theater's title
   bar — the video fills that space now.) */
.th-btn { background: rgba(255,255,255,0.1); border: 1px solid var(--border); color: var(--text); border-radius: 6px; padding: 6px 12px; cursor: pointer; font-size: 12px; }
.th-btn:hover { background: rgba(255,255,255,0.18); }
.th-controls { position: relative; z-index: 2; margin-top: auto; padding: 16px 22px 22px; background: linear-gradient(to top, rgba(0,0,0,0.72), transparent); }
.th-scrub { position: relative; height: 8px; background: rgba(255,255,255,0.18); border-radius: 4px; cursor: pointer; touch-action: none; }
.th-markers { position: absolute; inset: 0; pointer-events: none; }
.th-mk { position: absolute; top: -2px; width: 3px; height: 12px; border-radius: 1px; transform: translateX(-50%); }
.th-fill { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: var(--accent); border-radius: 4px; }
.th-knob { position: absolute; top: 50%; left: 0; width: 14px; height: 14px; border-radius: 50%; background: var(--accent); transform: translate(-50%, -50%); box-shadow: 0 0 8px rgba(78,161,255,0.7); }
.th-row { display: flex; align-items: center; gap: 12px; margin-top: 14px; color: var(--text); }
.th-icon { background: rgba(255,255,255,0.1); border: 1px solid var(--border); color: var(--text); border-radius: 6px; width: 36px; height: 36px; cursor: pointer; font-size: 14px; display: inline-flex; align-items: center; justify-content: center; }
.th-icon:hover { background: rgba(255,255,255,0.18); }
.th-icon.on { background: var(--accent); color: #0e1015; border-color: var(--accent); }
.th-time { font-family: ui-monospace, monospace; font-size: 13px; color: var(--muted); }
.th-hint { margin-left: auto; font-size: 12px; color: var(--muted); }
.th-hint b { color: var(--text); }
.th-navi { position: absolute; left: 0; right: 0; bottom: 118px; z-index: 3; padding: 12px 22px; background: linear-gradient(to top, rgba(0,0,0,0.88), transparent); }
.th-navi[hidden] { display: none; }
.th-navi-head { display: flex; align-items: center; justify-content: space-between; color: var(--muted); font-size: 12px; margin-bottom: 8px; }
.th-navi-close { background: none; border: 1px solid var(--border); color: var(--muted); border-radius: 5px; padding: 3px 9px; cursor: pointer; font-size: 11px; }
.th-navi-strip { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; }
.th-thumb { flex: none; min-width: 108px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel-2); padding: 9px 11px; cursor: pointer; }
.th-thumb:hover { border-color: var(--muted); }
.th-thumb.on { border-color: var(--accent); background: rgba(78,161,255,0.12); }
.th-thumb .tk { font-size: 9px; letter-spacing: 0.08em; }
.th-thumb .tn { font-size: 12px; font-weight: 600; color: var(--text); margin: 2px 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 140px; }
.th-thumb .tt { font-family: ui-monospace, monospace; font-size: 10px; color: var(--muted); }
.th-cmd { position: absolute; left: 50%; bottom: 128px; transform: translateX(-50%); z-index: 3; display: flex; align-items: center; gap: 10px; width: min(640px, 80vw); background: rgba(20,21,30,0.96); border: 1px solid var(--border); border-radius: 10px; padding: 10px 14px; box-shadow: 0 18px 50px -18px rgba(0,0,0,0.85); }
.th-cmd[hidden] { display: none; }
.th-cmd-at { font-family: ui-monospace, monospace; font-size: 12px; color: var(--accent); white-space: nowrap; }
.th-cmd-input { flex: 1; background: transparent; border: none; outline: none; color: var(--text); font-size: 14px; }
.notes-pane {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.notes-tabs {
  display: flex;
  border-bottom: 1px solid var(--border);
  background: #11141c;
}
.notes-tabs .tab {
  flex: 1;
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  padding: 10px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
}
.notes-tabs .tab:hover { color: var(--text); background: rgba(255,255,255,0.02); }
.notes-tabs .tab.active { color: var(--accent); border-bottom-color: var(--accent); background: var(--panel); }
.notes-tabs .form-toggle {
  flex: none;
  background: transparent;
  border: none;
  border-radius: 0;
  color: var(--muted);
  padding: 0 12px;
  cursor: pointer;
  font-size: 14px;
}
.notes-tabs .form-toggle:hover { color: var(--text); background: rgba(255,255,255,0.04); }

/* ── Notes-view modes (Standard / Quick review / Notebook) ─────────────
   Tab-spacer + mode-select styling now lives in review.css (the design
   port). */
.note-mode-view { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.note-mode-view[hidden] { display: none; }

/* Quick review — one row per death */
.qr-intro {
  margin: 0; padding: 11px 13px; font-size: 12px; line-height: 1.5;
  color: var(--muted); border-bottom: 1px solid var(--border);
  background: rgba(255,93,93,0.05); flex: none;
}
.qr-list { flex: 1; min-height: 0; overflow-y: auto; padding: 10px; display: flex; flex-direction: column; gap: 8px; }
.qr-row {
  display: grid; grid-template-columns: auto 52px 1fr auto; align-items: center; gap: 10px;
  padding: 9px 11px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel-2);
}
.qr-row.done { border-color: var(--accent); background: rgba(78,161,255,0.08); }
.qr-check {
  width: 20px; height: 20px; border-radius: 5px; border: 1.5px solid var(--border);
  display: flex; align-items: center; justify-content: center; color: transparent; font-size: 12px; flex: none;
}
.qr-row.done .qr-check { background: var(--accent); border-color: var(--accent); color: #0e1015; }
.qr-time { font-family: ui-monospace, monospace; font-size: 12px; color: var(--death); cursor: pointer; }
.qr-input { height: 30px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); color: var(--text); font-size: 12.5px; padding: 0 9px; width: 100%; box-sizing: border-box; }
.qr-seek { color: var(--muted); font-size: 13px; padding: 4px; cursor: pointer; }
.qr-seek:hover { color: var(--text); }
.qr-count { padding: 4px 2px; font-size: 11px; }

/* Notebook — chip strip + full-width writing surface */
.nb-strip { display: flex; gap: 6px; padding: 10px 12px; border-bottom: 1px solid var(--border); overflow-x: auto; flex: none; }
.nb-chip {
  flex: none; display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
  padding: 7px 11px; border: 1px solid var(--border); border-radius: 7px; background: var(--panel-2);
  min-width: 96px; cursor: pointer; text-align: left;
}
.nb-chip.on { border-color: var(--accent); background: rgba(78,161,255,0.08); }
.nb-chip .t { font-size: 11px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 150px; display: flex; align-items: center; gap: 5px; }
.nb-chip .t .d { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.nb-chip .r { font-family: ui-monospace, monospace; font-size: 10px; color: var(--muted); }
.nb-chip.nb-add { align-items: center; justify-content: center; min-width: 40px; color: var(--muted); font-size: 18px; }
.nb-editor { flex: 1; min-height: 0; display: flex; flex-direction: column; padding: 16px 18px; overflow-y: auto; }
.nb-titlerow { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.nb-dot { width: 12px; height: 12px; border-radius: 50%; flex: none; }
.nb-title { flex: 1; font-size: 18px; font-weight: 700; border: none; background: none; color: var(--text); outline: none; padding: 0; font-family: inherit; }
.nb-rangerow { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; flex-wrap: wrap; }
.nb-rchip { font-family: ui-monospace, monospace; font-size: 12px; color: var(--text); background: var(--panel-2); border: 1px solid var(--border); border-radius: 6px; padding: 4px 9px; display: inline-flex; align-items: center; gap: 6px; }
.nb-rchip .lab { font-size: 9px; letter-spacing: 0.08em; color: var(--muted); }
.nb-seek { font-size: 12px; padding: 4px 10px; }
.nb-prose { flex: 1; min-height: 200px; resize: none; border: none; background: none; color: var(--text); font-size: 14.5px; line-height: 1.7; outline: none; font-family: inherit; padding: 0; }
.nb-foot { display: flex; align-items: center; padding: 10px 0 0; flex: none; }
.nb-foot .ftxt { font-size: 11px; color: var(--muted); margin-left: auto; }
.notes-tab-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.notes-tab-body[data-tab-body="info"] { overflow-y: auto; }
.notes-tab-body[hidden] { display: none; }
.notes-header {
  padding: 12px;
  border-bottom: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.phase-pill {
  display: inline-block;
  font-size: 10px;
  background: rgba(78, 161, 255, 0.18);
  color: var(--accent);
  border: 1px solid rgba(78, 161, 255, 0.4);
  padding: 1px 6px;
  border-radius: 999px;
  margin-left: 6px;
  vertical-align: 1px;
}
.phase-empty {
  padding: 24px 16px;
  text-align: center;
  color: var(--muted);
  font-size: 13px;
}

.phase-stats {
  display: flex;
  gap: 8px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 4px;
}
.phase-stats .stat { flex: 1; text-align: center; }
.phase-stats .stat-label {
  display: block;
  font-size: 10px;
  color: var(--muted);
  letter-spacing: 0.05em;
}
.phase-stats .stat-value {
  display: block;
  font-size: 16px;
  font-weight: 600;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
.phase-stats .stat-value.pos { color: var(--kill); }
.phase-stats .stat-value.muted { color: var(--muted); }
.phase-stats .stat-rate {
  display: block;
  font-size: 10px;
  color: var(--muted);
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
.notes-list { flex: 1; overflow-y: auto; padding: 8px; }

/* ── Phases workbench (Phases tab) ─────────────────────────────────────
   A scrolling list of per-phase cards. Each shows CS + the player's HP/
   resource for that phase (from the recorded Live Client Data series); the
   active card expands with an auto-saved note + title-color palette. */
.wb-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 10px 12px 8px;
  border-bottom: 1px solid var(--border);
  flex: none;
}
.wb-title { font-weight: 600; font-size: 14px; }
.wb-note { font-size: 11px; line-height: 1.35; }
.wb-note.warn { color: var(--assist); }
.wb-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.wb-divider {
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--muted);
  padding: 8px 2px 2px;
  position: sticky;
  top: -10px;
  background: var(--panel);
  z-index: 1;
}
.wb-divider:first-child { padding-top: 2px; }
.pw-card {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  transition: border-color 0.12s, background 0.12s;
}
.pw-card.now { border-color: var(--accent); }
.pw-card.editing { border-color: var(--accent); background: #1f2536; }
.pw-card.obj .pw-name { color: var(--assist); }
/* Top segment seeks; bottom (note) segment edits — separated by a divider. */
.pw-top-seg { cursor: pointer; border-radius: 5px; }
.pw-top-seg:hover { background: rgba(255,255,255,0.03); }
.pw-sep { height: 1px; background: var(--border); margin: 8px -10px 0; }
.pw-note-seg { padding-top: 8px; cursor: pointer; }
.pw-note-seg.editing { cursor: default; }
.pw-note-seg:not(.editing):hover .pw-note-text,
.pw-note-seg.pw-empty:hover .pw-note-placeholder { color: var(--text); }
.pw-note-text { white-space: pre-wrap; font-size: 12px; color: var(--muted); line-height: 1.45; }
.pw-note-placeholder { font-size: 12px; color: var(--muted); font-style: italic; opacity: 0.65; }
.pw-top { display: flex; align-items: center; gap: 8px; }
.pw-name { font-weight: 600; font-size: 13px; }
.pw-recall {
  font-size: 10px;
  color: var(--note);
  border: 1px solid color-mix(in srgb, var(--note) 50%, transparent);
  border-radius: 4px;
  padding: 0 5px;
  white-space: nowrap;
}
.pw-range {
  margin-left: auto;
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.pw-grid { display: flex; gap: 14px; align-items: center; margin-top: 8px; }
.pw-cs { display: flex; flex-direction: column; min-width: 62px; }
.pw-cs .v { font-size: 18px; font-weight: 700; line-height: 1.1; }
.pw-cs .frac { font-size: 12px; color: var(--muted); font-weight: 600; }
.pw-cs .l { font-size: 10px; color: var(--muted); margin-top: 1px; }
.pw-bars { flex: 1; display: flex; flex-direction: column; gap: 5px; }
.pw-barrow { display: flex; align-items: center; gap: 6px; font-size: 10px; }
.pw-barrow .bl { width: 26px; color: var(--muted); }
.pw-barrow .bt { flex: 1; height: 6px; background: var(--bg); border-radius: 3px; overflow: hidden; }
.pw-barrow .bf { display: block; height: 100%; border-radius: 3px; background: var(--kill); transition: width 0.15s; }
.pw-barrow .bf.res { background: var(--accent); }
.pw-barrow .bv { width: 36px; text-align: right; color: var(--text); font-variant-numeric: tabular-nums; }
.pw-textarea {
  width: 100%;
  min-height: 64px;        /* ~3 lines while editing; JS auto-grows beyond */
  resize: none;
  overflow: hidden;
  box-sizing: border-box;
  font-family: inherit;
  line-height: 1.4;
}
.pw-edit-foot { display: flex; align-items: center; gap: 8px; margin-top: 7px; }

/* (Old color filter bar styling removed — the thin filter/actions bar now
   lives in review.css as part of the design port.) */
.note {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px;
  margin-bottom: 8px;
}
.note .note-title { font-weight: 600; cursor: pointer; }
.note .note-time { font-size: 11px; color: var(--muted); margin-top: 2px; }
.note .note-body { font-size: 13px; color: #c8cfdb; margin-top: 6px; white-space: pre-wrap; }
.note .note-actions { margin-top: 6px; display: flex; gap: 6px; }
.note .note-actions button { padding: 4px 8px; font-size: 12px; }
.note.editing { border-color: var(--accent); }
/* Currently-viewed note (set when the user seeks to it via click or 1/2/3
   hotkeys). The accent-tinted background + left bar make it easy to track
   while flipping between notes. */
.note.active {
  border-color: var(--accent);
  background: rgba(78, 161, 255, 0.10);
  box-shadow: inset 3px 0 0 var(--accent);
}
.note .edit-form { display: flex; flex-direction: column; gap: 6px; }
.note .edit-form input, .note .edit-form textarea { font-size: 13px; padding: 6px 8px; }
.note .edit-form .edit-row { display: flex; gap: 6px; align-items: stretch; }
.note .edit-form .edit-row > input { flex: 1; }

/* Input + "now" button row (used in note creation + edit). */
.input-with-button { display: flex; gap: 4px; align-items: stretch; }
.input-with-button > input { flex: 1; min-width: 0; }
.btn-now {
  flex: none;
  padding: 0 10px;
  font-size: 11px;
  font-weight: 600;
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--accent);
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
}
.btn-now:hover { background: #252b3d; }

.color-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.color-row .subtle { flex: none; }
.palette {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
}
.palette.disabled { opacity: 0.35; pointer-events: none; }
.swatch {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2px solid var(--border);
  padding: 0;
  cursor: pointer;
  flex: none;
  background-clip: padding-box;
}
.swatch:hover { border-color: rgba(255,255,255,0.45); }
.swatch.selected {
  border-color: var(--text);
  box-shadow: 0 0 0 1px var(--bg) inset;
}
.note-color-swatch {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  vertical-align: 1px;
  margin-right: 4px;
}

.clickable {
  cursor: pointer;
  border-bottom: 1px dashed transparent;
  transition: border-color 0.1s;
}
.clickable:hover { border-bottom-color: var(--accent); }
h1.clickable { display: inline-block; }

/* ---- Game Info ---- */
.map-container {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 4px;
  overflow: hidden;
  margin: 0;
}
.map-container img.map-bg {
  width: 100%; height: 100%; display: block; object-fit: cover;
}
/* Pins were sized for the old 200px-cramped map. With the larger map the
   22px circles read as too small relative to the rift drawing — bumped to
   36px (≈ 7-9% of the rendered map width) so the champion portraits are
   recognizable at a glance. */
.map-pin {
  position: absolute;
  width: 36px; height: 36px;
  border-radius: 50%;
  background: var(--panel-2);
  border: 2px solid var(--text);
  transform: translate(-50%, -50%);
  background-size: cover;
  background-position: center;
  box-shadow: 0 1px 2px rgba(0,0,0,0.6);
}
.map-pin.team-blue { border-color: var(--accent); }
.map-pin.team-red { border-color: var(--death); }
.map-pin { z-index: 2; }
/* Dead champions: greyscale icon + dim border so the user can scan the map
   and instantly tell who's available. Driven by real-time CHAMPION_KILL
   events + the death-timer formula, NOT by snapshot intervals. */
.map-pin.is-dead {
  filter: grayscale(1) brightness(0.55);
  border-color: var(--muted);
  opacity: 0.85;
}

/* Jungle path lines drawn into an SVG overlay between the bg image and the
   pins. Dotted, team-colored, ~1.5px wide. The SVG uses preserveAspectRatio
   none so the 0–100 viewBox maps directly to the container's % coords. */
.map-container svg.map-paths {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  z-index: 1;
  overflow: visible;
}
/* Past jungle path: widely-spaced round dots so the user reads it as
   "where they came from" rather than misreading it as a planned route.
   The bright forward arrow handles "where they're going". Full opacity —
   the wide dot spacing alone is enough to communicate "past, not active". */
.map-container svg.map-paths .jungle-path {
  fill: none;
  stroke-width: 1.4;
  stroke-linecap: round;
  /* Effectively dots only: near-zero dash length + round cap renders each
     stroke segment as a small disc, repeated every 3 viewBox units. Tighter
     than 4.5 (the dots became hard to follow as a path) but looser than the
     original 1.5 (which read as a continuous active line). */
  stroke-dasharray: 0.1 3;
  opacity: 0.85;
}
/* Darker, more saturated team colors for the path/arrow ONLY. The default
   --accent / --death are tuned for text + UI accents on a dark panel
   background; on the bright Summoner's Rift map image they read as too
   pale to follow. These richer variants sit much better on the map's
   varied (forest / brush / grass) backdrop. */
.map-container svg.map-paths .jungle-path.team-blue { stroke: #1a52c4; }
.map-container svg.map-paths .jungle-path.team-red { stroke: #c11919; }

/* Forward arrow: a short, solid, bright line + arrowhead pointing toward
   the jungler's NEXT-snapshot position. Suppressed entirely when the
   jungler will recall before the next snapshot. */
.map-container svg.map-paths .jungle-arrow {
  fill: none;
  stroke-width: 1.4;
  stroke-linecap: round;
  opacity: 1;
}
.map-container svg.map-paths .jungle-arrow.team-blue { stroke: #1a52c4; }
.map-container svg.map-paths .jungle-arrow.team-red { stroke: #c11919; }
.map-container svg.map-paths .jungle-arrow-head {
  stroke: none;
  opacity: 1;
}
.map-container svg.map-paths .jungle-arrow-head.team-blue { fill: #1a52c4; }
.map-container svg.map-paths .jungle-arrow-head.team-red { fill: #c11919; }
/* Snapshot stamp + prev/next nav arrows sit on a single row under the map.
   The arrow buttons step to the exact timestamp of the prior or next
   timeline frame so the user can jump between snapshots without scrubbing.
   They're disabled at the timeline ends. */
.map-snapshot-meta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 11px;
  color: var(--muted);
  margin-top: 6px;
}
.map-snapshot-meta .snapshot-link { color: var(--accent); }
.map-snapshot-meta .snap-nav {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--accent);
  padding: 1px 8px;
  border-radius: 3px;
  cursor: pointer;
  font-size: 12px;
  line-height: 1.1;
  font-family: inherit;
}
.map-snapshot-meta .snap-nav:hover:not(:disabled) {
  background: var(--panel-2);
  border-color: var(--accent);
}
.map-snapshot-meta .snap-nav:disabled {
  color: var(--muted);
  opacity: 0.4;
  cursor: not-allowed;
}

/* Phase Notes pane — single auto-saved textbox per phase, with the
   phase name as a read-only title above it. The textarea fills the
   pane vertically so it's the obvious place to type. */
.phase-note-header { gap: 10px; }
.phase-note-title-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.phase-note-title {
  font-weight: 700;
  font-size: 15px;
  color: var(--text);
}
.phase-note-range {
  font-variant-numeric: tabular-nums;
  font-size: 11px;
}
#phaseNoteBody {
  flex: 1;
  min-height: 180px;
  resize: vertical;
}

.timeline-pane {
  grid-column: 1 / -1;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  /* Trimmed top/bottom padding (was 14/18) so the timeline pane doesn't push
     the layout taller than the viewport on shorter screens. */
  padding: 8px 18px 8px;
}
.timeline-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  margin-bottom: 6px;
}
.view-toggle {
  display: flex;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 2px;
}
.view-btn {
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  padding: 4px 12px;
  border-radius: 4px;
  cursor: pointer;
}
.view-btn:hover { color: var(--text); background: rgba(255,255,255,0.04); }
.view-btn.active { background: var(--accent); color: #0e1015; }
.view-btn:disabled { opacity: 0.35; cursor: not-allowed; }
.view-btn:disabled:hover { background: transparent; color: var(--muted); }
.timeline-legend { display: flex; gap: 14px; font-size: 12px; color: var(--muted); }
.legend-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 4px; vertical-align: -1px; }

.timeline-track-wrap { position: relative; }
/* ── Hero timeline: Phases / Your notes / Time lanes ───────────────────
   Each lane is a labelled row (74px sticky label + a track). A full-height
   playhead overlay spans all lanes. (Coach lane omitted — single-user app.) */
.timeline-track {
  position: relative;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}
.gt-row { position: relative; border-bottom: 1px solid var(--border); }
.gt-row:last-child { border-bottom: none; }
.gt-row .rl {
  position: absolute; left: 0; top: 0; bottom: 0; width: 74px;
  border-right: 1px solid var(--border);
  display: flex; align-items: center; padding-left: 11px;
  font-size: 9px; letter-spacing: 0.09em;
  color: #737d91; background: var(--panel); z-index: 3;
}
.gt-track { position: absolute; left: 74px; right: 12px; top: 0; bottom: 0; cursor: pointer; }
/* Taller timeline overall; Phases lane kept compact so Your Notes (the focus)
   gets the most room. Time row stays short. */
.row-phase { height: 30px; }
.row-note  { height: 72px; }
.row-time  { height: 32px; }

/* Phases lane */
.gt-phase {
  position: absolute; top: 0; bottom: 0; border-radius: 3px;
  font-size: 10px; font-weight: 600; display: flex; align-items: center;
  justify-content: center; color: var(--muted); overflow: hidden;
  white-space: nowrap; cursor: pointer; user-select: none;
}
.gt-phase:hover { filter: brightness(1.35); }
.gt-phase.wave-0 { background: rgba(78,161,255,0.10); border: 1px solid rgba(78,161,255,0.20); }
.gt-phase.wave-1 { background: rgba(78,161,255,0.19); border: 1px solid rgba(78,161,255,0.30); }
.gt-phase.buy { background: rgba(255,255,255,0.05); border: 1px dashed #3a4252; }
.gt-phase.obj { background: rgba(240,194,68,0.10); border: 1px solid rgba(240,194,68,0.28); color: var(--assist); border-radius: 4px; }
.gt-phase.recall { box-shadow: inset 0 -3px 0 var(--accent); }
.gt-phase.sel { outline: 1.5px solid var(--accent); outline-offset: -1px; background: rgba(78,161,255,0.12); color: var(--text); z-index: 2; }
.gt-phase.sel.dim { outline-color: rgba(78,161,255,0.4); }
.gt-phase.has-note::after { content: ""; position: absolute; top: 2px; right: 2px; width: 4px; height: 4px; border-radius: 50%; background: var(--note); }

/* Your-notes lane: SVG paths now (the tail rail) — the rules live in
   review.css; this stub only keeps the old box styles from bleeding in. */
.gt-bar { cursor: pointer; }

/* Time lane: minute ticks (bottom) + full-height death spans + K/A arrows */
.gt-rtick { position: absolute; bottom: 2px; font-size: 9px; color: #737d91; transform: translateX(-50%); }
.gt-rtick::before { content: ""; position: absolute; left: 50%; top: -4px; width: 1px; height: 3px; background: #3a4252; }
.gt-dead {
  position: absolute; top: 0; bottom: 0; min-width: 4px;
  background: rgba(255,93,93,0.18);
  border-left: 1px solid rgba(255,93,93,0.6);
  border-right: 1px solid rgba(255,93,93,0.6);
  cursor: pointer;
}
.gt-kda { position: absolute; transform: translateX(-50%); cursor: pointer; }
.gt-kda.kill { bottom: 1px; width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 7px solid var(--kill); }
.gt-kda.assist { bottom: 1px; width: 0; height: 0; border-left: 3.5px solid transparent; border-right: 3.5px solid transparent; border-top: 6px solid var(--assist); opacity: 0.82; }
.gt-kda:hover { filter: brightness(1.3); }

/* Playhead overlay spanning all lanes */
.gt-overlay { position: absolute; left: 74px; right: 12px; top: 0; bottom: 0; pointer-events: none; z-index: 2; }
.gt-playhead { position: absolute; top: 0; bottom: 0; left: 0; width: 2px; background: var(--accent); box-shadow: 0 0 6px rgba(78,161,255,0.7); will-change: transform; }
.gt-playhead::after { content: ""; position: absolute; top: -1px; left: -4px; width: 10px; height: 10px; border-radius: 50%; background: var(--accent); }

.tl-tooltip {
  position: absolute;
  background: #0a0c11;
  border: 1px solid var(--border);
  padding: 6px 10px;
  border-radius: 4px;
  font-size: 12px;
  pointer-events: none;
  white-space: nowrap;
  transform: translate(-50%, -100%);
  margin-top: -10px;
  z-index: 10;
  display: none;
}
/* Flipped when the cursor is too near the top of the strip to fit above it. */
.tl-tooltip.below { transform: translate(-50%, 0); margin-top: 10px; }

.spinner {
  display: inline-block;
  width: 14px; height: 14px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
  vertical-align: -3px;
  margin-right: 6px;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Loading wheels (design handoff 25) ─────────────────────────────────
   Two on-brand, indigo-only, indeterminate spinners for panels that fetch
   before they render. #1 Track arc for lighter loads, #2 Conic sweep for
   heavy ones (rendering). Indigo hex fallbacks are baked in because this
   base sheet has no --brand/--indigo-* — only ledger.css / review.css add
   the indigo palette, and those override --accent to indigo too. */

/* #1 Track arc — hairline ring, indigo head arc. The canonical spinner. */
.sp-arc {
  width: 46px; height: 46px; border-radius: 50%;
  border: 3px solid var(--border);
  border-top-color: var(--brand, #4444d4);
  border-right-color: var(--indigo-500, #5e5ee2);
}

/* #2 Conic sweep — a comet tail masked into a thin ring. For heavy loads. */
.sp-conic {
  width: 48px; height: 48px; border-radius: 50%;
  background: conic-gradient(from 0deg,
    transparent 8%,
    var(--indigo-700, #3636b0) 40%,
    var(--accent, #8080ea) 92%,
    var(--indigo-200, #c7c7f5) 100%);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3.5px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3.5px));
}

/* A panel's loading state: the wheel over a mono status line, centred —
   the design's window `.body` + `.status`, minus the demo's mock chrome. */
.load-block {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 16px; padding: 34px 20px; min-height: 120px;
}
.load-block .load-status {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 12px; letter-spacing: .02em; color: var(--text-muted, var(--muted));
}
.load-block .load-status b { color: var(--text); font-weight: 400; }

@media (prefers-reduced-motion: no-preference) {
  .sp-arc   { animation: spin .8s linear infinite; }
  .sp-conic { animation: spin .9s linear infinite; }
}

.row { display: flex; gap: 8px; }
.row > * { flex: 1; }
.toolbar { display: flex; gap: 8px; align-items: center; }
.subtle { color: var(--muted); font-size: 12px; }

/* ---- Library tabs + clip library ---- */
/* The library header uses an explicit 3-column grid so the tabs sit dead
   center regardless of whether the "+ New Review" button is visible. With
   plain flex `space-between` the tabs slide when the button is hidden. */
.header.lib-header {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 14px;
}
.header.lib-header > h1 { justify-self: start; }
.header.lib-header > .lib-tabs { justify-self: center; }
.header.lib-header > .lib-header-actions { justify-self: end; }
/* Right-side action group — keeps recording pill + settings cog + New
   Review on a single line, all adjacent. */
.lib-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.lib-tabs {
  display: flex;
  gap: 4px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 4px;
}
.lib-tab {
  background: transparent;
  border: none;
  color: var(--muted);
  padding: 6px 14px;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.lib-tab:hover { background-color: rgba(255,255,255,0.04); color: var(--text); }
.lib-tab.active { background: var(--panel-2); color: var(--text); }
.lib-pane[hidden] { display: none; }

.clips-layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 16px;
  margin-top: 16px;
}
.clips-sidebar {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px;
  height: fit-content;
  position: sticky;
  top: 16px;
}
.sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}
.sidebar-title {
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--muted);
  font-weight: 700;
}
.btn-tiny {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  padding: 2px 8px;
  font-size: 11px;
  cursor: pointer;
}
.btn-tiny:hover { background-color: #252b3d; }
.btn-tiny.danger { color: var(--muted); }
.btn-tiny.danger:hover { color: var(--death); }

.folder-list { display: flex; flex-direction: column; gap: 2px; }
.folder-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  border-radius: 5px;
  cursor: pointer;
  font-size: 13px;
}
.folder-item:hover { background: rgba(255,255,255,0.04); }
.folder-item.active { background: var(--panel-2); color: var(--text); border: 1px solid var(--accent); padding: 5px 7px; }
.folder-item .folder-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.folder-item .folder-count {
  font-size: 11px;
  color: var(--muted);
  background: rgba(255,255,255,0.06);
  padding: 1px 6px;
  border-radius: 8px;
  flex: none;
}
.folder-item .folder-rename, .folder-item .folder-delete { padding: 1px 5px; font-size: 10px; }

.clips-main {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px;
}
.clips-main-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}
.clips-main-title { margin: 0; font-size: 16px; }

.clips-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 12px;
}
.clip-card {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  cursor: pointer;
  transition: border-color 0.1s, background-color 0.1s;
  position: relative; /* anchors the absolute-positioned select toggle */
}
.clip-card:hover { border-color: rgba(78, 161, 255, 0.4); }
.clip-card.is-pending { cursor: default; opacity: 0.75; }
.clip-card.is-pending:hover { border-color: var(--border); }
.clip-card.is-selected { border-color: var(--accent); background: rgba(78,161,255,0.10); }
.clip-card .actions { display: flex; gap: 6px; }
.clip-card .actions button { padding: 5px 10px; font-size: 12px; }
.clip-card .actions button.primary[disabled] { opacity: 0.5; cursor: not-allowed; }

/* Small square in the top-right of each card. Hidden until hover (or when the
   card is part of an active selection) so it doesn't add visual clutter to
   every grid cell. */
.clip-select-toggle {
  position: absolute;
  top: 8px; right: 8px;
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  font-size: 13px; line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.1s, border-color 0.1s, background-color 0.1s;
  padding: 0;
}
.clip-card:hover .clip-select-toggle,
.clip-card.is-selected .clip-select-toggle,
.clip-select-toggle:focus,
.clip-select-toggle.on { opacity: 1; }
.clip-select-toggle.on {
  background: var(--accent);
  border-color: var(--accent);
  color: #0e1015;
  font-weight: 700;
}

.clips-selection-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  margin-bottom: 8px;
  background: rgba(78, 161, 255, 0.10);
  border: 1px solid var(--accent);
  border-radius: 6px;
}
/* The selection bar is always in the DOM (so selection toggles can show /
   hide it in place without rebuilding the grid). A class selector's
   `display:flex` beats the UA `[hidden]` rule, so make the hidden state
   explicit or `bar.hidden = true` wouldn't actually hide it. */
.clips-selection-bar[hidden] { display: none; }

/* Stranded-recordings notice: recordings whose auto-review build gave up
   (no match ID / retries exhausted). One row per recording with a
   prefilled "Create manually" link + Dismiss. */
#pendingNotices { margin: 0 0 12px; display: flex; flex-direction: column; gap: 6px; }
.pending-notice {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: rgba(240, 194, 68, 0.10);
  border: 1px solid rgba(240, 194, 68, 0.45);
  border-radius: 6px;
  font-size: 13px;
}
.pending-notice-text { flex: 1; }
.pending-notice a.btn-tiny { text-decoration: none; }
.clips-selection-bar .selection-count { font-weight: 600; color: var(--accent); }

.badge.rendering { background: rgba(240, 194, 68, 0.15); color: var(--assist); border: 1px solid rgba(240,194,68,0.4); }

.card-description {
  font-size: 12px;
  color: #c8cfdb;
  background: rgba(255,255,255,0.03);
  border-left: 2px solid var(--accent);
  padding: 6px 8px;
  border-radius: 0 4px 4px 0;
  /* Hard-clamp to a single line so card heights stay uniform regardless of
     description length. The full text is still available via the tooltip. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* The auto-generated matchup ("Ryze vs Diana Mid") is visually quieter than a
   user-authored description — muted accent + lighter tint, so the user can
   tell at a glance which cards still need their own description. */
.card-description.is-fallback {
  color: var(--muted);
  background: transparent;
  border-left-color: var(--border);
  font-style: italic;
}

/* ---- Header title block (review + clip) ---- */
.title-block { display: flex; flex-direction: column; gap: 2px; }
.review-description {
  font-size: 12px;
  color: var(--muted);
  max-width: 540px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---- Clip viewer layout ----
   Two columns: a wide video pane on the left, and a narrower right column
   that stacks the clip-note editor on top of the sibling library. Stacking
   them gives the video more horizontal room than the previous 3-column
   layout — neither the note nor the library needs much vertical space. */
.clip-layout {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(280px, 1.4fr);
  grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-areas:
    "video notes"
    "video library";
  gap: 12px;
  padding: 12px;
  height: calc(100vh - 70px);
}
.clip-layout .video-pane    { grid-area: video; }
.clip-layout .notes-pane    { grid-area: notes; }
.clip-layout .library-pane  { grid-area: library; }
.clip-layout .video-pane,
.clip-layout .notes-pane,
.clip-layout .library-pane {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-height: 0; /* allow internal scroll panels to shrink within the grid row */
}
.clip-notes-pane { padding: 12px; gap: 10px; }
.clip-notes-header { display: flex; justify-content: space-between; align-items: center; }
.clip-note-form { display: flex; flex-direction: column; gap: 8px; flex: 1; }
.clip-note-form textarea { flex: 1; resize: none; }
.clip-note-source { font-size: 11px; line-height: 1.4; }

.library-pane { padding: 12px; }
.library-pane-header {
  /* Title + count cluster on the left with a clean separator gap; Create
     Reel button pinned to the right (margin-left:auto on the button itself).
     `space-between` was causing the count to drift away from the title when
     the title got long — the gap was unbounded and visually awkward. */
  display: flex; align-items: baseline;
  gap: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 8px;
}
.library-pane-header #libraryClipsCount::before {
  content: '·';
  margin-right: 8px;
  color: var(--border);
}
.lib-pane-title {
  font-weight: 600; font-size: 13px;
  /* The folder name can be quite long (Save All defaults to "<Review> —
     saved <timestamp>"). Clamp to a single line with ellipsis so the count
     and Create Reel button stay visible. */
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.library-pane-header #libraryClipsCount { flex: none; }
/* The Create Reel button sits in the library pane header (top-right) — small
   accent pill, so it doesn't compete with the folder title or clip count. */
.create-reel-btn { margin-left: auto; padding: 4px 10px; font-size: 12px; }
.create-reel-btn:hover { background-color: #6db4ff !important; }

/* Reel render progress modal */
.reel-progress { display: flex; flex-direction: column; gap: 10px; }
.reel-progress-text { font-size: 13px; color: var(--text); }
.reel-progress-bar {
  height: 8px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  overflow: hidden;
}
.reel-progress-fill {
  height: 100%;
  background: var(--accent);
  transition: width 0.3s ease;
}

/* Radio buttons in the reel create modal stack vertically — the default
   .modal-field is flex-column so each .radio-row is its own line. */
.modal-field.reel-radio-field { gap: 6px; }
.modal-field .radio-row {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px; color: var(--text);
  cursor: pointer;
  padding: 4px 6px;
  border-radius: 4px;
}
.modal-field .radio-row:hover { background: rgba(255,255,255,0.03); }
.modal-field .radio-row input[type="radio"] { width: auto; margin: 0; cursor: pointer; }
.folder-clips-list { display: flex; flex-direction: column; gap: 4px; overflow-y: auto; flex: 1; }
.fc-item {
  display: grid;
  grid-template-columns: 32px 1fr;
  gap: 8px;
  padding: 6px;
  border-radius: 6px;
  background: var(--panel-2);
  border: 1px solid transparent;
  cursor: pointer;
  align-items: center;
}
.fc-item:hover { border-color: rgba(78,161,255,0.35); }
.fc-item.active { border-color: var(--accent); background: rgba(78,161,255,0.08); }
.fc-item.pending { opacity: 0.6; cursor: default; }
.fc-icon {
  width: 32px; height: 32px;
  border-radius: 4px;
  background: var(--panel) center / cover no-repeat;
  border: 1px solid var(--border);
}
.fc-text { min-width: 0; }
.fc-title { font-weight: 600; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fc-meta { font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---- Modal ---- */
.modal-root {
  position: fixed;
  inset: 0;
  z-index: 1000;
}
.modal-root[hidden] { display: none; }
.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,0.55);
  backdrop-filter: blur(2px);
}
.modal-card {
  position: relative;
  max-width: 460px;
  margin: 80px auto;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 20px 50px rgba(0,0,0,0.5);
  padding: 0;
  z-index: 1;
}
.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
}
.modal-header h3 { margin: 0; font-size: 15px; }
/* The face is a 14px svg now (it was a 22px "×" that sized the button); the
   box stays the 26px target it had, with the glyph centred in it. */
.modal-close {
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
}
.modal-close:hover { color: var(--text); background-color: rgba(255,255,255,0.04); }
.modal-body { padding: 16px; display: flex; flex-direction: column; gap: 12px; }
.modal-field { display: flex; flex-direction: column; gap: 4px; }
.modal-field > span { font-size: 11px; color: var(--muted); letter-spacing: 0.05em; font-weight: 600; }
/* The browser default lets the user drag textareas in BOTH directions; for
   modal fields that's bad because dragging horizontally can push the
   textarea wider than the modal card. Constrain to vertical resize only. */
.modal-field textarea { resize: vertical; max-width: 100%; }
.modal-field .modal-count { align-self: flex-end; font-family: var(--font-mono, ui-monospace, monospace); font-size: 10px; color: var(--muted); text-transform: none; letter-spacing: 0; }
.modal-field .modal-count.over { color: var(--red, #e0556a); }
.modal-actions {
  display: flex; justify-content: flex-end; gap: 8px;
  padding: 12px 16px;
  border-top: 1px solid var(--border);
}

/* ---- Toast system: the ledger stack + milestones (Toast System design) ----
   One floating panel bottom-right; hairline-joined rows; state on the left
   edge; no timestamps, no header. Milestones are the one exception: their
   own window, top-center. Every display rule that pairs with [hidden]
   stays scoped; radii pinned where the squared reset would eat them. */
.drt-corner {
  position: fixed; right: 8px; bottom: 8px; z-index: 320;
  display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
}
.drt-stack {
  width: 346px;
  display: flex; flex-direction: column; background: var(--surface);
  border: 1px solid var(--border); box-shadow: var(--shadow-toast, 0 12px 32px -12px rgba(0, 0, 0, .7));
}
.drt-row { overflow: hidden; max-height: 60px; transition: opacity .22s cubic-bezier(.4, 0, .2, 1), max-height .22s cubic-bezier(.4, 0, .2, 1); }
.drt-row + .drt-row { border-top: 1px solid var(--border); }
.drt-row.drt-entering { animation: drt-grow .22s cubic-bezier(.4, 0, .2, 1); }
.drt-row.drt-leaving { opacity: 0; max-height: 0; border-top-color: transparent; }
.drt-line { display: flex; align-items: center; gap: 10px; height: 32px; padding: 0 11px; box-shadow: inset 3px 0 0 var(--drt-edge, var(--border-strong)); }
.drt-line .drt-text { font-size: 12px; color: var(--text); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drt-meta { font-family: var(--font-mono); font-size: 10px; letter-spacing: .04em; white-space: nowrap; color: var(--text-faint, #565b73); }
.drt-meta.act { background: transparent; border: none; padding: 0; cursor: pointer; color: var(--accent); text-decoration: underline; }
.drt-meta.act:hover { color: var(--indigo-300, #a5b4fc); }
.drt-artifact { display: flex; align-items: center; gap: 10px; padding: 8px 11px; box-shadow: inset 3px 0 0 var(--drt-edge, var(--green)); }
.drt-portrait { display: block; width: 30px; height: 30px; flex: none; border: 1px solid var(--border); background-color: var(--surface-raised); background-size: cover; background-position: center; }
.drt-art-col { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.drt-art-title { font-size: 12px; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drt-art-meta { font-family: var(--font-mono); font-size: 10px; letter-spacing: .04em; color: var(--text-faint, #565b73); white-space: nowrap; }

/* Milestones: top-center under the header, never in the stack. */
.drt-ms {
  position: fixed; top: 81px; left: 50%; transform: translateX(-50%); z-index: 330;
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: var(--shadow-toast, 0 12px 32px -12px rgba(0, 0, 0, .7));
}
.drt-ms-enter { animation: drt-enter .18s cubic-bezier(.4, 0, .2, 1) both; }
.drt-ms-goal { width: 296px; }
.drt-ms-line { display: flex; align-items: center; gap: 9px; height: 32px; padding: 0 11px; }
.drt-ms-line .t { font-size: 12px; color: var(--text); white-space: nowrap; }
.drt-ms-line .m { font-family: var(--font-mono); font-size: 10px; letter-spacing: .04em; color: var(--text-faint, #565b73); margin-left: auto; white-space: nowrap; }
.drt-ms-foot.ok2 { height: 2px; background: var(--green, #3ddc97); }
.drt-ms-cleared { width: 320px; border-color: var(--green, #3ddc97); }
.drt-ms-big { display: flex; align-items: center; gap: 11px; padding: 11px 12px; }
.drt-ms-check {
  display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; flex: none;
  background: var(--green-dim, rgba(61, 220, 151, .12)); border: 1px solid var(--green, #3ddc97);
  border-radius: 50% !important; animation: drt-pop .42s cubic-bezier(.4, 0, .2, 1) both;
}
.drt-ms-big .col { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.drt-ms-big .t { font-size: 13px; font-weight: 600; color: var(--text); }
.drt-ms-big .m { font-family: var(--font-mono); font-size: 10px; letter-spacing: .04em; color: var(--text-faint, #565b73); }
.drt-ms-bar { position: relative; height: 3px; overflow: hidden; background: var(--green-dim, rgba(61, 220, 151, .12)); }
.drt-ms-bar i { display: block; height: 3px; width: 100%; background: var(--green, #3ddc97); }
.drt-ms-bar b {
  position: absolute; top: 0; left: 0; height: 3px; width: 64px;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .6), rgba(255, 255, 255, 0));
  animation: drt-sweep 3.4s cubic-bezier(.4, 0, .2, 1) infinite;
}
/* Honeyfruit: docks raised under a goal, or floats alone, small. The sprite
   is the only colour in its row — no gold, no motion, no rounded corners. */
.drt-honey-dock { display: flex; align-items: center; gap: 8px; height: 26px; padding: 0 11px; border-top: 1px solid var(--border); background: var(--surface-raised); }
.drt-honey-alone { display: inline-flex; align-items: center; gap: 8px; height: 28px; padding: 0 11px; }
.drt-honey-dock .t, .drt-honey-alone .t { font-size: 11px; color: var(--text-muted); white-space: nowrap; }
.drt-honey-dock .m { font-family: var(--font-mono); font-size: 10px; letter-spacing: .04em; color: var(--text-faint, #565b73); margin-left: auto; }
.drt-honey-alone .m { font-family: var(--font-mono); font-size: 10px; letter-spacing: .04em; color: var(--text-faint, #565b73); padding-left: 6px; }
.drt-honey-ic { display: block; width: 20px; height: 20px; flex: none; }

/* Update toast: the one bottom-right window that never expires — docked above
   the stack in the corner column, sticky, two states (available/downloading)
   swapped in place with no re-entrance. The only toast with a primary button,
   because it is the only one asking permission. */
.drt-upd {
  position: relative; width: 346px;
  display: flex; flex-direction: column; gap: 9px; padding: 11px 12px;
  background: var(--surface); border: 1px solid var(--accent-border, rgba(96, 96, 226, .45));
  box-shadow: var(--shadow-toast, 0 12px 32px -12px rgba(0, 0, 0, .7));
}
.drt-upd.drt-upd-entering { animation: drt-upd-enter .18s cubic-bezier(.4, 0, .2, 1) both; }
.drt-upd.downloading { gap: 8px; padding-bottom: 13px; }
.drt-upd-head { display: flex; align-items: flex-start; gap: 10px; }
.drt-upd-head svg { flex: none; margin-top: 1px; }
.drt-upd-col { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.drt-upd-title { font-size: 12px; font-weight: 600; color: var(--text); }
.drt-upd-sub { font-family: var(--font-mono); font-size: 10px; letter-spacing: .04em; color: var(--text-faint, #565b73); }
.drt-upd-x {
  flex: none; width: 20px; height: 20px; display: flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid transparent; border-radius: 0; padding: 0;
  color: var(--text-faint, #565b73); cursor: pointer;
}
.drt-upd-x:hover { color: var(--text); border-color: var(--border); background-color: transparent; }
.drt-upd-foot { display: flex; align-items: center; gap: 6px; padding-top: 9px; border-top: 1px solid var(--border); }
.drt-upd-foot .grp { display: flex; gap: 6px; margin-left: auto; }
.drt-upd-btn {
  display: inline-flex; align-items: center; justify-content: center;
  height: 26px; padding: 0 9px; border-radius: 0;
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; line-height: 1; white-space: nowrap;
  background-color: var(--surface-raised); color: var(--text); border: 1px solid var(--border);
  cursor: pointer;
}
.drt-upd-btn.ghost { background-color: transparent; border-color: transparent; }
.drt-upd-btn.ghost:hover { background-color: var(--surface-hover, #252839); border-color: var(--border); }
.drt-upd-btn.primary { background-color: var(--brand, #4444d4); border-color: var(--brand, #4444d4); color: #fff; }
.drt-upd-btn.primary:hover { background-color: var(--brand-hover, #5e5ee2); border-color: var(--brand-hover, #5e5ee2); }
.drt-upd-btn:disabled { opacity: .5; cursor: default; }
/* downloading state */
.drt-upd-row { display: flex; align-items: center; gap: 10px; }
.drt-upd-row svg { flex: none; }
.drt-upd-row .drt-upd-title { flex: 1; min-width: 0; }
.drt-upd-pct { font-family: var(--font-mono); font-size: 12px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
.drt-upd-meta { display: flex; align-items: center; gap: 8px; }
.drt-upd-meta .drt-upd-sub { font-variant-numeric: tabular-nums; }
.drt-upd-cancel {
  margin-left: auto; font-family: var(--font-mono); font-size: 10px; letter-spacing: .04em;
  color: var(--text-muted, #8a93a6); background: transparent; border: none; padding: 0;
  cursor: pointer; text-decoration: underline;
}
.drt-upd-cancel:hover { color: var(--red, #ff5d5d); background-color: transparent; }
.drt-upd-track { position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: var(--surface-raised); }
.drt-upd-bar { height: 2px; width: 0%; background: var(--accent); transition: width .3s linear; }

@keyframes drt-upd-enter { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes drt-enter { from { opacity: 0; transform: translate(-50%, 6px); } to { opacity: 1; transform: translate(-50%, 0); } }
@keyframes drt-grow { from { opacity: 0; max-height: 0; } to { opacity: 1; max-height: 60px; } }
@keyframes drt-pop { 0% { transform: scale(.5); opacity: 0; } 55% { transform: scale(1.14); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
@keyframes drt-sweep { 0% { transform: translateX(-70px); } 55%, 100% { transform: translateX(348px); } }
@media (prefers-reduced-motion: reduce) {
  .drt-row.drt-entering, .drt-ms-enter, .drt-ms-check, .drt-ms-bar b, .drt-upd.drt-upd-entering { animation: none !important; }
}

/* ---- Settings modal ---- */
/* Lives in the existing #modalRoot. We don't reuse review.js's openModal
   because library.js isn't expected to share modal state with it — the
   settings card stays standalone. */
.modal-root { position: fixed; inset: 0; z-index: 100; background: rgba(0,0,0,0.55); display: flex; align-items: center; justify-content: center; }
.modal-root[hidden] { display: none; }
.modal-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  width: min(560px, 92vw);
  max-height: 86vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: 0 20px 60px rgba(0,0,0,0.6);
}
.modal-card .modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px; border-bottom: 1px solid var(--border);
}
.modal-card .modal-header h2 { font-size: 16px; margin: 0; font-weight: 600; }
.modal-card .modal-close {
  background: none; border: none; color: var(--muted); font-size: 24px;
  cursor: pointer; padding: 0; line-height: 1;
  width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center;
}
.modal-card .modal-close:hover { color: var(--text); background: transparent; }
.modal-card .modal-body { padding: 14px 18px; overflow-y: auto; }

/* ---- Modal float in / out ----------------------------------------------
   A slight rise + fade on open, the reverse on close — modelled on the clip
   viewer's nb-pop. `.is-closing` is added to the modal container by the modal
   managers (floatOutModal in modal.js) just before they wipe the DOM; the
   card's animationend is what tells them the exit has finished. Covers every
   #modalRoot surface: generic modals, settings, login, coaching, storage. */
@keyframes modalFloatIn  { from { opacity: 0; transform: translateY(8px); } }
@keyframes modalFloatOut { to   { opacity: 0; transform: translateY(8px); } }
@keyframes modalScrimIn  { from { opacity: 0; } }
@keyframes modalScrimOut { to   { opacity: 0; } }
@keyframes modalRootBgOut { to  { background-color: transparent; } }

.modal-card { animation: modalFloatIn .18s cubic-bezier(.16, .84, .44, 1) both; }
.modal-backdrop { animation: modalScrimIn .18s ease-out both; }

/* Exit: fade each piece (root background, scrim div, card) — NEVER the root's
   own opacity. The root is the ancestor of .modal-backdrop's backdrop-filter;
   starting an opacity animation there flips the whole subtree into an isolated
   compositor group whose first frame renders differently from the open state
   (the blur re-scopes + the scrims re-blend) — the one-instant dim spike on
   close. Per-piece fades all start at their current values, so frame zero of
   the exit is identical to the open state by construction. */
.modal-root.is-closing { animation: modalRootBgOut .16s ease-in forwards; }
.modal-root.is-closing .modal-backdrop { animation: modalScrimOut .16s ease-in forwards; }
.modal-root.is-closing .modal-card { animation: modalFloatOut .16s ease-in forwards; }

@media (prefers-reduced-motion: reduce) {
  .modal-card, .modal-backdrop,
  .modal-root.is-closing, .modal-root.is-closing .modal-backdrop,
  .modal-root.is-closing .modal-card { animation: none; }
}

.settings-modal .settings-legacy-note {
  background: rgba(240, 194, 68, 0.10);
  border: 1px solid #6a4a14;
  color: #f0c244;
  padding: 8px 12px;
  border-radius: 6px;
  font-size: 12px;
  margin-bottom: 14px;
}
.settings-modal .settings-section {
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}
.settings-modal .settings-section:last-of-type { border-bottom: none; }
.settings-modal .settings-section h3 { font-size: 13px; font-weight: 600; margin: 0 0 8px; color: var(--muted); letter-spacing: 0.04em; }
.settings-modal .settings-help { font-size: 12px; color: var(--muted); margin: 0 0 8px; line-height: 1.45; }
/* Warning-coloured help text — used by the direct-Riot-key section to make
   "for testing only" land harder than ordinary grey help text. */
.settings-modal .settings-help.settings-warn {
  color: #f0c244;
  background: rgba(240, 194, 68, 0.08);
  padding: 8px 10px;
  border-left: 2px solid #f0c244;
  border-radius: 0 4px 4px 0;
}
.settings-modal .settings-help code {
  background: var(--panel-2);
  padding: 0 4px;
  border-radius: 3px;
  font-size: 11px;
  color: var(--text);
}
.settings-modal .settings-row {
  display: flex; align-items: center; gap: 12px; margin-bottom: 8px;
}
.settings-modal .settings-row-block { flex-direction: column; align-items: flex-start; gap: 6px; }
.settings-modal .settings-label { color: var(--muted); font-size: 12px; min-width: 140px; }
.settings-modal .settings-row input[type="text"],
.settings-modal .settings-row input[type="password"],
.settings-modal .settings-row select { flex: 1; }
/* Checkboxes (auto-record toggle) must NOT honor the global
   `input { width: 100% }` — they'd otherwise stretch and push the label
   text far to the right of the actual click target. */
.settings-modal .settings-row input[type="checkbox"] { width: auto; flex: 0 0 auto; }
.settings-modal .queue-toggles {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
  width: 100%;
}
.settings-modal .queue-toggle {
  display: flex; align-items: center; gap: 6px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  padding: 6px 10px;
  border-radius: 6px;
  font-size: 12px;
  cursor: pointer;
}
.settings-modal .queue-toggle input { width: auto; }
.settings-modal .settings-saved {
  margin-top: 10px;
  color: var(--kill);
  font-size: 12px;
  text-align: right;
}
/* "testing" / "experimental" pill next to a setting label, marking it
   as a temporary affordance rather than something stable to depend on. */
/* Inline hint listing the placeholder tokens under the args template. */
.settings-modal .settings-args-hint {
  font-size: 11px;
  color: var(--muted);
  margin-top: 4px;
  line-height: 1.5;
}
.settings-modal .settings-args-hint code {
  background: var(--panel-2);
  padding: 1px 4px;
  border-radius: 3px;
  font-size: 10px;
  color: var(--text);
}

/* Args-templates examples under the recorder section. <details>/<summary>
   so it's collapsed by default — users who already know what they're
   doing don't need the 30 lines of OBS-specific guidance shoved at them. */
.settings-modal .settings-args-examples {
  margin: 6px 0 10px;
  font-size: 12px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 6px 10px;
}
.settings-modal .settings-args-examples summary {
  cursor: pointer;
  color: var(--accent);
  user-select: none;
  font-weight: 500;
}
.settings-modal .settings-args-examples dl {
  margin: 8px 0 4px;
}
.settings-modal .settings-args-examples dt {
  margin-top: 8px;
  color: var(--text);
  font-weight: 600;
}
.settings-modal .settings-args-examples dt:first-child { margin-top: 0; }
.settings-modal .settings-args-examples dd {
  margin: 4px 0 0;
  color: var(--muted);
  line-height: 1.5;
}
.settings-modal .settings-args-examples code {
  background: var(--bg);
  padding: 2px 6px;
  border-radius: 3px;
  font-size: 11px;
  word-break: break-all;
  color: var(--text);
  display: inline-block;
}
.settings-modal .settings-tag {
  display: inline-block;
  background: rgba(240, 194, 68, 0.15);
  color: #f0c244;
  border: 1px solid rgba(240, 194, 68, 0.35);
  font-style: normal;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 1px 6px;
  border-radius: 3px;
  margin-left: 6px;
  vertical-align: middle;
}

/* ---- Recording pill in the library header ---- */
.recording-pill {
  background: rgba(255, 93, 93, 0.12);
  border: 1px solid var(--death);
  color: var(--death);
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.recording-pill:hover { background: rgba(255, 93, 93, 0.20); }
.recording-menu {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.5);
  z-index: 90;
}
.recording-menu button {
  background: transparent;
  border: none;
  text-align: left;
  padding: 6px 10px;
  font-size: 12px;
  color: var(--text);
  border-radius: 4px;
  cursor: pointer;
}
.recording-menu button:hover { background: var(--panel-2); }

/* (The bespoke .auto-review-toast is gone — auto-review.js posts to the
   ledger stack now: an artifact row with the champion portrait + "open".) */

/* New-review page auto-flow banner — shown when we land on /new.html via
   the recording-finished pipeline. */
.auto-flow-banner {
  background: rgba(78, 161, 255, 0.08);
  border: 1px solid var(--accent);
  border-radius: 6px;
  padding: 10px 12px;
  margin-bottom: 14px;
  font-size: 13px;
  color: var(--text);
  line-height: 1.5;
}
.auto-flow-banner code {
  background: var(--panel-2);
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 12px;
  word-break: break-all;
}

/* Tauri file-picker replacement used on /new.html when running in the
   desktop app — standard <input type=file> doesn't expose absolute
   paths so we route through the Tauri dialog plugin instead. */
.tauri-file-picker {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.tauri-file-picker .tauri-picked-path {
  font-size: 12px;
  word-break: break-all;
  color: var(--muted);
}

/* ── Shared video transport (player.js) ─────────────────────────────────
   Lives here because it's the only stylesheet every page loads, and three
   surfaces use it: the clip export modal, the Clips tab's watch modal, and
   (volume only) the review + clip pages' own control bars.

   Native <video controls> is deliberately avoided — its gradient bar sits
   across the bottom of the frame, right over League's minimap. */

.vp-bar { display: flex; flex-direction: column; gap: 9px; }

.vp-track { position: relative; height: 6px; background: var(--surface-raised, #1b1d29);
  border: 1px solid var(--border, #292c3c); cursor: pointer; box-sizing: border-box; }
.vp-fill { position: absolute; top: 0; left: 0; bottom: 0; width: 0; background: var(--brand, #4444d4); }
.vp-knob { position: absolute; top: 50%; left: 0; transform: translate(-50%, -50%); width: 12px; height: 12px;
  border-radius: 50%; background: #fff; border: 2px solid var(--brand, #4444d4); box-sizing: border-box;
  transition: transform .1s cubic-bezier(.4, 0, .2, 1); }
.vp-track:hover .vp-knob { transform: translate(-50%, -50%) scale(1.25); }

.vp-btns { display: flex; align-items: center; gap: 6px; }
.vp-spacer { flex: 1; }
/* inline-flex: the faces are display:block svgs (below), and a block inside a
   plain button hugs its left edge. Play, mute and fullscreen sat 1px from the
   border of their 36px box until the button centred them as a flex item. */
.vp-btn { height: 30px; padding: 0 9px; background: var(--surface-raised, #1b1d29);
  border: 1px solid var(--border, #292c3c); color: var(--text, #e7e9f2);
  font-family: var(--font-mono, monospace); font-size: 12px; cursor: pointer; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background-color .1s, border-color .1s, color .1s; }
.vp-btn.is-glyph { min-width: 36px; padding: 0; font-family: var(--font-sans, sans-serif); font-size: 13px; }
.vp-btn:hover { background: var(--surface-hover, #252839); }
.vp-time { font-family: var(--font-mono, monospace); font-size: 12px; color: var(--text-muted, #8b8fa6);
  font-variant-numeric: tabular-nums; }

/* Volume: the slider hangs above the mute button and appears on hover. The
   wrapper is inline-flex so it drops into any existing control bar without
   disturbing its layout. */
.vp-vol { position: relative; display: inline-flex; }
.vp-volpop { position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%);
  display: none; padding: 9px 7px; background: var(--surface-raised, #1b1d29);
  border: 1px solid var(--border-strong, #363a4e); box-shadow: 0 6px 20px rgba(0, 0, 0, .5); z-index: 5; }
.vp-vol:hover .vp-volpop, .vp-vol.is-dragging .vp-volpop { display: block; }
/* A hover bridge — without it the gap between button and popup closes the
   popup the moment the pointer travels up to the slider. */
.vp-volpop::after { content: ""; position: absolute; top: 100%; left: 0; right: 0; height: 8px; }
.vp-voltrack { position: relative; display: block; width: 6px; height: 72px; cursor: pointer;
  background: var(--bg, #0c0d13); border: 1px solid var(--border, #292c3c); box-sizing: border-box; }
.vp-volfill { position: absolute; left: 0; right: 0; bottom: 0; height: 100%; background: var(--brand, #4444d4); }

/* ── Creature loaders (design handoff: "Loading Animations") ───────────
   Six hand-drawn sprite loops (gromp / krug / sapling / shrooms / turret
   shootout / scuttle crab) that replace the heavy conic spinner on long
   operations (clip render, coaching upload). creature-loader.js picks a random,
   non-repeating variant per mount; sprites live in /creature-assets/. Each
   variant carries its own authored stage box (set inline) scaled by --cl-scale;
   .cl-fit is the scaled-size clip box so layout reserves only the scaled size. */
.cl-loader { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.cl-fit { overflow: hidden; flex: none; }
.cl-stage { position: relative; flex: none; transform-origin: top left; transform: scale(var(--cl-scale, 1)); }
.cl-cap {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 11px; letter-spacing: .06em; color: var(--text-muted, var(--muted));
}
.cl-reduced { padding: 8px 0; }

@keyframes dust {
      0% { transform: translate(0,0) scale(1); opacity: 0; }
      10% { opacity: .5; }
      100% { transform: translate(-46px,-14px) scale(.3); opacity: 0; }
    }
@keyframes g4ToadHD {
      0%, 1% { transform: translate(0,0) scale(0); opacity: 1; }
      2.5% { transform: translate(0,-10px) scale(.65,.85); }
      4.5% { transform: translate(0,0) scale(1.16,.78); }
      6.5% { transform: translate(0,0) scale(.94,1.08); }
      8% { transform: translate(0,0) scale(1,1); }
      10% { transform: translate(0,1px) scale(1.12,.82); }
      13.5% { transform: translate(22px,-22px) scale(.94,1.08); }
      17% { transform: translate(44px,0) scale(1.12,.84); }
      19.5% { transform: translate(44px,0) scale(1,1); }
      22% { transform: translate(44px,1px) scale(1.12,.82); }
      25.5% { transform: translate(66px,-22px) scale(.94,1.08); }
      29% { transform: translate(88px,0) scale(1.12,.84); }
      31.5% { transform: translate(88px,0) scale(1,1); }
      34% { transform: translate(88px,1px) scale(1.16,.78); }
      38% { transform: translate(112px,-66px) scale(.92,1.1); }
      41.5% { transform: translate(134px,-35px) scale(1.14,.84); }
      44% { transform: translate(134px,-35px) scale(1,1); }
      50% { transform: translate(134px,-35px) scale(1.05,.95); }
      56.4% { transform: translate(134px,-35px) scale(1,1); opacity: 1; }
      56.5%, 100% { transform: translate(134px,-35px) scale(1,1); opacity: 0; }
    }
@keyframes gpGrompD {
      0%, 56.4% { transform: translate(0,0) scale(0); opacity: 0; }
      56.5% { transform: translate(0,0) scale(.3,.22); opacity: 1; }
      59% { transform: translate(0,-26px) scale(.6,.75); }
      62% { transform: translate(0,0) scale(1.14,.8); }
      64.5% { transform: translate(0,0) scale(.94,1.08); }
      67% { transform: translate(0,0) scale(1.03,.97); }
      69.5% { transform: translate(0,0) scale(1); }
      77% { transform: translate(0,0) scale(1.02,.98); }
      85% { transform: translate(0,0) scale(1); }
      91.5% { transform: translate(0,0) scale(1.07,.93); }
      93.5% { transform: translate(0,0) scale(.88,1.12); opacity: 1; }
      95.5%, 100% { transform: translate(0,0) scale(1.5,1.3); opacity: 0; }
    }
@keyframes gpPufPL {
      0%, 93.5% { transform: translate(0,0) scale(.3); opacity: 0; }
      94.5% { opacity: .5; }
      100% { transform: translate(-44px,-20px) scale(1.2); opacity: 0; }
    }
@keyframes gpPufPR {
      0%, 93.5% { transform: translate(0,0) scale(.3); opacity: 0; }
      94.5% { opacity: .5; }
      100% { transform: translate(44px,-20px) scale(1.2); opacity: 0; }
    }
@keyframes gpPufSL {
      0%, 1.5% { transform: translate(0,0) scale(.3); opacity: 0; }
      3% { opacity: .5; }
      12%, 100% { transform: translate(-26px,-12px) scale(1); opacity: 0; }
    }
@keyframes gpPufSR {
      0%, 1.5% { transform: translate(0,0) scale(.3); opacity: 0; }
      3% { opacity: .5; }
      12%, 100% { transform: translate(26px,-12px) scale(1); opacity: 0; }
    }
@keyframes gpPufTL {
      0%, 56.4% { transform: translate(0,0) scale(.3); opacity: 0; }
      57.5% { opacity: .5; }
      67%, 100% { transform: translate(-40px,-18px) scale(1.15); opacity: 0; }
    }
@keyframes gpPufTR {
      0%, 56.4% { transform: translate(0,0) scale(.3); opacity: 0; }
      57.5% { opacity: .5; }
      67%, 100% { transform: translate(40px,-18px) scale(1.15); opacity: 0; }
    }
@keyframes gpPufTU {
      0%, 56.4% { transform: translate(0,0) scale(.3); opacity: 0; }
      57.5% { opacity: .5; }
      67%, 100% { transform: translate(4px,-46px) scale(1.15); opacity: 0; }
    }
@keyframes gpShroomB {
      0%, 39.5% { transform: translate(0,0) scale(1); opacity: 1; }
      41.5% { transform: translate(0,0) scale(1.16,.8); opacity: 1; }
      44% { transform: translate(0,0) scale(.96,1.05); opacity: 1; }
      47% { transform: translate(0,0) scale(1); opacity: 1; }
      56.4% { transform: translate(0,0) scale(1); opacity: 1; }
      56.5% { transform: translate(0,0) scale(1); opacity: 0; }
      96% { transform: translate(0,-40px) scale(.5); opacity: 0; }
      96.6% { transform: translate(0,-30px) scale(.7); opacity: 1; }
      98.4% { transform: translate(0,0) scale(1.2,.78); opacity: 1; }
      99.4% { transform: translate(0,-3px) scale(.95,1.06); opacity: 1; }
      100% { transform: translate(0,0) scale(1); opacity: 1; }
    }
@keyframes gpSp1 {
      0%, 94% { transform: translate(0,0) scale(0); opacity: 0; }
      94.5% { transform: translate(-8px,-14px) scale(1); opacity: .9; }
      100% { transform: translate(-48px,24px) scale(.4); opacity: 0; }
    }
@keyframes gpSp2 {
      0%, 94% { transform: translate(0,0) scale(0); opacity: 0; }
      94.5% { transform: translate(10px,-20px) scale(1); opacity: .9; }
      100% { transform: translate(56px,18px) scale(.4); opacity: 0; }
    }
@keyframes gpSp3 {
      0%, 94% { transform: translate(0,0) scale(0); opacity: 0; }
      94.5% { transform: translate(-16px,-6px) scale(1); opacity: .9; }
      100% { transform: translate(-62px,-10px) scale(.4); opacity: 0; }
    }
@keyframes gpSp4 {
      0%, 94% { transform: translate(0,0) scale(0); opacity: 0; }
      94.5% { transform: translate(14px,-4px) scale(1); opacity: .9; }
      100% { transform: translate(44px,-32px) scale(.4); opacity: 0; }
    }
@keyframes groundScroll { from { background-position: 0 0; } to { background-position: -84px 0; } }
@keyframes k2MLHD {
      0%, 12.5% { transform: translate(0,0) scale(0); opacity: 1; }
      13% { transform: translate(0,-6px) scale(1); opacity: 1; animation-timing-function: linear; }
      14.6% { transform: translate(-9.2px,-32.7px) scale(1); opacity: 1; animation-timing-function: linear; }
      16.2% { transform: translate(-18.4px,-45.1px) scale(1); opacity: 1; animation-timing-function: linear; }
      17.8% { transform: translate(-27.6px,-43.3px) scale(1); opacity: 1; animation-timing-function: linear; }
      19.4% { transform: translate(-36.8px,-27.3px) scale(1); opacity: 1; animation-timing-function: linear; }
      21% { transform: translate(-46px,3px) scale(1.1,.89); opacity: 1; }
      24% { transform: translate(-46px,0) scale(1); opacity: 1; }
      31% { transform: translate(-46px,2px) scale(1.16,.81); opacity: 1; }
      33.5% { transform: translate(-46px,0) scale(1); opacity: 1; }
      34.99% { transform: translate(-46px,0) scale(1); opacity: 1; }
      35% { transform: translate(-46px,0) scale(1); opacity: 0; }
      100% { transform: translate(-46px,0) scale(1); opacity: 0; }
    }
@keyframes k2MRHD {
      0%, 12.5% { transform: translate(0,0) scale(0); opacity: 1; }
      13% { transform: translate(0,-6px) scale(1); opacity: 1; animation-timing-function: linear; }
      14.6% { transform: translate(9.2px,-32.7px) scale(1); opacity: 1; animation-timing-function: linear; }
      16.2% { transform: translate(18.4px,-45.1px) scale(1); opacity: 1; animation-timing-function: linear; }
      17.8% { transform: translate(27.6px,-43.3px) scale(1); opacity: 1; animation-timing-function: linear; }
      19.4% { transform: translate(36.8px,-27.3px) scale(1); opacity: 1; animation-timing-function: linear; }
      21% { transform: translate(46px,3px) scale(1.1,.89); opacity: 1; }
      24% { transform: translate(46px,0) scale(1); opacity: 1; }
      31% { transform: translate(46px,2px) scale(1.16,.81); opacity: 1; }
      33.5% { transform: translate(46px,0) scale(1); opacity: 1; }
      34.99% { transform: translate(46px,0) scale(1); opacity: 1; }
      35% { transform: translate(46px,0) scale(1); opacity: 0; }
      100% { transform: translate(46px,0) scale(1); opacity: 0; }
    }
@keyframes k3Big {
      0%, 8% { transform: translate(0,0) scale(1); opacity: 1; }
      11% { transform: translate(0,3px) scale(1.12,.84); opacity: 1; }
      12.99% { transform: translate(0,2px) scale(1.06,.9); opacity: 1; }
      13% { transform: translate(0,0) scale(.28); opacity: 0; }
      86.5% { transform: translate(0,0) scale(.28); opacity: 0; }
      88.5% { transform: translate(0,-2px) scale(1.15,.82); opacity: 1; }
      92% { transform: translate(0,0) scale(.95,1.06); opacity: 1; }
      96%, 100% { transform: translate(0,0) scale(1); opacity: 1; }
    }
@keyframes k3S1HD {
      0%, 34.5% { transform: translate(-46px,0) scale(0); opacity: 1; }
      35% { transform: translate(-46px,-5px) scale(1); animation-timing-function: linear; }
      36.4% { transform: translate(-51.2px,-24.4px) scale(1); animation-timing-function: linear; }
      37.8% { transform: translate(-56.4px,-33.4px) scale(1); animation-timing-function: linear; }
      39.2% { transform: translate(-61.6px,-32px) scale(1); animation-timing-function: linear; }
      40.6% { transform: translate(-66.8px,-20.2px) scale(1); animation-timing-function: linear; }
      42% { transform: translate(-72px,2px) scale(1.11,.84); }
      45% { transform: translate(-72px,0) scale(1); }
      54% { transform: translate(-72px,0) scale(1); }
      55% { transform: translate(-72px,1px) scale(1.11,.84); animation-timing-function: linear; }
      56% { transform: translate(-59.2px,-25.2px) scale(1); animation-timing-function: linear; }
      57% { transform: translate(-46.4px,-38.4px) scale(1); animation-timing-function: linear; }
      58% { transform: translate(-33.6px,-38.4px) scale(1); animation-timing-function: linear; }
      59% { transform: translate(-20.8px,-25.2px) scale(1); animation-timing-function: linear; }
      60% { transform: translate(-8px,1px) scale(1.11,.84); }
      62% { transform: translate(-8px,0) scale(1); }
      84% { transform: translate(-8px,0) scale(1); }
      86% { transform: translate(-8px,1px) scale(1.16,.79); opacity: 1; }
      88.5% { transform: translate(0,0) scale(.32); opacity: 0; }
      100% { transform: translate(0,0) scale(.32); opacity: 0; }
    }
@keyframes k3S2HD {
      0%, 34.5% { transform: translate(46px,0) scale(0); opacity: 1; }
      35% { transform: translate(46px,-5px) scale(1); animation-timing-function: linear; }
      36.4% { transform: translate(51.2px,-24.4px) scale(1); animation-timing-function: linear; }
      37.8% { transform: translate(56.4px,-33.4px) scale(1); animation-timing-function: linear; }
      39.2% { transform: translate(61.6px,-32px) scale(1); animation-timing-function: linear; }
      40.6% { transform: translate(66.8px,-20.2px) scale(1); animation-timing-function: linear; }
      42% { transform: translate(72px,2px) scale(1.11,.84); }
      45% { transform: translate(72px,0) scale(1); }
      57% { transform: translate(72px,1px) scale(1.11,.84); animation-timing-function: linear; }
      58% { transform: translate(59.2px,-25.2px) scale(1); animation-timing-function: linear; }
      59% { transform: translate(46.4px,-38.4px) scale(1); animation-timing-function: linear; }
      60% { transform: translate(33.6px,-38.4px) scale(1); animation-timing-function: linear; }
      61% { transform: translate(20.8px,-25.2px) scale(1); animation-timing-function: linear; }
      62% { transform: translate(8px,1px) scale(1.11,.84); }
      64% { transform: translate(8px,0) scale(1); }
      84% { transform: translate(8px,0) scale(1); }
      86% { transform: translate(8px,1px) scale(1.16,.79); opacity: 1; }
      88.5% { transform: translate(0,0) scale(.32); opacity: 0; }
      100% { transform: translate(0,0) scale(.32); opacity: 0; }
    }
@keyframes k3S3HD {
      0%, 34.5% { transform: translate(-46px,0) scale(0); opacity: 1; }
      35% { transform: translate(-46px,-5px) scale(1); animation-timing-function: linear; }
      36.4% { transform: translate(-41.4px,-24.4px) scale(1); animation-timing-function: linear; }
      37.8% { transform: translate(-36.8px,-33.4px) scale(1); animation-timing-function: linear; }
      39.2% { transform: translate(-32.2px,-32px) scale(1); animation-timing-function: linear; }
      40.6% { transform: translate(-27.6px,-20.2px) scale(1); animation-timing-function: linear; }
      42% { transform: translate(-23px,2px) scale(1.11,.84); }
      45% { transform: translate(-23px,0) scale(1); }
      61% { transform: translate(-23px,1px) scale(1.11,.84); animation-timing-function: linear; }
      62% { transform: translate(-20px,-29.2px) scale(1); animation-timing-function: linear; }
      63% { transform: translate(-17px,-47.4px) scale(1); animation-timing-function: linear; }
      64% { transform: translate(-14px,-53.6px) scale(1); animation-timing-function: linear; }
      65% { transform: translate(-11px,-47.8px) scale(1); animation-timing-function: linear; }
      66% { transform: translate(-8px,-29px) scale(1.11,.84); }
      68% { transform: translate(-8px,-30px) scale(1); }
      84% { transform: translate(-8px,-30px) scale(1); }
      86% { transform: translate(-8px,-29px) scale(1.16,.79); opacity: 1; }
      88.5% { transform: translate(0,-12px) scale(.32); opacity: 0; }
      100% { transform: translate(0,-12px) scale(.32); opacity: 0; }
    }
@keyframes k3S4HD {
      0%, 34.5% { transform: translate(46px,0) scale(0); opacity: 1; }
      35% { transform: translate(46px,-5px) scale(1); animation-timing-function: linear; }
      36.4% { transform: translate(41.4px,-24.4px) scale(1); animation-timing-function: linear; }
      37.8% { transform: translate(36.8px,-33.4px) scale(1); animation-timing-function: linear; }
      39.2% { transform: translate(32.2px,-32px) scale(1); animation-timing-function: linear; }
      40.6% { transform: translate(27.6px,-20.2px) scale(1); animation-timing-function: linear; }
      42% { transform: translate(23px,2px) scale(1.11,.84); }
      45% { transform: translate(23px,0) scale(1); }
      65% { transform: translate(23px,1px) scale(1.11,.84); animation-timing-function: linear; }
      66% { transform: translate(20px,-29.2px) scale(1); animation-timing-function: linear; }
      67% { transform: translate(17px,-47.4px) scale(1); animation-timing-function: linear; }
      68% { transform: translate(14px,-53.6px) scale(1); animation-timing-function: linear; }
      69% { transform: translate(11px,-47.8px) scale(1); animation-timing-function: linear; }
      70% { transform: translate(8px,-29px) scale(1.11,.84); }
      72% { transform: translate(8px,-30px) scale(1); }
      84% { transform: translate(8px,-30px) scale(1); }
      86% { transform: translate(8px,-29px) scale(1.16,.79); opacity: 1; }
      88.5% { transform: translate(0,-12px) scale(.32); opacity: 0; }
      100% { transform: translate(0,-12px) scale(.32); opacity: 0; }
    }
@keyframes saplingBob {
      0% { transform: translateY(0) rotate(-7deg) scale(1.04,.94); }
      25% { transform: translateY(-11px) rotate(0deg) scale(.98,1.04); }
      50% { transform: translateY(0) rotate(7deg) scale(1.04,.94); }
      75% { transform: translateY(-11px) rotate(0deg) scale(.98,1.04); }
      100% { transform: translateY(0) rotate(-7deg) scale(1.04,.94); }
    }
@keyframes scBob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
@keyframes scDropL {
      0% { transform: translate(0,0) scale(.6); opacity: 0; }
      12% { transform: translate(-7px,-15px) scale(1); opacity: .9; }
      55% { transform: translate(-18px,-18px) scale(.9); opacity: .75; }
      100% { transform: translate(-27px,7px) scale(.45); opacity: 0; }
    }
@keyframes scDropR {
      0% { transform: translate(0,0) scale(.6); opacity: 0; }
      12% { transform: translate(7px,-15px) scale(1); opacity: .9; }
      55% { transform: translate(18px,-18px) scale(.9); opacity: .75; }
      100% { transform: translate(27px,7px) scale(.45); opacity: 0; }
    }
@keyframes scF2 { 0%, 24.99% { opacity: 1; } 25%, 100% { opacity: 0; } }
@keyframes scF3 { 0%, 24.99% { opacity: 0; } 25%, 49.99% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes scF5 { 0%, 49.99% { opacity: 0; } 50%, 74.99% { opacity: 1; } 75%, 100% { opacity: 0; } }
@keyframes scF6 { 0%, 74.99% { opacity: 0; } 75%, 100% { opacity: 1; } }
@keyframes scRipple {
      0% { transform: translate(-50%,-50%) scale(.25); opacity: .55; }
      70% { opacity: .22; }
      100% { transform: translate(-50%,-50%) scale(1.3); opacity: 0; }
    }
@keyframes scShadow {
      0%, 49.99% { transform: translate(0,0); }
      50%, 74.99% { transform: translate(-9px,9px); }
      75%, 100% { transform: translate(9px,9px); }
    }
@keyframes scShadowBob { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(.96); opacity: .95; } }
@keyframes scWalk {
      0% { transform: translate(0,29px) scale(1); }
      25% { transform: translate(78px,0) scale(.775); }
      50% { transform: translate(0,-29px) scale(.55); }
      75% { transform: translate(-78px,0) scale(.775); }
      100% { transform: translate(0,29px) scale(1); }
    }
@keyframes shroomPop {
      0% { transform: scale(0); opacity: 0; }
      12% { transform: scale(1.18,1.05); opacity: 1; }
      20% { transform: scale(1); opacity: 1; }
      58% { transform: scale(1); opacity: 1; }
      68% { transform: scale(1.08,.88); opacity: 1; }
      78% { transform: scale(0); opacity: 0; }
      100% { transform: scale(0); opacity: 0; }
    }
@keyframes soBreathe {
      0% { transform: scale(1); }
      25% { transform: scale(1.015,.985); }
      50% { transform: scale(1); }
      100% { transform: scale(1); }
    }
@keyframes soBulM {
      0%, 16.63% { transform: translate(0,0) scale(.35); opacity: 0; }
      16.67% { transform: translate(0,0) scale(.35); opacity: 1; animation-timing-function: linear; }
      21.3% { transform: translate(-101px,22px) scale(1); opacity: 1; }
      21.33% { transform: translate(-101px,22px) scale(1); opacity: 0; }
      49.97% { transform: translate(0,0) scale(.35); opacity: 0; }
      50% { transform: translate(0,0) scale(.35); opacity: 1; animation-timing-function: linear; }
      54.63% { transform: translate(-101px,22px) scale(1); opacity: 1; }
      54.67%, 100% { transform: translate(-101px,22px) scale(1); opacity: 0; }
    }
@keyframes soBulT {
      0% { transform: translate(0,0) scale(1); opacity: 1; animation-timing-function: linear; }
      13.9% { transform: translate(108px,-36px) scale(.42); opacity: 1; }
      14%, 100% { transform: translate(108px,-36px) scale(.42); opacity: 0; }
    }
@keyframes soBulT2 {
      0%, 14.9% { transform: translate(0,0) scale(1); opacity: 0; }
      15% { transform: translate(0,0) scale(1); opacity: 1; animation-timing-function: linear; }
      28.9% { transform: translate(108px,-36px) scale(.42); opacity: 1; }
      29%, 100% { transform: translate(108px,-36px) scale(.42); opacity: 0; }
    }
@keyframes soCoin1 {
      0%, 76.3% { transform: translate(0,0) scaleX(1); opacity: 0; }
      76.6% { transform: translate(-2px,-5px) scaleX(.5); opacity: 1; animation-timing-function: linear; }
      77.3% { transform: translate(-6px,-14px) scaleX(1); animation-timing-function: linear; }
      78.3% { transform: translate(-12px,-23px) scaleX(.35); animation-timing-function: linear; }
      79.3% { transform: translate(-18px,-27px) scaleX(1); animation-timing-function: linear; }
      80.3% { transform: translate(-24px,-26px) scaleX(.35); animation-timing-function: linear; }
      81.3% { transform: translate(-30px,-20px) scaleX(1); opacity: 1; animation-timing-function: linear; }
      82.6%, 100% { transform: translate(-37px,-6px) scaleX(.5); opacity: 0; }
    }
@keyframes soCoin2 {
      0%, 76.3% { transform: translate(0,0) scaleX(1); opacity: 0; }
      76.6% { transform: translate(2px,-6px) scaleX(.4); opacity: 1; animation-timing-function: linear; }
      77.3% { transform: translate(7px,-16px) scaleX(1); animation-timing-function: linear; }
      78.3% { transform: translate(14px,-26px) scaleX(.35); animation-timing-function: linear; }
      79.3% { transform: translate(21px,-31px) scaleX(1); animation-timing-function: linear; }
      80.3% { transform: translate(28px,-30px) scaleX(.35); animation-timing-function: linear; }
      81.3% { transform: translate(35px,-24px) scaleX(1); opacity: 1; animation-timing-function: linear; }
      82.6%, 100% { transform: translate(43px,-9px) scaleX(.5); opacity: 0; }
    }
@keyframes soCoin3 {
      0%, 76.3% { transform: translate(0,0) scaleX(1); opacity: 0; }
      76.6% { transform: translate(1px,-7px) scaleX(.45); opacity: 1; animation-timing-function: linear; }
      77.3% { transform: translate(2px,-18px) scaleX(1); animation-timing-function: linear; }
      78.3% { transform: translate(4px,-30px) scaleX(.35); animation-timing-function: linear; }
      79.3% { transform: translate(6px,-36px) scaleX(1); animation-timing-function: linear; }
      80.3% { transform: translate(8px,-37px) scaleX(.35); animation-timing-function: linear; }
      81.3% { transform: translate(10px,-32px) scaleX(1); opacity: 1; animation-timing-function: linear; }
      82.6%, 100% { transform: translate(13px,-18px) scaleX(.5); opacity: 0; }
    }
@keyframes soCoin4 {
      0%, 76.3% { transform: translate(0,0) scaleX(1); opacity: 0; }
      76.6% { transform: translate(-3px,-3px) scaleX(.5); opacity: 1; animation-timing-function: linear; }
      77.3% { transform: translate(-9px,-8px) scaleX(1); animation-timing-function: linear; }
      78.3% { transform: translate(-18px,-12px) scaleX(.35); animation-timing-function: linear; }
      79.3% { transform: translate(-27px,-11px) scaleX(1); animation-timing-function: linear; }
      80.3% { transform: translate(-36px,-4px) scaleX(.4); opacity: .9; animation-timing-function: linear; }
      81.6%, 100% { transform: translate(-46px,9px) scaleX(1); opacity: 0; }
    }
@keyframes soCoin5 {
      0%, 76.3% { transform: translate(0,0) scaleX(1); opacity: 0; }
      76.6% { transform: translate(3px,-2px) scaleX(.5); opacity: 1; animation-timing-function: linear; }
      77.3% { transform: translate(10px,-6px) scaleX(1); animation-timing-function: linear; }
      78.3% { transform: translate(20px,-8px) scaleX(.35); animation-timing-function: linear; }
      79.3% { transform: translate(30px,-5px) scaleX(1); animation-timing-function: linear; }
      80.3% { transform: translate(40px,3px) scaleX(.4); opacity: .9; animation-timing-function: linear; }
      81.6%, 100% { transform: translate(51px,17px) scaleX(1); opacity: 0; }
    }
@keyframes soGold {
      0%, 76.3% { transform: translate(0,4px); opacity: 0; }
      76.8% { transform: translate(0,-6px); opacity: 1; animation-timing-function: linear; }
      78% { transform: translate(0,-14px); opacity: 1; animation-timing-function: linear; }
      79.5% { transform: translate(0,-19px); opacity: 1; animation-timing-function: linear; }
      81% { transform: translate(0,-21px); opacity: 1; animation-timing-function: linear; }
      82.5% { transform: translate(0,-19px); opacity: 1; animation-timing-function: linear; }
      84% { transform: translate(0,-13px); opacity: .9; animation-timing-function: linear; }
      85.5% { transform: translate(0,-3px); opacity: .55; animation-timing-function: linear; }
      87%, 100% { transform: translate(0,9px); opacity: 0; }
    }
@keyframes soHitM {
      0%, 14.2% { transform: scale(.2); opacity: 0; }
      14.8% { transform: scale(.85); opacity: .8; }
      17.5% { transform: scale(1.5); opacity: 0; }
      29.2% { transform: scale(.2); opacity: 0; }
      29.8% { transform: scale(.85); opacity: .8; }
      32.5%, 100% { transform: scale(1.5); opacity: 0; }
    }
@keyframes soHitT {
      0%, 21.4% { transform: scale(.2); opacity: 0; }
      21.6% { transform: scale(.85); opacity: .8; }
      22.5% { transform: scale(1.5); opacity: 0; }
      54.73% { transform: scale(.2); opacity: 0; }
      54.93% { transform: scale(.85); opacity: .8; }
      55.83%, 100% { transform: scale(1.5); opacity: 0; }
    }
@keyframes soHpM {
      0%, 4.5% { transform: scaleX(1); }
      4.8%, 9.5% { transform: scaleX(.833); }
      9.8%, 37.9% { transform: scaleX(.667); }
      38.2%, 42.9% { transform: scaleX(.5); }
      43.2%, 71.2% { transform: scaleX(.333); }
      71.5%, 76.2% { transform: scaleX(.167); }
      76.5%, 87.9% { transform: scaleX(0); }
      88.2%, 100% { transform: scaleX(1); }
    }
@keyframes soHpT {
      0%, 21.3% { transform: scaleX(1); }
      21.6%, 54.6% { transform: scaleX(.8); }
      54.9%, 87.9% { transform: scaleX(.6); }
      88.2%, 100% { transform: scaleX(1); }
    }
@keyframes soMDeath {
      0%, 76.2% { transform: scale(1); opacity: 1; }
      76.5% { transform: scale(1.15,.8); opacity: 1; }
      77.2% { transform: scale(1.4,1.3); opacity: 1; }
      77.7% { transform: scale(1.55,1.45); opacity: 0; }
      87.9% { transform: scale(0); opacity: 0; }
      88.2% { transform: scale(.4,.3); opacity: 1; }
      89.2% { transform: scale(.65,.8); opacity: 1; }
      90.2% { transform: scale(1.14,.82); opacity: 1; }
      91.2% { transform: scale(.94,1.06); opacity: 1; }
      92.2%, 100% { transform: scale(1); opacity: 1; }
    }
@keyframes soMFlash {
      0%, 13.9% { opacity: 0; }
      14.4% { opacity: .85; }
      16.5% { opacity: .2; }
      18% { opacity: .55; }
      20.5% { opacity: 0; }
      28.9% { opacity: 0; }
      29.4% { opacity: .85; }
      31.5% { opacity: .2; }
      33% { opacity: .55; }
      35.5%, 100% { opacity: 0; }
    }
@keyframes soMMuz {
      0%, 16.63% { transform: rotate(-33deg) scale(.3); opacity: 0; }
      16.87% { transform: rotate(-33deg) scale(.75); opacity: .95; }
      17.67% { transform: rotate(-33deg) scale(1.25); opacity: .7; }
      18.67% { transform: rotate(-33deg) scale(1.5); opacity: 0; }
      49.97% { transform: rotate(-33deg) scale(.3); opacity: 0; }
      50.2% { transform: rotate(-33deg) scale(.75); opacity: .95; }
      51% { transform: rotate(-33deg) scale(1.25); opacity: .7; }
      52%, 100% { transform: rotate(-33deg) scale(1.5); opacity: 0; }
    }
@keyframes soMRec {
      0%, 16.63% { transform: translate(0,0); }
      17.07% { transform: translate(7px,-5px) rotate(3deg); }
      17.83% { transform: translate(-2px,1px) rotate(-1.2deg); }
      18.67% { transform: translate(0,0); }
      49.97% { transform: translate(0,0); }
      50.4% { transform: translate(7px,-5px) rotate(3deg); }
      51.17% { transform: translate(-2px,1px) rotate(-1.2deg); }
      52%, 100% { transform: translate(0,0); }
    }
@keyframes soMShake {
      0%, 13.9% { transform: translate(0,0); }
      14.6% { transform: translate(4px,-3px) rotate(1.6deg); }
      16.2% { transform: translate(-3px,2px) rotate(-1.2deg); }
      17.8% { transform: translate(2px,-1px) rotate(.8deg); }
      19.4% { transform: translate(-1px,0) rotate(-.4deg); }
      21% { transform: translate(0,0); }
      28.9% { transform: translate(0,0); }
      29.6% { transform: translate(4px,-3px) rotate(1.6deg); }
      31.2% { transform: translate(-3px,2px) rotate(-1.2deg); }
      32.8% { transform: translate(2px,-1px) rotate(.8deg); }
      34.4% { transform: translate(-1px,0) rotate(-.4deg); }
      36%, 100% { transform: translate(0,0); }
    }
@keyframes soPop1 {
      0%, 76.3% { transform: translate(0,0) scale(.3); opacity: 0; }
      77.3% { opacity: .55; }
      84%, 100% { transform: translate(-26px,-16px) scale(1.2); opacity: 0; }
    }
@keyframes soPop2 {
      0%, 76.3% { transform: translate(0,0) scale(.3); opacity: 0; }
      77.3% { opacity: .55; }
      84%, 100% { transform: translate(26px,-14px) scale(1.2); opacity: 0; }
    }
@keyframes soPop3 {
      0%, 76.3% { transform: translate(0,0) scale(.3); opacity: 0; }
      77.3% { opacity: .55; }
      84%, 100% { transform: translate(2px,-32px) scale(1.2); opacity: 0; }
    }
@keyframes soPop4 {
      0%, 76.3% { transform: translate(0,0) scale(.3); opacity: 0; }
      77.3% { opacity: .55; }
      84%, 100% { transform: translate(-14px,18px) scale(1.2); opacity: 0; }
    }
@keyframes soPufM {
      0%, 16.67% { transform: translate(0,0) scale(.3); opacity: 0; }
      17.17% { opacity: .5; }
      20.67% { transform: translate(-22px,12px) scale(1.15); opacity: 0; }
      49.97% { transform: translate(0,0) scale(.3); opacity: 0; }
      50.47% { opacity: .5; }
      54%, 100% { transform: translate(-22px,12px) scale(1.15); opacity: 0; }
    }
@keyframes soTFlash {
      0%, 21.3% { opacity: 0; }
      21.47% { opacity: .85; }
      22.17% { opacity: .2; }
      22.67% { opacity: .55; }
      23.5% { opacity: 0; }
      54.63% { opacity: 0; }
      54.8% { opacity: .85; }
      55.5% { opacity: .2; }
      56% { opacity: .55; }
      56.83%, 100% { opacity: 0; }
    }
@keyframes soTRec {
      0% { transform: translate(0,0) scale(1); }
      1.2% { transform: translate(-5px,4px) rotate(-3deg) scale(1); }
      3.5% { transform: translate(2px,-1px) rotate(1deg) scale(1); }
      6% { transform: translate(0,0) scale(1); }
      14.9% { transform: translate(0,0) scale(1); }
      16.1% { transform: translate(-5px,4px) rotate(-3deg) scale(1); }
      18.4% { transform: translate(2px,-1px) rotate(1deg) scale(1); }
      22% { transform: translate(0,0) scale(1); }
      42% { transform: translate(0,0) scale(1.015,.985); }
      58% { transform: translate(0,0) scale(1); }
      80% { transform: translate(0,0) scale(1.015,.985); }
      100% { transform: translate(0,0) scale(1); }
    }
@keyframes soTShake {
      0%, 21.3% { transform: translate(0,0); }
      21.53% { transform: translate(-4px,3px) rotate(-1.6deg); }
      22.07% { transform: translate(3px,-2px) rotate(1.2deg); }
      22.6% { transform: translate(-2px,1px) rotate(-.8deg); }
      23.13% { transform: translate(1px,0) rotate(.4deg); }
      23.67% { transform: translate(0,0); }
      54.63% { transform: translate(0,0); }
      54.87% { transform: translate(-4px,3px) rotate(-1.6deg); }
      55.4% { transform: translate(3px,-2px) rotate(1.2deg); }
      55.93% { transform: translate(-2px,1px) rotate(-.8deg); }
      56.47% { transform: translate(1px,0) rotate(.4deg); }
      57%, 100% { transform: translate(0,0); }
    }

/* ── Context menus (ctxmenu.js) — the one right-click menu system ─────────
   Same chrome as the review page's note menu / the ledger row menu; those
   two are now thin wrappers over this. Squared (no radius), raised surface,
   mono title, 12.5px sans items. Submenus are separate fixed elements. */
.cm-menu {
  position: fixed; z-index: 4100; min-width: 172px; max-width: 300px;
  display: flex; flex-direction: column; padding: 4px; box-sizing: border-box;
  background: var(--surface-raised, #1b1d29); border: 1px solid var(--border-strong, #363a4e);
  box-shadow: var(--shadow-menu, 0 8px 24px rgba(0, 0, 0, .5));
  font-family: var(--font-sans, system-ui, sans-serif); color: var(--text, #e6e9ef);
  user-select: none; -webkit-user-select: none;
}
.cm-menu.cm-submenu { z-index: 4101; }
/* A submenu of bare swatches (the note colour picker) is a thin strip: the
   check column + the swatch, nothing else. */
.cm-menu.cm-submenu:has(.cm-item > .cm-sw:last-child) { min-width: 0; width: max-content; padding-left: 4px; padding-right: 4px; }
.cm-menu.cm-submenu:has(.cm-item > .cm-sw:last-child) .cm-item { padding-right: 8px; gap: 6px; }
.cm-menu.cm-submenu:has(.cm-item > .cm-sw:last-child) .cm-item .cm-sw { width: 14px; height: 14px; }
.cm-menu.cm-scroll { overflow-y: auto; overscroll-behavior: contain; }
.cm-title {
  padding: 6px 9px 5px; margin-bottom: 3px; border-bottom: 1px solid var(--border, #292c3c);
  font-family: var(--font-mono, ui-monospace, monospace); font-size: 10px; font-weight: 500; letter-spacing: .03em;
  color: var(--text-muted, #9aa0b5); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  display: flex; align-items: center; gap: 7px; min-height: 16px;
}
.cm-title img.cm-crest { width: 16px; height: 16px; flex: none; object-fit: contain; }
.cm-title .cm-tag { color: var(--text-faint, #565b73); }
.cm-item {
  display: flex; align-items: center; gap: 8px; width: 100%; height: 29px; padding: 0 9px; box-sizing: border-box;
  border: none; background: none; text-align: left; cursor: pointer;
  font-family: inherit; font-size: 12.5px; color: var(--text, #e6e9ef); white-space: nowrap;
}
.cm-item:hover, .cm-item.is-open { background: var(--surface-hover, #252839); }
.cm-item.danger { color: var(--red, #ff5d5d); }
.cm-item.accent { color: var(--accent, #4ea1ff); }
.cm-item.dis, .cm-item[disabled] { color: var(--text-faint, #565b73); cursor: default; }
.cm-item.dis:hover, .cm-item[disabled]:hover { background: none; }
.cm-item .cm-lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.cm-item .cm-car { flex: none; color: var(--text-faint, #565b73); font-size: 13px; line-height: 1; }
.cm-item .cm-check { flex: none; width: 12px; font-size: 11px; color: var(--accent, #4ea1ff); text-align: center; }
.cm-item .cm-sw { flex: none; width: 12px; height: 12px; border: 1px solid rgba(255, 255, 255, .18); box-sizing: border-box; }
.cm-item .cm-ico-note { flex: none; width: 14px; height: 14px; display: inline-flex; align-items: center; justify-content: center; }
.cm-item .cm-ico { flex: none; width: 14px; height: 14px; object-fit: cover; }
.cm-sep { height: 1px; margin: 4px 6px; background: var(--border, #292c3c); }
/* Two-line rows (the widget bar's Swap widget submenu — same rows as its own
   replace dropdown: icon, name, mono description). */
.cm-item:has(> .cm-col) { height: auto; padding: 8px 11px; gap: 10px; }
.cm-item > .cm-ico { width: 18px; height: 18px; object-fit: contain; background-size: contain; background-position: center; background-repeat: no-repeat; }
.cm-col { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cm-col .a { font-size: 12px; color: var(--text, #e6e9ef); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Descriptions wrap: a menu is at most 300px wide and a one-line sentence
   ("Standard timeline experience with a ruler of timestamps.") would clip. */
.cm-col .b { font-family: var(--font-mono, ui-monospace, monospace); font-size: 10px; color: var(--text-faint, #565b73); line-height: 1.35; white-space: normal; }
/* Pinned volume slider (right-click on the speaker / headset): behaves like
   a popup until the button is clicked again, a click lands elsewhere, or
   another context menu opens. */
.vp-vol.is-pinned .vp-volpop { display: block; }

/* Shared player (player.js): Solid Glyph transport faces, the skip icons numbered inside the ring. */
.vp-btn svg { display: block; }
.vp-ico { position: relative; display: inline-flex; width: 16px; height: 16px; align-items: center; justify-content: center; }
.vp-ico > b { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; padding-top: 1px; font: 700 6.5px var(--font-mono, ui-monospace, monospace); letter-spacing: -.05em; }
