diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 4151fcd3..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,24 +0,0 @@ -version: 2.1 - -jobs: - build: - docker: - - image: cimg/ruby:3.2.2 - steps: - - checkout - - run: - name: Install dependencies - command: bundle install - - run: - name: Jekyll build - command: | - bundle exec jekyll build --baseurl /output/job/$CIRCLE_WORKFLOW_JOB_ID/artifacts/0/_site - - store_artifacts: - path: _site - destination: _site - -workflows: - version: 2 - build: - jobs: - - build diff --git a/.github/workflows/build-site.yml b/.github/workflows/build-site.yml index 71a1b522..05e3a280 100644 --- a/.github/workflows/build-site.yml +++ b/.github/workflows/build-site.yml @@ -1,4 +1,4 @@ -name: Build and Jekyll site and run htmlproofer +name: Build Hugo site and run htmlproofer on: pull_request: @@ -17,20 +17,25 @@ jobs: - name: Check out the code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - name: Fetch main - run: | - git fetch origin main --depth 1 - git branch + - name: Setup Node.js + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: "20" + cache: npm + + - name: Install npm dependencies + run: npm ci - - name: Setup Ruby - uses: ruby/setup-ruby@6aaa311d81eba98ae12eaffbcb63296ace0efcde # v1.307.0 + - name: Setup Hugo + uses: peaceiris/actions-hugo@2752ce1d29631191ea3f27c23495fa06139a5b78 # v3 with: - bundler-cache: true # runs 'bundle install' and caches installed gems automatically + hugo-version: "0.139.4" + extended: true - - name: Build with Jekyll - run: bundle exec jekyll build + - name: Build with Hugo + run: hugo --gc --minify env: - JEKYLL_ENV: production + HUGO_ENV: production - name: Restore lychee cache uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 @@ -43,18 +48,17 @@ jobs: - name: Check links with lychee id: lychee - uses: lycheeverse/lychee-action@8646ba30535128ac92d33dfc9133794bfdd9b411 #v2.8.0 + uses: lycheeverse/lychee-action@8646ba30535128ac92d33dfc9133794bfdd9b411 # v2.8.0 with: fail: true - args: --root-dir _site _site + args: --root-dir public public env: - GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Check HTML using htmlproofer - uses: chabad360/htmlproofer@c2750eb7eb937599ac859517e7dd23a29f1b3ed7 #v2 + uses: chabad360/htmlproofer@c2750eb7eb937599ac859517e7dd23a29f1b3ed7 # v2 with: - directory: "_site" + directory: "public" arguments: | - --ignore-files "/.+\/_posts\/README.md" --ignore-urls "/^https?:\/\/(www\.)?pyopensci\.org\//" --checks "Images,Scripts" diff --git a/.github/workflows/circleci-artifact-redirector.yml b/.github/workflows/circleci-artifact-redirector.yml deleted file mode 100644 index 85186117..00000000 --- a/.github/workflows/circleci-artifact-redirector.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: CircleCI artifacts redirector -on: [status] - -# Restrict the permissions granted to the use of secrets.GITHUB_TOKEN in this -# github actions workflow: -# https://docs.github.com/en/actions/security-guides/automatic-token-authentication -permissions: - statuses: write - -jobs: - circleci_artifacts_redirector_job: - runs-on: ubuntu-latest - # For testing this action on a fork, remove the "github.repository =="" condition. - if: "github.repository == 'pyOpenSci/pyopensci.github.io' && github.event.context == 'ci/circleci: build'" - permissions: - statuses: write - name: Run CircleCI artifacts redirector - steps: - - name: GitHub Action step - id: step1 - uses: larsoner/circleci-artifacts-redirector-action@master - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - api-token: ${{ secrets.CIRCLECI_TOKEN }} - artifact-path: 0/_site/index.html - circleci-jobs: build - job-title: Check the rendered website build here! diff --git a/.gitignore b/.gitignore index 8b5bb863..bf9b000d 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,8 @@ node_modules/* public/ resources/ .lycheecache + +# site redesign +.cursor/* +_law_tests/* +jekyll/* diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8ef7e925..99f636d0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,6 +35,7 @@ repos: hooks: - id: codespell exclude_types: + - css - javascript - scss - yaml diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 00000000..11df6d9d --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,186 @@ +# Hugo site development notes + +Temporary reference for the pyOpenSci Hugo migration. Focus: how CSS is +organized and built. See also `README.md` for install and serve commands. + +## Quick start + +From the repository root: + +```bash +npm ci +hugo server --disableFastRender +``` + +Hugo Extended is required (SCSS + PostCSS). The first run needs `npm ci` so +PostCSS can run during the asset pipeline. + +Do **not** commit build output: `public/`, `resources/`, and `.hugo_build.lock` +are gitignored. + +## Two CSS locations (do not confuse them) + +Hugo treats `assets/` and `static/` differently. + +| Location | Role | Committed? | Built on deploy? | +|----------|------|------------|------------------| +| `themes/clean-hugo/assets/css/` | Main site SCSS source | Yes (source) | Yes → compiled CSS | +| `themes/clean-hugo/static/css/syntax.css` | Code-block highlighting only | Yes (as-is) | No — copied to site | + +There is no `static/scss/` folder. All authored styles live under +`assets/css/` as SCSS partials. + +### `assets/css/` — main styling (SCSS) + +* Entry file: `themes/clean-hugo/assets/css/site.scss` (see **Jekyll coexistence** + below — normally this would be `main.scss`) +* Partials: `_footer.scss`, `_blog.scss`, `_events.scss`, etc. +* Hugo compiles this at **build time** (local `hugo server` or Netlify). +* Output goes to `public/css/site.min..css` — never commit that file. + +### `static/css/syntax.css` — code highlighting only + +* One pre-generated file for Chroma/monokai highlighting in fenced code blocks. +* Served as `/css/syntax.css` with no processing. +* Originally generated with: + `hugo gen chromastyles --style=monokai` +* Not related to layout, footer, blog cards, or brand colors. + +## Build pipeline (what happens on `hugo server` / Netlify) + +Defined in `themes/clean-hugo/layouts/_default/baseof.html`: + +1. **Inline brand colors** — CSS custom properties from `hugo.toml` + `[params.theme.colors]` (injected in a ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/images/desola-lanre-ologun-unsplash.png b/static/images/desola-lanre-ologun-unsplash.png new file mode 100644 index 00000000..3b89b63f Binary files /dev/null and b/static/images/desola-lanre-ologun-unsplash.png differ diff --git a/static/images/events/bof-session-scipy-2025.png b/static/images/events/bof-session-scipy-2025.png new file mode 100644 index 00000000..37c4c5c7 Binary files /dev/null and b/static/images/events/bof-session-scipy-2025.png differ diff --git a/static/images/events/community-call-pavithra-may-2025.png b/static/images/events/community-call-pavithra-may-2025.png new file mode 100644 index 00000000..fe3e6ed7 Binary files /dev/null and b/static/images/events/community-call-pavithra-may-2025.png differ diff --git a/static/images/events/community-call-pavithra-may-2025.webp b/static/images/events/community-call-pavithra-may-2025.webp new file mode 100644 index 00000000..3596c036 Binary files /dev/null and b/static/images/events/community-call-pavithra-may-2025.webp differ diff --git a/static/images/events/fall-festival-2024-stats.png b/static/images/events/fall-festival-2024-stats.png new file mode 100644 index 00000000..ee6f42e2 Binary files /dev/null and b/static/images/events/fall-festival-2024-stats.png differ diff --git a/static/images/events/fall-festival-2024-stats.webp b/static/images/events/fall-festival-2024-stats.webp new file mode 100644 index 00000000..724ad3a1 Binary files /dev/null and b/static/images/events/fall-festival-2024-stats.webp differ diff --git a/static/images/events/fall-festival-blog-keynote-speakers.png b/static/images/events/fall-festival-blog-keynote-speakers.png new file mode 100644 index 00000000..d8f8caea Binary files /dev/null and b/static/images/events/fall-festival-blog-keynote-speakers.png differ diff --git a/static/images/events/fall-festival-blog-keynote-speakers.webp b/static/images/events/fall-festival-blog-keynote-speakers.webp new file mode 100644 index 00000000..7a82e324 Binary files /dev/null and b/static/images/events/fall-festival-blog-keynote-speakers.webp differ diff --git a/static/images/events/fall-festival-favorite-day.png b/static/images/events/fall-festival-favorite-day.png new file mode 100644 index 00000000..2b373a03 Binary files /dev/null and b/static/images/events/fall-festival-favorite-day.png differ diff --git a/static/images/events/fall-festival-favorite-day.webp b/static/images/events/fall-festival-favorite-day.webp new file mode 100644 index 00000000..a338a223 Binary files /dev/null and b/static/images/events/fall-festival-favorite-day.webp differ diff --git a/static/images/events/fall-festival-thank-you.png b/static/images/events/fall-festival-thank-you.png new file mode 100644 index 00000000..0187f434 Binary files /dev/null and b/static/images/events/fall-festival-thank-you.png differ diff --git a/static/images/events/fall-festival-thank-you.webp b/static/images/events/fall-festival-thank-you.webp new file mode 100644 index 00000000..8f5e5cfc Binary files /dev/null and b/static/images/events/fall-festival-thank-you.webp differ diff --git a/static/images/events/people-table-working-2.svg b/static/images/events/people-table-working-2.svg new file mode 100644 index 00000000..91fa5e80 --- /dev/null +++ b/static/images/events/people-table-working-2.svg @@ -0,0 +1 @@ + diff --git a/static/images/events/people-table-working.svg b/static/images/events/people-table-working.svg new file mode 100644 index 00000000..04e28085 --- /dev/null +++ b/static/images/events/people-table-working.svg @@ -0,0 +1 @@ + diff --git a/static/images/events/pyconus-maintainers-summit-2025.png b/static/images/events/pyconus-maintainers-summit-2025.png new file mode 100644 index 00000000..d1556065 Binary files /dev/null and b/static/images/events/pyconus-maintainers-summit-2025.png differ diff --git a/static/images/events/pyconus-maintainers-summit-2025.webp b/static/images/events/pyconus-maintainers-summit-2025.webp new file mode 100644 index 00000000..056ca80f Binary files /dev/null and b/static/images/events/pyconus-maintainers-summit-2025.webp differ diff --git a/static/images/events/scipy-2025/bof-discussions-pyopensci.png b/static/images/events/scipy-2025/bof-discussions-pyopensci.png new file mode 100644 index 00000000..ffe65096 Binary files /dev/null and b/static/images/events/scipy-2025/bof-discussions-pyopensci.png differ diff --git a/static/images/events/scipy-2025/bof-discussions-pyopensci.webp b/static/images/events/scipy-2025/bof-discussions-pyopensci.webp new file mode 100644 index 00000000..ac4f5564 Binary files /dev/null and b/static/images/events/scipy-2025/bof-discussions-pyopensci.webp differ diff --git a/static/images/events/scipy-2025/lightning-talk-song.png b/static/images/events/scipy-2025/lightning-talk-song.png new file mode 100644 index 00000000..41a9beed Binary files /dev/null and b/static/images/events/scipy-2025/lightning-talk-song.png differ diff --git a/static/images/events/scipy-2025/lightning-talk-song.webp b/static/images/events/scipy-2025/lightning-talk-song.webp new file mode 100644 index 00000000..cdb91511 Binary files /dev/null and b/static/images/events/scipy-2025/lightning-talk-song.webp differ diff --git a/static/images/events/scipy-2025/pixi-workshop.png b/static/images/events/scipy-2025/pixi-workshop.png new file mode 100644 index 00000000..032031ae Binary files /dev/null and b/static/images/events/scipy-2025/pixi-workshop.png differ diff --git a/static/images/events/scipy-2025/pixi-workshop.webp b/static/images/events/scipy-2025/pixi-workshop.webp new file mode 100644 index 00000000..599d8129 Binary files /dev/null and b/static/images/events/scipy-2025/pixi-workshop.webp differ diff --git a/static/images/events/scipy-2025/pyopensci-python-packaging-workshop.png b/static/images/events/scipy-2025/pyopensci-python-packaging-workshop.png new file mode 100644 index 00000000..33fd00a3 Binary files /dev/null and b/static/images/events/scipy-2025/pyopensci-python-packaging-workshop.png differ diff --git a/static/images/events/scipy-2025/pyopensci-python-packaging-workshop.webp b/static/images/events/scipy-2025/pyopensci-python-packaging-workshop.webp new file mode 100644 index 00000000..206fb982 Binary files /dev/null and b/static/images/events/scipy-2025/pyopensci-python-packaging-workshop.webp differ diff --git a/static/images/events/sprint-mentor-luiz-meer.png b/static/images/events/sprint-mentor-luiz-meer.png new file mode 100644 index 00000000..7b67b3d3 Binary files /dev/null and b/static/images/events/sprint-mentor-luiz-meer.png differ diff --git a/static/images/events/sprint-mentor-luiz-meer.webp b/static/images/events/sprint-mentor-luiz-meer.webp new file mode 100644 index 00000000..1642f291 Binary files /dev/null and b/static/images/events/sprint-mentor-luiz-meer.webp differ diff --git a/static/images/events/sprint-people-working.png b/static/images/events/sprint-people-working.png new file mode 100644 index 00000000..1ea99174 Binary files /dev/null and b/static/images/events/sprint-people-working.png differ diff --git a/static/images/events/sprint-people-working.webp b/static/images/events/sprint-people-working.webp new file mode 100644 index 00000000..be7dc931 Binary files /dev/null and b/static/images/events/sprint-people-working.webp differ diff --git a/static/images/events/sprint-scipy-2024.png b/static/images/events/sprint-scipy-2024.png new file mode 100644 index 00000000..787f099a Binary files /dev/null and b/static/images/events/sprint-scipy-2024.png differ diff --git a/static/images/events/sprint-scipy-2024.webp b/static/images/events/sprint-scipy-2024.webp new file mode 100644 index 00000000..a936adfd Binary files /dev/null and b/static/images/events/sprint-scipy-2024.webp differ diff --git a/static/images/events/sprint-scipy-2025.png b/static/images/events/sprint-scipy-2025.png new file mode 100644 index 00000000..8ca4409c Binary files /dev/null and b/static/images/events/sprint-scipy-2025.png differ diff --git a/static/images/favicon.ico b/static/images/favicon.ico new file mode 100644 index 00000000..0e7e7d5e Binary files /dev/null and b/static/images/favicon.ico differ diff --git a/static/images/foss-free-open-source-software/orphan-python-open-source-packages.png b/static/images/foss-free-open-source-software/orphan-python-open-source-packages.png new file mode 100644 index 00000000..91951485 Binary files /dev/null and b/static/images/foss-free-open-source-software/orphan-python-open-source-packages.png differ diff --git a/static/images/foss-free-open-source-software/why-scientists-should-care-open-source.png b/static/images/foss-free-open-source-software/why-scientists-should-care-open-source.png new file mode 100644 index 00000000..11d7f13e Binary files /dev/null and b/static/images/foss-free-open-source-software/why-scientists-should-care-open-source.png differ diff --git a/static/images/foss-free-open-source-software/xkcd-open-source-dependency.png b/static/images/foss-free-open-source-software/xkcd-open-source-dependency.png new file mode 100644 index 00000000..954f7ce2 Binary files /dev/null and b/static/images/foss-free-open-source-software/xkcd-open-source-dependency.png differ diff --git a/static/images/full-images/brooke-cagle-unsplash.jpg b/static/images/full-images/brooke-cagle-unsplash.jpg new file mode 100644 index 00000000..4b8bcad0 Binary files /dev/null and b/static/images/full-images/brooke-cagle-unsplash.jpg differ diff --git a/static/images/github/codespaces/create-github-codespace-main.png b/static/images/github/codespaces/create-github-codespace-main.png new file mode 100644 index 00000000..d10a2290 Binary files /dev/null and b/static/images/github/codespaces/create-github-codespace-main.png differ diff --git a/static/images/github/codespaces/create-github-codespace-main.webp b/static/images/github/codespaces/create-github-codespace-main.webp new file mode 100644 index 00000000..28c62bae Binary files /dev/null and b/static/images/github/codespaces/create-github-codespace-main.webp differ diff --git a/static/images/github/codespaces/reopen-codespace.gif b/static/images/github/codespaces/reopen-codespace.gif new file mode 100644 index 00000000..ba0987cc Binary files /dev/null and b/static/images/github/codespaces/reopen-codespace.gif differ diff --git a/static/images/github/codespaces/reopen-codespace.webp b/static/images/github/codespaces/reopen-codespace.webp new file mode 100644 index 00000000..c25e2af1 Binary files /dev/null and b/static/images/github/codespaces/reopen-codespace.webp differ diff --git a/static/images/github/codespaces/resume-github-codespace.png b/static/images/github/codespaces/resume-github-codespace.png new file mode 100644 index 00000000..481f7e21 Binary files /dev/null and b/static/images/github/codespaces/resume-github-codespace.png differ diff --git a/static/images/github/codespaces/resume-github-codespace.webp b/static/images/github/codespaces/resume-github-codespace.webp new file mode 100644 index 00000000..11cb2a85 Binary files /dev/null and b/static/images/github/codespaces/resume-github-codespace.webp differ diff --git a/static/images/github/codespaces/scipy-fork-repo.gif b/static/images/github/codespaces/scipy-fork-repo.gif new file mode 100644 index 00000000..28af2680 Binary files /dev/null and b/static/images/github/codespaces/scipy-fork-repo.gif differ diff --git a/static/images/github/codespaces/scipy-fork-repo.webp b/static/images/github/codespaces/scipy-fork-repo.webp new file mode 100644 index 00000000..0a52b4d0 Binary files /dev/null and b/static/images/github/codespaces/scipy-fork-repo.webp differ diff --git a/static/images/github/codespaces/scipy-open-codespace.gif b/static/images/github/codespaces/scipy-open-codespace.gif new file mode 100644 index 00000000..d3aba971 Binary files /dev/null and b/static/images/github/codespaces/scipy-open-codespace.gif differ diff --git a/static/images/github/codespaces/scipy-open-codespace.webp b/static/images/github/codespaces/scipy-open-codespace.webp new file mode 100644 index 00000000..9df3fd87 Binary files /dev/null and b/static/images/github/codespaces/scipy-open-codespace.webp differ diff --git a/static/images/github/pyopensci-github-help-board.png b/static/images/github/pyopensci-github-help-board.png new file mode 100644 index 00000000..f964f74c Binary files /dev/null and b/static/images/github/pyopensci-github-help-board.png differ diff --git a/static/images/header.png b/static/images/header.png new file mode 100644 index 00000000..d5658267 Binary files /dev/null and b/static/images/header.png differ diff --git a/static/images/headers/pyopensci-floral.png b/static/images/headers/pyopensci-floral.png new file mode 100644 index 00000000..09029ee9 Binary files /dev/null and b/static/images/headers/pyopensci-floral.png differ diff --git a/static/images/headers/pyopensci-floral.webp b/static/images/headers/pyopensci-floral.webp new file mode 100644 index 00000000..8ef9f648 Binary files /dev/null and b/static/images/headers/pyopensci-floral.webp differ diff --git a/static/images/headers/pyopensci-learn-header.png b/static/images/headers/pyopensci-learn-header.png new file mode 100644 index 00000000..9c6c9a71 Binary files /dev/null and b/static/images/headers/pyopensci-learn-header.png differ diff --git a/static/images/headers/pyopensci-learn-header.webp b/static/images/headers/pyopensci-learn-header.webp new file mode 100644 index 00000000..f215fc88 Binary files /dev/null and b/static/images/headers/pyopensci-learn-header.webp differ diff --git a/static/images/headers/pyopensci-quadratik.png b/static/images/headers/pyopensci-quadratik.png new file mode 100644 index 00000000..a10ddedb Binary files /dev/null and b/static/images/headers/pyopensci-quadratik.png differ diff --git a/static/images/headers/pyopensci-quadratik.webp b/static/images/headers/pyopensci-quadratik.webp new file mode 100644 index 00000000..9c8b94b4 Binary files /dev/null and b/static/images/headers/pyopensci-quadratik.webp differ diff --git a/static/images/headers/pyopensci-scipy-2025.png b/static/images/headers/pyopensci-scipy-2025.png new file mode 100644 index 00000000..51637fc2 Binary files /dev/null and b/static/images/headers/pyopensci-scipy-2025.png differ diff --git a/static/images/headers/pyopensci-scipy-2025.webp b/static/images/headers/pyopensci-scipy-2025.webp new file mode 100644 index 00000000..ce6d4545 Binary files /dev/null and b/static/images/headers/pyopensci-scipy-2025.webp differ diff --git a/static/images/headers/pyopensci-software.png b/static/images/headers/pyopensci-software.png new file mode 100644 index 00000000..5cdc4af6 Binary files /dev/null and b/static/images/headers/pyopensci-software.png differ diff --git a/static/images/headers/pyopensci-software.webp b/static/images/headers/pyopensci-software.webp new file mode 100644 index 00000000..a721c016 Binary files /dev/null and b/static/images/headers/pyopensci-software.webp differ diff --git a/static/images/headers/pyopensci-sprints-2025.png b/static/images/headers/pyopensci-sprints-2025.png new file mode 100644 index 00000000..e6ac50c7 Binary files /dev/null and b/static/images/headers/pyopensci-sprints-2025.png differ diff --git a/static/images/headers/pyopensci-sprints-2025.webp b/static/images/headers/pyopensci-sprints-2025.webp new file mode 100644 index 00000000..dd1640b7 Binary files /dev/null and b/static/images/headers/pyopensci-sprints-2025.webp differ diff --git a/static/images/headers/pyopensci-sprints.png b/static/images/headers/pyopensci-sprints.png new file mode 100644 index 00000000..b3b1c251 Binary files /dev/null and b/static/images/headers/pyopensci-sprints.png differ diff --git a/static/images/headers/pyopensci-sprints.webp b/static/images/headers/pyopensci-sprints.webp new file mode 100644 index 00000000..50534f7b Binary files /dev/null and b/static/images/headers/pyopensci-sprints.webp differ diff --git a/static/images/headers/pyopensci-sustainability.png b/static/images/headers/pyopensci-sustainability.png new file mode 100644 index 00000000..9ca5736f Binary files /dev/null and b/static/images/headers/pyopensci-sustainability.png differ diff --git a/static/images/headers/pyopensci-sustainability.webp b/static/images/headers/pyopensci-sustainability.webp new file mode 100644 index 00000000..ecdd0308 Binary files /dev/null and b/static/images/headers/pyopensci-sustainability.webp differ diff --git a/static/images/headers/pyos-peer-review-header.png b/static/images/headers/pyos-peer-review-header.png new file mode 100644 index 00000000..2015c3a2 Binary files /dev/null and b/static/images/headers/pyos-peer-review-header.png differ diff --git a/static/images/headers/pyos-peer-review-header.webp b/static/images/headers/pyos-peer-review-header.webp new file mode 100644 index 00000000..f55d8769 Binary files /dev/null and b/static/images/headers/pyos-peer-review-header.webp differ diff --git a/static/images/headers/python-packaging-header.png b/static/images/headers/python-packaging-header.png new file mode 100644 index 00000000..a8b614dd Binary files /dev/null and b/static/images/headers/python-packaging-header.png differ diff --git a/static/images/headers/python-packaging-header.webp b/static/images/headers/python-packaging-header.webp new file mode 100644 index 00000000..eaf8cea8 Binary files /dev/null and b/static/images/headers/python-packaging-header.webp differ diff --git a/static/images/headers/scipy-2024-workshop.png b/static/images/headers/scipy-2024-workshop.png new file mode 100644 index 00000000..a0215e3c Binary files /dev/null and b/static/images/headers/scipy-2024-workshop.png differ diff --git a/static/images/headers/scipy-2024-workshop.webp b/static/images/headers/scipy-2024-workshop.webp new file mode 100644 index 00000000..27ebea34 Binary files /dev/null and b/static/images/headers/scipy-2024-workshop.webp differ diff --git a/static/images/headers/white-header.png b/static/images/headers/white-header.png new file mode 100644 index 00000000..9bc626ae Binary files /dev/null and b/static/images/headers/white-header.png differ diff --git a/static/images/headers/white-header.webp b/static/images/headers/white-header.webp new file mode 100644 index 00000000..350a1f50 Binary files /dev/null and b/static/images/headers/white-header.webp differ diff --git a/static/images/hero-images/james-sprint-2026-scipy.png b/static/images/hero-images/james-sprint-2026-scipy.png new file mode 100644 index 00000000..4f1b71cc Binary files /dev/null and b/static/images/hero-images/james-sprint-2026-scipy.png differ diff --git a/static/images/hero-images/james-sprint-rotation-2.png b/static/images/hero-images/james-sprint-rotation-2.png new file mode 100644 index 00000000..744be512 Binary files /dev/null and b/static/images/hero-images/james-sprint-rotation-2.png differ diff --git a/static/images/hero-images/scipy-sprint-working.png b/static/images/hero-images/scipy-sprint-working.png new file mode 100644 index 00000000..8ec99877 Binary files /dev/null and b/static/images/hero-images/scipy-sprint-working.png differ diff --git a/static/images/hero-images/scipy-sprint-working.webp b/static/images/hero-images/scipy-sprint-working.webp new file mode 100644 index 00000000..06fb46be Binary files /dev/null and b/static/images/hero-images/scipy-sprint-working.webp differ diff --git a/static/images/hero-images/sprint-mentor-luiz-meer.png b/static/images/hero-images/sprint-mentor-luiz-meer.png new file mode 100644 index 00000000..7b67b3d3 Binary files /dev/null and b/static/images/hero-images/sprint-mentor-luiz-meer.png differ diff --git a/static/images/hero-images/sprint-mentor-luiz-meer.webp b/static/images/hero-images/sprint-mentor-luiz-meer.webp new file mode 100644 index 00000000..1642f291 Binary files /dev/null and b/static/images/hero-images/sprint-mentor-luiz-meer.webp differ diff --git a/static/images/hero-images/sprint-people-working.png b/static/images/hero-images/sprint-people-working.png new file mode 100644 index 00000000..1ea99174 Binary files /dev/null and b/static/images/hero-images/sprint-people-working.png differ diff --git a/static/images/hero-images/sprint-people-working.webp b/static/images/hero-images/sprint-people-working.webp new file mode 100644 index 00000000..be7dc931 Binary files /dev/null and b/static/images/hero-images/sprint-people-working.webp differ diff --git a/static/images/hero-images/sprint-scipy-2024.png b/static/images/hero-images/sprint-scipy-2024.png new file mode 100644 index 00000000..787f099a Binary files /dev/null and b/static/images/hero-images/sprint-scipy-2024.png differ diff --git a/static/images/jinx-and-luna.png b/static/images/jinx-and-luna.png new file mode 100644 index 00000000..dfb06188 Binary files /dev/null and b/static/images/jinx-and-luna.png differ diff --git a/static/images/landing-pages/community-partnerships.png b/static/images/landing-pages/community-partnerships.png new file mode 100644 index 00000000..a4e66cb8 Binary files /dev/null and b/static/images/landing-pages/community-partnerships.png differ diff --git a/static/images/landing-pages/community-partnerships.webp b/static/images/landing-pages/community-partnerships.webp new file mode 100644 index 00000000..541f4c9b Binary files /dev/null and b/static/images/landing-pages/community-partnerships.webp differ diff --git a/static/images/landing-pages/peer-review-people.png b/static/images/landing-pages/peer-review-people.png new file mode 100644 index 00000000..0aadfe63 Binary files /dev/null and b/static/images/landing-pages/peer-review-people.png differ diff --git a/static/images/landing-pages/peer-review-people.webp b/static/images/landing-pages/peer-review-people.webp new file mode 100644 index 00000000..f641b29b Binary files /dev/null and b/static/images/landing-pages/peer-review-people.webp differ diff --git a/static/images/landing-pages/peer-review-supports-maintainers.png b/static/images/landing-pages/peer-review-supports-maintainers.png new file mode 100644 index 00000000..8be47478 Binary files /dev/null and b/static/images/landing-pages/peer-review-supports-maintainers.png differ diff --git a/static/images/landing-pages/peer-review-supports-maintainers.webp b/static/images/landing-pages/peer-review-supports-maintainers.webp new file mode 100644 index 00000000..e34b6366 Binary files /dev/null and b/static/images/landing-pages/peer-review-supports-maintainers.webp differ diff --git a/static/images/landing-pages/peer-review-trusted-software.png b/static/images/landing-pages/peer-review-trusted-software.png new file mode 100644 index 00000000..e922f0ac Binary files /dev/null and b/static/images/landing-pages/peer-review-trusted-software.png differ diff --git a/static/images/landing-pages/peer-review-trusted-software.webp b/static/images/landing-pages/peer-review-trusted-software.webp new file mode 100644 index 00000000..398a805c Binary files /dev/null and b/static/images/landing-pages/peer-review-trusted-software.webp differ diff --git a/static/images/landing-pages/people-working-together.png b/static/images/landing-pages/people-working-together.png new file mode 100644 index 00000000..8f485728 Binary files /dev/null and b/static/images/landing-pages/people-working-together.png differ diff --git a/static/images/landing-pages/people-working-together.webp b/static/images/landing-pages/people-working-together.webp new file mode 100644 index 00000000..8cbd4a91 Binary files /dev/null and b/static/images/landing-pages/people-working-together.webp differ diff --git a/static/images/landing-pages/pyopensci-joss-partners.png b/static/images/landing-pages/pyopensci-joss-partners.png new file mode 100644 index 00000000..6a0103ba Binary files /dev/null and b/static/images/landing-pages/pyopensci-joss-partners.png differ diff --git a/static/images/landing-pages/pyopensci-joss-partners.webp b/static/images/landing-pages/pyopensci-joss-partners.webp new file mode 100644 index 00000000..3cfafaee Binary files /dev/null and b/static/images/landing-pages/pyopensci-joss-partners.webp differ diff --git a/static/images/landing-pages/pyopensci-joss-partnership.png b/static/images/landing-pages/pyopensci-joss-partnership.png new file mode 100644 index 00000000..3095e284 Binary files /dev/null and b/static/images/landing-pages/pyopensci-joss-partnership.png differ diff --git a/static/images/landing-pages/pyopensci-joss-partnership.webp b/static/images/landing-pages/pyopensci-joss-partnership.webp new file mode 100644 index 00000000..1231e889 Binary files /dev/null and b/static/images/landing-pages/pyopensci-joss-partnership.webp differ diff --git a/static/images/landing-pages/pyopensci-supports-maintainers.png b/static/images/landing-pages/pyopensci-supports-maintainers.png new file mode 100644 index 00000000..91b8a5d1 Binary files /dev/null and b/static/images/landing-pages/pyopensci-supports-maintainers.png differ diff --git a/static/images/landing-pages/pyopensci-supports-maintainers.webp b/static/images/landing-pages/pyopensci-supports-maintainers.webp new file mode 100644 index 00000000..e12bc53a Binary files /dev/null and b/static/images/landing-pages/pyopensci-supports-maintainers.webp differ diff --git a/static/images/landing-pages/pyopensci-working-together.png b/static/images/landing-pages/pyopensci-working-together.png new file mode 100644 index 00000000..90be3559 Binary files /dev/null and b/static/images/landing-pages/pyopensci-working-together.png differ diff --git a/static/images/landing-pages/pyopensci-working-together.webp b/static/images/landing-pages/pyopensci-working-together.webp new file mode 100644 index 00000000..e8a4a8cf Binary files /dev/null and b/static/images/landing-pages/pyopensci-working-together.webp differ diff --git a/static/images/landing-pages/scipy-bof-working.png b/static/images/landing-pages/scipy-bof-working.png new file mode 100644 index 00000000..fae1a6ef Binary files /dev/null and b/static/images/landing-pages/scipy-bof-working.png differ diff --git a/static/images/landing-pages/scipy-bof-working.webp b/static/images/landing-pages/scipy-bof-working.webp new file mode 100644 index 00000000..ede7e395 Binary files /dev/null and b/static/images/landing-pages/scipy-bof-working.webp differ diff --git a/static/images/landing-pages/scipy-sprint-2026.png b/static/images/landing-pages/scipy-sprint-2026.png new file mode 100644 index 00000000..f403a587 Binary files /dev/null and b/static/images/landing-pages/scipy-sprint-2026.png differ diff --git a/static/images/landing-pages/scipy-sprint-2026.webp b/static/images/landing-pages/scipy-sprint-2026.webp new file mode 100644 index 00000000..60eb2f9f Binary files /dev/null and b/static/images/landing-pages/scipy-sprint-2026.webp differ diff --git a/static/images/landing-pages/scipy-sprint-working.png b/static/images/landing-pages/scipy-sprint-working.png new file mode 100644 index 00000000..8ec99877 Binary files /dev/null and b/static/images/landing-pages/scipy-sprint-working.png differ diff --git a/static/images/landing-pages/scipy-sprint-working.webp b/static/images/landing-pages/scipy-sprint-working.webp new file mode 100644 index 00000000..06fb46be Binary files /dev/null and b/static/images/landing-pages/scipy-sprint-working.webp differ diff --git a/static/images/landing-pages/simple-python-packaging-header.png b/static/images/landing-pages/simple-python-packaging-header.png new file mode 100644 index 00000000..ad357cea Binary files /dev/null and b/static/images/landing-pages/simple-python-packaging-header.png differ diff --git a/static/images/landing-pages/simple-python-packaging-header.webp b/static/images/landing-pages/simple-python-packaging-header.webp new file mode 100644 index 00000000..0a6502d7 Binary files /dev/null and b/static/images/landing-pages/simple-python-packaging-header.webp differ diff --git a/static/images/landing-pages/software-peer-review.png b/static/images/landing-pages/software-peer-review.png new file mode 100644 index 00000000..5f42a88a Binary files /dev/null and b/static/images/landing-pages/software-peer-review.png differ diff --git a/static/images/landing-pages/software-peer-review.webp b/static/images/landing-pages/software-peer-review.webp new file mode 100644 index 00000000..2bae182f Binary files /dev/null and b/static/images/landing-pages/software-peer-review.webp differ diff --git a/static/images/landing-pages/trusted-python-software.png b/static/images/landing-pages/trusted-python-software.png new file mode 100644 index 00000000..98525077 Binary files /dev/null and b/static/images/landing-pages/trusted-python-software.png differ diff --git a/static/images/landing-pages/trusted-python-software.webp b/static/images/landing-pages/trusted-python-software.webp new file mode 100644 index 00000000..2ea8165e Binary files /dev/null and b/static/images/landing-pages/trusted-python-software.webp differ diff --git a/static/images/landing-pages/trusted-software.png b/static/images/landing-pages/trusted-software.png new file mode 100644 index 00000000..edd74d21 Binary files /dev/null and b/static/images/landing-pages/trusted-software.png differ diff --git a/static/images/landing-pages/trusted-software.webp b/static/images/landing-pages/trusted-software.webp new file mode 100644 index 00000000..b9f9a1ee Binary files /dev/null and b/static/images/landing-pages/trusted-software.webp differ diff --git a/static/images/landing-pages/women-collaborating.png b/static/images/landing-pages/women-collaborating.png new file mode 100644 index 00000000..9ad2c104 Binary files /dev/null and b/static/images/landing-pages/women-collaborating.png differ diff --git a/static/images/landing-pages/women-collaborating.webp b/static/images/landing-pages/women-collaborating.webp new file mode 100644 index 00000000..54d2dca9 Binary files /dev/null and b/static/images/landing-pages/women-collaborating.webp differ diff --git a/static/images/learn-graphics/community-created.png b/static/images/learn-graphics/community-created.png new file mode 100644 index 00000000..f4b031f5 Binary files /dev/null and b/static/images/learn-graphics/community-created.png differ diff --git a/static/images/learn-graphics/community-created.webp b/static/images/learn-graphics/community-created.webp new file mode 100644 index 00000000..e0a2364c Binary files /dev/null and b/static/images/learn-graphics/community-created.webp differ diff --git a/static/images/learn-graphics/github-collaboration.png b/static/images/learn-graphics/github-collaboration.png new file mode 100644 index 00000000..46e9dd86 Binary files /dev/null and b/static/images/learn-graphics/github-collaboration.png differ diff --git a/static/images/learn-graphics/github-collaboration.webp b/static/images/learn-graphics/github-collaboration.webp new file mode 100644 index 00000000..2a95234b Binary files /dev/null and b/static/images/learn-graphics/github-collaboration.webp differ diff --git a/static/images/logo.png b/static/images/logo.png new file mode 100644 index 00000000..ce4c14e8 Binary files /dev/null and b/static/images/logo.png differ diff --git a/static/images/movingpandas/mp_fig1.png b/static/images/movingpandas/mp_fig1.png new file mode 100644 index 00000000..db261fdb Binary files /dev/null and b/static/images/movingpandas/mp_fig1.png differ diff --git a/static/images/movingpandas/mp_fig2.png b/static/images/movingpandas/mp_fig2.png new file mode 100644 index 00000000..9f9d47ce Binary files /dev/null and b/static/images/movingpandas/mp_fig2.png differ diff --git a/static/images/movingpandas/mp_fig3.png b/static/images/movingpandas/mp_fig3.png new file mode 100644 index 00000000..1201ffec Binary files /dev/null and b/static/images/movingpandas/mp_fig3.png differ diff --git a/static/images/movingpandas/mp_fig4.gif b/static/images/movingpandas/mp_fig4.gif new file mode 100644 index 00000000..361c6025 Binary files /dev/null and b/static/images/movingpandas/mp_fig4.gif differ diff --git a/static/images/netlify-badge-dark.svg b/static/images/netlify-badge-dark.svg new file mode 100644 index 00000000..9ce2fb3a --- /dev/null +++ b/static/images/netlify-badge-dark.svg @@ -0,0 +1 @@ + diff --git a/static/images/newsletter/04-2024-newsletter/eomapslogo.png b/static/images/newsletter/04-2024-newsletter/eomapslogo.png new file mode 100644 index 00000000..1878ccf5 Binary files /dev/null and b/static/images/newsletter/04-2024-newsletter/eomapslogo.png differ diff --git a/static/images/newsletter/04-2024-newsletter/ms-pycon-2024.png b/static/images/newsletter/04-2024-newsletter/ms-pycon-2024.png new file mode 100644 index 00000000..3e336934 Binary files /dev/null and b/static/images/newsletter/04-2024-newsletter/ms-pycon-2024.png differ diff --git a/static/images/newsletter/04-2024-newsletter/peer-review-partners-process.png b/static/images/newsletter/04-2024-newsletter/peer-review-partners-process.png new file mode 100644 index 00000000..a7be8981 Binary files /dev/null and b/static/images/newsletter/04-2024-newsletter/peer-review-partners-process.png differ diff --git a/static/images/open-source/pyopensci-contributions-by-quarter.png b/static/images/open-source/pyopensci-contributions-by-quarter.png new file mode 100644 index 00000000..1f86e449 Binary files /dev/null and b/static/images/open-source/pyopensci-contributions-by-quarter.png differ diff --git a/static/images/pandera-logo.svg b/static/images/pandera-logo.svg new file mode 100644 index 00000000..ed266ecd --- /dev/null +++ b/static/images/pandera-logo.svg @@ -0,0 +1 @@ + diff --git a/static/images/peer-review/co-development-open-education.png b/static/images/peer-review/co-development-open-education.png new file mode 100644 index 00000000..aa14fa62 Binary files /dev/null and b/static/images/peer-review/co-development-open-education.png differ diff --git a/static/images/peer-review/co-development-open-education.webp b/static/images/peer-review/co-development-open-education.webp new file mode 100644 index 00000000..23eba2df Binary files /dev/null and b/static/images/peer-review/co-development-open-education.webp differ diff --git a/static/images/peer-review/peer-review-partners-process.png b/static/images/peer-review/peer-review-partners-process.png new file mode 100644 index 00000000..a7be8981 Binary files /dev/null and b/static/images/peer-review/peer-review-partners-process.png differ diff --git a/static/images/peer-review/peer-review-partners-process.webp b/static/images/peer-review/peer-review-partners-process.webp new file mode 100644 index 00000000..d3d12599 Binary files /dev/null and b/static/images/peer-review/peer-review-partners-process.webp differ diff --git a/static/images/peer-review/peer-review-submit-issue.gif b/static/images/peer-review/peer-review-submit-issue.gif new file mode 100644 index 00000000..6d98f8dc Binary files /dev/null and b/static/images/peer-review/peer-review-submit-issue.gif differ diff --git a/static/images/peer-review/pyopensci-python-software-peer-review-growth.png b/static/images/peer-review/pyopensci-python-software-peer-review-growth.png new file mode 100644 index 00000000..790f16c5 Binary files /dev/null and b/static/images/peer-review/pyopensci-python-software-peer-review-growth.png differ diff --git a/static/images/peer-review/pyopensci-python-software-peer-review-growth.webp b/static/images/peer-review/pyopensci-python-software-peer-review-growth.webp new file mode 100644 index 00000000..91e078c1 Binary files /dev/null and b/static/images/peer-review/pyopensci-python-software-peer-review-growth.webp differ diff --git a/static/images/peer-review/pyopensci-software-review-issue-selection.png b/static/images/peer-review/pyopensci-software-review-issue-selection.png new file mode 100644 index 00000000..bf99ea15 Binary files /dev/null and b/static/images/peer-review/pyopensci-software-review-issue-selection.png differ diff --git a/static/images/peer-review/pyopensci-software-review-issue-selection.webp b/static/images/peer-review/pyopensci-software-review-issue-selection.webp new file mode 100644 index 00000000..f13768e2 Binary files /dev/null and b/static/images/peer-review/pyopensci-software-review-issue-selection.webp differ diff --git a/static/images/peer-review/pyos-eic-rotation-2024.png b/static/images/peer-review/pyos-eic-rotation-2024.png new file mode 100644 index 00000000..5e99032f Binary files /dev/null and b/static/images/peer-review/pyos-eic-rotation-2024.png differ diff --git a/static/images/peer-review/pyos-eic-rotation-2024.webp b/static/images/peer-review/pyos-eic-rotation-2024.webp new file mode 100644 index 00000000..ed67f497 Binary files /dev/null and b/static/images/peer-review/pyos-eic-rotation-2024.webp differ diff --git a/static/images/peer-review/pyos-joss-peer-review.png b/static/images/peer-review/pyos-joss-peer-review.png new file mode 100644 index 00000000..b46906b8 Binary files /dev/null and b/static/images/peer-review/pyos-joss-peer-review.png differ diff --git a/static/images/peer-review/pyos-joss-peer-review.webp b/static/images/peer-review/pyos-joss-peer-review.webp new file mode 100644 index 00000000..2de3d83f Binary files /dev/null and b/static/images/peer-review/pyos-joss-peer-review.webp differ diff --git a/static/images/peer-review/pyos-partnerships-peer-review.png b/static/images/peer-review/pyos-partnerships-peer-review.png new file mode 100644 index 00000000..b1868943 Binary files /dev/null and b/static/images/peer-review/pyos-partnerships-peer-review.png differ diff --git a/static/images/peer-review/pyos-partnerships-peer-review.webp b/static/images/peer-review/pyos-partnerships-peer-review.webp new file mode 100644 index 00000000..45f8d4e5 Binary files /dev/null and b/static/images/peer-review/pyos-partnerships-peer-review.webp differ diff --git a/static/images/peer-review/submit-software-ui.png b/static/images/peer-review/submit-software-ui.png new file mode 100644 index 00000000..c9e2c0c7 Binary files /dev/null and b/static/images/peer-review/submit-software-ui.png differ diff --git a/static/images/peer-review/submit-software-ui.webp b/static/images/peer-review/submit-software-ui.webp new file mode 100644 index 00000000..460ce5b7 Binary files /dev/null and b/static/images/peer-review/submit-software-ui.webp differ diff --git a/static/images/people-building-blocks.jpg b/static/images/people-building-blocks.jpg new file mode 100644 index 00000000..8d2161db Binary files /dev/null and b/static/images/people-building-blocks.jpg differ diff --git a/static/images/people/Inessa-NumFocus-award-fall-2024.png b/static/images/people/Inessa-NumFocus-award-fall-2024.png new file mode 100644 index 00000000..16112bf6 Binary files /dev/null and b/static/images/people/Inessa-NumFocus-award-fall-2024.png differ diff --git a/static/images/people/Inessa-NumFocus-award-fall-2024.webp b/static/images/people/Inessa-NumFocus-award-fall-2024.webp new file mode 100644 index 00000000..2ac69441 Binary files /dev/null and b/static/images/people/Inessa-NumFocus-award-fall-2024.webp differ diff --git a/static/images/people/anita-graser.png b/static/images/people/anita-graser.png new file mode 100644 index 00000000..1ad549c4 Binary files /dev/null and b/static/images/people/anita-graser.png differ diff --git a/static/images/people/anita-graser.webp b/static/images/people/anita-graser.webp new file mode 100644 index 00000000..e36c4d26 Binary files /dev/null and b/static/images/people/anita-graser.webp differ diff --git a/static/images/people/bof-scipy-2025.png b/static/images/people/bof-scipy-2025.png new file mode 100644 index 00000000..cb57cdc3 Binary files /dev/null and b/static/images/people/bof-scipy-2025.png differ diff --git a/static/images/people/bof-scipy-2025.webp b/static/images/people/bof-scipy-2025.webp new file mode 100644 index 00000000..b0331e91 Binary files /dev/null and b/static/images/people/bof-scipy-2025.webp differ diff --git a/static/images/people/brianne-wilhelmi.jpeg b/static/images/people/brianne-wilhelmi.jpeg new file mode 100644 index 00000000..5473eac7 Binary files /dev/null and b/static/images/people/brianne-wilhelmi.jpeg differ diff --git a/static/images/people/carlos-ramos.jpg b/static/images/people/carlos-ramos.jpg new file mode 100644 index 00000000..1cec4058 Binary files /dev/null and b/static/images/people/carlos-ramos.jpg differ diff --git a/static/images/people/eliot-w-robson.jpg b/static/images/people/eliot-w-robson.jpg new file mode 100644 index 00000000..717acda3 Binary files /dev/null and b/static/images/people/eliot-w-robson.jpg differ diff --git a/static/images/people/eric-ma-headshot.jpeg b/static/images/people/eric-ma-headshot.jpeg new file mode 100644 index 00000000..248d67a5 Binary files /dev/null and b/static/images/people/eric-ma-headshot.jpeg differ diff --git a/static/images/people/jeremiah-paige.jpg b/static/images/people/jeremiah-paige.jpg new file mode 100644 index 00000000..00a7a80d Binary files /dev/null and b/static/images/people/jeremiah-paige.jpg differ diff --git a/static/images/people/jesse-headshot-bandw.jpg b/static/images/people/jesse-headshot-bandw.jpg new file mode 100644 index 00000000..cf7c8a39 Binary files /dev/null and b/static/images/people/jesse-headshot-bandw.jpg differ diff --git a/static/images/people/leah-wasser-pyopensci-leadership.jpg b/static/images/people/leah-wasser-pyopensci-leadership.jpg new file mode 100644 index 00000000..cc8fbc2b Binary files /dev/null and b/static/images/people/leah-wasser-pyopensci-leadership.jpg differ diff --git a/static/images/people/leah-wasser/headshot.jpg b/static/images/people/leah-wasser/headshot.jpg new file mode 100644 index 00000000..cc8fbc2b Binary files /dev/null and b/static/images/people/leah-wasser/headshot.jpg differ diff --git a/static/images/people/mandy-moore-headshot.png b/static/images/people/mandy-moore-headshot.png new file mode 100644 index 00000000..1e0ffc26 Binary files /dev/null and b/static/images/people/mandy-moore-headshot.png differ diff --git a/static/images/people/mandy-moore-headshot.webp b/static/images/people/mandy-moore-headshot.webp new file mode 100644 index 00000000..733bc8e0 Binary files /dev/null and b/static/images/people/mandy-moore-headshot.webp differ diff --git a/static/images/people/niels-bantilan-pyopensci.jpg b/static/images/people/niels-bantilan-pyopensci.jpg new file mode 100644 index 00000000..7333da1e Binary files /dev/null and b/static/images/people/niels-bantilan-pyopensci.jpg differ diff --git a/static/images/people/patrick-j-roddy.jpg b/static/images/people/patrick-j-roddy.jpg new file mode 100644 index 00000000..36ecd874 Binary files /dev/null and b/static/images/people/patrick-j-roddy.jpg differ diff --git a/static/images/people/pycon-2023-mentored-sprints-pyopensci.png b/static/images/people/pycon-2023-mentored-sprints-pyopensci.png new file mode 100644 index 00000000..d5fc3524 Binary files /dev/null and b/static/images/people/pycon-2023-mentored-sprints-pyopensci.png differ diff --git a/static/images/people/pycon-2023-mentored-sprints-pyopensci.webp b/static/images/people/pycon-2023-mentored-sprints-pyopensci.webp new file mode 100644 index 00000000..c29ce320 Binary files /dev/null and b/static/images/people/pycon-2023-mentored-sprints-pyopensci.webp differ diff --git a/static/images/people/pyopensc-executive-council.png b/static/images/people/pyopensc-executive-council.png new file mode 100644 index 00000000..4d58d120 Binary files /dev/null and b/static/images/people/pyopensc-executive-council.png differ diff --git a/static/images/people/pyopensc-executive-council.webp b/static/images/people/pyopensc-executive-council.webp new file mode 100644 index 00000000..41c57d2f Binary files /dev/null and b/static/images/people/pyopensc-executive-council.webp differ diff --git a/static/images/people/pyopensci-sprint-pycon-2023.png b/static/images/people/pyopensci-sprint-pycon-2023.png new file mode 100644 index 00000000..326f0bbc Binary files /dev/null and b/static/images/people/pyopensci-sprint-pycon-2023.png differ diff --git a/static/images/people/pyopensci-sprint-pycon-2023.webp b/static/images/people/pyopensci-sprint-pycon-2023.webp new file mode 100644 index 00000000..20218a14 Binary files /dev/null and b/static/images/people/pyopensci-sprint-pycon-2023.webp differ diff --git a/static/images/people/python-packaging-guide.png b/static/images/people/python-packaging-guide.png new file mode 100644 index 00000000..da5b7013 Binary files /dev/null and b/static/images/people/python-packaging-guide.png differ diff --git a/static/images/people/python-packaging-guide.webp b/static/images/people/python-packaging-guide.webp new file mode 100644 index 00000000..686b533e Binary files /dev/null and b/static/images/people/python-packaging-guide.webp differ diff --git a/static/images/people/raktim-mukhopadhyay.jpg b/static/images/people/raktim-mukhopadhyay.jpg new file mode 100644 index 00000000..01592c37 Binary files /dev/null and b/static/images/people/raktim-mukhopadhyay.jpg differ diff --git a/static/images/people/scipy-sprint-2026.png b/static/images/people/scipy-sprint-2026.png new file mode 100644 index 00000000..4b1490fe Binary files /dev/null and b/static/images/people/scipy-sprint-2026.png differ diff --git a/static/images/people/scipy-sprint-2026.webp b/static/images/people/scipy-sprint-2026.webp new file mode 100644 index 00000000..cdf66b4d Binary files /dev/null and b/static/images/people/scipy-sprint-2026.webp differ diff --git a/static/images/people/testimonial-fatima-pardo.png b/static/images/people/testimonial-fatima-pardo.png new file mode 100644 index 00000000..565449bb Binary files /dev/null and b/static/images/people/testimonial-fatima-pardo.png differ diff --git a/static/images/pyopensci-general/pyopensci-by-the-numbers-2024.png b/static/images/pyopensci-general/pyopensci-by-the-numbers-2024.png new file mode 100644 index 00000000..cb042ab5 Binary files /dev/null and b/static/images/pyopensci-general/pyopensci-by-the-numbers-2024.png differ diff --git a/static/images/pyopensci-general/pyopensci-by-the-numbers-2024.webp b/static/images/pyopensci-general/pyopensci-by-the-numbers-2024.webp new file mode 100644 index 00000000..0a38bcab Binary files /dev/null and b/static/images/pyopensci-general/pyopensci-by-the-numbers-2024.webp differ diff --git a/static/images/pyopensci-general/pyopensci-flower-pillars.png b/static/images/pyopensci-general/pyopensci-flower-pillars.png new file mode 100644 index 00000000..72999193 Binary files /dev/null and b/static/images/pyopensci-general/pyopensci-flower-pillars.png differ diff --git a/static/images/pyopensci-general/pyopensci-flower-pillars.webp b/static/images/pyopensci-general/pyopensci-flower-pillars.webp new file mode 100644 index 00000000..e0d31b29 Binary files /dev/null and b/static/images/pyopensci-general/pyopensci-flower-pillars.webp differ diff --git a/static/images/pyopensci-general/pyopensci-github-prs-issues.png b/static/images/pyopensci-general/pyopensci-github-prs-issues.png new file mode 100644 index 00000000..ea391b63 Binary files /dev/null and b/static/images/pyopensci-general/pyopensci-github-prs-issues.png differ diff --git a/static/images/pyopensci-general/pyopensci-github-prs-issues.webp b/static/images/pyopensci-general/pyopensci-github-prs-issues.webp new file mode 100644 index 00000000..a50528cb Binary files /dev/null and b/static/images/pyopensci-general/pyopensci-github-prs-issues.webp differ diff --git a/static/images/pyopensci-general/pyopensci-iterative-evaluation-program-design.png b/static/images/pyopensci-general/pyopensci-iterative-evaluation-program-design.png new file mode 100644 index 00000000..bb8bb266 Binary files /dev/null and b/static/images/pyopensci-general/pyopensci-iterative-evaluation-program-design.png differ diff --git a/static/images/pyopensci-general/pyopensci-iterative-evaluation-program-design.webp b/static/images/pyopensci-general/pyopensci-iterative-evaluation-program-design.webp new file mode 100644 index 00000000..7fd721a2 Binary files /dev/null and b/static/images/pyopensci-general/pyopensci-iterative-evaluation-program-design.webp differ diff --git a/static/images/pyopensci-general/pyopensci-timeline2019-2024.png b/static/images/pyopensci-general/pyopensci-timeline2019-2024.png new file mode 100644 index 00000000..9dd953d1 Binary files /dev/null and b/static/images/pyopensci-general/pyopensci-timeline2019-2024.png differ diff --git a/static/images/pyopensci-general/pyopensci-timeline2019-2024.webp b/static/images/pyopensci-general/pyopensci-timeline2019-2024.webp new file mode 100644 index 00000000..cc17bce0 Binary files /dev/null and b/static/images/pyopensci-general/pyopensci-timeline2019-2024.webp differ diff --git a/static/images/pyopensci-general/pyos-by-the-numbers-2024.png b/static/images/pyopensci-general/pyos-by-the-numbers-2024.png new file mode 100644 index 00000000..1e4d199b Binary files /dev/null and b/static/images/pyopensci-general/pyos-by-the-numbers-2024.png differ diff --git a/static/images/pyopensci-open-source-foundation-open-science.png b/static/images/pyopensci-open-source-foundation-open-science.png new file mode 100644 index 00000000..ecf4bee3 Binary files /dev/null and b/static/images/pyopensci-open-source-foundation-open-science.png differ diff --git a/static/images/pyopensci-packages/snyk-pandera-python-package-metrics.png b/static/images/pyopensci-packages/snyk-pandera-python-package-metrics.png new file mode 100644 index 00000000..e286968a Binary files /dev/null and b/static/images/pyopensci-packages/snyk-pandera-python-package-metrics.png differ diff --git a/static/images/pyopensci-packages/snyk-pygmt-python-package-metrics.png b/static/images/pyopensci-packages/snyk-pygmt-python-package-metrics.png new file mode 100644 index 00000000..9f55cdb2 Binary files /dev/null and b/static/images/pyopensci-packages/snyk-pygmt-python-package-metrics.png differ diff --git a/static/images/pyopensci-pillars-flower.png b/static/images/pyopensci-pillars-flower.png new file mode 100644 index 00000000..b96824fe Binary files /dev/null and b/static/images/pyopensci-pillars-flower.png differ diff --git a/static/images/pyopensci-programs.png b/static/images/pyopensci-programs.png new file mode 100644 index 00000000..d251f71d Binary files /dev/null and b/static/images/pyopensci-programs.png differ diff --git a/static/images/pyopensci-square-logo-dark-purple.png b/static/images/pyopensci-square-logo-dark-purple.png new file mode 100644 index 00000000..4d58d120 Binary files /dev/null and b/static/images/pyopensci-square-logo-dark-purple.png differ diff --git a/static/images/pyopensci-stickers.png b/static/images/pyopensci-stickers.png new file mode 100644 index 00000000..6147117b Binary files /dev/null and b/static/images/pyopensci-stickers.png differ diff --git a/static/images/pyos-days-python-environment-failed.png b/static/images/pyos-days-python-environment-failed.png new file mode 100644 index 00000000..e38e6a76 Binary files /dev/null and b/static/images/pyos-days-python-environment-failed.png differ diff --git a/static/images/pyos-partnerships.png b/static/images/pyos-partnerships.png new file mode 100644 index 00000000..1a41672f Binary files /dev/null and b/static/images/pyos-partnerships.png differ diff --git a/static/images/python-package-tools-decision-tree.png b/static/images/python-package-tools-decision-tree.png new file mode 100644 index 00000000..8908e9cf Binary files /dev/null and b/static/images/python-package-tools-decision-tree.png differ diff --git a/static/images/python-packages/dont-talk-about-peps-pyopensci.jpeg b/static/images/python-packages/dont-talk-about-peps-pyopensci.jpeg new file mode 100644 index 00000000..71b6b3b7 Binary files /dev/null and b/static/images/python-packages/dont-talk-about-peps-pyopensci.jpeg differ diff --git a/static/images/python-packages/lion-meme-pyopensci.jpeg b/static/images/python-packages/lion-meme-pyopensci.jpeg new file mode 100644 index 00000000..52ca3657 Binary files /dev/null and b/static/images/python-packages/lion-meme-pyopensci.jpeg differ diff --git a/static/images/python-packages/pyOS-package-guide-contributors.png b/static/images/python-packages/pyOS-package-guide-contributors.png new file mode 100644 index 00000000..3644c078 Binary files /dev/null and b/static/images/python-packages/pyOS-package-guide-contributors.png differ diff --git a/static/images/python-packages/pycon-packaging-review-process.png b/static/images/python-packages/pycon-packaging-review-process.png new file mode 100644 index 00000000..7ca98d46 Binary files /dev/null and b/static/images/python-packages/pycon-packaging-review-process.png differ diff --git a/static/images/python-packages/python-ecosystem-jake-vanderploss-pycon-2017.png b/static/images/python-packages/python-ecosystem-jake-vanderploss-pycon-2017.png new file mode 100644 index 00000000..0a95d40a Binary files /dev/null and b/static/images/python-packages/python-ecosystem-jake-vanderploss-pycon-2017.png differ diff --git a/static/images/python-packaging-guide.png b/static/images/python-packaging-guide.png new file mode 100644 index 00000000..f054af43 Binary files /dev/null and b/static/images/python-packaging-guide.png differ diff --git a/static/images/python-packaging/create-github-environment.gif b/static/images/python-packaging/create-github-environment.gif new file mode 100644 index 00000000..c279ed96 Binary files /dev/null and b/static/images/python-packaging/create-github-environment.gif differ diff --git a/static/images/python-packaging/dont-talk-about-peps-pyopensci.jpeg b/static/images/python-packaging/dont-talk-about-peps-pyopensci.jpeg new file mode 100644 index 00000000..71b6b3b7 Binary files /dev/null and b/static/images/python-packaging/dont-talk-about-peps-pyopensci.jpeg differ diff --git a/static/images/python-packaging/github-action-environment-pypi.png b/static/images/python-packaging/github-action-environment-pypi.png new file mode 100644 index 00000000..822ba25a Binary files /dev/null and b/static/images/python-packaging/github-action-environment-pypi.png differ diff --git a/static/images/python-packaging/github-action-environment-pypi.webp b/static/images/python-packaging/github-action-environment-pypi.webp new file mode 100644 index 00000000..ede3925d Binary files /dev/null and b/static/images/python-packaging/github-action-environment-pypi.webp differ diff --git a/static/images/python-packaging/have-you-created-python-package-scipy-24.png b/static/images/python-packaging/have-you-created-python-package-scipy-24.png new file mode 100644 index 00000000..c98da543 Binary files /dev/null and b/static/images/python-packaging/have-you-created-python-package-scipy-24.png differ diff --git a/static/images/python-packaging/lion-meme-pyopensci.jpeg b/static/images/python-packaging/lion-meme-pyopensci.jpeg new file mode 100644 index 00000000..52ca3657 Binary files /dev/null and b/static/images/python-packaging/lion-meme-pyopensci.jpeg differ diff --git a/static/images/python-packaging/packaging-101-outline.png b/static/images/python-packaging/packaging-101-outline.png new file mode 100644 index 00000000..d3c2053b Binary files /dev/null and b/static/images/python-packaging/packaging-101-outline.png differ diff --git a/static/images/python-packaging/packaging-101-outline.webp b/static/images/python-packaging/packaging-101-outline.webp new file mode 100644 index 00000000..1de6cf31 Binary files /dev/null and b/static/images/python-packaging/packaging-101-outline.webp differ diff --git a/static/images/python-packaging/publish-python-package-pypi-conda.png b/static/images/python-packaging/publish-python-package-pypi-conda.png new file mode 100644 index 00000000..953b5666 Binary files /dev/null and b/static/images/python-packaging/publish-python-package-pypi-conda.png differ diff --git a/static/images/python-packaging/pyOS-package-guide-contributors.png b/static/images/python-packaging/pyOS-package-guide-contributors.png new file mode 100644 index 00000000..3644c078 Binary files /dev/null and b/static/images/python-packaging/pyOS-package-guide-contributors.png differ diff --git a/static/images/python-packaging/pycon-packaging-review-process.png b/static/images/python-packaging/pycon-packaging-review-process.png new file mode 100644 index 00000000..7ca98d46 Binary files /dev/null and b/static/images/python-packaging/pycon-packaging-review-process.png differ diff --git a/static/images/python-packaging/pyopensci-python-package-tools-word-cloud-2024.png b/static/images/python-packaging/pyopensci-python-package-tools-word-cloud-2024.png new file mode 100644 index 00000000..07578656 Binary files /dev/null and b/static/images/python-packaging/pyopensci-python-package-tools-word-cloud-2024.png differ diff --git a/static/images/python-packaging/python-ecosystem-jake-vanderploss-pycon-2017.png b/static/images/python-packaging/python-ecosystem-jake-vanderploss-pycon-2017.png new file mode 100644 index 00000000..0a95d40a Binary files /dev/null and b/static/images/python-packaging/python-ecosystem-jake-vanderploss-pycon-2017.png differ diff --git a/static/images/python-packaging/successfully-created-python-package-scipy-24.png b/static/images/python-packaging/successfully-created-python-package-scipy-24.png new file mode 100644 index 00000000..e51f3188 Binary files /dev/null and b/static/images/python-packaging/successfully-created-python-package-scipy-24.png differ diff --git a/static/images/python-packaging/trusted-publisher-form.png b/static/images/python-packaging/trusted-publisher-form.png new file mode 100644 index 00000000..ffbc33b7 Binary files /dev/null and b/static/images/python-packaging/trusted-publisher-form.png differ diff --git a/static/images/python-packaging/trusted-publisher-form.webp b/static/images/python-packaging/trusted-publisher-form.webp new file mode 100644 index 00000000..de45575c Binary files /dev/null and b/static/images/python-packaging/trusted-publisher-form.webp differ diff --git a/static/images/python-packaging/trusted-publisher-manage.png b/static/images/python-packaging/trusted-publisher-manage.png new file mode 100644 index 00000000..6b8c5d5d Binary files /dev/null and b/static/images/python-packaging/trusted-publisher-manage.png differ diff --git a/static/images/python-packaging/trusted-publisher-manage.webp b/static/images/python-packaging/trusted-publisher-manage.webp new file mode 100644 index 00000000..c228afec Binary files /dev/null and b/static/images/python-packaging/trusted-publisher-manage.webp differ diff --git a/static/images/python-packaging/trusted-publisher-pypi-github.png b/static/images/python-packaging/trusted-publisher-pypi-github.png new file mode 100644 index 00000000..b2c5eb11 Binary files /dev/null and b/static/images/python-packaging/trusted-publisher-pypi-github.png differ diff --git a/static/images/python-packaging/trusted-publisher-pypi-github.webp b/static/images/python-packaging/trusted-publisher-pypi-github.webp new file mode 100644 index 00000000..fab5edc7 Binary files /dev/null and b/static/images/python-packaging/trusted-publisher-pypi-github.webp differ diff --git a/static/images/python-software-health/bus-factor-python-package-health.png b/static/images/python-software-health/bus-factor-python-package-health.png new file mode 100644 index 00000000..ef4647da Binary files /dev/null and b/static/images/python-software-health/bus-factor-python-package-health.png differ diff --git a/static/images/python-software-health/healthy-software-repo-file-checks-github.png b/static/images/python-software-health/healthy-software-repo-file-checks-github.png new file mode 100644 index 00000000..d384716b Binary files /dev/null and b/static/images/python-software-health/healthy-software-repo-file-checks-github.png differ diff --git a/static/images/python-software-health/html-proofer-pyopensci-website-checks.png b/static/images/python-software-health/html-proofer-pyopensci-website-checks.png new file mode 100644 index 00000000..2cd59577 Binary files /dev/null and b/static/images/python-software-health/html-proofer-pyopensci-website-checks.png differ diff --git a/static/images/quadratik/dash-landing.png b/static/images/quadratik/dash-landing.png new file mode 100644 index 00000000..7b004e20 Binary files /dev/null and b/static/images/quadratik/dash-landing.png differ diff --git a/static/images/quadratik/dash-landing.webp b/static/images/quadratik/dash-landing.webp new file mode 100644 index 00000000..8d2035be Binary files /dev/null and b/static/images/quadratik/dash-landing.webp differ diff --git a/static/images/quadratik/dog-cat-segmented.png b/static/images/quadratik/dog-cat-segmented.png new file mode 100644 index 00000000..d8686611 Binary files /dev/null and b/static/images/quadratik/dog-cat-segmented.png differ diff --git a/static/images/quadratik/dog-cat-segmented.webp b/static/images/quadratik/dog-cat-segmented.webp new file mode 100644 index 00000000..a8b70ae9 Binary files /dev/null and b/static/images/quadratik/dog-cat-segmented.webp differ diff --git a/static/images/quadratik/dog-cat.png b/static/images/quadratik/dog-cat.png new file mode 100644 index 00000000..47e8a873 Binary files /dev/null and b/static/images/quadratik/dog-cat.png differ diff --git a/static/images/quadratik/dog-cat.webp b/static/images/quadratik/dog-cat.webp new file mode 100644 index 00000000..9c2dd37f Binary files /dev/null and b/static/images/quadratik/dog-cat.webp differ diff --git a/static/images/quadratik/k-sample-test-results.png b/static/images/quadratik/k-sample-test-results.png new file mode 100644 index 00000000..f993e1ed Binary files /dev/null and b/static/images/quadratik/k-sample-test-results.png differ diff --git a/static/images/quadratik/k-sample-test-results.webp b/static/images/quadratik/k-sample-test-results.webp new file mode 100644 index 00000000..483b32a3 Binary files /dev/null and b/static/images/quadratik/k-sample-test-results.webp differ diff --git a/static/images/quadratik/normality-test-results.png b/static/images/quadratik/normality-test-results.png new file mode 100644 index 00000000..d5501953 Binary files /dev/null and b/static/images/quadratik/normality-test-results.png differ diff --git a/static/images/quadratik/normality-test-results.webp b/static/images/quadratik/normality-test-results.webp new file mode 100644 index 00000000..f8e5f294 Binary files /dev/null and b/static/images/quadratik/normality-test-results.webp differ diff --git a/static/images/quadratik/quadratik-organization.png b/static/images/quadratik/quadratik-organization.png new file mode 100644 index 00000000..8a2bf6cc Binary files /dev/null and b/static/images/quadratik/quadratik-organization.png differ diff --git a/static/images/quadratik/two-sample-test-results.png b/static/images/quadratik/two-sample-test-results.png new file mode 100644 index 00000000..3f988c7e Binary files /dev/null and b/static/images/quadratik/two-sample-test-results.png differ diff --git a/static/images/quadratik/two-sample-test-results.webp b/static/images/quadratik/two-sample-test-results.webp new file mode 100644 index 00000000..75eb731b Binary files /dev/null and b/static/images/quadratik/two-sample-test-results.webp differ diff --git a/static/images/quadratik/uniformity-test-results.png b/static/images/quadratik/uniformity-test-results.png new file mode 100644 index 00000000..3f5fbde1 Binary files /dev/null and b/static/images/quadratik/uniformity-test-results.png differ diff --git a/static/images/quadratik/uniformity-test-results.webp b/static/images/quadratik/uniformity-test-results.webp new file mode 100644 index 00000000..5374c713 Binary files /dev/null and b/static/images/quadratik/uniformity-test-results.webp differ diff --git a/static/images/quadratik/unit-sphere.png b/static/images/quadratik/unit-sphere.png new file mode 100644 index 00000000..3799c9e7 Binary files /dev/null and b/static/images/quadratik/unit-sphere.png differ diff --git a/static/images/quadratik/unit-sphere.webp b/static/images/quadratik/unit-sphere.webp new file mode 100644 index 00000000..9f724ebc Binary files /dev/null and b/static/images/quadratik/unit-sphere.webp differ diff --git a/static/images/quadratik/validation-dog-cat.png b/static/images/quadratik/validation-dog-cat.png new file mode 100644 index 00000000..84ed2bf5 Binary files /dev/null and b/static/images/quadratik/validation-dog-cat.png differ diff --git a/static/images/quadratik/validation-dog-cat.webp b/static/images/quadratik/validation-dog-cat.webp new file mode 100644 index 00000000..32f5f1c8 Binary files /dev/null and b/static/images/quadratik/validation-dog-cat.webp differ diff --git a/static/images/rdata/dataset.png b/static/images/rdata/dataset.png new file mode 100644 index 00000000..61e247be Binary files /dev/null and b/static/images/rdata/dataset.png differ diff --git a/static/images/rse-2023-packaging-tools.png b/static/images/rse-2023-packaging-tools.png new file mode 100644 index 00000000..e3451d3c Binary files /dev/null and b/static/images/rse-2023-packaging-tools.png differ diff --git a/static/images/sleplet/planck_2018_temp_mask.jpg b/static/images/sleplet/planck_2018_temp_mask.jpg new file mode 100644 index 00000000..e17cf746 Binary files /dev/null and b/static/images/sleplet/planck_2018_temp_mask.jpg differ diff --git a/static/images/sleplet/slepian_wavelet_coefficients_homer_3B_2jmin_2j_zoom.png b/static/images/sleplet/slepian_wavelet_coefficients_homer_3B_2jmin_2j_zoom.png new file mode 100644 index 00000000..36fefd95 Binary files /dev/null and b/static/images/sleplet/slepian_wavelet_coefficients_homer_3B_2jmin_2j_zoom.png differ diff --git a/static/images/sleplet/slepian_wavelets_south_america_3B_2jmin_2j_L128_res512_real.png b/static/images/sleplet/slepian_wavelets_south_america_3B_2jmin_2j_L128_res512_real.png new file mode 100644 index 00000000..e5804caf Binary files /dev/null and b/static/images/sleplet/slepian_wavelets_south_america_3B_2jmin_2j_L128_res512_real.png differ diff --git a/static/images/swoosh/swoosh-illustrator-bottom.svg b/static/images/swoosh/swoosh-illustrator-bottom.svg new file mode 100644 index 00000000..43ad0fbe --- /dev/null +++ b/static/images/swoosh/swoosh-illustrator-bottom.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/static/images/swoosh/swoosh-illustrator-top.svg b/static/images/swoosh/swoosh-illustrator-top.svg new file mode 100644 index 00000000..713f5704 --- /dev/null +++ b/static/images/swoosh/swoosh-illustrator-top.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/images/talks/david-nicholson-crowsetta-lightning-pycon2023.png b/static/images/talks/david-nicholson-crowsetta-lightning-pycon2023.png new file mode 100644 index 00000000..8780c0fa Binary files /dev/null and b/static/images/talks/david-nicholson-crowsetta-lightning-pycon2023.png differ diff --git a/static/images/talks/intro-slide-david-nicholson-crowsetta-lightning-pycon2023.png b/static/images/talks/intro-slide-david-nicholson-crowsetta-lightning-pycon2023.png new file mode 100644 index 00000000..e36fc1b9 Binary files /dev/null and b/static/images/talks/intro-slide-david-nicholson-crowsetta-lightning-pycon2023.png differ diff --git a/static/site.webmanifest b/static/site.webmanifest new file mode 100644 index 00000000..d1c9bea0 --- /dev/null +++ b/static/site.webmanifest @@ -0,0 +1,20 @@ +{ + "name": "pyOpenSci", + "short_name": "pyOpenSci", + "description": "pyOpenSci broadens participation in scientific open source.", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#2E6060", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/themes/clean-hugo/archetypes/blog.md b/themes/clean-hugo/archetypes/blog.md new file mode 100644 index 00000000..7f79afff --- /dev/null +++ b/themes/clean-hugo/archetypes/blog.md @@ -0,0 +1,12 @@ +--- +title: "How to Create a Full Width Flowing Blog Post or Page with Sections" of Different Colors"" +date: {{ .Date }} +draft: true +excerpt: "" +# JSON-LD: BlogPosting is output automatically for content in the blog section. +# Optional for richer snippets: author (string), image (src/alt), description (or use excerpt). +author: "Leah Wasser" +# image: +# src: "images/your-image.webp" +# alt: "Description for accessibility" +--- diff --git a/themes/clean-hugo/archetypes/default.md b/themes/clean-hugo/archetypes/default.md new file mode 100644 index 00000000..c6f3fcef --- /dev/null +++ b/themes/clean-hugo/archetypes/default.md @@ -0,0 +1,5 @@ ++++ +title = '{{ replace .File.ContentBaseName "-" " " | title }}' +date = {{ .Date }} +draft = true ++++ diff --git a/themes/clean-hugo/archetypes/documentation.md b/themes/clean-hugo/archetypes/documentation.md new file mode 100644 index 00000000..cae1ce8b --- /dev/null +++ b/themes/clean-hugo/archetypes/documentation.md @@ -0,0 +1,12 @@ +--- +title: "" +date: {{ .Date }} +draft: true +layout: "docs" +weight: 0 +excerpt: "" +header: + color: "primaryDark" +# JSON-LD: TechArticle (article rich results). Set tech_article: true or use cascade in hugo.toml for path. +tech_article: true +--- diff --git a/themes/clean-hugo/archetypes/gallery.md b/themes/clean-hugo/archetypes/gallery.md new file mode 100644 index 00000000..48dd9eb8 --- /dev/null +++ b/themes/clean-hugo/archetypes/gallery.md @@ -0,0 +1,20 @@ ++++ +title = '{{ replace .File.ContentBaseName "-" " " | title }}' +date = {{ .Date }} +excerpt = "" +groups = [] # Add group names for filtering (e.g., silver, green, variegated, small leaf) +tags = [] + +# Populate the hero with a title, excerpt and image +[ hero ] +image = "image.jpg" +subtitle = "A description of this gallery item." + +# Optional--explicit list of images +[image_roles] +flower = "flower.jpg" +habit = "habit.jpg" +images = [] ++++ + +A short summary or notes about this item. Add more details below. diff --git a/themes/clean-hugo/assets/css/_admonition.scss b/themes/clean-hugo/assets/css/_admonition.scss new file mode 100644 index 00000000..b393b2c2 --- /dev/null +++ b/themes/clean-hugo/assets/css/_admonition.scss @@ -0,0 +1,88 @@ + /* Admonition Component */ + .admonition { + border-left-width: 4px; + border-radius: 0 1rem 1rem 0; + padding: 2rem; + box-shadow: $shadow-md; + border: 1px solid; + border-left-width: 4px; + margin: 3rem 0; + display: flex; + gap: 0.75rem; + + @media (max-width: 640px) { + padding: 0.875rem; + gap: 0.5rem; + } + + &__icon { + flex-shrink: 0; + margin-top: 0.125rem; + + svg { + width: 1.75rem; + height: 1.75rem; + + @media (max-width: 640px) { + width: 1.15rem; + height: 1.15rem; + } + } + } + + &__content { + flex: 1 1 0%; + min-width: 0; + } + + &__title { + font-weight: 600; + margin-bottom: 0.25rem; + font-size: clamp(1.3rem, 2vw, 1.4rem); + } + + &__body { + font-size: clamp(0.99rem, 2vw, 1rem); + max-width: none; + line-height: 1.6; + } + + /* Admonition Type Variants */ + &--info, + &--success, + &--warning, + &--danger, + &--note { + background-color: color-mix(in srgb, var(--base-color) 8%, white); + border-color: color-mix(in srgb, var(--base-color) 95%, black); + + .admonition__title, + .admonition__body { + color: color-mix(in srgb, var(--base-color) 25%, black); + } + + .admonition__icon { + color: color-mix(in srgb, var(--base-color) 90%, black); + } + } + + &--info { + --base-color: var(--color-admonition-info, #3B82F6); + } + + &--success { + --base-color: var(--color-admonition-success, #22C55E); + } + + &--warning { + --base-color: var(--color-admonition-warning, #EAB308); + } + + &--danger { + --base-color: var(--color-admonition-danger, #EF4444); + } + + &--note { + --base-color: var(--color-admonition-note, #6B7280); + } + } diff --git a/themes/clean-hugo/assets/css/_blog-listing.scss b/themes/clean-hugo/assets/css/_blog-listing.scss new file mode 100644 index 00000000..93e17534 --- /dev/null +++ b/themes/clean-hugo/assets/css/_blog-listing.scss @@ -0,0 +1,85 @@ +/* Gallery Blog Components - Using Mixins */ + +/* Blog gallery listing page */ +.blog-listing { + @include container; + padding: 4rem 1.5rem; + + .container { + width: 100%; + } + + h2 { + @include responsive(font-size, 1.5rem, 1.875rem, 2.25rem); + margin-bottom: 2rem; + } + + .blog-grid { + @include responsive-grid(1, 2, 3); + } + + article { + position: relative; + display: flex; + flex-direction: column; + border-radius: $radius-md; + overflow: hidden; + background-color: var(--color-white); + box-shadow: $shadow-lg; + @include card-hover(-0.25rem, $shadow-2xl); + + .card-media { + @include image-zoom(1.1, $transition-slower); + width: 100%; + + img { + height: 10rem; + object-fit: cover; + } + } + + .card-body { + padding: 1rem; + display: flex; + flex-direction: column; + flex-grow: 1; + } + + h3 { + margin-top: 0; + font-size: 1.125rem; + font-weight: 600; + line-height: 1.25; + + a { + text-decoration: none; + color: var(--color-gray-900); + } + } + + time { + display: block; + margin-top: 0.5rem; + font-size: 0.75rem; + color: var(--color-gray-700); + } + + .excerpt { + margin-top: 0.5rem; + font-size: 0.875rem; + line-height: 1.625; + color: var(--color-gray-600); + } + + .stretched-link { + @include stretched-link; + } + } + + .pagination { + margin-top: $spacing-section; + display: flex; + justify-content: center; + gap: 0.5rem; + } +} diff --git a/themes/clean-hugo/assets/css/_blog.scss b/themes/clean-hugo/assets/css/_blog.scss new file mode 100644 index 00000000..2edea920 --- /dev/null +++ b/themes/clean-hugo/assets/css/_blog.scss @@ -0,0 +1,338 @@ +/* Blog card styles are found in _cards.scss */ +.blog-hero { + position: relative; + padding: $spacing-xl 0; + margin-bottom: $spacing-lg; + background-color: var(--color-primary-dark); + + @media (min-width: $breakpoint-md) { + padding: $spacing-xl 0; + } + + > .container h1 { + margin: 0; + color: var(--color-white); + font-weight: 700; + line-height: 1.1; + text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5); + } + + &__lead { + color: rgba(255, 255, 255, 0.92); + font-size: 1.125rem; + line-height: 1.5; + max-width: 42rem; + margin: $spacing-sm 0 0; + text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5); + } + + &--overlay { + min-height: 11rem; + background-size: cover; + background-repeat: no-repeat; + background-position: center; + background-color: var(--color-primary-dark); + + @media (min-width: $breakpoint-md) { + min-height: 13rem; + } + + &::before { + content: ""; + position: absolute; + inset: 0; + background: rgba(20, 13, 36, 0.55); + pointer-events: none; + } + + > .container { + position: relative; + z-index: 1; + } + } +} + +/* Blog grid page */ +.blog-index { + .filter-btn[aria-pressed="true"] { + background-color: var(--color-brand-purple); + border-color: var(--color-brand-purple); + color: var(--color-white); + } +} + +.blog-filter-hidden, +.blog-filter-section-hidden { + display: none !important; +} + +.blog-grid { + padding: 3rem 0; + + /* Category filter buttons - uses shared .filter-btn from _filter.scss */ + > div:first-child { + display: flex; + flex-wrap: wrap; + gap: 0.75rem; + margin-bottom: 3rem; + + /* Blog filters use the same .filter-btn class from _filter.scss */ + } +} + +/* Featured section layout */ +.blog-grid__featured { + display: grid; + grid-template-columns: 1fr; + gap: 2rem; + margin-bottom: 4rem; + min-height: 0; + + @media (min-width: $breakpoint-lg) { + grid-template-columns: repeat(3, 1fr); + } +} + + +/* Sidebar layout */ +.blog-grid__sidebar { + display: flex; + flex-direction: column; + gap: 1.5rem; + + /* .blog-card { + flex: 1 1 0%; + } + + /* Sidebar card titles - Card-specific: medium size between grid and featured */ + /* .blog-card > a > div h2 { + font-size: 1.5rem; + } */ +} + +/* Grid layout */ +.blog-grid__posts { + display: grid; + grid-template-columns: 1fr; + gap: 2rem; + + @media (min-width: $breakpoint-md) { + grid-template-columns: repeat(2, 1fr); + } + + @media (min-width: $breakpoint-lg) { + grid-template-columns: repeat(3, 1fr); + } +} + +/* Empty state */ +.blog-grid__empty { + text-align: center; + padding: 4rem 0; +} + +/* Blog single post styles */ +.blog-post__header { + position: relative; + width: 100%; + height: 400px; + margin-bottom: 2rem; + + > img { + width: 100%; + height: 100%; + object-fit: cover; + } + + > div:first-of-type { + position: absolute; + inset: 0; + background: linear-gradient(to top, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0.5), transparent); + } + + > div:nth-of-type(2) { + position: absolute; + bottom: 0; + left: 0; + right: 0; + color: white; + padding: 2rem 1rem; + max-width: $container-narrow; + margin: 0 auto; + word-break: break-word; + hyphens: auto; + @media (min-width: $breakpoint-md) { + padding: 2.5rem 2rem; + } + h1 { + font-size: 2rem; + font-weight: 800; + line-height: 1.15; + margin: 0 0 0.5rem 0; + max-width: 100%; + word-break: break-word; + hyphens: auto; + @media (min-width: $breakpoint-md) { + font-size: 2.5rem; + } + @media (min-width: $breakpoint-lg) { + font-size: 3rem; + } + } + p { + font-size: 1rem; + margin: 0; + color: var(--color-gray-200); + } + } + + > div:last-child { + position: absolute; + bottom: 0.5rem; + right: 0.5rem; + color: white; + font-size: 0.75rem; + opacity: 0.75; + } +} + +.blog-post__excerpt { + max-width: 56rem; + margin: 0 auto; + padding: 0 2rem; + margin-bottom: 2rem; + font-weight: 700; + + p { + font-size: 1.25rem; + line-height: 1.625; + color: var(--color-gray-700); + } +} + +// Blog content styles now handled by unified .content-main class + +/* Blog-specific typography overrides */ +.blog-post__header + .content-main { + /* Left align all headings (h2 and below) and ensure sentence case */ + /* Headings use base typography scale from main.scss, only override alignment */ + h2, h3, h4, h5, h6 { + text-align: left !important; + text-transform: none; + } + + /* Hugo syntax highlighting wrapper */ + .highlight { + margin-bottom: 1rem; + + pre { + margin: 0; + } + } +} + +.blog-post__tags { + max-width: 56rem; + margin: 0 auto; + padding: 0 2rem; + margin-top: 3rem; + font-size: 0.875rem; + color: var(--color-gray-600); + + a { + transition: color 200ms; + color: inherit; + + &:hover { + color: var(--color-gray-900); + } + } +} + +/* Last modified date for blog posts */ +.content-main + .content-last-modified { + max-width: 65ch; + margin: 0 auto; + padding: 0 2rem; +} + +/* Blog highlight section (for shortcode - full-width dark background) */ +.blog-highlight { + width: 100%; + padding: $spacing-section-lg 0 6rem; + background-color: var(--color-gray-900); + + .container { + @include container($container-max-width, 1.5rem, 2rem); + } + + .intro { + max-width: $container-wide; + margin: 0 auto; + + @media (min-width: $breakpoint-lg) { + margin: 0; + } + + h2 { + @include responsive(font-size, 2.25rem, 3rem); + font-weight: 600; + letter-spacing: -0.025em; + color: var(--color-white); + } + } + + .highlight-grid { + max-width: $container-wide; + margin: 2.5rem auto 0; + gap: 4rem 2rem; + border-top: 1px solid var(--color-gray-700); + padding-top: 2.5rem; + + @media (min-width: $breakpoint-sm) { + margin-top: 4rem; + padding-top: 4rem; + } + + @media (min-width: $breakpoint-lg) { + max-width: none; + margin-inline: 0; + } + } + + &__actions { + margin-top: 2.5rem; + } +} + +/* Blog archives section — soft purple band (matches main site) */ +.blog-archives { + width: 100vw; + max-width: 100vw; + margin: 3rem calc(50% - 50vw); + padding: 2.5rem clamp(1rem, 4vw, 2rem); + box-sizing: border-box; + background-color: color-mix(in srgb, var(--color-soft-purple) 35%, transparent); + + > .container > div:first-child { + margin-bottom: 1.5rem; + + h2 { + color: var(--color-brand-purple); + } + } +} + +.highlight-grid { + display: grid; + grid-template-columns: 1fr; + gap: 1.5rem; + + @media (min-width: $breakpoint-md) { + grid-template-columns: repeat(2, 1fr); + } + + @media (min-width: $breakpoint-lg) { + grid-template-columns: repeat(3, 1fr); + } +} diff --git a/themes/clean-hugo/assets/css/_buttons.scss b/themes/clean-hugo/assets/css/_buttons.scss new file mode 100644 index 00000000..1ac90531 --- /dev/null +++ b/themes/clean-hugo/assets/css/_buttons.scss @@ -0,0 +1,235 @@ +/* + Buttons — pyOpenSci brand variants + Adjust light-fill mix ratios below (higher = more color, lower = more white). +*/ +$btn-green-mix: 55%; +$btn-light-purple-mix: 65%; + +/* Base */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + padding: 0.75rem 1.5rem; + font-weight: 600; + font-size: 1.3rem; + text-decoration: none; + text-align: center; + line-height: 1.4; + border-radius: $radius-lg; + border: $btn-bd solid transparent; + cursor: pointer; + transition: transform $transition-base ease, box-shadow $transition-base ease, + background-color $transition-base ease, color $transition-base ease; + + &:hover { + transform: translateY(-1px); + box-shadow: $shadow-md; + } + + &:active { + transform: translateY(0); + } + + &:focus { + @include focus-ring; + } + + &:disabled, + &[aria-disabled="true"] { + opacity: 0.5; + cursor: not-allowed; + transform: none; + box-shadow: none; + } + + p { + margin: 0; + color: inherit; + } +} + +/* Dark purple fill — main CTA */ +.btn--dark-purple { + background-color: var(--color-brand-purple); + color: var(--color-white); + + &, + &:hover, + &:focus, + p { + color: var(--color-white); + } + + &:hover { + background-color: var(--color-brand-purple-dark); + } + + &:focus { + box-shadow: 0 0 0 2px var(--color-white), 0 0 0 4px var(--color-brand-purple); + } +} + +/* White fill — dark purple text */ +.btn--white { + background-color: var(--color-white); + color: var(--color-brand-purple); + + &:hover { + background-color: var(--color-gray-50); + color: var(--color-brand-purple); + } + + &:focus { + box-shadow: 0 0 0 2px var(--color-white), 0 0 0 4px var(--color-brand-purple); + } +} + +/* Light green fill — black text, mixed with white for contrast */ +.btn--green { + background-color: color-mix( + in srgb, + var(--color-admonition-success) $btn-green-mix, + var(--color-white) + ); + color: var(--color-gray-900); + + &:hover { + background-color: color-mix( + in srgb, + var(--color-admonition-success) calc($btn-green-mix + 10%), + var(--color-white) + ); + color: var(--color-gray-900); + } + + &:focus { + box-shadow: 0 0 0 2px var(--color-white), + 0 0 0 4px var(--color-admonition-success); + } +} + +/* Light purple fill — black text, mixed with white for contrast */ +.btn--light-purple { + background-color: color-mix( + in srgb, + var(--color-light-purple) $btn-light-purple-mix, + var(--color-white) + ); + color: var(--color-gray-900); + + &:hover { + background-color: color-mix( + in srgb, + var(--color-light-purple) calc($btn-light-purple-mix + 10%), + var(--color-white) + ); + color: var(--color-gray-900); + } + + &:focus { + box-shadow: 0 0 0 2px var(--color-white), + 0 0 0 4px var(--color-brand-medium-purple); + } +} + +/* Outline — medium purple border, dark purple text */ +.btn--outline { + background-color: transparent; + color: var(--color-brand-purple); + border-color: var(--color-brand-medium-purple); + + &:hover { + background-color: color-mix( + in srgb, + var(--color-brand-medium-purple) 12%, + transparent + ); + color: var(--color-brand-purple); + } + + &:focus { + box-shadow: 0 0 0 2px var(--color-white), + 0 0 0 4px var(--color-brand-medium-purple); + } +} + +/* Hero — white outline on dark purple backgrounds */ +.btn--outline-on-dark { + background-color: transparent; + color: var(--color-white); + border: $btn-bd-thin solid var(--color-white); + + &:hover { + background-color: color-mix(in srgb, var(--color-white) 12%, transparent); + color: var(--color-white); + } + + &:focus { + box-shadow: 0 0 0 2px var(--color-brand-purple-dark), + 0 0 0 4px var(--color-white); + } +} + +/* Large */ +.btn--lg, +.btn--large { + padding: 1rem 2rem; + font-size: 1.125rem; +} + +/* Groups */ +.btn-group { + display: flex; + gap: 1rem; + flex-wrap: wrap; + + &--center { + justify-content: center; + } + + &--right { + justify-content: flex-end; + } + + @media (max-width: $breakpoint-sm) { + flex-direction: column; + + .btn { + width: 100%; + } + } +} + +/* Icons */ +.btn--icon { + i, svg { + flex-shrink: 0; + } +} + +/* Legacy aliases — remove when content is fully migrated */ +.btn--primary { + @extend .btn--dark-purple; +} + +.btn--secondary { + @extend .btn--outline; +} + +.btn--accent { + @extend .btn--green; +} + +.btn--success { + @extend .btn--green; +} + +.btn--info { + @extend .btn--dark-purple; +} + +.btn--outline-on-light { + @extend .btn--outline; +} diff --git a/themes/clean-hugo/assets/css/_cards.scss b/themes/clean-hugo/assets/css/_cards.scss new file mode 100644 index 00000000..25ffbe6b --- /dev/null +++ b/themes/clean-hugo/assets/css/_cards.scss @@ -0,0 +1,817 @@ +/* Impact Cards Section - Hero/splash page cards */ +.impact-cards { + max-width: $container-max-width; + margin: 0 auto; + padding: $fluid-space-2xl $fluid-container-padding; +} + +.impact-cards__grid { + display: grid; + grid-template-columns: 1fr; + gap: $card-gap; + + @media (min-width: $breakpoint-md) { + grid-template-columns: repeat(2, 1fr); + } +} + +/* Opt-in from page front matter: cards_layout: wide */ +.impact-cards--wide { + max-width: $container-impact-wide; +} + +.impact-cards__grid--wide { + @media (min-width: $breakpoint-lg) { + grid-template-columns: repeat(3, 1fr); + } +} + +/* Impact cards - fluid padding scales from mobile to desktop */ +.impact-cards .card { + padding: $fluid-card-padding-lg; + margin: 0; + + /* Consistent typography for all card types */ + p { + font-size: $card-text-size; + line-height: $card-line-height; + color: $card-text-color; + } + + h2, h3 { + line-height: 1.25; + } +} + +/* Home-only full-bleed programs section */ +.home-programs-full { + width: 100vw; + position: relative; + left: 50%; + margin-inline: -50vw; + padding: 0 $fluid-container-padding; + + h2 { + margin: 0; + padding-top: $fluid-space-xl; + padding-bottom: 1rem; + text-align: left; + } + + .impact-cards { + max-width: none; + margin: 0; + padding-inline: 0; + } +} + +/* Optional 16:9 image strip above body (e.g. “What we offer” on /events/) */ +.impact-cards .card.card--with-top-image { + padding: 0; + overflow: hidden; + + .card__top-image { + margin: 0; + aspect-ratio: 16 / 9; + overflow: hidden; + + img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + transition: transform $transition-base ease-out; + } + } + + &:hover .card__top-image img { + transform: scale(1.03); + } + + > div { + @include responsive-padding(1.25rem, 1.25rem, 2.5rem, 2.5rem); + flex: 1 1 auto; + min-height: 0; + display: flex; + flex-direction: column; + } + + .card__cta { + padding: 0 1.25rem 1.25rem; + @media (min-width: $breakpoint-md) { + padding: 0 2.5rem 2.5rem; + } + } + + > div > .event-card__type:first-of-type { + align-self: flex-start; + margin-bottom: 0.25rem; + } +} + + .card--text { + @include card-base(); + @include responsive-padding(2.5rem, 2.5rem, 3rem, 3rem); + display: flex; + flex-direction: column; + @media (min-width: $breakpoint-md) { + min-height: 260px; + } + > div { + @include flex-center; + text-align: center; + flex: 1; + h2 { + @include responsive(font-size, 2.25rem, 3.75rem); + font-weight: 800; + line-height: 1.25; + max-width: 32rem; + color: var(--color-gray-900); + margin-top: 0; + margin-bottom: 0; + @media (min-width: $breakpoint-md) { + font-size: 3rem; + } + } + p { + font-size: $card-text-size; + line-height: $card-line-height; + color: $card-text-color; + transition: color $transition-base ease; + margin-bottom: 0; + @media (min-width: $breakpoint-md) { + font-size: 1.25rem; + } + } + > div:last-child { + margin-top: 1.5rem; + } + } + } + + /* Unused - kept for potential future use */ + .card-hover { + transition: transform $transition-base ease-in-out; + will-change: transform, box-shadow; + + &:hover, + &:focus-visible { + transform: $card-hover-transform; + box-shadow: $shadow-xl; + } + + /* ensure hover does NOT change text color */ + :is(.card__cta, h2, h3, p, li, a) { + color: inherit; + } + } + + /* Unused - kept for potential future use */ + .card-hover--compact:hover { + transform: translateY(-2px); + box-shadow: 0 6px 18px rgba(17,24,39,0.06); + } + + .card { + @include card-base(); + @include responsive-padding(1.25rem, 1.25rem, 2.5rem, 2.5rem); + display: flex; + flex-direction: column; + h3 { + font-size: $card-heading-size; + font-weight: 800; + line-height: 1.3; + margin-bottom: 1rem; + transition: color $transition-base ease; + margin-top: 0; + @media (min-width: $breakpoint-md) { + font-size: 1.5rem; + } + } + > div > h3 + div { + font-size: $card-text-size; + line-height: $card-line-height; + color: $card-text-color; + transition: color $transition-base ease; + @media (min-width: $breakpoint-md) { + font-size: 1.125rem; + } + p { + margin-bottom: 0.5rem; + &:last-child { + margin-bottom: 0; + } + } + + ul, ol { + padding-left: $card-list-padding; + + li { + font-size: $card-text-size; + line-height: $card-line-height; + margin-bottom: 0.5rem; + } + } + + a { + color: var(--color-link); + text-decoration: underline; + transition: color .2s ease; + + &:hover, + &:focus { + color: var(--color-link-hover); + } + } + + strong { + color: var(--color-gray-900); + font-weight: 600; + } + } + } + + /* Highlight card - can also use bg-primary utility */ + .card--highlight { + background-color: var(--color-primary-light); + transition: background-color $transition-base ease-in-out; + } + + /* White card variant - plain white background */ + .card--white { + background-color: var(--color-white); + } + + .card__icon { + font-size: $card-icon-size; + margin-bottom: 1rem; + display: inline-block; /* Prevent icon from creating extra layout space */ + margin-top: 0; /* Ensure no top margin */ + } + + .card__cta { + margin-top: 1rem; + @include responsive(font-size, 0.875rem, 1rem); + color: var(--color-link); + transition: color $transition-base ease; + + &:hover, + &:focus { + color: var(--color-link-hover); + } + } + +/* ========================================== + BLOG CARD MODIFIER - Consolidated from _blog.scss + ========================================== */ + +.card--blog { + display: flex; + flex-direction: column; + padding: 0; + overflow: hidden; + + a { + display: block; + height: 100%; + border-radius: $radius-md; + overflow: hidden; + background-color: var(--color-white); + box-shadow: $shadow-sm; + transition: box-shadow $transition-base ease-in-out, transform $transition-base ease-in-out; + text-decoration: none; + + &:focus { + outline: none; + box-shadow: 0 0 0 2px var(--color-white), 0 0 0 4px var(--color-primary); + } + + &:hover { + box-shadow: $shadow-lg; + transform: translateY(-2px); + + .card--blog__image img, + .card--blog__image-placeholder { + transform: scale(1.03); + } + } + } + + /* Image container */ + .card--blog__image, + .card--blog__image-placeholder { + width: 100%; + overflow: hidden; + aspect-ratio: 16 / 9; + transition: transform $transition-base ease-out; + margin: 0; + } + + .card--blog__image img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform $transition-base ease-out; + } + + /* Content area (featured + sidebar cards) */ + .card--blog__content { + flex: 1 1 0%; + display: flex; + flex-direction: column; + gap: 0.5rem; + padding: 1rem; + + .card--blog__badge { + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.05em; + text-transform: uppercase; + display: block; + margin-bottom: 0.5rem; + color: var(--color-brand-purple); + background: color-mix(in srgb, var(--color-soft-purple) 45%, transparent); + align-self: flex-start; + padding: 0.2rem 0.55rem; + border-radius: $radius-full; + } + + h2 { + font-size: 1.25rem; + font-weight: 600; + line-height: 1.25; + text-align: left; + color: var(--color-gray-900); + margin-top: 0; + margin-bottom: 0; + } + + time { + font-size: 0.75rem; + color: var(--color-gray-600); + } + + .card--blog__author { + font-size: 0.875rem; + color: var(--color-gray-700); + margin-bottom: 0; + } + + .card--blog__excerpt { + font-size: 1rem; + line-height: 1.625; + color: var(--color-gray-700); + margin-bottom: 0; + } + } +} + +/* Grid blog cards — dark header, white title + date (Jekyll blog index style) */ +.card--blog--grid { + .card--blog__link { + display: flex; + flex-direction: column; + height: 100%; + } + + .card--blog__media { + position: relative; + aspect-ratio: 16 / 10; + overflow: hidden; + display: flex; + flex-direction: column; + justify-content: flex-end; + } + + .card--blog__media-bg, + .card--blog__media-fallback { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + } + + .card--blog__media-scrim { + position: absolute; + inset: 0; + z-index: 1; + background: linear-gradient( + to top, + color-mix(in srgb, var(--color-brand-purple) 92%, transparent) 0%, + color-mix(in srgb, var(--color-brand-purple) 50%, transparent) 42%, + color-mix(in srgb, var(--color-brand-purple) 15%, transparent) 100% + ); + } + + @each $index, $color in ( + 0: var(--color-brand-magenta), + 1: var(--color-brand-header-purple), + 2: var(--color-soft-purple), + 3: var(--color-brand-medium-purple) + ) { + .card--blog__media-fallback--#{$index} { + background-color: #{$color}; + } + } + + .card--blog__image-placeholder { + &.card--blog__media-fallback--0 { background-color: var(--color-brand-magenta); } + &.card--blog__media-fallback--1 { background-color: var(--color-brand-header-purple); } + &.card--blog__media-fallback--2 { background-color: var(--color-soft-purple); } + &.card--blog__media-fallback--3 { background-color: var(--color-brand-medium-purple); } + } + + .card--blog__media-text { + position: relative; + z-index: 2; + padding: 0.85rem 1rem 1rem; + + h2 { + margin: 0 0 0.35rem; + font-size: 1.25rem; + font-weight: 600; + line-height: 1.25; + color: var(--color-white); + } + + time { + font-size: 0.75rem; + color: rgba(255, 255, 255, 0.88); + } + } + + .card--blog__body { + display: flex; + flex: 1 1 auto; + flex-direction: column; + gap: 0.45rem; + padding: 1rem 1.1rem 1.15rem; + } + + .card--blog__badge { + align-self: flex-start; + padding: 0.2rem 0.55rem; + border-radius: $radius-full; + font-size: 0.6875rem; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; + color: var(--color-brand-purple); + background: color-mix(in srgb, var(--color-soft-purple) 45%, transparent); + } + + .card--blog__excerpt { + flex: 1 1 auto; + margin: 0; + font-size: 0.875rem; + line-height: 1.5; + color: var(--color-gray-700); + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 3; + overflow: hidden; + } + + a:hover .card--blog__media-bg { + transform: scale(1.03); + } + + .card--blog__media-bg { + transition: transform $transition-base ease-out; + } +} + +/* Featured blog card modifier */ +.card--blog--featured { + @media (min-width: $breakpoint-lg) { + grid-column: span 2 / span 2; + } + + .card--blog__content { + gap: 0.75rem; + padding: 1.5rem; + + h2 { + font-size: 2rem; + font-weight: 700; + text-align: left; + letter-spacing: -0.02em; + margin-top: 0; + margin-bottom: 0; + + @media (min-width: $breakpoint-md) { + font-size: 2.25rem; + } + @media (min-width: $breakpoint-lg) { + font-size: 2.5rem; + } + } + + .card--blog__badge { + margin-bottom: 0.75rem; + } + + time { + font-size: 1rem; + } + + .card--blog__excerpt { + font-size: 1.125rem; + line-height: 1.625; + margin-bottom: 0; + + @media (min-width: $breakpoint-md) { + font-size: 1.25rem; + } + } + } +} + +/* Sidebar blog card modifier */ +.card--blog--sidebar { + .card--blog__content h2 { + font-size: 1.5rem; + } +} + +/* Shared listing cards used by blog/event archive grids */ +.listing-card { + @include card-surface($radius-md, 1px solid var(--color-gray-200), $shadow-sm, var(--color-white)); + padding: map-get($listing-card-default, padding); + display: flex; + flex-direction: column; + transition: box-shadow $transition-base ease-in-out, transform $transition-base ease-in-out, background-color $transition-base ease-in-out; + + &:hover { + box-shadow: $shadow-xl; + transform: translateY(-2px); + } + + .meta { + display: flex; + align-items: center; + gap: map-get($listing-card-default, meta-gap); + margin-bottom: 1rem; + font-size: map-get($listing-card-default, meta-font-size); + color: var(--color-gray-600); + + time { + font-weight: 500; + } + } + + .category { + padding: map-get($listing-card-default, category-padding); + border-radius: $radius-sm; + font-size: map-get($listing-card-default, category-font-size); + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.025em; + } + + .content { + position: relative; + display: flex; + flex-direction: column; + flex-grow: 1; + } + + h3 { + margin-top: 0; + margin-bottom: 0.75rem; + font-size: map-get($listing-card-default, title-font-size); + line-height: map-get($listing-card-default, title-line-height); + color: var(--color-gray-900); + + a { + color: inherit; + text-decoration: none; + transition: color $transition-base ease; + + &::before { + content: ""; + position: absolute; + inset: 0; + } + + &:hover { + color: var(--color-primary); + } + } + } + + .excerpt { + line-height: map-get($listing-card-default, excerpt-line-height); + margin-bottom: 1rem; + font-size: map-get($listing-card-default, excerpt-font-size); + color: var(--color-gray-700); + } + + .read-more { + margin-top: auto; + display: inline-flex; + align-items: center; + gap: 0.5rem; + position: relative; + z-index: 1; + font-weight: 500; + font-size: map-get($listing-card-default, read-more-font-size); + color: var(--color-link); + transition: color $transition-base ease; + + i { + font-size: 0.75rem; + transition: transform $transition-base ease; + } + + &:hover, + &:focus { + color: var(--color-link-hover); + + i { + transform: translateX(0.25rem); + } + } + } +} + +.listing-card--density-compact { + padding: map-get($listing-card-compact, padding); + + .meta { + gap: map-get($listing-card-compact, meta-gap); + margin-bottom: 0.5rem; + font-size: map-get($listing-card-compact, meta-font-size); + } + + .category { + font-size: map-get($listing-card-compact, category-font-size); + padding: map-get($listing-card-compact, category-padding); + } + + h3 { + margin-bottom: 0.4rem; + font-size: map-get($listing-card-compact, title-font-size); + line-height: map-get($listing-card-compact, title-line-height); + } + + .excerpt { + margin-bottom: 0.6rem; + font-size: map-get($listing-card-compact, excerpt-font-size); + line-height: map-get($listing-card-compact, excerpt-line-height); + } + + .read-more { + font-size: map-get($listing-card-compact, read-more-font-size); + } +} + +.listing-card--with-image { + padding: 0; + overflow: hidden; + + .listing-card__image { + margin: 0; + aspect-ratio: 16 / 10; + overflow: hidden; + + a { + display: block; + height: 100%; + } + + img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + transition: transform $transition-base ease-out; + } + } + + &:hover .listing-card__image img { + transform: scale(1.03); + } + + .listing-card__body { + display: flex; + flex-direction: column; + flex-grow: 1; + padding: map-get($listing-card-default, padding); + } +} + +.listing-card--blog-archive { + background-color: var(--color-white); + border: 1px solid color-mix(in srgb, var(--color-brand-purple) 10%, transparent); + box-shadow: 0 2px 6px color-mix(in srgb, var(--color-brand-purple) 6%, transparent); + + &:hover { + background-color: var(--color-white); + box-shadow: 0 4px 12px color-mix(in srgb, var(--color-brand-purple) 10%, transparent); + } + + .meta { + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + gap: 0.5rem; + width: 100%; + } + + .category { + margin-left: auto; + padding: 0.15rem 0.5rem; + border-radius: $radius-full; + font-size: map-get($listing-card-default, category-font-size); + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; + background-color: color-mix(in srgb, var(--color-soft-purple) 50%, transparent); + color: var(--color-brand-purple); + } + + h3 a { + color: var(--color-brand-purple); + text-decoration: underline; + text-decoration-color: color-mix(in srgb, var(--color-brand-purple) 35%, transparent); + text-underline-offset: 0.15em; + + &:hover, + &:focus { + color: var(--color-brand-purple-dark); + text-decoration-color: currentColor; + } + } + + .read-more { + color: var(--color-brand-purple); + text-decoration: underline; + text-decoration-color: color-mix(in srgb, var(--color-brand-purple) 35%, transparent); + text-underline-offset: 0.15em; + + &:hover, + &:focus { + color: var(--color-brand-purple-dark); + text-decoration-color: currentColor; + } + } +} + +.listing-card--on-light { + background-color: color-mix(in srgb, var(--color-primary-light) 60%, white 40%); + border-color: var(--color-gray-200); + + &:hover { + background-color: color-mix(in srgb, white 60%, var(--color-primary-light) 40%); + } + + .category { + background-color: var(--color-primary-light); + color: var(--color-primary-dark); + } +} + +.listing-card--on-dark { + background-color: var(--color-gray-900); + border-color: var(--color-gray-700); + + .meta { + color: var(--color-gray-200); + } + + .category { + color: var(--color-link-on-dark); + background-color: color-mix(in srgb, var(--color-link-on-dark) 10%, transparent); + border: 1px solid color-mix(in srgb, var(--color-link-on-dark) 20%, transparent); + transition: background-color $transition-base ease, border-color $transition-base ease; + + &:hover, + &:focus { + background-color: color-mix(in srgb, var(--color-link-on-dark) 20%, transparent); + border-color: color-mix(in srgb, var(--color-link-on-dark) 30%, transparent); + } + } + + h3 { + color: var(--color-white); + + a:hover { + color: var(--color-primary-light); + } + } + + .excerpt { + color: var(--color-gray-200); + } + + .read-more { + color: var(--color-link-on-dark); + + &:hover, + &:focus { + color: var(--color-primary-light); + } + } +} diff --git a/themes/clean-hugo/assets/css/_code.scss b/themes/clean-hugo/assets/css/_code.scss new file mode 100644 index 00000000..437d463a --- /dev/null +++ b/themes/clean-hugo/assets/css/_code.scss @@ -0,0 +1,96 @@ +/* Code block and syntax highlighting styles */ +/* These styles apply globally across all pages (blog, content, packages, etc.) */ + +code { + border-radius: 0.25rem; + padding: 0.125rem 0.375rem; + font-size: 0.95rem; + font-family: $font-family-mono; + background-color: rgba(0, 0, 0, 0.05); + color: #e83e8c; +} + +/* Code blocks (pre elements) - base and syntax highlighted */ +pre { + border-radius: 0.5rem; + padding: 1rem; + overflow-x: auto; + margin-bottom: 1rem; + background-color: #272822; + color: #f8f8f2; + font-size: 0.95rem; + line-height: 1.5; + font-family: $font-family-mono; + + code { + padding: 0; + background-color: transparent; + color: inherit; + font-size: inherit; + border-radius: 0; + } +} + +/* Hugo syntax highlighting wrapper (.highlight) - used by Chroma */ +.highlight { + margin-bottom: 1rem; + position: relative; + + pre { + margin: 0; + padding: 2rem; + } +} + +/* Chroma syntax highlighter wrapper */ +.highlight .chroma { + background-color: #272822; + border-radius: 0.5rem; + + pre { + background-color: transparent; + } +} + +/* Inline code within paragraphs, lists, and tables */ +p code, +li code, +td code { + padding: 0.125rem 0.375rem; + background-color: rgba(0, 0, 0, 0.05); + color: #e83e8c; + font-size: 0.875em; +} + +/* Code blocks should not have inline code styling */ +pre code, +.highlight code, +.chroma code { + background-color: transparent; + color: inherit; + padding: 0; +} + +/* Ensure code blocks are scrollable on mobile */ +pre, +.highlight pre, +.chroma pre { + overflow-x: auto; + -webkit-overflow-scrolling: touch; +} + +/* Line numbers (if enabled in Hugo config) */ +.highlight .lnt, +.chroma .lnt { + display: inline-block; + padding-right: 1em; + color: #75715e; + user-select: none; +} + +/* Ensure proper spacing for code blocks in content */ +.content-main pre, +.splash-page__content pre, +article pre { + margin-bottom: 1rem; +} diff --git a/themes/clean-hugo/assets/css/_content.scss b/themes/clean-hugo/assets/css/_content.scss new file mode 100644 index 00000000..0b87d403 --- /dev/null +++ b/themes/clean-hugo/assets/css/_content.scss @@ -0,0 +1,300 @@ + +/* Unified content container and headings (formerly blog styles) */ +.content-container, +.content-page { + max-width: $container-narrow; + margin: 0 auto; + padding: 0 $fluid-container-padding; +} + +/* Shared base class for all prose content */ +.prose-content { + margin: 0 auto; + font-size: 1rem; + line-height: 1.625; + color: var(--color-gray-700); + +/* Content links — exclude buttons (variant colors live in _buttons.scss) */ +.content-main a:not(.btn), +.splash-page__content a:not(.btn), +.prose-content a:not(.btn) { + color: var(--color-link); + + &:hover, + &:focus { + color: var(--color-link-hover); + } +} + + /* Shared code styling */ + pre { + border-radius: 0.5rem; + padding: 1rem; + overflow-x: auto; + margin-bottom: 1rem; + background-color: #272822; + color: #f8f8f2; + font-size: 0.875rem; + line-height: 1.5; + } + + code { + border-radius: 0.25rem; + padding: 0.125rem 0.375rem; + font-size: 0.875em; + background-color: rgba(0, 0, 0, 0.05); + color: #e83e8c; + } + + pre code { + padding: 0; + background-color: transparent; + color: inherit; + font-size: inherit; + } + + /* Responsive font sizing */ + @media (min-width: $breakpoint-lg) { + font-size: 1.25rem; + } +} + +.content-title { + @include responsive(font-size, 2rem, 2.5rem, 3rem); + font-weight: 800; + margin-bottom: 1rem; +} + +.content-body { + @extend .prose-content; + max-width: 65ch; + + + .highlight { + margin-bottom: 1rem; + pre { + margin: 0; + } + } + + h1 { + font-size: 2rem; + font-weight: 800; + margin-bottom: 1rem; + @media (min-width: $breakpoint-md) { + font-size: 2.5rem; + } + @media (min-width: $breakpoint-lg) { + font-size: 3rem; + } + } + h2 { + font-size: 1.5rem; + font-weight: 700; + margin-bottom: 1rem; + @media (min-width: $breakpoint-md) { + font-size: 1.875rem; + } + @media (min-width: $breakpoint-lg) { + font-size: 2.25rem; + } + } + h3 { + font-size: 1.25rem; + font-weight: 600; + margin-bottom: 1rem; + @media (min-width: $breakpoint-md) { + font-size: 1.5rem; + } + @media (min-width: $breakpoint-lg) { + font-size: 1.75rem; + } + } + p { + font-size: 1.125rem; + line-height: 1.625; + color: var(--color-gray-700); + margin-bottom: 1rem; + @media (min-width: $breakpoint-md) { + font-size: 1.25rem; + } + } +} + +.content-date { + margin-bottom: 2rem; + color: var(--color-gray-600); +} + +// Headings left aligned for all content +.content-main h2, +.content-main h3, +.content-main h4, +.content-main h5, +.content-main h6, +.splash-page__content h2, +.splash-page__content h3, +.splash-page__content h4, +.splash-page__content h5, +.splash-page__content h6 { + text-align: left !important; + text-transform: none; +} + +@media (min-width: $breakpoint-lg) { + .content-main, + .splash-page__content { + font-size: 1.25rem; + } +} + +// Full-width shortcodes for unified content container +.content-main > .metrics-bar, +.content-main > .blog-highlight, +.content-main > .single-card-wide, +.content-main > .youtube-container:not(.youtube-container--constrained), +.content-main > .two-card-row, +.content-main > .impact-cards, +.content-main > .swoosh-section, +.content-main > .swoosh-section__divider-wrap, +.splash-page__content > .metrics-bar, +.splash-page__content > .blog-highlight, +.splash-page__content > .single-card-wide, +.splash-page__content > .youtube-container:not(.youtube-container--constrained), +.splash-page__content > .two-card-row, +.splash-page__content > .impact-cards, +.splash-page__content > .swoosh-section, +.splash-page__content > .swoosh-section__divider-wrap { + width: 100vw; + position: relative; + left: 50%; + margin-inline: -50vw; +} + +// Unified content container with prose constraints and full-width support +.content-main { + @extend .prose-content; + max-width: 65ch; // Optimal reading width + margin: 0 auto; // Center the constrained content + + // Full-width shortcodes (defined above) + // These will break out of the 65ch constraint when needed +} + +/* Splash home: same typography as .content-main but no 65ch cap (cards / grids set their own max-width) */ +.splash-page__content { + @extend .prose-content; + max-width: 80rem; + width: 100%; + margin: 0 auto; + padding: 0 $fluid-container-padding; + box-sizing: border-box; +} + +// List styles for unified content +.content-main ul, +.content-main ol, +.splash-page__content ul, +.splash-page__content ol { + margin-bottom: 1rem; +} +.content-main li, +.splash-page__content li { + margin-bottom: 0.5rem; +} +.content-main p, +.splash-page__content p { + margin-bottom: 1rem; + line-height: 1.625; + color: var(--color-gray-700); +} + +/* Section styles for list pages */ +.section-container { + padding: 3rem 0; +} + +.section-content { + margin-bottom: 1.5rem; +} + +.section-list { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + +.section-item { + a { + font-size: 1.125rem; + font-weight: 500; + transition: color 0.2s; + color: var(--color-gray-900); + + &:hover, + &:focus { + text-decoration: underline; + color: var(--color-link); + } + } +} + +.section-item__meta { + font-size: 0.875rem; + color: var(--color-gray-600); +} + +/* Term/taxonomy listing styles */ +.term-list { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.term-item { + a { + font-size: 1.125rem; + transition: color 0.2s; + color: var(--color-gray-900); + + &:hover, + &:focus { + color: var(--color-link); + } + } +} + +.term-count { + font-size: 0.875rem; + color: var(--color-gray-700); +} + +.term-description { + font-size: 0.875rem; + margin-bottom: 1.5rem; + color: var(--color-gray-600); +} + +/* Last modified date footer */ +.content-last-modified { + margin: 3rem .5rem .5rem .5rem; + padding-top: 2rem; + border-top: 1px solid; + border-color: var(--color-gray-200); + font-style: italic; + + p { + font-size: 0.875rem; + margin-bottom: 0; + color: var(--color-gray-600); + + strong { + font-weight: 600; + color: var(--color-gray-700); + } + + time { + color: var(--color-gray-600); + } + } +} diff --git a/themes/clean-hugo/assets/css/_docs.scss b/themes/clean-hugo/assets/css/_docs.scss new file mode 100644 index 00000000..cd468ea0 --- /dev/null +++ b/themes/clean-hugo/assets/css/_docs.scss @@ -0,0 +1,512 @@ +/** + * Documentation Layout Styles + * Using mixins and variables + */ + +/* Documentation Header */ +.docs-header { + padding: 1rem 0; + margin-bottom: 2rem; + background-color: var(--color-primary-dark); + + /* Color variants */ + &--primary { + background-color: var(--color-primary); + } + + &--primaryDark { + background-color: var(--color-primary-dark); + } + + &--secondary { + background-color: var(--color-secondary); + } + + &--accent { + background-color: var(--color-accent); + } + + &--neutral { + background-color: var(--color-neutral); + } +} + +.docs-header__inner { + @include container; +} + +.docs-header__title { + @include responsive(font-size, 1.5rem, 1.25rem); + font-weight: 700; + color: white; + margin: 0; +} + +.docs-layout { + @include container; + display: grid; + gap: 3rem; + padding-block: 2rem; + position: relative; + grid-template-columns: 1fr; + + @media (min-width: $breakpoint-lg) { + grid-template-columns: 280px 1fr; + gap: 2rem; + } +} + +/* Sidebar Navigation */ +.docs-sidebar { + /* Mobile: fixed slide-out drawer */ + position: fixed; + top: 0; + left: 0; + width: 300px; + height: 100vh; + background-color: white; + padding: 1rem; + max-height: 100vh; + overflow-y: auto; + z-index: 1001; + transform: translateX(-300px); + transition: transform $transition-fast ease-in-out; + box-shadow: $shadow-lg; + border-right: 1px solid var(--color-gray-200); + @include custom-scrollbar; + + &.open { + transform: translateX(0); + } + + /* Desktop: static sidebar in layout */ + @media (min-width: $breakpoint-lg) { + position: static; + width: auto; + height: fit-content; + top: 2rem; + max-height: calc(100vh - 4rem); + padding-right: 1rem; + transform: none; + box-shadow: none; + border-right: none; + border-bottom: 2px solid var(--color-gray-200); + padding-bottom: 2rem; + z-index: auto; + } +} + +/* Overlay for mobile sidebar */ +.overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + opacity: 0; + visibility: hidden; + transition: opacity $transition-fast, visibility $transition-fast; + z-index: 1000; + + &.open { + opacity: 1; + visibility: visible; + } + + @media (min-width: $breakpoint-lg) { + display: none; + } +} + +/* Mobile toggle button for sidebar */ +.docs-toggle { + position: fixed; + top: 1rem; + left: 1rem; + width: 2.5rem; + height: 2.5rem; + background-color: var(--color-primary-dark); + border: none; + border-radius: $radius-md; + color: white; + cursor: pointer; + z-index: 1002; + @include flex-center; + transition: all $transition-fast; + box-shadow: $shadow-md; + + &:hover { + background-color: var(--color-primary); + box-shadow: $shadow-lg; + } + + i { + font-size: 1.25rem; + } + + @media (min-width: $breakpoint-lg) { + display: none; + } +} + +/* Section navigation */ +.docs-section-nav { + margin-bottom: 1.5rem; +} + +.docs-section-title { + font-size: 0.875rem; + font-weight: 700; + color: var(--color-gray-900); + margin-bottom: 0.75rem; + text-transform: uppercase; + letter-spacing: 0.025em; +} + +.docs-nav-separator { + border-top: 1px solid var(--color-gray-200); + margin: 1.5rem 0; +} + +.docs-section-list { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +/* Navigation items generated by JavaScript */ +.docs-nav__list { + list-style: none; + padding: 0; + margin: 0; +} + +.docs-nav__item { + margin-bottom: 0.5rem; + + &--sub { + margin-bottom: 0.25rem; + } +} + +.docs-nav__sublist { + list-style: none; + padding-left: 1rem; + margin: 0.5rem 0; + border-left: 2px solid var(--color-gray-200); +} + +.docs-nav__link { + display: block; + padding: 0.5rem 0.75rem; + color: var(--color-gray-700); + text-decoration: none; + border-radius: $radius-md; + transition: all $transition-fast; + line-height: 1.375; + font-size: 0.875rem; + + &:hover { + background-color: var(--color-gray-200); + color: var(--color-primary-dark); + } + + &--active { + font-weight: 600; + background-color: var(--color-primary-light); + color: var(--color-primary-dark); + } + + .docs-nav__item--sub & { + padding: 0.375rem 0.75rem; + font-size: 0.75rem; + } +} + +/* Hugo-generated menu styles */ +.docs-menu__list { + list-style: none; + padding: 0; + margin: 0; + + &--level-2 { + padding-left: 1rem; + margin-top: 0.5rem; + border-left: 2px solid var(--color-gray-200); + } + + &--level-3 { + padding-left: 1rem; + margin-top: 0.25rem; + } +} + +.docs-menu__item { + margin-bottom: 0.25rem; + + &--expanded { + margin-bottom: 0.5rem; + } +} + +.docs-menu__link { + display: block; + padding: 0.5rem 0.75rem; + color: var(--color-gray-700); + text-decoration: none; + border-radius: $radius-md; + transition: all $transition-fast; + line-height: 1.375; + font-size: 0.875rem; + + &:hover { + background-color: var(--color-gray-200); + color: var(--color-primary-dark); + } + + &--active { + font-weight: 600; + background-color: var(--color-primary-light); + color: var(--color-primary-dark); + } + + // Icon spacing + i { + margin-right: 0.5rem; + width: 1rem; + text-align: center; + } + + .docs-menu__list--level-2 & { + padding: 0.375rem 0.75rem; + font-size: 0.8125rem; + } + + .docs-menu__list--level-3 & { + padding: 0.25rem 0.75rem; + font-size: 0.75rem; + } +} + +/* Inline Table of Contents (in sidebar under active page) */ +.toc-items { + list-style: none; + padding: 0.5rem 0 0 1rem; + margin: 0.5rem 0 0 0; + border-left: 2px solid var(--color-gray-200); +} + +.toc-item { + margin-bottom: 0.25rem; + + &--sub { + margin-bottom: 0.125rem; + } +} + +.toc-sublist { + list-style: none; + padding-left: 0.75rem; + margin: 0.25rem 0; +} + +.toc-link { + display: block; + padding: 0.375rem 0.75rem; + color: var(--color-gray-600); + text-decoration: none; + border-radius: $radius-sm; + transition: all $transition-fast; + line-height: 1.3; + font-size: 0.75rem; + + &:hover { + background-color: var(--color-gray-100); + color: var(--color-primary-dark); + } + + &--active { + font-weight: 500; + color: var(--color-primary-dark); + background-color: var(--color-primary-light); + } + + .toc-item--sub & { + padding: 0.25rem 0.75rem; + font-size: 0.6875rem; + color: var(--color-gray-500); + } + + .toc-item--sub &:hover { + color: var(--color-primary-dark); + } +} + +/* "On This Page" TOC container */ +#docs-page-toc { + margin-top: 1.5rem; +} + +/* Main Content */ +.docs-content { + min-width: 0; + max-width: $container-narrow; + + h1 { + @include responsive(font-size, 2.25rem, 1.875rem); + font-weight: 700; + color: var(--color-gray-900); + margin-bottom: 1rem; + line-height: 1.25; + } + + h2 { + font-size: 1.875rem; + font-weight: 700; + color: var(--color-gray-900); + margin-top: 3rem; + margin-bottom: 1rem; + padding-bottom: 0.5rem; + border-bottom: 2px solid var(--color-gray-200); + scroll-margin-top: 2rem; + + &:first-child { + margin-top: 0; + } + } + + h3 { + font-size: 1.5rem; + font-weight: 600; + color: var(--color-gray-900); + margin-top: 2rem; + margin-bottom: 0.75rem; + scroll-margin-top: 2rem; + } + + h4 { + font-size: 1.25rem; + font-weight: 600; + color: var(--color-gray-900); + margin-top: 1.5rem; + margin-bottom: 0.5rem; + } + + p { + margin-bottom: 1rem; + color: var(--color-gray-700); + line-height: 1.625; + } + + ul, ol { + margin-bottom: 1rem; + padding-left: 1.5rem; + color: var(--color-gray-700); + + li { + margin-bottom: 0.5rem; + } + } + + pre { + margin-bottom: 1.5rem; + border-radius: $radius-md; + overflow-x: auto; + } + + code { + font-size: 0.875rem; + font-family: $font-family-mono; + } + + p code, + li code { + background-color: var(--color-gray-200); + padding: 0.125rem 0.375rem; + border-radius: $radius-sm; + color: var(--color-gray-900); + } + + a { + text-decoration: underline; + color: var(--color-link); + + &:hover { + color: var(--color-link-hover); + } + } + + table { + width: 100%; + margin-bottom: 1.5rem; + border-collapse: collapse; + + th, td { + padding: 0.75rem; + border: 1px solid var(--color-gray-200); + text-align: left; + } + + th { + background-color: var(--color-gray-200); + font-weight: 600; + } + } + + img { + max-width: 100%; + height: auto; + border-radius: $radius-md; + margin: 1.5rem 0; + } +} + +.docs-excerpt { + font-size: 1.25rem; + color: var(--color-gray-600); + margin-bottom: 2rem; + line-height: 1.625; +} + +/* Scroll to Top Button */ +.docs-scroll-btn { + position: fixed; + bottom: 2rem; + right: 2rem; + width: 3rem; + height: 3rem; + border-radius: $radius-full; + border: none; + cursor: pointer; + @include flex-center; + box-shadow: $shadow-lg; + opacity: 0; + visibility: hidden; + transition: all $transition-fast; + z-index: $z-fixed; + background-color: var(--color-primary-dark); + color: white; + + @media (min-width: $breakpoint-md) { + bottom: 1rem; + right: 1rem; + width: 2.5rem; + height: 2.5rem; + } + + &:hover { + transform: translateY(-0.125rem); + background-color: var(--color-primary); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15); + } + + &--visible { + opacity: 1; + visibility: visible; + } + + i { + @include responsive(font-size, 1.25rem, 1rem); + } +} diff --git a/themes/clean-hugo/assets/css/_events.scss b/themes/clean-hugo/assets/css/_events.scss new file mode 100644 index 00000000..aaaa3c17 --- /dev/null +++ b/themes/clean-hugo/assets/css/_events.scss @@ -0,0 +1,430 @@ +/* Events listing (/events/) — uses global .container */ +.events-list { + padding: 2rem 0 4rem; +} + +.blog-hero .events-list__intro { + color: rgba(255, 255, 255, 0.92); + font-size: 1.125rem; + line-height: 1.5; + max-width: 42rem; + margin: 0.5rem 0 0; +} + +/* Small caps section label above upcoming cards */ +.events-list__kicker { + font-family: $font-family-body; + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--color-gray-600); + margin: 0 0 1rem; +} + +.events-list__kicker-amp { + letter-spacing: 0.08em; +} + +.events-list__heading { + margin-top: 2.5rem; + margin-bottom: 1.25rem; + font-size: 1.75rem; + + &:first-of-type { + margin-top: 0; + } +} + +/* Upcoming/live: flexible grid for many events */ +.events-list__featured { + display: grid; + gap: 1.25rem; + grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); + + @media (min-width: $breakpoint-lg) { + gap: 1.5rem; + } +} + +.events-list__empty { + color: var(--color-gray-700); + margin-bottom: 2rem; +} + +.events-list__types { + margin-top: 3rem; + margin-bottom: 1rem; +} + +.events-list__actions { + margin-top: 1.5rem; + display: flex; + justify-content: flex-start; +} + +/* Event archive bands reuse .blog-archives + .listing-card--blog-archive from _blog.scss */ +.events-past-archives { + margin-top: 0; +} + +.events-upcoming-archives .events-list__kicker-amp, +.events-past-archives .events-list__kicker-amp { + letter-spacing: 0.08em; +} + +/* Event type pill — colors from hugo.toml CSS variables */ +.event-card__type { + display: inline-flex; + align-items: center; + font-size: 0.75rem; + font-weight: 600; + padding: 0.3rem 0.7rem; + border-radius: 9999px; + line-height: 1.2; + white-space: nowrap; + max-width: 100%; +} + +.event-card__type--training { + background-color: var(--color-event-label-training-bg, var(--color-primary-light)); + color: var(--color-event-label-training-fg, var(--color-primary-dark)); +} + +.event-card__type--sprint { + background-color: var(--color-event-label-sprint-bg, var(--color-accent-light)); + color: var(--color-event-label-sprint-fg, var(--color-gray-900)); +} + +.event-card__type--community { + background-color: var(--color-event-label-community-bg, var(--color-secondary)); + color: var(--color-event-label-community-fg, var(--color-gray-900)); +} + +.event-card__type--talk { + background-color: var(--color-event-label-talk-bg, var(--color-admonition-note, #cae4e4)); + color: var(--color-event-label-talk-fg, var(--color-primary-dark)); +} + +.event-card__type--default { + background-color: var(--color-gray-200); + color: var(--color-gray-700); +} + +/* Featured (upcoming/live) cards — white surface, mock-inspired layout */ +.event-card--featured { + > a { + display: flex; + flex-direction: column; + height: 100%; + min-height: 12rem; + padding: 0; + overflow: hidden; + text-decoration: none; + color: inherit; + border-radius: $radius-md; + background-color: var(--color-white); + box-shadow: $shadow-sm; + border: 1px solid var(--color-gray-200); + transition: box-shadow $transition-base ease-in-out, transform $transition-base ease-in-out; + + &:hover { + box-shadow: $shadow-lg; + transform: translateY(-2px); + + .event-card__cta { + color: var(--color-link-hover); + } + } + } +} + +.event-card__featured-image { + margin: 0; + aspect-ratio: 16 / 9; + overflow: hidden; + + img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + transition: transform $transition-base ease-out; + } +} + +.event-card--featured:hover .event-card__featured-image img { + transform: scale(1.03); +} + +.event-card__featured-inner { + display: flex; + flex-direction: column; + height: 100%; + gap: 0.65rem; + min-height: 0; + padding: 1.25rem 1.35rem; + flex: 1 1 auto; +} + +.event-card--featured:not(.event-card--with-image) > a { + padding: 1.25rem 1.35rem; +} + +.event-card__featured-top { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 0.75rem; +} + +.event-card__date-badge { + flex-shrink: 0; + min-width: 3.25rem; + max-width: 8rem; + padding: 0.45rem 0.5rem; + border-radius: $radius-sm; + background-color: var(--color-event-date-badge-bg, var(--color-accent)); + color: var(--color-event-date-badge-fg, var(--color-white)); + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + line-height: 1.15; +} + +.event-card__date-badge-primary { + font-size: 1.0625rem; + font-weight: 800; + letter-spacing: 0.02em; +} + +.event-card__date-badge-secondary { + font-size: 0.65rem; + font-weight: 700; + letter-spacing: 0.08em; +} + +.event-card__date-badge-year { + font-size: 0.6rem; + font-weight: 600; + margin-top: 0.15rem; + opacity: 0.95; +} + +.event-card--featured .event-card__title { + font-size: 1.25rem; + font-weight: 700; + line-height: 1.25; + margin: 0; + color: var(--color-gray-900); +} + +.event-card__meta { + margin: 0; + font-size: 0.9375rem; + line-height: 1.45; + color: var(--color-gray-600); +} + +.event-card__cta { + margin-top: auto; + padding-top: 0.35rem; + font-size: 0.875rem; + font-weight: 600; + color: var(--color-link); +} + +/* Compact past cards (horizontal thumb) */ +.event-card:not(.event-card--featured) { + > a { + display: block; + height: 100%; + text-decoration: none; + color: inherit; + border-radius: $radius-md; + overflow: hidden; + background-color: var(--color-white); + box-shadow: $shadow-sm; + border: 1px solid var(--color-gray-200); + transition: box-shadow $transition-base ease-in-out, transform $transition-base ease-in-out; + + &:hover { + box-shadow: $shadow-lg; + transform: translateY(-2px); + } + } +} + +.event-card__content { + display: flex; + flex-direction: row; + min-height: 0; +} + +.event-card__date { + position: relative; + flex: 0 0 6.5rem; + min-height: 7rem; + overflow: hidden; +} + +.event-card__date-background { + position: absolute; + inset: 0; + background-size: cover; + background-position: center; + + &--default { + background: linear-gradient(145deg, var(--color-primary) 0%, var(--color-primary-dark) 100%); + } +} + +.event-card__date-text { + position: relative; + z-index: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + padding: 0.5rem; + color: var(--color-white); + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35); + font-weight: 700; + line-height: 1.15; + text-align: center; + + span { + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.02em; + } + + span:first-child { + font-size: 1.25rem; + font-weight: 800; + } + + span:nth-child(3) { + font-size: 0.7rem; + opacity: 0.95; + } +} + +.event-card__details { + flex: 1; + padding: 1rem 1.125rem; + display: flex; + flex-direction: column; + gap: 0.5rem; + min-width: 0; +} + +.event-card__type--inline { + align-self: flex-start; + margin-bottom: 0.15rem; +} + +.event-card__title { + font-size: 1.125rem; + font-weight: 600; + line-height: 1.3; + margin: 0; + color: var(--color-gray-900); +} + +.event-card__details p { + margin: 0; + font-size: 0.875rem; + line-height: 1.5; + color: var(--color-gray-600); +} + +.event-card__button { + margin-top: auto; + font-size: 0.8125rem; + font-weight: 600; + color: var(--color-primary); +} + +/* Event detail: instructors (optional front matter) */ +.event-instructors { + margin-top: 3rem; + padding-top: 2rem; + border-top: 1px solid var(--color-gray-200); +} + +.event-instructors__heading { + font-size: 1.5rem; + margin-bottom: 1.25rem; +} + +.event-instructors__grid { + list-style: none; + margin: 0; + padding: 0; + display: grid; + gap: 1.5rem; + grid-template-columns: 1fr; + + @media (min-width: $breakpoint-md) { + grid-template-columns: repeat(2, 1fr); + } +} + +.event-instructors__card { + display: flex; + gap: 1rem; + align-items: flex-start; + padding: 1rem; + border-radius: $radius-md; + border: 1px solid var(--color-gray-200); + background-color: var(--color-white); + box-shadow: $shadow-sm; +} + +.event-instructors__avatar { + flex-shrink: 0; + width: 5rem; + height: 5rem; + border-radius: 9999px; + object-fit: cover; +} + +.event-instructors__name { + margin: 0 0 0.5rem; + font-size: 1.125rem; +} + +.event-instructors__bio { + margin: 0; + font-size: 0.9375rem; + line-height: 1.5; + color: var(--color-gray-700); +} + +.event-card--compact { + .event-card__date { + flex-basis: 4.5rem; + min-height: 5rem; + } + + .event-card__date-text span:first-child { + font-size: 1rem; + } + + .event-card__details { + padding: 0.75rem 0.875rem; + } + + .event-card__title { + font-size: 0.9375rem; + } + + .event-card__type { + font-size: 0.65rem; + padding: 0.2rem 0.5rem; + } +} diff --git a/themes/clean-hugo/assets/css/_feature-section.scss b/themes/clean-hugo/assets/css/_feature-section.scss new file mode 100644 index 00000000..d9588c57 --- /dev/null +++ b/themes/clean-hugo/assets/css/_feature-section.scss @@ -0,0 +1,111 @@ + /* Container classes for both feature and feature-section */ + .feature, + .feature-section { + padding: $fluid-space-2xl 0; + + header { + @include responsive(margin-bottom, 2.5rem, 3rem); + text-align: center; + + h2 { + @include responsive(font-size, 2.25rem, 3.75rem); + font-weight: 700; + margin-bottom: 1rem; + + @media (min-width: $breakpoint-sm) { + font-size: 3rem; + } + } + + p { + @include responsive(font-size, 1.125rem, 1.5rem); + opacity: 0.8; + max-width: 48rem; + margin-inline: auto; + + @media (min-width: $breakpoint-sm) { + font-size: 1.25rem; + } + } + } + + div { + display: grid; + grid-template-columns: 1fr; + gap: 2rem; + } + } + + /* Unified feature card — same shell as interactive cards, no hover motion */ + .feature-card { + @include card-surface($bg: var(--color-feature-card)); + padding: $fluid-card-padding-md; + } + + .feature-card h3 { + @include responsive(font-size, 1.25rem, 1.875rem); + font-weight: 800; + margin-top: 2rem; + margin-bottom: 1rem; + + @media (min-width: $breakpoint-sm) { + font-size: 1.5rem; + } + + &:first-child { + margin-top: 0; + } + } + + .feature-card h4 { + @include responsive(font-size, 1.125rem, 1.25rem); + font-weight: 600; + margin-top: 2rem; + margin-bottom: 0.75rem; + } + + .feature-card .lead { + @include responsive(font-size, 1.125rem, 1.25rem); + margin-bottom: 1.5rem; + } + + .feature-card p { + @include responsive(font-size, 1rem, 1.25rem); + margin-bottom: 1.5rem; + + @media (min-width: $breakpoint-sm) { + font-size: 1.125rem; + } + } + + .feature-card ul { + list-style-type: disc; + padding-left: 1.5rem; + padding-right: 1rem; + @include responsive(font-size, 1rem, 1.125rem); + line-height: 1.625; + + > li + li { + margin-top: 0.5rem; + } + } + + .feature-card ul.links a { + text-decoration: underline; + color: var(--color-link); + + &:hover, + &:focus { + color: var(--color-link-hover); + } + } + + .feature-card a { + text-decoration: underline; + color: currentColor; + + &:hover, + &:focus { + color: var(--color-link); + } + } diff --git a/themes/clean-hugo/assets/css/_figure.scss b/themes/clean-hugo/assets/css/_figure.scss new file mode 100644 index 00000000..f6f9a4e2 --- /dev/null +++ b/themes/clean-hugo/assets/css/_figure.scss @@ -0,0 +1,22 @@ +/* Figure shortcode styles */ +.figure { + margin: 1.5rem 0; + + &__link, + &__picture { + display: block; + } + + &__image { + width: 100%; + height: auto; + border-radius: $radius-md; + } + + &__caption { + margin-top: 0.5rem; + font-size: 0.875rem; + text-align: center; + color: var(--color-gray-600); + } +} diff --git a/themes/clean-hugo/assets/css/_filter.scss b/themes/clean-hugo/assets/css/_filter.scss new file mode 100644 index 00000000..162989a7 --- /dev/null +++ b/themes/clean-hugo/assets/css/_filter.scss @@ -0,0 +1,56 @@ +/* Filterable grid page container and headings to match blog layout */ +.filterable-grid-container { + max-width: $container-narrow; + margin: 0 auto; + padding: 0 $fluid-container-padding; +} + +.filterable-grid-title { + @include responsive(font-size, 2rem, 2.5rem, 3rem); + font-weight: 800; + margin-bottom: 1rem; +} + +.filterable-grid-body { + font-size: 1rem; + line-height: 1.625; + color: var(--color-gray-700); + @media (min-width: $breakpoint-lg) { + font-size: 1.25rem; + } +} +/* Filter Components */ +.filter-row { + display: flex; + flex-wrap: wrap; + gap: 0.75rem; + margin-bottom: 2rem; + justify-content: center; +} + +.filter-btn { + padding: 0.5rem 1rem; + border-radius: $radius-full; + font-size: 0.875rem; + font-weight: 500; + border: 1px solid var(--color-gray-200); + background-color: var(--color-white); + color: var(--color-gray-700); + cursor: pointer; + transition: all $transition-base; + + &[aria-pressed="true"] { + background-color: var(--color-primary); + border-color: var(--color-primary); + color: white; + } + + &[aria-pressed="false"]:hover { + background-color: var(--color-gray-50); + border-color: var(--color-gray-600); + } + + &:focus { + @include focus-ring; + } +} diff --git a/themes/clean-hugo/assets/css/_footer.scss b/themes/clean-hugo/assets/css/_footer.scss new file mode 100644 index 00000000..59a25b33 --- /dev/null +++ b/themes/clean-hugo/assets/css/_footer.scss @@ -0,0 +1,126 @@ +.site-footer { + width: 100%; + margin-top: $spacing-xl; + padding: $spacing-lg $spacing-sm $spacing-lg; + color: rgba(255, 255, 255, 0.9); + font-family: $font-family-heading; + font-size: 0.85rem; + line-height: 1.3rem; + background-color: color-mix(in srgb, var(--color-brand-purple) 92%, black); + + &__inner { + display: flex; + flex-direction: column; + align-items: center; + gap: $spacing-sm; + max-width: $container-max-width; + margin: 0 auto; + padding: 0 $spacing-sm; + } + + &__follow { + width: 100%; + text-align: center; + + .social-icons { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: $spacing-sm; + margin: 0; + padding: 0; + list-style: none; + } + + li { + display: inline-flex; + } + } + + &__social-link { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + width: 2.75rem; + height: 2.75rem; + text-decoration: none; + border-radius: $radius-md; + transition: color $transition-base; + + i { + font-size: 1.75rem; + color: color-mix(in srgb, var(--color-white) 42%, var(--color-soft-purple)); + transition: color $transition-base; + } + + &:hover i, + &:focus-visible i { + color: color-mix(in srgb, var(--color-white) 92%, var(--color-light-purple)); + } + + &[data-tooltip]::after { + content: attr(data-tooltip); + position: absolute; + bottom: calc(100% + 0.35rem); + left: 50%; + transform: translateX(-50%); + padding: 0.2rem 0.5rem; + font-family: $font-family-heading; + font-size: 0.7rem; + font-weight: 600; + line-height: 1.2; + white-space: nowrap; + color: var(--color-white); + background-color: color-mix(in srgb, var(--color-brand-purple) 75%, black); + border-radius: $radius-sm; + opacity: 0; + pointer-events: none; + transition: opacity $transition-fast; + } + + &:hover::after, + &:focus-visible::after { + opacity: 1; + } + + &:focus-visible { + outline: 2px solid var(--color-white); + outline-offset: 2px; + } + } + + &__copyright { + width: 100%; + max-width: 56.25rem; + margin: 0 auto; + padding: $spacing-sm; + text-align: left; + line-height: 1.35; + + p { + margin: 0 0 0.5em; + color: rgba(255, 255, 255, 0.82); + } + } + + &__mission { + font-size: 0.85rem; + line-height: 1.4; + } + + &__copyright a { + color: rgba(255, 255, 255, 0.82); + text-decoration: none; + + &:hover { + color: var(--color-white); + text-decoration: underline; + } + } + + &__copy { + margin: 0; + font-size: 0.68rem; + } +} diff --git a/themes/clean-hugo/assets/css/_gallery.scss b/themes/clean-hugo/assets/css/_gallery.scss new file mode 100644 index 00000000..7c46ff1c --- /dev/null +++ b/themes/clean-hugo/assets/css/_gallery.scss @@ -0,0 +1,172 @@ +/* Gallery Components - Using Mixins */ + +/* Shared container styles - max-width 80rem with responsive padding */ +.gallery-list-wrapper, +.gallery-grid-container, +.gallery-images { + @include container; +} + +.gallery-images { + @include responsive-padding($spacing-section, 1rem); +} + +/* Gallery grid elements with BEM nesting */ +.gallery-grid { + &__title { + @include responsive(font-size, 1.5rem, 1.875rem); + font-weight: 700; + margin-bottom: 1rem; + } + + &__category-title { + @include responsive(font-size, 1.25rem, 1.5rem); + font-weight: 600; + margin-bottom: 1rem; + text-transform: capitalize; + } + + &__section { + margin-bottom: $spacing-section; + } + + &__items { + @include grid-auto-fit; + } +} + +/* Gallery content wrapper - narrower max-width */ +.gallery-content { + @include container($container-narrow); + padding: 0 $fluid-container-padding-lg; +} + +/* Gallery header with nested elements */ +.gallery-header { + margin-bottom: 2rem; + + h2 { + @include responsive(font-size, 1.5rem, 1.875rem, 2.25rem); + margin-bottom: 0.5rem; + } + + .common-name { + font-size: 1.125rem; + margin-bottom: 1rem; + color: var(--color-gray-600); + } +} + +/* Markdown body */ +.gallery-description { + max-width: none; + + /* Hide h1 in gallery description - title should only be in hero */ + h1 { + display: none; + } +} + +/* Gallery images section heading */ +.gallery-images h2 { + @include responsive(font-size, 1.25rem, 1.5rem, 1.875rem); + margin-bottom: 1rem; +} + +/* Masonry layout using CSS columns */ +.gallery-masonry { + columns: 1; + column-gap: clamp(0.5rem, 2vw, 1.5rem); + padding: clamp(0.5rem, 2vw, 1.5rem); + + figure { + break-inside: avoid; + margin-bottom: clamp(0.25rem, 1vw, .5rem); + display: block; + } + + img { + width: 100%; + max-width: 100%; + height: auto; + display: block; + } + + a { + display: block; + &:hover img { + transform: scale(1.03); + } + } + + @media (min-width: $breakpoint-sm) { + columns: 2; + padding-inline: 0; + } + @media (min-width: $breakpoint-lg) { + columns: 3; + } + + img { + width: 100%; + height: auto; + display: block; + border-radius: $radius-md; + transition: transform $transition-base ease-out; + cursor: zoom-in; + } + + figcaption { + display: block; + } +} + +.gallery-caption { + padding: 0.625rem; + font-size: 0.875rem; + color: var(--color-gray-700); +} + +/* Gallery card component with BEM nesting */ +.gallery-card { + position: relative; + display: flex; + flex-direction: column; + width: 100%; + max-width: 340px; + border: 1px solid var(--color-gray-200); + border-radius: $radius-lg; + overflow: hidden; + background-color: var(--color-white); + box-shadow: $shadow-md; + transition: box-shadow $transition-base ease-out; + + &__link { + display: block; + + &:focus { + @include focus-ring; + } + } + + &__image { + @include image-zoom; + width: 100%; + height: 10rem; + } + + &__content { + display: flex; + flex-direction: column; + gap: 0.75rem; + padding: 1.5rem; + } + + &__title { + font-family: $font-family-heading; + font-weight: 700; + font-size: 1.125rem; + padding: 0.5rem 0.75rem; + color: var(--color-gray-900); + } +} diff --git a/themes/clean-hugo/assets/css/_hero.scss b/themes/clean-hugo/assets/css/_hero.scss new file mode 100644 index 00000000..4b576dcd --- /dev/null +++ b/themes/clean-hugo/assets/css/_hero.scss @@ -0,0 +1,152 @@ +/* Hero section components */ + +.hero { + padding: 0.5rem 0; + @include flex-center; + overflow: hidden; + margin-bottom: 3rem; + background-color: var(--color-hero-bg); + width: 100%; + max-width: 100vw; + + /* Direct child .container gets additional padding */ + > .container { + width: 100%; + @include responsive(padding-top, 0.875rem, 2rem); + @include responsive(padding-bottom, 0.875rem, 2rem); + } + + &__grid { + display: grid; + @include responsive(gap, 1.5rem, 2rem); + align-items: center; + + @media (min-width: $breakpoint-md) { + grid-template-columns: repeat(12, 1fr); + } + } + + &__content { + order: 2; + color: var(--color-white); + + @media (min-width: $breakpoint-md) { + order: 1; + grid-column: span 12; + } + } + + &__title { + @include responsive(font-size, 2.25rem, 3.75rem); + @include responsive(margin-bottom, 1rem, 1.5rem); + font-weight: 700; + color: white; + + @media (min-width: $breakpoint-sm) { + font-size: 3rem; + } + } + + &__subtitle { + @include responsive(font-size, 1.25rem, 1.875rem); + @include responsive(margin-bottom, 1rem, 1.5rem); + font-weight: 600; + color: white; + + @media (min-width: $breakpoint-sm) { + font-size: 1.5rem; + } + } + + &__excerpt { + @include responsive(font-size, 1rem, 1.25rem); + @include responsive(line-height, 1.5, 1.6); + color: white; + + @media (min-width: $breakpoint-sm) { + font-size: 1.125rem; + } + } + + &__actions { + @include responsive(margin-top, 1.25rem, 1.75rem); + + &.btn-group { + @media (max-width: ($breakpoint-sm - 0.02px)) { + flex-direction: row; + flex-wrap: wrap; + + .btn { + flex: 1 1 auto; + min-width: 0; + max-width: 100%; + } + } + } + } + + &__image-wrapper { + order: 1; + display: flex; + justify-content: center; + + @media (min-width: $breakpoint-md) { + order: 2; + grid-column: span 4; + justify-content: end; + } + } + + &__image-container { + width: clamp(8rem, 25vw, 10rem); + height: clamp(8rem, 25vw, 10rem); + border-radius: $radius-full; + overflow: hidden; + border: 8px solid var(--color-white); + box-shadow: $shadow-2xl; + + @media (min-width: $breakpoint-sm) { + width: 12rem; + height: 12rem; + } + + @media (min-width: $breakpoint-md) { + width: 14rem; + height: 14rem; + } + + @media (min-width: $breakpoint-lg) { + width: 16rem; + height: 16rem; + } + } + + &__image { + width: 100%; + height: 100%; + object-fit: cover; + } +} + +/* Square image variant for gallery/plant pages */ +.hero__image-container-square { + border-radius: $radius-md; + overflow: hidden; + border: 4px solid var(--color-white); + box-shadow: $shadow-2xl; + margin-inline: 0; + width: 260px; + + @media (min-width: $breakpoint-sm) { + margin-inline: 1rem; + } + + @media (min-width: $breakpoint-md) { + width: 340px; + margin-inline: 2rem; + } + + @media (min-width: $breakpoint-lg) { + width: 400px; + } +} diff --git a/themes/clean-hugo/assets/css/_intro-section.scss b/themes/clean-hugo/assets/css/_intro-section.scss new file mode 100644 index 00000000..43571b06 --- /dev/null +++ b/themes/clean-hugo/assets/css/_intro-section.scss @@ -0,0 +1,22 @@ +/* Intro Section Component */ +.intro-section { + background-color: transparent; + @include responsive(padding, 1.75rem 0, 2.25rem 0, 3rem 0); + + .container div { + text-align: center; + + /* Intentionally larger paragraphs for intro sections */ + p { + @include responsive(font-size, 1.25rem, 1.5rem); + line-height: 1.625; + color: var(--color-gray-700); + font-weight: 400; + } + + strong { + color: var(--color-gray-900); + font-weight: 600; + } + } +} diff --git a/themes/clean-hugo/assets/css/_learn-more.scss b/themes/clean-hugo/assets/css/_learn-more.scss new file mode 100644 index 00000000..5b3f1aa8 --- /dev/null +++ b/themes/clean-hugo/assets/css/_learn-more.scss @@ -0,0 +1,60 @@ + .learn-more { + margin: 3rem 0; + border-radius: $radius-xl; + padding: 2rem; + box-shadow: $shadow-lg; + background-color: var(--color-gray-50); + } + + .learn-more__header { + @include flex-center; + gap: 0.75rem; + margin-bottom: 1.5rem; + justify-content: flex-start; + } + + .learn-more__title { + font-size: 1.5rem; + font-weight: 700; + margin: 0; + color: var(--color-gray-900); + + i { + color: var(--color-gray-900); + } + } + + .learn-more__list { + list-style: none; + padding: 0; + margin: 0; + + > li + li { + margin-top: 1rem; + } + } + + .learn-more__item { + a { + @include flex-center; + gap: 1rem; + text-decoration: none; + transition: color $transition-base; + color: var(--color-gray-900); + justify-content: flex-start; + + &:hover, + &:focus { + color: var(--color-link); + } + } + } + + .learn-more__item-text { + font-size: 1.125rem; + font-weight: 600; + + i { + margin-right: 0.5rem; + } + } diff --git a/themes/clean-hugo/assets/css/_mixins.scss b/themes/clean-hugo/assets/css/_mixins.scss new file mode 100644 index 00000000..cbebf82c --- /dev/null +++ b/themes/clean-hugo/assets/css/_mixins.scss @@ -0,0 +1,231 @@ +/* Card shell — border, radius, shadow, background (no motion) */ +@mixin card-surface( + $radius: $radius-lg, + $border: 1px solid var(--color-gray-200), + $shadow: $shadow-sm, + $bg: var(--color-white) +) { + border-radius: $radius; + border: $border; + box-shadow: $shadow; + background-color: $bg; +} + +/* Card base — surface + lift/shadow on hover */ +@mixin card-base( + $radius: $radius-lg, + $border: 1px solid var(--color-gray-200), + $shadow: $shadow-sm, + $bg: var(--color-white), + $hover-lift: -4px, + $hover-shadow: $shadow-xl +) { + @include card-surface($radius, $border, $shadow, $bg); + transition: transform $transition-base ease-in-out, box-shadow $transition-base ease-in-out; + + &:hover { + transform: translateY($hover-lift); + box-shadow: $hover-shadow; + } +} + +/* Base heading / prose steps (mobile → md → lg) */ +@mixin type-scale-3($mobile, $tablet, $desktop) { + font-size: $mobile; + + @media (min-width: $breakpoint-md) { + font-size: $tablet; + } + + @media (min-width: $breakpoint-lg) { + font-size: $desktop; + } +} + +/* Body text: mobile + md only */ +@mixin type-scale-md($mobile, $tablet) { + font-size: $mobile; + + @media (min-width: $breakpoint-md) { + font-size: $tablet; + } +} +/** + * Reusable SCSS Mixins - Mobile First + * Base styles target mobile (320px+), breakpoints enhance for larger screens + */ + +/* Container mixin - centered with max-width and responsive padding */ +@mixin container($max-width: $container-max-width, $padding-mobile: 0.75rem, $padding-tablet: 1.5rem) { + max-width: $max-width; + margin: 0 auto; + padding: 0 $padding-mobile; + + @media (min-width: $breakpoint-md) { + padding: 0 $padding-tablet; + } +} + +/* Focus ring mixin - consistent focus states */ +@mixin focus-ring($color: var(--color-primary)) { + outline: none; + box-shadow: 0 0 0 2px var(--color-white), 0 0 0 4px $color; +} + +/* Card hover effect - lift and shadow on hover */ +@mixin card-hover($lift: -2px, $shadow: $shadow-xl) { + transition: box-shadow $transition-base ease-in-out, transform $transition-base ease-in-out; + + &:hover { + transform: translateY($lift); + box-shadow: $shadow; + } +} + +/* Responsive property - mobile, tablet, desktop values */ +@mixin responsive($property, $mobile, $tablet: null, $desktop: null) { + #{$property}: $mobile; + + @if $tablet { + @media (min-width: $breakpoint-md) { + #{$property}: $tablet; + } + } + + @if $desktop { + @media (min-width: $breakpoint-lg) { + #{$property}: $desktop; + } + } +} + +/* Responsive padding - mobile base with optional tablet/desktop values */ +@mixin responsive-padding($mobile-y: 1.5rem, $mobile-x: 0.75rem, $tablet-y: null, $tablet-x: 1.5rem) { + padding: $mobile-y $mobile-x; + + @if $tablet-y and $tablet-x { + @media (min-width: $breakpoint-md) { + padding: $tablet-y $tablet-x; + } + } @else if $tablet-x { + @media (min-width: $breakpoint-md) { + padding-left: $tablet-x; + padding-right: $tablet-x; + } + } +} + +/* Image hover zoom effect */ +@mixin image-zoom($scale: 1.1, $duration: $transition-slow) { + overflow: hidden; + + img { + transition: transform $duration ease-out; + } + + &:hover img { + transform: scale($scale); + } +} + +/* Truncate text with ellipsis */ +@mixin truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +/* Line clamp - limit text to N lines */ +@mixin line-clamp($lines: 3) { + display: -webkit-box; + -webkit-line-clamp: $lines; + -webkit-box-orient: vertical; + overflow: hidden; +} + +/* Stretched link - make entire card clickable */ +@mixin stretched-link { + &::after { + content: ""; + position: absolute; + inset: 0; + z-index: 10; + } +} + +/* Flexbox centering */ +@mixin flex-center { + display: flex; + align-items: center; + justify-content: center; +} + +/* Grid auto-fit columns */ +@mixin grid-auto-fit($min-width: 250px, $gap: 1.5rem) { + display: grid; + gap: $gap; + grid-template-columns: repeat(auto-fill, minmax($min-width, 1fr)); +} + +/* Responsive grid columns */ +@mixin responsive-grid($mobile: 1, $tablet: 2, $desktop: 3, $gap: 2rem) { + display: grid; + gap: $gap; + grid-template-columns: repeat($mobile, 1fr); + + @media (min-width: $breakpoint-md) { + grid-template-columns: repeat($tablet, 1fr); + } + + @media (min-width: $breakpoint-lg) { + grid-template-columns: repeat($desktop, 1fr); + } +} + +/* Custom scrollbar styling */ +@mixin custom-scrollbar($width: 0.375rem, $track-color: var(--color-gray-200), $thumb-color: var(--color-gray-600)) { + &::-webkit-scrollbar { + width: $width; + } + + &::-webkit-scrollbar-track { + background-color: $track-color; + border-radius: $radius-sm; + } + + &::-webkit-scrollbar-thumb { + background-color: $thumb-color; + border-radius: $radius-sm; + + &:hover { + background-color: var(--color-gray-700); + } + } +} + +/* Mobile-first font sizing - base size with optional scaling */ +@mixin fluid-font($mobile-size, $desktop-size: null) { + font-size: $mobile-size; + + @if $desktop-size { + @media (min-width: $breakpoint-lg) { + font-size: $desktop-size; + } + } +} + +/* Stack to row - mobile stacks, desktop horizontal */ +@mixin stack-to-row($gap: 1rem, $breakpoint: $breakpoint-md) { + display: flex; + flex-direction: column; + gap: $gap; + + @media (min-width: $breakpoint) { + flex-direction: row; + } +} + +/* Mobile safe area - accounts for notches/home indicators */ +@mixin mobile-safe-padding($padding: 1rem) { + padding: max($padding, env(safe-area-inset-top)) max($padding, env(safe-area-inset-right)) max($padding, env(safe-area-inset-bottom)) max($padding, env(safe-area-inset-left)); +} diff --git a/themes/clean-hugo/assets/css/_navigation.scss b/themes/clean-hugo/assets/css/_navigation.scss new file mode 100644 index 00000000..4d5bcb35 --- /dev/null +++ b/themes/clean-hugo/assets/css/_navigation.scss @@ -0,0 +1,301 @@ +/* Site navigation */ +.site-nav { + border-bottom: 1px solid var(--color-gray-200); + position: relative; + background-color: var(--color-white); + z-index: 1000; +} + +.site-nav__container { + max-width: $container-max-width; + margin: 0 auto; + padding: 0.75rem; + display: flex; + justify-content: space-between; + align-items: center; + + @media (min-width: $breakpoint-md) { + padding: 1rem; + } +} + +.site-nav__brand { + font-size: 1.5rem; + font-weight: 700; + color: var(--color-gray-900); + text-decoration: none; + + &:hover { + color: var(--color-link); + } + + &:focus { + color: var(--color-link); + outline: 2px solid var(--color-link); + outline-offset: 2px; + } + + &--logo { + display: inline-flex; + align-items: center; + gap: 0.5rem; + font-size: 1rem; + font-weight: 600; + } +} + +.site-nav__logo { + display: block; + width: auto; + height: clamp(2.75rem, 5vw, 3.25rem); + object-fit: contain; + + @media (min-width: $breakpoint-md) { + height: clamp(3rem, 4.5vw, 3.75rem); + } +} + +/* Hamburger menu toggle button */ +.site-nav__toggle { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + width: 2.5rem; + height: 2.5rem; + padding: 0.5rem; + border: 1px solid var(--color-gray-200); + border-radius: 0.25rem; + background-color: transparent; + cursor: pointer; + transition: background-color 0.2s; + flex-shrink: 0; + + &:hover { + background-color: var(--color-gray-50); + } + + &:focus { + outline: none; + box-shadow: 0 0 0 2px var(--color-link), 0 0 0 4px var(--color-white); + } + + &[aria-expanded="true"] { + .site-nav__toggle-icon { + &:nth-child(1) { + transform: rotate(45deg) translate(0.25rem, 0.25rem); + } + + &:nth-child(2) { + opacity: 0; + } + + &:nth-child(3) { + transform: rotate(-45deg) translate(0.25rem, -0.25rem); + } + } + } +} + +@media (min-width: $breakpoint-md) { + .site-nav__toggle { + display: none; + } +} + +.site-nav__toggle-icon { + display: block; + width: 1.25rem; + height: 0.125rem; + margin-bottom: 0.25rem; + background-color: var(--color-gray-900); + transition: all 0.2s; + + &:last-child { + margin-bottom: 0; + } +} + +/* Navigation menu */ +.site-nav__menu { + display: none; + position: absolute; + top: 100%; + left: 0; + right: 0; + flex-direction: column; + background-color: white; + border-top: 1px solid var(--color-gray-200); + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); + padding-block: 1rem; + + &[aria-expanded="true"], + &.site-nav__menu--open { + display: flex; + } +} + +@media (min-width: $breakpoint-md) { + .site-nav__menu { + display: flex; + position: relative; + top: auto; + flex-direction: row; + align-items: center; + gap: 1.5rem; + background-color: transparent; + border-top: 0; + box-shadow: none; + padding: 0; + } +} + +.site-nav__link { + padding: 0.5rem 1rem; + font-size: 1.125rem; + font-weight: 500; + transition: color 0.2s; + display: block; + color: var(--color-gray-900); + text-decoration: none; + + &:hover { + color: var(--color-link); + } + + &:focus { + color: var(--color-link); + outline: none; + box-shadow: 0 0 0 2px var(--color-link), 0 0 0 4px var(--color-white); + } +} + +@media (min-width: $breakpoint-md) { + .site-nav__link { + display: inline-block; + } +} + +/* Dropdown menu */ +.site-nav__dropdown { + position: relative; +} + +.site-nav__link--dropdown { + display: flex; + align-items: center; + gap: 0.5rem; + background: none; + border: none; + cursor: pointer; + font-family: inherit; + + i { + font-size: 0.75rem; + transition: transform 0.2s; + } + + /* Icon rotation when dropdown is open (mobile) */ + &[aria-expanded="true"] i { + transform: rotate(180deg); + } +} + +/* Desktop hover behavior */ +@media (min-width: $breakpoint-md) { + .site-nav__dropdown:hover, + .site-nav__dropdown:focus-within { + .site-nav__link--dropdown i { + transform: rotate(180deg); + } + + .site-nav__dropdown-menu { + display: block; + } + } +} + +.site-nav__dropdown-menu { + display: none; + padding-left: 0; + padding-top: 0.5rem; + list-style: none; + padding-right: 0; + margin: 0; + + &.site-nav__dropdown-menu--open { + display: block; + } + + li { + width: 100%; + } +} + +@media (min-width: $breakpoint-md) { + .site-nav__dropdown-menu { + position: absolute; + top: calc(100% + 0.5rem); + left: 0; + background-color: white; + border: 1px solid var(--color-gray-200); + border-radius: 0.5rem; + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); + padding: 0.5rem 0; + z-index: 50; + min-width: 200px; + } + + /* Create an invisible bridge to prevent hover state loss */ + .site-nav__dropdown-menu::before { + content: ''; + position: absolute; + top: -0.5rem; + left: 0; + right: 0; + height: 0.5rem; + } +} + +.site-nav__dropdown-link { + padding: 0.75rem 1rem; + font-size: 1rem; + font-weight: 500; + transition: background-color 0.3s ease, color 0.3s ease; + display: block; + width: 100%; + color: var(--color-gray-900); + text-decoration: none; + border-radius: 0.25rem; + background-color: transparent; + + i { + margin-left: 0.375rem; + font-size: 0.75rem; + } + + &:hover, + &:focus { + color: var(--color-gray-900); + background-color: var(--color-gray-200); + outline: none; + } +} + +/* On mobile, make dropdown links indent slightly for hierarchy */ +@media (max-width: 767px) { + .site-nav__dropdown-link { + padding-left: 2rem; + } +} + +/* Navigation CTA Button - uses base button system */ +.site-nav__button { + /* Navigation-specific positioning */ + margin-top: 1rem; + + @media (min-width: $breakpoint-md) { + margin-top: 0; + margin-left: 1rem; + } +} diff --git a/themes/clean-hugo/assets/css/_packages.scss b/themes/clean-hugo/assets/css/_packages.scss new file mode 100644 index 00000000..10c572c2 --- /dev/null +++ b/themes/clean-hugo/assets/css/_packages.scss @@ -0,0 +1,233 @@ + /* Packages Page Layout */ + + .packages-page__content { + width: 100%; + /* Child elements use .container utility class */ + } + + .packages-page__partner-nav { + width: 100%; + padding: 1.5rem 0; + background-color: var(--color-primary-light); + /* Child div uses .container utility class */ + } + + .packages-page__controls { + width: 100%; + padding: 2rem 0; + margin-bottom: 2rem; + background-color: var(--color-gray-50); + /* Child div uses .container utility class */ + } + + .packages-page__section { + margin-bottom: 4rem; + /* Child div uses .container utility class */ + } + + /* Archived packages — reuses .blog-archives full-bleed band from _blog.scss */ + .packages-page__archives { + margin-bottom: 4rem; + + .intro p { + margin: 0.75rem 0 0; + max-width: 42rem; + color: var(--color-gray-700); + line-height: 1.6; + } + + .packages-grid { + margin-top: 0; + } + } + + .packages-page__empty { + padding: 3rem 0; + text-align: center; + /* Uses .container utility class in template */ + } + + /* Package Filters */ + .packages-filters { + margin-bottom: 2rem; + + input { + width: 100%; + max-width: 28rem; + padding: 0.5rem 1rem; + font-size: 1.125rem; + border: 1px solid var(--color-gray-200); + border-radius: $radius-md; + margin-bottom: 1rem; + + &:focus { + outline: none; + box-shadow: 0 0 0 2px var(--color-primary); + border-color: var(--color-primary); + } + } + + > div { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + + button { + padding: 0.5rem 1rem; + border-radius: $radius-md; + border: 1px solid var(--color-gray-200); + font-weight: 500; + transition: all $transition-base; + background-color: var(--color-gray-200); + color: var(--color-gray-700); + + &:hover { + background-color: var(--color-gray-200); + transform: translateY(-1px); + } + + &.is-checked { + background-color: var(--color-primary); + border-color: var(--color-primary-dark); + color: white; + } + } + } + } + + /* Package Grid */ + .packages-grid { + @include responsive-grid($mobile: 1, $tablet: 2, $desktop: 3, $gap: 1.5rem); + margin-top: 3rem; + } + + /* Package Card */ + .package_card { + display: flex; + flex-direction: column; + + > div { + border-radius: $radius-md; + border: 1px solid var(--color-gray-200); + border-top: 4px solid var(--color-primary-dark); + box-shadow: $shadow-sm; + padding: 1.5rem; + display: flex; + flex-direction: column; + flex: 1; + transition: all $transition-base; + background-color: var(--color-white); + + &:hover { + transform: $card-hover-transform; + box-shadow: $shadow-xl; + } + + /* Title - Card-specific: smaller than base h3 for card layout */ + > h3 { + font-size: 1.25rem; + font-weight: 600; + margin-bottom: 0.75rem; + color: var(--color-gray-900); + } + + /* Meta section (stars, etc) */ + > .package_card__meta { + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 1rem; + font-size: 0.875rem; + color: var(--color-gray-600); + i { color: var(--color-gray-600); } + } + + /* Description */ + > p { + flex-grow: 1; + margin-bottom: 1rem; + color: var(--color-gray-700); + line-height: 1.6; + } + + /* Links */ + > ul { + list-style: none; + margin: 0; + padding: 0; + padding-top: 1rem; + margin-top: auto; + border-top: 1px solid var(--color-gray-200); + + li { + margin-bottom: 0.5rem; + + a { + display: inline-flex; + align-items: center; + gap: 0.5rem; + text-decoration: none; + color: var(--color-primary-dark); + transition: color $transition-base ease; + + &:hover { color: var(--color-link-hover); } + i { font-size: 0.875rem; } + + /* Partner badge styling */ + img.partner-badge { + height: 1.25rem; + vertical-align: middle; + margin-left: 0.25rem; + } + } + } + } + + /* Archived badge */ + .package_card__archived { + display: inline-flex; + align-items: center; + gap: 0.5rem; + color: var(--color-gray-700); + font-style: italic; + } + } + } + + /* Partner Navigation Button */ + .partner-button { + display: inline-flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem 1.5rem; + border-radius: $radius-md; + font-weight: 600; + transition: all $transition-base; + text-decoration: none; + background-color: white; + border: 2px solid var(--color-gray-200); + color: var(--color-gray-900); + + &:hover { + box-shadow: $shadow-lg; + transform: translateY(-2px); + border-color: var(--color-primary); + } + + img { + height: 1.25rem; + } + + span { + font-size: 1rem; + } + + &--astropy { + border-color: #FF8C00; + + &:hover { + background-color: #FFF5E6; + border-color: #FF8C00; + } + } + } diff --git a/themes/clean-hugo/assets/css/_people.scss b/themes/clean-hugo/assets/css/_people.scss new file mode 100644 index 00000000..513eadf4 --- /dev/null +++ b/themes/clean-hugo/assets/css/_people.scss @@ -0,0 +1,208 @@ + .people-page__content { + width: 100%; + } + + .people-page__controls { + width: 100%; + padding: 2rem 0; + margin-bottom: 2rem; + background-color: var(--color-gray-50); + } + + .people-page__section { + margin-bottom: 4rem; + } + + .people-page__empty { + padding: 3rem 0; + text-align: center; + } + + .people-filters { + margin-bottom: 2rem; + + input { + width: 100%; + max-width: 28rem; + padding: 0.5rem 1rem; + font-size: 1.125rem; + border: 1px solid var(--color-gray-200); + border-radius: $radius-md; + margin-bottom: 1rem; + + &:focus { + outline: none; + box-shadow: 0 0 0 2px var(--color-primary); + border-color: var(--color-primary); + } + } + + > div { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + + button { + padding: 0.5rem 1rem; + border-radius: $radius-md; + border: 1px solid var(--color-gray-200); + font-weight: 500; + transition: all $transition-base; + background-color: var(--color-gray-200); + color: var(--color-gray-700); + + &:hover { + background-color: var(--color-gray-200); + transform: translateY(-1px); + } + + &.is-checked { + background-color: var(--color-primary); + border-color: var(--color-primary-dark); + color: white; + } + } + } + } + + .people-grid { + display: grid; + gap: 1rem; + margin-top: 3rem; + grid-template-columns: 1fr; + + @media (min-width: $breakpoint-sm) { + grid-template-columns: repeat(2, 1fr); + } + + @media (min-width: 1000px) { + grid-template-columns: repeat(3, 1fr); + } + + @media (min-width: 1246px) { + grid-template-columns: repeat(4, 1fr); + } + + @media (min-width: $breakpoint-2xl) { + grid-template-columns: repeat(6, 1fr); + } + } + + .people_card { + display: flex; + flex-direction: column; + + > div { + border-radius: $radius-md; + border: 1px solid var(--color-gray-200); + box-shadow: $shadow-sm; + display: flex; + flex-direction: column; + flex: 1; + transition: all $transition-base; + background-color: var(--color-white); + overflow: hidden; + + &:hover { + transform: $card-hover-transform; + box-shadow: $shadow-xl; + } + } + } + + .people_card__image { + width: 100%; + overflow: hidden; + aspect-ratio: 1; + background-color: var(--color-gray-200); + + img { + width: 100%; + height: 100%; + object-fit: cover; + } + } + + .people_card__content { + padding: 1rem; + display: flex; + flex-direction: column; + flex-grow: 1; + + h3 { + font-size: 1.125rem; + font-weight: 600; + margin-bottom: 0.375rem; + color: var(--color-gray-900); + + a { + text-decoration: none; + color: inherit; + + &:hover { + color: var(--color-link); + } + } + } + } + + .people_card__title { + font-size: 0.75rem; + margin-bottom: 0.375rem; + color: var(--color-gray-600); + line-height: 1.4; + } + + .people_card__org { + font-size: 0.75rem; + margin-bottom: 0.75rem; + color: var(--color-gray-600); + font-style: italic; + } + + .people_card__social { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin-top: auto; + font-size: 0.75rem; + + a { + display: inline-flex; + align-items: center; + gap: 0.25rem; + text-decoration: none; + color: var(--color-gray-600); + transition: color $transition-base ease; + + &:hover { + color: var(--color-link); + } + + i { + font-size: 0.875rem; + } + } + } + + .people-grid-static { + display: grid; + gap: 1rem; + grid-template-columns: 1fr; + + @media (min-width: $breakpoint-sm) { + grid-template-columns: repeat(2, 1fr); + } + + @media (min-width: 1000px) { + grid-template-columns: repeat(3, 1fr); + } + + @media (min-width: 1246px) { + grid-template-columns: repeat(4, 1fr); + } + + @media (min-width: $breakpoint-2xl) { + grid-template-columns: repeat(5, 1fr); + } + } diff --git a/themes/clean-hugo/assets/css/_quotes.scss b/themes/clean-hugo/assets/css/_quotes.scss new file mode 100644 index 00000000..53786ff0 --- /dev/null +++ b/themes/clean-hugo/assets/css/_quotes.scss @@ -0,0 +1,155 @@ +/* + Quotes — change text size here. All quote types use the same size. +*/ +$quote-font-size: 2rem; + +/* Quote text */ +.content-main blockquote:not(.twitter-tweet) p, +.splash-page__content blockquote:not(.twitter-tweet) p, +.docs-content blockquote p, +.pullquote__text, +.admonition-quote__body, +.admonition-quote__body p { + font-family: $font-family-quote; + font-style: italic; + font-size: $quote-font-size; + line-height: 1.65; + color: var(--color-gray-600); +} + +/* Blockquote — left bar + background */ +.content-main blockquote:not(.twitter-tweet), +.splash-page__content blockquote:not(.twitter-tweet), +.docs-content blockquote { + border-left: 4px solid var(--color-primary); + padding: 0.5rem 0 0.5rem 1rem; + margin: 1rem 0; + background-color: var(--color-gray-50); + + p { + margin-bottom: 0; + } +} + +/* Pull quote — decorative mark, no sidebar */ +.pullquote { + --pullquote-accent: var(--color-primary); + + margin: 4.5rem 0; + padding: 0; + border: none; + background: none; + + &--magenta { --pullquote-accent: var(--color-accent-light); } + &--purple { --pullquote-accent: var(--color-accent); } + + &::before { + content: '\201C'; + display: block; + font-size: 4rem; + font-weight: 700; + color: var(--pullquote-accent); + line-height: 0; + margin-bottom: 0.15rem; + opacity: 0.85; + } + + &__text { + margin: 0; + } + + &__footer { + font-family: $font-family-body; + font-size: 1rem; + text-align: right; + font-style: italic; + margin: 1rem 0 0; + color: var(--color-gray-600); + } +} + +/* Admonition quote — colored callout box */ +.admonition-quote { + border-left-width: 4px; + border-radius: 0 1rem 1rem 0; + padding: 2rem; + box-shadow: $shadow-md; + border: 1px solid; + border-left-width: 4px; + margin: 3rem 0; + display: flex; + flex-direction: column; + gap: 0.5rem; + + @media (max-width: 640px) { + padding: 0.875rem; + gap: 0.375rem; + } + + &__mark::before { + content: '\201C'; + display: block; + font-size: 2.1rem; + font-weight: 700; + color: var(--base-color, var(--color-primary)); + line-height: 1; + opacity: 0.85; + } + + &__title { + font-weight: 600; + margin-bottom: 0.25rem; + font-size: clamp(1.3rem, 2vw, 1.4rem); + } + + &__body p:last-child { + margin-bottom: 0; + } + + &__footer { + font-family: $font-family-body; + margin: 0.75rem 0 0; + font-size: 0.95rem; + color: color-mix(in srgb, var(--base-color) 35%, black); + } + + &--info, + &--success, + &--warning, + &--danger, + &--note { + background-color: color-mix(in srgb, var(--base-color) 8%, white); + border-color: color-mix(in srgb, var(--base-color) 95%, black); + + .admonition-quote__title, + .admonition-quote__body { + color: color-mix(in srgb, var(--base-color) 25%, black); + } + + .admonition-quote__mark::before { + color: color-mix(in srgb, var(--base-color) 90%, black); + } + } + + &--info { --base-color: var(--color-admonition-info, #3B82F6); } + &--success { --base-color: var(--color-admonition-success, #22C55E); } + &--warning { --base-color: var(--color-admonition-warning, #EAB308); } + &--danger { --base-color: var(--color-admonition-danger, #EF4444); } + &--note { --base-color: var(--color-admonition-note, #6B7280); } +} + +/* Training testimonial cards */ +.testimonial-showcase__blockquote { + margin: 0; + padding: 0; + border: 0; + + p { + font-family: $font-family-quote; + font-style: italic; + font-size: $quote-font-size; + line-height: 1.55; + margin: 0 0 0.75rem; + color: var(--color-gray-700); + } +} diff --git a/themes/clean-hugo/assets/css/_shortcodes.scss b/themes/clean-hugo/assets/css/_shortcodes.scss new file mode 100644 index 00000000..b8815cbd --- /dev/null +++ b/themes/clean-hugo/assets/css/_shortcodes.scss @@ -0,0 +1,318 @@ + /* Metrics Bar */ + .metrics-bar { + width: 100%; + padding: 6rem 0; + margin: 3rem 0 5rem; + background-color: color-mix(in srgb, var(--color-primary) 8%, var(--color-gray-50)); + + /* Grid container */ + > div { + width: 100%; + padding: 0 1.5rem; + display: grid; + gap: 2rem; + grid-template-columns: repeat(2, 1fr); + max-width: $container-max-width; + margin: 0 auto; + + @media (min-width: $breakpoint-lg) { + grid-template-columns: repeat(4, 1fr); + } + + /* Items */ + > div { + text-align: center; + @include responsive(font-size, 1rem, 1.125rem); + line-height: 1.625; + color: var(--color-gray-700); + + /* Numbers */ + strong { + display: block; + @include responsive(font-size, 2.25rem, 3rem, 3.75rem); + @include responsive(margin-bottom, 0.5rem, 0.75rem); + font-weight: 900; + line-height: 1.25; + color: var(--color-gray-900); + letter-spacing: -0.02em; + } + } + } + } + + /* Two Card Row */ + .two-card-row { + padding: 1.5rem 0; + background-color: var(--color-gray-50); + } + + .two-card-row__container { + @include responsive-grid($mobile: 1, $tablet: 2, $desktop: 2, $gap: 1.5rem); + align-items: start; + max-width: $container-max-width; + margin: 0 auto; + padding: 0 $fluid-container-padding; + } + + /* Card Shortcode (used in two-card-row) - can use bg-card, bg-primary, or bg-secondary utilities */ + .card-shortcode { + width: 100%; + border-radius: $card-border-radius; + border: $card-border; + box-shadow: $card-shadow; + @include responsive-padding(1.5rem, 1.5rem, 2.5rem, 2.5rem); + height: 100%; + background-color: var(--color-white); + @include card-hover($lift: -4px, $shadow: $card-shadow-hover); + + @media (min-width: $breakpoint-md) { + width: auto; + } + + div { + display: flex; + flex-direction: column; + } + + .card-shortcode__icon { + font-size: $card-icon-size; + margin-bottom: 1rem; + + i { + color: inherit; + } + } + + h3 { + font-size: $card-heading-size; + font-weight: 800; + line-height: 1.3; + margin-bottom: 1.5rem; + color: var(--color-gray-900); + } + + div div:last-child { + font-size: $card-text-size; + line-height: $card-line-height; + color: $card-text-color; + + ul, ol { + padding-left: $card-list-padding; + + li { + font-size: $card-text-size; + line-height: $card-line-height; + margin-bottom: 0.5rem; + } + } + + a { + color: var(--color-link); + text-decoration: underline; + transition: color .2s ease; + + &:hover, + &:focus { + color: var(--color-link-hover); + } + } + + strong { + color: var(--color-gray-900); + font-weight: 600; + } + } + } + + /* Single Card Wide */ + .single-card-wide { + padding: 2rem 0 4rem; + margin: 2.5rem 0 4rem; + background-color: var(--color-gray-50); + + .container > div { + border-radius: $card-border-radius; + border: $card-border; + box-shadow: $card-shadow; + @include responsive-padding(1.5rem, 1.5rem, 2.5rem, 2.5rem); + background-color: color-mix(in srgb, var(--color-primary-dark) 12%, var(--color-primary-light)); + @include card-hover($lift: -4px, $shadow: $card-shadow-hover); + } + + .single-card-wide__icon { + font-size: $card-icon-size; + margin-bottom: 1rem; + + i { + color: inherit; + } + } + + h3 { + font-size: $card-heading-size; + font-weight: 800; + margin-bottom: 1.5rem; + color: var(--color-gray-900); + } + + .single-card-wide__body, + .container > div > div:last-child { + font-size: $card-text-size; + line-height: $card-line-height; + color: $card-text-color; + + ul { + padding-left: $card-list-padding; + + > li + li { + margin-top: 0.5rem; + } + } + + li { + font-size: $card-text-size; + line-height: $card-line-height; + } + + a:not(.btn) { + color: var(--color-link); + text-decoration: underline; + font-weight: 500; + transition: color .2s ease; + + &:hover, + &:focus { + color: var(--color-link-hover); + } + } + + .btn { + margin-top: 1.25rem; + } + + strong { + color: var(--color-gray-900); + font-weight: 600; + } + } + } + + /* YouTube Video Embed */ + .youtube-container { + margin: 2rem 0; + /* Automatically breaks out to full-width in blog posts via auto-detection */ + } + + /* Constrained width variant - stays within content width */ + .youtube-container--constrained { + width: auto !important; + position: static !important; + inset-inline: auto !important; + margin-inline: 0 !important; + } + + .youtube-wrapper { + position: relative; + padding-bottom: 56.25%; /* 16:9 aspect ratio */ + height: 0; + overflow: hidden; + } + + .youtube-iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; + } + + /* Section Heading Shortcode */ + .section-heading { + text-align: center; + padding: $fluid-space-lg 0 2rem; + margin-bottom: 2rem; + } + + .section-heading__title { + @include responsive(font-size, 2.25rem, 3rem, 3.75rem); + font-weight: 700; + margin-bottom: 1rem; + color: var(--color-gray-900); + + @media (min-width: $breakpoint-xl) { + font-size: 4.5rem; + } + } + + .section-heading__subtitle { + text-align: center; + @include responsive(font-size, 1.125rem, 1.25rem); + opacity: 0.8; + color: var(--color-gray-600); + } + + /* Theme Colors Shortcode Styling */ + .theme-colors { + @include grid-auto-fit($min-width: 280px, $gap: 1.5rem); + margin: 2rem 0; + + > div { + display: flex; + align-items: center; + gap: 1rem; + padding: 1rem; + border: 1px solid var(--color-gray-200); + border-radius: $radius-md; + background: var(--color-white); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + + /* Color swatch */ + > div:first-child { + width: 80px; + height: 80px; + border-radius: $radius-md; + border: 2px solid rgba(0, 0, 0, 0.1); + flex-shrink: 0; + } + + /* Info container */ + > div:last-child { + display: flex; + flex-direction: column; + gap: 0.25rem; + min-width: 0; + + strong { + font-size: 1rem; + color: var(--color-gray-900); + word-break: break-word; + } + + code { + font-size: 0.875rem; + font-family: $font-family-mono; + color: var(--color-gray-600); + background: var(--color-gray-200); + padding: 0.25rem 0.5rem; + border-radius: $radius-sm; + display: inline-block; + } + } + } + + @media (max-width: $breakpoint-sm) { + grid-template-columns: 1fr; + + > div { + align-items: flex-start; + text-align: left; + flex-wrap: wrap; + + > div:first-child { + width: 64px; + height: 64px; + } + } + } + } diff --git a/themes/clean-hugo/assets/css/_swoosh.scss b/themes/clean-hugo/assets/css/_swoosh.scss new file mode 100644 index 00000000..c50488a9 --- /dev/null +++ b/themes/clean-hugo/assets/css/_swoosh.scss @@ -0,0 +1,109 @@ +/** + * Swoosh sections: full-width blocks with optional curved SVG dividers. + * Section is always full viewport width; content is constrained in __content. + */ + +/* Full-bleed: section escapes any parent max-width so it's always full width */ +.swoosh-section { + width: 100vw; + position: relative; + left: 50%; + margin: 0 -50vw; + padding: 0; +} + +.swoosh-section__content { + max-width: 80rem; /* 1280px */ + margin-inline: auto; + padding: $fluid-space-2xl $fluid-container-padding; +} + +/* Background modifiers */ +.swoosh-section--white { + background-color: var(--color-white, #fff); +} + +.swoosh-section--purple { + background-color: var(--swoosh-bg-purple, #e1dfed); + --swoosh-fill-1: #bdb6d6; + --swoosh-fill-2: #e2dfed; +} + +.swoosh-section--green { + background-color: var(--swoosh-bg-green, #d4ebe3); + --swoosh-fill-1: #4e7064; /* darker green highlight (a bit lighter than black-mix) */ + --swoosh-fill-2: #d4ebe3; /* same light green as section, blends */ +} + +/* Divider theme: fill vars when divider is outside section (top/bottom partial) */ +.swoosh-section__divider--purple { + --swoosh-fill-1: #bdb6d6; + --swoosh-fill-2: #e2dfed; +} + +.swoosh-section__divider--green { + --swoosh-fill-1: #4e7064; /* darker green highlight (a bit lighter than black-mix) */ + --swoosh-fill-2: #d4ebe3; /* same light green as section, blends */ +} + +.swoosh-section__divider--white { + --swoosh-fill-1: var(--color-white, #fff); + --swoosh-fill-2: var(--color-white, #fff); +} + +/* Wrapper for standalone divider (above/below section): full width like section */ +.swoosh-section__divider-wrap { + width: 100vw; + position: relative; + left: 50%; + margin-inline: -50vw; +} + +/* Contained width (layout="docs"): fill content column only, no sidebar bleed */ +.swoosh-section--docs, +.swoosh-section__divider-wrap--docs { + width: 100%; + max-width: 100%; + inset-inline: auto; + margin-inline: 0; +} + +/* Divider: full width, contains SVG wave */ +.swoosh-section__divider { + position: relative; + width: 100%; + line-height: 0; +} + +.swoosh-section__divider--bottom { + margin-top: 0; +} + +.swoosh-section__divider--top { + margin-bottom: 0; +} + +.swoosh-section__svg { + display: block; + width: 100%; + height: auto; +} + +/* Wave paths: fill from CSS variables (set by section modifier) */ +.swoosh-section__wave--1 { + fill: var(--swoosh-fill-1); + opacity: 0.9; +} + +.swoosh-section__wave--2 { + fill: var(--swoosh-fill-2); +} + +/* Bottom divider: SVG sits at bottom of its wrapper */ +.swoosh-section__divider--bottom .swoosh-section__svg { + vertical-align: bottom; +} + +.swoosh-section__divider--top .swoosh-section__svg { + vertical-align: top; +} diff --git a/themes/clean-hugo/assets/css/_training-feature.scss b/themes/clean-hugo/assets/css/_training-feature.scss new file mode 100644 index 00000000..de04ebea --- /dev/null +++ b/themes/clean-hugo/assets/css/_training-feature.scss @@ -0,0 +1,101 @@ +/* Reusable training / promo strip (Params.training_feature + shortcode). */ + +.training-feature { + margin-bottom: $spacing-section-lg; + + @media (min-width: $breakpoint-md) { + margin-bottom: 3rem; + } + + &__card { + display: grid; + gap: $fluid-space-md; + align-items: center; + padding: $fluid-card-padding-md; + border-radius: $radius-xl; + background-color: color-mix(in srgb, var(--color-primary-light) 55%, var(--color-white)); + border: 1px solid color-mix(in srgb, var(--color-primary-dark) 12%, transparent); + + @media (min-width: $breakpoint-md) { + grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); + gap: $fluid-space-lg; + padding: $fluid-card-padding-lg; + } + } + + &__content { + min-width: 0; + } + + &__eyebrow { + margin: 0 0 0.5rem; + font-size: 0.75rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--color-primary-dark); + } + + &__badge { + margin: 0 0 0.75rem; + } + + &__badge-pill { + display: inline-block; + padding: 0.25rem 0.65rem; + font-size: 0.8125rem; + font-weight: 600; + color: var(--color-gray-700); + background-color: var(--color-gray-200); + border-radius: $radius-full; + } + + &__title { + margin: 0 0 0.75rem; + @include responsive(font-size, 1.5rem, 1.875rem, 2rem); + font-weight: 700; + line-height: 1.2; + color: var(--color-primary-dark); + } + + &__excerpt { + margin: 0 0 1rem; + @include responsive(font-size, 1rem, 1.0625rem); + line-height: 1.55; + color: var(--color-gray-700); + + p { + margin: 0 0 0.5rem; + + &:last-child { + margin-bottom: 0; + } + } + } + + &__actions { + margin: 0; + padding-top: 0.25rem; + } + + &__media { + min-width: 0; + justify-self: center; + width: 100%; + max-width: 22rem; + + @media (min-width: $breakpoint-md) { + max-width: none; + justify-self: end; + } + } + + &__image { + display: block; + width: 100%; + height: auto; + border-radius: $radius-lg; + object-fit: cover; + box-shadow: $shadow-md; + } +} diff --git a/themes/clean-hugo/assets/css/_training.scss b/themes/clean-hugo/assets/css/_training.scss new file mode 100644 index 00000000..b16b3035 --- /dev/null +++ b/themes/clean-hugo/assets/css/_training.scss @@ -0,0 +1,350 @@ +/* Training / learn pages — tutorials, university partnerships, testimonials */ + +.learn-page__tutorials { + margin-bottom: 0; + padding-bottom: 0.5rem; +} + +.tutorial-grid { + display: grid; + gap: 1.25rem; + grid-template-columns: 1fr; + margin-top: 1.5rem; + margin-bottom: 0; + + @media (min-width: $breakpoint-sm) { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + @media (min-width: $breakpoint-md) { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + @media (min-width: $breakpoint-xl) { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + + align-items: stretch; +} + +.tutorial-grid__card { + display: flex; + flex-direction: column; + height: 100%; + border: 1px solid var(--color-gray-200); + border-radius: $radius-md; + background-color: var(--color-white); + box-shadow: $shadow-sm; + transition: transform $transition-base ease, box-shadow $transition-base ease; + + &:hover, + &:focus-within { + transform: translateY(-0.125rem); + box-shadow: $shadow-lg; + } +} + +.tutorial-grid__body { + flex: 1 1 auto; + padding: 1.1rem 1rem 0.85rem; +} + +.tutorial-grid__title { + margin: 0 0 0.65rem; + font-size: 1.125rem; + font-weight: 600; + color: var(--color-gray-900); + line-height: 1.3; +} + +.tutorial-grid__excerpt { + margin: 0; + font-size: 0.9375rem; + line-height: 1.55; + color: var(--color-gray-700); +} + +.tutorial-grid__cta { + margin-top: auto; + border-radius: 0 0 $radius-md $radius-md; + justify-content: center; + gap: 0.5rem; + background-color: var(--color-brand-purple); + color: var(--color-white); + font-weight: 600; + text-decoration: none; + + &:hover, + &:focus { + background-color: var(--color-brand-purple-dark); + color: var(--color-white); + transform: translateY(-1px); + box-shadow: $shadow-md; + } + + .fa-magnifying-glass { + color: var(--color-white); + } +} + +.benefits-list { + list-style: none; + margin: 1.5rem 0 0; + padding: 0; + + li { + margin-bottom: 1.25rem; + padding-left: 0; + list-style: none; + + .fa-solid { + font-size: 1.1rem; + color: var(--color-accent); + margin-right: 0.4rem; + } + } +} + +.partnership-cards { + display: grid; + gap: 1.25rem; + grid-template-columns: 1fr; + margin: 2rem 0 1.5rem; + align-items: stretch; + + @media (min-width: $breakpoint-sm) { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + @media (min-width: $breakpoint-md) { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } +} + +.partnership-card { + display: flex; + flex-direction: column; + min-height: 100%; + padding: 1.1rem 1rem; + border: 1px solid color-mix(in srgb, var(--color-brand-purple) 18%, transparent); + border-radius: $radius-md; + background-color: var(--color-white); + box-shadow: $shadow-sm; + transition: transform $transition-base ease, box-shadow $transition-base ease; + + &:hover, + &:focus-within { + transform: translateY(-0.125rem); + box-shadow: $shadow-lg; + } + + &__title { + margin: 0.6rem 0 1.2rem; + color: var(--color-brand-purple); + font-size: 1.25rem; + font-weight: 600; + line-height: 1.25; + text-align: center; + } + + &__star { + color: var(--color-accent-light); + } + + p.partnership-card__price { + margin: 0 0 0.85rem; + color: var(--color-brand-purple); + font-size: 1.5rem; + font-weight: 700; + line-height: 1.2; + text-align: center; + } + + &__body { + flex: 1 1 auto; + display: flex; + flex-direction: column; + min-height: 0; + } + + &__main { + flex: 1 1 auto; + min-height: 0; + display: flex; + flex-direction: column; + } + + .partnership-card__body > p.partnership-card__price { + flex-shrink: 0; + margin-top: 0; + margin-bottom: 0.35rem; + } + + a.partnership-card__cta { + flex-shrink: 0; + align-self: stretch; + margin: 1rem 0 0; + text-align: center; + text-decoration: none; + } + + p.partnership-card__lede { + margin: 0 0 0.85rem; + color: var(--color-gray-700); + font-size: 0.9375rem; + line-height: 1.55; + } + + &__features { + list-style: none; + margin: 0; + padding: 0; + + li { + position: relative; + margin: 0 0 0.55rem; + padding-left: 1.3rem; + font-size: 0.875rem; + line-height: 1.5; + color: var(--color-gray-700); + list-style: none; + + &::before { + content: "✓"; + position: absolute; + left: 0; + top: 0.02rem; + color: var(--color-accent); + font-weight: 600; + } + + &:last-child { + margin-bottom: 0; + } + } + } + + &__divider { + width: 100%; + border: 0; + border-top: 1px solid color-mix(in srgb, var(--color-soft-purple) 95%, transparent); + margin: 1rem 0 0.7rem; + } + + p.partnership-card__subheader { + margin: 0.6rem 0 1.2rem; + color: color-mix(in srgb, var(--color-brand-purple) 55%, var(--color-soft-purple)); + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.08em; + text-transform: uppercase; + line-height: 1.4; + } +} + +.partnership-card--featured { + border-color: color-mix(in srgb, var(--color-primary-dark) 45%, transparent); + box-shadow: $shadow-md; +} + +.testimonial-showcase { + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 1.25rem; + max-width: 100%; +} + +.testimonial-showcase__featured { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; + margin: 0; + padding: 1.25rem 1.25rem 1.35rem; + border-radius: $radius-md; + background-color: var(--color-white); + box-shadow: $shadow-sm; + border: 1px solid color-mix(in srgb, var(--color-brand-purple) 12%, transparent); + text-align: left; + + @media (min-width: $breakpoint-sm) { + flex-direction: row; + align-items: flex-start; + gap: 1.5rem; + padding: 1.5rem 1.5rem 1.6rem; + } +} + +.testimonial-showcase__avatar-wrap { + flex-shrink: 0; +} + +.testimonial-showcase__avatar { + width: 7.5rem; + height: 7.5rem; + border-radius: $radius-full; + object-fit: cover; + display: block; + border: 3px solid color-mix(in srgb, var(--color-brand-purple) 18%, transparent); + box-sizing: border-box; +} + +.testimonial-showcase__featured-body { + flex: 1 1 auto; + min-width: 0; +} + +.testimonial-showcase__mark { + margin: 0 0 0.35rem; + line-height: 1; + color: var(--color-brand-purple); + + .fa-quote-left { + font-size: 1.5rem; + } + + &--compact { + color: var(--color-accent); + + .fa-quote-left { + font-size: 1.25rem; + } + } +} + +.testimonial-showcase__cite { + margin: 0; + font-size: 0.875rem; + line-height: 1.4; + font-style: normal; + font-weight: 600; + color: var(--color-gray-600); +} + +.testimonial-showcase__grid { + display: grid; + gap: 1.25rem; + grid-template-columns: 1fr; + + @media (min-width: $breakpoint-sm) { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +.testimonial-showcase__card { + margin: 0; + padding: 1.1rem 1rem 1.15rem; + border-radius: $radius-md; + background-color: var(--color-white); + box-shadow: $shadow-sm; + border: 1px solid color-mix(in srgb, var(--color-brand-purple) 12%, transparent); + border-top: 4px solid var(--color-accent); + text-align: left; +} + +.training-page__figure { + margin: 2rem auto; + max-width: 48rem; +} diff --git a/themes/clean-hugo/assets/css/_utilities.scss b/themes/clean-hugo/assets/css/_utilities.scss new file mode 100644 index 00000000..33ac367f --- /dev/null +++ b/themes/clean-hugo/assets/css/_utilities.scss @@ -0,0 +1,84 @@ +/* + Accessibility utilities: skip links. + Link is visually hidden by default and becomes visible on :focus + so keyboard users can jump to main content. +*/ + +.skip-links { + position: absolute; + z-index: 100; + margin: 0; + padding: 0; + list-style: none; + + ul { + margin: 0; + padding: 0; + list-style: none; + } + + li { + margin: 0; + } +} + +.skip-link__link { + position: absolute; + clip: rect(1px, 1px, 1px, 1px); + clip-path: inset(50%); + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + border: 0; + white-space: nowrap; + + &:focus { + position: fixed; + top: 0.5rem; + left: 0.5rem; + z-index: 10001; + clip: auto; + clip-path: none; + width: auto; + height: auto; + margin: 0; + padding: 0.75rem 1rem; + background: var(--color-white, #fff); + color: var(--color-link, #2563eb); + font-weight: 600; + text-decoration: none; + box-shadow: 0 0 0 2px currentColor; + border-radius: 0.25rem; + } +} + +/* + Print styles: hide non-content, keep focus on main content. +*/ +@media print { + .skip-links, + .site-nav, + .site-footer, + .docs-toggle, + .docs-scroll-btn, + .docs-sidebar, + button.site-nav__toggle { + display: none !important; + } + + body { + font-size: 12pt; + line-height: 1.4; + } + + a[href]::after { + content: none; + } + + main { + print-color-adjust: exact; + -webkit-print-color-adjust: exact; + } +} diff --git a/themes/clean-hugo/assets/css/_variables.scss b/themes/clean-hugo/assets/css/_variables.scss new file mode 100644 index 00000000..490a5ae6 --- /dev/null +++ b/themes/clean-hugo/assets/css/_variables.scss @@ -0,0 +1,151 @@ +/** + * Theme Variables - Mobile First + * Base values target mobile (320px+), use breakpoints to enhance + */ + +/* Typography — font names (@font-face) and stacks (never hardcode fonts elsewhere) */ +$font-name-body: 'Nunito Sans'; +$font-name-heading: 'Poppins'; +$font-name-quote: 'Lora'; + +$font-family-body: $font-name-body, 'ui-sans-serif', 'system-ui', '-apple-system', + 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial', sans-serif; +$font-family-heading: $font-name-heading, $font-name-body, 'ui-sans-serif', 'system-ui', + sans-serif; +$font-family-quote: $font-name-quote, 'Georgia', 'Times New Roman', serif; +$font-family-mono: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', + monospace; + +/* Breakpoints - min-width (mobile first) */ +$breakpoint-sm: 640px; /* Large phones / small tablets */ +$breakpoint-md: 768px; /* Tablets */ +$breakpoint-lg: 1024px; /* Desktop */ +$breakpoint-xl: 1280px; /* Large desktop */ +$breakpoint-2xl: 1536px; /* Extra large */ + +/* Container Max Widths */ +$container-max-width: 80rem; /* 1280px - standard container */ +$container-impact-wide: 96rem; /* 1536px - optional wide splash / impact card grid */ +$container-narrow: 56rem; /* 896px - content/blog posts */ +$container-wide: 42rem; /* 672px - narrow content */ + +/* Spacing - mobile base values */ +$spacing-xs: 0.5rem; /* 8px - minimal spacing */ +$spacing-sm: 1rem; /* 16px - small spacing */ +$spacing-md: 1.5rem; /* 24px - medium spacing */ +$spacing-lg: 2rem; /* 32px - large spacing */ +$spacing-xl: 3rem; /* 48px - extra large spacing */ +$spacing-section: 2rem; /* Mobile section padding */ +$spacing-section-lg: 3rem; /* Desktop section padding */ + +/* Fluid Spacing - Using clamp() for smooth mobile-first scaling */ +$fluid-space-xs: clamp(0.5rem, 1vw, 0.75rem); /* 8px → 12px */ +$fluid-space-sm: clamp(0.75rem, 2vw, 1.5rem); /* 12px → 24px */ +$fluid-space-md: clamp(1rem, 3vw, 2rem); /* 16px → 32px */ +$fluid-space-lg: clamp(1.5rem, 4vw, 3rem); /* 24px → 48px */ +$fluid-space-xl: clamp(2rem, 6vw, 4rem); /* 32px → 64px */ +$fluid-space-2xl: clamp(2rem, 8vw, 5rem); /* 32px → 80px */ +$fluid-space-3xl: clamp(2.5rem, 10vw, 6rem); /* 40px → 96px */ + +/* Fluid Container Padding */ +$fluid-container-padding: clamp(0.75rem, 3vw, 1.5rem); /* Container horizontal */ +$fluid-container-padding-lg: clamp(1rem, 4vw, 2rem); /* Narrow containers */ + +/* Fluid Card/Component Padding */ +$fluid-card-padding-sm: clamp(1rem, 3vw, 1.5rem); /* Small cards */ +$fluid-card-padding-md: clamp(1.25rem, 4vw, 2.5rem); /* Medium cards */ +$fluid-card-padding-lg: clamp(1.5rem, 5vw, 4rem); /* Large impact cards */ + +/* Border Radius */ +$radius-sm: 0.25rem; /* 4px */ +$radius-md: 0.5rem; /* 8px */ +$radius-lg: 1rem; /* 16px */ +$radius-xl: 1.5rem; /* 24px */ +$radius-full: 9999px; /* Fully rounded */ + +/* Outline button border widths (width only; use in `border: … solid …`) */ +$btn-bd-thin: 0.8px; /* hero on dark, .btn--secondary — may paint as 1px on some DPR */ +$btn-bd: 1px; /* .btn--outline-on-light */ + +/* Transitions */ +$transition-fast: 150ms; +$transition-base: 200ms; +$transition-slow: 300ms; +$transition-slower: 500ms; + +/* Shadows */ +$shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); +$shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); +$shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); +$shadow-xl: 0 10px 30px rgba(17, 24, 39, 0.08); +$shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25); + +/* Z-index scale */ +$z-dropdown: 50; +$z-sticky: 100; +$z-fixed: 200; +$z-overlay: 300; +$z-modal: 400; + +/* Card Typography - Shared across homepage content cards */ +/* (impact cards, two-card-row, single-card-wide) */ +$card-heading-size: clamp(1.7rem, 3vw, 1.875rem); /* H3 headings */ +$card-text-size: clamp(1.25rem, 2.5vw, 1.5rem); /* Paragraphs & list items */ +$card-list-padding: clamp(0.25rem, 2.5vw, 1.5rem); /* List padding-left - minimal on mobile */ +$card-text-color: var(--color-gray-700); /* Body text color */ +$card-line-height: 1.6; /* Text line height */ + +/* Card Layout & Styling - Shared styles for card components */ +$card-border-radius: $radius-lg; /* Card corner rounding */ +$card-border: 1px solid var(--color-gray-200); /* Card border */ +$card-shadow: $shadow-sm; /* Card shadow */ +$card-shadow-hover: $shadow-xl; /* Card shadow on hover */ +$card-hover-transform: translateY(-4px); /* Card lift on hover */ +$card-icon-size: clamp(2.25rem, 4vw, 3rem); /* Icon size in cards */ +$card-gap: clamp(1.25rem, 3vw, 2.5rem); /* Gap between cards in grid */ + +/* Listing card density tokens for blog/event archive cards */ +$listing-card-default: ( + padding: 1.5rem, + meta-font-size: 0.9375rem, + meta-gap: 0.75rem, + category-font-size: 0.75rem, + category-padding: 0.25rem 0.5rem, + title-font-size: 1.25rem, + title-line-height: 1.4, + excerpt-font-size: 1rem, + excerpt-line-height: 1.6, + read-more-font-size: 0.9375rem +); + +$listing-card-compact: ( + padding: 0.8rem 0.9rem, + meta-font-size: 0.65rem, + meta-gap: 0.4rem, + category-font-size: 0.55rem, + category-padding: 0.16rem 0.36rem, + title-font-size: 0.85rem, + title-line-height: 1.35, + excerpt-font-size: 0.7rem, + excerpt-line-height: 1.55, + read-more-font-size: 0.65rem +); + +/* Base HTML heading font sizes: mobile, tablet, desktop */ +$heading-font-sizes: ( + h1: 3rem 3.75rem 4.5rem, + h2: 2.25rem 2.25rem 3rem, + h3: 1.5rem 1.875rem 2.25rem, + h4: 1.25rem 1.5rem 1.875rem, + h5: 1.125rem 1.25rem 1.5rem, + h6: 1rem 1.125rem 1.25rem, +); + +$heading-meta: ( + h1: (weight: 700, margin-top: 0, margin-bottom: 0.5rem), + h2: (weight: 600, margin-top: 2.8rem, margin-bottom: 0.5rem), + h3: (weight: 600, margin-top: 2.3rem, margin-bottom: 0.5rem), + h4: (weight: 600, margin-top: 1.8rem, margin-bottom: 0.5rem), + h5: (weight: 600, margin-top: 1.55rem, margin-bottom: 0.5rem), + h6: (weight: 600, margin-top: 1.3rem, margin-bottom: 0.5rem), +); diff --git a/themes/clean-hugo/assets/css/site.scss b/themes/clean-hugo/assets/css/site.scss new file mode 100644 index 00000000..a754bfab --- /dev/null +++ b/themes/clean-hugo/assets/css/site.scss @@ -0,0 +1,275 @@ +/* +Breakpoints: +sm: 640px +md: 768px +lg: 1024px +xl: 1280px +2xl: 1536px +*/ + +/* Variables and Mixins - Import First */ +@import 'variables'; +@import 'mixins'; + +/* Button System */ +@import 'buttons'; + +/* Accessibility utilities (skip links) */ +@import 'utilities'; + +/* Base Styles */ + /* Universal box-sizing and overflow fix */ + *, *::before, *::after { + box-sizing: border-box; + } + + html { + overflow-x: hidden; + } + + /* + Self-hosted font declarations + Font files are in themes/clean-hugo/static/fonts/ + */ + + /* Nunito Sans variable font (body text) - regular/roman style */ + @font-face { + font-family: $font-name-body; + font-style: normal; + font-weight: 200 900; + font-display: swap; + src: url('../fonts/NunitoSans-VariableFont.woff2') format('woff2'); + } + + /* Nunito Sans variable font (body text) - italic style */ + @font-face { + font-family: $font-name-body; + font-style: italic; + font-weight: 200 900; + font-display: swap; + src: url('../fonts/NunitoSans-Italic-VariableFont.woff2') format('woff2'); + } + + /* Poppins (headings) */ + @font-face { + font-family: $font-name-heading; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('../fonts/Poppins-Light.woff2') format('woff2'); + } + + @font-face { + font-family: $font-name-heading; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('../fonts/Poppins-Regular.woff2') format('woff2'); + } + + @font-face { + font-family: $font-name-heading; + font-style: italic; + font-weight: 400; + font-display: swap; + src: url('../fonts/Poppins-Italic.woff2') format('woff2'); + } + + @font-face { + font-family: $font-name-heading; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url('../fonts/Poppins-Medium.woff2') format('woff2'); + } + + @font-face { + font-family: $font-name-heading; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url('../fonts/Poppins-SemiBold.woff2') format('woff2'); + } + + @font-face { + font-family: $font-name-heading; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('../fonts/Poppins-Bold.woff2') format('woff2'); + } + + /* Lora italic variable font (quotations) */ + @font-face { + font-family: $font-name-quote; + font-style: italic; + font-weight: 400 700; + font-display: swap; + src: url('../fonts/Lora-Italic-VariableFont_wght.woff2') format('woff2'); + } + + /* + CSS Variables for theme colors + All color variables are injected via inline + + {{/* Theme styles */}} + {{ $styles := resources.Get "css/site.scss" | toCSS | postCSS | minify | fingerprint }} + + + {{/* Chroma syntax highlighting CSS - generated with: hugo gen chromastyles --style=monokai */}} + + + {{/* GLightbox CSS for gallery feature */}} + {{ if .Site.Params.theme.enableGallery | default true }} + + {{ end }} + + {{/* Analytics */}} + {{ with .Site.Params.analytics.google }} + + + + {{ end }} + {{ with .Site.Params.analytics.plausible }} + + + {{ end }} + + {{/* AlpineJS for interactive components (packages filtering, etc.) */}} + + + {{/* Package filter component - loads immediately (no defer) to register listener before Alpine initializes */}} + + {{/* People filter component - loads immediately (no defer) to register listener before Alpine initializes */}} + + + + {{ partial "skip-link.html" . }} + + + +
+ {{ block "main" . }}{{ end }} +
+ {{ partial "footer.html" . }} + + {{/* Navigation bar toggle JavaScript */}} + + + {{ block "scripts" . }}{{ end }} + + diff --git a/themes/clean-hugo/layouts/_default/docs.html b/themes/clean-hugo/layouts/_default/docs.html new file mode 100644 index 00000000..7b67ce9c --- /dev/null +++ b/themes/clean-hugo/layouts/_default/docs.html @@ -0,0 +1,38 @@ +{{ define "main" }} +{{ $header := .Params.header | default dict }} +{{ $headerColor := $header.color | default "primaryDark" }} +{{ $headerTitle := $header.title | default .Title }} +{{ $isHex := hasPrefix $headerColor "#" }} +
+
+

{{ $headerTitle }}

+
+
+ +
+ + + +
+ + +
+ {{ with .Params.excerpt }}

{{ . }}

{{ end }} + {{ .Content }} + {{ partial "last-modified.html" . }} +
+ + +
+ + + +{{ end }} diff --git a/themes/clean-hugo/layouts/_default/list.html b/themes/clean-hugo/layouts/_default/list.html new file mode 100644 index 00000000..9b0c9e61 --- /dev/null +++ b/themes/clean-hugo/layouts/_default/list.html @@ -0,0 +1,17 @@ +{{ define "main" }} +
+

{{ .Title }}

+ {{ with .Content }} +
{{ . }}
+ {{ end }} + +
+ {{ range .Pages }} + + {{ end }} +
+
+{{ end }} diff --git a/themes/clean-hugo/layouts/_default/packages-list.html b/themes/clean-hugo/layouts/_default/packages-list.html new file mode 100644 index 00000000..8cd72c49 --- /dev/null +++ b/themes/clean-hugo/layouts/_default/packages-list.html @@ -0,0 +1,69 @@ +{{ define "main" }} + +{{ $pkgStats := partial "calculate-package-stats.html" . }} + +{{ partial "hero.html" . }} + +{{ $stats := slice + (printf "**%d** Packages Accepted" $pkgStats.total) + (printf "**%d** Published in JOSS" $pkgStats.joss) + (printf "**%d** Currently Active" $pkgStats.active) + (printf "**%d** Unique Maintainers" $pkgStats.maintainers) +}} +{{ partial "metrics-bar-render.html" (dict "stats" $stats) }} + +
+
+ {{ .Content }} +
+
+ +{{ if .Site.Data.packages }} + +
+ + + +
+
+ {{ partial "packages/filters.html" . }} +
+
+ +
+
+

pyOpenSci Accepted Packages

+ {{ partial "packages/grid.html" (dict "activeOnly" true) }} +
+
+ +
+
+
+

Archived Packages

+

+ Archived packages are packages that have successfully completed peer review + but are no longer actively maintained. +

+
+ {{ partial "packages/grid.html" (dict "activeOnly" false) }} +
+
+
+{{ else }} +
+

No package data found. Add packages to data/packages.yml to display them here.

+
+{{ end }} + +{{ end }} diff --git a/themes/clean-hugo/layouts/_default/single.html b/themes/clean-hugo/layouts/_default/single.html new file mode 100644 index 00000000..fe7d0240 --- /dev/null +++ b/themes/clean-hugo/layouts/_default/single.html @@ -0,0 +1,16 @@ +{{ define "main" }} + +{{ partial "hero.html" . }} + +
+ + {{ if and (not .Params.hero) (not .Params.hideDate) }} + {{/* Only show date at top for pages without hero sections */}} + + {{ end }} +
+ {{ .Content }} + {{ partial "last-modified.html" . }} +
+
+{{ end }} diff --git a/themes/clean-hugo/layouts/_default/splash.html b/themes/clean-hugo/layouts/_default/splash.html new file mode 100644 index 00000000..0a49254a --- /dev/null +++ b/themes/clean-hugo/layouts/_default/splash.html @@ -0,0 +1,9 @@ +{{ define "main" }} + +{{ partial "hero.html" . }} + +
+ {{ .Content }} +
+ +{{ end }} diff --git a/themes/clean-hugo/layouts/_default/taxonomy.html b/themes/clean-hugo/layouts/_default/taxonomy.html new file mode 100644 index 00000000..d3544777 --- /dev/null +++ b/themes/clean-hugo/layouts/_default/taxonomy.html @@ -0,0 +1,15 @@ +{{ define "main" }} +
+

{{ .Title | default "Topics" }}

+ + +
+{{ end }} diff --git a/themes/clean-hugo/layouts/_default/term.html b/themes/clean-hugo/layouts/_default/term.html new file mode 100644 index 00000000..cd56b1ef --- /dev/null +++ b/themes/clean-hugo/layouts/_default/term.html @@ -0,0 +1,15 @@ +{{ define "main" }} +
+

{{ .Title }}

+

Posts tagged "{{ .Title }}"

+ +
+ {{ range .Pages }} + + {{ end }} +
+
+{{ end }} diff --git a/themes/clean-hugo/layouts/blog/list.html b/themes/clean-hugo/layouts/blog/list.html new file mode 100644 index 00000000..b1b0c1bc --- /dev/null +++ b/themes/clean-hugo/layouts/blog/list.html @@ -0,0 +1,96 @@ +{{ define "main" }} +{{ partial "section-hero.html" . }} + +
+
+
+ + {{/* Get all blog posts, newest first */}} + {{ $allPosts := sort (where .Site.RegularPages "Type" "blog") "Date" "desc" }} + + {{/* Separate recent posts from archive posts */}} + {{ $recentPosts := slice }} + {{ $archivePosts := slice }} + {{ $cutoffDate := time "2025-01-01" }} + + {{ range $allPosts }} + {{ $isOld := le (.Date.Unix) ($cutoffDate.Unix) }} + {{ $hasNoImage := not .Params.image }} + {{ if and $isOld $hasNoImage }} + {{ $archivePosts = $archivePosts | append . }} + {{ else }} + {{ $recentPosts = $recentPosts | append . }} + {{ end }} + {{ end }} + + {{/* Empty state - no posts */}} + {{ if eq (len $allPosts) 0 }} +
+

No blog posts yet. Check back soon!

+
+ {{ else }} + + {{/* Featured post is always the most recent (first post from recent posts) */}} + {{ $featuredPost := false }} + {{ $sidebarPosts := slice }} + {{ $remainingPosts := slice }} + + {{ if gt (len $recentPosts) 0 }} + {{ $featuredPost = index $recentPosts 0 }} + {{ $sidebarCount := .Site.Params.blog.sidebar_count | default 2 }} + {{ $skipCount := add $sidebarCount 1 }} + {{ if gt (len $recentPosts) 1 }} + {{ $sidebarPosts = first $sidebarCount (after 1 $recentPosts) }} + {{ end }} + {{ if gt (len $recentPosts) $skipCount }} + {{ $remainingPosts = after $skipCount $recentPosts }} + {{ end }} + {{ end }} + + {{/* Topic filters — fixed order from data/blog_topics.yml */}} + {{ $topicOrder := slice "community" "learn" "software" "updates" }} + {{ $topicsData := .Site.Data.blog_topics | default dict }} +
+ + {{ range $topicOrder }} + {{ $entry := index $topicsData . }} + {{ if $entry }} + + {{ end }} + {{ end }} +
+ + {{/* Featured section: 1 large post + sidebar posts */}} + {{ if or $featuredPost (gt (len $sidebarPosts) 0) }} + + {{ end }} + + {{/* Remaining posts grid */}} + {{ if gt (len $remainingPosts) 0 }} +
+ {{ range $index, $post := $remainingPosts }} + {{ partial "blog-card.html" (dict "." $post "modifier" "card--blog--grid" "showExcerpt" true "colorIndex" (mod $index 4)) }} + {{ end }} +
+ {{ end }} + + {{ end }} +
+
+ +{{/* Archives section for old posts without images */}} +{{ partial "blog-archives.html" $archivePosts }} +
+ + +{{ end }} diff --git a/themes/clean-hugo/layouts/blog/single.html b/themes/clean-hugo/layouts/blog/single.html new file mode 100644 index 00000000..64972720 --- /dev/null +++ b/themes/clean-hugo/layouts/blog/single.html @@ -0,0 +1,72 @@ +{{ define "main" }} + +
+ {{ $img := partial "get-image.html" (dict "image" .Params.image "fallbackAlt" .Title "page" .) }} + {{ if $img.exists }} + {{ $img.alt }} + {{ end }} + + +
+ + +
+

{{ .Title }}

+

{{ .Date.Format "Jan 2, 2006" }}{{ with partial "blog-topic.html" . }}{{ with .label }} • {{ . }}{{ end }}{{ end }}

+
+ + + {{ if $img.credit }} +
+ {{ $img.credit }} +
+ {{ end }} +
+
+ + + + + {{ with .Params.excerpt }} +
+

{{ . | markdownify }}

+
+ {{ end }} + + +
+ {{ .Content }} + + {{ partial "learn-more.html" . }} +
+ + +
+ {{ with .Params.tags }}Tags: {{ range $i, $t := . }}{{ if $i }}, {{ end }}{{ $t }}{{ end }}{{ end }} +
+ + + {{ partial "last-modified.html" . }} +
+{{ end }} + +{{ define "scripts" }} + {{/* Load GLightbox only if masonry shortcode was used */}} + {{ if .Page.Scratch.Get "hasGallery" }} + {{ partial "glightbox-scripts.html" . }} + {{ end }} +{{ end }} diff --git a/themes/clean-hugo/layouts/events/list.html b/themes/clean-hugo/layouts/events/list.html new file mode 100644 index 00000000..094a49a3 --- /dev/null +++ b/themes/clean-hugo/layouts/events/list.html @@ -0,0 +1,30 @@ +{{ define "main" }} +{{ partial "section-hero.html" . }} + +{{ $today := now.Format "2006-01-02" }} +{{ $past := slice }} +{{ range .Pages }} + {{ $e := .Params.event }} + {{ if and $e $e.start_date }} + {{ $start := $e.start_date }} + {{ $end := $e.end_date | default $e.start_date }} + {{ if gt $today $end }} + {{ $past = $past | append . }} + {{ end }} + {{ end }} +{{ end }} + +{{ partial "events-upcoming.html" (dict "context" . "pages" .Pages) }} + +{{ with .Content }} +
+
+
+ {{ . }} +
+
+
+{{ end }} + +{{ partial "events-past-archives.html" (sort $past "Params.event.start_date" "desc") }} +{{ end }} diff --git a/themes/clean-hugo/layouts/events/single.html b/themes/clean-hugo/layouts/events/single.html new file mode 100644 index 00000000..f98c120d --- /dev/null +++ b/themes/clean-hugo/layouts/events/single.html @@ -0,0 +1,59 @@ +{{ define "main" }} +{{ $e := .Params.event }} +{{ $dateLine := "" }} +{{ if $e }} + {{ $dateLine = partial "event-date-display.html" (dict "event" $e) }} + {{ $loc := $e.location_name | default $e.location }} + {{ with $loc }} + {{ $dateLine = printf "%s · %s" $dateLine . }} + {{ end }} +{{ end }} +{{ $gradientFrom := "#71B3B5" }} +{{ $gradientTo := "#2E6060" }} +{{ if and $e (not .Params.image) }} + {{ $t := lower ($e.event_type | default "") }} + {{ if eq $t "workshop" }} + {{ $gradientFrom = "#71B3B5" }}{{ $gradientTo = "#2E6060" }} + {{ else if eq $t "community" }} + {{ $gradientFrom = "#AC87A0" }}{{ $gradientTo = "#8B6A8F" }} + {{ end }} +{{ end }} +
+ {{ $img := partial "get-image.html" (dict "image" .Params.image "fallbackAlt" .Title "page" .) }} + {{ if $img.exists }} + {{ $img.alt }} + {{ end }} +
+
+

{{ .Title }}

+ {{ if $dateLine }}

{{ $dateLine }}

{{ end }} +
+ {{ if $img.credit }} +
{{ $img.credit }}
+ {{ end }} +
+
+ {{ with .Params.excerpt }} +
+

{{ . | markdownify }}

+
+ {{ end }} +
+ {{ .Content }} + {{ partial "event-instructors.html" . }} + {{ partial "learn-more.html" . }} +
+
+ {{ with .Params.tags }}Tags: {{ range $i, $t := . }}{{ if $i }}, {{ end }}{{ $t }}{{ end }}{{ end }} +
+ {{ partial "last-modified.html" . }} +
+{{ end }} + +{{ define "scripts" }} + {{ if .Page.Scratch.Get "hasGallery" }} + {{ partial "glightbox-scripts.html" . }} + {{ end }} +{{ end }} diff --git a/themes/clean-hugo/layouts/gallery/list.html b/themes/clean-hugo/layouts/gallery/list.html new file mode 100644 index 00000000..d3a0972d --- /dev/null +++ b/themes/clean-hugo/layouts/gallery/list.html @@ -0,0 +1,37 @@ +{{ define "main" }} + {{ partial "hero.html" . }} + + + + + {{ partial "gallery-filter.html" (dict "cardSelector" ".gallery-card" "ariaLabel" "Filter gallery by group") }} +{{ end }} diff --git a/themes/clean-hugo/layouts/gallery/single.html b/themes/clean-hugo/layouts/gallery/single.html new file mode 100644 index 00000000..e28c4c94 --- /dev/null +++ b/themes/clean-hugo/layouts/gallery/single.html @@ -0,0 +1,36 @@ +{{/* Layout for a single gallery item page */}} +{{ define "main" }} + {{ partial "hero.html" . }} + + +{{ end }} + +{{ define "scripts" }} + {{ partial "glightbox-scripts.html" . }} +{{ end }} diff --git a/themes/clean-hugo/layouts/packages/list.html b/themes/clean-hugo/layouts/packages/list.html new file mode 100644 index 00000000..ae330ae1 --- /dev/null +++ b/themes/clean-hugo/layouts/packages/list.html @@ -0,0 +1,78 @@ +{{ define "main" }} + +{{/* Calculate package metrics using shared partial */}} +{{ $pkgStats := partial "calculate-package-stats.html" . }} + +{{/* Hero section - similar to splash layout */}} +{{ partial "hero.html" . }} + +{{/* Metrics Bar - render with calculated stats TODO Move this to a separate calculation step in the actually website vs here in the template*/}} +{{ $stats := slice + (printf "**%d** Packages Accepted" $pkgStats.total) + (printf "**%d** Published in JOSS" $pkgStats.joss) + (printf "**%d** Currently Active" $pkgStats.active) + (printf "**%d** Unique Maintainers" $pkgStats.maintainers) +}} +{{ partial "metrics-bar-render.html" (dict "stats" $stats) }} + +{{/* Page content with metrics and intro text - centered with max-width */}} +
+
+ {{ .Content }} +
+
+ +{{/* Packages listing - full width with inner max-width containers */}} +{{ if .Site.Data.packages }} + +
+ + {{/* Partner Button - above filters */}} + + + {{/* Filters and Search - contained width */}} +
+
+ {{ partial "packages/filters.html" . }} +
+
+ + {{/* Active Packages */}} +
+
+

pyOpenSci Accepted Packages

+ {{ partial "packages/grid.html" (dict "activeOnly" true) }} +
+
+ + {{/* Archived Packages — full-bleed band (same as blog archives) */}} +
+
+
+

Archived Packages

+

+ Archived packages are packages that have successfully completed peer review + but are no longer actively maintained. +

+
+ {{ partial "packages/grid.html" (dict "activeOnly" false) }} +
+
+
+{{ else }} +
+

No package data found. Add packages to data/packages.yml to display them here.

+
+{{ end }} + +{{ end }} diff --git a/themes/clean-hugo/layouts/partials/_events.scss b/themes/clean-hugo/layouts/partials/_events.scss new file mode 100644 index 00000000..c85a03d4 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/_events.scss @@ -0,0 +1,401 @@ +/* Events listing (/events/) */ +.events-list { + padding: 2rem 0 4rem; + + .container { + max-width: $container-max-width; + margin: 0 auto; + padding: 0 $fluid-container-padding; + } +} + +.blog-hero .events-list__intro { + color: rgba(255, 255, 255, 0.92); + font-size: 1.125rem; + line-height: 1.5; + max-width: 42rem; + margin: 0.5rem 0 0; +} + +/* Small caps section label above upcoming cards */ +.events-list__kicker { + font-family: $font-family-body; + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--color-gray-600); + margin: 0 0 1rem; +} + +.events-list__kicker-amp { + letter-spacing: 0.08em; +} + +.events-list__heading { + margin-top: 2.5rem; + margin-bottom: 1.25rem; + font-size: 1.75rem; + + &:first-of-type { + margin-top: 0; + } +} + +/* Upcoming/live: flexible grid for many events */ +.events-list__featured { + display: grid; + gap: 1.25rem; + grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); + + @media (min-width: $breakpoint-lg) { + gap: 1.5rem; + } +} + +.events-list__empty { + color: var(--color-gray-700); + margin-bottom: 2rem; +} + +.events-list__types { + margin-top: 3rem; + margin-bottom: 1rem; + max-width: 65ch; +} + +/* Past events use shared .blog-archives + .highlight-grid from _blog.scss */ +.events-past-archives { + margin-top: 0; +} + +/* Event type pill — colors from hugo.toml CSS variables */ +.event-card__type { + display: inline-flex; + align-items: center; + font-size: 0.75rem; + font-weight: 600; + padding: 0.3rem 0.7rem; + border-radius: 9999px; + line-height: 1.2; + white-space: nowrap; + max-width: 100%; +} + +.event-card__type--training { + background-color: var(--color-event-label-training-bg, var(--color-primary-light)); + color: var(--color-event-label-training-fg, var(--color-primary-dark)); +} + +.event-card__type--sprint { + background-color: var(--color-event-label-sprint-bg, var(--color-accent-light)); + color: var(--color-event-label-sprint-fg, var(--color-gray-900)); +} + +.event-card__type--community { + background-color: var(--color-event-label-community-bg, var(--color-secondary)); + color: var(--color-event-label-community-fg, var(--color-gray-900)); +} + +.event-card__type--talk { + background-color: var(--color-event-label-talk-bg, var(--color-admonition-note, #cae4e4)); + color: var(--color-event-label-talk-fg, var(--color-primary-dark)); +} + +.event-card__type--default { + background-color: var(--color-gray-200); + color: var(--color-gray-700); +} + +/* Featured (upcoming/live) cards — white surface, mock-inspired layout */ +.event-card--featured { + > a { + display: flex; + flex-direction: column; + height: 100%; + min-height: 12rem; + text-decoration: none; + color: inherit; + border-radius: $radius-md; + background-color: var(--color-white); + box-shadow: $shadow-sm; + border: 1px solid var(--color-gray-200); + padding: 1.25rem 1.35rem; + transition: box-shadow $transition-base ease-in-out, transform $transition-base ease-in-out; + + &:hover { + box-shadow: $shadow-lg; + transform: translateY(-2px); + + .event-card__cta { + color: var(--color-link-hover); + } + } + } +} + +.event-card__featured-inner { + display: flex; + flex-direction: column; + height: 100%; + gap: 0.65rem; + min-height: 0; +} + +.event-card__featured-top { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 0.75rem; +} + +.event-card__date-badge { + flex-shrink: 0; + min-width: 3.25rem; + max-width: 8rem; + padding: 0.45rem 0.5rem; + border-radius: $radius-sm; + background-color: var(--color-event-date-badge-bg, var(--color-accent)); + color: var(--color-event-date-badge-fg, var(--color-white)); + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + line-height: 1.15; +} + +.event-card__date-badge-primary { + font-size: 1.0625rem; + font-weight: 800; + letter-spacing: 0.02em; +} + +.event-card__date-badge-secondary { + font-size: 0.65rem; + font-weight: 700; + letter-spacing: 0.08em; +} + +.event-card__date-badge-year { + font-size: 0.6rem; + font-weight: 600; + margin-top: 0.15rem; + opacity: 0.95; +} + +.event-card--featured .event-card__title { + font-size: 1.25rem; + font-weight: 700; + line-height: 1.25; + margin: 0; + color: var(--color-gray-900); +} + +.event-card__meta { + margin: 0; + font-size: 0.9375rem; + line-height: 1.45; + color: var(--color-gray-600); +} + +.event-card__cta { + margin-top: auto; + padding-top: 0.35rem; + font-size: 0.875rem; + font-weight: 600; + color: var(--color-link); +} + +/* Compact past cards (horizontal thumb) */ +.event-card:not(.event-card--featured) { + > a { + display: block; + height: 100%; + text-decoration: none; + color: inherit; + border-radius: $radius-md; + overflow: hidden; + background-color: var(--color-white); + box-shadow: $shadow-sm; + border: 1px solid var(--color-gray-200); + transition: box-shadow $transition-base ease-in-out, transform $transition-base ease-in-out; + + &:hover { + box-shadow: $shadow-lg; + transform: translateY(-2px); + } + } +} + +.event-card__content { + display: flex; + flex-direction: row; + min-height: 0; +} + +.event-card__date { + position: relative; + flex: 0 0 6.5rem; + min-height: 7rem; + overflow: hidden; +} + +.event-card__date-background { + position: absolute; + inset: 0; + background-size: cover; + background-position: center; + + &--default { + background: linear-gradient(145deg, var(--color-primary) 0%, var(--color-primary-dark) 100%); + } +} + +.event-card__date-text { + position: relative; + z-index: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + padding: 0.5rem; + color: var(--color-white); + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35); + font-weight: 700; + line-height: 1.15; + text-align: center; + + span { + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.02em; + } + + span:first-child { + font-size: 1.25rem; + font-weight: 800; + } + + span:nth-child(3) { + font-size: 0.7rem; + opacity: 0.95; + } +} + +.event-card__details { + flex: 1; + padding: 1rem 1.125rem; + display: flex; + flex-direction: column; + gap: 0.5rem; + min-width: 0; +} + +.event-card__type--inline { + align-self: flex-start; + margin-bottom: 0.15rem; +} + +.event-card__title { + font-size: 1.125rem; + font-weight: 600; + line-height: 1.3; + margin: 0; + color: var(--color-gray-900); +} + +.event-card__details p { + margin: 0; + font-size: 0.875rem; + line-height: 1.5; + color: var(--color-gray-600); +} + +.event-card__button { + margin-top: auto; + font-size: 0.8125rem; + font-weight: 600; + color: var(--color-primary); +} + +/* Event detail: instructors (optional front matter) */ +.event-instructors { + margin-top: 3rem; + padding-top: 2rem; + border-top: 1px solid var(--color-gray-200); +} + +.event-instructors__heading { + font-size: 1.5rem; + margin-bottom: 1.25rem; +} + +.event-instructors__grid { + list-style: none; + margin: 0; + padding: 0; + display: grid; + gap: 1.5rem; + grid-template-columns: 1fr; + + @media (min-width: $breakpoint-md) { + grid-template-columns: repeat(2, 1fr); + } +} + +.event-instructors__card { + display: flex; + gap: 1rem; + align-items: flex-start; + padding: 1rem; + border-radius: $radius-md; + border: 1px solid var(--color-gray-200); + background-color: var(--color-white); + box-shadow: $shadow-sm; +} + +.event-instructors__avatar { + flex-shrink: 0; + width: 5rem; + height: 5rem; + border-radius: 9999px; + object-fit: cover; +} + +.event-instructors__name { + margin: 0 0 0.5rem; + font-size: 1.125rem; +} + +.event-instructors__bio { + margin: 0; + font-size: 0.9375rem; + line-height: 1.5; + color: var(--color-gray-700); +} + +.event-card--compact { + .event-card__date { + flex-basis: 4.5rem; + min-height: 5rem; + } + + .event-card__date-text span:first-child { + font-size: 1rem; + } + + .event-card__details { + padding: 0.75rem 0.875rem; + } + + .event-card__title { + font-size: 0.9375rem; + } + + .event-card__type { + font-size: 0.65rem; + padding: 0.2rem 0.5rem; + } +} diff --git a/themes/clean-hugo/layouts/partials/blog-archives.html b/themes/clean-hugo/layouts/partials/blog-archives.html new file mode 100644 index 00000000..b80ef858 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/blog-archives.html @@ -0,0 +1,45 @@ +{{/* + Blog Archives Partial + + Parameters: + - "." (context): Array of archive posts +*/}} +{{ $archivePosts := . }} + +{{ if gt (len $archivePosts) 0 }} +
+
+
+

From the Archives

+
+ +
+ {{ range $archivePosts }} + {{ $topic := partial "blog-topic.html" . }} +
+
+ + {{ if $topic.label }} + {{ $topic.label }} + {{ end }} +
+ +
+

+ {{ .Title }} +

+ +

+ {{ partial "blog-excerpt.html" (dict "." . "length" 200) }} +

+ + + Read more + +
+
+ {{ end }} +
+
+
+{{ end }} diff --git a/themes/clean-hugo/layouts/partials/blog-card.html b/themes/clean-hugo/layouts/partials/blog-card.html new file mode 100644 index 00000000..9b9e0985 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/blog-card.html @@ -0,0 +1,79 @@ +{{/* + Blog Card Partial + + Parameters: + - "." (context): The blog post page object (passed as "." in dict) + - "modifier" (string): card--blog--featured | card--blog--sidebar | card--blog--grid + - "showExcerpt" (bool): Whether to show excerpt +*/}} +{{ $post := index . "." }} +{{ $modifier := .modifier | default "" }} +{{ $showExcerpt := .showExcerpt | default false }} +{{ $topic := partial "blog-topic.html" $post }} +{{ $excerptLength := $post.Site.Params.blog.excerpt_length | default 200 }} +{{ $isGrid := eq $modifier "card--blog--grid" }} +{{ $colorIndex := .colorIndex | default 0 }} + +
+ + {{ if $isGrid }} + {{/* Grid cards: banner image + scrim, white title + date (Jekyll banner_only) */}} + {{ $img := partial "get-image.html" (dict "image" $post.Params.image "fallbackAlt" $post.Title "page" $post) }} +
+ {{ if $img.exists }} + + {{ else }} + + {{ end }} + +
+

{{ $post.Title }}

+ +
+
+
+ {{ if $topic.label }} + {{ $topic.label }} + {{ end }} + {{ if $showExcerpt }} +

+ {{ partial "blog-excerpt.html" (dict "." $post "length" 130) }} +

+ {{ end }} +
+ {{ else }} + {{ $img := partial "get-image.html" (dict "image" $post.Params.image "fallbackAlt" $post.Title "page" $post) }} + {{ if $img.exists }} +
+ {{ $img.alt }} +
+ {{ else }} +
+ {{ end }} +
+ {{ if $topic.label }} + {{ $topic.label | upper }} + {{ end }} +

{{ $post.Title }}

+ + {{ if $post.Params.show_author }} +

{{ $post.Params.author | default $post.Site.Params.author }}

+ {{ end }} + {{ if $showExcerpt }} +

+ {{ partial "blog-excerpt.html" (dict "." $post "length" $excerptLength) }} +

+ {{ end }} +
+ {{ end }} +
+
diff --git a/themes/clean-hugo/layouts/partials/blog-excerpt.html b/themes/clean-hugo/layouts/partials/blog-excerpt.html new file mode 100644 index 00000000..8fb9c2c7 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/blog-excerpt.html @@ -0,0 +1,17 @@ +{{/* + Blog Excerpt Partial + + Parameters: + - "." (context): The blog post page object (passed as "." in dict) + - "length" (int): Character length for truncation (default: 200) +*/}} +{{ $post := index . "." }} +{{ $length := .length | default 200 }} + +{{ if $post.Params.excerpt }} + {{ $post.Params.excerpt | markdownify | plainify | htmlUnescape | truncate $length }} +{{ else if $post.Summary }} + {{ $post.Summary | plainify | htmlUnescape | truncate $length }} +{{ else }} + {{ $post.Plain | htmlUnescape | truncate $length }} +{{ end }} diff --git a/themes/clean-hugo/layouts/partials/blog-list.html b/themes/clean-hugo/layouts/partials/blog-list.html new file mode 100644 index 00000000..f7815890 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/blog-list.html @@ -0,0 +1,42 @@ +
+
+
+

{{ .Params.blog_title | default "Recent Thoughts" }}

+
+ +
+ {{ $limit := .Params.blog_limit | default 3 }} + {{ range first $limit (where .Site.RegularPages "Type" "blog") }} + {{ $p := . }} +
+
+ + {{ with $p.Params.category }} + {{ . }} + {{ end }} +
+ +
+

+ {{ $p.Title }} +

+ +

+ {{ if $p.Params.excerpt }} + {{ $p.Params.excerpt | markdownify | plainify | truncate 200 }} + {{ else if $p.Summary }} + {{ $p.Summary | plainify | truncate 200 }} + {{ else }} + {{ $p.Plain | truncate 200 }} + {{ end }} +

+ + + Read more + +
+
+ {{ end }} +
+
+
diff --git a/themes/clean-hugo/layouts/partials/blog-topic.html b/themes/clean-hugo/layouts/partials/blog-topic.html new file mode 100644 index 00000000..657b9832 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/blog-topic.html @@ -0,0 +1,13 @@ +{{/* + Blog topic label lookup + + Parameters: + - "." (context): Blog post page object + + Returns dict: slug, label +*/}} +{{ $slug := .Params.blog_topic | default "community" }} +{{ $topics := site.Data.blog_topics | default dict }} +{{ $entry := index $topics $slug }} +{{ $label := $entry.label | default ($slug | humanize) }} +{{ return (dict "slug" $slug "label" $label) }} diff --git a/themes/clean-hugo/layouts/partials/calculate-package-stats.html b/themes/clean-hugo/layouts/partials/calculate-package-stats.html new file mode 100644 index 00000000..caf2a1d7 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/calculate-package-stats.html @@ -0,0 +1,34 @@ +{{/* + Calculate Package Statistics + Returns a dict with: total, active, joss, maintainers + Usage: {{ $stats := partial "calculate-package-stats.html" . }} +*/}} + +{{ $allMaintainers := slice }} +{{ $activeCount := 0 }} +{{ $jossCount := 0 }} +{{ $totalCount := 0 }} + +{{ with .Site.Data.packages }} + {{ $totalCount = len . }} + {{ range . }} + {{ if .active }} + {{ $activeCount = add $activeCount 1 }} + {{ end }} + {{ if .joss }} + {{ $jossCount = add $jossCount 1 }} + {{ end }} + {{ range .all_current_maintainers }} + {{ $allMaintainers = $allMaintainers | append .github_username }} + {{ end }} + {{ end }} +{{ end }} + +{{ $uniqueMaintainers := $allMaintainers | uniq }} + +{{ return (dict + "total" $totalCount + "active" $activeCount + "joss" $jossCount + "maintainers" (len $uniqueMaintainers) +) }} diff --git a/themes/clean-hugo/layouts/partials/cards.html b/themes/clean-hugo/layouts/partials/cards.html new file mode 100644 index 00000000..8177424e --- /dev/null +++ b/themes/clean-hugo/layouts/partials/cards.html @@ -0,0 +1,64 @@ + + + +{{ $icon := .icon }} +{{ $textOnly := false }} +{{ if reflect.IsMap . }} + {{ if .text_only }} + {{ $textOnly = eq .text_only true }} + {{ end }} +{{ end }} + +{{ if $textOnly }} +
+
+
+

+ {{ .title }} +

+ {{ with .excerpt }} +

{{ . }}

+ {{ end }} + {{ with .url }} +
+ {{ $.cta | default "Learn more →" }} +
+ {{ end }} +
+
+
+{{ else }} +{{ $page := index . "page" }} +{{ $img := partial "get-image.html" (dict "image" .image "fallbackAlt" .title "page" $page) }} +{{ $kind := lower (urlize (.event_type | default "")) }} +{{ $typeLabels := dict "training" "Training" "sprint" "Sprint" "community" "Community event" "talk" "Talk" }} +{{ $typeLabel := index $typeLabels $kind }} +
+ {{ if $img.exists }} +
+ {{ $img.alt }} +
+ {{ end }} +
+ {{ if and $typeLabel (ne $kind "") }} + {{ $typeLabel }} + {{ end }} +

{{ if and $icon (in (printf "%s" $icon) "fa-") }} + + {{ else if and $icon (ne (printf "%s" $icon) "") }} +
{{ $icon | safeHTML }}
+ {{ end }} {{ .title }}

+ {{ with .excerpt }} +
{{ . | markdownify }}
+ {{ end }} +
+ + {{ with .url }} + {{ $.cta | default "Learn more →" }} + {{ end }} +
+{{ end }} diff --git a/themes/clean-hugo/layouts/partials/docs-menu-recursive.html b/themes/clean-hugo/layouts/partials/docs-menu-recursive.html new file mode 100644 index 00000000..0427c8c0 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/docs-menu-recursive.html @@ -0,0 +1,42 @@ +{{- /* + Recursive menu builder for documentation sidebar + Usage: {{ partial "docs-menu-recursive.html" (dict "pages" .Pages "context" .) }} + + Parameters: + - pages: Collection of pages to render (typically .Pages.ByWeight) + - context: Current page context for active state detection + - level: Current nesting level (default: 1) +*/ -}} + +{{- $pages := .pages -}} +{{- $context := .context -}} +{{- $currentPage := $context -}} +{{- $level := .level | default 1 -}} + +{{- if $pages -}} + +{{- end -}} diff --git a/themes/clean-hugo/layouts/partials/docs-sidebar.html b/themes/clean-hugo/layouts/partials/docs-sidebar.html new file mode 100644 index 00000000..fd11864f --- /dev/null +++ b/themes/clean-hugo/layouts/partials/docs-sidebar.html @@ -0,0 +1,59 @@ +{{- /* + Documentation sidebar with auto-generated menu + + The sidebar now displays: + 1. Auto-populated menu from documentation pages (by weight) + 2. Inline TOC for the active page (nested under the active page link) + + The inline TOC is populated by JavaScript after page load +*/ -}} + +{{- $currentPage := . -}} +{{- $docSection := .Site.GetPage "/documentation" -}} + +{{- if $docSection -}} +
+

Documentation

+ + +
+ +
+{{- end -}} diff --git a/themes/clean-hugo/layouts/partials/docs-toc.html b/themes/clean-hugo/layouts/partials/docs-toc.html new file mode 100644 index 00000000..5aff5eb0 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/docs-toc.html @@ -0,0 +1,24 @@ +{{- /* + Inline Table of Contents for active documentation page + Usage: {{ partial "docs-toc.html" .Page }} + + Generates an inline TOC from H2/H3 headings that appears under the active page + in the sidebar navigation. This is populated via JavaScript after page load. + + Parameters: + - page: The page context to generate TOC for +*/ -}} + +{{- $page := . -}} + +{{- /* + The TOC is a placeholder list that will be populated by JavaScript + JavaScript will: + 1. Find all h2/h3 headings in the page content + 2. Create anchor links to them + 3. Insert them into the ul.toc-items list below +*/ -}} + + diff --git a/themes/clean-hugo/layouts/partials/event-card.html b/themes/clean-hugo/layouts/partials/event-card.html new file mode 100644 index 00000000..641e6706 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/event-card.html @@ -0,0 +1,110 @@ +{{/* + Event card partial. Pass dict: + Page (required), compact (bool), variant (optional: "featured" for upcoming/live grid). + Front matter: params.event.start_date, optional end_date, location, conference, subtitle, + event_type: training | sprint | community | talk +*/}} +{{ $p := .Page }} +{{ $compact := .compact | default false }} +{{ $variant := .variant | default "" }} +{{ $featured := and (not $compact) (eq $variant "featured") }} +{{ $e := $p.Params.event }} +{{ if not $e }} + {{ return }} +{{ end }} +{{ $img := partial "get-image.html" (dict "image" $p.Params.image "fallbackAlt" $p.Title "page" $p) }} +{{ $rootClass := printf "%s%s" (cond $compact "event-card event-card--compact" (cond $featured "event-card event-card--featured" "event-card")) (cond (and $featured $img.exists) " event-card--with-image" "") }} +{{ $kind := lower (urlize ($e.event_type | default "")) }} +{{ $typeLabels := dict "training" "Training" "sprint" "Sprint" "community" "Community event" "talk" "Talk" }} +{{ $typeLabel := index $typeLabels $kind }} +{{ $start := time $e.start_date }} +{{ $endStr := $e.end_date | default $e.start_date }} +{{ $end := time $endStr }} +{{ $subtitle := $e.subtitle | default "" }} +{{ if not $subtitle }} + {{ with $e.conference }} + {{ $subtitle = printf "%s • %s" . ($e.location | default "") }} + {{ else }} + {{ $subtitle = $e.location | default "" }} + {{ end }} +{{ end }} +
+ + {{ if $featured }} + {{ if $img.exists }} + + {{ end }} + + {{ else }} +
+
+ {{ if $img.exists }} +
+ {{ else }} +
+ {{ end }} +
+ {{ with $e.end_date }} + {{ $end2 := time . }} + {{ if ne $start.Year $end2.Year }} + {{ $start.Format "Jan 2" }}–{{ $end2.Format "Jan 2, 2006" }} + {{ else if ne $start.Month $end2.Month }} + {{ $start.Format "Jan 2" }}–{{ $end2.Format "Jan 2" }} + {{ else if ne $start.Day $end2.Day }} + {{ $start.Format "2" }}–{{ $end2.Format "2" }} + {{ else }} + {{ $start.Format "2" }} + {{ end }} + {{ else }} + {{ $start.Format "2" }} + {{ end }} + {{ $start.Format "Jan" }} + {{ $start.Format "2006" }} +
+
+
+ {{ if and $typeLabel (ne $kind "") }} + {{ $typeLabel }} + {{ end }} +

{{ $p.Title }}

+ {{ with $p.Summary }} +

{{ . | plainify | truncate 120 }}

+ {{ end }} + {{ cond $compact "View" "Learn more" }} +
+
+ {{ end }} +
+
diff --git a/themes/clean-hugo/layouts/partials/event-date-display.html b/themes/clean-hugo/layouts/partials/event-date-display.html new file mode 100644 index 00000000..de4e4552 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/event-date-display.html @@ -0,0 +1,17 @@ +{{/* + Human-readable event date (and optional ISO range for