diff --git a/README.md b/README.md
index e5068d3..08771e1 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ public/brand/ logo, project icons
src/
main.ts single entry, mounts whatever a page contains
data/site.ts projects and people. Edit content here
- components/ nav, footer, cards, mark draw, reveals, marquee
+ components/ nav, footer, cards, mark draw, reveals
lib/eggzec-block.ts the eggzec Block bitmap display font, as TypeScript
styles/ tokens, base, layout, components, pages
```
@@ -49,7 +49,6 @@ Almost everything is data rather than markup, and it all lives in
| Projects, taglines, repository and docs and PyPI links | `PROJECTS` |
| Human facing name when the repo name is not one | `display` on a project |
| Which projects lead the landing page | `LEAD` in `src/data/site.ts` |
-| Who builds on our packages | `src/data/used-by.ts` |
| Maintainers | `PEOPLE` |
| Nav links | `NAV` |
| Footer links | `COLUMNS` in `src/components/footer.ts` |
@@ -64,12 +63,6 @@ card appears twice.
Landing page statistics are counted from the catalog at runtime, so the numbers
cannot drift from what is actually listed.
-`src/data/used-by.ts` is the one generated file. It comes from GitHub's
-dependency graph — the `network/dependents` listing for each repository —
-filtered to named organisations and checked one at a time against the API. Only
-pydoe, pyswarm, mcerp and soerp have any dependents, so that is what the list
-draws on. Regenerate it by hand rather than trusting it to stay current.
-
## Design
Colours are the Electropop palette on white:
diff --git a/index.html b/index.html
index 5710c19..d6421d7 100644
--- a/index.html
+++ b/index.html
@@ -57,11 +57,6 @@
GitHub
-
-
diff --git a/public/brand/users/anesthesiasimulation.png b/public/brand/users/anesthesiasimulation.png
deleted file mode 100644
index 7021627..0000000
Binary files a/public/brand/users/anesthesiasimulation.png and /dev/null differ
diff --git a/public/brand/users/atomicateam.png b/public/brand/users/atomicateam.png
deleted file mode 100644
index c0fe0af..0000000
Binary files a/public/brand/users/atomicateam.png and /dev/null differ
diff --git a/public/brand/users/bgu-aidnd.png b/public/brand/users/bgu-aidnd.png
deleted file mode 100644
index 81dc910..0000000
Binary files a/public/brand/users/bgu-aidnd.png and /dev/null differ
diff --git a/public/brand/users/cmu-db.png b/public/brand/users/cmu-db.png
deleted file mode 100644
index f12fb30..0000000
Binary files a/public/brand/users/cmu-db.png and /dev/null differ
diff --git a/public/brand/users/codecentric.png b/public/brand/users/codecentric.png
deleted file mode 100644
index 15931f8..0000000
Binary files a/public/brand/users/codecentric.png and /dev/null differ
diff --git a/public/brand/users/curtin-timescales-of-mineral-systems.png b/public/brand/users/curtin-timescales-of-mineral-systems.png
deleted file mode 100644
index 5ed7961..0000000
Binary files a/public/brand/users/curtin-timescales-of-mineral-systems.png and /dev/null differ
diff --git a/public/brand/users/emsl-computing.png b/public/brand/users/emsl-computing.png
deleted file mode 100644
index bb41529..0000000
Binary files a/public/brand/users/emsl-computing.png and /dev/null differ
diff --git a/public/brand/users/gemseo.png b/public/brand/users/gemseo.png
deleted file mode 100644
index e08202c..0000000
Binary files a/public/brand/users/gemseo.png and /dev/null differ
diff --git a/public/brand/users/ibm.png b/public/brand/users/ibm.png
deleted file mode 100644
index 14d6e44..0000000
Binary files a/public/brand/users/ibm.png and /dev/null differ
diff --git a/public/brand/users/icb-dcm.png b/public/brand/users/icb-dcm.png
deleted file mode 100644
index 7d30c01..0000000
Binary files a/public/brand/users/icb-dcm.png and /dev/null differ
diff --git a/public/brand/users/icrar.png b/public/brand/users/icrar.png
deleted file mode 100644
index f7608eb..0000000
Binary files a/public/brand/users/icrar.png and /dev/null differ
diff --git a/public/brand/users/industrial-optimization-group.png b/public/brand/users/industrial-optimization-group.png
deleted file mode 100644
index 2733469..0000000
Binary files a/public/brand/users/industrial-optimization-group.png and /dev/null differ
diff --git a/public/brand/users/lanl.png b/public/brand/users/lanl.png
deleted file mode 100644
index da138db..0000000
Binary files a/public/brand/users/lanl.png and /dev/null differ
diff --git a/public/brand/users/llnl.png b/public/brand/users/llnl.png
deleted file mode 100644
index f975e4c..0000000
Binary files a/public/brand/users/llnl.png and /dev/null differ
diff --git a/public/brand/users/nanograv.png b/public/brand/users/nanograv.png
deleted file mode 100644
index e82bcd6..0000000
Binary files a/public/brand/users/nanograv.png and /dev/null differ
diff --git a/public/brand/users/nasa.png b/public/brand/users/nasa.png
deleted file mode 100644
index a101449..0000000
Binary files a/public/brand/users/nasa.png and /dev/null differ
diff --git a/public/brand/users/national-digital-twin.png b/public/brand/users/national-digital-twin.png
deleted file mode 100644
index 5210425..0000000
Binary files a/public/brand/users/national-digital-twin.png and /dev/null differ
diff --git a/public/brand/users/openmdao.png b/public/brand/users/openmdao.png
deleted file mode 100644
index d411a29..0000000
Binary files a/public/brand/users/openmdao.png and /dev/null differ
diff --git a/public/brand/users/openworm.png b/public/brand/users/openworm.png
deleted file mode 100644
index a2642b7..0000000
Binary files a/public/brand/users/openworm.png and /dev/null differ
diff --git a/public/brand/users/paypal.png b/public/brand/users/paypal.png
deleted file mode 100644
index e50e0a2..0000000
Binary files a/public/brand/users/paypal.png and /dev/null differ
diff --git a/public/brand/users/philipmorrisintl.png b/public/brand/users/philipmorrisintl.png
deleted file mode 100644
index 7482905..0000000
Binary files a/public/brand/users/philipmorrisintl.png and /dev/null differ
diff --git a/public/brand/users/qubole.png b/public/brand/users/qubole.png
deleted file mode 100644
index 4f79e10..0000000
Binary files a/public/brand/users/qubole.png and /dev/null differ
diff --git a/public/brand/users/sandialabs.png b/public/brand/users/sandialabs.png
deleted file mode 100644
index 893d2b4..0000000
Binary files a/public/brand/users/sandialabs.png and /dev/null differ
diff --git a/public/brand/users/seduceproject.png b/public/brand/users/seduceproject.png
deleted file mode 100644
index 2bc1582..0000000
Binary files a/public/brand/users/seduceproject.png and /dev/null differ
diff --git a/public/brand/users/smtorg.png b/public/brand/users/smtorg.png
deleted file mode 100644
index e0f7024..0000000
Binary files a/public/brand/users/smtorg.png and /dev/null differ
diff --git a/public/brand/users/terrapower.png b/public/brand/users/terrapower.png
deleted file mode 100644
index 129d222..0000000
Binary files a/public/brand/users/terrapower.png and /dev/null differ
diff --git a/public/brand/users/wwu-mmll.png b/public/brand/users/wwu-mmll.png
deleted file mode 100644
index f153ba4..0000000
Binary files a/public/brand/users/wwu-mmll.png and /dev/null differ
diff --git a/src/components/content.ts b/src/components/content.ts
index fbdfd15..27d02d4 100644
--- a/src/components/content.ts
+++ b/src/components/content.ts
@@ -4,7 +4,6 @@
*/
import { PEOPLE, PROJECTS } from '../data/site'
-import { USED_BY } from '../data/used-by'
/**
* `` on /community/.
@@ -32,28 +31,6 @@ export function mountPeople(root: ParentNode = document): void {
).join('')
}
-/**
- * `
` in the hero ticker.
- *
- * Logos rather than names: at a glance a reader recognises a mark faster than
- * they read an org login. Filled before the marquee mounts so it measures real
- * content, and each one links to the repository the dependency was verified in,
- * because a claim like this is only worth making if it can be checked.
- */
-export function mountUsedBy(root: ParentNode = document): void {
- const host = root.querySelector
('[data-used-by]')
- if (!host) return
-
- host.innerHTML = USED_BY.map(
- (d) => `
-
-
- `,
- ).join('')
-}
-
/**
* Fills `[data-stat]` elements from the catalog rather than from hard-coded
* markup, so the landing-page numbers cannot drift from what is actually
diff --git a/src/components/marquee.ts b/src/components/marquee.ts
deleted file mode 100644
index eedd492..0000000
--- a/src/components/marquee.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * Infinite marquee.
- *
- * Duplicates its track until the strip is at least twice the viewport width,
- * then translates by exactly one copy — so the loop is seamless regardless of
- * content width. Speed is expressed in px/second, which keeps long and short
- * strips moving at the same visual pace.
- *
- * …items…
- */
-
-import { prefersReducedMotion } from '../lib/env'
-
-export function mountMarquees(root: ParentNode = document): void {
- for (const host of root.querySelectorAll('[data-marquee]')) {
- setupMarquee(host)
- }
-}
-
-function setupMarquee(host: HTMLElement): void {
- const original = Array.from(host.children) as HTMLElement[]
- if (original.length === 0) return
-
- const speed = Number(host.dataset.speed ?? 40)
- const direction = Number(host.dataset.direction ?? 1) >= 0 ? 1 : -1
-
- const viewport = document.createElement('div')
- viewport.className = 'marquee__viewport'
-
- const track = document.createElement('div')
- track.className = 'marquee__track'
-
- const group = document.createElement('div')
- group.className = 'marquee__group'
- group.append(...original)
- track.append(group)
- viewport.append(track)
- host.replaceChildren(viewport)
- host.classList.add('marquee')
-
- const measure = () => {
- // Reset to a single group before measuring, then top up.
- for (const clone of Array.from(track.querySelectorAll('.marquee__group[data-clone]'))) {
- clone.remove()
- }
-
- const groupWidth = group.getBoundingClientRect().width
- if (groupWidth < 1) return
-
- const needed = Math.ceil((host.getBoundingClientRect().width * 2) / groupWidth)
- for (let i = 0; i < Math.max(1, needed); i++) {
- const clone = group.cloneNode(true) as HTMLElement
- clone.dataset.clone = 'true'
- clone.setAttribute('aria-hidden', 'true')
- track.append(clone)
- }
-
- track.style.setProperty('--marquee-shift', `${groupWidth}px`)
- track.style.setProperty('--marquee-duration', `${groupWidth / speed}s`)
- track.style.setProperty('--marquee-direction', direction > 0 ? 'normal' : 'reverse')
- track.dataset.animated = String(!prefersReducedMotion())
- }
-
- measure()
-
- // Late-loading logos change the group width — re-measure when they land.
- for (const img of host.querySelectorAll('img')) {
- if (!img.complete) img.addEventListener('load', measure, { once: true })
- }
-
- let resizeTimer = 0
- new ResizeObserver(() => {
- window.clearTimeout(resizeTimer)
- resizeTimer = window.setTimeout(measure, 120)
- }).observe(host)
-}
diff --git a/src/data/used-by.ts b/src/data/used-by.ts
deleted file mode 100644
index 8ffacc8..0000000
--- a/src/data/used-by.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- * Organisations that build on these packages.
- *
- * Most entries were verified against the package manifests on the repository's
- * default branch: a `requirements*.txt`, `setup.py`, `setup.cfg` or
- * `pyproject.toml` that names the package. Entries that only appeared in
- * GitHub's dependents *index* did not survive — that index lags, and several of
- * them had since dropped the dependency or commented it out.
- *
- * The exception is the block marked below, taken from the "Who uses PyDOE?"
- * page in the pydoe documentation. Those repositories no longer declare pyDOE
- * on their default branch, so they are kept on the strength of that page rather
- * than a manifest we can point at today.
- *
- * pyDOE2 and pyDOE3 count as pyDOE: both forks have been merged back and are
- * maintained here, so a manifest naming either one is a pyDOE user.
- *
- * pyswarm is matched on a word boundary so that `pyswarms` — an unrelated
- * package by a different author — never counts.
- *
- * Logos are the organisations' own marks, desaturated and normalised to a single
- * height by `tools/build-user-logos.py`, so the strip stays even and nothing
- * flashes colour while it loads. Orgs whose avatar is a default identicon, a
- * photograph, or an image that turns to mush in greyscale are left off rather
- * than shown badly.
- */
-
-export interface Dependent {
- /** GitHub org, and the basename of its logo under `/brand/users/`. */
- login: string
- name: string
- /** The repository the dependency was verified in. */
- repo: string
- uses: string
-}
-
-export const USED_BY: Dependent[] = [
- { login: 'nasa', name: 'NASA', repo: 'nasa/GlennOPT', uses: 'pyDOE' },
- { login: 'llnl', name: 'Lawrence Livermore National Laboratory', repo: 'llnl/merlin', uses: 'pyDOE' },
- { login: 'lanl', name: 'Los Alamos National Laboratory', repo: 'lanl/impala', uses: 'pyswarm' },
- { login: 'sandialabs', name: 'Sandia National Laboratories', repo: 'sandialabs/pvOps', uses: 'pyDOE' },
- { login: 'OpenMDAO', name: 'OpenMDAO', repo: 'OpenMDAO/OpenMDAO', uses: 'pyDOE' },
- { login: 'philipmorrisintl', name: 'Philip Morris International', repo: 'philipmorrisintl/GOBench', uses: 'pyswarm' },
- { login: 'cmu-db', name: 'CMU Database Group', repo: 'cmu-db/ottertune', uses: 'pyDOE' },
- { login: 'qubole', name: 'Qubole', repo: 'qubole/uchit', uses: 'pyDOE' },
- { login: 'codecentric', name: 'codecentric', repo: 'codecentric/maximum-entropy', uses: 'pyswarm' },
- { login: 'ICRAR', name: 'ICRAR', repo: 'ICRAR/daliuge', uses: 'pyswarm' },
- { login: 'EMSL-Computing', name: 'EMSL Computing', repo: 'EMSL-Computing/CoreMS', uses: 'pyswarm' },
- { login: 'National-Digital-Twin', name: 'National Digital Twin', repo: 'National-Digital-Twin/NOVA', uses: 'pyswarm' },
- { login: 'gemseo', name: 'GEMSEO', repo: 'gemseo/gemseo', uses: 'pyDOE' },
- { login: 'SMTorg', name: 'SMT', repo: 'SMTorg/smt', uses: 'pyDOE' },
- { login: 'ICB-DCM', name: 'ICB-DCM', repo: 'ICB-DCM/pyPESTO', uses: 'pyswarm' },
- { login: 'openworm', name: 'OpenWorm', repo: 'openworm/ChannelWorm', uses: 'pyswarm' },
- { login: 'wwu-mmll', name: 'Medical Machine Learning Lab', repo: 'wwu-mmll/photonai', uses: 'pyDOE' },
-
- // University research groups.
- {
- login: 'industrial-optimization-group',
- name: 'Multiobjective Optimization Group, University of Jyväskylä',
- repo: 'industrial-optimization-group/pyRVEA',
- uses: 'pyDOE',
- },
- {
- login: 'Curtin-Timescales-of-Mineral-Systems',
- name: 'Timescales of Mineral Systems, Curtin University',
- repo: 'Curtin-Timescales-of-Mineral-Systems/UPb-Unmixer',
- uses: 'soerp',
- },
- { login: 'BGU-AiDnD', name: 'AiDnD, Ben-Gurion University', repo: 'BGU-AiDnD/Debugger', uses: 'pyswarm' },
- { login: 'SeduceProject', name: 'SeDuCe', repo: 'SeduceProject/seduce_ml', uses: 'mcerp' },
- { login: 'atomicateam', name: 'Atomica', repo: 'atomicateam/atomica', uses: 'pyswarm' },
- {
- login: 'AnesthesiaSimulation',
- name: 'Anesthesia Simulation',
- repo: 'AnesthesiaSimulation/Python_Anesthesia_Simulator',
- uses: 'pyswarm',
- },
-
- // From the "Who uses PyDOE?" page in the pydoe docs. Not currently declared
- // in these repositories' manifests — see the note at the top of this file.
- { login: 'ibm', name: 'IBM', repo: 'ibm/simulai', uses: 'pyDOE' },
- { login: 'paypal', name: 'PayPal', repo: 'paypal/gators', uses: 'pyDOE' },
- { login: 'terrapower', name: 'TerraPower', repo: 'terrapower/armi', uses: 'pyDOE' },
- { login: 'nanograv', name: 'NANOGrav', repo: 'nanograv/holodeck', uses: 'pyDOE' },
-]
diff --git a/src/main.ts b/src/main.ts
index 759ba38..d92e929 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -19,12 +19,11 @@ import { mountFooter } from './components/footer'
import { mountCounters, mountReveals } from './components/reveal'
import { mountDisplayType } from './components/wordmark'
import { mountDrawFields } from './components/draw-field'
-import { mountMarquees } from './components/marquee'
import { mountPixelRules } from './components/pixel-rule'
import { mountPointerEffects } from './components/pointer'
import { mountMotes } from './components/motes'
import { mountFeaturedGrid, mountCatalog } from './components/project-cards'
-import { mountPeople, mountUsedBy, syncStats } from './components/content'
+import { mountPeople, syncStats } from './components/content'
import { defineEggzecText } from './lib/eggzec-block'
import { prefersReducedMotion } from './lib/env'
@@ -69,13 +68,11 @@ function boot(): void {
mountFeaturedGrid()
mountCatalog()
mountPeople()
- mountUsedBy()
syncStats()
mountDisplayType()
// Behaviour over whatever ended up in the DOM.
mountDrawFields()
- mountMarquees()
mountPixelRules()
mountReveals()
mountCounters()
diff --git a/src/styles/components.css b/src/styles/components.css
index c416961..35045f3 100644
--- a/src/styles/components.css
+++ b/src/styles/components.css
@@ -803,87 +803,6 @@
color: var(--ink-muted);
}
-/* ---- marquee ----------------------------------------------------------- */
-
-.marquee {
- --marquee-shift: 0px;
- --marquee-duration: 30s;
- --marquee-direction: normal;
- position: relative;
- overflow: hidden;
- mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
- -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
-}
-
-.marquee__viewport {
- overflow: hidden;
-}
-
-.marquee__track {
- display: flex;
- width: max-content;
-}
-
-.marquee__track[data-animated='true'] {
- animation: marquee-scroll var(--marquee-duration) linear infinite;
- animation-direction: var(--marquee-direction);
-}
-
-.marquee:hover .marquee__track[data-animated='true'] {
- animation-play-state: paused;
-}
-
-.marquee__group {
- display: flex;
- align-items: center;
- gap: var(--space-7);
- padding-right: var(--space-7);
- flex: 0 0 auto;
-}
-
-@keyframes marquee-scroll {
- from {
- transform: translateX(0);
- }
- to {
- transform: translateX(calc(var(--marquee-shift) * -1));
- }
-}
-
-/* ---- tool chips inside the marquee ------------------------------------- */
-
-/* ---- used by ------------------------------------------------------------ */
-
-/* Sized for a landing-page logo strip, not for GitHub's own "Used by" widget,
- which runs at 24px because it is a dense sidebar list of user avatars. These
- are marks meant to be recognised in passing, so they get roughly double that.
-
- Hover darkens and nothing else. The strip is moving, so anything that changes
- the logo's size or position under the cursor reads as a glitch. */
-.used-by {
- display: inline-flex;
- align-items: center;
- padding: 0.4rem 1.35rem;
-}
-
-/*
- * Every logo is delivered at one height, so the strip needs a single `height`
- * here and nothing else. The width cap is for the occasional wordmark that is
- * much wider than it is tall.
- */
-.used-by__logo {
- width: auto;
- height: 68px;
- max-width: 210px;
- object-fit: contain;
- opacity: 0.62;
- transition: opacity var(--dur-base) var(--ease-out);
-}
-
-.used-by:hover .used-by__logo {
- opacity: 1;
-}
-
/* ---- spotlight surface -------------------------------------------------- */
[data-spotlight] {
diff --git a/src/styles/pages.css b/src/styles/pages.css
index 3803e93..53a4f58 100644
--- a/src/styles/pages.css
+++ b/src/styles/pages.css
@@ -110,25 +110,6 @@
margin-top: var(--space-2);
}
-.hero__ticker {
- display: flex;
- align-items: center;
- gap: var(--space-4);
- margin-top: var(--space-6);
- padding-top: var(--space-6);
- border-top: var(--border) solid var(--line);
-}
-
-.hero__ticker-label {
- flex: 0 0 auto;
- color: var(--ink-faint);
-}
-
-.hero__ticker-strip {
- min-width: 0;
- flex: 1;
-}
-
/* ---- install strip ------------------------------------------------------ */
.install {
diff --git a/tools/build-user-logos.py b/tools/build-user-logos.py
deleted file mode 100644
index 36a68ca..0000000
--- a/tools/build-user-logos.py
+++ /dev/null
@@ -1,84 +0,0 @@
-"""
-Build the "Used by" logo strip.
-
-Each source logo — an organisation's GitHub avatar, or replacement artwork
-dropped into the source directory — is flattened onto white, desaturated, and
-scaled to one content height. Desaturating here rather than in CSS keeps the
-strip even and stops anything flashing colour while it loads; the single height
-lands every logo on one optical line instead of a row of mismatched sizes.
-
- python tools/build-user-logos.py [--out public/brand/users]
-
-Source files are named `.`, lowercased; the site looks the
-logo up by login. Orgs whose avatar is a default identicon, a photograph, or an
-image that turns to mush in greyscale are better left out than shown badly.
-"""
-
-import argparse
-import os
-import sys
-
-import cv2
-import numpy as np
-
-HEIGHT = 128 # content height in px — 2x the CSS height, for retina
-MAX_WIDTH = 420 # width cap, so a long wordmark cannot take over the strip
-
-
-def load(path):
- """Read an image path that may contain non-ASCII characters on Windows."""
- im = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
- if im is None:
- raise SystemExit(f"unreadable: {path}")
- if im.ndim == 2:
- im = cv2.cvtColor(im, cv2.COLOR_GRAY2BGR)
- if im.shape[2] == 4:
- return im[:, :, :3], im[:, :, 3]
- return im, None
-
-
-def process(src, dest):
- bgr, alpha = load(src)
-
- # Avatars ship an alpha channel that only rounds the corners, and the page
- # behind the strip is white — so flatten onto white and keep the square.
- if alpha is not None:
- a = (alpha.astype(np.float32) / 255.0)[:, :, None]
- bgr = (bgr.astype(np.float32) * a + 255.0 * (1 - a)).astype(np.uint8)
-
- gray = cv2.cvtColor(bgr, cv2.COLOR_BGR2GRAY)
-
- h, w = gray.shape
- scale = min(HEIGHT / h, MAX_WIDTH / w)
- size = (max(1, round(w * scale)), max(1, round(h * scale)))
- interp = cv2.INTER_AREA if scale < 1 else cv2.INTER_CUBIC
- gray = cv2.resize(gray, size, interpolation=interp)
-
- ok, buf = cv2.imencode(".png", cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR),
- [cv2.IMWRITE_PNG_COMPRESSION, 9])
- if not ok:
- raise SystemExit(f"could not encode: {dest}")
- buf.tofile(dest)
- return size
-
-
-def main():
- ap = argparse.ArgumentParser(description=__doc__)
- ap.add_argument("source", help="directory of . logo files")
- ap.add_argument("--out", default=os.path.join("public", "brand", "users"))
- args = ap.parse_args()
-
- os.makedirs(args.out, exist_ok=True)
- names = sorted(f for f in os.listdir(args.source)
- if f.lower().endswith((".png", ".jpg", ".jpeg", ".webp")))
- if not names:
- sys.exit(f"no images in {args.source}")
-
- for name in names:
- login = os.path.splitext(name)[0].lower()
- w, h = process(os.path.join(args.source, name), os.path.join(args.out, f"{login}.png"))
- print(f" {login:38} {w:4}x{h:<4}")
-
-
-if __name__ == "__main__":
- main()