ML Intern commited on
Commit
74ca420
·
1 Parent(s): c673df8

Fix livescore standings CSS + update to 2026-2027 season

Browse files

- Update LEAGUE_IDS to 2026-2027 tournaments:
nha=36781, laliga=38843, seriea=36072, bundesliga=40040, ligue1=37298
- Add BXH standings tabs for Serie A, Bundesliga, Ligue 1 (League 1)
- Style bongda div-based leaderboard rows (previously only <table> was styled -> broken BXH table)
- Inject header row (# / team / Tr T H B BT BB +/- / points) via _decorateStandings
- Bump app_v2.js to v=20260821k for cache-bust

Files changed (5) hide show
  1. main.py +2 -2
  2. static/app_v2.js +17 -2
  3. static/fm_fix.css +120 -0
  4. static/index_v2.html +1 -1
  5. static/live_mode.js +16 -1
main.py CHANGED
@@ -51,7 +51,7 @@ _cache_ttl_live = 60
51
  _cache_ttl_yt = 1800
52
 
53
  PRIORITY_LEAGUES = ["Ngoại Hạng Anh","FA Cup","Champions League","LaLiga","Copa del Rey","Serie A","Bundesliga","Ligue 1","V-League"]
54
- LEAGUE_IDS = {"nha":27110,"laliga":27233,"seriea":27044,"bundesliga":26891,"ligue1":27212}
55
  HL_LEAGUES = {
56
  "premier-league":{"path":"anh/premier-league","name":"Premier League","emoji":"🏴󠁧󠁢󠁥󠁮󠁧󠁿"},
57
  "fa-cup":{"path":"anh/fa-cup","name":"FA Cup","emoji":"🏆"},
@@ -399,7 +399,7 @@ def api_livescore_results():
399
  today=datetime.now(VN_TZ).strftime("%Y-%m-%d");return JSONResponse({"html":_cached("ls_results",lambda:fetch_bongda_api(f"/api/fixtures/get-by-date?date={today}&status=finished"),ttl=_cache_ttl)})
400
  @app.get("/api/livescore/standings/{league}")
401
  def api_livescore_standings(league:str):
402
- tid=LEAGUE_IDS.get(league,27110);return JSONResponse({"html":_cached(f"ls_bxh_{league}",lambda:fetch_bongda_api(f"/api/league-table/home?tournament_id={tid}&is_detail=True"),ttl=_cache_ttl)})
403
  @app.get("/api/livescore/date/{date}")
404
  def api_livescore_date(date:str):return JSONResponse({"html":fetch_bongda_api(f"/api/fixtures/get-by-date?date={date}")})
405
 
 
51
  _cache_ttl_yt = 1800
52
 
53
  PRIORITY_LEAGUES = ["Ngoại Hạng Anh","FA Cup","Champions League","LaLiga","Copa del Rey","Serie A","Bundesliga","Ligue 1","V-League"]
54
+ LEAGUE_IDS = {"nha":36781,"laliga":38843,"seriea":36072,"bundesliga":40040,"ligue1":37298}
55
  HL_LEAGUES = {
56
  "premier-league":{"path":"anh/premier-league","name":"Premier League","emoji":"🏴󠁧󠁢󠁥󠁮󠁧󠁿"},
57
  "fa-cup":{"path":"anh/fa-cup","name":"FA Cup","emoji":"🏆"},
 
399
  today=datetime.now(VN_TZ).strftime("%Y-%m-%d");return JSONResponse({"html":_cached("ls_results",lambda:fetch_bongda_api(f"/api/fixtures/get-by-date?date={today}&status=finished"),ttl=_cache_ttl)})
400
  @app.get("/api/livescore/standings/{league}")
401
  def api_livescore_standings(league:str):
402
+ tid=LEAGUE_IDS.get(league,36781);return JSONResponse({"html":_cached(f"ls_bxh_{league}",lambda:fetch_bongda_api(f"/api/league-table/home?tournament_id={tid}&is_detail=True"),ttl=_cache_ttl)})
403
  @app.get("/api/livescore/date/{date}")
404
  def api_livescore_date(date:str):return JSONResponse({"html":fetch_bongda_api(f"/api/fixtures/get-by-date?date={date}")})
405
 
static/app_v2.js CHANGED
@@ -152,7 +152,7 @@ async function loadHome(){
152
  +'<div id="ai-wall-under-compose"></div>'
153
  +'<div id="hashtag-box"></div>'
154
  +'<div id="home-hl-section"></div>'
155
- +'<div class="ls-section"><div class="ls-header"><h3>⚽ Livescore</h3></div><div class="ls-tabs"><span class="ls-tab active" data-tab="recent" onclick="loadLivescore(\'recent\')">📋 Cập nhật</span><span class="ls-tab" data-tab="live" onclick="loadLivescore(\'live\')">🔴 Live</span><span class="ls-tab" data-tab="today" onclick="loadLivescore(\'today\')">📅 Hôm nay</span><span class="ls-tab" data-tab="incoming" onclick="loadLivescore(\'incoming\')">⏰ Sắp tới</span><span class="ls-tab" data-tab="results" onclick="loadLivescore(\'results\')">✅ Kết quả</span><span class="ls-tab" data-tab="bxh_nha" onclick="loadLivescore(\'bxh_nha\')">🏆 NHA</span><span class="ls-tab" data-tab="bxh_laliga" onclick="loadLivescore(\'bxh_laliga\')">🏆 La Liga</span></div><div class="ls-content" id="ls-content"><div class="loading">Đang tải...</div></div></div>'
156
  +'<div id="wc2026-live-section" class="wc2026-section"><div class="wc-header"><h2>🏆 World Cup 2026</h2><span class="wc-live-badge">● LIVE</span></div><div class="wc-tabs"><span class="wc-tab active" onclick="switchWCTab(\'news\')">📰 Tin tức</span><span class="wc-tab" onclick="switchWCTab(\'fixtures\')">📅 Lịch thi đấu</span><span class="wc-tab" onclick="switchWCTab(\'standings\')">🏆 BXH</span><span class="wc-tab" onclick="switchWCTab(\'highlights\')">🎬 Highlight</span><span class="wc-tab" onclick="switchWCTab(\'stats\')">📊 Thống kê</span></div><div class="wc-content" id="wc-content"><div class="loading">Đang tải World Cup 2026...</div></div></div>'
157
  +'<div id="home-after-wc"></div>';
158
 
@@ -1089,7 +1089,22 @@ function searchTopic(topic){if(!topic){topic=document.getElementById('topic-inpu
1089
  async function showHashtagSources(topic,page){const box=document.getElementById('hashtag-box');if(!box)return;if(page===0)box.innerHTML=`<div class="hashtag-sources"><h3>🔍 ${esc(topic)}</h3><div class="hashtag-loading"><div class="hashtag-spinner"></div>Đang tìm...</div></div>`;try{const r=await fetch(`/api/hashtag/sources?topic=${encodeURIComponent(topic)}&page=${page}`);const j=await r.json();const sources=j.sources||[];if(!sources.length&&page===0){box.innerHTML=`<div class="hashtag-sources"><h3>🔍 ${esc(topic)}</h3><div style="color:#888;padding:8px">Không tìm được bài viết liên quan</div></div>`;return;}let h='';if(page===0)h=`<div class="hashtag-sources"><h3>🔍 ${esc(topic)} <span style="font-size:10px;color:#888">(${j.total} bài từ 8 nguồn)</span></h3><div id="ht-list">`;sources.forEach((s,i)=>{const idx=page*8+i;h+=`<div class="hashtag-src-item" onclick="readArticle('${esc(s.url)}')"><div class="hashtag-src-img" id="ht-img-${idx}"></div><div class="hashtag-src-text"><div class="hashtag-src-title">${esc(s.title)}</div><div class="hashtag-src-via">${esc(s.via||'')}</div></div></div>`;});if(page===0){h+=`</div><button class="hashtag-rewrite-btn" onclick="rewriteHashtag('${esc(topic).replace(/'/g,"\\'")}')">🤖 Rewrite AI tổng hợp & đăng tường</button>`;if(j.has_more)h+=`<button class="hashtag-load-more" id="ht-more" onclick="loadMoreHashtag()">Tải thêm ▼</button>`;h+=`</div>`;box.innerHTML=h;}else{document.getElementById('ht-list')?.insertAdjacentHTML('beforeend',h);const btn=document.getElementById('ht-more');if(btn){if(!j.has_more)btn.remove();else{btn.disabled=false;btn.textContent='Tải thêm ▼';}}}sources.forEach((s,i)=>{const idx=page*8+i;if(!s.url)return;const ctrl=new AbortController();setTimeout(()=>ctrl.abort(),4000);fetch('/api/article?url='+encodeURIComponent(s.url),{signal:ctrl.signal}).then(r=>r.json()).then(d=>{if(d&&(d.og_image||d.img)){const el=document.getElementById('ht-img-'+idx);if(el)el.innerHTML=`<img src="${_proxyImg(esc(d.og_image||d.img))}" onerror="this.style.display='none'">`;}}).catch(()=>{});});}catch(e){box.innerHTML=`<div class="hashtag-sources"><h3>🔍 ${esc(topic)}</h3><div style="color:#e74c3c;padding:8px">Lỗi: ${esc(e.message)}</div></div>`;}}
1090
  function loadMoreHashtag(){_htPage++;const btn=document.getElementById('ht-more');if(btn){btn.disabled=true;btn.textContent='Đang tải...';}showHashtagSources(_htTopic,_htPage);}
1091
  async function rewriteHashtag(topic){const btn=event?.target;if(btn){btn.disabled=true;btn.textContent='Đang tổng hợp...';}try{const r=await fetch('/api/topic_post',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({topic})});const j=await r.json();if(!r.ok||j.error)throw new Error(j.error||'Lỗi');toast('✅ Đã đăng Tường AI!');if(btn)btn.textContent='✅ Đăng thành công!';if(j.post)prependWallPost(j.post);}catch(e){toast('❌ '+e.message);if(btn){btn.disabled=false;btn.textContent='🤖 Rewrite AI';}}}
1092
- async function loadLivescore(tab){document.querySelectorAll('.ls-tab').forEach(t=>t.classList.remove('active'));document.querySelector(`.ls-tab[data-tab="${tab}"]`)?.classList.add('active');const el=document.getElementById('ls-content');if(!el)return;el.innerHTML='<div class="loading">Đang tải...</div>';let ep='/api/livescore/'+tab;if(tab.startsWith('bxh_'))ep='/api/livescore/standings/'+tab.replace('bxh_','');try{const d=await _fetchWithTimeout(ep,12000);el.innerHTML=d.html&&d.html.length>50?d.html:'<div class="loading">Không có dữ liệu</div>';bindMatchClicks(el);}catch(e){el.innerHTML='<div class="loading">Lỗi tải hoặc hết thời gian</div>';}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1093
  function bindMatchClicks(el){el.querySelectorAll('.match-detail').forEach(md=>{md.style.cursor='pointer';md.addEventListener('click',function(e){const statusA=this.querySelector('.status a');const teamA=this.querySelector('.teams a[href*="/tran-dau/"]');const a = statusA || teamA;if(a){e.preventDefault();e.stopPropagation();const href=a.getAttribute('href')||'';const m=href.match(/\/tran-dau\/(\d+)\//);if(m){const fullUrl=href.startsWith('http')?href:'https://bongda.com.vn'+href;openMatch(m[1],fullUrl);}}});});el.querySelectorAll('a').forEach(a=>{a.addEventListener('click',e=>{e.preventDefault();e.stopPropagation()});});}
1094
  function openMatch(id,url){if(!id)return;_currentEventId=id;if(url)_currentMatchUrl=url;document.getElementById('match-overlay').classList.add('active');document.body.style.overflow='hidden';loadMatchTab('detail')}
1095
  function closeMatch(){document.getElementById('match-overlay').classList.remove('active');document.body.style.overflow=''}
 
152
  +'<div id="ai-wall-under-compose"></div>'
153
  +'<div id="hashtag-box"></div>'
154
  +'<div id="home-hl-section"></div>'
155
+ +'<div class="ls-section"><div class="ls-header"><h3>⚽ Livescore</h3></div><div class="ls-tabs"><span class="ls-tab active" data-tab="recent" onclick="loadLivescore(\'recent\')">📋 Cập nhật</span><span class="ls-tab" data-tab="live" onclick="loadLivescore(\'live\')">🔴 Live</span><span class="ls-tab" data-tab="today" onclick="loadLivescore(\'today\')">📅 Hôm nay</span><span class="ls-tab" data-tab="incoming" onclick="loadLivescore(\'incoming\')">⏰ Sắp tới</span><span class="ls-tab" data-tab="results" onclick="loadLivescore(\'results\')">✅ Kết quả</span><span class="ls-tab" data-tab="bxh_nha" onclick="loadLivescore(\'bxh_nha\')">🏆 NHA</span><span class="ls-tab" data-tab="bxh_laliga" onclick="loadLivescore(\'bxh_laliga\')">🏆 La Liga</span><span class="ls-tab" data-tab="bxh_seriea" onclick="loadLivescore(\'bxh_seriea\')">🏆 Serie A</span><span class="ls-tab" data-tab="bxh_bundesliga" onclick="loadLivescore(\'bxh_bundesliga\')">🏆 Bundesliga</span><span class="ls-tab" data-tab="bxh_ligue1" onclick="loadLivescore(\'bxh_ligue1\')">🏆 League 1</span></div><div class="ls-content" id="ls-content"><div class="loading">Đang tải...</div></div></div>'
156
  +'<div id="wc2026-live-section" class="wc2026-section"><div class="wc-header"><h2>🏆 World Cup 2026</h2><span class="wc-live-badge">● LIVE</span></div><div class="wc-tabs"><span class="wc-tab active" onclick="switchWCTab(\'news\')">📰 Tin tức</span><span class="wc-tab" onclick="switchWCTab(\'fixtures\')">📅 Lịch thi đấu</span><span class="wc-tab" onclick="switchWCTab(\'standings\')">🏆 BXH</span><span class="wc-tab" onclick="switchWCTab(\'highlights\')">🎬 Highlight</span><span class="wc-tab" onclick="switchWCTab(\'stats\')">📊 Thống kê</span></div><div class="wc-content" id="wc-content"><div class="loading">Đang tải World Cup 2026...</div></div></div>'
157
  +'<div id="home-after-wc"></div>';
158
 
 
1089
  async function showHashtagSources(topic,page){const box=document.getElementById('hashtag-box');if(!box)return;if(page===0)box.innerHTML=`<div class="hashtag-sources"><h3>🔍 ${esc(topic)}</h3><div class="hashtag-loading"><div class="hashtag-spinner"></div>Đang tìm...</div></div>`;try{const r=await fetch(`/api/hashtag/sources?topic=${encodeURIComponent(topic)}&page=${page}`);const j=await r.json();const sources=j.sources||[];if(!sources.length&&page===0){box.innerHTML=`<div class="hashtag-sources"><h3>🔍 ${esc(topic)}</h3><div style="color:#888;padding:8px">Không tìm được bài viết liên quan</div></div>`;return;}let h='';if(page===0)h=`<div class="hashtag-sources"><h3>🔍 ${esc(topic)} <span style="font-size:10px;color:#888">(${j.total} bài từ 8 nguồn)</span></h3><div id="ht-list">`;sources.forEach((s,i)=>{const idx=page*8+i;h+=`<div class="hashtag-src-item" onclick="readArticle('${esc(s.url)}')"><div class="hashtag-src-img" id="ht-img-${idx}"></div><div class="hashtag-src-text"><div class="hashtag-src-title">${esc(s.title)}</div><div class="hashtag-src-via">${esc(s.via||'')}</div></div></div>`;});if(page===0){h+=`</div><button class="hashtag-rewrite-btn" onclick="rewriteHashtag('${esc(topic).replace(/'/g,"\\'")}')">🤖 Rewrite AI tổng hợp & đăng tường</button>`;if(j.has_more)h+=`<button class="hashtag-load-more" id="ht-more" onclick="loadMoreHashtag()">Tải thêm ▼</button>`;h+=`</div>`;box.innerHTML=h;}else{document.getElementById('ht-list')?.insertAdjacentHTML('beforeend',h);const btn=document.getElementById('ht-more');if(btn){if(!j.has_more)btn.remove();else{btn.disabled=false;btn.textContent='Tải thêm ▼';}}}sources.forEach((s,i)=>{const idx=page*8+i;if(!s.url)return;const ctrl=new AbortController();setTimeout(()=>ctrl.abort(),4000);fetch('/api/article?url='+encodeURIComponent(s.url),{signal:ctrl.signal}).then(r=>r.json()).then(d=>{if(d&&(d.og_image||d.img)){const el=document.getElementById('ht-img-'+idx);if(el)el.innerHTML=`<img src="${_proxyImg(esc(d.og_image||d.img))}" onerror="this.style.display='none'">`;}}).catch(()=>{});});}catch(e){box.innerHTML=`<div class="hashtag-sources"><h3>🔍 ${esc(topic)}</h3><div style="color:#e74c3c;padding:8px">Lỗi: ${esc(e.message)}</div></div>`;}}
1090
  function loadMoreHashtag(){_htPage++;const btn=document.getElementById('ht-more');if(btn){btn.disabled=true;btn.textContent='Đang tải...';}showHashtagSources(_htTopic,_htPage);}
1091
  async function rewriteHashtag(topic){const btn=event?.target;if(btn){btn.disabled=true;btn.textContent='Đang tổng hợp...';}try{const r=await fetch('/api/topic_post',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({topic})});const j=await r.json();if(!r.ok||j.error)throw new Error(j.error||'Lỗi');toast('✅ Đã đăng Tường AI!');if(btn)btn.textContent='✅ Đăng thành công!';if(j.post)prependWallPost(j.post);}catch(e){toast('❌ '+e.message);if(btn){btn.disabled=false;btn.textContent='🤖 Rewrite AI';}}}
1092
+ async function loadLivescore(tab){document.querySelectorAll('.ls-tab').forEach(t=>t.classList.remove('active'));document.querySelector(`.ls-tab[data-tab="${tab}"]`)?.classList.add('active');const el=document.getElementById('ls-content');if(!el)return;el.innerHTML='<div class="loading">Đang tải...</div>';let ep='/api/livescore/'+tab;if(tab.startsWith('bxh_'))ep='/api/livescore/standings/'+tab.replace('bxh_','');try{const d=await _fetchWithTimeout(ep,12000);el.innerHTML=d.html&&d.html.length>50?d.html:'<div class="loading">Không có dữ liệu</div>';bindMatchClicks(el);if(tab.startsWith('bxh_'))_decorateStandings(el);}catch(e){el.innerHTML='<div class="loading">Lỗi tải hoặc hết thời gian</div>';}}
1093
+ function _decorateStandings(el){
1094
+ try{
1095
+ const items=el.querySelectorAll('.leaderboard-item');
1096
+ if(!items.length)return;
1097
+ // Build header row: # | Đội bóng | Tr T H B BT BB +/- Đ
1098
+ const head=document.createElement('div');
1099
+ head.className='ls-bxh-head';
1100
+ head.innerHTML='<div class="team"><span>#</span><a class="link"><p>Đội bóng</p></a></div><div class="copy"><p>Tr</p><p>T</p><p>H</p><p>B</p><p>BT</p><p>BB</p><p>+/-</p><p>Đ</p></div>';
1101
+ el.insertBefore(head, items[0]);
1102
+ // Make each row use flex layout with the copy cells as a fixed-width grid
1103
+ items.forEach(function(it){
1104
+ it.classList.add('ls-bxh-row');
1105
+ });
1106
+ }catch(e){}
1107
+ }
1108
  function bindMatchClicks(el){el.querySelectorAll('.match-detail').forEach(md=>{md.style.cursor='pointer';md.addEventListener('click',function(e){const statusA=this.querySelector('.status a');const teamA=this.querySelector('.teams a[href*="/tran-dau/"]');const a = statusA || teamA;if(a){e.preventDefault();e.stopPropagation();const href=a.getAttribute('href')||'';const m=href.match(/\/tran-dau\/(\d+)\//);if(m){const fullUrl=href.startsWith('http')?href:'https://bongda.com.vn'+href;openMatch(m[1],fullUrl);}}});});el.querySelectorAll('a').forEach(a=>{a.addEventListener('click',e=>{e.preventDefault();e.stopPropagation()});});}
1109
  function openMatch(id,url){if(!id)return;_currentEventId=id;if(url)_currentMatchUrl=url;document.getElementById('match-overlay').classList.add('active');document.body.style.overflow='hidden';loadMatchTab('detail')}
1110
  function closeMatch(){document.getElementById('match-overlay').classList.remove('active');document.body.style.overflow=''}
static/fm_fix.css CHANGED
@@ -168,3 +168,123 @@
168
  min-width:100%!important;max-width:none!important;max-height:none!important;
169
  object-fit:cover!important;
170
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  min-width:100%!important;max-width:none!important;max-height:none!important;
169
  object-fit:cover!important;
170
  }
171
+
172
+ /* ============================================================
173
+ BXH / BÅNG XẼP HẠNG (standing league table) FIX
174
+ Bongda returns div-based Tailwind rows (.ranking-table .leaderboard
175
+ .leaderboard-item / .head / .team / .copy). The old CSS only styled
176
+ <table> so the standings rendered broken. Style the divs directly.
177
+ ============================================================ */
178
+ #ls-content .ranking-table,
179
+ #ls-content .leaderboard{display:block!important;width:100%!important}
180
+ #ls-content .ranking-table .head,
181
+ #ls-content .leaderboard .head{display:flex!important;width:100%!important;background:#222!important;border-bottom:1px solid #333!important;padding:5px 0!important;font-size:10px!important;color:#999!important}
182
+ #ls-content .ranking-table .head .team,
183
+ #ls-content .leaderboard .head .team{flex:1 1 auto!important;min-width:0!important}
184
+ #ls-content .ranking-table .head .team span,
185
+ #ls-content .leaderboard .head .team span{display:inline-block!important;width:18px!important;text-align:center!important;color:#888!important}
186
+ #ls-content .ranking-table .head .team .link,
187
+ #ls-content .leaderboard .head .team .link{font-size:10px!important;color:#999!important;font-weight:700!important}
188
+ #ls-content .ranking-table .head .copy,
189
+ #ls-content .leaderboard .head .copy{display:flex!important;gap:2px!important;align-items:center!important;justify-content:flex-end!important;min-width:0!important}
190
+ #ls-content .ranking-table .head .copy p,
191
+ #ls-content .leaderboard .head .copy p{font-size:9px!important;color:#888!important;min-width:16px!important;text-align:center!important;margin:0!important}
192
+ #ls-content .ranking-table .head .copy p.form,
193
+ #ls-content .leaderboard .head .copy p.form{display:none!important}
194
+ #ls-content .ranking-table .leaderboard-item,
195
+ #ls-content .ranking-table #team_,
196
+ #ls-content .leaderboard .leaderboard-item{
197
+ display:table!important;width:100%!important;table-layout:fixed!important;
198
+ border-collapse:collapse!important;border-bottom:1px solid #1a1a1a!important;
199
+ font-size:11px!important;color:#ccc!important;background:transparent!important
200
+ }
201
+ #ls-content .ranking-table .leaderboard-item>div.team,
202
+ #ls-content .ranking-table .leaderboard-item>.team,
203
+ #ls-content .leaderboard .leaderboard-item .team{
204
+ display:table-cell!important;vertical-align:middle!important;
205
+ padding:5px 4px!important;text-align:left!important;min-width:0!important
206
+ }
207
+ #ls-content .ranking-table .leaderboard-item>div.team span,
208
+ #ls-content .ranking-table .leaderboard-item>.team span{
209
+ display:inline-block!important;width:18px!important;min-width:18px!important;
210
+ text-align:center!important;font-size:10px!important;color:#888!important;font-weight:600!important
211
+ }
212
+ #ls-content .ranking-table .leaderboard-item>div.team a.link,
213
+ #ls-content .ranking-table .leaderboard-item>.team a.link{
214
+ display:inline-flex!important;align-items:center!important;gap:4px!important;
215
+ min-width:0!important;font-size:11px!important;color:#ccc!important;text-decoration:none!important
216
+ }
217
+ #ls-content .ranking-table .leaderboard-item>div.team a.link img,
218
+ #ls-content .ranking-table .leaderboard-item>.team a.link img{width:16px!important;height:16px!important;object-fit:contain!important;flex:0 0 auto!important}
219
+ #ls-content .ranking-table .leaderboard-item>div.team a.link p,
220
+ #ls-content .ranking-table .leaderboard-item>.team a.link p{
221
+ font-size:11px!important;color:#ccc!important;margin:0!important;
222
+ white-space:nowrap!important;overflow:hidden!important;text-overflow:ellipsis!important
223
+ }
224
+ #ls-content .ranking-table .leaderboard-item>div.copy,
225
+ #ls-content .ranking-table .leaderboard-item>.copy,
226
+ #ls-content .leaderboard .leaderboard-item .copy{
227
+ display:table-cell!important;vertical-align:middle!important;
228
+ padding:5px 2px!important;text-align:center!important;white-space:nowrap!important
229
+ }
230
+ #ls-content .ranking-table .leaderboard-item>div.copy p,
231
+ #ls-content .ranking-table .leaderboard-item>.copy p{
232
+ display:inline-block!important;min-width:22px!important;text-align:center!important;
233
+ font-size:11px!important;color:#ccc!important;margin:0 1px!important
234
+ }
235
+ #ls-content .ranking-table .leaderboard-item>div.copy p strong,
236
+ #ls-content .ranking-table .leaderboard-item>.copy p strong{
237
+ display:inline-block!important;min-width:22px!important;text-align:center!important;
238
+ font-weight:800!important;color:#f0c040!important;font-size:12px!important
239
+ }
240
+ #ls-content .ranking-table .leaderboard-item>div.copy p.form,
241
+ #ls-content .ranking-table .leaderboard-item>.copy p.form{display:inline-flex!important;flex-wrap:nowrap!important}
242
+ #ls-content .ranking-table .leaderboard-item>div.copy p.form span,
243
+ #ls-content .ranking-table .leaderboard-item>.copy p.form span{
244
+ display:inline-block!important;min-width:14px!important;height:14px!important;
245
+ line-height:14px!important;text-align:center!important;font-size:9px!important;
246
+ border-radius:2px!important;margin:0 1px!important;color:#fff!important
247
+ }
248
+ #ls-content .ranking-table .leaderboard-item>div.copy p.form span.bg-green,
249
+ #ls-content .ranking-table .leaderboard-item>.copy p.form span.bg-green{background:#2d8659!important}
250
+ #ls-content .ranking-table .leaderboard-item>div.copy p.form span.bg-gray-5,
251
+ #ls-content .ranking-table .leaderboard-item>.copy p.form span.bg-gray-5,
252
+ #ls-content .leaderboard .leaderboard-item .copy p.form span.bg-gray-5,
253
+ #ls-content .ranking-table .leaderboard-item .copy p.form span.bg-gray-5{background:#555!important;color:#ccc!important}
254
+ #ls-content .ranking-table .leaderboard-item>div.copy p.form span.bg-red,
255
+ #ls-content .ranking-table .leaderboard-item>.copy p.form span.bg-red{background:#c0392b!important}
256
+ /* hide the bongda left accent bar that floats absolutely */
257
+ #ls-content .ranking-table .leaderboard-item>div[class*="w-["],
258
+ #ls-content .ranking-table .leaderboard-item div.relative{display:none!important}
259
+ /* top row = champion accent can stay, but clean layout */
260
+ #ls-content .leaderboard-item{margin:0!important}
261
+ #ls-content .rank-table{width:100%!important;overflow-x:auto!important}
262
+ /* fallback generic so ANY div-based standings table gets readable */
263
+ #ls-content .team .name,#ls-content .team .logo{font-size:11px!important;color:#ccc!important}
264
+ #ls-content .copy p{font-size:11px!important;color:#ccc!important}
265
+ /* injected BXH header + row layout (see _decorateStandings in app_v2.js) */
266
+ #ls-content .ls-bxh-head{
267
+ display:flex!important;width:100%!important;align-items:center!important;gap:4px!important;
268
+ background:#222!important;border-bottom:1px solid #333!important;
269
+ padding:5px 2px!important;position:sticky!important;top:0!important;z-index:2!important
270
+ }
271
+ #ls-content .ls-bxh-head .team{flex:1!important;min-width:0!important;display:flex!important;align-items:center!important;gap:4px!important}
272
+ #ls-content .ls-bxh-head .team span{display:inline-block!important;width:18px!important;min-width:18px!important;text-align:center!important;color:#888!important;font-size:10px!important;font-weight:700!important}
273
+ #ls-content .ls-bxh-head .team p{font-size:10px!important;color:#999!important;font-weight:700!important;margin:0!important;text-transform:uppercase!important}
274
+ #ls-content .ls-bxh-head .copy{display:flex!important;align-items:center!important;gap:2px!important;white-space:nowrap!important}
275
+ #ls-content .ls-bxh-head .copy p{display:inline-block!important;min-width:20px!important;text-align:center!important;font-size:9px!important;color:#888!important;font-weight:700!important;margin:0!important}
276
+ #ls-content .leaderboard-item{display:flex!important;width:100%!important;align-items:center!important;gap:4px!important;border-bottom:1px solid #1a1a1a!important;padding:4px 2px!important;background:transparent!important}
277
+ #ls-content .leaderboard-item .team{flex:1!important;min-width:0!important;display:flex!important;align-items:center!important;gap:4px!important}
278
+ #ls-content .leaderboard-item .team span{display:inline-block!important;width:18px!important;min-width:18px!important;text-align:center!important;color:#888!important;font-size:10px!important;font-weight:600!important}
279
+ #ls-content .leaderboard-item .team a{display:inline-flex!important;align-items:center!important;gap:4px!important;font-size:11px!important;color:#ccc!important;text-decoration:none!important;overflow:hidden!important;min-width:0!important}
280
+ #ls-content .leaderboard-item .team a img{width:16px!important;height:16px!important;object-fit:contain!important;flex:0 0 auto!important}
281
+ #ls-content .leaderboard-item .team a p{font-size:11px!important;color:#ccc!important;margin:0!important;white-space:nowrap!important;overflow:hidden!important;text-overflow:ellipsis!important}
282
+ #ls-content .leaderboard-item .copy{display:flex!important;align-items:center!important;gap:2px!important;white-space:nowrap!important}
283
+ #ls-content .leaderboard-item .copy p{display:inline-block!important;min-width:20px!important;text-align:center!important;font-size:11px!important;color:#ccc!important;margin:0!important}
284
+ #ls-content .leaderboard-item .copy p strong{font-weight:800!important;color:#f0c040!important;min-width:20px!important;text-align:center!important}
285
+ #ls-content .leaderboard-item .copy p.form{display:inline-flex!important;flex-wrap:nowrap!important}
286
+ #ls-content .leaderboard-item .copy p.form span{width:14px!important;height:14px!important;line-height:14px!important;font-size:9px!important;border-radius:2px!important;color:#fff!important;margin:0 1px!important;text-align:center!important}
287
+ #ls-content .leaderboard-item .copy p.form span.bg-green{background:#2d8659!important;display:inline-block!important}
288
+ #ls-content .leaderboard-item .copy p.form span.bg-gray-5{background:#555!important;color:#ccc!important;display:inline-block!important}
289
+ #ls-content .leaderboard-item .copy p.form span.bg-red{background:#c0392b!important;display:inline-block!important}
290
+ #ls-content .leaderboard-item>div[class*="w-["]{display:none!important}
static/index_v2.html CHANGED
@@ -75,7 +75,7 @@ function doShare(title,url,img,postId){
75
  async function init(){_cats=await fetch('/api/categories').then(r=>r.json()).catch(()=>[]);let bar='<div class="cat active" data-cat="home">🏠</div><div class="cat" data-cat="news-all">📰 Tin tức</div>';_cats.forEach(c=>{bar+='<div class="cat" data-cat="'+c.id+'">'+c.name+'</div>'});document.getElementById('cat-bar').innerHTML=bar;document.querySelectorAll('.cat').forEach(t=>{t.onclick=()=>switchCat(t.dataset.cat)});}
76
  var SPACE=location.origin;
77
  </script>
78
- <script src="/static/app_v2.js?v=20260821j"></script>
79
  <script src="/static/designer_v2.js?v=20260817fix1"></script>
80
  <script src="/static/yt_live.js"></script>
81
  <script src="/static/vtv_init.js"></script>
 
75
  async function init(){_cats=await fetch('/api/categories').then(r=>r.json()).catch(()=>[]);let bar='<div class="cat active" data-cat="home">🏠</div><div class="cat" data-cat="news-all">📰 Tin tức</div>';_cats.forEach(c=>{bar+='<div class="cat" data-cat="'+c.id+'">'+c.name+'</div>'});document.getElementById('cat-bar').innerHTML=bar;document.querySelectorAll('.cat').forEach(t=>{t.onclick=()=>switchCat(t.dataset.cat)});}
76
  var SPACE=location.origin;
77
  </script>
78
+ <script src="/static/app_v2.js?v=20260821k"></script>
79
  <script src="/static/designer_v2.js?v=20260817fix1"></script>
80
  <script src="/static/yt_live.js"></script>
81
  <script src="/static/vtv_init.js"></script>
static/live_mode.js CHANGED
@@ -23,7 +23,22 @@
23
  .hashtag-src-img img{width:100%!important;height:100%!important;object-fit:cover!important}
24
  .hashtag-src-text{flex:1!important;min-width:0!important}
25
  .hashtag-src-title{font-size:12px!important;font-weight:700!important;color:#eee!important;display:-webkit-box!important;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden!important}
26
- .hashtag-src-via{font-size:10px!important;color:#888!important;margin-top:2px!important}`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  document.head.appendChild(style);
28
 
29
  // Load rewrite fix
 
23
  .hashtag-src-img img{width:100%!important;height:100%!important;object-fit:cover!important}
24
  .hashtag-src-text{flex:1!important;min-width:0!important}
25
  .hashtag-src-title{font-size:12px!important;font-weight:700!important;color:#eee!important;display:-webkit-box!important;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden!important}
26
+ .hashtag-src-via{font-size:10px!important;color:#888!important;margin-top:2px!important}
27
+ #ls-content .ranking-table .head,#ls-content .leaderboard .head{width:100%!important}
28
+ #ls-content .ranking-table .leaderboard-item,#ls-content .leaderboard .leaderboard-item{display:flex!important;width:100%!important;align-items:center!important;gap:4px!important;border-bottom:1px solid #1a1a1a!important;padding:4px 2px!important;background:transparent!important}
29
+ #ls-content .ranking-table .leaderboard-item>div.team,#ls-content .ranking-table .leaderboard-item>.team,#ls-content .leaderboard .leaderboard-item .team{flex:1!important;min-width:0!important;display:flex!important;align-items:center!important;gap:4px!important}
30
+ #ls-content .leaderboard-item .team a{display:inline-flex!important;align-items:center!important;gap:4px!important;font-size:11px!important;color:#ccc!important;text-decoration:none!important;overflow:hidden!important}
31
+ #ls-content .leaderboard-item .team a img{width:16px!important;height:16px!important;object-fit:contain!important}
32
+ #ls-content .leaderboard-item .team a p{font-size:11px!important;color:#ccc!important;margin:0!important;white-space:nowrap!important;overflow:hidden!important;text-overflow:ellipsis!important}
33
+ #ls-content .leaderboard-item .copy{display:flex!important;align-items:center!important;gap:2px!important;white-space:nowrap!important}
34
+ #ls-content .leaderboard-item .copy p{display:inline-block!important;min-width:20px!important;text-align:center!important;font-size:11px!important;color:#ccc!important;margin:0!important}
35
+ #ls-content .leaderboard-item .copy p strong{font-weight:800!important;color:#f0c040!important;min-width:20px!important;text-align:center!important}
36
+ #ls-content .leaderboard-item .copy p.form span{width:14px!important;height:14px!important;line-height:14px!important;font-size:9px!important;border-radius:2px!important;color:#fff!important;margin:0 1px!important}
37
+ #ls-content .leaderboard-item .copy p.form span.bg-green{background:#2d8659!important}
38
+ #ls-content .leaderboard-item .copy p.form span.bg-gray-5{background:#555!important;color:#ccc!important}
39
+ #ls-content .leaderboard-item .copy p.form span.bg-red{background:#c0392b!important}
40
+ #ls-content .leaderboard-item>div[class*="w-["]{display:none!important}
41
+ #ls-content .leaderboard-item .w-\[2px\]{display:none!important}`;
42
  document.head.appendChild(style);
43
 
44
  // Load rewrite fix