Skip to content

v2.27.0 — The Anthology Atlas and the recovered back catalogue

Latest

Choose a tag to compare

@EISSeuropa EISSeuropa released this 19 Aug 20:20
· 111 commits to master since this release
Immutable release. Only release title and notes can be modified.
c5a5f49

This release turns the Anthology from a list you read into a corpus you can explore, cite and download. The Atlas maps the whole thing as a network you can filter, search and link into, each of the 17 research themes gains a page and a feed of its own, and the corpus is now deposited with a DOI, described in HAL and archived in Software Heritage. Alongside that, EISS 2026 abstract coverage reaches every paper, recovery of the pre-Indico back catalogue begins, and volunteers get somewhere to publish under their own names.

The Anthology Atlas

The Atlas opened this cycle as a proof of concept and closes it as a page in its own right, indexed, signposted from the Anthology and able to explain itself on a first visit. It draws every paper as a dot pulled toward the research themes it touches, with a second lens that maps co-authorship instead, and it now draws the links between papers rather than only between papers and themes.

Screenshot 2026-08-19 at 22 23 11

You can filter by edition, search with a Find control, deep-link a view and hand that URL to someone else, and on a phone the map leads instead of a wall of filters. Each of the 17 research themes has a page of its own, a share card, and an Atom feed carrying new papers and newly recovered abstracts as they land.

Screenshot 2026-08-19 at 22 24 59

The corpus, citable and machine-readable

The Anthology is deposited on Zenodo as a dataset under CC BY 4.0, described in a note deposited in HAL, and archived in Software Heritage together with the code that builds it. The page carries all three as badges and a "Cite this corpus" panel holding the reference, and citation metadata in its head means saving the page into a reference manager records the dataset rather than a web page. Every paper carries a downloadable .bib or .ris reference, a filtered set can be exported in one go, and the whole corpus is available as plain JSON with a corpus-description note documenting its scope and its limits.

The back catalogue, edition by edition

EISS 2026 abstract coverage is complete, all 69 papers, and recovery has moved back into the pre-Indico editions that Indico cannot export: 20 papers from 2018, 18 from 2019, five from 2021, and more across 2022 and 2023, transcribed by hand from the organisers' files.

Screenshot 2026-08-19 at 22 24 05

The Anthology shows that coverage year by year rather than as a single figure. Paper pages suggest related papers and link the research themes their own abstract is about, the by-person view lists who each author has written with, and the by-paper view gains an Event filter so the joint workshops are findable on their own. The 2017 and 2018 conferences join the archive list on /past with real programme pages in place of two screenshots.

Around the site

Volunteers and interns have somewhere to publish: /blog.html carries a page per post with a visible byline, and the internship page is rebuilt around four kinds of work, stating the terms it runs on and crediting people whose track produces no byline of their own. The site announces its new Co-Director team, /GlobalRisks carries the 2026 survey alongside 2025, and the main menu is grouped so it stops hiding half the site. A living style guide at /design-system.html renders from the stylesheet that defines the design language, so a token that exists is a token that appears. The August accessibility audit fixed four defects across the site and five places where white text sat on the accent colour in dark mode, the Anthology stopped scrolling sideways on phones, and the build-sanity lint now runs on every pull request instead of skipping about a quarter of them.

Index of changes

Added

  • The footer no longer calls EISS a registered charity. The English half of the legal-status line read "EISS is a registered charity (W751263001) under French law" while the French half of the same string said association loi 1901. The two contradicted each other on every page of the site, and an association loi 1901 is not a charity in the English sense. It now reads "a non-profit association under the French law of 1901, registered as W751263001", in all three locale catalogues.

  • A blog, so volunteers and interns can publish under their own names. /blog.html and a page per post, with a visible byline: the author's name and one line of standing, such as "EISS volunteer, 2027". The internship programme is built on the promise that a placement ends with something published under your own name, and until now there was nowhere on the site to put one. /news carries short association announcements with no per-item page and no author, because it was never meant to hold long-form writing, so the blog sits beside it rather than inside it. Publishing is one Markdown file in src/blog/ and no other edit: the layout, the tag and the permalink come from a directory data file, and description is computed from the post's own summary. Posts fold into the existing /feed.xml rather than getting a second feed, so one subscription still delivers everything, and entry dates come from front matter rather than build time, since this repo rebuilds on a schedule and a build-time timestamp would re-notify every subscriber on a timer. scripts/check-feeds.py gates that: it asserts newest-first ordering and a content-derived <updated> across all 18 feeds, which is what caught the ordering question in the first place. Linked from the footer and the visual sitemap in all three locales, and picked up by sitemap.xml automatically. English only, and the page says so: rule §1 forbids machine translation, so every locale added here would be a hand-translation burden on every future post forever, and committing to three languages would mean fewer posts rather than more readers. No DOI yet, deliberately, since depositing short posts in a Zenodo community that currently holds the corpus would change what that community signals. Revisit once there are three or four worth depositing. Ships with no posts: the surface exists so that the first volunteer piece has somewhere to go, and /blog.html says so plainly until one arrives. Closes #1259.

  • /roadmap gets its own share card, in all three locales. It was falling back to the generic site image, so a link shared on LinkedIn or Mastodon read as generic rather than intentional. Generated by scripts/make-share-cards.py like every other page card. Closes #272.

  • The Anthology and the Atlas now carry their own design credit. The site-wide footer credit sits at the level nobody reads it at, so someone citing the Anthology, linking the Atlas or writing about either had nothing to attribute the design to. Each page now names Dr Arthur PB Laudrain and links to his board card, resolving the slug from board.json the way the footer credit already does, in all three locales on the Anthology and in English on the English-only Atlas. README.md names both. The same name and the same discreet register as the footer line, deliberately: two different names, or a louder treatment, would read as competing claims rather than one claim at a more useful level. The 17 per-theme Atlas pages do not repeat it, since they are the same Atlas pre-filtered and eighteen credits for one piece of work would be noise. Closes #1228.

  • The sitemap now tells search engines when each page last changed. Every one of the 418 URLs carries a <lastmod>, from two sources: the 315 paper pages take the corpus ledger's date, which records when the paper or its abstract actually landed, and every other page takes its source file's last git commit. The ledger wins where it exists, because a git date would track edits to the data module that happens to contain a paper rather than the paper itself. Search engines use lastmod to decide what is worth re-fetching, and the site had been forgoing the signal entirely. The blocker recorded on the issue is cleared: deploy.yml's checkout now uses fetch-depth: 0, since git log in a shallow checkout reports the checkout commit for every file. That failure mode is the reason this needed care rather than a one-line filter: 418 pages all claiming to have changed today would be worse than no dates at all, because it teaches crawlers to ignore the signal. The filter detects a shallow clone and omits the element rather than faking it, so a workflow without full history produces a dateless sitemap instead of a wrong one, and check-build-sanity.mjs fails if the dates ever come out all identical. The dates span 31 distinct days across the corpus, and the git pass costs about 0.2 seconds because it reads the whole history once rather than shelling out per page. Closes #620.

  • You can now follow a research theme by feed, and each theme has its own Atom feed of new papers and newly recovered abstracts. /feeds/themes/<slug>.xml, one per theme, capped at 50 entries, advertised through <link rel="alternate"> and a visible "Follow this theme" control on each Atlas theme page. The Anthology grows in bursts and the site has no mailing list and no analytics, so there was no mechanism at all for turning a first visit into a second one. A feed needs no account and stores nothing on our side, which suits a site that runs without tracking. The design question was the entry date, since the corpus carries a year and had no record of when anything was added. src/_data/corpusLedger.json now tracks two dates per paper, when it entered the corpus and when its abstract first attached, and an entry takes the later of the two, so a recovered abstract surfaces as fresh years after its conference and is labelled as such. The ledger is committed and authoritative: it is the only record of those dates, and regenerating it would fire a false update at every subscriber. Existing papers were backdated to their edition rather than to the day the script first ran, so the feeds read as a plausible history instead of 511 items dated the same afternoon. Each feed's <updated> derives from its newest entry and never from the build, because this repo rebuilds on a schedule and a build-time timestamp would notify every subscriber on a timer. scripts/check-feeds.py parses every feed and asserts that, plus required Atom elements, RFC 3339 dates, unique ids, the cap and newest-first ordering. It caught a real bug: Nunjucks has no selectattr filter, so the head link on every theme page pointed at the same wrong feed while the visible link was correct. Documented in docs/anthology-machine-readable.md, which also covers the citation exports and the theme pages. Closes #1256.

  • Each of the 17 research themes now has its own Atlas page and its own share card. A filtered Atlas view lived only in a query string, and crawlers neither run JavaScript nor distinguish ?themes=Deterrence from the bare URL, so every shared link produced the same generic preview and the one thing making it interesting was invisible. /anthology-atlas/theme/<slug>.html is a real URL per theme with its own title, description and generated card, rendering the map already filtered rather than flashing the whole corpus first. Cards are produced by scripts/make-share-cards.py from the same data module the pages paginate over, so a new theme in the corpus yields a page and a card without anyone retyping a name, and they carry the Anthology constellation rather than the EISS wordmark, since a mark that is itself a network map says what the page is without words. Editions were left on the generic card: the issue offered 29 pages and flagged the cost, and theme views are the ones people share. The existing ?themes= links behave exactly as before and each theme page links to its equivalent, so the two forms cannot diverge. The Atlas body moved into src/_includes/atlas-body.njk so the canonical page and the 17 theme pages render from one source rather than 17 copies. Pages carry data-pagefind-ignore to keep near-identical entries out of site search while staying in the sitemap, which is the point of them. Building this surfaced an Eleventy default worth knowing: pagination.addAllPagesToCollections is false, so only a paginated template's first page reaches collections.all and therefore the sitemap. The theme pages opt in; the same default is why 314 of the 315 paper pages are missing from the sitemap, tracked separately. Closes #1255.

  • Every paper in the Anthology now has a downloadable reference, and the whole filtered set can be exported at once. Each paper page gains /papers/<slug>.bib and /papers/<slug>.ris siblings, so a reference can be fetched with no JavaScript at all, and the by-paper view gains an "Export these references" control that builds a BibTeX or RIS file from whatever the filters are currently showing. The bulk file is assembled client-side from /data/citations.json, fetched on the first export click rather than on page load, since the by-paper view already renders 500+ rows and most readers never export. Three defects surfaced while building it. Twenty papers from the three joint events (the 2019 Joint Policy Workshop, the 2024 Joint Sciences Po–EISS Conference, the Joint Conference on the War in Ukraine) were telling Google Scholar, Zotero and every BibTeX reader that they had been presented at the annual conference, through a hardcoded citation_conference_title and a matching booktitle. Sixty-four titles carried acronyms with no brace protection, so a style that title-cases rendered NATO as "nato". One title's ampersand would have broken a LaTeX compile outright. All three are fixed, and scripts/check-citations.mjs now asserts brace balance, escaping, RIS well-formedness and acronym protection across all 511 papers in CI. The citation builders moved out of paperPages.js into src/_data/citations.js: they were reachable only for the 315 papers that have a landing page, and a bulk export that silently dropped the other 196 would have been worse than none. Zotero needs no custom translator, since the citation_* tags the pages already emit are exactly what its Embedded Metadata translator reads. Part of #1254.

  • The constellation blue is now a design token, and the style guide proves how the marks behave. #73caff, half the two-colour brand identity and the colour of every constellation node, existed only as a literal inside the logo SVGs: the one part of the brand outside the token system, so it could not be inspected or checked. It is now --brand-network in site.css, with the three brand SVGs carrying fill="var(--brand-network, #73caff)" so the fallback keeps the rendered colour provably identical. It deliberately has no dark-mode override, because the constellation holds one value on every surface, which is what lets a single asset sit on a light header and a dark hero. /design-system.html gains a brand-marks section rendering all three variants at 128, 64, 32 and 16px on a light and a dark panel side by side, which turns two things BRAND.md asserts into things you can see: the wordmark follows its surface via currentColor, and the constellation does not. Groundwork for #1253.

  • A living style guide at /design-system.html, rendered from the stylesheet that defines the design language. The 68 design tokens in site.css's :root are parsed at build time by src/_data/designTokens.js and drive every scale on the page: colour swatches, the type ramp, the spacing steps, radii, shadows and motion. Adding a token to the stylesheet makes it appear with no other edit, so the guide cannot drift from what the browser actually uses. A partial set of components renders alongside them, each labelled with the class prefix that owns it. The page exists for rule §14 as much as for reference: a component rendered in isolation, at desktop and phone width, is where undefined CSS surfaces, which is how the press kit and the search modal both shipped invisible. scripts/a11y_lint.py now sweeps it like any other page. noindex, out of the navigation and excluded from site search, since it is a maintainer surface. Closes #1271.

  • docs/design-system.md gains the design-token reference, generated rather than written. The 68 tokens across 21 families are emitted into the doc by scripts/gen-token-reference.mjs between TOKENS markers, the same machine-managed-block convention the roadmap autostamp already uses, with the prose around it maintainer-written. A hand-maintained table of 68 values is why this sat in the backlog since May: it would have gone stale the first time a token changed. --check reports staleness for wiring into CI later. Closes #1269, and with the style guide largely supersedes #282.

  • /licensing now tells you how to cite the Anthology, and where its description lives. A "Citing the Anthology" section on /licensing.html (+ FR + DE) carries the ready-made reference, the concept DOI that always resolves to the newest version, and a pointer to the corpus-description note deposited in HAL at hal-05711925. It renders from site.corpus in src/_data/site.js, which now also holds halId and halUrl, so the citation cannot drift from the block already on /anthology: one edit updates both pages. README.md gains a paragraph distinguishing the three deposits, since a reader seeing a DOI badge and two Software Heritage badges has no way to tell that one identifies the data and the others the code. Completes the surfacing criteria on #1221, #1222 and #1223.

  • The internship page becomes a volunteering page, built around four kinds of work. /internship.html (+ FR + DE) is rebuilt on the bénévolat model: unpaid, remote, around a day a week, with no fixed hours, and open to graduates as well as enrolled students, since volunteering needs no enrolment. Four task categories replace the vague "supporting our events": corpus and abstract indexing, researching and writing a thematic brief, improving the database, and Annual Conference preparation. A convention de stage stays available for students whose programme requires one, in a single line rather than a legal explainer, and the old "up to two months" framing is gone: it stated the gratification threshold as though it were a duration cap. Nav labels, the /initiative call to action and the visual sitemap follow in all three locales.

  • The Anthology carries the deposit badges, and the DOI one stops rendering broken. The Zenodo DOI badge and the two Software Heritage badges now sit in the page header, visible without opening anything, the same three the repository README shows. They carry the DOI and the SWHID in their alt text, so the "Cite this corpus" panel drops the text rows that repeated them and keeps the reference string and the HAL note. Both surfaces serve them from src/assets/images/badges/ instead of hotlinking: Zenodo rate-limits GitHub's image proxy, which is why the README's DOI badge intermittently showed as a broken image, and a hotlink on the site would have added that flakiness plus a third-party request for every visitor. Refreshing them is a curl in the release-time pass that already re-collects the SWHID.

  • Saving the Anthology into a reference manager now records the dataset, not the web page. The three Anthology pages carry citation metadata in their head, so the Zotero connector (and anything else reading Highwire or Dublin Core tags) files the deposited corpus with its title, author, year, publisher, DOI, abstract, language and CC BY 4.0 rights, typed as a dataset. The fields render from site.corpus, the same record the visible "Cite this corpus" reference comes from, so the automatic capture and the printed reference cannot drift apart. scripts/check-build-sanity.mjs guards the one silent way to break it: any Highwire tag that names a journal, conference, book, thesis or report would retype every save with a green build and no visible change on the page.

  • The corpus can now be exported as plain JSON, and a corpus-description note documents it. scripts/export-corpus-json.mjs emits one self-describing JSON file (meta, editions, the 17-theme vocabulary with its per-locale labels, per-year abstract coverage, 511 papers, 494 authors) from corpus.js and paperIndex.js, so the Zenodo deposit can carry data rather than the raw Eleventy data modules it holds today. Not wired into the Eleventy build: the deposit is cut by hand a couple of times a year, and the published build-time export belongs to #641 with its data dictionary. Alongside it, docs/anthology-corpus-note.md describes the corpus for readers rather than maintainers: scope and the twelve editions, the two source eras behind it (Indico from 2023, transcribed programmes before that) and the abstract-coverage cliff that follows from them, how panel-level theme tagging works and what it therefore cannot support, the co-authorship structure (184 pairs across 64 clusters, 300 authors with no co-author), six stated limitations, and the citation. Every figure in it is derived from the export and machine-checked against it. The note carries an English abstract and a hand-written French Résumé, both leading with the coverage discontinuity rather than burying it, so the bilingual HAL metadata fields can be filled from the document itself. scripts/build-corpus-note-pdf.sh renders it to PDF for the deposit (pandoc via xelatex, for the French accents and the two en-dashes inside proper nouns), kept out of CI for the same reason as the JSON export. The note is now deposited at hal-05711925 as a Research report, retyped from the conference proceedings it was first filed under: proceedings asserted an edited volume that does not exist, and implied EISS had published papers whose rights sit with their authors. The Research report typing also placed the record in LARA, HAL's portal for scientific and technical reports. docs/corpus-archiving.md now carries the full deposit procedure as a numbered list, opening on the step most easily skipped: the Zenodo files are a generated export, so regenerating them is step one and a deposit that skips it ships the previous state's numbers under a new version label. It also documents what the export contains key by key, that theme references are stable keys rather than display labels (so they survive a retranslation), and the paperIndex.stats.editions trap the script routes around. The export script prints the remaining steps after it writes, since that is the point at which someone is actually depositing. The same doc and the roadmap record the resulting split (HAL holds the readable description, Zenodo holds the dataset), that a dedicated EISS collection needs a structure registered in AuréHAL and is deferred rather than refused, and the two fixes still outstanding on the HAL record: it cites the version DOI rather than the concept DOI, and carries no licence. Part of #1221 and #1222.

  • The Anthology can now be cited: a "Cite this corpus" block carrying its Zenodo DOI. The corpus is deposited as a CC BY 4.0 dataset on Zenodo, and the Anthology header now says so, with a ready-made reference and the DOI, in a collapsed <details> sitting beside the abstract-coverage bars (EN/FR/DE, hand-translated chrome; the reference itself stays in English in every locale, because a bibliographic reference is reproduced rather than translated). The reference and the DOI live once in site.corpus (src/_data/site.js) and render through archive-page.njk, so a future deposit is a one-line edit. In the header rather than the foot, per the lesson in #1134. Part of #1221.

  • docs/corpus-archiving.md records how the corpus is deposited, and which DOI to use. Zenodo mints two DOIs per record and they are not interchangeable: the concept DOI always resolves to the newest version, the version DOI pins to one snapshot forever. The doc states that citations use the concept DOI, notes the still-unsettled versioning cadence (the deposit follows this repo's SemVer, while #1221 specified one version per annual conference edition), and records the known gap that the deposited files are the raw .js data modules rather than the machine-readable export in #641. Registered in docs/README.md.

  • A new /internship.html page describes the EISS internship and how to apply (EN/FR/DE). The internship is a remote placement of up to two months supporting the network's events — above all the Annual Conference. Because the EISS is a French loi 1901 association, the placement is scoped to French labour law: it is open only to enrolled students who can provide a tripartite convention de stage from their (French or convention-compatible European) institution, and it is unpaid within the limits that convention allows — the page states the convention requirement explicitly. It lays out the placement at a glance and a "How to apply" card: send a CV and cover letter to contact@eiss-europa.com, with the institution and the dates the convention can cover (applications for the first half of the year, January–June, are preferred). It reuses the existing page components (no new CSS) and is signposted from the footer's "About us" list next to Membership and from the "get involved" CTA strip at the foot of /initiative.html, in all three locales.

  • A proof-of-concept "Anthology Atlas" maps the paper corpus as a force-directed graph. A new, unlinked /anthology-atlas.html (EN-only, noindex, kept out of the sitemap and site search) draws all 511 deduplicated papers as dots pulled toward the 17 research-theme hubs (plus an "Untagged" hub), so multi-theme papers settle on the bridges between fields; each dot is coloured by its edition year, chips filter by year and spotlight a theme, papers with an Anthology landing page render solid while those without show as hollow rings (so curation gaps are visible), and Best Paper Prize winners and published versions are badged. It is the paper-side sibling of the NetSec Atlas (which maps people), built as a vanilla-canvas renderer over a build-generated /data/anthology-atlas.json projected from src/_data/paperIndex.js — nothing hand-maintained. Soft launch for judging before any promotion. Part of #1124.

  • The Anthology Atlas gains an "Authors" lens: a co-authorship map of the corpus. A lens switcher (Papers / Authors) lets the same map be read per paper or per author. The Authors lens draws one dot per deduplicated author (deduped on the NetSec-compatible name_key, now a shared src/_data/nameKey.js used by both the Atlas and authorsIndex.js), anchored to the theme hubs its papers touch, with author↔author co-author edges drawn on top (heavier for a pair sharing more than one paper) so collaboration clusters settle out; dot size scales with paper count. A "Collaborators only" chip (Authors lens only) hides solo-only authors, leaving just the collaboration clusters — the headline view. Year chips filter both lenses, the hover card lists co-authors and links to the author's by-person Anthology view, and the stats strip becomes lens-aware. After name_key dedup the map carries 496 authors, 184 co-author pairs and 65 clusters (195 authors collaborate; 301 are solo-only). src/_data/anthologyAtlas.js now emits authors[] + coauthorEdges[] alongside papers[]. Part of #1129.

  • The Anthology Atlas is out of soft launch: indexed, signposted, and self-explaining. /anthology-atlas.html drops its noindex, rejoins the sitemap and the site search, and gains a real meta description and social card, so it is now discoverable rather than unlinked. A new atlas-signpost.njk link-card (the established speakers-cta pattern) sits in the Anthology page header, directly under the corpus stats it maps, in every locale, with a data-derived sub-line (papers / authors / research themes) and an "in English" note on the FR/DE cards, so the map is two clicks from /anthology and /papers in all three languages. (The card first shipped at the foot of the page, which put it ~87,000px down — below the entire 500-row list — where nobody would ever reach it; it moved into the header immediately after.) First-time visitors get a welcome strip (revealed pre-paint to avoid layout shift, dismissed sticky via localStorage) and a guided coachmark tour — a reusable, dependency-free engine (src/assets/js/atlas-tour.js, window.eissTour, ported from the NetSec directory's tour with its keyboard, focus-trap, ARIA and reduced-motion behaviour intact) that walks through the lens switcher, filters, the map, the marker legend, the stats strip, and the Authors-lens "Collaborators only" view; a ? button in the masthead reopens it any time, the step list is viewport-aware (a shorter walkthrough on phones), and steps whose target is hidden are skipped so "Step X of N" stays honest. Nav is untouched — the Anthology cluster is a flat top-nav item, so signposts + the sitemap carry discovery. Closes #1134.

  • /GlobalRisks now carries the 2026 edition of the survey, alongside 2025. The page had been showing only the inaugural 2025 results. It now leads with Global Risks to the EU 2026 (Veronica Anghel, EUI, 2026), the second annual wave, fielded from 12 November 2025 across the EUI, EUISS, TEPSA and EISS expert networks: the five scenarios that rank as high risks to EU security in 2026 (a hybrid attack on EU critical infrastructure, a Ukraine ceasefire on Russia's terms, a US withdrawal from security guarantees, new Russian military action in non-NATO neighbours, and a China–Taiwan cross-strait conflict), the report's principal-findings pull quote, and three figures lifted from the report itself (the world risk map, the high-risk likelihood/impact scatter, and the 30-risk radar) under its CC BY 4.0 licence with attribution. The 2025 edition is preserved in full beneath as "Previous edition", and the CTAs now point at the current project URL plus a direct download of the 2026 report.

  • A leadership announcement: the EISS has a new Co-Director team. A new /leadership-2026.html press-release page (EN/FR/DE) announces Hugo Meijer's move to Founding and Honorary Director after nine years as Director, the appointment of Chiara Ruffa and Moritz Weiss as Co-Directors, and Arthur Laudrain and John Helferich joining the Board, with a circular headshot strip of the five and a closing thank-you to departing members Sarka Kolmasova and Marco Wyss. A news-type item in src/_data/news.json surfaces it on /news, the homepage "Latest" strip and /feed.xml, and the homepage announcement card (src/_data/announcement.js) is refreshed from the June conference wrap-up to the same story.

  • A new EISS 2026 paper joins the Cyber and Digital Sovereignty panel. Dmytro Uzlov and Vladyslav Vilihura's "From National Incident Response to Zero Trust: Bridging Cyber Defence Policy and Technical Implementation in Wartime Ukraine" is added to src/_data/archiveProgrammes.js and now shows on the /2026 programme grid and its own Anthology page, its abstract pulled in by scripts/sync-abstracts.mjs. Adding a paper after the freeze also surfaced a stale-data gap: the Anthology corpus was still reading 2026 papers from the live indico.json snapshot cached from before the conference ended, so the frozen archive edit alone would not have attached. Running the overdue scripts/sync-indico.py (the daily sync had gone quiet since 11 June) let the past event drop out of the live snapshot, restoring the archive as the source for 2026. Tracked in #1085.

  • The Anthology's by-paper view gains an "Event" filter, so joint events are findable on their own. The by-person view already let you filter by event; the by-paper list only offered a year filter, which lumped the 2019 EISS–NDC Joint Policy Workshop (Brussels) in with the annual EISS 2019 conference, and the two 2024 joint conferences in with EISS 2024. A new "Event" dropdown lists every edition (the annual EISS / ESSC conferences and each joint event) with its paper count and mirrors into the URL for shareable links. It replaces the by-paper year filter, which it subsumes (selecting an edition is more precise than a year), matching the terminology the by-person view already uses. EN/FR/DE.

  • Seven more recovered abstracts: five fill out the 2019 EISS–NDC Joint Policy Workshop, two more land in EISS 2021. From the organisers' submission files, the Joint Policy Workshop now also shows abstracts for Šárka Kolmašová ("A critical appraisal of Višegrád 4 Security Potential"), Liviu Horovitz & Elias Götz ("Explaining the US Decision to enlarge NATO"), Thomas Scotto & Konstantin Gavras ("Citizens' attitudes to EDC in UK, France, and Germany"), Mark Webber & Jens Ringsmose ("European Allies' response to the Trump Presidency") and Dominika Kunertova ("Change in Burden-Sharing mind-set in NATO"), taking that workshop to 8 of 10 papers (only Michnik and Bunde remain). EISS 2021 gains Constantino Xavier's "India's New Security Approach to the European Union" and Marc DeVore's "Building the Best Tank". Where a submission carried no separate abstract, the paper's own introduction was distilled in its place. Added to src/_data/paperAbstractsManual.json. Part of #794. Progresses #886.

  • The 2019 EISS–NDC Joint Policy Workshop gains three paper abstracts. Christelle Calmels's "NATO's 360° approach reflective of internal division", Marc De Vore's "Collaborative Arms Procurement", and Jonas Driedger's "The British and German attitudes to Russia" now show their abstracts on their Anthology paper pages, distilled from the authors' submitted papers and hand-added to src/_data/paperAbstractsManual.json. A fourth recovered proposal (a migration / Mediterranean paper) was not on the workshop programme, so it was left out. Part of #794. Progresses #886.

  • Four more pre-Indico paper abstracts recovered from old proposal files (2021 and 2022). Jordan Becker's "Arms Without Influence? Defense Industrial Policy and Burden-Sharing in the Transatlantic Community", Brendan Flynn's "European Naval Procurement under Global Competition", and Alberto Cunha's "Slowly Moving Towards a European Defence?" (all EISS 2021 Lisbon), plus Dominika Kunertova's "Un-Hyping Hypersonic Weapons" (EISS 2022 Berlin), now show their abstracts on their Anthology paper pages. Each was confirmed against the transcribed programme and hand-added to src/_data/paperAbstractsManual.json from the author's submission. A batch of other recovered proposals turned out to be papers that never made the final programme (proposed but not presented), so they were correctly left out. Part of #794. Progresses #886.

  • Fixed a transcription bug in Carrie Lee's EISS 2022 paper title. "Military Politics on the Battlefield: Strategy and Effectiveness in War" was recorded with a stray "USA," affiliation fragment leaking into the title; the title now reads cleanly on the programme grid and the Anthology.

  • Three more EISS 2026 panel abstracts recovered, lifting 2026 coverage to 65 of 69 papers. Benoît Pelopidas's "Nuclear Futures, Utopias, and the Case for a Renewed 'Strict Sufficiency'", Emma Rosengren's "Reconceptualizing nuclear deterrence and national identity: the cases of Finland and Sweden", and Matthew Evangelista's "Ritual deterrence, magic strategies, and nuclear war in Europe" now show their abstracts on the 2026 programme grid and their Anthology paper pages. They run as panel subcontributions, which the Indico export API does not expose, so they were hand-added to src/_data/paperAbstractsManual.json from the convener's file. A fourth paper on the panel was not available. Part of #794. Progresses #886.

  • The 2026 "Conduct of Contemporary and Future War" panel gets its three paper abstracts, taking 2026 coverage to 68 of 69. Baptiste Alloui-Cros and Giles Moon's "Learning from Ukraine: The West must be prepared for positional warfare", Martijn Rouvroije's "Conceptual Inquiry into Military Deep Operations: A Framework for Analysis", and Troels Burchall Henningsen's "Working in the Margins: Can Small State Special Operations contribute to Deterrence?" now show their abstracts on the 2026 programme grid and their Anthology paper pages. Recovered from the panel's Indico submission, which bundles the individual paper abstracts as an attachment the export API does not reach, and hand-added to src/_data/paperAbstractsManual.json. Part of #794. Progresses #886.

  • EISS 2026 abstract coverage is now complete (69 of 69 papers). The last gap, Kurt Bassuener's "Filling the EU's Identity Void from Without and Within – Forging a Geopolitics of Values" (the fourth paper on the GEO-POWER-EU panel), now shows its abstract on the 2026 programme grid and its Anthology paper page. Recovered from the panel's Indico submission attachment and hand-added to src/_data/paperAbstractsManual.json. Part of #794. Progresses #886.

  • The pre-Indico back catalogue begins: 18 EISS 2019 open-panel abstracts recovered (2019 coverage 0 → 18 of 68). The 2019 conference pre-dated the Indico abstracts module, so its papers had no abstract on the site. Eighteen are recovered from the open-panel proposal documents the organisers circulated (climate-and-security, grand strategy, deterrence, military innovation, the domestic politics of defence, military recruitment, among others), held in the old eissnetwork@gmail.com archive and read out of Drive. Each is added verbatim to src/_data/paperAbstractsManual.json and now shows on the paper's Anthology page. First slice of the pre-Indico recovery in #1040; part of #794.

  • EISS 2018 recovery: 20 of 82 papers (the conference pre-dated Indico). Recovered verbatim from the organisers' panel-proposal documents in the eissnetwork@gmail.com archive, panel by panel: European Grand Strategy (Henke and van Hooft, Simon, Gilli, Minnella); Asia-Pacific "Security and Deterrence" (Jones, Dossi, Odgaard, Dian); "Democratization and Politicization of Military Issues" (Devine, Isernia and Olmastroni, Wagner, Thiébaut, Scotto); "Collective security and strategic (in)stability in the digital domain" (Taillat, Rotundo, Delerue, Kulesza, Creemers); plus Cusumano's "Migrant Rescuing as Organized Hypocrisy" and Barras Tejudo's "Criminal Networks in Africa". Added to src/_data/paperAbstractsManual.json. Continues the pre-Indico recovery in #1040; part of #794.

  • EISS 2021 Lisbon: 5 paper abstracts recovered (the postponed-2020 edition, pre-Indico). From the individual submission documents in the eissnetwork@gmail.com archive: Raphaëlle Khan's "An Indian Perspective on Security and the Use of Force", Nicolas Blarel's "Opening the Black Box of Defence Procurement and Planning Processes", Damien Carrière's "Peacock in a Coal Mine", Ana Sánchez-Cobaleda's "What Do We Talk About When We Talk About Dual-use Goods?", and Dominika Kunertova's "The Proliferation of Military Drones in Europe". Extracted verbatim and added to src/_data/paperAbstractsManual.json. Continues #1040; part of #794. This closes out what the central archive holds for the pre-Indico editions (2017 and most of 2018/2021 were submitted directly to panel chairs, not the central inbox).

  • EISS 2023: Daniel Neumann's "The Role of National Secondments for Intelligence Support to EU Foreign Policymaking" abstract added (2023 coverage to 57 of 59). One of the remaining 2023 panel subcontributions, recovered from the author's submission and added verbatim to src/_data/paperAbstractsManual.json. Progresses #886.

  • Emilie Berthelsen's EISS 2025 paper "Innovation and engineering at the front: the Ukrainian case of Unmanned Systems" gains its published card. It appeared in Defence Studies as "Innovating at the pace of relevance: the case of Ukrainian unmanned systems" (doi.org/10.1080/14702436.2026.2692416) and now shows on the paper's Anthology page. The automatic matcher missed it for two reasons: the journal published it on 23 June 2026, a week after the last match run, and the title was rewritten enough on the way to print (the lead phrase changed entirely) that it would have scored only in the review band, not auto-confirmed. Added by hand to src/_data/paperLinks.json.

  • The Anthology now shows abstract coverage at a glance. The header carries an "abstracts on file" figure beside the paper count, with an information icon whose tooltip explains the ratio. Below it, an "Abstract coverage by year" disclosure opens a per-year progress bar from 2017 to 2026, so a reader can see where the back catalogue is filled in and where the recovery work is still under way. Coverage is measured against the papers eligible for an abstract, so roundtables, keynotes, posters and workshop sessions are left out of the ratio rather than dragging it down. Progresses #886.

  • The 2024 abstract coverage figure no longer counts the joint Sciences Po–EISS conference, lifting it to 49 of 52. That one-day symposium on the origins of war and diplomacy shares its calendar year with the EISS 2024 annual conference but never collected Indico-style abstracts, the same as the other pre-Indico and joint events. Its nine papers were previously counted as "eligible" and dragging the 2024 ratio down to 49 of 60; they're now correctly excluded, the same way roundtables and keynotes already are. Progresses #886.

  • Anthology paper pages now suggest related papers. Each of the ~560 paper landing pages closes with a short "Related in the Anthology" list, computed at build time from the corpus adjacency the Atlas draws: shared authors weigh heaviest, then panel-mates, then shared research themes, with ties broken toward the nearer edition. Entries the within-edition prev/next nav already shows are filtered out, so a paper page now browses onward instead of dead-ending. Closes #1148.

  • Paper pages show their research themes as links. The themes that place a paper on the Atlas and in the by-paper filter were never visible on the paper's own page. They now render as tag chips under the byline, each linking to the by-paper view filtered to that theme. Closes #1149.

  • The Anthology's by-person view now lists who each author wrote with. Every author entry gains a "Co-authored with" line naming their co-authors across the corpus, ordered by shared paper count, each name jumping to that person's own entry. The relation is the same co-authorship the Atlas's Authors lens draws, joined back onto the list view at build time (EN/FR/DE chrome, hand-translated). Closes #1150.

  • The Anthology Atlas is now deep-linkable. The lens, the edition-year and theme filters, and the "Collaborators only" toggle mirror into the page URL as you use them (the same pattern as the by-paper Event filter), and are restored on load. A filtered view of the map — one theme's cluster, one edition's papers, the co-authorship view — can now be shared as a plain link, and Anthology surfaces can link into their own corner of the map. Closes #1151.

  • The Atlas gains an abstract-coverage overlay. A new "Abstract on file" chip on the Papers lens fades every paper without an abstract to the background, so the recovery work's remaining gaps show where they sit on the map — which themes and editions are still dark — complementing the per-year bars on the Anthology, which show when. The chip mirrors into the URL like the other filters. Closes #1152.

  • The Atlas gains a visible list alternative and a documented canvas limitation. A line beneath the map points to the same corpus as filterable lists on the Anthology page (the canvas is opaque to assistive technologies, and a plain list suits plenty of sighted readers too), the canvas aria-label now describes both lenses, and the accessibility statement's known-limitations list documents the canvas with its mitigations in all three locales. Closes #1155.

  • The Atlas now filters by edition, not bare year. The edition chips give the joint events their own entries — "JPW 2019", "Sciences Po 2024", "Ukraine 2024" — instead of lumping them into their calendar year, matching the terminology the by-paper Event filter already uses. Chips keep their year's colour (node colours are unchanged), the full event name rides on the chip tooltip, the URL param becomes editions= (older years= links still work, expanded to the editions inside each year), and the stats strip now counts the true 12 editions. Closes #1153.

  • The Atlas gains a Find control. A search field above the map matches any author name or paper title (native datalist over the corpus, exact match first, then substring), switches to the right lens, pins an accent halo on the found node and lights its neighbourhood the way hover does. The query mirrors into the URL (find=), so "here I am on the map" is a shareable link. Clearing the field clears the spotlight. Closes #1154.

  • The Atlas has its own share card. Sharing /anthology-atlas.html now shows the constellation itself: a capture of the settled map with the EISS iconmark and the corpus figures (511 papers, 494 authors, 17 research themes), replacing the borrowed Anthology card. Closes #1156.

  • Papers now carry the research themes their own abstract is about, not just their panel's. Themes were matched against the panel title alone, so every paper in a panel inherited an identical set: the whole corpus collapsed into 30 distinct theme combinations, and the Atlas had 30 positions in which to place 511 papers. Abstracts, now on file for most papers, are read too, so a paper is tagged for what it argues rather than for the room it was presented in. The corpus moves to 91 distinct combinations, papers touching more than one theme go from 56 to 131 (11% to 26% of the corpus), and 9 previously untagged papers gain a theme, while the average stays at 1.28 themes per paper rather than becoming tag soup. The panel title remains the trusted prior and is always kept; abstract evidence is additive and has to clear a two-mention threshold. Three themes carry a prose-only pattern that drops vocabulary which is ambient in this literature rather than topical ("theoretical" appears in 27% of all abstracts, NATO in 19%), and a new build-sanity assertion fails the build if any theme ever swallows more than a quarter of the corpus. Closes #1186.

  • The Atlas can now draw the links between papers, not just between papers and themes. A "Link related papers" chip on the Papers lens draws the corpus adjacency the landing pages already list as "Related in the Anthology": shared authors, panel-mates and shared research themes, 890 links connecting 508 of the 511 papers. Until now the Papers lens was a star of dots around theme hubs with nothing joining the dots themselves. The scoring moved into one shared module so the map and the paper pages cannot drift apart, and the layer is off by default and deep-linkable as ?links=1. Closes #1188.

  • Papers and authors now link onto the map, and the map answers in place. Every paper page gains a "See this on the Atlas" button, and all 494 author entries on the by-person view gain a link that pins that person's papers on the map (EN/FR/DE). In the other direction, clicking an author's dot on the Atlas no longer navigates away: it switches to the Papers lens and rings their papers, with the author's name shown in the Find field so it is clear why the view changed, and the state carried in the URL as ?author= so it can be shared. Closes #1189. Closes #1190.

  • On phones, the Atlas leads with the map instead of a wall of filters. The twelve edition chips and eighteen theme chips sat above the canvas, pushing it below the fold on a 375px screen. They now sit in a collapsible "Filters" section, closed on first load on small screens only, with the summary line reporting how many editions and themes are active so a narrowed view is never hidden silently. Desktop is unchanged. Closes #1191.

  • Board and community profile pages now carry Schema.org Person structured data. Each /board/<slug>.html page emits a JSON-LD block with the member's name, role, affiliation, photo and identifying links (ORCID, personal site, socials), so search engines can index board profiles the same way the site's papers and events already are. Closes #756.

Changed

  • The Anthology Atlas is listed on the site map. /sitemap.html and its French and German siblings carried a line for the Anthology and none for the map of it, so the one page in this release a reader is most likely to want to find was reachable from the navigation and the Anthology header but not from the inventory that claims to list everything. The French and German entries flag that the Atlas itself is in English.

  • The Atlas card on the Anthology says what the map is for, instead of repeating the stats above it. Its sub-line read "511 papers · 494 authors · 17 research themes, mapped", three numbers the stats row directly above already shows. It now reads "Visualise the data and identify connections between authors and clusters", which is what the Atlas actually offers a reader deciding whether to open it. The French and German lines are hand-translated and both keep the note that the Atlas itself is in English, and both are a line shorter on a phone than the counts they replace.

  • The Anthology's "Cite this corpus" panel now carries all three deposits, not just the DOI. Beside the Zenodo DOI it lists the corpus-description note in HAL (hal-05711925) and the Software Heritage archive of the code that builds the corpus (swh:1:dir:482a1c8…), each on the same row treatment so the three read as one list. The SWHID moved into site.corpus in _data/site.js, where the DOI and the HAL identifier already live, so /licensing and the Anthology now quote one recorded value rather than a literal repeated in four templates.

  • The 2017 and 2018 conferences join the archive list on /past, replacing two screenshots of their programmes. Both editions have had real pages with the full session-by-session programme for some time, and /past neither linked them nor knew they existed: it carried a prose section per edition with a low-resolution PNG of the printed programme, so the archive's two oldest editions were the only ones whose content a reader could not select, search or hear read aloud. They are now entries in src/_data/conferences.js like every other edition, and the archive list runs 2026 back to 2017 in one uniform set of cards, in all three locales. The editionCount used on /initiative carried a hardcoded + 2 to add the founding-era editions back, since they sat outside the array. That offset is removed in the same change, so the public "9 annual conferences since 2017" figure is unchanged rather than jumping to eleven. Part of #1225.

  • The internship page says what it means and stops explaining itself, and the thematic-brief track now links the blog. The copy had a habit of justifying every fact it stated: the entitlements arrived as "what the placement owes you, not favours we extend if there is time", the weekly call "exists so that working alone does not mean working in silence", the output cap was capped "because our reviewing capacity is the real limit rather than your willingness". Each sentence argued for the decision behind it. The facts are unchanged and the arguments are gone, taking the English page from 1,306 words to 1,060 and hand-translated through French and German to match. Several definition-list headings lost the same tic, so "Unpaid, and we say so plainly" is now "Unpaid" and "Someone to ask, rather than someone checking up on you" is "Someone to ask". The thematic-brief tile also names where a brief actually appears, linking /blog.html in all three locales, which had been promised in prose since the blog shipped without ever being a link. A sweep of the other text-heavy pages found the pattern is not there: measured per hundred words, the internship page carried four times the next page, and on /initiative most matches turned out to be inside template comments. So nothing else was rewritten.

  • Volunteers whose track produces no byline can now be credited by name on the internship page. Two of the four tracks, corpus and abstract indexing and the database work, produce no byline at all, so the blog's author field never reaches the people doing the larger and more useful body of work. A "Who has done this" section on /internship.html (+ FR + DE) names them with one line on what each did and an optional link to the work, reading from src/_data/contributors.js, where adding someone is one object and no other edit. The section renders only when that list is non-empty, so it is invisible today rather than an empty heading advertising the opposite of its purpose: the repository's only human contributor so far is the maintainer, and there is nobody yet to seed it with. Names go up with the person's agreement, which the page says and the data file repeats, because a published name carries a permanent address and cannot be quietly withdrawn later. A plain array rather than a sync or a profile system, and a section rather than a page: volunteers are not board members, and the moment to give the list its own page is when it outgrows a section. Closes #1354.

  • The internship page now recruits and onboards, and states the terms it runs on. /internship.html (+ FR + DE) gains four sections and reframes the rest around what a volunteer leaves with rather than what they do. Two of the terms are load-bearing and neither was on the page. The placement runs on two routes: French law treats a placement as a stage only where it sits inside a course carrying at least 200 hours of teaching a year, so outside that there is no convention and bénévolat is the correct frame, which is what most people who write to us are on. The page had mentioned only the convention de stage, reading as though it were the default. And the exposure is subordination, not hours: a bénévole becomes a salarié where the association directs, controls and sanctions the work, and the label the parties use does not protect anyone, because the qualification is d'ordre public. A named point of contact, a weekly call, deadlines and an editorial gate all sit on that axis, so the copy is part of the mitigation: the volunteer chooses the track, sets the pace and may stop without giving a reason, nobody counts hours between the call and the contact, and the gate declines a text rather than sanctioning a person. "No fixed hours and no set end date" is gone with it, since an open-ended unpaid commitment under a named tutor is the worst-looking version of the arrangement on exactly that axis, and the placement is in fact about a day a week over two months. Also new: a "What you get out of it" block stating the byline, the credit, the board conversation and the cohort call as entitlements rather than favours, a year-at-a-glance so the spring logistics peak is expected rather than discovered, and an "Already started? Start here" section, which is the page's second job. The four task tiles keep their copy and gain what each one produces, plus a link to the live "help wanted" list. Zero new CSS: the two new blocks reuse .definition-list and the checklist reuses .prose. Closes #1352.

  • The main menu is now grouped, and stops hiding half the site. The flat bar of five links has become five sections, ordered by why someone arrives: Conference, Anthology, Activities, About, Get involved. Four of them open a dropdown. The change fixes three things at once. The first item used to point at the archive, so anyone arriving for the next conference landed on a list of past ones. It now leads with the editions themselves, generated from conferences.js, so the yearly rollover carries the menu with it and the upcoming edition is tagged as such the moment it goes live. Pages that were reachable only from the footer, or in two cases from almost nowhere, now have a home: the European Security Studies Prize had one inbound link on the whole site, members' publications had one, and volunteering and internships had two. And one thing stops having four names, with the programme family called Activities in the menu, the footer, the site map and the page's own heading, where it was previously Events, Programmes, Activities and Programmes & activities depending on where you looked. Built on native <details> disclosure, so it works with the keyboard, with a screen reader, and with JavaScript switched off, and it becomes an indented accordion inside the mobile drawer. Hand-translated into French and German. Closes #1319.

  • The Anthology and the Atlas now carry their own mark, and their introductions are a great deal shorter. The Atlas signpost used a generic Lucide share-2 glyph, and the Atlas masthead carried no mark at all. Both now use the sub-brand constellation, anthology-mark.svg: one central hub linked out to the discipline's research themes, the corpus as an ego network. The EISS iconmark is already a constellation and the Atlas is a network map of the field, so the sub-brand shows that rather than inventing a second language. One asset serves both surfaces, with the hub on currentColor and the network on --brand-network, so it recolours per surface without forking. The Atlas introduction drops from about 150 words to three sentences, and the Anthology's loses a clause in all three locales. The mechanics the Atlas lede used to carry are all on the page already, in the legend under the map, the first-visit welcome strip and the guided tour. That welcome strip gets the same copy treatment: the bold lead-in on every row goes, since the Lucide glyph beside it already does the scanning work, and "solid dots have an Anthology page, hollow rings don't yet" becomes two positive sentences. Part of #1253.

  • The public roadmap's v2.27.0 card now describes the release as it is actually shaping up. The card kept the "Polish and ESSC 2027 prep" framing from June, while the cycle's real headline became the Anthology Atlas and the recovered abstract back catalogue. The card title and description now say so, in all three locales, and the internal docs/roadmap-2026.md timeline is resynthesised to match (shipped items marked, open items kept).

  • The roadmap gains a v2.28.0 release, targeted at 8 December 2026: "Persistent identifiers and the corpus in French". A new Q4 2026 card on /roadmap.html (EN/FR/DE, hand-translated) and the matching row and section in docs/roadmap-2026.md, covering two strands. Making the corpus outlast the website: a Zenodo concept DOI over the corpus as a dataset (#1221), a HAL collection if the CCSD confirms a loi 1901 association is eligible (#1222), and the source archived in Software Heritage with its SWHIDs shown on /licensing (#1223). And making it usable in French: the French Anthology out of beta on a declared, finite scope (#1224), per-theme annotated bibliographies for teaching (#1226), and an analytical export of affiliations, themes and co-authorship (#1227). The milestone existed before the roadmap row, which is the wrong order under rule §10; this closes the gap.

Fixed

  • The link checker stops treating a rate-limited host as a broken link. scripts/check-links.sh had been growing a permanent SKIP_HOSTS entry every time a board member's personal site answered HTTP 429 to the CI runner, two so far, and each skip was silent and forever: if one of those sites later went dark, nothing would have noticed. A 429 is the server saying "you are asking too often", which is affirmative evidence that it is up, so it now counts as reachable and is reported as rate-limited rather than counted as broken. A transient "network is unreachable" from the runner is retried once, the same treatment 5xx and timeouts already had. Both personal-site skips are removed and those links are checked again like everyone else. scripts/test-check-links.py pins all four behaviours, including that a 404 is still broken. Closes #1367.

  • The Anthology no longer scrolls sideways on a phone. The coverage tooltip on the abstracts stat was hidden with opacity: 0, and an absolutely-positioned box still counts toward its ancestors' scrollable overflow while it is merely transparent. That one invisible element, up to 16rem wide and centred on an icon near the right edge, pushed the document 54px past a 320px viewport, so the page failed WCAG 1.4.10 Reflow at the width the criterion is measured at. It is hidden with display: none now and revealed the same way on hover and keyboard focus. visibility: hidden was measured first and does not help, because a hidden box still occupies space. The fade went with it: a transition cannot run on an element that did not exist in the previous frame. Verified at 320px across sixteen pages, including a control that reinstates the old rule and reproduces the overflow. Part of #1225.

  • Four accessibility defects fixed across the site, found by the August 2026 axe-core audit. The beta and archive ribbons were <div role="note"> rendered before the site header, so their content sat outside every landmark on all 132 French and German pages. Both are now <aside>, which is a landmark and reads as what they are. The Atlas stats strip and the Anthology's coverage tooltip both carried an aria-label on an element with no role, where assistive technology ignores it, on 21 pages between them: the strip is now a labelled group and the tooltip an img, which is what an icon with a text alternative is. The speaker index wrapped its alphabet headings in <li role="presentation">, which stripped the list item and left an <h2> as a direct child of <ol role="list">, an axe critical. Dropping the presentation role restores a valid list without changing what renders. And the redirect pages left by renamed URLs used a three-second <meta http-equiv="refresh">, which fails WCAG 2.2.1 and 2.2.4 outright on 26 pages. The delay is now zero, which is the sufficient technique rather than a time limit. Part of #1225.

  • The build-sanity lint now runs on every pull request, where it used to skip about a quarter of them. It gated on paths: [src/**, ...], so a PR touching only docs/, scripts/ or .claude/ never ran it: 11 of the last 40 merged PRs, mostly the bot's own roadmap refreshes but also hand-written ones. That matters more than it sounds, because check-build-sanity.mjs is the repo's main lint — duplicate data keys, empty and junk href/src, the §15 cross-block class-collision check, sitemap completeness — and tooling outside src/ can break the built output while matching no filter. It matters most for #501, which plans to make checks required on master: a required check that never runs does not pass, it sits pending, so every roadmap-auto PR would have become unmergeable the day that switched on. The whole job takes about a minute, so the filter was not buying anything. The link check keeps a filter, because it reaches third-party servers and running it on a .github-only PR costs someone else's bandwidth for no result, but it widens to docs/** and **.md, which carry links too; that leaves it needing a "skipped but required" shim before it could join the required set. Closes #1343.

  • The EISS letters are back in the header on phones. Below 600px the header swapped the logo for the bare constellation and a separate "EISS" text span, and #1322 then dropped that span below 480px to make room, leaving phones with a logo that had no letters in it. The swap was never worth making: logo-mark.svg and logo-lockup.svg share a viewBox, the lockup only adding the four wordmark paths inside the same box, so at a given height the bare mark is exactly as wide as the full lockup. The phone treatment was costing more width than the thing it replaced, 102px against 62px, and spending it on fewer letters. So there is now one lockup at every width, the same logo on a phone as on a desktop, and the separate mark variant, the text span and both brand breakpoints are deleted. Net 30 lines lighter.

  • Five places where white text sat on the accent colour are legible in dark mode again. --accent is a deep blue in light mode and a light blue in dark, so white on it measures 4.51:1 in one theme and 2.08:1 in the other, well under the 4.5:1 that AA asks for normal text. The site already has the answer to this and has used it in .btn-primary all along: --accent-text, which is white in light and near-black in dark. Five rules had never been migrated to it and still hard-coded white or #fff: the language chip marking which language you are reading, the What's New banner, the footer social icons on hover and focus, and the Atlas help and tour buttons. All five now take the token, which changes nothing in light mode and lifts dark mode from 2.08:1 to 8.99:1. The language chip was the one that mattered most, since it is the control the French and German readers it exists for have to be able to read. Found while fixing #1322, and the other four came from grepping the bug's siblings rather than waiting to be asked. Closes #1326.

  • The brand mark is back in the header on phones, where it had been rendering 0.3 px wide. Below 600 px the header swaps the desktop lockup for the constellation iconmark, and on every phone that iconmark was invisible: the header showed a bare "EISS". The cause was not the artwork. An inline SVG carries an aspect ratio but no intrinsic size, so its min-content width is zero, and as a flex item in a header that had run out of room it was the one thing that could be squeezed to nothing while the text beside it kept its own floor. The header was genuinely over-subscribed: at 375 px it wanted 396 px and had 343 px, and the deficit happened to be almost exactly the width of the mark. So the mark is now unshrinkable, which turns a silent disappearance into a visible overflow, and the row is given the space it needs. Below 480 px the three language chips collapse into one control showing the current language, opening the other two on tap, and the word "EISS" beside the mark gives way to the mark alone. Dropping the language switcher outright was not an option, since #137 tried exactly that and it stranded French and German readers in whichever locale they landed in. The mark now renders at its true width from 320 px up with room to spare. The new control reuses the disclosure pattern from the nav dropdowns, so it closes on Escape, on a click away, and when a nav group opens, and it works with JavaScript off. Closes #1322.

  • Ten share cards that no page pointed at are gone, /programmes is wired to the card that was made for it, and a check now stops the class recurring. docs/new-conference.md has always told the maintainer to delete a year's card at rollover and claimed an orphan check would catch a miss, but no such check existed, which is how 2022-meta.jpg and 2023-meta.jpg survived. The check reads the built og:image tags rather than metaImage in the templates, because several pages compute the filename and a literal grep reports seventeen live Atlas theme cards as orphans. Of the twelve it found, /programmes had a card generated for it but was never wired to it, profdev-meta.jpg belonged to a page that no longer exists, and the remaining eight belonged to redirect pages, which emit noindex and never show a card. /joint-2024 was also pointing at the generic site image while every other archive page uses the shared past-conference card.

  • The CSS collision guard's allowlist drops from nine entries to one. The §15 cross-block lint shipped with eight rules allowlisted rather than fixed, to keep that PR's diff to the lint itself. Every allowlist entry weakens the guard, because an exception for a class also masks a future real collision on that class. The /outputs publications block was dead CSS, none of its selectors appearing in any template, and is deleted. The live programme grid's phone collapse, a photo-gallery print rule and two board-card footer tweaks had drifted into sections that do not own them, and each moves into the section that does. The one remaining entry is .btn.stretched-link:active, a genuine compound state variant rather than a redefinition, which is the shape the list was always meant to hold. No visual change: a before-and-after diff of every rule body confirms exactly seven rules removed, all from the dead block, and none added or altered. Closes #1092.

  • The living style guide was silently missing 13 of the 71 design tokens. /design-system.html renders each token family in the shape that family deserves, colour swatches, a type ramp, spacing bars, and that hand-authoring is what makes it readable. It was also a hole: a token whose family had no bespoke block simply did not appear. The font stacks, all four line-heights, both tracking values, the layout maxima, both blurs and --saturate were absent, while the page claimed to be the render surface for the whole token layer and the release notes claimed it could not drift. An "Other tokens" table now catches everything the blocks above do not render, so adding a token to site.css always makes it appear somewhere, which is the property the page is supposed to have. Verified by adding a token in a family the page had never seen and watching it show up. Found while checking the acceptance criteria on #1271 before closing it, rather than taking the shipped feature at its word.

  • Every paper page is now in sitemap.xml, where only one of the 315 used to be. Eleventy adds only a paginated template's first page to collections.all, which is what the sitemap walks, so 314 paper pages were absent from what the site submits to search engines while the build stayed green and the pages themselves were perfect. Those pages carry the citation metadata, the ScholarlyArticle JSON-LD and the .bib/.ris siblings, so they are the most citable surface the site has. The sitemap goes from 104 to 418 URLs, and each paper URL carries a real <lastmod> derived from the corpus ledger, so the new entries tell a crawler which papers actually changed rather than reading as bulk. Pages with no trustworthy date omit the element, which the protocol allows per URL, because a build-time date would be a lie that changes on every scheduled rebuild. The human-readable /sitemap.html is untouched and stays hand-written: 315 paper URLs are what a crawler wants and the last thing a reader wants. board-profile.njk hits the same default and is deliberately still out, pending a decision on whether 138 historical and per-locale profile variants belong in a sitemap. scripts/check-build-sanity.mjs now asserts the paper-page count on disk matches the sitemap, since this failed silently for months. Closes #1293.

  • The build now fails on Finder/iCloud duplicate files instead of quietly doubling itself. ~/Documents is iCloud-synced and iCloud produces name 2.ext copies of files while they are being edited: 41 appeared during one working session. .gitignore already kept them out of git, but Eleventy does not apply that pattern, and the three classes fail very differently. A duplicated template fails the build outright, which is fine. A duplicated data file or asset is silent: the build succeeds, an extra data global loads, and duplicate images are copied straight into _site. That matters because rule §14 leans on rendering and verifying locally, and a build with doubled inputs cannot prove anything. scripts/check-build-sanity.mjs now fails on any such file under src/ or scripts/ and names the offenders. An .eleventyignore entry was tried first and does not work, so it is not shipped.

  • Filter chips on the Anthology Atlas were unreadable, and their colour said two things at once. Every edition and theme chip was a saturated fill with white text, which failed WCAG AA on 27 of 35 chips in dark mode and 21 of 35 in light, worst case 1.63:1 against a 4.5:1 floor at that size. Worse, the twelve edition colours and the seventeen theme colours were two independent full-spectrum scales stacked above the map, so a green chip could mean either a year or a research theme and neither reading was safe. Chips now follow the rule the design system already states for charts: the series colour rides on a dot and the label wears the surface's own ink token. Nothing fails AA in either theme now, worst case 7.58:1, and the filter stack reads as an interface rather than a colour field. The same treatment lands on the theme pills in the map's hover card. Part of #1225.

  • Form controls fell through to the browser's default focus ring. Anchors, buttons and .btn all carried the brand focus treatment (a 2px accent outline plus a soft --accent-soft halo), but input, select, textarea and summary were never in that selector list, so keyboard focus on every filter field, search box and disclosure on the site showed the default Chrome ring instead. BRAND.md rules that ring out explicitly. All four now take the same treatment. Part of #1225.

  • The Atlas statistics tiles used the frosted-glass colour without the glass. --surface is a translucent fill that only reads correctly alongside the backdrop blur and shadow that make it look like glass; the tiles carried the fill alone, which rendered as a flat murky box and made them the one place on the site using the glass colour without the effect. They now carry backdrop-filter and --shadow-2 like every other card.

  • The Atlas welcome strip used emoji, and its graph chrome used off-brand colours. The five emoji in the first-visit tips are replaced with Lucide glyphs, which is what BRAND.md says carries meaning ("no emoji" is a stated non-negotiable). The co-author edge colour, a stray cyan #0aa2c0 that was the only second hue in the interface, and the grey marking "no Anthology page yet" are now the --atlas-edge and --atlas-inactive tokens, read by both the legend swatches and the canvas renderer so the map and its key cannot drift apart.

  • The DOI badge on README.md was broken, and pointed at the wrong DOI. Its image source was https://shields.io — the shields.io homepage, which serves HTML, not an image — so the badge rendered broken on the repository front page. It also linked the version DOI (…21776210, pinned to v2.26.0 forever) rather than the concept DOI (…21776209, which resolves to the latest version). Both fixed in the one line. Part of #1221.

  • Sanne Verschuren's board-profile website link now resolves. Her site serves no working HTTPS (the TLS handshake fails for browsers as well as the link checker), so the https:// link on the board cards was dead; it now points to http://www.sanneverschuren.com, which returns 200. This was tripping the external-link check on every HTML-touching PR.