Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions src/chrome/src/ui/apocalypse-kit.css
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,34 @@ button:active:not(:disabled),
box-shadow:inset 0 -2px 0 var(--accent);
}

/* WebBrain signature above the page title. The page keeps its own mark (a nuclear
trefoil, W, PDF); this eyebrow only says which product that mark belongs to, so
it stays unboxed — a chip here would read as a third button beside Back. */
.kit-brand {
display:inline-flex;
align-items:center;
gap:6px;
align-self:start;
margin-bottom:3px;
color:var(--muted);
text-decoration:none;
font:760 9px/1 var(--font-mono);
letter-spacing:.08em;
text-transform:uppercase;
transition:color .16s ease;
}

/* The PDF reader colors every link in its heading; the signature is not one. */
a.kit-brand,
a.kit-brand:hover .kit-brand-logo { text-decoration:none; }
.document-heading a.kit-brand { color:var(--muted);font-size:9px; }
.document-heading a.kit-brand:hover { color:var(--accent);text-decoration:none; }

.kit-brand-logo { width:15px;height:15px;flex:0 0 15px;display:block; }
.kit-brand-sep { opacity:.5; }

a.kit-brand:hover { color:var(--accent); }

.topbar .apocalypse-icon,
.ap-page .apocalypse-icon {
width:64px;
Expand Down Expand Up @@ -1060,6 +1088,9 @@ button:active:not(:disabled),
}

@media (max-width:700px) {
/* The eyebrow sheds the mode name before the page's own title gives up room. */
.kit-brand-sep,
.kit-brand-mode { display:none; }
.ap-page > header { min-height:0;overflow:visible; }
.ap-page .header-right { margin-inline-start:0; }
.ap-page .hero-overview { padding:22px 18px; }
Expand Down
2 changes: 1 addition & 1 deletion src/chrome/src/ui/apocalypse-mode.html
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
<link rel="stylesheet" href="offline-rag-readiness.css">
</head>
<body class="ap-page">
<header><span class="apocalypse-icon" aria-hidden="true">☢</span><div class="header-copy"><h1 data-i18n="ap.title"></h1><p class="muted" data-i18n="ap.subtitle"></p></div><div class="header-right"><div class="header-stats" data-i18n-aria-label="ap.metric.summary"><span class="header-stat"><strong id="installed-count">0</strong><small data-i18n="ap.metric.installed"></small></span><span class="header-stat"><strong id="archive-bytes">0 B</strong><small data-i18n="ap.metric.archive_bytes"></small></span><span class="header-stat"><strong id="storage-usage"></strong><small data-i18n="ap.metric.storage"></small></span></div><span id="models-readiness" class="models-readiness" data-kind="disabled" role="status" aria-live="polite"><span class="models-readiness-dot" aria-hidden="true"></span><span id="models-readiness-label"></span></span></div></header>
<header><span class="apocalypse-icon" aria-hidden="true">☢</span><div class="header-copy"><span class="kit-brand"><img class="kit-brand-logo" src="../../icons/icon128.png" alt="" aria-hidden="true"><span class="kit-brand-name">WebBrain</span></span><h1 data-i18n="ap.title"></h1><p class="muted" data-i18n="ap.subtitle"></p></div><div class="header-right"><div class="header-stats" data-i18n-aria-label="ap.metric.summary"><span class="header-stat"><strong id="installed-count">0</strong><small data-i18n="ap.metric.installed"></small></span><span class="header-stat"><strong id="archive-bytes">0 B</strong><small data-i18n="ap.metric.archive_bytes"></small></span><span class="header-stat"><strong id="storage-usage"></strong><small data-i18n="ap.metric.storage"></small></span></div><span id="models-readiness" class="models-readiness" data-kind="disabled" role="status" aria-live="polite"><span class="models-readiness-dot" aria-hidden="true"></span><span id="models-readiness-label"></span></span></div></header>
<main>
<section class="card hero">
<div class="hero-overview">
Expand Down
1 change: 1 addition & 0 deletions src/chrome/src/ui/emergency-box.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<a class="back-button" href="apocalypse-mode.html" data-i18n-aria-label="eb.back" data-i18n-title="ap.title">←</a>
<span class="apocalypse-icon" aria-hidden="true">☢</span>
<div class="title-block">
<a class="kit-brand" href="apocalypse-mode.html" data-i18n-title="ap.title"><img class="kit-brand-logo" src="../../icons/icon128.png" alt="" aria-hidden="true"><span class="kit-brand-name">WebBrain</span><span class="kit-brand-sep" aria-hidden="true">·</span><span class="kit-brand-mode" data-i18n="ap.title"></span></a>
<h1 data-i18n="eb.title"></h1>
<p data-i18n="eb.subtitle"></p>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/chrome/src/ui/emergency-communication.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<a class="back-button" href="emergency-box.html" aria-label="Back to Emergency Box" title="Emergency Box">←</a>
<span class="language-mark" aria-hidden="true">言</span>
<div class="title-block">
<a class="kit-brand" href="apocalypse-mode.html" data-i18n-title="ap.title"><img class="kit-brand-logo" src="../../icons/icon128.png" alt="" aria-hidden="true"><span class="kit-brand-name">WebBrain</span><span class="kit-brand-sep" aria-hidden="true">·</span><span class="kit-brand-mode" data-i18n="ap.title"></span></a>
<h1 data-copy="header">Emergency Communication</h1>
<p data-copy="headerSubtitle">A basic word board that works without the internet</p>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/chrome/src/ui/emergency-pdf.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<a class="back-button" href="emergency-box.html" data-i18n-aria-label="ep.back">←</a>
<span class="pdf-mark" aria-hidden="true">PDF</span>
<div class="document-heading">
<a class="kit-brand" href="apocalypse-mode.html" data-i18n-title="ap.title"><img class="kit-brand-logo" src="../../icons/icon128.png" alt="" aria-hidden="true"><span class="kit-brand-name">WebBrain</span><span class="kit-brand-sep" aria-hidden="true">·</span><span class="kit-brand-mode" data-i18n="ap.title"></span></a>
<div class="document-title-row">
<h1 id="document-title" data-i18n="ep.loading"></h1>
<span id="offline-badge" class="document-offline-badge" data-i18n="ep.available_offline" hidden></span>
Expand Down
1 change: 1 addition & 0 deletions src/chrome/src/ui/emergency-text.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<a class="back-button" href="emergency-box.html" data-i18n-aria-label="et.back">←</a>
<span class="text-mark" aria-hidden="true">TXT</span>
<div class="document-heading">
<a class="kit-brand" href="apocalypse-mode.html" data-i18n-title="ap.title"><img class="kit-brand-logo" src="../../icons/icon128.png" alt="" aria-hidden="true"><span class="kit-brand-name">WebBrain</span><span class="kit-brand-sep" aria-hidden="true">·</span><span class="kit-brand-mode" data-i18n="ap.title"></span></a>
<h1 id="document-title" data-i18n="et.loading"></h1>
<p id="document-meta"></p>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/chrome/src/ui/wikipedia-library.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<a class="back-button" href="emergency-box.html" data-i18n-aria-label="wl.back">←</a>
<span class="archive-mark" aria-hidden="true">W</span>
<div class="title-block">
<a class="kit-brand" href="apocalypse-mode.html" data-i18n-title="ap.title"><img class="kit-brand-logo" src="../../icons/icon128.png" alt="" aria-hidden="true"><span class="kit-brand-name">WebBrain</span><span class="kit-brand-sep" aria-hidden="true">·</span><span class="kit-brand-mode" data-i18n="ap.title"></span></a>
<h1 data-i18n="wl.title"></h1>
<p data-i18n="wl.subtitle"></p>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/chrome/src/ui/wikipedia-reader.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<a class="back-button" href="apocalypse-mode.html" data-i18n-aria-label="ar.back">←</a>
<span class="apocalypse-icon" aria-hidden="true">☢</span>
<div class="title-block">
<a class="kit-brand" href="apocalypse-mode.html" data-i18n-title="ap.title"><img class="kit-brand-logo" src="../../icons/icon128.png" alt="" aria-hidden="true"><span class="kit-brand-name">WebBrain</span><span class="kit-brand-sep" aria-hidden="true">·</span><span class="kit-brand-mode" data-i18n="ap.title"></span></a>
<h1 data-i18n="ar.title"></h1>
<p id="archive-name" data-i18n="ar.loading_archive"></p>
</div>
Expand Down
31 changes: 31 additions & 0 deletions src/firefox/src/ui/apocalypse-kit.css
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,34 @@ button:active:not(:disabled),
box-shadow:inset 0 -2px 0 var(--accent);
}

/* WebBrain signature above the page title. The page keeps its own mark (a nuclear
trefoil, W, PDF); this eyebrow only says which product that mark belongs to, so
it stays unboxed — a chip here would read as a third button beside Back. */
.kit-brand {
display:inline-flex;
align-items:center;
gap:6px;
align-self:start;
margin-bottom:3px;
color:var(--muted);
text-decoration:none;
font:760 9px/1 var(--font-mono);
letter-spacing:.08em;
text-transform:uppercase;
transition:color .16s ease;
}

/* The PDF reader colors every link in its heading; the signature is not one. */
a.kit-brand,
a.kit-brand:hover .kit-brand-logo { text-decoration:none; }
.document-heading a.kit-brand { color:var(--muted);font-size:9px; }
.document-heading a.kit-brand:hover { color:var(--accent);text-decoration:none; }

.kit-brand-logo { width:15px;height:15px;flex:0 0 15px;display:block; }
.kit-brand-sep { opacity:.5; }

a.kit-brand:hover { color:var(--accent); }

.topbar .apocalypse-icon,
.ap-page .apocalypse-icon {
width:64px;
Expand Down Expand Up @@ -1060,6 +1088,9 @@ button:active:not(:disabled),
}

@media (max-width:700px) {
/* The eyebrow sheds the mode name before the page's own title gives up room. */
.kit-brand-sep,
.kit-brand-mode { display:none; }
.ap-page > header { min-height:0;overflow:visible; }
.ap-page .header-right { margin-inline-start:0; }
.ap-page .hero-overview { padding:22px 18px; }
Expand Down
2 changes: 1 addition & 1 deletion src/firefox/src/ui/apocalypse-mode.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
<link rel="stylesheet" href="offline-rag-readiness.css">
</head>
<body class="ap-page">
<header><span class="apocalypse-icon" aria-hidden="true">☢</span><div class="header-copy"><h1 data-i18n="ap.title"></h1><p class="muted" data-i18n="ap.subtitle"></p></div><div class="header-stats" data-i18n-aria-label="ap.metric.summary"><span class="header-stat"><strong id="installed-count">0</strong><small data-i18n="ap.metric.installed"></small></span><span class="header-stat"><strong id="archive-bytes">0 B</strong><small data-i18n="ap.metric.archive_bytes"></small></span><span class="header-stat"><strong id="storage-usage"></strong><small data-i18n="ap.metric.storage"></small></span></div></header>
<header><span class="apocalypse-icon" aria-hidden="true">☢</span><div class="header-copy"><span class="kit-brand"><img class="kit-brand-logo" src="../../icons/icon128.png" alt="" aria-hidden="true"><span class="kit-brand-name">WebBrain</span></span><h1 data-i18n="ap.title"></h1><p class="muted" data-i18n="ap.subtitle"></p></div><div class="header-stats" data-i18n-aria-label="ap.metric.summary"><span class="header-stat"><strong id="installed-count">0</strong><small data-i18n="ap.metric.installed"></small></span><span class="header-stat"><strong id="archive-bytes">0 B</strong><small data-i18n="ap.metric.archive_bytes"></small></span><span class="header-stat"><strong id="storage-usage"></strong><small data-i18n="ap.metric.storage"></small></span></div></header>
<main>
<section class="hero">
<div><h2 data-i18n="ap.hero.title"></h2><p class="muted" data-i18n="ap.hero.desc"></p><p class="warning" data-i18n="ap.hero.consent"></p></div>
Expand Down
1 change: 1 addition & 0 deletions src/firefox/src/ui/emergency-box.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<a class="back-button" href="apocalypse-mode.html" data-i18n-aria-label="eb.back" data-i18n-title="ap.title">←</a>
<span class="apocalypse-icon" aria-hidden="true">☢</span>
<div class="title-block">
<a class="kit-brand" href="apocalypse-mode.html" data-i18n-title="ap.title"><img class="kit-brand-logo" src="../../icons/icon128.png" alt="" aria-hidden="true"><span class="kit-brand-name">WebBrain</span><span class="kit-brand-sep" aria-hidden="true">·</span><span class="kit-brand-mode" data-i18n="ap.title"></span></a>
<h1 data-i18n="eb.title"></h1>
<p data-i18n="eb.subtitle"></p>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/firefox/src/ui/emergency-communication.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<a class="back-button" href="emergency-box.html" aria-label="Back to Emergency Box" title="Emergency Box">←</a>
<span class="language-mark" aria-hidden="true">言</span>
<div class="title-block">
<a class="kit-brand" href="apocalypse-mode.html" data-i18n-title="ap.title"><img class="kit-brand-logo" src="../../icons/icon128.png" alt="" aria-hidden="true"><span class="kit-brand-name">WebBrain</span><span class="kit-brand-sep" aria-hidden="true">·</span><span class="kit-brand-mode" data-i18n="ap.title"></span></a>
<h1 data-copy="header">Emergency Communication</h1>
<p data-copy="headerSubtitle">A basic word board that works without the internet</p>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/firefox/src/ui/emergency-pdf.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<a class="back-button" href="emergency-box.html" data-i18n-aria-label="ep.back">←</a>
<span class="pdf-mark" aria-hidden="true">PDF</span>
<div class="document-heading">
<a class="kit-brand" href="apocalypse-mode.html" data-i18n-title="ap.title"><img class="kit-brand-logo" src="../../icons/icon128.png" alt="" aria-hidden="true"><span class="kit-brand-name">WebBrain</span><span class="kit-brand-sep" aria-hidden="true">·</span><span class="kit-brand-mode" data-i18n="ap.title"></span></a>
<div class="document-title-row">
<h1 id="document-title" data-i18n="ep.loading"></h1>
<span id="offline-badge" class="document-offline-badge" data-i18n="ep.available_offline" hidden></span>
Expand Down
1 change: 1 addition & 0 deletions src/firefox/src/ui/emergency-text.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<a class="back-button" href="emergency-box.html" data-i18n-aria-label="et.back">←</a>
<span class="text-mark" aria-hidden="true">TXT</span>
<div class="document-heading">
<a class="kit-brand" href="apocalypse-mode.html" data-i18n-title="ap.title"><img class="kit-brand-logo" src="../../icons/icon128.png" alt="" aria-hidden="true"><span class="kit-brand-name">WebBrain</span><span class="kit-brand-sep" aria-hidden="true">·</span><span class="kit-brand-mode" data-i18n="ap.title"></span></a>
<h1 id="document-title" data-i18n="et.loading"></h1>
<p id="document-meta"></p>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/firefox/src/ui/wikipedia-library.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<a class="back-button" href="emergency-box.html" data-i18n-aria-label="wl.back">←</a>
<span class="archive-mark" aria-hidden="true">W</span>
<div class="title-block">
<a class="kit-brand" href="apocalypse-mode.html" data-i18n-title="ap.title"><img class="kit-brand-logo" src="../../icons/icon128.png" alt="" aria-hidden="true"><span class="kit-brand-name">WebBrain</span><span class="kit-brand-sep" aria-hidden="true">·</span><span class="kit-brand-mode" data-i18n="ap.title"></span></a>
<h1 data-i18n="wl.title"></h1>
<p data-i18n="wl.subtitle"></p>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/firefox/src/ui/wikipedia-reader.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<a class="back-button" href="apocalypse-mode.html" data-i18n-aria-label="ar.back">←</a>
<span class="apocalypse-icon" aria-hidden="true">☢</span>
<div class="title-block">
<a class="kit-brand" href="apocalypse-mode.html" data-i18n-title="ap.title"><img class="kit-brand-logo" src="../../icons/icon128.png" alt="" aria-hidden="true"><span class="kit-brand-name">WebBrain</span><span class="kit-brand-sep" aria-hidden="true">·</span><span class="kit-brand-mode" data-i18n="ap.title"></span></a>
<h1 data-i18n="ar.title"></h1>
<p id="archive-name" data-i18n="ar.loading_archive"></p>
</div>
Expand Down
58 changes: 58 additions & 0 deletions test/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -25510,6 +25510,64 @@ test('Emergency Box UI and PDF reader stay in Chrome and Firefox parity', () =>
}
});

test('every WebBrain page signs its header with the extension logo', () => {
// The suite pages carry their own marks (a nuclear trefoil, W, PDF, TXT), so the
// WebBrain lockup is what tells a reader whose product those marks belong to.
const apocalypsePages = [
'emergency-box.html',
'wikipedia-library.html',
'wikipedia-reader.html',
'emergency-communication.html',
'emergency-pdf.html',
'emergency-text.html',
];
for (const browser of ['chrome', 'firefox']) {
const uiDir = path.join(ROOT, `src/${browser}/src/ui`);

const kit = fs.readFileSync(path.join(uiDir, 'apocalypse-kit.css'), 'utf8');
assert.match(kit, /\.kit-brand \{[\s\S]*?font:[^;]*var\(--font-mono\)/,
`${browser}: the Apocalypse Kit does not style the shared WebBrain eyebrow`);
assert.doesNotMatch(kit, /\.kit-brand \{[^}]*border:/,
`${browser}: a boxed signature reads as a third button beside Back`);
assert.match(kit, /@media \(max-width:700px\) \{[\s\S]*?\.kit-brand-mode \{ display:none; \}/,
`${browser}: the eyebrow does not shed the mode name on a narrow topbar`);
assert.match(kit, /\.document-heading a\.kit-brand \{ color:var\(--muted\)/,
`${browser}: the PDF reader paints the signature like one of its heading links`);

for (const page of apocalypsePages) {
const html = fs.readFileSync(path.join(uiDir, page), 'utf8');
assert.match(html, /<a class="kit-brand" href="apocalypse-mode\.html"[\s\S]*?src="\.\.\/\.\.\/icons\/icon128\.png"[\s\S]*?WebBrain[\s\S]*?data-i18n="ap\.title"[\s\S]*?<\/a>/,
`${browser}: ${page} does not carry the WebBrain lockup back to Apocalypse Mode`);
assert.match(html, /<div class="(?:title-block|document-heading)">\s*<a class="kit-brand"/,
`${browser}: ${page} does not sit the signature above its own page title`);
}

// The hub already names the mode in its h1 and must not link to itself.
const hub = fs.readFileSync(path.join(uiDir, 'apocalypse-mode.html'), 'utf8');
assert.match(hub, /<div class="header-copy"><span class="kit-brand"><img class="kit-brand-logo" src="\.\.\/\.\.\/icons\/icon128\.png"[^>]*><span class="kit-brand-name">WebBrain<\/span><\/span><h1 data-i18n="ap\.title">/,
`${browser}: Apocalypse Mode does not sign the title it already names`);
assert.doesNotMatch(hub, /<a class="kit-brand"/,
`${browser}: Apocalypse Mode links its own brand lockup back to itself`);

// Settings, History, and Traces put the logo inside the gradient title. The
// translated text has to stay in its own element: applyDOMTranslations writes
// textContent, which would drop an <img> sibling inside the same node.
for (const [page, key] of [['history.html', 'hist.title'], ['traces.html', 'tr.title']]) {
const html = fs.readFileSync(path.join(uiDir, page), 'utf8');
assert.match(html, new RegExp(`<h1><img class="brand-mark" src="\\.\\./\\.\\./icons/icon128\\.png"[^>]*><span data-i18n="${key.replace('.', '\\.')}"></span></h1>`),
`${browser}: ${page} does not show the WebBrain logo beside a separately translated title`);
}
const settings = fs.readFileSync(path.join(uiDir, 'settings.html'), 'utf8');
assert.match(settings, /<h1><img class="brand-mark" src="\.\.\/\.\.\/icons\/icon128\.png"[^>]*><a id="settings-title-link"[^>]*data-i18n="st\.title"><\/a><\/h1>/,
`${browser}: Settings does not show the WebBrain logo beside its title link`);
for (const page of ['settings.html', 'history.html', 'traces.html']) {
const html = fs.readFileSync(path.join(uiDir, page), 'utf8');
assert.match(html, /\.brand-mark \{[\s\S]*?width: \d+px;/,
`${browser}: ${page} ships the title logo without sizing it`);
}
}
});

test('Apocalypse download tracker follows every offline transfer from its pages and Settings', () => {
const pages = [
'apocalypse-mode.html',
Expand Down
Loading