Simplificar a "FAB abre modal nativo" y añadir hora fin sesión
El usuario prefiere ver la página de Uso nativa de Claude en vez de un overlay propio. Eso permite borrar mucho código: - Fuera openOverlayPanel, closeOverlayPanel, setOverlaySpinner, renderOverlayWithCache, showOverlayError. - Fuera refreshInBackground, tryOpenViaPushState/Hash/Click, closeUsageModal, waitForDialogWithData — ya no auto-abrimos en background. - Fuera formatAge y CACHE_TTL_MS y OVERLAY_ID y refreshPromise. - Fuera __claudeUsageTracker (era andamio de debug). - Fuera bloque de CSS del overlay (~120 líneas). Nuevo onFabClick: 3 intentos en cascada para abrir el modal nativo de Claude (hash → pushState+popstate → click en "Uso"). Si los 3 fallan, warn en consola y queda el manual. Y siguiendo lo que pediste, en el resumen del tracker (el que se inyecta dentro del modal) ahora aparece un bloque azul "⏱ Sesión termina a las HH:MM (en Xh Ym)" justo debajo del bloque verde del reinicio semanal. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
277
content.js
277
content.js
@@ -587,6 +587,14 @@
|
|||||||
${dailyData.willRunOut ? `<span class="estimated-end-hours">(en ~${Math.round(dailyData.hoursToReach100)}h)</span>` : ''}
|
${dailyData.willRunOut ? `<span class="estimated-end-hours">(en ~${Math.round(dailyData.hoursToReach100)}h)</span>` : ''}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
${pageData.sessionEndTime ? `
|
||||||
|
<div class="session-reset-info">
|
||||||
|
<span class="session-reset-info-label">⏱ Sesión termina</span>
|
||||||
|
<span class="session-reset-info-time">a las ${formatTime(pageData.sessionEndTime)}</span>
|
||||||
|
<span class="session-reset-info-remaining">(en ${Math.floor(pageData.sessionTimeRemainingMin / 60)}h ${pageData.sessionTimeRemainingMin % 60}m)</span>
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
|
|
||||||
<div class="usage-info-row">
|
<div class="usage-info-row">
|
||||||
<div class="usage-stat">
|
<div class="usage-stat">
|
||||||
<span class="usage-stat-label">Tiempo transcurrido</span>
|
<span class="usage-stat-label">Tiempo transcurrido</span>
|
||||||
@@ -669,13 +677,10 @@
|
|||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
|
|
||||||
const CACHE_KEY = 'claude_usage_cache';
|
const CACHE_KEY = 'claude_usage_cache';
|
||||||
const CACHE_TTL_MS = 5 * 60 * 1000; // 5 min
|
|
||||||
const FAB_ID = 'claude-usage-tracker-fab';
|
const FAB_ID = 'claude-usage-tracker-fab';
|
||||||
const OVERLAY_ID = 'claude-usage-tracker-overlay';
|
|
||||||
const TRACKER_ID = 'claude-usage-tracker';
|
const TRACKER_ID = 'claude-usage-tracker';
|
||||||
|
|
||||||
let dialogObserver = null;
|
let dialogObserver = null;
|
||||||
let refreshPromise = null;
|
|
||||||
|
|
||||||
// -------- Cache (chrome.storage.local) --------
|
// -------- Cache (chrome.storage.local) --------
|
||||||
// chrome.storage serializa con JSON: los Date salen como strings ISO. Al
|
// chrome.storage serializa con JSON: los Date salen como strings ISO. Al
|
||||||
@@ -732,15 +737,6 @@
|
|||||||
return (Date.now() - new Date(scrapedAt).getTime()) / 60000;
|
return (Date.now() - new Date(scrapedAt).getTime()) / 60000;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatAge(min) {
|
|
||||||
if (!isFinite(min)) return 'sin datos';
|
|
||||||
if (min < 1) return 'ahora';
|
|
||||||
if (min < 60) return `hace ${Math.floor(min)} min`;
|
|
||||||
const h = Math.floor(min / 60);
|
|
||||||
const m = Math.floor(min % 60);
|
|
||||||
return `hace ${h}h ${m}m`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------- Detección del modal de Uso --------
|
// -------- Detección del modal de Uso --------
|
||||||
function findUsageDialog() {
|
function findUsageDialog() {
|
||||||
const dialogs = document.querySelectorAll('[role="dialog"]');
|
const dialogs = document.querySelectorAll('[role="dialog"]');
|
||||||
@@ -885,221 +881,44 @@
|
|||||||
else fab.classList.remove('claude-usage-tracker-fab--hidden');
|
else fab.classList.remove('claude-usage-tracker-fab--hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Click en el FAB: abrir el modal de Uso de Claude. Intenta varios métodos
|
||||||
|
// por si el router no escucha hashchange (Next.js puede colgar de popstate o
|
||||||
|
// de clicks en sus propios links). El usuario se conforma con ver el panel
|
||||||
|
// nativo, así que no abrimos nada propio.
|
||||||
async function onFabClick() {
|
async function onFabClick() {
|
||||||
try {
|
try {
|
||||||
const cache = await loadCache();
|
if (isUsageDialogOpen()) return;
|
||||||
openOverlayPanel(cache);
|
|
||||||
const ageMin = cache ? cacheAgeMin(cache.scrapedAt) : Infinity;
|
|
||||||
if (ageMin > CACHE_TTL_MS / 60000) {
|
|
||||||
refreshInBackground('overlay-stale');
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error('[Claude Usage Tracker] FAB click error:', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------- Overlay propio --------
|
// Método 1: setear hash
|
||||||
function openOverlayPanel(cache) {
|
if (location.hash !== '#settings/usage') {
|
||||||
try {
|
location.hash = '#settings/usage';
|
||||||
closeOverlayPanel();
|
|
||||||
const overlay = document.createElement('div');
|
|
||||||
overlay.id = OVERLAY_ID;
|
|
||||||
overlay.className = 'claude-usage-tracker-overlay';
|
|
||||||
overlay.addEventListener('click', e => {
|
|
||||||
if (e.target === overlay) closeOverlayPanel();
|
|
||||||
});
|
|
||||||
|
|
||||||
const panel = document.createElement('div');
|
|
||||||
panel.className = 'claude-usage-tracker-overlay-panel';
|
|
||||||
|
|
||||||
const header = document.createElement('div');
|
|
||||||
header.className = 'claude-usage-tracker-overlay-header';
|
|
||||||
const ageMin = cache ? cacheAgeMin(cache.scrapedAt) : Infinity;
|
|
||||||
header.innerHTML = `
|
|
||||||
<span class="claude-usage-tracker-overlay-age">${formatAge(ageMin)}</span>
|
|
||||||
<div class="claude-usage-tracker-overlay-actions">
|
|
||||||
<button class="claude-usage-tracker-overlay-refresh" title="Refrescar ahora">↻ Refrescar</button>
|
|
||||||
<button class="claude-usage-tracker-overlay-close" title="Cerrar">✕</button>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
header.querySelector('.claude-usage-tracker-overlay-close').addEventListener('click', closeOverlayPanel);
|
|
||||||
header.querySelector('.claude-usage-tracker-overlay-refresh').addEventListener('click', () => refreshInBackground('overlay-manual'));
|
|
||||||
|
|
||||||
const body = document.createElement('div');
|
|
||||||
body.className = 'claude-usage-tracker-overlay-body';
|
|
||||||
|
|
||||||
if (cache && cache.pageData) {
|
|
||||||
body.appendChild(createWeeklyTracker(cache.pageData, cache.dailyData));
|
|
||||||
} else {
|
|
||||||
body.innerHTML = '<div class="claude-usage-tracker-overlay-empty">Sin datos aún. Refrescando…</div>';
|
|
||||||
setTimeout(() => refreshInBackground('overlay-empty'), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
panel.appendChild(header);
|
|
||||||
panel.appendChild(body);
|
|
||||||
overlay.appendChild(panel);
|
|
||||||
document.body.appendChild(overlay);
|
|
||||||
|
|
||||||
document.addEventListener('keydown', overlayEscapeHandler);
|
|
||||||
} catch (e) {
|
|
||||||
console.error('[Claude Usage Tracker] overlay error:', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function overlayEscapeHandler(e) {
|
|
||||||
if (e.key === 'Escape') closeOverlayPanel();
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeOverlayPanel() {
|
|
||||||
const ov = document.getElementById(OVERLAY_ID);
|
|
||||||
if (ov) ov.remove();
|
|
||||||
document.removeEventListener('keydown', overlayEscapeHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setOverlaySpinner(active) {
|
|
||||||
const ov = document.getElementById(OVERLAY_ID);
|
|
||||||
if (!ov) return;
|
|
||||||
let spinner = ov.querySelector('.claude-usage-tracker-overlay-spinner');
|
|
||||||
if (active && !spinner) {
|
|
||||||
spinner = document.createElement('span');
|
|
||||||
spinner.className = 'claude-usage-tracker-overlay-spinner';
|
|
||||||
spinner.textContent = '⟳ actualizando…';
|
|
||||||
const header = ov.querySelector('.claude-usage-tracker-overlay-header');
|
|
||||||
if (header) header.appendChild(spinner);
|
|
||||||
} else if (!active && spinner) {
|
|
||||||
spinner.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderOverlayWithCache(cache) {
|
|
||||||
const ov = document.getElementById(OVERLAY_ID);
|
|
||||||
if (!ov) return;
|
|
||||||
const body = ov.querySelector('.claude-usage-tracker-overlay-body');
|
|
||||||
const age = ov.querySelector('.claude-usage-tracker-overlay-age');
|
|
||||||
if (body) {
|
|
||||||
body.innerHTML = '';
|
|
||||||
if (cache && cache.pageData) {
|
|
||||||
body.appendChild(createWeeklyTracker(cache.pageData, cache.dailyData));
|
|
||||||
} else {
|
} else {
|
||||||
body.innerHTML = '<div class="claude-usage-tracker-overlay-empty">No he podido cargar los datos. Abre Uso manualmente.</div>';
|
// ya estaba seteado pero el modal no está abierto: limpiar primero
|
||||||
|
location.hash = '';
|
||||||
|
await new Promise(r => setTimeout(r, 100));
|
||||||
|
location.hash = '#settings/usage';
|
||||||
}
|
}
|
||||||
}
|
await new Promise(r => setTimeout(r, 600));
|
||||||
if (age && cache) age.textContent = formatAge(cacheAgeMin(cache.scrapedAt));
|
if (isUsageDialogOpen()) return;
|
||||||
}
|
|
||||||
|
|
||||||
function showOverlayError(msg) {
|
// Método 2: pushState + popstate
|
||||||
const ov = document.getElementById(OVERLAY_ID);
|
history.pushState(null, '', '#settings/usage');
|
||||||
if (!ov) return;
|
window.dispatchEvent(new PopStateEvent('popstate'));
|
||||||
const body = ov.querySelector('.claude-usage-tracker-overlay-body');
|
await new Promise(r => setTimeout(r, 600));
|
||||||
const hasTracker = body && body.querySelector('.claude-usage-tracker-container');
|
if (isUsageDialogOpen()) return;
|
||||||
if (hasTracker) {
|
|
||||||
// No destruir el tracker visible — mostrar aviso temporal en el header
|
|
||||||
const header = ov.querySelector('.claude-usage-tracker-overlay-header');
|
|
||||||
if (header) {
|
|
||||||
const existing = header.querySelector('.claude-usage-tracker-overlay-notice');
|
|
||||||
if (existing) existing.remove();
|
|
||||||
const notice = document.createElement('span');
|
|
||||||
notice.className = 'claude-usage-tracker-overlay-notice';
|
|
||||||
notice.textContent = msg;
|
|
||||||
header.appendChild(notice);
|
|
||||||
setTimeout(() => { if (notice.parentNode) notice.remove(); }, 7000);
|
|
||||||
}
|
|
||||||
} else if (body) {
|
|
||||||
body.textContent = '';
|
|
||||||
const empty = document.createElement('div');
|
|
||||||
empty.className = 'claude-usage-tracker-overlay-empty';
|
|
||||||
empty.textContent = msg;
|
|
||||||
body.appendChild(empty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------- Refresh: abrir modal en background, scrapear, cerrar --------
|
// Método 3: clickar el enlace "Uso" si está visible
|
||||||
function waitForDialogWithData(timeoutMs) {
|
const usoBtn = [...document.querySelectorAll('a, button')]
|
||||||
return new Promise(resolve => {
|
.find(el => (el.innerText || '').trim() === 'Uso' && el.offsetParent !== null);
|
||||||
const t0 = Date.now();
|
if (usoBtn) {
|
||||||
const check = () => {
|
usoBtn.click();
|
||||||
const d = findUsageDialog();
|
|
||||||
if (d && dialogHasData(d)) return resolve(d);
|
|
||||||
if (Date.now() - t0 > timeoutMs) return resolve(null);
|
|
||||||
setTimeout(check, 80);
|
|
||||||
};
|
|
||||||
check();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function tryOpenViaPushState() {
|
|
||||||
history.pushState(null, '', '#settings/usage');
|
|
||||||
window.dispatchEvent(new PopStateEvent('popstate'));
|
|
||||||
return waitForDialogWithData(700);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function tryOpenViaHash() {
|
|
||||||
location.hash = '#settings/usage';
|
|
||||||
return waitForDialogWithData(700);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function tryOpenViaClick() {
|
|
||||||
const candidates = [...document.querySelectorAll('a, button')]
|
|
||||||
.filter(el => (el.innerText || '').trim() === 'Uso');
|
|
||||||
if (candidates.length === 0) return null;
|
|
||||||
candidates[0].click();
|
|
||||||
return waitForDialogWithData(1500);
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeUsageModal() {
|
|
||||||
const dialog = findUsageDialog();
|
|
||||||
if (!dialog) return;
|
|
||||||
const closeBtn = [...dialog.querySelectorAll('button')]
|
|
||||||
.find(b => /close|cerrar/i.test(b.getAttribute('aria-label') || ''));
|
|
||||||
if (closeBtn) { closeBtn.click(); return; }
|
|
||||||
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true, cancelable: true }));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function refreshInBackground(reason) {
|
|
||||||
if (refreshPromise) return refreshPromise;
|
|
||||||
refreshPromise = (async () => {
|
|
||||||
console.log('[Claude Usage Tracker] refresh:', reason);
|
|
||||||
setOverlaySpinner(true);
|
|
||||||
|
|
||||||
const previousHash = location.hash;
|
|
||||||
const wasOpen = isUsageDialogOpen();
|
|
||||||
|
|
||||||
let dialog = wasOpen ? findUsageDialog() : null;
|
|
||||||
if (!dialog) dialog = await tryOpenViaPushState();
|
|
||||||
if (!dialog) dialog = await tryOpenViaHash();
|
|
||||||
if (!dialog) dialog = await tryOpenViaClick();
|
|
||||||
|
|
||||||
if (!dialog) {
|
|
||||||
console.warn('[Claude Usage Tracker] no he podido abrir el modal automáticamente');
|
|
||||||
setOverlaySpinner(false);
|
|
||||||
showOverlayError('No he podido refrescar automáticamente — abre Uso manualmente y vuelve.');
|
|
||||||
refreshPromise = null;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pageData = parsePageData();
|
console.warn('[Claude Usage Tracker] No he podido abrir el modal de Uso. Ábrelo manualmente desde el avatar.');
|
||||||
let cache = null;
|
} catch (e) {
|
||||||
if (pageData.weeklyUsage > 0 || pageData.resetDayIndex >= 0) {
|
console.error('[Claude Usage Tracker] FAB click error:', e);
|
||||||
initSession();
|
}
|
||||||
const dailyData = calculateDailyUsage(pageData);
|
|
||||||
saveCache(pageData, dailyData, reason === 'overlay-manual' ? 'manual' : 'auto');
|
|
||||||
cache = { pageData, dailyData, scrapedAt: new Date().toISOString() };
|
|
||||||
updateFabState(cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cerrar modal solo si nosotros lo abrimos
|
|
||||||
if (!wasOpen) {
|
|
||||||
closeUsageModal();
|
|
||||||
if (location.hash !== previousHash) {
|
|
||||||
history.replaceState(null, '', location.pathname + location.search + previousHash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setOverlaySpinner(false);
|
|
||||||
renderOverlayWithCache(cache);
|
|
||||||
refreshPromise = null;
|
|
||||||
})();
|
|
||||||
return refreshPromise;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- Bootstrap --------
|
// -------- Bootstrap --------
|
||||||
@@ -1128,30 +947,6 @@
|
|||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exposición para depuración manual desde la consola
|
|
||||||
window.__claudeUsageTracker = {
|
|
||||||
version: 'debug-fab-click',
|
|
||||||
loadCache,
|
|
||||||
saveCache,
|
|
||||||
openOverlayPanel,
|
|
||||||
closeOverlayPanel,
|
|
||||||
refreshInBackground,
|
|
||||||
findUsageDialog,
|
|
||||||
isUsageDialogOpen,
|
|
||||||
parsePageData,
|
|
||||||
injectFloatingButton,
|
|
||||||
updateFabState,
|
|
||||||
fabExists: () => !!document.getElementById(FAB_ID),
|
|
||||||
overlayExists: () => !!document.getElementById(OVERLAY_ID),
|
|
||||||
forceShowOverlay: async () => {
|
|
||||||
const cache = await loadCache();
|
|
||||||
console.log('[CUT-DIAG forceShowOverlay] cache:', cache);
|
|
||||||
openOverlayPanel(cache);
|
|
||||||
return !!document.getElementById(OVERLAY_ID);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
console.log('[CUT-DIAG] window.__claudeUsageTracker expuesto. Métodos:', Object.keys(window.__claudeUsageTracker).join(', '));
|
|
||||||
|
|
||||||
if (document.readyState === 'loading') {
|
if (document.readyState === 'loading') {
|
||||||
document.addEventListener('DOMContentLoaded', bootstrap);
|
document.addEventListener('DOMContentLoaded', bootstrap);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
129
styles.css
129
styles.css
@@ -576,126 +576,31 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ===========================================================================
|
/* ===========================================================================
|
||||||
Overlay propio — abierto al click del FAB
|
Resumen — hora del próximo reinicio de sesión
|
||||||
=========================================================================== */
|
=========================================================================== */
|
||||||
.claude-usage-tracker-overlay {
|
.session-reset-info {
|
||||||
position: fixed;
|
|
||||||
inset: 0;
|
|
||||||
z-index: 999999;
|
|
||||||
background: rgba(0, 0, 0, 0.55);
|
|
||||||
backdrop-filter: blur(4px);
|
|
||||||
-webkit-backdrop-filter: blur(4px);
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 60px 16px 40px;
|
|
||||||
overflow-y: auto;
|
|
||||||
animation: claude-tracker-fade-in 0.15s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes claude-tracker-fade-in {
|
|
||||||
from { opacity: 0; }
|
|
||||||
to { opacity: 1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.claude-usage-tracker-overlay-panel {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 720px;
|
|
||||||
background: #1a1a1d;
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
||||||
border-radius: 14px;
|
|
||||||
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6);
|
|
||||||
padding: 16px 20px 20px;
|
|
||||||
color: #f5f5f5;
|
|
||||||
font-family: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.claude-usage-tracker-overlay-header {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
gap: 12px;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
padding-bottom: 12px;
|
|
||||||
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.claude-usage-tracker-overlay-age {
|
|
||||||
font-size: 12px;
|
|
||||||
color: var(--text-400, #a3a3a3);
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.claude-usage-tracker-overlay-actions {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin-left: auto;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.claude-usage-tracker-overlay-refresh,
|
|
||||||
.claude-usage-tracker-overlay-close {
|
|
||||||
background: rgba(255, 255, 255, 0.06);
|
|
||||||
color: #f5f5f5;
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 6px 12px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
font-family: inherit;
|
|
||||||
transition: background 0.15s ease, border-color 0.15s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.claude-usage-tracker-overlay-refresh:hover,
|
|
||||||
.claude-usage-tracker-overlay-close:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.12);
|
|
||||||
border-color: rgba(255, 255, 255, 0.22);
|
|
||||||
}
|
|
||||||
|
|
||||||
.claude-usage-tracker-overlay-close {
|
|
||||||
padding: 6px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.claude-usage-tracker-overlay-spinner {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #06b6d4;
|
|
||||||
font-style: italic;
|
|
||||||
margin-left: 8px;
|
|
||||||
animation: claude-tracker-spin-pulse 1.2s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.claude-usage-tracker-overlay-notice {
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
padding: 6px 10px;
|
padding: 10px 14px;
|
||||||
background: rgba(245, 158, 11, 0.12);
|
background: rgba(59, 130, 246, 0.1);
|
||||||
border: 1px solid rgba(245, 158, 11, 0.35);
|
border: 1px solid rgba(59, 130, 246, 0.3);
|
||||||
border-radius: 6px;
|
border-radius: 8px;
|
||||||
font-size: 12px;
|
font-size: 13px;
|
||||||
color: #f59e0b;
|
|
||||||
animation: claude-tracker-fade-in 0.2s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes claude-tracker-spin-pulse {
|
.session-reset-info-label {
|
||||||
0%, 100% { opacity: 0.6; }
|
|
||||||
50% { opacity: 1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.claude-usage-tracker-overlay-body {
|
|
||||||
min-height: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.claude-usage-tracker-overlay-empty {
|
|
||||||
padding: 40px 16px;
|
|
||||||
text-align: center;
|
|
||||||
color: var(--text-300, #a3a3a3);
|
color: var(--text-300, #a3a3a3);
|
||||||
font-size: 14px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cuando el tracker se inyecta dentro de nuestro overlay, ya está dentro de un
|
.session-reset-info-time {
|
||||||
contenedor con padding/borde; quitamos su margen superior para que pegue. */
|
font-weight: 600;
|
||||||
.claude-usage-tracker-overlay-body .claude-usage-tracker-container {
|
color: var(--text-100, #f5f5f5);
|
||||||
margin-top: 0;
|
}
|
||||||
|
|
||||||
|
.session-reset-info-remaining {
|
||||||
|
color: var(--text-200, #d4d4d4);
|
||||||
|
font-weight: 500;
|
||||||
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user