@@ -827,30 +827,87 @@ void MainWindow::displayRandomGames() {
827827 imgLabel->setScaledContents (true );
828828 stack->addWidget (imgLabel);
829829
830+ // Dark gradient overlay (left-to-right for portrait+text layout)
830831 QWidget* overlay = new QWidget ();
831832 overlay->setFixedHeight (240 );
832833 overlay->setStyleSheet (
833- " background: qlineargradient(x1:0, y1:1 , x2:0 , y2:0, stop:0 rgba(0,0,0,220 ), stop:0.4 rgba(0,0,0,0 ));"
834+ " background: qlineargradient(x1:0, y1:0 , x2:1 , y2:0, stop:0 rgba(0,0,0,210 ), stop:0.55 rgba(0,0,0,120), stop:1 rgba(0,0,0,30 ));"
834835 " border-radius: 12px;"
835836 );
836- QVBoxLayout* overlayLayout = new QVBoxLayout (overlay);
837- overlayLayout->addStretch (1 );
837+
838+ // Horizontal layout: portrait on left, text info on right
839+ QHBoxLayout* heroLayout = new QHBoxLayout (overlay);
840+ heroLayout->setContentsMargins (20 , 15 , 20 , 15 );
841+ heroLayout->setSpacing (24 );
842+
843+ // Portrait thumbnail (left side)
844+ QLabel* portraitLabel = new QLabel ();
845+ portraitLabel->setFixedSize (130 , 200 );
846+ portraitLabel->setStyleSheet (
847+ " background: rgba(255,255,255,8); border: 1px solid rgba(255,255,255,15); border-radius: 8px;"
848+ );
849+ portraitLabel->setScaledContents (true );
850+ heroLayout->addWidget (portraitLabel);
851+
852+ // Game info column
853+ QVBoxLayout* infoLayout = new QVBoxLayout ();
854+ infoLayout->setSpacing (6 );
855+ infoLayout->addStretch (1 );
856+
857+ QLabel* badgeLbl = new QLabel (QString::fromUtf8 (" \xe2\x98\x85 FEATURED" ));
858+ badgeLbl->setStyleSheet (
859+ " font-size: 11px; font-weight: 700; color: #FFB74D; letter-spacing: 2px;"
860+ " background: transparent; border: none; font-family: 'Roboto', 'Segoe UI';"
861+ );
862+ infoLayout->addWidget (badgeLbl);
838863
839864 QLabel* nameLbl = new QLabel (featuredName);
840- nameLbl->setStyleSheet (" font-size: 26px; font-weight: bold; color: white; background: transparent; border: none;" );
841- nameLbl->setAlignment (Qt::AlignHCenter);
842- overlayLayout->addWidget (nameLbl);
865+ nameLbl->setStyleSheet (
866+ " font-size: 26px; font-weight: bold; color: white; background: transparent; border: none;"
867+ " font-family: 'Roboto', 'Segoe UI';"
868+ );
869+ nameLbl->setWordWrap (true );
870+ infoLayout->addWidget (nameLbl);
843871
844872 QLabel* idLbl = new QLabel (QString (" App ID: %1" ).arg (featuredId));
845- idLbl->setStyleSheet (" font-size: 14px; color: #aaaaaa; background: transparent; border: none;" );
846- idLbl->setAlignment (Qt::AlignHCenter);
847- overlayLayout->addWidget (idLbl);
848- overlayLayout->addSpacing (15 );
873+ idLbl->setStyleSheet (
874+ " font-size: 13px; color: rgba(255,255,255,140); background: transparent; border: none;"
875+ " font-family: 'Roboto', 'Segoe UI';"
876+ );
877+ infoLayout->addWidget (idLbl);
878+ infoLayout->addStretch (1 );
879+
880+ heroLayout->addLayout (infoLayout, 1 );
849881
850882 stack->addWidget (overlay);
851883 m_heroStack->addWidget (slide);
852884
853- // Fetch high-quality hero image, with fallback to low-res header
885+ // Fetch portrait thumbnail for left side
886+ QString portraitUrl = QString (" https://cdn.akamai.steamstatic.com/steam/apps/%1/library_600x900_2x.jpg" ).arg (featuredId);
887+ QNetworkRequest portraitReq{QUrl (portraitUrl)};
888+ portraitReq.setHeader (QNetworkRequest::UserAgentHeader, " SteamLuaPatcher/2.0" );
889+ QNetworkReply* portraitReply = m_networkManager->get (portraitReq);
890+ QPointer<QLabel> safePortrait (portraitLabel);
891+ connect (portraitReply, &QNetworkReply::finished, this , [portraitReply, safePortrait]() {
892+ portraitReply->deleteLater ();
893+ if (portraitReply->error () == QNetworkReply::NoError && safePortrait) {
894+ QPixmap rawPix;
895+ if (rawPix.loadFromData (portraitReply->readAll ())) {
896+ QPixmap rounded (130 , 200 );
897+ rounded.fill (Qt::transparent);
898+ QPainter p (&rounded);
899+ p.setRenderHint (QPainter::Antialiasing);
900+ QPainterPath clipPath;
901+ clipPath.addRoundedRect (rounded.rect (), 8 , 8 );
902+ p.setClipPath (clipPath);
903+ p.drawPixmap (rounded.rect (), rawPix.scaled (130 , 200 , Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation));
904+ p.end ();
905+ if (safePortrait) safePortrait->setPixmap (rounded);
906+ }
907+ }
908+ });
909+
910+ // Fetch high-quality hero image for background, with fallback to low-res header
854911 QString heroUrl = QString (" https://cdn.akamai.steamstatic.com/steam/apps/%1/library_hero.jpg" ).arg (featuredId);
855912 QNetworkRequest req{QUrl (heroUrl)};
856913 req.setHeader (QNetworkRequest::UserAgentHeader, " SteamLuaPatcher/2.0" );
@@ -864,21 +921,19 @@ void MainWindow::displayRandomGames() {
864921 if (heroReply->error () == QNetworkReply::NoError && safeImgLabel) {
865922 QPixmap rawPix;
866923 if (rawPix.loadFromData (heroReply->readAll ())) {
867- // Create rounded version to ensure corners aren't sharp
868924 QPixmap rounded (rawPix.size ());
869925 rounded.fill (Qt::transparent);
870926 QPainter painter (&rounded);
871927 painter.setRenderHint (QPainter::Antialiasing);
872928 QPainterPath path;
873- path.addRoundedRect (rounded.rect (), 35 , 35 ); // Visual radius for the raw buffer
929+ path.addRoundedRect (rounded.rect (), 35 , 35 );
874930 painter.setClipPath (path);
875931 painter.drawPixmap (0 , 0 , rawPix);
876932
877933 if (safeImgLabel) safeImgLabel->setPixmap (rounded);
878934 success = true ;
879935 }
880936 }
881- // Fallback strategy if HD library hero is missing (fetch low-res header)
882937 if (!success && safeImgLabel && nm) {
883938 QString fallbackUrl = QString (" https://cdn.akamai.steamstatic.com/steam/apps/%1/header.jpg" ).arg (featuredId);
884939 QNetworkRequest fallbackReq{QUrl (fallbackUrl)};
0 commit comments