diff --git a/src/views.rs b/src/views.rs
index 63f3270..aba23ad 100644
--- a/src/views.rs
+++ b/src/views.rs
@@ -88,12 +88,27 @@ pub struct SubjectBlock {
fn head(ctx: &Ctx, title: &str) -> String {
format!(
- r#"
+ r##"
-{t} · WhalePrep
+{t} · WhalePrep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-"#,
+"##,
t = esc(title),
- b = ctx.base
+ b = ctx.base,
+ origin = public_origin()
)
}
+/// The absolute origin for og:image URLs — meta tags need a full URL, not a
+/// relative path. Derived from the request when behind the tunnel; falls
+/// back to the production domain.
+fn public_origin() -> String {
+ std::env::var("PUBLIC_ORIGIN").unwrap_or_else(|_| "https://whaleprep.oiupoyt.space".into())
+}
+
fn nav(ctx: &Ctx, user: Option<&str>) -> String {
let brand = format!(
- r##""##,
+ r##""##,
b = ctx.base
);
let links = match user {
diff --git a/static/apple-touch-icon.png b/static/apple-touch-icon.png
new file mode 100644
index 0000000..ef646c6
Binary files /dev/null and b/static/apple-touch-icon.png differ
diff --git a/static/embed.png b/static/embed.png
new file mode 100644
index 0000000..8d1d4e9
Binary files /dev/null and b/static/embed.png differ
diff --git a/static/embed.svg b/static/embed.svg
new file mode 100644
index 0000000..34d1df4
--- /dev/null
+++ b/static/embed.svg
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ WhalePrep
+
+
+ JEE Main practice, built like the real exam
+
+
+ 9,813 PYQs · 2002-2025 · +4/−1 marking
+
+
diff --git a/static/favicon.png b/static/favicon.png
new file mode 100644
index 0000000..7862f27
Binary files /dev/null and b/static/favicon.png differ
diff --git a/static/logo.svg b/static/logo.svg
new file mode 100644
index 0000000..37ce6a0
--- /dev/null
+++ b/static/logo.svg
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/static/style.css b/static/style.css
index d5362d1..033f51b 100644
--- a/static/style.css
+++ b/static/style.css
@@ -2216,3 +2216,10 @@ button.pal-fab {
.zp-subtopic-row:has(input:checked) .zp-subtopic-title {
color: #60a5fa;
}
+
+/* ===== brand logo ===== */
+img.brand-logo {
+ display: inline-block;
+ vertical-align: middle;
+ filter: drop-shadow(0 0 6px rgba(59, 130, 246, 0.3));
+}