diff --git a/content/english/_index.md b/content/english/_index.md
deleted file mode 100644
index 06a4475..0000000
--- a/content/english/_index.md
+++ /dev/null
@@ -1,5 +0,0 @@
-+++
-title = "English"
-description = "Browse English chapters in the curriculum catalog."
-sort_by = "weight"
-+++
diff --git a/content/english/reading-comprehension-foundations/_index.md b/content/english/reading-comprehension-foundations/_index.md
deleted file mode 100644
index 8c70a27..0000000
--- a/content/english/reading-comprehension-foundations/_index.md
+++ /dev/null
@@ -1,60 +0,0 @@
-+++
-title = "Reading comprehension foundations"
-description = "Find the main idea, key details, and evidence in short texts."
-template = "chapter.html"
-weight = 1
-[extra]
-subject = "english"
-chapter_id = "reading-comprehension-foundations"
-strand = "Reading & Writing Foundations"
-+++
-
-
-
- Reading comprehension means understanding what a text says directly and what it suggests
- indirectly. In this chapter you will practice spotting the
- main idea , finding
- supporting details , and selecting
- text evidence .
-
-
-
Main idea and key details
-
- The main idea is the most important message in a paragraph or passage.
- Key details are specific facts or examples that support that message.
-
-
-
-
Quick strategy
-
- Ask: “If I had to summarize this paragraph in one sentence, what would I say?” Then check
- which details in the text prove your sentence.
-
-
-
-
Use evidence, not guesses
-
- Good answers point to exact words or phrases in the passage. You can quote directly or
- paraphrase, but your answer should always connect back to the text.
-
-
-
- Checkpoint: main idea
-
-
- Read this sentence: “After weeks of practice, the choir finally sang in harmony during the
- final rehearsal.” What is the main idea, and which words are the strongest evidence?
-
-
-
-
-
- Checkpoint: evidence
-
-
- A student writes: “The character is brave.” Improve this answer by adding one short quote
- from the text and explaining how that quote proves bravery.
-
-
-
-
diff --git a/content/english/reading-comprehension-foundations/core.html b/content/english/reading-comprehension-foundations/core.html
deleted file mode 100644
index 9f76039..0000000
--- a/content/english/reading-comprehension-foundations/core.html
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
- Reading comprehension means understanding what a text says directly and what it suggests
- indirectly. In this chapter you will practice spotting the
- main idea , finding
- supporting details , and selecting
- text evidence .
-
-
-
Main idea and key details
-
- The main idea is the most important message in a paragraph or passage.
- Key details are specific facts or examples that support that message.
-
-
-
-
Quick strategy
-
- Ask: “If I had to summarize this paragraph in one sentence, what would I say?” Then check
- which details in the text prove your sentence.
-
-
-
-
Use evidence, not guesses
-
- Good answers point to exact words or phrases in the passage. You can quote directly or
- paraphrase, but your answer should always connect back to the text.
-
-
-
- Checkpoint: main idea
-
-
- Read this sentence: “After weeks of practice, the choir finally sang in harmony during the
- final rehearsal.” What is the main idea, and which words are the strongest evidence?
-
-
-
-
-
- Checkpoint: evidence
-
-
- A student writes: “The character is brave.” Improve this answer by adding one short quote
- from the text and explaining how that quote proves bravery.
-
-
-
-
diff --git a/content/english/subject.scss b/content/english/subject.scss
deleted file mode 100644
index a9b8239..0000000
--- a/content/english/subject.scss
+++ /dev/null
@@ -1,10 +0,0 @@
-// Shared styles for English chapters.
-// Keep chapter-specific rules in each chapter folder's chapter.scss.
-
-.english-key-term {
- padding: 0.05rem 0.32rem;
- border-radius: 4px;
- background: color-mix(in srgb, var(--accent) 12%, transparent);
- font-family: var(--mono);
- font-size: 0.85em;
-}
diff --git a/data/catalog.json b/data/catalog.json
index e27515d..5de126b 100644
--- a/data/catalog.json
+++ b/data/catalog.json
@@ -3,9 +3,36 @@
"subtitle": "Browse chapters by subject and curriculum",
"curriculums": ["Foundation", "DSE", "IB", "A-Level", "AP", "IGCSE", "Common Core"],
"subjects": [
- { "id": "math", "name": "Mathematics", "banner": "/catalog/banners/math.webp" },
- { "id": "english", "name": "English" },
- { "id": "physics", "name": "Physics", "banner": "/catalog/banners/physics.jpg" },
+ {
+ "id": "math",
+ "name": "Mathematics",
+ "banner": "/catalog/banners/math.webp",
+ "contributors": [
+ {
+ "id": "man-lung-yeung",
+ "name": "Man Lung Yeung",
+ "avatar": "/contributors/manlung.png",
+ "job_title": "EdTech specialist / software engineer",
+ "education": "BEng in Computer Science (HKUST) + BBA (HKUST)",
+ "contributions": ["Project Creator", "Math textbook", "Physics textbook"]
+ }
+ ]
+ },
+ {
+ "id": "physics",
+ "name": "Physics",
+ "banner": "/catalog/banners/physics.jpg",
+ "contributors": [
+ {
+ "id": "man-lung-yeung",
+ "name": "Man Lung Yeung",
+ "avatar": "/contributors/manlung.png",
+ "job_title": "EdTech specialist / software engineer",
+ "education": "BEng in Computer Science (HKUST) + BBA (HKUST)",
+ "contributions": ["Project Creator", "Math textbook", "Physics textbook"]
+ }
+ ]
+ },
{ "id": "science", "name": "Science" },
{ "id": "humanities", "name": "Humanities" },
{ "id": "computing", "name": "Computing" }
diff --git a/data/catalog.types.ts b/data/catalog.types.ts
index 9bdd38f..5ac227d 100644
--- a/data/catalog.types.ts
+++ b/data/catalog.types.ts
@@ -34,11 +34,21 @@ export type CatalogGraph = {
edges: CatalogGraphEdge[];
};
+export type CatalogSubjectContributor = {
+ id: string;
+ name: string;
+ avatar: string;
+ job_title?: string;
+ education?: string;
+ contributions?: string[];
+};
+
export type CatalogSubject = {
id: string;
name: string;
/** Root-relative URL, e.g. /catalog/banners/math.webp */
banner?: string;
+ contributors?: CatalogSubjectContributor[];
strands: CatalogStrand[];
graph?: CatalogGraph;
};
diff --git a/data/english-curriculum.json b/data/english-curriculum.json
deleted file mode 100644
index 32c50b9..0000000
--- a/data/english-curriculum.json
+++ /dev/null
@@ -1,39 +0,0 @@
-{
- "title": "English",
- "intro": "Build reading, writing, speaking, and analysis skills through progressive chapter pathways.",
- "graph": {
- "edges": []
- },
- "strands": [
- {
- "id": "reading-writing-foundations",
- "title": "Reading & Writing Foundations",
- "chapters": [
- {
- "slug": "reading-comprehension-foundations",
- "title": "Reading comprehension foundations",
- "description": "Find main ideas, supporting details, and text evidence in short passages.",
- "status": "live",
- "curriculumCoverage": {
- "Foundation": "core",
- "IGCSE": "core",
- "Common Core": "core",
- "IB": "related"
- }
- },
- {
- "slug": "paragraph-writing-basics",
- "title": "Paragraph writing basics",
- "description": "Write focused paragraphs with a clear topic sentence, evidence, and explanation.",
- "status": "planned",
- "curriculumCoverage": {
- "Foundation": "core",
- "IGCSE": "core",
- "Common Core": "core",
- "IB": "related"
- }
- }
- ]
- }
- ]
-}
diff --git a/frontend/src/components/catalog-app.tsx b/frontend/src/components/catalog-app.tsx
index c43ee80..e285cf5 100644
--- a/frontend/src/components/catalog-app.tsx
+++ b/frontend/src/components/catalog-app.tsx
@@ -8,6 +8,7 @@ import type {
CatalogChapter,
CatalogData,
CatalogStrand,
+ CatalogSubjectContributor,
CatalogSubject,
CatalogViewMode,
} from "../../../data/catalog.types";
@@ -33,6 +34,7 @@ function normalizeChapter(chapter: CatalogChapter): CatalogChapter {
function normalizeSubject(subject: CatalogSubject): CatalogSubject {
return {
...subject,
+ contributors: subject.contributors ?? [],
strands: (subject.strands ?? []).map((strand) => ({
...strand,
chapters: (strand.chapters ?? []).map(normalizeChapter),
@@ -94,6 +96,20 @@ function syncUrl(subjectId: string, viewMode: CatalogViewMode) {
window.history.replaceState(null, "", url);
}
+function openDialogById(id: string) {
+ const dialog = document.getElementById(id);
+ if (dialog instanceof HTMLDialogElement) {
+ dialog.showModal();
+ }
+}
+
+function closeDialogById(id: string) {
+ const dialog = document.getElementById(id);
+ if (dialog instanceof HTMLDialogElement) {
+ dialog.close();
+ }
+}
+
export function CatalogApp() {
const data = readCatalogData();
if (!data) {
@@ -141,6 +157,37 @@ export function CatalogApp() {
return `Showing ${count} ${filterText} chapter${count === 1 ? "" : "s"}`;
});
+ const subjectContributors = createMemo(
+ () => currentSubject()?.contributors ?? []
+ );
+
+ const contributorsPickerDialogId = createMemo(
+ () => `catalog-contributors-picker-dialog-${currentSubjectId()}`
+ );
+
+ const contributorDialogId = (contributorId: string) =>
+ `catalog-contributor-dialog-${currentSubjectId()}-${contributorId}`;
+
+ const openContributorsPickerDialog = () => {
+ openDialogById(contributorsPickerDialogId());
+ };
+
+ const openContributorDialog = (contributorId: string) => {
+ openDialogById(contributorDialogId(contributorId));
+ };
+
+ const openContributorFromPicker = (contributorId: string) => {
+ closeDialogById(contributorsPickerDialogId());
+ openDialogById(contributorDialogId(contributorId));
+ };
+
+ const closeContributorsDialogOnBackdrop = (event: MouseEvent) => {
+ if (!(event.currentTarget instanceof HTMLDialogElement)) return;
+ if (event.target === event.currentTarget) {
+ event.currentTarget.close();
+ }
+ };
+
const selectSubject = (subjectId: string) => {
if (subjectId !== "math" && viewMode() === "compare") {
setViewMode("linear");
@@ -244,6 +291,151 @@ export function CatalogApp() {
Open Free Books
https://openfreebooks.org/
Recent updates to Open Free Books pages and live chapters.
- Thu, 21 May 2026 16:43:43 GMT
+ Thu, 21 May 2026 16:54:30 GMT
-
-
Loci
- https://openfreebooks.org/math/loci/
- https://openfreebooks.org/math/loci/
- Thu, 21 May 2026 16:43:43 GMT
- Describe and construct loci in the plane, linking geometric constraints to algebraic equations.
+ Advanced trigonometry
+ https://openfreebooks.org/math/advanced-trigonometry/
+ https://openfreebooks.org/math/advanced-trigonometry/
+ Thu, 21 May 2026 16:54:30 GMT
+ Use sine and cosine rules, radians, and trigonometric graphs in 2D and 3D applications.
+
+ -
+
Basic probability
+ https://openfreebooks.org/math/basic-probability/
+ https://openfreebooks.org/math/basic-probability/
+ Thu, 21 May 2026 16:54:30 GMT
+ Calculate theoretical and experimental probabilities for simple events and complements.
+
+ -
+
Properties of circles
+ https://openfreebooks.org/math/circle-properties/
+ https://openfreebooks.org/math/circle-properties/
+ Thu, 21 May 2026 16:54:30 GMT
+ Apply chord, tangent, and angle theorems in circles to prove results and solve geometry problems.
+
+ -
+
Congruence & similarity
+ https://openfreebooks.org/math/congruence-similarity/
+ https://openfreebooks.org/math/congruence-similarity/
+ Thu, 21 May 2026 16:54:30 GMT
+ Apply congruence and similarity criteria to justify properties of triangles and scale figures.
+
+ -
+
Coordinate geometry of circles
+ https://openfreebooks.org/math/coordinate-circles/
+ https://openfreebooks.org/math/coordinate-circles/
+ Thu, 21 May 2026 16:54:30 GMT
+ Find equations of circles, tangents, and intersections using coordinate methods and distance.
+
+ -
+
Coordinate geometry foundations
+ https://openfreebooks.org/math/coordinate-geometry-foundations/
+ https://openfreebooks.org/math/coordinate-geometry-foundations/
+ Thu, 21 May 2026 16:54:30 GMT
+ Plot points, find distances and midpoints, and work with slopes of lines in the Cartesian plane.
+
+ -
+
Deductive geometry
+ https://openfreebooks.org/math/deductive-geometry/
+ https://openfreebooks.org/math/deductive-geometry/
+ Thu, 21 May 2026 16:54:30 GMT
+ Prove angle and side relationships for intersecting lines, triangles, and polygons.
-
Introduction to trigonometry
https://openfreebooks.org/math/introduction-trigonometry/
https://openfreebooks.org/math/introduction-trigonometry/
- Thu, 21 May 2026 16:43:43 GMT
+ Thu, 21 May 2026 16:54:30 GMT
Define sine, cosine, and tangent ratios and solve right-angled triangle problems.
-
-
Permutations, combinations & probability
- https://openfreebooks.org/math/permutations-combinations-probability/
- https://openfreebooks.org/math/permutations-combinations-probability/
- Thu, 21 May 2026 16:43:43 GMT
- Count outcomes with permutations and combinations, then compute probabilities in finite sample spaces.
+ Loci
+ https://openfreebooks.org/math/loci/
+ https://openfreebooks.org/math/loci/
+ Thu, 21 May 2026 16:54:30 GMT
+ Describe and construct loci in the plane, linking geometric constraints to algebraic equations.
+
+ -
+
Measures of dispersion
+ https://openfreebooks.org/math/measures-dispersion/
+ https://openfreebooks.org/math/measures-dispersion/
+ Thu, 21 May 2026 16:54:30 GMT
+ Interpret range, interquartile range, variance, and standard deviation for comparing data sets.
-
Mensuration in 3D
https://openfreebooks.org/math/mensuration-3d/
https://openfreebooks.org/math/mensuration-3d/
- Thu, 21 May 2026 16:43:43 GMT
+ Thu, 21 May 2026 16:54:30 GMT
Find volumes and surface areas of prisms, cylinders, pyramids, cones, and spheres.
-
Normal distribution & z-scores
https://openfreebooks.org/math/normal-distribution-z-scores/
https://openfreebooks.org/math/normal-distribution-z-scores/
- Thu, 21 May 2026 16:43:43 GMT
+ Thu, 21 May 2026 16:54:30 GMT
Model continuous data with the normal curve, standardise with z-scores, and read probabilities from tables.
-
-
Coordinate geometry foundations
- https://openfreebooks.org/math/coordinate-geometry-foundations/
- https://openfreebooks.org/math/coordinate-geometry-foundations/
- Thu, 21 May 2026 16:43:43 GMT
- Plot points, find distances and midpoints, and work with slopes of lines in the Cartesian plane.
+ Permutations, combinations & probability
+ https://openfreebooks.org/math/permutations-combinations-probability/
+ https://openfreebooks.org/math/permutations-combinations-probability/
+ Thu, 21 May 2026 16:54:30 GMT
+ Count outcomes with permutations and combinations, then compute probabilities in finite sample spaces.
-
-
Measures of dispersion
- https://openfreebooks.org/math/measures-dispersion/
- https://openfreebooks.org/math/measures-dispersion/
- Thu, 21 May 2026 16:43:43 GMT
- Interpret range, interquartile range, variance, and standard deviation for comparing data sets.
-
- -
-
Advanced trigonometry
- https://openfreebooks.org/math/advanced-trigonometry/
- https://openfreebooks.org/math/advanced-trigonometry/
- Thu, 21 May 2026 16:43:43 GMT
- Use sine and cosine rules, radians, and trigonometric graphs in 2D and 3D applications.
-
- -
-
Properties of circles
- https://openfreebooks.org/math/circle-properties/
- https://openfreebooks.org/math/circle-properties/
- Thu, 21 May 2026 16:43:43 GMT
- Apply chord, tangent, and angle theorems in circles to prove results and solve geometry problems.
-
- -
-
Deductive geometry
- https://openfreebooks.org/math/deductive-geometry/
- https://openfreebooks.org/math/deductive-geometry/
- Thu, 21 May 2026 16:43:43 GMT
- Prove angle and side relationships for intersecting lines, triangles, and polygons.
-
- -
-
Coordinate geometry of circles
- https://openfreebooks.org/math/coordinate-circles/
- https://openfreebooks.org/math/coordinate-circles/
- Thu, 21 May 2026 16:43:43 GMT
- Find equations of circles, tangents, and intersections using coordinate methods and distance.
-
- -
-
Basic probability
- https://openfreebooks.org/math/basic-probability/
- https://openfreebooks.org/math/basic-probability/
- Thu, 21 May 2026 16:43:43 GMT
- Calculate theoretical and experimental probabilities for simple events and complements.
+ Pythagoras' theorem
+ https://openfreebooks.org/math/pythagoras-theorem/
+ https://openfreebooks.org/math/pythagoras-theorem/
+ Thu, 21 May 2026 16:54:30 GMT
+ Use Pythagoras' theorem and its converse in 2D problems and coordinate settings.
-
Charts & averages
https://openfreebooks.org/math/statistical-charts-averages/
https://openfreebooks.org/math/statistical-charts-averages/
- Thu, 21 May 2026 16:43:43 GMT
+ Thu, 21 May 2026 16:54:30 GMT
Organise data with tables and charts and calculate mean, median, and mode.
-
Statistical literacy
https://openfreebooks.org/math/statistical-literacy/
https://openfreebooks.org/math/statistical-literacy/
- Thu, 21 May 2026 16:43:43 GMT
+ Thu, 21 May 2026 16:54:30 GMT
Evaluate claims in media and research: sampling bias, correlation versus causation, and misleading charts.
- -
-
Congruence & similarity
- https://openfreebooks.org/math/congruence-similarity/
- https://openfreebooks.org/math/congruence-similarity/
- Thu, 21 May 2026 16:43:43 GMT
- Apply congruence and similarity criteria to justify properties of triangles and scale figures.
-
- -
-
Pythagoras' theorem
- https://openfreebooks.org/math/pythagoras-theorem/
- https://openfreebooks.org/math/pythagoras-theorem/
- Thu, 21 May 2026 16:43:43 GMT
- Use Pythagoras' theorem and its converse in 2D problems and coordinate settings.
-
-
Complex numbers
https://openfreebooks.org/math/complex-numbers/
@@ -201,20 +201,6 @@
Thu, 21 May 2026 05:05:38 GMT
Add, subtract, multiply, and divide whole numbers using vertical written form: align columns, regroup, and read the result.
- -
-
English
- https://openfreebooks.org/english/
- https://openfreebooks.org/english/
- Thu, 21 May 2026 02:10:55 GMT
- Browse English chapters in the curriculum catalog.
-
- -
-
Reading comprehension foundations
- https://openfreebooks.org/english/reading-comprehension-foundations/
- https://openfreebooks.org/english/reading-comprehension-foundations/
- Thu, 21 May 2026 02:10:55 GMT
- Find the main idea, key details, and evidence in short texts.
-
-
FAQ
https://openfreebooks.org/faq/
diff --git a/static/sitemap.xml b/static/sitemap.xml
index 4a83df9..da32a9b 100644
--- a/static/sitemap.xml
+++ b/static/sitemap.xml
@@ -20,14 +20,6 @@
https://openfreebooks.org/credits/
2026-05-19T05:33:20.000Z
-
- https://openfreebooks.org/english/
- 2026-05-21T02:10:55.000Z
-
-
- https://openfreebooks.org/english/reading-comprehension-foundations/
- 2026-05-21T02:10:55.000Z
-
https://openfreebooks.org/faq/
2026-05-21T02:10:55.000Z
@@ -38,7 +30,7 @@
https://openfreebooks.org/math/advanced-trigonometry/
- 2026-05-21T16:43:43.537Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/algebraic-fractions-formulas/
@@ -50,11 +42,11 @@
https://openfreebooks.org/math/basic-probability/
- 2026-05-21T16:43:43.535Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/circle-properties/
- 2026-05-21T16:43:43.537Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/complex-numbers/
@@ -62,15 +54,15 @@
https://openfreebooks.org/math/congruence-similarity/
- 2026-05-21T16:43:43.137Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/coordinate-circles/
- 2026-05-21T16:43:43.536Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/coordinate-geometry-foundations/
- 2026-05-21T16:43:43.663Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/counting-and-numbers/
@@ -78,7 +70,7 @@
https://openfreebooks.org/math/deductive-geometry/
- 2026-05-21T16:43:43.537Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/directed-numbers-rates/
@@ -98,7 +90,7 @@
https://openfreebooks.org/math/introduction-trigonometry/
- 2026-05-21T16:43:43.931Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/laws-of-indices/
@@ -118,23 +110,23 @@
https://openfreebooks.org/math/loci/
- 2026-05-21T16:43:43.932Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/measures-dispersion/
- 2026-05-21T16:43:43.662Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/mensuration-3d/
- 2026-05-21T16:43:43.798Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/normal-distribution-z-scores/
- 2026-05-21T16:43:43.798Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/permutations-combinations-probability/
- 2026-05-21T16:43:43.799Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/polynomials-expansion-factorisation/
@@ -146,7 +138,7 @@
https://openfreebooks.org/math/pythagoras-theorem/
- 2026-05-21T16:43:43.137Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/quadratic-equations/
@@ -158,11 +150,11 @@
https://openfreebooks.org/math/statistical-charts-averages/
- 2026-05-21T16:43:43.394Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/statistical-literacy/
- 2026-05-21T16:43:43.394Z
+ 2026-05-21T16:54:30.000Z
https://openfreebooks.org/math/variations/
diff --git a/themes/openfreebooks/sass/_catalog.scss b/themes/openfreebooks/sass/_catalog.scss
index 7e99bf2..5188550 100644
--- a/themes/openfreebooks/sass/_catalog.scss
+++ b/themes/openfreebooks/sass/_catalog.scss
@@ -265,6 +265,120 @@
color: var(--muted);
}
+.catalog-subject-contributors {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.catalog-avatar-group {
+ display: inline-flex;
+ align-items: center;
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+
+.catalog-avatar-group__item {
+ width: 36px;
+ height: 36px;
+ margin-left: -8px;
+ border: 2px solid var(--card-bg);
+ border-radius: 50%;
+ overflow: hidden;
+ background: var(--card-bg);
+ box-shadow: 0 2px 8px var(--shadow-soft);
+
+ &:first-child {
+ margin-left: 0;
+ }
+
+ img {
+ display: block;
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ }
+}
+
+.catalog-avatar-group__button {
+ display: block;
+ width: 100%;
+ height: 100%;
+ border: none;
+ padding: 0;
+ background: transparent;
+ cursor: pointer;
+}
+
+.catalog-subject-contributors__info {
+ display: none;
+ padding: 6px 10px;
+ border: 1px solid var(--line);
+ border-radius: 999px;
+ background: var(--paper);
+ color: var(--ink);
+ font-size: 0.82rem;
+ font-weight: 600;
+ cursor: pointer;
+}
+
+.catalog-contributors-dialog {
+ max-width: min(92vw, 420px);
+}
+
+.catalog-contributors-dialog__title {
+ margin: 0;
+ font-size: clamp(1.1rem, 2vw, 1.35rem);
+ font-family: var(--font-heading);
+ font-weight: 400;
+ line-height: 1.25;
+}
+
+.catalog-contributors-dialog__contributions {
+ margin: 0 0 14px;
+ color: var(--soft-ink);
+ font-size: 0.98rem;
+ line-height: 1.65;
+}
+
+.catalog-contributors-dialog__list {
+ margin: 8px 0 0;
+ padding: 0;
+ list-style: none;
+ display: grid;
+ gap: 10px;
+}
+
+.catalog-contributors-dialog__item {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ width: 100%;
+ border: 1px solid var(--line);
+ border-radius: 10px;
+ padding: 8px 10px;
+ color: var(--ink);
+ background: transparent;
+ text-align: left;
+ cursor: pointer;
+}
+
+.catalog-contributors-dialog__item:hover,
+.catalog-contributors-dialog__item:focus-visible {
+ border-color: var(--accent);
+ background: var(--paper);
+ outline: none;
+}
+
+.catalog-contributors-dialog__avatar {
+ display: block;
+ border-radius: 50%;
+ object-fit: cover;
+ border: 1px solid var(--card-border);
+ background: var(--paper);
+}
+
.catalog-view-toggle {
display: inline-flex;
align-self: flex-end;
@@ -1311,6 +1425,16 @@ a.catalog-chapter-card {
align-items: flex-start;
}
+ .catalog-avatar-group {
+ display: none;
+ }
+
+ .catalog-subject-contributors__info {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ }
+
.catalog-view-toggle {
align-self: stretch;
width: 100%;
diff --git a/themes/openfreebooks/templates/base.html b/themes/openfreebooks/templates/base.html
index 0a5d757..632c983 100644
--- a/themes/openfreebooks/templates/base.html
+++ b/themes/openfreebooks/templates/base.html
@@ -65,6 +65,9 @@
+
diff --git a/themes/openfreebooks/templates/catalog.html b/themes/openfreebooks/templates/catalog.html
index 5885d75..0d4fafb 100644
--- a/themes/openfreebooks/templates/catalog.html
+++ b/themes/openfreebooks/templates/catalog.html
@@ -19,7 +19,8 @@
{
"id": {{ subject.id | json_encode() | safe }},
"name": {{ subject.name | json_encode() | safe }}{% if subject.banner %},
- "banner": {{ subject.banner | json_encode() | safe }}{% endif %},
+ "banner": {{ subject.banner | json_encode() | safe }}{% endif %}{% if subject.contributors %},
+ "contributors": {{ subject.contributors | json_encode() | safe }}{% endif %},
"strands": {{ subject_curriculum.strands | default(value=[]) | json_encode() | safe }}{% if subject_curriculum.graph %},
"graph": {{ subject_curriculum.graph | json_encode() | safe }}{% endif %}
}{% if not loop.last %},{% endif %}