Merge pull request #5 from JulienMaille/main
UI Enhancements, Light Theme Support, and Miscellaneous Fixes
This commit is contained in:
commit
70c942e39b
7 changed files with 225 additions and 36 deletions
|
|
@ -47,7 +47,7 @@
|
|||
<div>
|
||||
<div class="sidebar-logo">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="14.75 14.75 70.5 70.5" >
|
||||
<g fill="white" >
|
||||
<g fill="currentColor" >
|
||||
<path d="M38.25 14.75H85.25V61.75H61.75V38.25H38.25ZM14.75 38.25H38.25V61.75H61.75V85.25H14.75Z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
@ -138,9 +138,9 @@
|
|||
<header class="detail-header">
|
||||
<img id="album-detail-image" src="" alt="" class="detail-header-image">
|
||||
<div class="detail-header-info">
|
||||
<div class="type">Album</div>
|
||||
<h1 class="title" id="album-detail-title"></h1>
|
||||
<div class="meta" id="album-detail-meta"></div>
|
||||
<div class="meta" id="album-detail-producer"></div>
|
||||
<div class="detail-header-actions">
|
||||
<button id="play-album-btn" class="btn-primary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||
|
|
@ -236,8 +236,10 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="theme-picker" id="theme-picker">
|
||||
<div class="theme-option" data-theme="monochrome">Black</div>
|
||||
<div class="theme-option" data-theme="system">System</div>
|
||||
<div class="theme-option" data-theme="light">Light</div>
|
||||
<div class="theme-option" data-theme="dark">Dark</div>
|
||||
<div class="theme-option" data-theme="monochrome">Black</div>
|
||||
<div class="theme-option" data-theme="ocean">Ocean</div>
|
||||
<div class="theme-option" data-theme="purple">Purple</div>
|
||||
<div class="theme-option" data-theme="forest">Forest</div>
|
||||
|
|
|
|||
14
js/api.js
14
js/api.js
|
|
@ -324,6 +324,20 @@ export class LosslessAPI {
|
|||
}
|
||||
}
|
||||
|
||||
// If album exists but has no releaseDate, try to extract from tracks
|
||||
if (album && !album.releaseDate && tracksSection?.items && tracksSection.items.length > 0) {
|
||||
const firstTrack = tracksSection.items[0];
|
||||
const track = firstTrack.item || firstTrack;
|
||||
|
||||
if (track) {
|
||||
if (track.album && track.album.releaseDate) {
|
||||
album = { ...album, releaseDate: track.album.releaseDate };
|
||||
} else if (track.streamStartDate) {
|
||||
album = { ...album, releaseDate: track.streamStartDate.split('T')[0] };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const tracks = (tracksSection?.items || []).map(i => this.prepareTrack(i.item || i));
|
||||
const result = { album, tracks };
|
||||
|
||||
|
|
|
|||
|
|
@ -207,10 +207,13 @@ export async function downloadAlbumAsZip(album, tracks, api, quality, lyricsMana
|
|||
const zip = new JSZip();
|
||||
|
||||
const template = localStorage.getItem('zip-folder-template') || '{albumTitle} - {albumArtist} - monochrome.tf';
|
||||
const releaseDate = album.releaseDate ? new Date(album.releaseDate) : null;
|
||||
const year = (releaseDate && !isNaN(releaseDate.getTime())) ? releaseDate.getFullYear() : '';
|
||||
|
||||
const folderName = formatTemplate(template, {
|
||||
albumTitle: album.title,
|
||||
albumArtist: album.artist?.name,
|
||||
year: new Date(album.releaseDate).getFullYear()
|
||||
year: year
|
||||
});
|
||||
|
||||
const notification = createBulkDownloadNotification('album', album.title, tracks.length);
|
||||
|
|
@ -380,10 +383,13 @@ export async function downloadDiscography(artist, api, quality, lyricsManager =
|
|||
|
||||
try {
|
||||
const { album: fullAlbum, tracks } = await api.getAlbum(album.id);
|
||||
const releaseDate = fullAlbum.releaseDate ? new Date(fullAlbum.releaseDate) : null;
|
||||
const year = (releaseDate && !isNaN(releaseDate.getTime())) ? releaseDate.getFullYear() : '';
|
||||
|
||||
const albumFolder = formatTemplate(template, {
|
||||
albumTitle: fullAlbum.title,
|
||||
albumArtist: fullAlbum.artist?.name,
|
||||
year: new Date(fullAlbum.releaseDate).getFullYear()
|
||||
year: year
|
||||
});
|
||||
|
||||
for (const track of tracks) {
|
||||
|
|
|
|||
47
js/events.js
47
js/events.js
|
|
@ -275,9 +275,7 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen
|
|||
contextTrack = trackDataStore.get(trackItem);
|
||||
if (contextTrack) {
|
||||
const rect = menuBtn.getBoundingClientRect();
|
||||
contextMenu.style.top = `${rect.bottom + 5}px`;
|
||||
contextMenu.style.left = `${rect.left}px`;
|
||||
contextMenu.style.display = 'block';
|
||||
positionMenu(contextMenu, rect.left, rect.bottom + 5, rect);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
@ -307,9 +305,7 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen
|
|||
contextTrack = trackDataStore.get(trackItem);
|
||||
|
||||
if (contextTrack) {
|
||||
contextMenu.style.top = `${e.pageY}px`;
|
||||
contextMenu.style.left = `${e.pageX}px`;
|
||||
contextMenu.style.display = 'block';
|
||||
positionMenu(contextMenu, e.pageX, e.pageY);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -387,3 +383,42 @@ function formatTime(seconds) {
|
|||
const s = Math.floor(seconds % 60);
|
||||
return `${m}:${String(s).padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
function positionMenu(menu, x, y, anchorRect = null) {
|
||||
// Temporarily show to measure dimensions
|
||||
menu.style.visibility = 'hidden';
|
||||
menu.style.display = 'block';
|
||||
|
||||
const menuWidth = menu.offsetWidth;
|
||||
const menuHeight = menu.offsetHeight;
|
||||
const windowWidth = window.innerWidth;
|
||||
const windowHeight = window.innerHeight;
|
||||
|
||||
let left = x;
|
||||
let top = y;
|
||||
|
||||
if (anchorRect) {
|
||||
// Adjust horizontal position if it overflows right
|
||||
if (left + menuWidth > windowWidth - 10) { // 10px buffer
|
||||
left = anchorRect.right - menuWidth;
|
||||
if (left < 10) left = 10;
|
||||
}
|
||||
// Adjust vertical position if it overflows bottom
|
||||
if (top + menuHeight > windowHeight - 10) {
|
||||
top = anchorRect.top - menuHeight - 5;
|
||||
}
|
||||
} else {
|
||||
// Adjust horizontal position if it overflows right
|
||||
if (left + menuWidth > windowWidth - 10) {
|
||||
left = windowWidth - menuWidth - 10;
|
||||
}
|
||||
// Adjust vertical position if it overflows bottom
|
||||
if (top + menuHeight > windowHeight - 10) {
|
||||
top = y - menuHeight;
|
||||
}
|
||||
}
|
||||
|
||||
menu.style.top = `${top}px`;
|
||||
menu.style.left = `${left}px`;
|
||||
menu.style.visibility = 'visible';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -229,8 +229,9 @@ export const themeManager = {
|
|||
CUSTOM_THEME_KEY: 'monochrome-custom-theme',
|
||||
|
||||
defaultThemes: {
|
||||
monochrome: {},
|
||||
light: {},
|
||||
dark: {},
|
||||
monochrome: {},
|
||||
ocean: {},
|
||||
purple: {},
|
||||
forest: {}
|
||||
|
|
@ -238,15 +239,21 @@ export const themeManager = {
|
|||
|
||||
getTheme() {
|
||||
try {
|
||||
return localStorage.getItem(this.STORAGE_KEY) || 'monochrome';
|
||||
return localStorage.getItem(this.STORAGE_KEY) || 'system';
|
||||
} catch (e) {
|
||||
return 'monochrome';
|
||||
return 'system';
|
||||
}
|
||||
},
|
||||
|
||||
setTheme(theme) {
|
||||
localStorage.setItem(this.STORAGE_KEY, theme);
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
|
||||
if (theme === 'system') {
|
||||
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');
|
||||
} else {
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
}
|
||||
},
|
||||
|
||||
getCustomTheme() {
|
||||
|
|
@ -318,3 +325,12 @@ export const lyricsSettings = {
|
|||
localStorage.setItem(this.DOWNLOAD_WITH_TRACKS, enabled ? 'true' : 'false');
|
||||
}
|
||||
};
|
||||
|
||||
// System theme listener
|
||||
if (typeof window !== 'undefined' && window.matchMedia) {
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
|
||||
if (themeManager.getTheme() === 'system') {
|
||||
document.documentElement.setAttribute('data-theme', e.matches ? 'dark' : 'light');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
92
js/ui.js
92
js/ui.js
|
|
@ -23,14 +23,41 @@ export class UIRenderer {
|
|||
`;
|
||||
}
|
||||
|
||||
createTrackItemHTML(track, index, showCover = false) {
|
||||
adjustTitleFontSize(element, text) {
|
||||
element.classList.remove('long-title', 'very-long-title');
|
||||
if (text.length > 40) {
|
||||
element.classList.add('very-long-title');
|
||||
} else if (text.length > 25) {
|
||||
element.classList.add('long-title');
|
||||
}
|
||||
}
|
||||
|
||||
createTrackItemHTML(track, index, showCover = false, hasMultipleDiscs = false) {
|
||||
const playIconSmall = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>';
|
||||
const trackImageHTML = showCover ? `<img src="${this.api.getCoverUrl(track.album?.cover, '80')}" alt="Track Cover" class="track-item-cover" loading="lazy">` : '';
|
||||
const trackNumberHTML = `<div class="track-number">${showCover ? trackImageHTML : index + 1}</div>`;
|
||||
|
||||
let displayIndex;
|
||||
if (hasMultipleDiscs && !showCover) {
|
||||
const discNum = track.volumeNumber ?? track.discNumber ?? 1;
|
||||
displayIndex = `${discNum}-${track.trackNumber}`;
|
||||
} else {
|
||||
displayIndex = index + 1;
|
||||
}
|
||||
|
||||
const trackNumberHTML = `<div class="track-number">${showCover ? trackImageHTML : displayIndex}</div>`;
|
||||
const explicitBadge = hasExplicitContent(track) ? this.createExplicitBadge() : '';
|
||||
const trackArtists = getTrackArtists(track);
|
||||
const trackTitle = getTrackTitle(track);
|
||||
|
||||
let yearDisplay = '';
|
||||
const releaseDate = track.album?.releaseDate || track.streamStartDate;
|
||||
if (releaseDate) {
|
||||
const date = new Date(releaseDate);
|
||||
if (!isNaN(date.getTime())) {
|
||||
yearDisplay = ` • ${date.getFullYear()}`;
|
||||
}
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="track-item" data-track-id="${track.id}">
|
||||
${trackNumberHTML}
|
||||
|
|
@ -40,7 +67,7 @@ export class UIRenderer {
|
|||
${trackTitle}
|
||||
${explicitBadge}
|
||||
</div>
|
||||
<div class="artist">${trackArtists}</div>
|
||||
<div class="artist">${trackArtists}${yearDisplay}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="track-item-duration">${formatTime(track.duration)}</div>
|
||||
|
|
@ -57,13 +84,21 @@ export class UIRenderer {
|
|||
|
||||
createAlbumCardHTML(album) {
|
||||
const explicitBadge = hasExplicitContent(album) ? this.createExplicitBadge() : '';
|
||||
let yearDisplay = '';
|
||||
if (album.releaseDate) {
|
||||
const date = new Date(album.releaseDate);
|
||||
if (!isNaN(date.getTime())) {
|
||||
yearDisplay = `${date.getFullYear()}`;
|
||||
}
|
||||
}
|
||||
return `
|
||||
<a href="#album/${album.id}" class="card">
|
||||
<div class="card-image-wrapper">
|
||||
<img src="${this.api.getCoverUrl(album.cover, '320')}" alt="${album.title}" class="card-image" loading="lazy">
|
||||
</div>
|
||||
<h3 class="card-title">${album.title} ${explicitBadge}</h3>
|
||||
<p class="card-subtitle">Album • ${album.artist?.name ?? ''}</p>
|
||||
<p class="card-subtitle">${album.artist?.name ?? ''}</p>
|
||||
<p class="card-subtitle">${yearDisplay}</p>
|
||||
</a>
|
||||
`;
|
||||
}
|
||||
|
|
@ -75,7 +110,6 @@ export class UIRenderer {
|
|||
<img src="${this.api.getArtistPictureUrl(artist.picture, '320')}" alt="${artist.name}" class="card-image" loading="lazy">
|
||||
</div>
|
||||
<h3 class="card-title">${artist.name}</h3>
|
||||
<p class="card-subtitle">Artist</p>
|
||||
</a>
|
||||
`;
|
||||
}
|
||||
|
|
@ -100,7 +134,7 @@ export class UIRenderer {
|
|||
<div class="skeleton-card ${isArtist ? 'artist' : ''}">
|
||||
<div class="skeleton skeleton-card-image"></div>
|
||||
<div class="skeleton skeleton-card-title"></div>
|
||||
<div class="skeleton skeleton-card-subtitle"></div>
|
||||
${!isArtist ? '<div class="skeleton skeleton-card-subtitle"></div>' : ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
|
@ -117,8 +151,11 @@ export class UIRenderer {
|
|||
const fragment = document.createDocumentFragment();
|
||||
const tempDiv = document.createElement('div');
|
||||
|
||||
// Check if there are multiple discs in the tracks array
|
||||
const hasMultipleDiscs = tracks.some(t => (t.volumeNumber || t.discNumber || 1) > 1);
|
||||
|
||||
tempDiv.innerHTML = tracks.map((track, i) =>
|
||||
this.createTrackItemHTML(track, i, showCover)
|
||||
this.createTrackItemHTML(track, i, showCover, hasMultipleDiscs)
|
||||
).join('');
|
||||
|
||||
while (tempDiv.firstChild) {
|
||||
|
|
@ -245,12 +282,14 @@ export class UIRenderer {
|
|||
const imageEl = document.getElementById('album-detail-image');
|
||||
const titleEl = document.getElementById('album-detail-title');
|
||||
const metaEl = document.getElementById('album-detail-meta');
|
||||
const prodEl = document.getElementById('album-detail-producer');
|
||||
const tracklistContainer = document.getElementById('album-detail-tracklist');
|
||||
|
||||
imageEl.src = '';
|
||||
imageEl.style.backgroundColor = 'var(--muted)';
|
||||
titleEl.innerHTML = '<div class="skeleton" style="height: 48px; width: 300px; max-width: 90%;"></div>';
|
||||
metaEl.innerHTML = '<div class="skeleton" style="height: 16px; width: 200px; max-width: 80%;"></div>';
|
||||
prodEl.innerHTML = '<div class="skeleton" style="height: 16px; width: 200px; max-width: 80%;"></div>';
|
||||
tracklistContainer.innerHTML = `
|
||||
<div class="track-list-header">
|
||||
<span style="width: 40px; text-align: center;">#</span>
|
||||
|
|
@ -269,16 +308,29 @@ export class UIRenderer {
|
|||
const explicitBadge = hasExplicitContent(album) ? this.createExplicitBadge() : '';
|
||||
titleEl.innerHTML = `${album.title} ${explicitBadge}`;
|
||||
|
||||
const totalDuration = calculateTotalDuration(tracks);
|
||||
const releaseDate = new Date(album.releaseDate);
|
||||
const year = releaseDate.getFullYear();
|
||||
this.adjustTitleFontSize(titleEl, album.title);
|
||||
|
||||
const dateDisplay = window.innerWidth > 768
|
||||
? releaseDate.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })
|
||||
: year;
|
||||
const totalDuration = calculateTotalDuration(tracks);
|
||||
let dateDisplay = '';
|
||||
if (album.releaseDate) {
|
||||
const releaseDate = new Date(album.releaseDate);
|
||||
if (!isNaN(releaseDate.getTime())) {
|
||||
const year = releaseDate.getFullYear();
|
||||
dateDisplay = window.innerWidth > 768
|
||||
? releaseDate.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })
|
||||
: year;
|
||||
}
|
||||
}
|
||||
|
||||
const firstCopyright = tracks.find(track => track.copyright)?.copyright;
|
||||
|
||||
metaEl.innerHTML =
|
||||
`By <a href="#artist/${album.artist.id}">${album.artist.name}</a> • ${dateDisplay} • ${tracks.length} tracks • ${formatDuration(totalDuration)}`;
|
||||
(dateDisplay ? `${dateDisplay} • ` : '') +
|
||||
`${tracks.length} tracks • ${formatDuration(totalDuration)}`;
|
||||
|
||||
prodEl.innerHTML =
|
||||
`By <a href="#artist/${album.artist.id}">${album.artist.name}</a>` +
|
||||
(firstCopyright ? ` • ${firstCopyright}` : '');
|
||||
|
||||
tracklistContainer.innerHTML = `
|
||||
<div class="track-list-header">
|
||||
|
|
@ -288,7 +340,12 @@ export class UIRenderer {
|
|||
</div>
|
||||
`;
|
||||
|
||||
tracks.sort((a, b) => a.trackNumber - b.trackNumber);
|
||||
tracks.sort((a, b) => {
|
||||
const discA = a.volumeNumber ?? a.discNumber ?? 1;
|
||||
const discB = b.volumeNumber ?? b.discNumber ?? 1;
|
||||
if (discA !== discB) return discA - discB;
|
||||
return a.trackNumber - b.trackNumber;
|
||||
});
|
||||
this.renderListWithTracks(tracklistContainer, tracks, false);
|
||||
|
||||
recentActivityManager.addAlbum(album);
|
||||
|
|
@ -332,6 +389,8 @@ async renderPlaylistPage(playlistId) {
|
|||
|
||||
titleEl.textContent = playlist.title;
|
||||
|
||||
this.adjustTitleFontSize(titleEl, playlist.title);
|
||||
|
||||
const totalDuration = calculateTotalDuration(tracks);
|
||||
|
||||
metaEl.textContent = `${playlist.numberOfTracks} tracks • ${formatDuration(totalDuration)}`;
|
||||
|
|
@ -377,6 +436,9 @@ async renderPlaylistPage(playlistId) {
|
|||
imageEl.src = this.api.getArtistPictureUrl(artist.picture, '750');
|
||||
imageEl.style.backgroundColor = '';
|
||||
nameEl.textContent = artist.name;
|
||||
|
||||
this.adjustTitleFontSize(nameEl, artist.name);
|
||||
|
||||
metaEl.textContent = `${artist.popularity} popularity`;
|
||||
|
||||
this.renderListWithTracks(tracksContainer, artist.tracks, true);
|
||||
|
|
|
|||
66
styles.css
66
styles.css
|
|
@ -114,6 +114,27 @@
|
|||
--explicit-badge: #f59e0b;
|
||||
}
|
||||
|
||||
:root[data-theme="light"] {
|
||||
--background: #ffffff;
|
||||
--foreground: #000000;
|
||||
--card: #f4f4f5;
|
||||
--card-foreground: #000000;
|
||||
--primary: #2563eb;
|
||||
--primary-foreground: #ffffff;
|
||||
--secondary: #e4e4e7;
|
||||
--secondary-foreground: #000000;
|
||||
--muted: #e4e4e7;
|
||||
--muted-foreground: #71717a;
|
||||
--border: #e4e4e7;
|
||||
--input: #e4e4e7;
|
||||
--ring: #2563eb;
|
||||
--highlight: #2563eb;
|
||||
--highlight-rgb: 37, 99, 235;
|
||||
--active-highlight: var(--highlight);
|
||||
--explicit-badge: #ef4444;
|
||||
--explicit-badge-foreground: #ffffff;
|
||||
}
|
||||
|
||||
*, *::before, *::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
|
|
@ -166,19 +187,18 @@ kbd {
|
|||
height: 100dvh;
|
||||
grid-template:
|
||||
"sidebar main" 1fr
|
||||
"player player" auto / 280px 1fr;
|
||||
"player player" auto / 190px 1fr;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
grid-area: sidebar;
|
||||
background-color: var(--background);
|
||||
border-right: 1px solid var(--border);
|
||||
padding: 1.5rem;
|
||||
padding: 1.25rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
|
|
@ -190,7 +210,7 @@ kbd {
|
|||
|
||||
.now-playing-bar {
|
||||
grid-area: player;
|
||||
background-color: #050505;
|
||||
background-color: var(--card);
|
||||
border-top: 1px solid var(--border);
|
||||
padding: var(--spacing-md) var(--spacing-lg);
|
||||
display: grid;
|
||||
|
|
@ -491,7 +511,7 @@ kbd {
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--explicit-badge);
|
||||
color: #000;
|
||||
color: var(--explicit-badge-foreground, #000);
|
||||
font-size: 0.65rem;
|
||||
font-weight: 700;
|
||||
padding: 0.15rem 0.35rem;
|
||||
|
|
@ -682,6 +702,15 @@ kbd {
|
|||
align-items: center;
|
||||
gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.detail-header-info .title.long-title {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.detail-header-info .title.very-long-title {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
.detail-header-info .meta {
|
||||
|
|
@ -1805,7 +1834,7 @@ input:checked + .slider::before {
|
|||
/* Responsive Design */
|
||||
@media (max-width: 1024px) {
|
||||
.app-container {
|
||||
grid-template-columns: 240px 1fr;
|
||||
grid-template-columns: 160px 1fr;
|
||||
}
|
||||
|
||||
.card-grid {
|
||||
|
|
@ -1817,6 +1846,14 @@ input:checked + .slider::before {
|
|||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.detail-header-info .title.long-title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.detail-header-info .title.very-long-title {
|
||||
font-size: 1.35rem;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding: var(--spacing-lg);
|
||||
}
|
||||
|
|
@ -1850,6 +1887,7 @@ input:checked + .slider::before {
|
|||
height: 100%;
|
||||
transform: translateX(-100%);
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.sidebar.is-open {
|
||||
|
|
@ -1900,6 +1938,14 @@ input:checked + .slider::before {
|
|||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.detail-header-info .title.long-title {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.detail-header-info .title.very-long-title {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.detail-header-info .meta {
|
||||
font-size: 0.85rem;
|
||||
gap: 0.35rem;
|
||||
|
|
@ -2136,6 +2182,14 @@ input:checked + .slider::before {
|
|||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
.detail-header-info .title.long-title {
|
||||
font-size: 1.35rem;
|
||||
}
|
||||
|
||||
.detail-header-info .title.very-long-title {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.search-tab {
|
||||
padding: var(--spacing-sm) var(--spacing-md);
|
||||
font-size: 0.9rem;
|
||||
|
|
|
|||
Loading…
Reference in a new issue