/* ═══════════════════════════════════════════════════════════ Map Layout — faithful reproduction of v1 style.css Scoped under .ml-* prefix to avoid conflicts with dashboard ═══════════════════════════════════════════════════════════ */ /* ── Layout ───────────────────────────────────────────── */ .ml-layout { display: flex; height: 100vh; overflow: hidden; background: #111; color: #eee; font-family: "Segoe UI", sans-serif; } /* ── Sidebar ──────────────────────────────────────────── */ .ml-sidebar { width: 400px; min-width: 400px; background: #1a1a1a; border-right: 2px solid #333; display: flex; flex-direction: column; overflow-y: auto; padding: 12px 14px; scrollbar-width: none; -ms-overflow-style: none; } .ml-sidebar::-webkit-scrollbar { display: none; } .ml-sidebar-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .ml-sidebar-title { font-size: 0.85rem; font-weight: 600; color: #88f; } .ml-view-toggle { font-size: 0.7rem; padding: 3px 10px; background: #333; color: #aaa; border: 1px solid #555; border-radius: 3px; cursor: pointer; } .ml-view-toggle:hover { background: #444; color: #fff; } /* ── Server status ────────────────────────────────────── */ .ml-server-status { display: flex; align-items: center; gap: 6px; padding: 4px 0 8px; font-size: 0.75rem; color: #aaa; } .ml-status-dot { width: 8px; height: 8px; border-radius: 50%; } .ml-status-dot.online { background: #4c4; animation: ml-pulse 2s ease-in-out infinite; } .ml-status-dot.offline { background: #c44; } .ml-status-detail { color: #888; font-size: 0.7rem; } .ml-status-latency { margin-left: auto; color: #888; } /* ── Tool links ───────────────────────────────────────── */ .ml-tool-links { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 8px; } .ml-tool-link { font-size: 0.68rem; color: #8ac; text-decoration: none; padding: 2px 6px; background: rgba(68, 136, 255, 0.08); border: 1px solid rgba(68, 136, 255, 0.15); border-radius: 3px; transition: all 0.15s; } .ml-tool-link:hover { background: rgba(68, 136, 255, 0.18); color: #adf; } @keyframes ml-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } } /* ── Aggregate counters ───────────────────────────────── */ .ml-counters { display: flex; gap: 6px; margin-bottom: 10px; } .ml-counter { flex: 1; text-align: center; padding: 6px 4px; border-radius: 4px; background: #222; border: 1px solid #333; } .ml-counter-val { display: block; font-size: 1rem; font-weight: 700; font-variant-numeric: tabular-nums; } .ml-counter-lbl { display: block; font-size: 0.6rem; color: #888; text-transform: uppercase; letter-spacing: 0.3px; } .ml-counter.rares .ml-counter-val { color: #ffcc00; } .ml-counter.kph .ml-counter-val { color: #4af; } .ml-counter.kph { border-color: #234; animation: ml-kph-glow 3s ease-in-out infinite; } .ml-counter.kph.ultra { background: linear-gradient(135deg, #112, #221); animation: ml-kph-glow 1.5s ease-in-out infinite; } .ml-counter.kills .ml-counter-val { color: #f66; } @keyframes ml-kph-glow { 0%, 100% { box-shadow: 0 0 4px rgba(68, 170, 255, 0.2); } 50% { box-shadow: 0 0 12px rgba(68, 170, 255, 0.5); } } /* ── Sort buttons ─────────────────────────────────────── */ .ml-sort-buttons { display: flex; gap: 2px; margin: 8px 0; } .ml-sort-btn { flex: 1; padding: 4px 0; font-size: 0.65rem; font-weight: 600; background: #2a2a2a; color: #888; border: 1px solid #444; border-radius: 3px; cursor: pointer; text-transform: uppercase; letter-spacing: 0.3px; } .ml-sort-btn:hover { background: #333; color: #ccc; } .ml-sort-btn.active { background: #334; color: #88f; border-color: #88f; } /* ── Filter input ─────────────────────────────────────── */ .ml-filter { width: 100%; padding: 5px 8px; font-size: 0.78rem; background: #222; color: #eee; border: 1px solid #444; border-radius: 3px; outline: none; margin-bottom: 8px; box-sizing: border-box; } .ml-filter:focus { border-color: #88f; } .ml-filter::placeholder { color: #666; } /* ── Player list ──────────────────────────────────────── */ .ml-player-list { list-style: none; margin: 0; padding: 0; flex: 1; overflow-y: auto; scrollbar-width: none; /* Firefox */ -ms-overflow-style: none; /* IE/Edge */ } .ml-player-list::-webkit-scrollbar { display: none; /* Chrome/Safari */ } .ml-player-row { padding: 6px 8px; border-bottom: 1px solid #2a2a2a; border-left: 3px solid transparent; cursor: pointer; transition: background 0.1s; } .ml-player-row:hover { background: #252525; } .ml-player-row.ml-player-selected { background: #2a3344; } .ml-pr-name { font-size: 0.82rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .ml-pr-coords { font-size: 0.65rem; color: #888; margin-bottom: 3px; } /* ── Vital bars ───────────────────────────────────────── */ .ml-pr-vitals { display: flex; gap: 3px; margin-bottom: 4px; } .ml-vital-bar { flex: 1; height: 4px; border-radius: 2px; overflow: hidden; } .ml-vital-bar.hp { background: #330000; } .ml-vital-bar.sta { background: #331a00; } .ml-vital-bar.mana { background: #001433; } .ml-vital-bar.hp .ml-vital-fill { background: linear-gradient(90deg, #ff4444, #ff6666); } .ml-vital-bar.sta .ml-vital-fill { background: linear-gradient(90deg, #ffaa00, #ffcc44); } .ml-vital-bar.mana .ml-vital-fill { background: linear-gradient(90deg, #4488ff, #66aaff); } .ml-vital-fill { height: 100%; border-radius: 2px; transition: width 0.3s ease-out; } /* ── Stats grid (3 columns aligned) ───────────────────── */ .ml-pr-header { display: flex; justify-content: space-between; align-items: baseline; cursor: pointer; } .ml-pr-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1px 8px; font-size: 0.68rem; color: #aaa; margin-bottom: 4px; } .ml-gs { font-variant-numeric: tabular-nums; display: inline-flex; align-items: center; gap: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .ml-suffix { font-size: 0.58rem; color: #666; text-transform: uppercase; letter-spacing: 0.3px; } .ml-taper-icon { width: 14px; height: 14px; margin-right: 2px; vertical-align: text-bottom; } .ml-meta-pill { font-size: 0.6rem; padding: 0 6px; border-radius: 3px; background: #333; color: #888; text-align: center; justify-self: end; } /* ── Action buttons ───────────────────────────────────── */ .ml-pr-buttons { display: flex; gap: 3px; margin-top: 4px; } .ml-btn { padding: 2px 8px; font-size: 0.63rem; font-weight: 500; border: 1px solid #3a3a3a; border-radius: 4px; background: #2a2a2a; color: #999; cursor: pointer; white-space: nowrap; transition: all 0.15s; letter-spacing: 0.2px; } .ml-btn:hover { background: #383838; color: #ddd; border-color: #555; } .ml-btn.accent { background: rgba(68, 136, 255, 0.12); color: #6aadff; border-color: rgba(68, 136, 255, 0.3); } .ml-btn.accent:hover { background: rgba(68, 136, 255, 0.22); color: #8ec5ff; border-color: rgba(68, 136, 255, 0.5); } .ml-meta-pill.active { background: rgba(68, 204, 68, 0.15); color: #4c4; } .ml-meta-pill.other { background: rgba(204, 68, 68, 0.15); color: #c44; } /* ── Map container ────────────────────────────────────── */ .ml-map-container { flex: 1; position: relative; overflow: hidden; background: #000; cursor: grab; } .ml-map-container:active { cursor: grabbing; } .ml-map-group { position: absolute; top: 0; left: 0; transform-origin: 0 0; } .ml-map-img { display: block; user-select: none; -webkit-user-drag: none; } /* ── Player dots ──────────────────────────────────────── */ .ml-dots-layer { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .ml-dot { position: absolute; width: 6px; height: 6px; border-radius: 50%; transform: translate(-50%, -50%); border: 1px solid rgba(0, 0, 0, 0.5); pointer-events: all; cursor: pointer; z-index: 5; } .ml-dot:hover { width: 10px; height: 10px; z-index: 10; } .ml-dot.ml-dot-selected { width: 10px; height: 10px; z-index: 10; animation: ml-blink 0.6s step-end infinite; } @keyframes ml-blink { 50% { opacity: 0; } } /* ── Version display ──────────────────────────────────── */ .ml-version { font-size: 0.65rem; color: #aaa; margin-bottom: 2px; } /* Floating version badge in the top-left of the viewport. Lets us verify at a glance which build is running. */ .ml-version-badge { position: fixed; top: 4px; left: 4px; z-index: 10000; padding: 3px 8px; background: rgba(0, 0, 0, 0.75); border: 1px solid rgba(255, 200, 64, 0.5); border-radius: 4px; color: #ffcc44; font-family: monospace; font-size: 0.7rem; pointer-events: none; letter-spacing: 0.02em; } /* ── Tooltip ──────────────────────────────────────────── */ .ml-tooltip { position: absolute; background: rgba(0, 30, 60, 0.92); color: #eee; padding: 6px 10px; border-radius: 4px; font-size: 0.75rem; pointer-events: none; z-index: 1000; white-space: nowrap; border: 1px solid #335; } /* ── Coordinate display ───────────────────────────────── */ .ml-coords { position: absolute; bottom: 8px; left: 8px; background: rgba(0, 50, 100, 0.85); color: #eee; padding: 4px 10px; border-radius: 4px; font-size: 0.75rem; pointer-events: none; z-index: 100; font-variant-numeric: tabular-nums; } /* ── Map toggles ──────────────────────────────────────── */ .ml-toggles { display: flex; gap: 12px; margin-bottom: 8px; font-size: 0.72rem; } .ml-toggle-label { display: flex; align-items: center; gap: 4px; color: #aaa; cursor: pointer; } .ml-toggle-label input { accent-color: #4488ff; } /* ── Trail SVG overlay ────────────────────────────────── */ .ml-trails-svg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } /* ── Heatmap canvas overlay ───────────────────────────── */ .ml-heatmap-canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; opacity: 0.8; } /* ── Portal markers ───────────────────────────────────── */ .ml-portals-layer { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .ml-portal-icon { position: absolute; width: 6px; height: 6px; transform: translate(-50%, -50%); pointer-events: all; cursor: help; } .ml-portal-icon::before { content: '🌀'; font-size: 10px; position: absolute; transform: translate(-50%, -50%); } /* ── Draggable windows ────────────────────────────────── */ .ml-window { position: fixed; background: #1a1a1a; border: 1px solid #444; border-radius: 6px; display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 8px 32px rgba(0,0,0,0.5); } .ml-window-header { display: flex; justify-content: space-between; align-items: center; padding: 6px 12px; background: linear-gradient(135deg, #2a3a5a, #1a2a40); cursor: move; user-select: none; border-bottom: 1px solid #334; } .ml-window-title { font-size: 0.8rem; font-weight: 600; color: #aaccff; } .ml-window-close { background: none; border: none; color: #888; font-size: 1.1rem; cursor: pointer; line-height: 1; padding: 0 4px; } .ml-window-close:hover { color: #f66; } .ml-window-content { flex: 1; overflow: auto; display: flex; flex-direction: column; } .ml-window-resize { position: absolute; bottom: 0; right: 0; width: 14px; height: 14px; cursor: nwse-resize; opacity: 0.3; background: linear-gradient(135deg, transparent 50%, #888 50%, transparent 52%, #888 65%, transparent 67%, #888 80%); } .ml-window-resize:hover { opacity: 0.6; } /* ── Stats window (Grafana iframes) ───────────────────── */ .ml-stats-controls { display: flex; gap: 4px; padding: 6px 10px; border-bottom: 1px solid #333; } .ml-stats-range-btn { padding: 3px 10px; font-size: 0.7rem; background: #2a2a2a; color: #888; border: 1px solid #444; border-radius: 3px; cursor: pointer; } .ml-stats-range-btn.active { background: rgba(68,136,255,0.15); color: #6aadff; border-color: rgba(68,136,255,0.3); } .ml-stats-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; padding: 4px; flex: 1; } .ml-stats-panel { min-height: 200px; background: #fff; border-radius: 3px; overflow: hidden; } .ml-stats-panel iframe { border: none; } /* ── Chat window ──────────────────────────────────────── */ .ml-chat-messages { flex: 1; overflow-y: auto; padding: 6px 10px; font-size: 0.75rem; font-family: 'Consolas', 'Courier New', monospace; line-height: 1.4; } .ml-chat-line { word-break: break-word; } .ml-chat-form { display: flex; border-top: 1px solid #333; padding: 4px; } .ml-chat-input { flex: 1; background: #222; color: #eee; border: 1px solid #444; border-radius: 3px; padding: 4px 8px; font-size: 0.78rem; outline: none; } .ml-chat-input:focus { border-color: #4488ff; } .ml-chat-input::placeholder { color: #666; } /* ── Rare notifications ───────────────────────────────── */ .ml-rare-notifications { position: fixed; top: 20px; left: 50%; transform: translateX(-50%); z-index: 99999; display: flex; flex-direction: column; gap: 8px; pointer-events: none; } .ml-rare-notif { background: linear-gradient(135deg, #1a0a2e, #2a1040); border: 2px solid #ffcc00; border-radius: 8px; padding: 16px 32px; text-align: center; animation: ml-notif-in 0.5s ease-out; box-shadow: 0 0 40px rgba(255, 204, 0, 0.3); } .ml-rare-notif.exiting { animation: ml-notif-out 0.5s ease-in forwards; } .ml-rare-notif-title { font-size: 1.4rem; font-weight: 800; color: #ffcc00; text-shadow: 0 0 20px rgba(255, 204, 0, 0.5); margin-bottom: 4px; } .ml-rare-notif-name { font-size: 1.1rem; font-weight: 600; color: #fff; margin-bottom: 4px; } .ml-rare-notif-by { font-size: 0.75rem; color: #888; } .ml-rare-notif-char { font-size: 1rem; font-weight: 700; color: #ffcc00; } @keyframes ml-notif-in { from { transform: translateY(-40px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } @keyframes ml-notif-out { to { transform: translateY(-60px); opacity: 0; } } /* ── Fireworks ────────────────────────────────────────── */ .ml-fireworks { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 99998; } .ml-firework-particle { position: absolute; width: 6px; height: 6px; border-radius: 50%; animation: ml-particle 2s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; } @keyframes ml-particle { 0% { transform: translate(0, 0) scale(1); opacity: 1; } 100% { transform: translate(var(--dx), var(--dy)) scale(0); opacity: 0; } } /* ── Mobile ───────────────────────────────────────────── */ @media (max-width: 768px) { .ml-layout { flex-direction: column; } .ml-sidebar { width: 100%; min-width: 100%; max-height: 40vh; border-right: none; border-bottom: 2px solid #333; } .ml-map-container { min-height: 60vh; } }