diff --git a/public/banner.js b/public/banner.js index dddcc62..b81cacc 100644 --- a/public/banner.js +++ b/public/banner.js @@ -10,16 +10,19 @@ * * * Query parameters (appended to the script src URL): - * lang=fr Override the browser language (default: auto-detected) - * id=myDiv Insert the banner inside the element with this id - * (default: prepend to
) - * size=normal Banner size: "normal" (default), "mini" or "minimal" - * link=URL Make the banner text a link (default: https://keepandroidopen.org) - * Set link=none to disable the link - * hidebutton=on Show an X close button (default: on) - * Set hidebutton=off to hide the close button - * animation=on Add animation to border of banner (default: on) - * Set animation=off to disable + * lang=fr Override the browser language (default: auto-detected) + * id=myDiv Insert the banner inside the element with this id + * (default: prepend to ) + * size=normal Banner size: "normal" (default), "mini" or "minimal" + * link=URL Make the banner text a link (default: https://keepandroidopen.org) + * Set link=none to disable the link + * hidebutton=on Show an X close button (default: on) + * Set hidebutton=off to hide the close button + * animation=on Add animation to the banner (default: on) + * Set animation=off to disable + * theme=auto Color theme: "auto" (default), "light", or "dark" + * style=modern Visual style: "modern" (default) or "classic" + * classic = the pre-2026 bold all-caps red design */ (function () { "use strict"; @@ -30,32 +33,32 @@ ar: "سيصبح نظام أندرويد منصة مغلقة في", he: "אנדרואיד תהפוך לפלטפורמה נעולה בעוד", en: "Android will become a locked-down platform in", - ca: "Android es convertir\u00E0 en una plataforma tancada", + ca: "Android es convertirà en una plataforma tancada", cs: "Android se stane uzamčenou platformou za", de: "Android wird eine geschlossene Plattform werden.", da: "Android vil blive en lukket platform om", nl: "Android zal een gesloten platform worden over", - el: "\u03A4\u03BF Android \u03B8\u03B1 \u03B3\u03AF\u03BD\u03B5\u03B9 \u03BC\u03AF\u03B1 \u03BA\u03BB\u03B5\u03B9\u03C3\u03C4\u03AE \u03C0\u03BB\u03B1\u03C4\u03C6\u03CC\u03C1\u03BC\u03B1", - es: "Android se convertir\u00E1 en una plataforma cerrada en", - fr: "Android va devenir une plateforme ferm\u00E9e dans", + el: "Το Android θα γίνει μία κλειστή πλατφόρμα", + es: "Android se convertirá en una plataforma cerrada en", + fr: "Android va devenir une plateforme fermée dans", id: "Android akan menjadi platform yang terkunci.", - it: "Android diventer\u00E0 una piattaforma bloccata", - ko: "Android\uAC00 \uD3D0\uC1C4\uB41C \uD50C\uB7AB\uD3FC\uC774 \uB418\uAE30\uAE4C\uC9C0 \uB0A8\uC740 \uC2DC\uAC04:", - pl: "Android stanie si\u0119 platform\u0105 zamkni\u0119t\u0105 za", - "pt-BR": "O Android se tornar\u00E1 uma plataforma fechada em", - ru: "Android \u0441\u0442\u0430\u043D\u0435\u0442 \u0437\u0430\u043A\u0440\u044B\u0442\u043E\u0439 \u043F\u043B\u0430\u0442\u0444\u043E\u0440\u043C\u043E\u0439 \u0447\u0435\u0440\u0435\u0437", + it: "Android diventerà una piattaforma bloccata", + ko: "Android가 폐쇄된 플랫폼이 되기까지 남은 시간:", + pl: "Android stanie się platformą zamkniętą za", + "pt-BR": "O Android se tornará uma plataforma fechada em", + ru: "Android станет закрытой платформой через", sk: "Android sa stane uzamknutou platformou", - th: "Android\u0E08\u0E30\u0E40\u0E1B\u0E47\u0E19\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21\u0E17\u0E35\u0E48\u0E16\u0E39\u0E01\u0E25\u0E47\u0E2D\u0E01", - tr: "Android k\u0131s\u0131tl\u0131 bir platform haline gelecek.", - uk: "Android \u0441\u0442\u0430\u043D\u0435 \u0437\u0430\u043A\u0440\u0438\u0442\u043E\u044E \u043F\u043B\u0430\u0442\u0444\u043E\u0440\u043C\u043E\u044E", - "zh-CN": "\u5B89\u5353\u5C06\u6210\u4E3A\u4E00\u4E2A\u5C01\u95ED\u5E73\u53F0", - "zh-TW": "Android \u5C07\u6210\u70BA\u4E00\u500B\u5C01\u9589\u5E73\u53F0", + th: "Androidจะเป็นแพลตฟอร์มที่ถูกล็อก", + tr: "Android kısıtlı bir platform haline gelecek.", + uk: "Android стане закритою платформою", + "zh-CN": "安卓将成为一个封闭平台", + "zh-TW": "Android 將成為一個封閉平台", ja: "Androidは閉鎖的なプラットフォームになろうとしています", fi: "Androidista tulee suljettu alusta", hu: "Az Android egy lezárt platform lesz", vi: "Android sẽ trở thành một hệ điều hành đóng", bg: "Android ще стане заключена платформа след", - be: "Android \u0441\u0442\u0430\u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u0430\u0439 \u043f\u043b\u0430\u0444\u0442\u043e\u0440\u043c\u0430\u0439 \u0020 \u0020", + be: "Android стане закрытай плафтормай ", }; // ── Parse query parameters from the script's own src URL ────────────── @@ -112,6 +115,15 @@ ? "minimal" : "normal"; + // ── Theme (new) ─────────────────────────────────────────────────────── + var theme = params.theme === "dark" ? "dark" + : params.theme === "light" + ? "light" + : "auto"; + + // ── Style (new): "modern" (default) or "classic" (the original look) ── + var styleMode = params.style === "classic" ? "classic" : "modern"; + // ── Link ──────────────────────────────────────────────────────────── var linkParam = params.link; var defaultLink = "https://keepandroidopen.org" + (locale === "en" ? "" : "/" + locale + "/"); @@ -121,10 +133,207 @@ var showClose = params.hidebutton !== "off"; var storageKey = "kao-banner-hidden"; var dismissDays = 30; + var noAnim = params.animation === "off"; + + // ── CSS: tokens (light + dark + auto) ──────────────────────────────── + var cssTokens = + ".kao-banner.kao-banner--style-modern{" + + "--kao-bg-from:#fff1d0;--kao-bg-to:#ffe1a0;" + + "--kao-fg:#4a3000;--kao-fg-strong:#2a1a00;" + + "--kao-accent:#b85d00;--kao-accent-strong:#7a3d00;" + + "--kao-border:rgba(184,93,0,.32);--kao-pill-bg:rgba(184,93,0,.14);" + + "--kao-stripe:rgba(184,93,0,.10);--kao-glow:rgba(255,184,77,.45);" + + "}" + + ".kao-banner.kao-banner--style-modern.kao-banner--theme-dark{" + + "--kao-bg-from:#2a1f08;--kao-bg-to:#3a2c10;" + + "--kao-fg:#ffd9a3;--kao-fg-strong:#fff1dc;" + + "--kao-accent:#ffb84d;--kao-accent-strong:#ffce80;" + + "--kao-border:rgba(255,184,77,.34);--kao-pill-bg:rgba(255,184,77,.14);" + + "--kao-stripe:rgba(255,184,77,.10);--kao-glow:rgba(255,184,77,.30);" + + "}" + + "@media(prefers-color-scheme:dark){" + + ".kao-banner.kao-banner--style-modern.kao-banner--theme-auto{" + + "--kao-bg-from:#2a1f08;--kao-bg-to:#3a2c10;" + + "--kao-fg:#ffd9a3;--kao-fg-strong:#fff1dc;" + + "--kao-accent:#ffb84d;--kao-accent-strong:#ffce80;" + + "--kao-border:rgba(255,184,77,.34);--kao-pill-bg:rgba(255,184,77,.14);" + + "--kao-stripe:rgba(255,184,77,.10);--kao-glow:rgba(255,184,77,.30);" + + "}" + + "}"; + + // ── CSS: modern base + reset ──────────────────────────────────────── + var cssBase = + ".kao-banner.kao-banner--style-modern{" + + "position:relative;box-sizing:border-box;width:100%;" + + "font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;" + + "font-size:14px;font-weight:400;line-height:1.4;letter-spacing:normal;" + + "text-shadow:none;text-transform:none;text-align:start;" + + "color:var(--kao-fg);" + + "background:" + + "repeating-linear-gradient(-45deg,transparent 0,transparent 22px," + + "var(--kao-stripe) 22px,var(--kao-stripe) 24px)," + + "linear-gradient(95deg,var(--kao-bg-from) 0%,var(--kao-bg-to) 100%);" + + "border-bottom:1px solid var(--kao-border);" + + "box-shadow:0 6px 18px -10px var(--kao-glow);" + + "contain:layout style;" + + "}" + + ".kao-banner.kao-banner--style-modern *{box-sizing:border-box;}" + + ".kao-banner.kao-banner--style-modern .kao-banner__inner{" + + "position:relative;display:flex;align-items:center;" + + "gap:12px;min-width:0;max-width:1200px;margin:0 auto;" + + "padding:0 16px;height:100%;" + + "}" + + ".kao-banner.kao-banner--style-modern .kao-banner__icon{" + + "flex-shrink:0;width:22px;height:22px;" + + "color:var(--kao-accent);" + + "filter:drop-shadow(0 1px 2px var(--kao-glow));" + + "animation:kao-warn-pulse 2.4s ease-in-out infinite;" + + "}" + + ".kao-banner.kao-banner--style-modern .kao-banner__icon-mark{" + + "fill:#1a0e00;" + + "}" + + "@keyframes kao-warn-pulse{" + + "0%,100%{opacity:1;transform:scale(1);}" + + "50%{opacity:.78;transform:scale(.94);}" + + "}" + + ".kao-banner.kao-banner--style-modern .kao-banner__text{" + + "margin:0;flex:0 1 auto;min-width:0;overflow:hidden;" + + "text-overflow:ellipsis;white-space:nowrap;" + + "font-size:.875rem;font-weight:500;" + + "}" + + ".kao-banner.kao-banner--style-modern .kao-banner__brand{" + + "font-weight:700;color:var(--kao-fg-strong);" + + "text-transform:uppercase;font-size:.8125rem;" + + "letter-spacing:.04em;margin-inline-end:6px;" + + "}" + + ".kao-banner.kao-banner--style-modern .kao-banner__verify{" + + "opacity:.92;margin-inline-end:6px;color:inherit;" + + "}" + + ".kao-banner.kao-banner--style-modern a.kao-banner__verify{" + + "text-decoration:none;color:inherit;" + + "}" + + ".kao-banner.kao-banner--style-modern a.kao-banner__verify:hover{" + + "text-decoration:underline;" + + "}" + + ".kao-banner.kao-banner--style-modern .kao-banner__count{" + + "flex-shrink:0;margin-inline-start:auto;" + + "font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Monaco,Consolas,monospace;" + + "font-variant-numeric:tabular-nums;font-weight:600;" + + "color:var(--kao-accent-strong);padding:2px 7px;border-radius:6px;" + + "background:var(--kao-pill-bg);border:1px solid var(--kao-border);" + + "font-size:.8125rem;letter-spacing:.02em;white-space:nowrap;" + + "}" + + ".kao-banner.kao-banner--style-modern .kao-banner__cta{" + + "display:inline-flex;align-items:center;gap:4px;" + + "font-size:.8125rem;font-weight:700;color:var(--kao-accent-strong);" + + "text-decoration:none;flex-shrink:0;padding:5px 12px;" + + "border-radius:999px;border:1px solid var(--kao-border);" + + "background:transparent;" + + "transition:background .2s,transform .2s,border-color .2s;" + + "}" + + ".kao-banner.kao-banner--style-modern .kao-banner__cta:hover{" + + "background:var(--kao-pill-bg);" + + "border-color:var(--kao-accent);" + + "transform:translateX(2px);" + + "}" + + ".kao-banner.kao-banner--style-modern .kao-banner__cta:focus-visible{" + + "outline:2px solid var(--kao-fg-strong);outline-offset:2px;" + + "}" + + ".kao-banner.kao-banner--style-modern.kao-banner--has-close .kao-banner__inner{" + + "padding-inline-end:40px;" + + "}" + + ".kao-banner.kao-banner--style-modern .kao-banner__close{" + + "position:absolute;inset-inline-end:8px;top:50%;" + + "transform:translateY(-50%);background:none;border:0;" + + "-webkit-appearance:none;appearance:none;cursor:pointer;" + + "color:var(--kao-fg);opacity:.6;font-size:14px;line-height:1;" + + "padding:6px 8px;" + + "}" + + ".kao-banner.kao-banner--style-modern .kao-banner__close:hover{opacity:1;}" + + ".kao-banner.kao-banner--style-modern .kao-banner__close:focus-visible{" + + "outline:2px solid var(--kao-fg-strong);outline-offset:2px;opacity:1;" + + "}" + + ".kao-banner.kao-banner--style-modern .kao-banner__a11y-status{" + + "position:absolute;width:1px;height:1px;padding:0;margin:-1px;" + + "overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;" + + "}"; + + // ── CSS: modern size variants ──────────────────────────────────────── + var cssSizes = + ".kao-banner.kao-banner--style-modern.kao-banner--normal{height:48px;}" + + ".kao-banner.kao-banner--style-modern.kao-banner--mini{height:36px;}" + + ".kao-banner.kao-banner--style-modern.kao-banner--mini .kao-banner__icon{" + + "width:18px;height:18px;" + + "}" + + ".kao-banner.kao-banner--style-modern.kao-banner--mini .kao-banner__text{" + + "font-size:.75rem;" + + "}" + + ".kao-banner.kao-banner--style-modern.kao-banner--mini .kao-banner__brand{" + + "font-size:.75rem;" + + "}" + + ".kao-banner.kao-banner--style-modern.kao-banner--mini .kao-banner__count{" + + "font-size:.6875rem;padding:1px 5px;" + + "}" + + ".kao-banner.kao-banner--style-modern.kao-banner--minimal{height:28px;}" + + ".kao-banner.kao-banner--style-modern.kao-banner--minimal .kao-banner__inner{" + + "padding:0 12px;gap:6px;" + + "}" + + ".kao-banner.kao-banner--style-modern.kao-banner--minimal .kao-banner__text{" + + "font-size:.75rem;" + + "}" + + ".kao-banner.kao-banner--style-modern.kao-banner--minimal .kao-banner__count{" + + "font-size:.6875rem;padding:1px 5px;" + + "}"; + + // ── CSS: media queries (responsive truncation) ─────────────────────── + // At narrow widths the verify (and eventually brand) text is hidden, leaving + // the text element empty. Drop the count's auto inline-start margin so the + // right-side cluster sits next to the brand/icon instead of being pushed to + // the far edge — otherwise the layout reads as right-aligned. + var cssMedia = + "@media(max-width:860px){" + + ".kao-banner.kao-banner--style-modern .kao-banner__verify{display:none;}" + + ".kao-banner.kao-banner--style-modern .kao-banner__count{margin-inline-start:0;}" + + "}" + + "@media(max-width:640px){" + + ".kao-banner.kao-banner--style-modern.kao-banner--normal{height:44px;}" + + ".kao-banner.kao-banner--style-modern .kao-banner__inner{gap:8px;padding:0 12px;}" + + ".kao-banner.kao-banner--style-modern.kao-banner--has-close .kao-banner__inner{padding-inline-end:40px;}" + + ".kao-banner.kao-banner--style-modern .kao-banner__icon{width:18px;height:18px;}" + + ".kao-banner.kao-banner--style-modern .kao-banner__cta__label{display:none;}" + + ".kao-banner.kao-banner--style-modern .kao-banner__cta{padding:5px 8px;}" + + "}" + + "@media(max-width:380px){" + + ".kao-banner.kao-banner--style-modern .kao-banner__brand{display:none;}" + + "}"; - // ── Inject CSS ──────────────────────────────────────────────────────── - var cssNormal = - ".kao-banner{" + + // ── CSS: motion preferences ────────────────────────────────────────── + var cssMotion = + "@media(prefers-reduced-motion:reduce){" + + ".kao-banner.kao-banner--style-modern .kao-banner__icon{animation:none;}" + + ".kao-banner.kao-banner--style-modern .kao-banner__cta{transition:none;}" + + ".kao-banner.kao-banner--style-modern .kao-banner__cta:hover{transform:none;}" + + "}" + + ".kao-banner.kao-banner--style-modern.kao-banner--no-anim .kao-banner__icon{" + + "animation:none;" + + "}" + + ".kao-banner.kao-banner--style-modern.kao-banner--no-anim .kao-banner__cta{" + + "transition:none;" + + "}" + + ".kao-banner.kao-banner--style-modern.kao-banner--no-anim .kao-banner__cta:hover{" + + "transform:none;" + + "}"; + + // ── CSS: RTL adjustments ───────────────────────────────────────────── + var cssRtl = + "[dir=rtl] .kao-banner.kao-banner--style-modern .kao-banner__cta__arrow," + + ".kao-banner.kao-banner--style-modern[dir=rtl] .kao-banner__cta__arrow{" + + "transform:scaleX(-1);" + + "}"; + + // ── CSS: classic style (original look preserved 1:1) ───────────────── + var cssClassicNormal = + ".kao-banner.kao-banner--style-classic.kao-banner--normal{" + "position:relative;" + "font-variant-numeric:tabular-nums;" + "background:linear-gradient(180deg,#d32f2f 0%,#b71c1c 100%);" + @@ -147,8 +356,8 @@ "box-sizing:border-box;" + "}"; - var cssMini = - ".kao-banner{" + + var cssClassicMini = + ".kao-banner.kao-banner--style-classic.kao-banner--mini{" + "position:relative;" + "font-variant-numeric:tabular-nums;" + "background:linear-gradient(180deg,#d32f2f 0%,#b71c1c 100%);" + @@ -169,32 +378,33 @@ "box-sizing:border-box;" + "}"; - var cssMinimal = - ".kao-banner{" + - "position:relative;" + - "font-variant-numeric:tabular-nums;" + - "background:linear-gradient(180deg,#d32f2f 0%,#b71c1c 100%);" + - "border-bottom:2px solid #801313;" + - "color:#fff;" + - "font-family:'Arial Black',sans-serif;" + - "font-weight:900;" + - "text-transform:uppercase;" + - "letter-spacing:1px;" + - "font-size:0.75rem;" + - "text-align:center;" + - "text-shadow:" + - "0px 1px 0px #9e1a1a," + - "0px 2px 0px #8a1515," + - "0px 3px 5px rgba(0,0,0,0.4);" + - "padding:0.25rem 1.5rem;" + - "line-height:1.4;" + - "box-sizing:border-box;" + + var cssClassicMinimal = + ".kao-banner.kao-banner--style-classic.kao-banner--minimal{" + + "position:relative;" + + "font-variant-numeric:tabular-nums;" + + "background:linear-gradient(180deg,#d32f2f 0%,#b71c1c 100%);" + + "border-bottom:2px solid #801313;" + + "color:#fff;" + + "font-family:'Arial Black',sans-serif;" + + "font-weight:900;" + + "text-transform:uppercase;" + + "letter-spacing:1px;" + + "font-size:0.75rem;" + + "text-align:center;" + + "text-shadow:" + + "0px 1px 0px #9e1a1a," + + "0px 2px 0px #8a1515," + + "0px 3px 5px rgba(0,0,0,0.4);" + + "padding:0.25rem 1.5rem;" + + "line-height:1.4;" + + "box-sizing:border-box;" + "}"; - var cssCommon = - ".kao-banner a{color:#fff;text-decoration:none;}" + - ".kao-banner a:hover{text-decoration:underline;}" + - ".kao-banner-close{" + + var cssClassicCommon = + ".kao-banner.kao-banner--style-classic a{color:#fff;text-decoration:none;}" + + ".kao-banner.kao-banner--style-classic a:hover{text-decoration:underline;}" + + ".kao-banner.kao-banner--style-classic .kao-banner-close,"+ + ".kao-banner.kao-banner--style-classic .kao-banner__close{" + "position:absolute;" + "right:0.5rem;" + "top:50%;" + @@ -209,21 +419,34 @@ "line-height:1;" + "text-shadow:none;" + "}" + - ".kao-banner-close:hover{opacity:1;}"; + ".kao-banner.kao-banner--style-classic .kao-banner-close:hover,"+ + ".kao-banner.kao-banner--style-classic .kao-banner__close:hover{opacity:1;}"; - var cssKaoPulse = - ".kao-banner:not(.no-animation) { animation:kao-pulse 2s infinite; }" + + var cssClassicPulse = + ".kao-banner.kao-banner--style-classic:not(.no-animation):not(.kao-banner--no-anim){" + + "animation:kao-pulse 2s infinite;" + + "}" + "@keyframes kao-pulse{" + "0%{box-shadow:0 0 0 0 rgba(211,47,47,0.7)}" + "70%{box-shadow:0 0 0 15px rgba(211,47,47,0)}" + "100%{box-shadow:0 0 0 0 rgba(211,47,47,0)}" + + "}" + + "@media(prefers-reduced-motion:reduce){" + + ".kao-banner.kao-banner--style-classic{animation:none!important;}" + "}"; - var style = document.createElement("style"); - style.textContent = (size === "mini" ? cssMini : size === "minimal" ? cssMinimal : cssNormal) - + (params.animation === "off" ? "" : cssKaoPulse) - + cssCommon; - document.head.appendChild(style); + var cssClassic = + cssClassicNormal + + cssClassicMini + + cssClassicMinimal + + cssClassicCommon + + cssClassicPulse; + + // ── Inject single