diff --git a/apps/extensions/public/store.css b/apps/extensions/public/store.css
index edde84f..9c028ac 100644
--- a/apps/extensions/public/store.css
+++ b/apps/extensions/public/store.css
@@ -92,6 +92,15 @@ input:focus, textarea:focus, select:focus { outline: none; border-color: var(--a
font-weight: 800; color: #04211d; background: linear-gradient(135deg, var(--accent), var(--accent-2));
flex: 0 0 auto;
}
+/* Real logo (usually a transparent PNG): contain it in a padded, bordered tile
+ and drop the gradient. The backdrop is chosen from the logo's luminance in
+ store.js (hydrateIcons); a neutral panel shows until then. */
+img.avatar.icon {
+ background: var(--panel); border: 1px solid var(--border);
+ padding: 5px; object-fit: contain;
+}
+img.avatar.icon.icon-dark { background: #0b1018; }
+img.avatar.icon.icon-light { background: #ffffff; border-color: rgba(0, 0, 0, 0.12); }
.card h3 { margin: 0; font-size: 16px; }
.card .summary { color: var(--muted); font-size: 14px; margin: 0; min-height: 38px; }
.card .meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: auto; }
diff --git a/apps/extensions/public/store.js b/apps/extensions/public/store.js
index 2ef873d..ab63b69 100644
--- a/apps/extensions/public/store.js
+++ b/apps/extensions/public/store.js
@@ -8,10 +8,52 @@ function qs(name) { return new URLSearchParams(location.search).get(name); }
function initials(name) { return (name || '?').trim().split(/\s+/).slice(0, 2).map((w) => w[0] || '').join('').toUpperCase(); }
// Logo if the listing has one (auto-ingested from the .crx icons), else initials.
+// Most logos are transparent PNGs, so we render them CONTAINED (never cropped)
+// and pick a light or dark backdrop from the logo's own luminance in
+// hydrateIcons() — otherwise a transparent logo shows over the gradient avatar
+// and looks muddy.
function avatar(ext, px) {
- const style = px ? ` style="width:${px}px;height:${px}px"` : '';
- if (ext.iconUrl) return ``;
- return `
Couldn't load extensions: ${esc(e.message)}
`; } @@ -162,6 +205,7 @@ async function initDetail() {Chromium auto-updates this extension from its update_url:
${esc(ext.updateUrl)}`;
+ hydrateIcons(root);
document.getElementById('flagBtn').addEventListener('click', async () => {
const reason = prompt('Reason? (malware, privacy, broken, spam, other)', 'other');