UI: migrate remaining compact button families to the .btn--sm tier

Continue the design-system unification (kettui UI-consistency item):
migrate the five remaining compact button families onto the shared
.btn .btn--sm primitive + color modifiers, and drop their bespoke base
CSS (net -125 lines of CSS).

- ya-header-btn (Your Albums/Artists, discover.js-injected) -> .btn .btn--sm
  .btn--secondary; ya-refresh/ya-settings/ya-viewall co-modifiers kept.
- explorer-action-btn (Playlist Explorer) -> .btn--secondary / .btn--primary.
- repair-bulk-btn -> .btn--secondary / .btn--primary / .btn--warning (fix-all).
- enhanced-bulk-btn (Library bulk bar, library.js-injected) -> .btn--primary/
  --secondary/--danger; class kept as a hook for the mobile.css size
  override + the .tag-write / .rg-analyze special colors.
- profile-create-btn (init.js-injected) -> .btn .btn--block .btn--primary;
  class kept for the scoped .profile-edit-buttons flex:1 rule.

mini-nav-btn deliberately left as a distinct icon-button archetype.
This commit is contained in:
BoulderBadgeDad 2026-05-29 11:40:31 -07:00
parent 169c30fd5b
commit 9b34d06b6d
5 changed files with 51 additions and 176 deletions

View file

@ -136,13 +136,13 @@
<input type="checkbox" id="new-profile-can-download" checked> Can download music
</label>
</div>
<button id="create-profile-btn" class="profile-create-btn">Create Profile</button>
<button id="create-profile-btn" class="btn btn--block btn--primary profile-create-btn">Create Profile</button>
</div>
<div id="admin-pin-section" class="admin-pin-section" style="display: none;">
<h4>Admin PIN</h4>
<p class="admin-pin-note">Required when multiple profiles exist</p>
<input type="password" id="admin-pin-input" class="profile-input" placeholder="Set admin PIN" maxlength="6">
<button id="set-admin-pin-btn" class="profile-create-btn">Set Admin PIN</button>
<button id="set-admin-pin-btn" class="btn btn--block btn--primary profile-create-btn">Set Admin PIN</button>
</div>
</div>
</div>
@ -2761,8 +2761,8 @@
<!-- Populated dynamically -->
</div>
<div class="enhanced-bulk-modal-footer">
<button class="enhanced-bulk-btn secondary" onclick="closeBulkEditModal()">Cancel</button>
<button class="enhanced-bulk-btn primary" onclick="executeBulkEdit()">Apply Changes</button>
<button class="btn btn--sm btn--secondary enhanced-bulk-btn" onclick="closeBulkEditModal()">Cancel</button>
<button class="btn btn--sm btn--primary enhanced-bulk-btn" onclick="executeBulkEdit()">Apply Changes</button>
</div>
</div>
</div>
@ -2774,10 +2774,10 @@
<span class="enhanced-bulk-bar-label">tracks selected</span>
</div>
<div class="enhanced-bulk-bar-actions">
<button class="enhanced-bulk-btn secondary" onclick="showBulkEditModal()">Edit Selected</button>
<button class="enhanced-bulk-btn tag-write" onclick="batchWriteTagsSelected()">Write Tags</button>
<button class="enhanced-bulk-btn rg-analyze" onclick="batchAnalyzeReplayGainSelected()">ReplayGain</button>
<button class="enhanced-bulk-btn clear" onclick="clearTrackSelection()">Clear Selection</button>
<button class="btn btn--sm btn--secondary enhanced-bulk-btn" onclick="showBulkEditModal()">Edit Selected</button>
<button class="btn btn--sm btn--secondary enhanced-bulk-btn tag-write" onclick="batchWriteTagsSelected()">Write Tags</button>
<button class="btn btn--sm btn--secondary enhanced-bulk-btn rg-analyze" onclick="batchAnalyzeReplayGainSelected()">ReplayGain</button>
<button class="btn btn--sm btn--danger enhanced-bulk-btn" onclick="clearTrackSelection()">Clear Selection</button>
</div>
</div>
@ -2801,8 +2801,8 @@
<span id="tag-preview-sync-text">Sync to server</span>
</label>
<div class="tag-preview-footer-actions">
<button class="enhanced-bulk-btn secondary" onclick="closeTagPreviewModal()">Cancel</button>
<button class="enhanced-bulk-btn primary" id="tag-preview-write-btn" onclick="executeWriteTags()">Write Tags</button>
<button class="btn btn--sm btn--secondary enhanced-bulk-btn" onclick="closeTagPreviewModal()">Cancel</button>
<button class="btn btn--sm btn--primary enhanced-bulk-btn" id="tag-preview-write-btn" onclick="executeWriteTags()">Write Tags</button>
</div>
</div>
</div>
@ -2829,8 +2829,8 @@
<span id="batch-tag-preview-sync-text">Sync to server</span>
</label>
<div class="tag-preview-footer-actions">
<button class="enhanced-bulk-btn secondary" onclick="closeBatchTagPreviewModal()">Cancel</button>
<button class="enhanced-bulk-btn primary" id="batch-tag-preview-write-btn" onclick="executeBatchWriteTags()">Write Tags</button>
<button class="btn btn--sm btn--secondary enhanced-bulk-btn" onclick="closeBatchTagPreviewModal()">Cancel</button>
<button class="btn btn--sm btn--primary enhanced-bulk-btn" id="batch-tag-preview-write-btn" onclick="executeBatchWriteTags()">Write Tags</button>
</div>
</div>
</div>
@ -2847,8 +2847,8 @@
<!-- Populated dynamically -->
</div>
<div class="enhanced-bulk-modal-footer" id="reorganize-modal-footer">
<button class="enhanced-bulk-btn secondary" onclick="closeReorganizeModal()">Cancel</button>
<button class="enhanced-bulk-btn primary" id="reorganize-apply-btn" onclick="executeReorganize()" disabled>Apply</button>
<button class="btn btn--sm btn--secondary enhanced-bulk-btn" onclick="closeReorganizeModal()">Cancel</button>
<button class="btn btn--sm btn--primary enhanced-bulk-btn" id="reorganize-apply-btn" onclick="executeReorganize()" disabled>Apply</button>
</div>
</div>
</div>
@ -3043,13 +3043,13 @@
<p class="discover-section-subtitle" id="your-artists-subtitle">Artists you follow across your music services</p>
</div>
<div class="discover-section-actions">
<button class="ya-header-btn ya-refresh-btn" id="your-artists-refresh-btn" onclick="refreshYourArtists()" title="Refresh from services">
<button class="btn btn--sm btn--secondary ya-header-btn ya-refresh-btn" id="your-artists-refresh-btn" onclick="refreshYourArtists()" title="Refresh from services">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M23 4v6h-6"/><path d="M1 20v-6h6"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg>
</button>
<button class="ya-header-btn ya-settings-btn" onclick="openYourArtistsSourcesModal()" title="Configure sources">
<button class="btn btn--sm btn--secondary ya-header-btn ya-settings-btn" onclick="openYourArtistsSourcesModal()" title="Configure sources">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
</button>
<button class="ya-header-btn ya-viewall-btn" onclick="openYourArtistsModal()">
<button class="btn btn--sm btn--secondary ya-header-btn ya-viewall-btn" onclick="openYourArtistsModal()">
<span>View All</span>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M5 12h14"/><path d="M12 5l7 7-7 7"/></svg>
</button>
@ -3068,13 +3068,13 @@
<p class="discover-section-subtitle" id="your-albums-subtitle">Albums you've saved across your music services</p>
</div>
<div class="discover-section-actions">
<button class="ya-header-btn ya-refresh-btn" id="your-albums-refresh-btn" onclick="refreshYourAlbums()" title="Refresh from services">
<button class="btn btn--sm btn--secondary ya-header-btn ya-refresh-btn" id="your-albums-refresh-btn" onclick="refreshYourAlbums()" title="Refresh from services">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M23 4v6h-6"/><path d="M1 20v-6h6"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg>
</button>
<button class="ya-header-btn ya-settings-btn" onclick="openYourAlbumsSourcesModal()" title="Configure sources">
<button class="btn btn--sm btn--secondary ya-header-btn ya-settings-btn" onclick="openYourAlbumsSourcesModal()" title="Configure sources">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
</button>
<button class="ya-header-btn" id="your-albums-download-btn" onclick="downloadMissingYourAlbums()" style="display:none;" title="Download missing albums">
<button class="btn btn--sm btn--secondary ya-header-btn" id="your-albums-download-btn" onclick="downloadMissingYourAlbums()" style="display:none;" title="Download missing albums">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3"/></svg>
</button>
</div>
@ -3679,15 +3679,15 @@
<span class="explorer-selection-count" id="explorer-selection-count">0 albums selected</span>
</div>
<div class="explorer-action-buttons">
<button class="explorer-action-btn" onclick="explorerSelectAll()">
<button class="btn btn--sm btn--secondary" onclick="explorerSelectAll()">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 11 12 14 22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>
Select All
</button>
<button class="explorer-action-btn" onclick="explorerDeselectAll()">
<button class="btn btn--sm btn--secondary" onclick="explorerDeselectAll()">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><rect x="3" y="3" width="18" height="18" rx="2"/></svg>
Deselect
</button>
<button class="explorer-action-btn primary" onclick="explorerAddToWishlist()">
<button class="btn btn--sm btn--primary" onclick="explorerAddToWishlist()">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>
Add to Wishlist
</button>
@ -6395,9 +6395,9 @@
</label>
<div class="repair-findings-bulk" id="repair-findings-bulk" style="display:none;">
<span class="repair-bulk-count" id="repair-bulk-count"></span>
<button class="repair-bulk-btn fix" onclick="bulkFixFindings()">Fix Selected</button>
<button class="repair-bulk-btn" onclick="bulkRepairAction('dismiss')">Dismiss Selected</button>
<button class="repair-bulk-btn fix-all" id="repair-fix-all-btn" style="display:none;" onclick="fixAllMatchingFindings()">Fix All</button>
<button class="btn btn--sm btn--primary" onclick="bulkFixFindings()">Fix Selected</button>
<button class="btn btn--sm btn--secondary" onclick="bulkRepairAction('dismiss')">Dismiss Selected</button>
<button class="btn btn--sm btn--warning" id="repair-fix-all-btn" style="display:none;" onclick="fixAllMatchingFindings()">Fix All</button>
</div>
<button class="repair-clear-btn" onclick="clearRepairFindings()" title="Clear findings matching current filters">Clear Findings</button>
</div>

View file

@ -4654,15 +4654,15 @@ async function openYourArtistInfoModal(poolId) {
// Footer
if (footerEl) {
const watchBtn = pool.on_watchlist
? `<button class="ya-header-btn" onclick="toggleYourArtistWatchlist(${pool.id}, '${escapeForInlineJs(artistName)}', '${escapeForInlineJs(artistId)}', '${escapeForInlineJs(pool.active_source || '')}', this); this.textContent='Done'; this.disabled=true">Remove from Watchlist</button>`
: `<button class="ya-header-btn" onclick="toggleYourArtistWatchlist(${pool.id}, '${escapeForInlineJs(artistName)}', '${escapeForInlineJs(artistId)}', '${escapeForInlineJs(pool.active_source || '')}', this); this.textContent='Added!'; this.disabled=true">Add to Watchlist</button>`;
? `<button class="btn btn--sm btn--secondary ya-header-btn" onclick="toggleYourArtistWatchlist(${pool.id}, '${escapeForInlineJs(artistName)}', '${escapeForInlineJs(artistId)}', '${escapeForInlineJs(pool.active_source || '')}', this); this.textContent='Done'; this.disabled=true">Remove from Watchlist</button>`
: `<button class="btn btn--sm btn--secondary ya-header-btn" onclick="toggleYourArtistWatchlist(${pool.id}, '${escapeForInlineJs(artistName)}', '${escapeForInlineJs(artistId)}', '${escapeForInlineJs(pool.active_source || '')}', this); this.textContent='Added!'; this.disabled=true">Add to Watchlist</button>`;
footerEl.innerHTML = `
${watchBtn}
<button class="ya-header-btn" onclick="document.getElementById('ya-info-modal-overlay')?.remove(); document.getElementById('your-artists-modal-overlay')?.remove(); openArtistMapExplorerDirect('${escapeForInlineJs(artistName)}')">
<button class="btn btn--sm btn--secondary ya-header-btn" onclick="document.getElementById('ya-info-modal-overlay')?.remove(); document.getElementById('your-artists-modal-overlay')?.remove(); openArtistMapExplorerDirect('${escapeForInlineJs(artistName)}')">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<span>Explore</span>
</button>
<a class="ya-header-btn ya-viewall-btn" href="${buildArtistDetailPath(artistId, pool.active_source || null)}" onclick="document.getElementById('ya-info-modal-overlay')?.remove(); document.getElementById('your-artists-modal-overlay')?.remove();" style="text-decoration:none;color:inherit;">
<a class="btn btn--sm btn--secondary ya-header-btn ya-viewall-btn" href="${buildArtistDetailPath(artistId, pool.active_source || null)}" onclick="document.getElementById('ya-info-modal-overlay')?.remove(); document.getElementById('your-artists-modal-overlay')?.remove();" style="text-decoration:none;color:inherit;">
<span>View Discography</span>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M5 12h14"/><path d="M12 5l7 7-7 7"/></svg>
</a>
@ -6436,8 +6436,8 @@ function _showArtistMapSearchPrompt() {
</div>
<input type="text" id="artmap-explore-input" class="artmap-explore-input" placeholder="Artist name..." autofocus>
<div class="artmap-search-prompt-actions">
<button class="ya-header-btn" onclick="document.getElementById('artmap-search-prompt').remove()">Cancel</button>
<button class="ya-header-btn ya-viewall-btn" id="artmap-explore-go">
<button class="btn btn--sm btn--secondary ya-header-btn" onclick="document.getElementById('artmap-search-prompt').remove()">Cancel</button>
<button class="btn btn--sm btn--secondary ya-header-btn ya-viewall-btn" id="artmap-explore-go">
<span>Explore</span>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M5 12h14"/><path d="M12 5l7 7-7 7"/></svg>
</button>

View file

@ -1829,7 +1829,7 @@ function showProfileEditForm(profileId, currentName, currentColor, currentAvatar
btnRow.className = 'profile-edit-buttons';
const saveBtn = document.createElement('button');
saveBtn.className = 'profile-create-btn';
saveBtn.className = 'btn btn--block btn--primary profile-create-btn';
saveBtn.textContent = 'Save';
saveBtn.onclick = async () => {
const newName = nameInput.value.trim();
@ -1957,7 +1957,7 @@ function showSelfEditForm() {
btnRow.style.marginTop = '12px';
const saveBtn = document.createElement('button');
saveBtn.className = 'profile-create-btn';
saveBtn.className = 'btn btn--block btn--primary profile-create-btn';
saveBtn.textContent = 'Save';
saveBtn.onclick = async () => {
const newName = nameInput.value.trim();

View file

@ -6395,8 +6395,8 @@ function openHaveMissingTrackModal(track, album) {
<div class="enhanced-have-import-detail">Waiting to start.</div>
</div>
<div class="enhanced-bulk-modal-footer">
<button class="enhanced-bulk-btn secondary" type="button" id="enhanced-have-cancel">Cancel</button>
<button class="enhanced-bulk-btn primary" type="button" id="enhanced-have-confirm" disabled>Import Track</button>
<button class="btn btn--sm btn--secondary enhanced-bulk-btn" type="button" id="enhanced-have-cancel">Cancel</button>
<button class="btn btn--sm btn--primary enhanced-bulk-btn" type="button" id="enhanced-have-confirm" disabled>Import Track</button>
</div>
`;
overlay.appendChild(modal);

View file

@ -34318,13 +34318,9 @@ div.artist-hero-badge {
.ya-watchlist-btn.active { color: var(--accent); border-color: rgba(var(--accent-rgb),0.3); background: rgba(var(--accent-rgb),0.15); }
/* Your Artists header buttons */
.ya-header-btn {
display: flex; align-items: center; gap: 6px;
padding: 7px 14px; border-radius: 10px; font-size: 12px; font-weight: 600;
cursor: pointer; transition: all 0.2s; border: 1px solid rgba(255,255,255,0.08);
background: rgba(255,255,255,0.04); color: rgba(255,255,255,0.5);
}
.ya-header-btn:hover { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.8); border-color: rgba(255,255,255,0.12); }
/* .ya-header-btn base styling migrated to .btn .btn--sm .btn--secondary.
Class kept on the markup (discover.js injects it) along with the
.ya-refresh-btn / .ya-settings-btn / .ya-viewall-btn co-modifiers. */
.ya-refresh-btn { padding: 7px 10px; }
.ya-refresh-btn:hover svg { transform: rotate(45deg); }
.ya-refresh-btn svg { transition: transform 0.3s; }
@ -43230,22 +43226,9 @@ div.artist-hero-badge {
border-color: #fff;
}
.profile-create-btn {
width: 100%;
padding: 10px;
background: #6366f1;
color: #fff;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: background 0.2s;
}
.profile-create-btn:hover {
background: #4f46e5;
}
/* .profile-create-btn migrated to .btn .btn--block .btn--primary. The class
is kept on the markup (init.js sets it) as a hook for the scoped
`.profile-edit-buttons .profile-create-btn { flex: 1 }` layout rule. */
.admin-pin-section {
margin-top: 20px;
@ -46445,36 +46428,11 @@ textarea.enhanced-meta-field-input {
display: flex;
gap: 8px;
}
.enhanced-bulk-btn {
padding: 8px 16px;
border: none;
border-radius: 8px;
font-size: 12px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
}
.enhanced-bulk-btn.primary {
background: rgb(var(--accent-rgb));
color: #ffffff;
}
.enhanced-bulk-btn.primary:hover {
background: rgb(var(--accent-light-rgb));
}
.enhanced-bulk-btn.secondary {
background: rgba(255,255,255,0.1);
color: rgba(255,255,255,0.8);
}
.enhanced-bulk-btn.secondary:hover {
background: rgba(255,255,255,0.15);
}
.enhanced-bulk-btn.clear {
background: rgba(255, 65, 54, 0.1);
color: #ff4136;
}
.enhanced-bulk-btn.clear:hover {
background: rgba(255, 65, 54, 0.2);
}
/* .enhanced-bulk-btn base + .primary/.secondary/.clear migrated to
.btn .btn--sm (.btn--primary / .btn--secondary / .btn--danger). The
.enhanced-bulk-btn class is kept on the markup as a hook for the mobile
size override (.enhanced-bulk-bar .enhanced-bulk-btn) and the special
.tag-write / .rg-analyze color variants below. */
/* Bulk Edit Modal */
.enhanced-bulk-modal {
@ -52329,42 +52287,8 @@ tr.tag-diff-same {
margin-right: 4px;
}
.repair-bulk-btn {
background: rgba(255, 255, 255, 0.06);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 6px;
color: rgba(255, 255, 255, 0.7);
padding: 6px 14px;
font-size: 12px;
cursor: pointer;
transition: all 0.2s ease;
}
.repair-bulk-btn:hover {
background: rgba(255, 255, 255, 0.12);
color: #fff;
}
.repair-bulk-btn.fix {
background: rgba(var(--accent-rgb, 99, 102, 241), 0.12);
border-color: rgba(var(--accent-rgb, 99, 102, 241), 0.3);
color: rgb(var(--accent-light-rgb, 129, 140, 248));
font-weight: 600;
}
.repair-bulk-btn.fix:hover {
background: rgba(var(--accent-rgb, 99, 102, 241), 0.2);
}
.repair-bulk-btn.fix-all {
background: rgba(245, 158, 11, 0.12);
border-color: rgba(245, 158, 11, 0.3);
color: #fbbf24;
font-weight: 600;
}
.repair-bulk-btn.fix-all:hover {
background: rgba(245, 158, 11, 0.22);
}
/* .repair-bulk-btn / .fix / .fix-all migrated to .btn .btn--sm
(.btn--secondary / .btn--primary / .btn--warning). */
.repair-clear-btn {
margin-left: auto;
@ -54910,57 +54834,8 @@ tr.tag-diff-same {
gap: 6px;
}
.explorer-action-btn {
padding: 7px 14px;
font-size: 11px;
font-weight: 600;
color: rgba(255, 255, 255, 0.5);
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(255, 255, 255, 0.07);
border-radius: 8px;
cursor: pointer;
transition: all 0.2s;
letter-spacing: 0.2px;
display: flex;
align-items: center;
gap: 5px;
}
.explorer-action-btn svg { opacity: 0.5; }
.explorer-action-btn:hover {
background: rgba(255, 255, 255, 0.08);
color: rgba(255, 255, 255, 0.85);
border-color: rgba(255, 255, 255, 0.12);
}
.explorer-action-btn:hover svg { opacity: 0.8; }
.explorer-action-btn.primary {
background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 80%, #fff));
border-color: transparent;
color: #fff;
font-weight: 700;
padding: 8px 20px;
font-size: 12px;
position: relative;
overflow: hidden;
box-shadow: 0 2px 10px rgba(var(--accent-rgb), 0.2);
}
.explorer-action-btn.primary svg { opacity: 1; }
.explorer-action-btn.primary::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, transparent 50%);
border-radius: inherit;
pointer-events: none;
}
.explorer-action-btn.primary:hover {
box-shadow: 0 6px 22px rgba(var(--accent-rgb), 0.4);
filter: brightness(1.1);
transform: translateY(-1px);
}
/* .explorer-action-btn / .primary migrated to .btn .btn--sm
(.btn--secondary / .btn--primary). */
/* Viewport */
.explorer-viewport {