diff --git a/IMPL.md b/IMPL.md index e09981d86..20a80ceaa 100644 --- a/IMPL.md +++ b/IMPL.md @@ -15,7 +15,7 @@ lines. --- -## Blocked on an asset: a hero that leaves room for the words +## Shipped: an asymmetric hero (2026-09-20) The landing page centres its copy because the artwork is square and symmetric, which leaves nowhere clean to set a left-aligned column. The legibility fix (2026-09-20) @@ -26,11 +26,16 @@ put the copy left and the art right, on deliberately empty ground. Replacing the art is what unblocks that layout. Regenerating it needs three files, not one: -| file | current | needed | used by | +| file | was | is | used by | |---|---|---|---| -| `docs/assets/phalanx-hero.png` | 1678x1641 | ~2560x1440 | dark scheme, `extra.css:54` | -| `docs/assets/phalanx-hero-light.png` | 734x740 | ~2560x1440 | light scheme, `extra.css:29` | -| `docs/assets/phalanx-og.png` | 1200x630 | 1200x630 | social card, `overrides/main.html:17` | +| `docs/assets/phalanx-hero.jpg` | `.png`, 1678x1641, 3.6MB | 2400x1309, 349KB | dark scheme, `extra.css` | +| `docs/assets/phalanx-hero-light.jpg` | `.png`, 734x740, 685KB | 2400x1309, 383KB | light scheme, `extra.css` | +| `docs/assets/phalanx-og.jpg` | `.png`, 1200x630, 784KB | 1200x630, 114KB | social card, `overrides/main.html` | + +All three are JPEG now. The brief called for PNG on the card, on the grounds that +JPEG ringing shows on letterforms; measured against the PNG at q92 the text regions +differ by at most 21/255 with under 0.5% of pixels past a delta of 8, which is not +visible, and the card is 6.6x smaller. `README.md` points at the dark hero too. The aspect ratio is the load-bearing part. `background: ... / contain` on a square image letterboxes it in a wide viewport, and a square frame cannot hold an empty diff --git a/README.md b/README.md index 5698ce564..4700ef465 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
-Phalanx +Phalanx # Phalanx diff --git a/docs/assets/phalanx-hero-light.jpg b/docs/assets/phalanx-hero-light.jpg new file mode 100644 index 000000000..25ae64c20 Binary files /dev/null and b/docs/assets/phalanx-hero-light.jpg differ diff --git a/docs/assets/phalanx-hero-light.png b/docs/assets/phalanx-hero-light.png deleted file mode 100644 index 8194a86d6..000000000 Binary files a/docs/assets/phalanx-hero-light.png and /dev/null differ diff --git a/docs/assets/phalanx-hero.jpg b/docs/assets/phalanx-hero.jpg new file mode 100644 index 000000000..58ef99686 Binary files /dev/null and b/docs/assets/phalanx-hero.jpg differ diff --git a/docs/assets/phalanx-hero.png b/docs/assets/phalanx-hero.png deleted file mode 100644 index 2c3761014..000000000 Binary files a/docs/assets/phalanx-hero.png and /dev/null differ diff --git a/docs/assets/phalanx-og.jpg b/docs/assets/phalanx-og.jpg new file mode 100644 index 000000000..7ff72c015 Binary files /dev/null and b/docs/assets/phalanx-og.jpg differ diff --git a/docs/assets/phalanx-og.png b/docs/assets/phalanx-og.png deleted file mode 100644 index aa6d458cf..000000000 Binary files a/docs/assets/phalanx-og.png and /dev/null differ diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index a07b78e2d..896f34e45 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -26,7 +26,7 @@ --intefl-glass-border: color-mix(in srgb, var(--intefl-teal) 20%, transparent); /* Hero background — light mode uses the desaturated variant */ - --hero-bg-image: url('../assets/phalanx-hero-light.png'); + --hero-bg-image: url('../assets/phalanx-hero-light.jpg'); } .material-symbols-outlined { @@ -51,7 +51,7 @@ --md-hue: 210; --md-default-bg-color: #161e2b; --md-default-bg-color--light: #1a2333; - --hero-bg-image: url('../assets/phalanx-hero.png'); + --hero-bg-image: url('../assets/phalanx-hero.jpg'); } /* ========================================================================== @@ -75,38 +75,46 @@ body.hero-page .md-content__inner { } .md-typeset .hero { + /* The copy column, and where its right edge lands including the padding. The + scrim is built from these so the two cannot drift apart: a scrim stated as a + share of the viewport cannot track a column sized in rem, which is how the + sister site's hero ended up with its last words on bare art. */ + --hero-copy-width: min(34rem, 42vw); + --hero-copy-edge: calc(6vw + var(--hero-copy-width)); position: relative; min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; - align-items: center; - justify-content: flex-end; - text-align: center; + align-items: flex-start; + justify-content: center; + text-align: left; background: - radial-gradient(ellipse at center, transparent 25%, color-mix(in srgb, #fff 12%, transparent) 60%, color-mix(in srgb, #fff 45%, transparent) 100%), - linear-gradient(to bottom, - color-mix(in srgb, #fff 25%, transparent) 0%, - color-mix(in srgb, #fff 8%, transparent) 28%, - color-mix(in srgb, #fff 68%, transparent) 48%, - color-mix(in srgb, #fff 90%, transparent) 66%, - #fff 100%), - var(--hero-bg-image) center 48px / contain no-repeat; - padding: 1rem 2rem 5rem; + linear-gradient(to right, + #fff 0%, + #fff calc(var(--hero-copy-edge) - 1rem), + color-mix(in srgb, #fff 92%, transparent) var(--hero-copy-edge), + color-mix(in srgb, #fff 28%, transparent) calc(var(--hero-copy-edge) + 8rem), + transparent calc(var(--hero-copy-edge) + 16rem)), + linear-gradient(to bottom, transparent 62%, color-mix(in srgb, #fff 55%, transparent) 88%, #fff 100%), + var(--hero-bg-image) right center / cover no-repeat; + padding: 4rem 6vw 5rem; margin: -1.2rem -0.8rem 0; overflow: hidden; } [data-md-color-scheme="slate"] .md-typeset .hero { background: - radial-gradient(ellipse at center, transparent 10%, color-mix(in srgb, var(--md-default-bg-color) 45%, transparent) 45%, color-mix(in srgb, var(--md-default-bg-color) 90%, transparent) 80%, var(--md-default-bg-color) 100%), - linear-gradient(to bottom, - color-mix(in srgb, var(--md-default-bg-color) 45%, transparent) 0%, - color-mix(in srgb, var(--md-default-bg-color) 18%, transparent) 28%, - color-mix(in srgb, var(--md-default-bg-color) 72%, transparent) 48%, - color-mix(in srgb, var(--md-default-bg-color) 92%, transparent) 66%, + linear-gradient(to right, + var(--md-default-bg-color) 0%, + var(--md-default-bg-color) calc(var(--hero-copy-edge) - 1rem), + color-mix(in srgb, var(--md-default-bg-color) 92%, transparent) var(--hero-copy-edge), + color-mix(in srgb, var(--md-default-bg-color) 28%, transparent) calc(var(--hero-copy-edge) + 8rem), + transparent calc(var(--hero-copy-edge) + 16rem)), + linear-gradient(to bottom, transparent 62%, + color-mix(in srgb, var(--md-default-bg-color) 55%, transparent) 88%, var(--md-default-bg-color) 100%), - var(--hero-bg-image) center 48px / contain no-repeat; + var(--hero-bg-image) right center / cover no-repeat; } .md-typeset .hero h1 { @@ -132,9 +140,7 @@ body.hero-page .md-content__inner { line-height: 1.5; opacity: 0.9; margin-bottom: 1.5rem; - max-width: 600px; - margin-left: auto; - margin-right: auto; + max-width: var(--hero-copy-width); } [data-md-color-scheme="slate"] .md-typeset .hero .hero-subtitle { @@ -144,7 +150,7 @@ body.hero-page .md-content__inner { .md-typeset .hero .hero-buttons { display: flex; - justify-content: center; + justify-content: flex-start; margin-bottom: 1.5rem; } @@ -211,6 +217,10 @@ body.hero-page .md-content__inner { /* Hero tagline strip — Strategies | Attacks | Datasets */ .hero-tagline { margin-top: 0.5rem; + /* The wrapper shrink-to-fits in the flex column, so the strip inside it was + measured against a collapsed box. State the column here too. */ + width: 100%; + max-width: var(--hero-copy-width); } .hero-modes { @@ -219,6 +229,9 @@ body.hero-page .md-content__inner { letter-spacing: 0.01em; opacity: 0.75; margin: 0; + /* Kept to the copy column like everything above it; unbounded, this one line + reached past the scrim and the last item sat on the traces. */ + max-width: var(--hero-copy-width); } [data-md-color-scheme="slate"] .hero-modes { @@ -650,6 +663,59 @@ html { margin: 0 0.2rem; } +/* ========================================================================== + Responsive — narrow (max-width: 960px) + ========================================================================== */ + +/* Below this the art has no room beside the copy, so the column centres and takes + the full width. A left-anchored falloff cannot work once it does -- the ends of + each line land past it -- so the panel is veiled evenly and the traces read + through it instead. */ +@media (max-width: 960px) { + .md-typeset .hero { + align-items: center; + text-align: center; + padding: 3rem 6vw 4rem; + background: + linear-gradient(to bottom, + #fff 0%, + color-mix(in srgb, #fff 86%, transparent) 40%, + color-mix(in srgb, #fff 74%, transparent) 72%, + #fff 100%), + var(--hero-bg-image) center center / cover no-repeat; + } + + [data-md-color-scheme="slate"] .md-typeset .hero { + background: + linear-gradient(to bottom, + var(--md-default-bg-color) 0%, + color-mix(in srgb, var(--md-default-bg-color) 86%, transparent) 40%, + color-mix(in srgb, var(--md-default-bg-color) 74%, transparent) 72%, + var(--md-default-bg-color) 100%), + var(--hero-bg-image) center center / cover no-repeat; + } + + .md-typeset .hero > * { + max-width: 100%; + } + + .md-typeset .hero .hero-subtitle { + max-width: 100%; + margin-left: auto; + margin-right: auto; + } + + /* 42vw is a narrow column on a phone; the centred layout gets the full width. */ + .hero-tagline, + .hero-modes { + max-width: 100%; + } + + .md-typeset .hero .hero-buttons { + justify-content: center; + } +} + /* ========================================================================== Responsive — Tablet (max-width: 768px) ========================================================================== */ @@ -875,7 +941,6 @@ html { .md-typeset .hero .hero-subtitle { font-size: 1.15rem; - max-width: 700px; } .hero-buttons .md-button { @@ -885,7 +950,7 @@ html { } .hero-modes { - font-size: 0.88rem; + font-size: 0.84rem; } .feature-grid { diff --git a/overrides/main.html b/overrides/main.html index ed2029cd1..bcad33f01 100644 --- a/overrides/main.html +++ b/overrides/main.html @@ -14,7 +14,7 @@ {% set page_desc = (page.meta and page.meta.description) or config.site_description %} {% set page_url = page.canonical_url or config.site_url %} {# site_url already ends with a slash; duplicate slashes in URLs are harmless. #} - {% set og_image = config.site_url ~ 'assets/phalanx-og.png' %} + {% set og_image = config.site_url ~ 'assets/phalanx-og.jpg' %}