beatport progress
This commit is contained in:
parent
5e73b53a0f
commit
69c8622588
5 changed files with 771 additions and 0 deletions
|
|
@ -1403,6 +1403,263 @@ class BeatportUnifiedScraper:
|
|||
print(f"Error extracting track data: {e}")
|
||||
return None
|
||||
|
||||
def scrape_homepage_top10_releases(self) -> List[Dict]:
|
||||
"""Scrape Top 10 Releases from homepage - FIXED VERSION"""
|
||||
print("\n💿 FIXED: Scraping Top 10 Releases from homepage...")
|
||||
|
||||
soup = self.get_page(self.base_url)
|
||||
if not soup:
|
||||
print(" ❌ Could not get homepage")
|
||||
return []
|
||||
|
||||
# Extract Top 10 Releases items - EXACT same as test script
|
||||
top10_releases_items = soup.select('[data-testid="top-10-releases-item"]')
|
||||
print(f" FOUND {len(top10_releases_items)} Top 10 Releases items")
|
||||
|
||||
if len(top10_releases_items) == 0:
|
||||
print(" ❌ No items found - trying alternatives")
|
||||
return []
|
||||
|
||||
releases = []
|
||||
for i, item in enumerate(top10_releases_items, 1):
|
||||
try:
|
||||
# Use the SAME function name as the test script
|
||||
release_data = self.extract_release_from_item_FIXED(item, i)
|
||||
if release_data:
|
||||
releases.append(release_data)
|
||||
print(f" ✅ {i}. {release_data['artist']} - {release_data['title']}")
|
||||
else:
|
||||
print(f" ❌ {i}. No data extracted")
|
||||
except Exception as e:
|
||||
print(f" ❌ Error extracting release {i}: {e}")
|
||||
|
||||
print(f"✅ FINAL: Extracted {len(releases)} Top 10 Releases")
|
||||
return releases
|
||||
|
||||
def extract_release_from_item_FIXED(self, item, rank):
|
||||
"""Extract release data from a list item - EXACT COPY FROM WORKING TEST SCRIPT"""
|
||||
try:
|
||||
# Get the release URL
|
||||
link_elem = item.select_one('a[href*="/release/"]')
|
||||
release_url = ""
|
||||
if link_elem and link_elem.get('href'):
|
||||
release_url = f"https://www.beatport.com{link_elem.get('href')}"
|
||||
|
||||
# Extract release title
|
||||
title = "Unknown Title"
|
||||
# Try multiple selectors for title
|
||||
title_selectors = [
|
||||
'[class*="ItemName"]',
|
||||
'[class*="ReleaseName"]',
|
||||
'[class*="release-name"]',
|
||||
'[class*="TrackName"]',
|
||||
'[class*="track-name"]',
|
||||
'a[href*="/release/"]',
|
||||
'h3', 'h4', 'h5',
|
||||
'[class*="title"]',
|
||||
'[class*="Title"]'
|
||||
]
|
||||
|
||||
for selector in title_selectors:
|
||||
title_elem = item.select_one(selector)
|
||||
if title_elem:
|
||||
title = title_elem.get_text(strip=True)
|
||||
if title and title != "Unknown Title" and len(title) > 2:
|
||||
break
|
||||
|
||||
# Extract artist name - try multiple approaches
|
||||
artist = "Unknown Artist"
|
||||
artist_selectors = [
|
||||
'[class*="Artists"]',
|
||||
'[class*="artist"]',
|
||||
'[class*="Artist"]',
|
||||
'[class*="ItemArtist"]',
|
||||
'a[href*="/artist/"]',
|
||||
'[class*="by"]',
|
||||
'[class*="By"]'
|
||||
]
|
||||
|
||||
for selector in artist_selectors:
|
||||
artist_elem = item.select_one(selector)
|
||||
if artist_elem:
|
||||
artist = artist_elem.get_text(strip=True)
|
||||
if artist and artist != "Unknown Artist" and len(artist) > 1:
|
||||
break
|
||||
|
||||
# Extract label name - try multiple approaches
|
||||
label = "Unknown Label"
|
||||
label_selectors = [
|
||||
'[class*="Label"]',
|
||||
'[class*="label"]',
|
||||
'[class*="ItemLabel"]',
|
||||
'a[href*="/label/"]',
|
||||
'[class*="imprint"]',
|
||||
'[class*="Imprint"]'
|
||||
]
|
||||
|
||||
for selector in label_selectors:
|
||||
label_elem = item.select_one(selector)
|
||||
if label_elem:
|
||||
label = label_elem.get_text(strip=True)
|
||||
if label and label != "Unknown Label" and len(label) > 2:
|
||||
break
|
||||
|
||||
# Extract image URL - this is important for releases
|
||||
image_url = ""
|
||||
image_selectors = [
|
||||
'img[src]',
|
||||
'img[data-src]',
|
||||
'img[data-lazy]',
|
||||
'[style*="background-image"]',
|
||||
'picture img',
|
||||
'.artwork img',
|
||||
'[class*="artwork"] img',
|
||||
'[class*="Artwork"] img',
|
||||
'[class*="image"] img',
|
||||
'[class*="Image"] img'
|
||||
]
|
||||
|
||||
for selector in image_selectors:
|
||||
img_elem = item.select_one(selector)
|
||||
if img_elem:
|
||||
# Try different image source attributes
|
||||
img_src = (img_elem.get('src') or
|
||||
img_elem.get('data-src') or
|
||||
img_elem.get('data-lazy') or
|
||||
img_elem.get('data-original'))
|
||||
|
||||
if img_src and img_src.startswith(('http', '//')):
|
||||
image_url = img_src
|
||||
break
|
||||
elif img_src and img_src.startswith('/'):
|
||||
image_url = f"https://www.beatport.com{img_src}"
|
||||
break
|
||||
|
||||
return {
|
||||
"rank": rank,
|
||||
"title": title,
|
||||
"artist": artist,
|
||||
"label": label,
|
||||
"url": release_url,
|
||||
"image_url": image_url,
|
||||
"list_name": "Top 10 Releases"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error extracting release data: {e}")
|
||||
return None
|
||||
|
||||
def extract_release_from_top10_item(self, item, rank):
|
||||
"""Extract release data from a top 10 releases item"""
|
||||
try:
|
||||
# Get the release URL
|
||||
link_elem = item.select_one('a[href*="/release/"]')
|
||||
release_url = ""
|
||||
if link_elem and link_elem.get('href'):
|
||||
release_url = f"https://www.beatport.com{link_elem.get('href')}"
|
||||
|
||||
# Extract release title
|
||||
title = "Unknown Title"
|
||||
title_selectors = [
|
||||
'[class*="ItemName"]',
|
||||
'[class*="ReleaseName"]',
|
||||
'[class*="release-name"]',
|
||||
'[class*="TrackName"]',
|
||||
'[class*="track-name"]',
|
||||
'a[href*="/release/"]',
|
||||
'h3', 'h4', 'h5',
|
||||
'[class*="title"]',
|
||||
'[class*="Title"]'
|
||||
]
|
||||
|
||||
for selector in title_selectors:
|
||||
title_elem = item.select_one(selector)
|
||||
if title_elem:
|
||||
title = title_elem.get_text(strip=True)
|
||||
if title and title != "Unknown Title" and len(title) > 2:
|
||||
break
|
||||
|
||||
# Extract artist name
|
||||
artist = "Unknown Artist"
|
||||
artist_selectors = [
|
||||
'[class*="Artists"]',
|
||||
'[class*="artist"]',
|
||||
'[class*="Artist"]',
|
||||
'[class*="ItemArtist"]',
|
||||
'a[href*="/artist/"]',
|
||||
'[class*="by"]',
|
||||
'[class*="By"]'
|
||||
]
|
||||
|
||||
for selector in artist_selectors:
|
||||
artist_elem = item.select_one(selector)
|
||||
if artist_elem:
|
||||
artist = artist_elem.get_text(strip=True)
|
||||
if artist and artist != "Unknown Artist" and len(artist) > 1:
|
||||
break
|
||||
|
||||
# Extract label name
|
||||
label = "Unknown Label"
|
||||
label_selectors = [
|
||||
'[class*="Label"]',
|
||||
'[class*="label"]',
|
||||
'[class*="ItemLabel"]',
|
||||
'a[href*="/label/"]',
|
||||
'[class*="imprint"]',
|
||||
'[class*="Imprint"]'
|
||||
]
|
||||
|
||||
for selector in label_selectors:
|
||||
label_elem = item.select_one(selector)
|
||||
if label_elem:
|
||||
label = label_elem.get_text(strip=True)
|
||||
if label and label != "Unknown Label" and len(label) > 2:
|
||||
break
|
||||
|
||||
# Extract image URL - important for releases
|
||||
image_url = ""
|
||||
image_selectors = [
|
||||
'img[src]',
|
||||
'img[data-src]',
|
||||
'img[data-lazy]',
|
||||
'[style*="background-image"]',
|
||||
'picture img',
|
||||
'.artwork img',
|
||||
'[class*="artwork"] img',
|
||||
'[class*="Artwork"] img',
|
||||
'[class*="image"] img',
|
||||
'[class*="Image"] img'
|
||||
]
|
||||
|
||||
for selector in image_selectors:
|
||||
img_elem = item.select_one(selector)
|
||||
if img_elem:
|
||||
img_src = (img_elem.get('src') or
|
||||
img_elem.get('data-src') or
|
||||
img_elem.get('data-lazy') or
|
||||
img_elem.get('data-original'))
|
||||
|
||||
if img_src and img_src.startswith(('http', '//')):
|
||||
image_url = img_src
|
||||
break
|
||||
elif img_src and img_src.startswith('/'):
|
||||
image_url = f"https://www.beatport.com{img_src}"
|
||||
break
|
||||
|
||||
return {
|
||||
"rank": rank,
|
||||
"title": title,
|
||||
"artist": artist,
|
||||
"label": label,
|
||||
"url": release_url,
|
||||
"image_url": image_url,
|
||||
"list_name": "Top 10 Releases"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error extracting release data: {e}")
|
||||
return None
|
||||
|
||||
def scrape_new_on_beatport_hero(self, limit: int = 10) -> List[Dict]:
|
||||
"""Scrape the 'New on Beatport' hero slideshow from homepage"""
|
||||
print("\n🎯 Scraping 'New on Beatport' hero slideshow...")
|
||||
|
|
|
|||
|
|
@ -13262,6 +13262,44 @@ def get_beatport_homepage_top10_lists():
|
|||
"hype_count": 0
|
||||
}), 500
|
||||
|
||||
@app.route('/api/beatport/homepage/top-10-releases-cards', methods=['GET'])
|
||||
def get_beatport_homepage_top10_releases_cards():
|
||||
"""Get Beatport Top 10 Releases CARDS from homepage (not individual tracks)"""
|
||||
try:
|
||||
logger.info("💿 API request for Beatport homepage Top 10 Releases CARDS")
|
||||
|
||||
# Initialize the Beatport scraper
|
||||
scraper = BeatportUnifiedScraper()
|
||||
|
||||
# Get top 10 releases from homepage
|
||||
top10_releases = scraper.scrape_homepage_top10_releases()
|
||||
|
||||
logger.info(f"✅ API extracted {len(top10_releases)} Top 10 Release Cards")
|
||||
|
||||
# Debug: Log first release if any
|
||||
if top10_releases:
|
||||
logger.info(f"First release: {top10_releases[0].get('title', 'No title')} by {top10_releases[0].get('artist', 'No artist')}")
|
||||
else:
|
||||
logger.warning("❌ No releases found by scraper")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"releases": top10_releases,
|
||||
"releases_count": len(top10_releases),
|
||||
"source": "beatport_homepage_top10_releases_cards"
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Error getting Beatport homepage Top 10 Releases cards: {e}")
|
||||
import traceback
|
||||
logger.error(f"Full traceback: {traceback.format_exc()}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"releases": [],
|
||||
"releases_count": 0
|
||||
}), 500
|
||||
|
||||
@app.route('/api/beatport/homepage/featured-charts', methods=['GET'])
|
||||
def get_beatport_homepage_featured_charts():
|
||||
"""Get Beatport Featured Charts from homepage section"""
|
||||
|
|
|
|||
|
|
@ -850,6 +850,26 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Top 10 Releases Section -->
|
||||
<div class="beatport-releases-top10-section">
|
||||
<div class="beatport-releases-top10-header">
|
||||
<h2 class="beatport-releases-top10-title">💿 Top 10 Releases</h2>
|
||||
<p class="beatport-releases-top10-subtitle">Most popular albums and EPs on Beatport</p>
|
||||
</div>
|
||||
|
||||
<div class="beatport-releases-top10-container">
|
||||
<div class="beatport-releases-top10-list" id="beatport-releases-top10-list">
|
||||
<!-- Loading placeholder -->
|
||||
<div class="beatport-releases-top10-loading">
|
||||
<div class="beatport-releases-top10-loading-content">
|
||||
<h4>💿 Loading Top 10 Releases...</h4>
|
||||
<p>Fetching trending albums and EPs</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- New Releases Grid Slideshow Section -->
|
||||
<div class="beatport-releases-section">
|
||||
<div class="beatport-releases-header">
|
||||
|
|
|
|||
|
|
@ -9735,6 +9735,7 @@ function initializeSyncPage() {
|
|||
if (tabId === 'rebuild') {
|
||||
initializeBeatportRebuildSlider();
|
||||
loadBeatportTop10Lists();
|
||||
loadBeatportTop10Releases();
|
||||
initializeBeatportReleasesSlider();
|
||||
initializeBeatportHypePicksSlider();
|
||||
initializeBeatportChartsSlider();
|
||||
|
|
@ -19844,3 +19845,79 @@ function showTop10ListsError(errorMessage) {
|
|||
if (beatportContainer) beatportContainer.innerHTML = errorHtml;
|
||||
if (hypeContainer) hypeContainer.innerHTML = errorHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load top 10 releases data from API and populate the list
|
||||
*/
|
||||
async function loadBeatportTop10Releases() {
|
||||
try {
|
||||
console.log('💿 Loading top 10 releases data...');
|
||||
const response = await fetch('/api/beatport/homepage/top-10-releases-cards');
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
console.log(`💿 Loaded ${data.releases_count} Top 10 Releases`);
|
||||
populateBeatportTop10Releases(data.releases);
|
||||
return true;
|
||||
} else {
|
||||
console.error('Failed to load top 10 releases:', data.error);
|
||||
showTop10ReleasesError(data.error || 'No data available');
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading top 10 releases:', error);
|
||||
showTop10ReleasesError('Failed to load top 10 releases');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate Top 10 Releases list with data
|
||||
*/
|
||||
function populateBeatportTop10Releases(releases) {
|
||||
const container = document.getElementById('beatport-releases-top10-list');
|
||||
if (!container || !releases || releases.length === 0) return;
|
||||
|
||||
// Generate HTML for the releases
|
||||
let releasesHtml = `
|
||||
<div class="beatport-releases-top10-tracks">
|
||||
`;
|
||||
|
||||
releases.forEach((release, index) => {
|
||||
releasesHtml += `
|
||||
<div class="beatport-releases-top10-card" data-url="${release.url || '#'}">
|
||||
<div class="beatport-releases-top10-card-rank">${release.rank || index + 1}</div>
|
||||
<div class="beatport-releases-top10-card-artwork">
|
||||
${release.image_url ?
|
||||
`<img src="${release.image_url}" alt="${release.title}" loading="lazy">` :
|
||||
'<div class="beatport-releases-top10-card-placeholder">💿</div>'
|
||||
}
|
||||
</div>
|
||||
<div class="beatport-releases-top10-card-info">
|
||||
<h4 class="beatport-releases-top10-card-title">${release.title || 'Unknown Title'}</h4>
|
||||
<p class="beatport-releases-top10-card-artist">${release.artist || 'Unknown Artist'}</p>
|
||||
<p class="beatport-releases-top10-card-label">${release.label || 'Unknown Label'}</p>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
releasesHtml += '</div>';
|
||||
container.innerHTML = releasesHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show error message for top 10 releases
|
||||
*/
|
||||
function showTop10ReleasesError(errorMessage) {
|
||||
const container = document.getElementById('beatport-releases-top10-list');
|
||||
|
||||
const errorHtml = `
|
||||
<div class="beatport-releases-top10-error">
|
||||
<h3>❌ Error Loading Releases</h3>
|
||||
<p>${errorMessage}</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
if (container) container.innerHTML = errorHtml;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12506,6 +12506,384 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
/* =======================================
|
||||
BEATPORT TOP 10 RELEASES SECTION
|
||||
======================================= */
|
||||
|
||||
.beatport-releases-top10-section {
|
||||
margin-top: 40px;
|
||||
padding: 0 30px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-header {
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-title {
|
||||
font-size: 36px;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
margin-bottom: 8px;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.beatport-releases-top10-subtitle {
|
||||
font-size: 16px;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Single column container for releases */
|
||||
.beatport-releases-top10-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* List styling with unique design */
|
||||
.beatport-releases-top10-list {
|
||||
background: linear-gradient(135deg,
|
||||
rgba(20, 20, 20, 0.95),
|
||||
rgba(35, 35, 35, 0.9));
|
||||
border-radius: 24px;
|
||||
padding: 40px;
|
||||
backdrop-filter: blur(25px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||
box-shadow:
|
||||
0 25px 50px rgba(0, 0, 0, 0.6),
|
||||
0 0 25px rgba(138, 43, 226, 0.1),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.15);
|
||||
border-left: 4px solid #8a2be2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Track containers with grid layout for releases */
|
||||
.beatport-releases-top10-tracks {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
/* Individual release cards - unique design with images */
|
||||
.beatport-releases-top10-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: linear-gradient(135deg,
|
||||
rgba(30, 30, 30, 0.9),
|
||||
rgba(45, 45, 45, 0.85));
|
||||
border-radius: 20px;
|
||||
padding: 20px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(15px);
|
||||
transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1);
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
|
||||
min-height: 120px;
|
||||
max-height: 120px;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Hover animations for release cards */
|
||||
.beatport-releases-top10-card:hover {
|
||||
background: linear-gradient(135deg,
|
||||
rgba(138, 43, 226, 0.15),
|
||||
rgba(45, 45, 45, 0.95));
|
||||
border-color: rgba(138, 43, 226, 0.4);
|
||||
transform: translateY(-5px) scale(1.02);
|
||||
box-shadow:
|
||||
0 20px 40px rgba(0, 0, 0, 0.6),
|
||||
0 0 30px rgba(138, 43, 226, 0.25);
|
||||
}
|
||||
|
||||
/* Release rank number */
|
||||
.beatport-releases-top10-card-rank {
|
||||
font-size: 24px;
|
||||
font-weight: 900;
|
||||
color: #8a2be2;
|
||||
min-width: 40px;
|
||||
text-align: center;
|
||||
margin-right: 20px;
|
||||
text-shadow: 0 3px 8px rgba(138, 43, 226, 0.4);
|
||||
background: linear-gradient(135deg, rgba(138, 43, 226, 0.15), rgba(138, 43, 226, 0.08));
|
||||
border-radius: 16px;
|
||||
padding: 12px 0;
|
||||
border: 2px solid rgba(138, 43, 226, 0.3);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
/* Release artwork - larger since these have images */
|
||||
.beatport-releases-top10-card-artwork {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 16px;
|
||||
margin-right: 20px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5);
|
||||
border: 3px solid rgba(255, 255, 255, 0.15);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card-artwork img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 0.5s ease;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card:hover .beatport-releases-top10-card-artwork img {
|
||||
transform: scale(1.2) rotate(2deg);
|
||||
}
|
||||
|
||||
/* Artwork placeholder for releases */
|
||||
.beatport-releases-top10-card-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 28px;
|
||||
background: linear-gradient(135deg, rgba(138, 43, 226, 0.2), rgba(80, 80, 80, 0.8));
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
/* Release info */
|
||||
.beatport-releases-top10-card-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card-title {
|
||||
font-size: 18px;
|
||||
font-weight: 800;
|
||||
color: #ffffff;
|
||||
line-height: 1.3;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.9);
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card-artist {
|
||||
font-size: 15px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
font-weight: 600;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card-label {
|
||||
font-size: 13px;
|
||||
color: rgba(138, 43, 226, 0.95);
|
||||
font-weight: 700;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.8px;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Loading states for releases */
|
||||
.beatport-releases-top10-loading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 200px;
|
||||
background: linear-gradient(135deg,
|
||||
rgba(20, 20, 20, 0.7),
|
||||
rgba(30, 30, 30, 0.5));
|
||||
border-radius: 20px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.beatport-releases-top10-loading-content {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-loading-content h4 {
|
||||
font-size: 20px;
|
||||
color: #ffffff;
|
||||
margin-bottom: 10px;
|
||||
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
.beatport-releases-top10-loading-content p {
|
||||
font-size: 15px;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Error states for releases */
|
||||
.beatport-releases-top10-error {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 200px;
|
||||
background: linear-gradient(135deg,
|
||||
rgba(255, 51, 51, 0.12),
|
||||
rgba(45, 45, 45, 0.9));
|
||||
border-radius: 20px;
|
||||
border: 1px solid rgba(255, 51, 51, 0.25);
|
||||
text-align: center;
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-error h3 {
|
||||
color: #ff3366;
|
||||
font-size: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-error p {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-size: 15px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Responsive Design for Top 10 Releases */
|
||||
@media (max-width: 1300px) {
|
||||
.beatport-releases-top10-card-title {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card-artist {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card-label {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card-rank {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.beatport-releases-top10-tracks {
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-list {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card {
|
||||
min-height: 110px;
|
||||
max-height: 110px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card-artwork {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.beatport-releases-top10-tracks {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-section {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-title {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card {
|
||||
min-height: 100px;
|
||||
max-height: 100px;
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card-artwork {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card-rank {
|
||||
font-size: 18px;
|
||||
min-width: 35px;
|
||||
margin-right: 16px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.beatport-releases-top10-section {
|
||||
padding: 0 15px;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-header {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-list {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-title {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card {
|
||||
min-height: 90px;
|
||||
max-height: 90px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card-artwork {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card-rank {
|
||||
font-size: 16px;
|
||||
min-width: 30px;
|
||||
margin-right: 12px;
|
||||
padding: 6px 0;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card-title {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card-artist {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.beatport-releases-top10-card-label {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================
|
||||
BEATPORT NEW RELEASES SECTION
|
||||
================================ */
|
||||
|
|
@ -13863,6 +14241,7 @@ body {
|
|||
}
|
||||
|
||||
.beatport-dj-creator {
|
||||
display: none;
|
||||
font-size: 16px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
font-weight: 500;
|
||||
|
|
|
|||
Loading…
Reference in a new issue