diff --git a/content/about-peer-review.md b/content/about-peer-review.md index 85d1b583..b32746e3 100644 --- a/content/about-peer-review.md +++ b/content/about-peer-review.md @@ -11,7 +11,7 @@ hero: url: "/python-packages/" --- -{{< swoosh_section background="purple" swoosh="bottom" >}} +{{< section_band color="light-purple" divider="bottom" >}} {{< feature-row layout="left" title="How Python software peer review works" @@ -77,7 +77,7 @@ View our Author Guide {{< /button >}} {{< /single-card-wide >}} -{{< /swoosh_section >}} +{{< /section_band >}}
diff --git a/content/blog/2026-05-01-clean-hugo-blog-theme-features.md b/content/blog/2026-05-01-clean-hugo-blog-theme-features.md index 4ca14742..580f6087 100644 --- a/content/blog/2026-05-01-clean-hugo-blog-theme-features.md +++ b/content/blog/2026-05-01-clean-hugo-blog-theme-features.md @@ -629,16 +629,16 @@ shortcode form (percent signs). **Usage:** ``` -{{}} +{{}} {{}} -{{}} +{{}} ``` **Rendered:** -{{< swoosh_section background="purple" swoosh="bottom" >}} +{{< section_band color="light-purple" divider="bottom" >}} {{< section-heading title="Inside a swoosh section" subtitle="Purple background • optional top or bottom curve" >}} -{{< /swoosh_section >}} +{{< /section_band >}} ## Intro section @@ -839,7 +839,18 @@ hierarchy. The `metrics-bar` shortcode renders a row of key statistics with large numbers. Use it to highlight impact data. -**Usage:** +**Named presets** (live data from site YAML): + +``` +{{}} +{{}} +``` + +Or set `metrics_set: volunteer` in page front matter and call +`{{}}`. Presets live in +`layouts/partials/metrics/presets/`. + +**Manual stats** (static or demo content): ``` {{}} ``` -**Rendered:** +**Rendered** (manual example): {{< metrics-bar stat1="**128** blog posts migrated" diff --git a/content/learn-universities-labs.md b/content/learn-universities-labs.md index 5aaf0b08..51419a27 100644 --- a/content/learn-universities-labs.md +++ b/content/learn-universities-labs.md @@ -28,7 +28,7 @@ from open source leaders. {{< university-benefits-list >}} -{{% swoosh_section background="purple" swoosh="bottom" %}} +{{% section_band color="light-purple" divider="bottom" %}} {{< pullquote color="purple" author="Zach Chandler" event="Director, Stanford Open Source Program Office" >}} pyOpenSci has proven to be a valuable partner in developing our competencies @@ -38,7 +38,7 @@ does significant work in Python (which is all universities!) I highly recommend getting involved with pyOpenSci. {{< /pullquote >}} -{{% /swoosh_section %}} +{{% /section_band %}} ## Research software accelerator programs @@ -59,7 +59,7 @@ source. Open doors for your researchers to engage with other Python developers, troubleshoot challenges together, and gain ongoing support as they develop their scientific open source skills. -{{% swoosh_section background="purple" swoosh="top" %}} +{{% section_band color="light-purple" divider="top" %}} ## Don't take our word for it: hear from previous course learners @@ -67,14 +67,14 @@ their scientific open source skills. *Our current content is the 10-day Ship It: Python Packaging in the GenAI Era course.* -{{% /swoosh_section %}} +{{% /section_band %}} ### Beta Partnership packages We are currently piloting our partnership program to find the best combination of resources and events that best support our University partners. -{{% swoosh_section background="purple" swoosh="top" %}} +{{% section_band color="light-purple" divider="top" %}} ## Ready to explore a pyOpenSci membership? @@ -92,7 +92,7 @@ pyOpenSci also offers a wide variety of free training resources for individual learners. Explore our workshops, webinars, and more on our [events page](/events/). -{{% /swoosh_section %}} +{{% /section_band %}} ## Why partnering with pyOpenSci matters diff --git a/content/learn.md b/content/learn.md index 76879fcb..5402ff3c 100644 --- a/content/learn.md +++ b/content/learn.md @@ -27,7 +27,7 @@ Are you interested in cohort learning options? Visit our page to learn more. {{< /admonition >}} -{{< swoosh_section background="purple" swoosh="bottom" >}} +{{< section_band color="light-purple" divider="bottom" >}} {{< feature-row layout="right" title="Our process: Community-developed Python tutorials" @@ -42,7 +42,7 @@ Our tutorials are created through a multi-stage community review process. review for accuracy, usability and accessibility. {{< /feature-row >}} -{{< /swoosh_section >}} +{{< /section_band >}}
@@ -56,7 +56,7 @@ order, but you can always pick a specific topic if you wish to jump around.
-{{< swoosh_section background="purple" swoosh="top" >}} +{{< section_band color="light-purple" divider="top" >}} {{< feature-row layout="right" title="Lessons: Collaborative GitHub for Scientists" @@ -91,7 +91,7 @@ then work through the contribute path: [Ways to contribute](https://www.pyopensci.org/lessons/contribute-open-source/ways-to-contribute.html) {{< /feature-row >}} -{{< /swoosh_section >}} +{{< /section_band >}}
diff --git a/content/partners.md b/content/partners.md index e6659823..1327a868 100644 --- a/content/partners.md +++ b/content/partners.md @@ -14,7 +14,7 @@ header: Domain-specific communities can partner with pyOpenSci to leverage both our peer review process and development of Python packaging guidelines. -{{< swoosh_section background="purple" swoosh="bottom" >}} +{{< section_band color="light-purple" divider="bottom" >}} {{< feature-row layout="right" title="Community partnerships streamline peer review & packaging standards" @@ -42,7 +42,7 @@ Through a single review process, community maintainers: * Are supported in maintaining their tools, with input from our diverse, knowledgeable community, including active members from across the Python, Conda, PyPA and broader Python packaging ecosystem {{< /feature-row >}} -{{< /swoosh_section >}} +{{< /section_band >}} ## Partnering with pyOpenSci increases the visibility of your communities' tools @@ -54,7 +54,7 @@ We will: * Provide a feed allowing you to cross-list affiliated packages on your website. * Keep in touch with maintainers to ensure packages are actively maintained. -{{< swoosh_section background="purple" swoosh="top" >}} +{{< section_band color="light-purple" divider="top" >}} {{< feature-row layout="left" title="Help scientists find the Python software tools that they need" @@ -66,7 +66,7 @@ Our catalog of vetted open source tools makes it easier for scientists to find the trusted tools that they need to develop their open science workflows. {{< /feature-row >}} -{{< /swoosh_section >}} +{{< /section_band >}} ## Leverage our peer review process @@ -81,7 +81,7 @@ developed and well-documented peer review process which includes: Learn more about our partnerships {{< /button >}} -{{< swoosh_section background="purple" swoosh="top" >}} +{{< section_band color="light-purple" divider="top" >}} {{< feature-row layout="left" title="Let's make packaging easier for scientists, together" @@ -102,7 +102,7 @@ across the Python ecosystem. This consistency will lower the barrier of entry fo new potential contributors. {{< /feature-row >}} -{{< /swoosh_section >}} +{{< /section_band >}} {{< feature-row layout="right" title="Harness the power of community" diff --git a/content/python-packaging-science.md b/content/python-packaging-science.md index 350d529c..dbe0de15 100644 --- a/content/python-packaging-science.md +++ b/content/python-packaging-science.md @@ -16,7 +16,7 @@ intro_section: {{< intro-section >}} -{{< swoosh_section background="purple" swoosh="bottom" >}} +{{< section_band color="light-purple" divider="bottom" >}} {{< feature-row layout="right" title="Community-created Python packaging guide" @@ -40,7 +40,7 @@ citation. {{< packaging-guide-grid >}} -{{< /swoosh_section >}} +{{< /section_band >}}
@@ -53,7 +53,7 @@ process of creating a Python package, following modern best practices.
-{{< swoosh_section background="purple" swoosh="top" >}} +{{< section_band color="light-purple" divider="top" >}} {{< feature-row layout="left" title="Get involved: Help us improve our Python packaging resources" @@ -74,4 +74,4 @@ All contributions are recognized both on our website and in the guidebook's citation. {{< /feature-row >}} -{{< /swoosh_section >}} +{{< /section_band >}} diff --git a/content/volunteer.md b/content/volunteer.md index 85db3c74..66eba801 100644 --- a/content/volunteer.md +++ b/content/volunteer.md @@ -1,98 +1,203 @@ --- -title: "Get involved with pyOpenSci" +title: "Open science is fueled by people like you" layout: splash url: /volunteer/ aliases: - /volunteer.html - /get-involved-contact.html description: >- - Volunteer with pyOpenSci — review packages, contribute on GitHub, write for - the blog, and join a diverse community supporting scientific open source. -cards_layout: wide + pyOpenSci runs on volunteer energy. Whether you want to review a Python package, help maintain our tools, or translate resources for your community — there's a role that fits your time and skills. +metrics_set: volunteer +cards_align: center +cards_layout: five cards: - - title: "Lend a Hand on GitHub" + - modifier: "card--white" + title: "Reviewer" + label: "Async" + label_style: "accent" + tags: + - "Technical review" + - "~5–10 hrs / review" excerpt: >- - Got some time to help? Check out our GitHub Project Board for a list of - current issues that we could use help with. Any issue that is tagged - help-wanted in our repos is also fair game for anyone to tackle! We add - anyone who contributes to pyOpenSci to our - [community page](/our-community/). - url: "https://github.com/orgs/pyOpenSci/projects/3/views/1" - cta: "> Check out our GitHub Help Wanted Board" - - title: "Sign up to review a Python package" + Evaluate a Python package for usability, documentation, and packaging + best practices. Most reviewers complete one or two reviews per year on + their own schedule. + url: "https://forms.gle/GHfxvmS47nQFDcBM6" + cta: "Sign up to be a reviewer →" + - modifier: "card--white" + title: "Editor" + label: "Async" + label_style: "accent" + tags: + - "Editorial oversight" + - "~3–5 hrs / month" + excerpt: >- + Manage 2–3 active reviews — recruit reviewers, keep submissions on track, + and provide light technical guidance. + url: "https://docs.google.com/forms/d/e/1FAIpQLScRQHQ7NKVEAG3BKAphiUdVFvQ5nkez0IpyXBMZDzXjuBPloQ/viewform" + cta: "Apply to be an editor →" + - modifier: "card--white" + title: "Editor in Chief" + label: "Team role" + label_style: "team" + tags: + - "Leadership" + - "6–12 month rotation" + excerpt: >- + Serve as rotating lead for the editorial board — onboard new editors, + handle escalations, and help shape review policies. + #url: "https://docs.google.com/forms/d/e/1FAIpQLScRQHQ7NKVEAG3BKAphiUdVFvQ5nkez0IpyXBMZDzXjuBPloQ/viewform" + #cta: "Express interest →" + - modifier: "card--white" + title: "Peer review triage" + label: "Async" + label_style: "accent" + tags: + - "Intake & routing" + - "~2–4 hrs / month" + excerpt: >- + Screen new package submissions before they enter the review queue. A good + entry point if you want editorial experience with a lighter time + commitment. + #url: "https://forms.gle/GHfxvmS47nQFDcBM6" + cta: "Sign up for triage →" + - modifier: "card--stipend" + title: "Peer review lead" + label: "Stipended" + label_style: "stipend" + tags: + - "Program coordination" + - "Part-time" + excerpt: >- + Coordinate the day-to-day health of the review program — track open + submissions, support editors, and iterate on process documentation. This + role carries a stipend. + #url: "" + cta: "Apply for this role →" +translation_cards_align: center +translation_cards: + - modifier: "card--white" + title: "Translation Lead" + label: "Coordination" + label_style: "team" + tags: + - "Language coordination" + - "~3–5 hrs / month" excerpt: >- - We are always looking for new reviewers from a broad range of scientific - domains. Some reviewers have extensive packaging expertise and others - have domain expertise or focus on package usability. If you are new to - reviewing we are happy to support you through our peer review mentorship - program. - [Learn more about the reviewer role](https://www.pyopensci.org/software-peer-review/how-to/reviewer-guide.html) - and sign up using the link below. + Own a language track — coordinate contributors, manage review cycles, and + keep translations consistent with source updates. + url: "mailto:hello@pyopensci.org" + cta: "Apply to lead →" + - modifier: "card--white" + title: "Translation Contributor" + label: "Async" + label_style: "accent" + tags: + - "Translating & reviewing" + - "Flexible" + excerpt: >- + Translate or review content for a language you know well. Contribute as + much or as little as your schedule allows. url: "https://forms.gle/GHfxvmS47nQFDcBM6" - cta: "> Sign up now." - - title: "Get involved as software peer review Editor" + cta: "Sign up to translate →" +maintainer_cards_align: left +maintainer_cards: + - modifier: "card--white" + title: "Infrastructure maintainer" + label: "Ongoing" + label_style: "team" + tags: + - "CI & infrastructure" + - "Flexible" + excerpt: >- + Start with triage — labeling issues and reviewing pull requests — then + grow into CI, deployments, and codebase ownership as you get comfortable. + All skill levels welcome. + #url: "https://www.pyopensci.org/handbook/CONTRIBUTING.html" + #cta: "Become a maintainer →" + - modifier: "card--white" + title: "Website contributor" + label: "Async" + label_style: "accent" + tags: + - "Content & design" + - "Flexible" excerpt: >- - We also often recruit new editors to support our peer review process. - url: "https://www.pyopensci.org/software-peer-review/how-to/editors-guide.html" - cta: "> Click here to learn more about the editor role." + Help keep pyOpenSci.org welcoming and useful — write and edit content, + improve accessibility, refine our Hugo theme, and polish page layouts. + #url: "https://github.com/pyOpenSci/pyopensci.github.io" + cta: "Support our website →" +impact_destinations: + eyebrow: "Your impact" + title: "Where your work goes" + subtitle: >- + Volunteer contributions flow directly into resources scientists across + the ecosystem rely on every day. + items: + - icon: "fa-solid fa-box" + title: "Python Packaging Guide" + excerpt: "The community reference for packaging" + url: "https://www.pyopensci.org/python-package-guide/" + - icon: "fa-solid fa-globe" + title: "pyOpenSci website" + excerpt: "Content, design, and infrastructure" + url: "/" + - icon: "fa-solid fa-book" + title: "Tutorials & lessons" + excerpt: "Open learning content for researchers" + url: "/learn/" + - icon: "fa-solid fa-magnifying-glass" + title: "Peer review process" + excerpt: "Infrastructure for software quality" + url: "/about-peer-review/" + - icon: "fa-solid fa-earth-americas" + title: "Translations" + excerpt: "Resources in more languages" + url: "https://www.pyopensci.org/python-package-guide/" --- -pyOpenSci is a volunteer community that broadens participation in scientific -open source. We make finding, sharing and contributing to reusable code easier -for everyone, everywhere. +{{< feature-row layout="right" + title="Volunteers are the core of everything we do" + image="/images/people/leah-chase-pavithra-carol.png" + alt="Four pyOpenSci community members, including Carol Willing, smiling together outdoors at PyCon US 2023." >}} +Every package that earns a pyOpenSci badge has been evaluated by a volunteer +reviewer. Every guide a researcher relies on has been written, edited, or +translated by a community member. Every sprint has been organized by someone +who believed open science was worth their time. + +When you volunteer with pyOpenSci, your work flows directly into the +infrastructure the scientific Python ecosystem depends on — and into a community +of people doing the same. +{{< /feature-row >}} + +{{< section-heading align="left" + title="Support software review" + subtitle="pyOpenSci runs a community peer review process for research software written in Python. [Learn about peer review →](/about-peer-review/)" >}} -{{< swoosh_section background="purple" swoosh="bottom" >}} -{{< section-heading title="Volunteer opportunities with pyOpenSci" subtitle="There are many ways to get involved with pyOpenSci! We're always looking for folks to:" >}} {{< impact-cards >}} -{{< /swoosh_section >}} -## Share your expertise and experience with the broader community through blogging -And last but not least, we'd also love for you to be a guest blogger on the -[pyOpenSci blog](/blog/)! If you'd like to write about a pyOpenSci package, -your experiences with pyOpenSci, or how you're using free and open Python tools -in your scientific endeavors, we'd love to hear from you! Email our Community -team at [media@pyopensci.org](mailto:media@pyopensci.org) for more information. -{{% swoosh_section background="purple" swoosh="bottom" %}} -{{< figure src="/images/people/pyopensci-sprint-pycon-2023.png" alt="Contributors collaborating at a pyOpenSci sprint during PyCon US 2023." >}} +{{< section_band color="light-purple" divider="bottom" >}} + +{{< section-heading eyebrow="Translation" align="left" + title="Help break down language barriers" + subtitle="Our community is global. Our resources should be too. Translation volunteers make pyOpenSci's guides and tutorials accessible to scientists who don't work primarily in English. Translations for our [Python Packaging Guide](https://www.pyopensci.org/python-package-guide/) are in progress. Add a new language or support building out an existing on." >}} -### pyOpenSci volunteers come from diverse backgrounds +{{< impact-cards section="translation" >}} -Our volunteers come from a diverse array of backgrounds, including industry, -academia, agencies, national labs, and more. pyOpenSci volunteers are -primarily engaged in both the peer review process and developing resources to -support the scientific Python community. Volunteers help improve the quality, -maintainability and usability of the software that scientists need for open -science. They also support maintainers in developing scientific Python -software. +{{< /section_band >}} -{{% /swoosh_section %}} +{{< section-heading eyebrow="pyOpenSci Maintainer Team" align="left" + title="Help build and maintain our infrastructure" + subtitle="Our maintainer team keeps the website, guides, and tooling running. Roles follow a triage → merge → issue ownership progression. [Read the contributor handbook →](https://www.pyopensci.org/handbook/CONTRIBUTING.html)" >}} -{{< figure src="/images/people-building-blocks.jpg" alt="Illustration of people building blocks together, representing community collaboration." >}} +{{< impact-cards section="maintainer" >}} -### pyOpenSci volunteers build skills and community -When you volunteer with pyOpenSci, you're both giving back and developing -professional skills. As a volunteer you will: -* **Learn new skills:** you don't have to be a Python expert to get involved - with pyOpenSci. We can help you level up your packaging game and learn how - to constructively review both code and copy through contributions to our - online learning resources. -* **Get recognized** on the [pyOpenSci website](/our-community/) and in our - [GitHub repositories](https://github.com/pyOpenSci): your contribution - matters, and we want to ensure your work is recognized and celebrated in a - public forum. If you serve as an editor you can also connect with pyOpenSci - professionally as a volunteer for our organization on LinkedIn. -{{< swoosh_section background="purple" swoosh="top" >}} -{{< section-heading title="Meet the most recent pyOpenSci community contributors" >}} -{{< recent-contributors >}} -{{< button href="/our-community/" variant="green" icon="arrow-right" iconPosition="right" >}} -View all contributors -{{< /button >}} -{{< /swoosh_section >}} +{{< metrics-bar >}} -{{< connect-with-pyos >}} +{{< impact-destinations >}} diff --git a/content/ways-to-give.md b/content/ways-to-give.md index 86ba6c28..c87855a4 100644 --- a/content/ways-to-give.md +++ b/content/ways-to-give.md @@ -24,7 +24,7 @@ an individual funder passionate about open science, we offer clear pathways for you to support our mission. {{< /feature-row >}} -{{< swoosh_section background="purple" >}} +{{< section_band color="light-purple" >}} ## For companies: corporate sponsorship @@ -80,9 +80,9 @@ with different goals. Contact us to design a package that fits your team. Inquire to learn more {{< /button >}} -{{< /swoosh_section >}} +{{< /section_band >}} -{{< swoosh_section background="white" >}} +{{< section_band color="white" >}} ## For funders & community: direct donations @@ -122,4 +122,4 @@ access to world-class education while sustaining pyOpenSci's mission. Donate today {{< /button >}} -{{< /swoosh_section >}} +{{< /section_band >}} diff --git a/hugo.toml b/hugo.toml index 6841181a..0aeea11e 100644 --- a/hugo.toml +++ b/hugo.toml @@ -32,8 +32,8 @@ buildFuture = true # Upper-left nav: logo image (served from static/images/). [params.nav_logo] - src = 'images/logo.png' - alt = 'pyOpenSci logo: a purple flower opening over the O in Open, representing open science.' + src = 'images/logo-white.png' + alt = 'pyOpenSci logo: white flower icon above pyOpenSci wordmark.' blog_title = 'pyOpenSci Blog' description = 'pyOpenSci broadens participation in scientific open source.' @@ -133,7 +133,7 @@ buildFuture = true [params.nav_button] text = 'Donate' url = 'https://give.communityin.org/pyopensci_2024' - variant = 'dark-purple' + variant = 'green' # Site search — Algolia InstantSearch (ported from search branch / PR #788). [params.search] diff --git a/static/images/logo-white.png b/static/images/logo-white.png new file mode 100644 index 00000000..075b0e10 Binary files /dev/null and b/static/images/logo-white.png differ diff --git a/static/images/people/leah-chase-pavithra-carol.png b/static/images/people/leah-chase-pavithra-carol.png new file mode 100644 index 00000000..5c05a2b2 Binary files /dev/null and b/static/images/people/leah-chase-pavithra-carol.png differ diff --git a/static/images/people/leah-chase-pavithra-carol.webp b/static/images/people/leah-chase-pavithra-carol.webp new file mode 100644 index 00000000..5cb802dc Binary files /dev/null and b/static/images/people/leah-chase-pavithra-carol.webp differ diff --git a/themes/clean-hugo/assets/css/_blog.scss b/themes/clean-hugo/assets/css/_blog.scss index 301f9681..5f5c8c79 100644 --- a/themes/clean-hugo/assets/css/_blog.scss +++ b/themes/clean-hugo/assets/css/_blog.scss @@ -3,7 +3,7 @@ position: relative; padding: $spacing-xl 0; margin-bottom: $spacing-lg; - background-color: var(--color-primary-dark); + background-color: var(--color-surface-dark-purple); @media (min-width: $breakpoint-md) { padding: $spacing-xl 0; @@ -31,7 +31,7 @@ background-size: cover; background-repeat: no-repeat; background-position: center; - background-color: var(--color-primary-dark); + background-color: var(--color-surface-dark-purple); @media (min-width: $breakpoint-md) { min-height: 13rem; diff --git a/themes/clean-hugo/assets/css/_cards.scss b/themes/clean-hugo/assets/css/_cards.scss index 25ffbe6b..e85f06d7 100644 --- a/themes/clean-hugo/assets/css/_cards.scss +++ b/themes/clean-hugo/assets/css/_cards.scss @@ -1,8 +1,22 @@ /* Impact Cards Section - Hero/splash page cards */ .impact-cards { + padding: $fluid-space-2xl 0; +} + +.impact-cards__container { max-width: $container-max-width; - margin: 0 auto; - padding: $fluid-space-2xl $fluid-container-padding; + width: 100%; + margin-inline: auto; + padding-inline: $fluid-container-padding; + box-sizing: border-box; +} + +.impact-cards--align-left .impact-cards__container { + margin-inline: 0 auto 0 0; +} + +.impact-cards--align-right .impact-cards__container { + margin-inline: 0 0 0 auto; } .impact-cards__grid { @@ -17,7 +31,9 @@ /* Opt-in from page front matter: cards_layout: wide */ .impact-cards--wide { - max-width: $container-impact-wide; + .impact-cards__container { + max-width: $container-impact-wide; + } } .impact-cards__grid--wide { @@ -26,6 +42,33 @@ } } +/* Opt-in: cards_layout: five — 3 cards, then 2 centered (volunteer peer review) */ +.impact-cards--five { + padding-top: 0; + + .impact-cards__container { + max-width: $container-impact-wide; + } +} + +.impact-cards__grid--five { + @media (min-width: $breakpoint-lg) { + grid-template-columns: repeat(6, minmax(0, 1fr)); + + > .card { + grid-column: span 2; + } + + > .card:nth-child(4) { + grid-column: 2 / span 2; + } + + > .card:nth-child(5) { + grid-column: 4 / span 2; + } + } +} + /* Impact cards - fluid padding scales from mobile to desktop */ .impact-cards .card { padding: $fluid-card-padding-lg; @@ -59,8 +102,12 @@ } .impact-cards { + padding-inline: 0; + } + + .impact-cards__container { max-width: none; - margin: 0; + margin-inline: 0; padding-inline: 0; } } @@ -172,6 +219,73 @@ box-shadow: 0 6px 18px rgba(17,24,39,0.06); } + .card__header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 0.75rem; + margin-bottom: 0.75rem; + } + + .card__header h3 { + flex: 1 1 auto; + min-width: 0; + margin-bottom: 0; + } + + .card__label { + flex-shrink: 0; + display: inline-flex; + align-items: center; + font-size: 0.75rem; + font-weight: 600; + padding: 0.3rem 0.65rem; + border-radius: $radius-full; + line-height: 1.2; + white-space: nowrap; + } + + .card__label--accent { + background-color: var(--color-admonition-success, var(--color-primary)); + color: var(--color-white); + } + + .card__label--team { + background-color: var(--color-brand-light-purple); + color: var(--color-brand-purple); + } + + .card__label--stipend { + background-color: var(--color-secondary); + color: var(--color-gray-900); + } + + .card__label--default { + background-color: var(--color-gray-200); + color: var(--color-gray-700); + } + + .card__tags { + display: flex; + flex-wrap: wrap; + gap: 0.4rem; + margin: 0 0 1rem; + padding: 0; + list-style: none; + } + + .card__tag { + display: inline-flex; + align-items: center; + font-size: 0.75rem; + font-weight: 500; + padding: 0.25rem 0.55rem; + border-radius: $radius-full; + line-height: 1.2; + background-color: var(--color-gray-200); + color: var(--color-gray-700); + } + .card { @include card-base(); @include responsive-padding(1.25rem, 1.25rem, 2.5rem, 2.5rem); @@ -188,6 +302,7 @@ font-size: 1.5rem; } } + > div > .card__excerpt, > div > h3 + div { font-size: $card-text-size; line-height: $card-line-height; @@ -242,6 +357,25 @@ background-color: var(--color-white); } + /* Stipended volunteer roles — light green fill (after .card base white) */ + .card--stipend { + border-color: var(--color-admonition-success); + background-color: color-mix( + in srgb, + var(--color-admonition-success) 35%, + var(--color-white) + ); + } + + .card--featured { + border-color: var(--color-secondary); + background-color: color-mix( + in srgb, + var(--color-secondary) 18%, + var(--color-white) + ); + } + .card__icon { font-size: $card-icon-size; margin-bottom: 1rem; diff --git a/themes/clean-hugo/assets/css/_content.scss b/themes/clean-hugo/assets/css/_content.scss index 81fcc3ef..3580fad6 100644 --- a/themes/clean-hugo/assets/css/_content.scss +++ b/themes/clean-hugo/assets/css/_content.scss @@ -159,8 +159,9 @@ .content-main > .two-card-row, .content-main > .three-card-row, .content-main > .impact-cards, -.content-main > .swoosh-section, -.content-main > .swoosh-section__divider-wrap, +.content-main > .section-band, +.content-main > .section-band__divider-wrap, +.content-main > .impact-destinations, .splash-page__content > .metrics-bar, .splash-page__content > .blog-highlight, .splash-page__content > .single-card-wide, @@ -168,8 +169,9 @@ .splash-page__content > .two-card-row, .splash-page__content > .three-card-row, .splash-page__content > .impact-cards, -.splash-page__content > .swoosh-section, -.splash-page__content > .swoosh-section__divider-wrap { +.splash-page__content > .section-band, +.splash-page__content > .section-band__divider-wrap, +.splash-page__content > .impact-destinations { width: 100vw; position: relative; left: 50%; diff --git a/themes/clean-hugo/assets/css/_feature-row.scss b/themes/clean-hugo/assets/css/_feature-row.scss index 543a5fbf..0a29b94d 100644 --- a/themes/clean-hugo/assets/css/_feature-row.scss +++ b/themes/clean-hugo/assets/css/_feature-row.scss @@ -12,6 +12,10 @@ display: grid; gap: 1.5rem; align-items: start; + + @media (min-width: $breakpoint-md) { + align-items: center; + } } &__media { @@ -54,8 +58,8 @@ &--left { .feature-row__inner { @media (min-width: $breakpoint-md) { - /* Image ~33%, text ~66% */ - grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); + /* Image 2/5, text 3/5 */ + grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); } } } @@ -63,8 +67,8 @@ &--right { .feature-row__inner { @media (min-width: $breakpoint-md) { - /* Text ~66%, image ~33% (body fills col 1 via order) */ - grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); + /* Text 3/5, image 2/5 (body fills col 1 via order) */ + grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); .feature-row__media { order: 2; diff --git a/themes/clean-hugo/assets/css/_impact-destinations.scss b/themes/clean-hugo/assets/css/_impact-destinations.scss new file mode 100644 index 00000000..c81c1ddf --- /dev/null +++ b/themes/clean-hugo/assets/css/_impact-destinations.scss @@ -0,0 +1,135 @@ +/* Dark purple band — “where your work goes” */ + +.impact-destinations { + width: 100%; + padding: $fluid-space-2xl $fluid-container-padding; + background-color: var(--color-surface-dark-purple-card); + color: var(--color-white); + box-sizing: border-box; + + &__container { + max-width: $container-max-width; + margin-inline: auto; + } + + &__header { + max-width: 42rem; + margin-bottom: $fluid-space-lg; + + /* Beat .splash-page__content p { color: gray-700 } */ + .impact-destinations__eyebrow { + margin: 0 0 0.5rem; + font-family: $font-family-heading; + font-size: 0.8125rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--color-admonition-success); + } + + .impact-destinations__subtitle { + margin: 0; + font-size: 1.0625rem; + line-height: 1.6; + color: var(--color-white); + } + } + + &__title { + margin: 0 0 0.75rem; + font-size: clamp(1.75rem, 4vw, 2.5rem); + font-weight: 700; + line-height: 1.2; + color: var(--color-white); + } + + &__grid { + display: grid; + gap: 1rem; + grid-template-columns: 1fr; + + @media (min-width: $breakpoint-md) { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + @media (min-width: $breakpoint-lg) { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } + } + + &__card { + display: flex; + align-items: flex-start; + gap: 1rem; + padding: 1.25rem 1.5rem; + border-radius: $radius-lg; + border: 1px solid color-mix( + in srgb, + var(--color-brand-medium-purple) 35%, + transparent + ); + background-color: var(--color-surface-footer-purple); + color: var(--color-white); + text-decoration: none; + transition: border-color $transition-base ease, + transform $transition-base ease; + + @media (min-width: $breakpoint-lg) { + grid-column: span 2; + } + + &:nth-child(4) { + @media (min-width: $breakpoint-lg) { + grid-column: 2 / span 2; + } + } + + &:nth-child(5) { + @media (min-width: $breakpoint-lg) { + grid-column: 4 / span 2; + } + } + + &:hover, + &:focus-visible { + border-color: color-mix( + in srgb, + var(--color-admonition-success) 55%, + transparent + ); + transform: translateY(-2px); + } + + /* Beat .splash-page__content p { color: gray-700 } */ + .impact-destinations__card-text { + margin: 0; + font-size: 0.9375rem; + line-height: 1.5; + color: color-mix(in srgb, var(--color-white) 90%, transparent); + } + } + + &__icon { + flex-shrink: 0; + display: inline-flex; + align-items: center; + justify-content: center; + width: 2.5rem; + height: 2.5rem; + font-size: 1.25rem; + color: var(--color-admonition-success); + } + + &__body { + min-width: 0; + } + + &__card-title { + margin: 0 0 0.35rem; + font-family: $font-family-heading; + font-size: 1.0625rem; + font-weight: 700; + line-height: 1.3; + color: var(--color-white); + } +} diff --git a/themes/clean-hugo/assets/css/_navigation.scss b/themes/clean-hugo/assets/css/_navigation.scss index 4d5bcb35..c0c8770e 100644 --- a/themes/clean-hugo/assets/css/_navigation.scss +++ b/themes/clean-hugo/assets/css/_navigation.scss @@ -1,8 +1,7 @@ -/* Site navigation */ +/* Site navigation — dark purple banner with light text */ .site-nav { - border-bottom: 1px solid var(--color-gray-200); position: relative; - background-color: var(--color-white); + background-color: var(--color-brand-purple); z-index: 1000; } @@ -22,16 +21,16 @@ .site-nav__brand { font-size: 1.5rem; font-weight: 700; - color: var(--color-gray-900); + color: var(--color-white); text-decoration: none; &:hover { - color: var(--color-link); + color: var(--color-link-on-dark); } &:focus { - color: var(--color-link); - outline: 2px solid var(--color-link); + color: var(--color-link-on-dark); + outline: 2px solid var(--color-link-on-dark); outline-offset: 2px; } @@ -64,7 +63,11 @@ width: 2.5rem; height: 2.5rem; padding: 0.5rem; - border: 1px solid var(--color-gray-200); + border: 1px solid color-mix( + in srgb, + var(--color-white) 35%, + transparent + ); border-radius: 0.25rem; background-color: transparent; cursor: pointer; @@ -72,12 +75,17 @@ flex-shrink: 0; &:hover { - background-color: var(--color-gray-50); + background-color: color-mix( + in srgb, + var(--color-white) 10%, + transparent + ); } &:focus { outline: none; - box-shadow: 0 0 0 2px var(--color-link), 0 0 0 4px var(--color-white); + box-shadow: 0 0 0 2px var(--color-link-on-dark), + 0 0 0 4px var(--color-brand-purple); } &[aria-expanded="true"] { @@ -108,7 +116,7 @@ width: 1.25rem; height: 0.125rem; margin-bottom: 0.25rem; - background-color: var(--color-gray-900); + background-color: var(--color-white); transition: all 0.2s; &:last-child { @@ -124,9 +132,13 @@ 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); + background-color: var(--color-brand-purple); + border-top: 1px solid color-mix( + in srgb, + var(--color-white) 12%, + transparent + ); + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.25); padding-block: 1rem; &[aria-expanded="true"], @@ -156,17 +168,18 @@ font-weight: 500; transition: color 0.2s; display: block; - color: var(--color-gray-900); + color: var(--color-white); text-decoration: none; &:hover { - color: var(--color-link); + color: var(--color-link-on-dark); } &:focus { - color: var(--color-link); + color: var(--color-link-on-dark); outline: none; - box-shadow: 0 0 0 2px var(--color-link), 0 0 0 4px var(--color-white); + box-shadow: 0 0 0 2px var(--color-link-on-dark), + 0 0 0 4px var(--color-brand-purple); } } @@ -291,11 +304,30 @@ /* 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; } + + /* Solid pyOpenSci green on dark nav */ + &.btn--green { + background-color: var(--color-admonition-success); + color: var(--color-gray-900); + + &:hover { + background-color: color-mix( + in srgb, + var(--color-admonition-success) 85%, + var(--color-gray-900) + ); + color: var(--color-gray-900); + } + + &:focus { + box-shadow: 0 0 0 2px var(--color-brand-purple), + 0 0 0 4px var(--color-admonition-success); + } + } } diff --git a/themes/clean-hugo/assets/css/_people.scss b/themes/clean-hugo/assets/css/_people.scss index 77a92711..725a051b 100644 --- a/themes/clean-hugo/assets/css/_people.scss +++ b/themes/clean-hugo/assets/css/_people.scss @@ -94,10 +94,10 @@ margin-top: 3rem; } - /* Home / volunteer recent contributors — fluid cards, no awkward 4+1 wrap */ + /* Home / volunteer recent contributors — compact row of five */ .people-grid.people-grid--recent { margin-top: 1.5rem; - gap: clamp(0.75rem, 1.5vw, 1rem); + gap: clamp(0.5rem, 1.25vw, 0.875rem); grid-template-columns: minmax(0, 1fr); @media (min-width: $breakpoint-sm) { @@ -109,27 +109,38 @@ } @media (min-width: $breakpoint-lg) { - grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr)); + grid-template-columns: repeat(5, minmax(0, 1fr)); + } + + .people_card__image { + aspect-ratio: 3 / 2; } .people_card__content { - padding: clamp(0.65rem, 1.25vw, 1rem); + padding: clamp(0.5rem, 1vw, 0.75rem); h3 { - font-size: clamp(0.9375rem, 1.5vw, 1.125rem); + font-size: clamp(0.875rem, 1.35vw, 1rem); + margin-bottom: 0.25rem; } } .people_card__title, .people_card__org { - font-size: clamp(0.6875rem, 1.1vw, 0.75rem); + font-size: clamp(0.625rem, 1vw, 0.6875rem); + margin-bottom: 0.25rem; + } + + .people_card__org { + margin-bottom: 0.375rem; } .people_card__social { - font-size: clamp(0.6875rem, 1vw, 0.75rem); + font-size: clamp(0.625rem, 0.95vw, 0.6875rem); + gap: 0.375rem; i { - font-size: clamp(0.75rem, 1.1vw, 0.875rem); + font-size: clamp(0.6875rem, 1vw, 0.75rem); } } } diff --git a/themes/clean-hugo/assets/css/_search.scss b/themes/clean-hugo/assets/css/_search.scss index 5f337997..3819757a 100644 --- a/themes/clean-hugo/assets/css/_search.scss +++ b/themes/clean-hugo/assets/css/_search.scss @@ -11,23 +11,31 @@ height: 2.5rem; margin-top: 1rem; padding: 0; - border: 1px solid var(--color-gray-200); + border: 1px solid color-mix( + in srgb, + var(--color-white) 35%, + transparent + ); border-radius: $radius-sm; background-color: transparent; - color: var(--color-gray-900); + color: var(--color-white); cursor: pointer; transition: background-color $transition-base, color $transition-base; &:hover { - background-color: var(--color-gray-50); - color: var(--color-link); + background-color: color-mix( + in srgb, + var(--color-white) 10%, + transparent + ); + color: var(--color-link-on-dark); } &:focus { outline: none; - box-shadow: 0 0 0 2px var(--color-link), - 0 0 0 4px var(--color-white); + box-shadow: 0 0 0 2px var(--color-link-on-dark), + 0 0 0 4px var(--color-brand-purple); } @media (min-width: $breakpoint-md) { diff --git a/themes/clean-hugo/assets/css/_section-band.scss b/themes/clean-hugo/assets/css/_section-band.scss new file mode 100644 index 00000000..f2924be8 --- /dev/null +++ b/themes/clean-hugo/assets/css/_section-band.scss @@ -0,0 +1,173 @@ +/** + * Section bands: full-width colored blocks with optional curved SVG dividers. + * color param: white | light-purple | soft-purple | green | brand-purple + */ + +.section-band { + width: 100vw; + position: relative; + left: 50%; + margin: 0 -50vw; + padding: 0; +} + +.section-band__content { + max-width: $container-max-width; + margin-inline: auto; + padding: $fluid-space-2xl $fluid-container-padding; +} + +/* Color modifiers — backgrounds and divider wave fills from theme variables */ +.section-band--white { + background-color: var(--color-white); + --section-band-fill-1: var(--color-white); + --section-band-fill-2: var(--color-white); +} + +.section-band--light-purple { + background-color: var(--color-light-purple); + --section-band-fill-1: var(--color-soft-purple); + --section-band-fill-2: var(--color-light-purple); +} + +.section-band--soft-purple { + background-color: var(--color-soft-purple); + --section-band-fill-1: color-mix( + in srgb, + var(--color-brand-medium-purple) 65%, + var(--color-soft-purple) + ); + --section-band-fill-2: var(--color-soft-purple); +} + +.section-band--green { + background-color: var(--color-primary-light); + --section-band-fill-1: color-mix( + in srgb, + var(--color-primary) 40%, + var(--color-primary-light) + ); + --section-band-fill-2: var(--color-primary-light); +} + +.section-band--brand-purple { + background-color: var(--color-brand-purple); + --section-band-fill-1: var(--color-brand-medium-purple); + --section-band-fill-2: var(--color-brand-purple); +} + +/* Divider fill when rendered outside the band (top/bottom partials) */ +.section-band__divider--white { + --section-band-fill-1: var(--color-white); + --section-band-fill-2: var(--color-white); +} + +.section-band__divider--light-purple { + --section-band-fill-1: var(--color-soft-purple); + --section-band-fill-2: var(--color-light-purple); +} + +.section-band__divider--soft-purple { + --section-band-fill-1: color-mix( + in srgb, + var(--color-brand-medium-purple) 65%, + var(--color-soft-purple) + ); + --section-band-fill-2: var(--color-soft-purple); +} + +.section-band__divider--green { + --section-band-fill-1: color-mix( + in srgb, + var(--color-primary) 40%, + var(--color-primary-light) + ); + --section-band-fill-2: var(--color-primary-light); +} + +.section-band__divider--brand-purple { + --section-band-fill-1: var(--color-brand-medium-purple); + --section-band-fill-2: var(--color-brand-purple); +} + +.section-band__divider-wrap { + width: 100vw; + position: relative; + left: 50%; + margin-inline: -50vw; +} + +.section-band--docs, +.section-band__divider-wrap--docs { + width: 100%; + max-width: 100%; + inset-inline: auto; + margin-inline: 0; +} + +.section-band__divider { + position: relative; + width: 100%; + line-height: 0; +} + +.section-band__divider--bottom { + margin-top: 0; +} + +.section-band__divider--top { + margin-bottom: 0; +} + +.section-band__svg { + display: block; + width: 100%; + height: auto; +} + +.section-band__wave--1 { + fill: var(--section-band-fill-1); + opacity: 0.9; +} + +.section-band__wave--2 { + fill: var(--section-band-fill-2); +} + +.section-band__divider--bottom .section-band__svg { + vertical-align: bottom; +} + +.section-band__divider--top .section-band__svg { + vertical-align: top; +} + +/* Nested shortcodes: stay contained inside the band (no viewport breakout) */ +.section-band__content { + > .impact-cards, + > .section-heading, + > .metrics-bar, + > .two-card-row, + > .three-card-row, + > .single-card-wide { + width: 100%; + position: static; + left: auto; + margin-inline: 0; + } + + > .impact-cards { + padding-top: 0; + padding-inline: 0; + + .impact-cards__container { + max-width: 100%; + padding-inline: 0; + } + } + + > .section-heading.container { + max-width: 100%; + padding-inline: 0; + } +} diff --git a/themes/clean-hugo/assets/css/_shortcodes.scss b/themes/clean-hugo/assets/css/_shortcodes.scss index 23ca9f30..4202d20d 100644 --- a/themes/clean-hugo/assets/css/_shortcodes.scss +++ b/themes/clean-hugo/assets/css/_shortcodes.scss @@ -40,6 +40,24 @@ } } + /* Metrics + dark band flush above site footer */ + .splash-page__content > .metrics-bar + .impact-destinations { + margin-top: 0; + } + + .splash-page__content > .metrics-bar:has(+ .impact-destinations) { + margin-bottom: 0; + } + + .splash-page__content > .impact-destinations:last-child { + margin-bottom: 0; + } + + .page-content:has(.splash-page__content > .impact-destinations:last-child) + .site-footer { + margin-top: 0; + } + /* Two Card Row */ .two-card-row { padding: 1.5rem 0; @@ -264,4 +282,26 @@ @include responsive(font-size, 1.125rem, 1.25rem); opacity: 0.8; color: var(--color-gray-600); + + p:last-child { + margin-bottom: 0; + } + } + + .section-heading--left { + text-align: left; + + .section-heading__subtitle { + text-align: left; + max-width: 42rem; + } + } + + .section-heading__eyebrow { + margin: 0 0 0.5rem; + font-size: 0.8125rem; + font-weight: 700; + letter-spacing: 0.06em; + text-transform: uppercase; + color: var(--color-primary); } diff --git a/themes/clean-hugo/assets/css/_swoosh.scss b/themes/clean-hugo/assets/css/_swoosh.scss deleted file mode 100644 index c50488a9..00000000 --- a/themes/clean-hugo/assets/css/_swoosh.scss +++ /dev/null @@ -1,109 +0,0 @@ -/** - * 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/main.scss b/themes/clean-hugo/assets/css/main.scss index 27ac00bc..f88e6a38 100644 --- a/themes/clean-hugo/assets/css/main.scss +++ b/themes/clean-hugo/assets/css/main.scss @@ -114,6 +114,24 @@ xl: 1280px from site configuration (hugo.toml or theme.toml defaults) */ + :root { + --color-surface-dark-purple: color-mix( + in srgb, + var(--color-brand-purple) 85%, + black + ); + --color-surface-dark-purple-card: color-mix( + in srgb, + var(--color-brand-purple) 68%, + black + ); + --color-surface-footer-purple: color-mix( + in srgb, + var(--color-brand-purple) 92%, + black + ); + } + body { font-family: $font-family-body; color: var(--color-gray-900); @@ -276,9 +294,10 @@ xl: 1280px @import 'cards'; @import 'feature-row'; @import 'intro-section'; +@import 'impact-destinations'; @import 'training-feature'; @import 'home-bands'; -@import 'swoosh'; +@import 'section-band'; @import 'footer'; @import 'shortcodes'; @import 'admonition'; diff --git a/themes/clean-hugo/layouts/_default/packages-list.html b/themes/clean-hugo/layouts/_default/packages-list.html index c7cd1d76..c27d0485 100644 --- a/themes/clean-hugo/layouts/_default/packages-list.html +++ b/themes/clean-hugo/layouts/_default/packages-list.html @@ -1,16 +1,10 @@ {{ 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) }} +{{ $scratch := newScratch }} +{{ partial "metrics/build-stats.html" (dict "context" . "set" "packages" "scratch" $scratch) }} +{{ partial "metrics-bar-render.html" (dict "stats" ($scratch.Get "stats")) }}
diff --git a/themes/clean-hugo/layouts/partials/cards.html b/themes/clean-hugo/layouts/partials/cards.html index 8177424e..d9c19c8b 100644 --- a/themes/clean-hugo/layouts/partials/cards.html +++ b/themes/clean-hugo/layouts/partials/cards.html @@ -3,9 +3,15 @@ - Use text_only: true in front matter to render a plain white, non-interactive text card. - Otherwise renders the interactive highlight card (supports Font Awesome class strings or raw HTML icons). - Optional image (map: src, alt) renders a 16:9 strip at the top; optional event_type shows the same pill as event cards. + - Optional label + label_style (accent | team | stipend | default) for a top-right pill. + - modifier card--stipend: light green background for stipended roles. + - Optional tags (list) for secondary grey pills below the title. --> {{ $icon := .icon }} +{{ $label := .label }} +{{ $labelStyle := .label_style | default "default" }} +{{ $tags := .tags }} {{ $textOnly := false }} {{ if reflect.IsMap . }} {{ if .text_only }} @@ -47,13 +53,25 @@

{{ 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 }}

+
+

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

+ {{ with $label }} + {{ . }} + {{ end }} +
+ {{ with $tags }} +
    + {{ range . }} +
  • {{ . }}
  • + {{ end }} +
+ {{ end }} {{ with .excerpt }} -
{{ . | markdownify }}
+
{{ . | markdownify }}
{{ end }}
diff --git a/themes/clean-hugo/layouts/partials/impact-cards.html b/themes/clean-hugo/layouts/partials/impact-cards.html index b21bae27..27f22cd7 100644 --- a/themes/clean-hugo/layouts/partials/impact-cards.html +++ b/themes/clean-hugo/layouts/partials/impact-cards.html @@ -1,15 +1,55 @@ - -{{ $wide := eq (lower (default "" .Params.cards_layout)) "wide" }} -
-
- {{ $cards := .Params.cards }} - {{ if $cards }} - {{ range $i, $c := $cards }} - {{ partial "cards.html" (merge $c (dict "page" $)) }} + Optional section param: reads {section}_cards (e.g. translation_cards). + Optional: cards_layout / {section}_cards_layout: wide. + Optional: cards_align / {section}_cards_align: left | center | right (default: center). + Shortcode align param overrides page alignment. --> + +{{ $page := . }} +{{ $section := "" }} +{{ $align := "" }} +{{ if and (reflect.IsMap .) (isset . "page") }} + {{ $page = .page }} + {{ $align = .align | default "" }} + {{ $section = .section | default "" }} +{{ end }} + +{{ $cardsKey := "cards" }} +{{ $alignKey := "cards_align" }} +{{ $layoutKey := "cards_layout" }} +{{ if ne $section "" }} + {{ $cardsKey = printf "%s_cards" $section }} + {{ $alignKey = printf "%s_cards_align" $section }} + {{ $layoutKey = printf "%s_cards_layout" $section }} +{{ end }} + +{{ if eq $align "" }} + {{ $align = index $page.Params $alignKey | default ($page.Params.cards_align | default "center") }} +{{ end }} +{{ $align = lower $align }} +{{ if not (in (slice "left" "center" "right") $align) }} + {{ $align = "center" }} +{{ end }} + +{{ $layout := "" }} +{{ if ne $section "" }} + {{ $layout = index $page.Params $layoutKey | default "" }} +{{ else }} + {{ $layout = index $page.Params "cards_layout" | default "" }} +{{ end }} +{{ $layoutLower := lower $layout }} +{{ $wide := eq $layoutLower "wide" }} +{{ $five := eq $layoutLower "five" }} +
+
+
+ {{ $cards := index $page.Params $cardsKey }} + {{ if $cards }} + {{ range $i, $c := $cards }} + {{ partial "cards.html" (merge $c (dict "page" $page)) }} + {{ end }} {{ end }} - {{ end }} +
diff --git a/themes/clean-hugo/layouts/partials/impact-destinations.html b/themes/clean-hugo/layouts/partials/impact-destinations.html new file mode 100644 index 00000000..0fa8b0b3 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/impact-destinations.html @@ -0,0 +1,69 @@ + + +{{ $page := . }} +{{ $section := "" }} +{{ if and (reflect.IsMap .) (isset . "page") }} + {{ $page = .page }} + {{ $section = .section | default "" }} +{{ end }} + +{{ $dataKey := "impact_destinations" }} +{{ if ne $section "" }} + {{ $dataKey = printf "%s_impact_destinations" $section }} +{{ end }} + +{{ $data := index $page.Params $dataKey }} +{{ if $data }} +
+
+
+ {{ with $data.eyebrow }} +

{{ . }}

+ {{ end }} + {{ with $data.title }} +

{{ . }}

+ {{ end }} + {{ with $data.subtitle }} +

{{ . | markdownify }}

+ {{ end }} +
+ + {{ with $data.items }} +
+ {{ range . }} + {{ if and .url (ne (printf "%s" .url) "") }} + + {{ with .icon }} + + {{ end }} +
+

{{ .title }}

+ {{ with .excerpt }} +

{{ . }}

+ {{ end }} +
+
+ {{ else }} +
+ {{ with .icon }} + + {{ end }} +
+

{{ .title }}

+ {{ with .excerpt }} +

{{ . }}

+ {{ end }} +
+
+ {{ end }} + {{ end }} +
+ {{ end }} +
+
+{{ end }} diff --git a/themes/clean-hugo/layouts/partials/metrics-bar-render.html b/themes/clean-hugo/layouts/partials/metrics-bar-render.html index 33bbcb7f..d8765405 100644 --- a/themes/clean-hugo/layouts/partials/metrics-bar-render.html +++ b/themes/clean-hugo/layouts/partials/metrics-bar-render.html @@ -1,7 +1,10 @@ {{/* Metrics Bar Renderer A partial that renders the metrics bar HTML structure within a layout - Usage: {{ partial "metrics-bar-render.html" (dict "stats" (slice "**5** Packages" "**10** Users")) }} + Usage: + {{ $scratch := newScratch }} + {{ partial "metrics/build-stats.html" (dict "context" . "set" "volunteer" "scratch" $scratch) }} + {{ partial "metrics-bar-render.html" (dict "stats" ($scratch.Get "stats")) }} */}} {{ $stats := .stats | default slice }} diff --git a/themes/clean-hugo/layouts/partials/metrics/build-stats.html b/themes/clean-hugo/layouts/partials/metrics/build-stats.html new file mode 100644 index 00000000..382746fc --- /dev/null +++ b/themes/clean-hugo/layouts/partials/metrics/build-stats.html @@ -0,0 +1,21 @@ +{{/* + Build a metrics-bar stats slice from a named preset or explicit values. + Sets "stats" on the passed scratch map. + + Usage: + {{ $scratch := newScratch }} + {{ partial "metrics/build-stats.html" (dict + "context" .Page + "set" "volunteer" + "scratch" $scratch + ) }} + {{ $stats := $scratch.Get "stats" }} +*/}} +{{ $set := .set | default "" }} +{{ if eq $set "volunteer" }} + {{ partial "metrics/presets/volunteer.html" . }} +{{ else if eq $set "packages" }} + {{ partial "metrics/presets/packages.html" . }} +{{ else if .stats }} + {{ .scratch.Set "stats" .stats }} +{{ end }} diff --git a/themes/clean-hugo/layouts/partials/metrics/presets/packages.html b/themes/clean-hugo/layouts/partials/metrics/presets/packages.html new file mode 100644 index 00000000..d09df7a6 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/metrics/presets/packages.html @@ -0,0 +1,12 @@ +{{/* + Python packages catalog metrics — live counts from packages data. +*/}} +{{ $ctx := .context }} +{{ $scratch := .scratch }} +{{ $pkgStats := partial "calculate-package-stats.html" $ctx }} +{{ $scratch.Set "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) +) }} diff --git a/themes/clean-hugo/layouts/partials/metrics/presets/volunteer.html b/themes/clean-hugo/layouts/partials/metrics/presets/volunteer.html new file mode 100644 index 00000000..355f8b62 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/metrics/presets/volunteer.html @@ -0,0 +1,13 @@ +{{/* + Volunteer page metrics — live counts from site data. +*/}} +{{ $ctx := .context }} +{{ $scratch := .scratch }} +{{ $pkgStats := partial "calculate-package-stats.html" $ctx }} +{{ $contributors := len ($ctx.Site.Data.contributors | default slice) }} +{{ $scratch.Set "stats" (slice + (printf "**%d** contributors" $contributors) + (printf "**%d** maintainers" $pkgStats.maintainers) + (printf "**%d** packages accepted" $pkgStats.total) + "**3** languages" +) }} diff --git a/themes/clean-hugo/layouts/partials/section-band-divider-bottom.html b/themes/clean-hugo/layouts/partials/section-band-divider-bottom.html new file mode 100644 index 00000000..cc86c54c --- /dev/null +++ b/themes/clean-hugo/layouts/partials/section-band-divider-bottom.html @@ -0,0 +1,20 @@ +{{/* Curved divider at bottom of a section band (wave into next section). */}} +{{ $color := .color | default "light-purple" }} +{{ if eq $color "purple" }}{{ $color = "light-purple" }}{{ end }} + diff --git a/themes/clean-hugo/layouts/partials/section-band-divider-top.html b/themes/clean-hugo/layouts/partials/section-band-divider-top.html new file mode 100644 index 00000000..04e851c8 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/section-band-divider-top.html @@ -0,0 +1,19 @@ +{{/* Curved divider at top of a section band (wave down from previous section). */}} +{{ $color := .color | default "light-purple" }} +{{ if eq $color "purple" }}{{ $color = "light-purple" }}{{ end }} + diff --git a/themes/clean-hugo/layouts/partials/section-band-inner-content.html b/themes/clean-hugo/layouts/partials/section-band-inner-content.html new file mode 100644 index 00000000..e32e4106 --- /dev/null +++ b/themes/clean-hugo/layouts/partials/section-band-inner-content.html @@ -0,0 +1,45 @@ +{{/* + Render section band inner content. + + {{< section_band >}} with nested shortcodes only: Hugo pre-renders them to HTML; + pass through with safeHTML. + + Unprocessed shortcode markers: RenderString once to execute them. + + Mixed markdown + shortcode HTML (e.g. ways-to-give): split blocks so markdown + renders without re-processing HTML into
 fences.
+
+  {{% section_band %}} — markdown prose only; do not nest {{< shortcodes >}}.
+*/}}
+{{- $inner := replace .inner "\r\n" "\n" -}}
+{{- $page := .page -}}
+{{- $trimmed := trim $inner " \n\r\t" -}}
+{{- $m := "SECTIONBANDSPLIT" -}}
+{{- $hasShortcodes := findRE `\{\{[%<]` $inner -}}
+
+{{- if $hasShortcodes -}}
+  {{ $inner | $page.RenderString }}
+{{- else if hasPrefix $trimmed "<" -}}
+  {{ $inner | safeHTML }}
+{{- else -}}
+  {{- $inner = replaceRE `\n\n+(<(?:div|section|figure|a |article))` "\n\nSECTIONBANDSPLIT$1" $inner -}}
+  {{- $inner = replaceRE `(?s)(
)\s*\n\n+(### )` "$1\n\nSECTIONBANDSPLIT$2" $inner -}} + {{- $inner = replaceRE `(?s)(
)\s*\n\n+(## )` "$1\n\nSECTIONBANDSPLIT$2" $inner -}} + {{- $inner = replaceRE `(?s)(
)\s*\n\n+(\| )` "$1\n\nSECTIONBANDSPLIT$2" $inner -}} + {{- $inner = replaceRE `(?s)(
)\s*\n\n+([A-Z][a-z])` "$1\n\nSECTIONBANDSPLIT$2" $inner -}} + {{- $inner = replaceRE `(?s)()\s*\n\n+(### )` "$1\n\nSECTIONBANDSPLIT$2" $inner -}} + {{- $inner = replaceRE `(?s)()\s*\n\n+(## )` "$1\n\nSECTIONBANDSPLIT$2" $inner -}} + {{- $inner = replaceRE `(?s)()\s*\n\n+(### )` "$1\n\nSECTIONBANDSPLIT$2" $inner -}} + {{- $inner = replaceRE `(?s)()\s*\n\n+(## )` "$1\n\nSECTIONBANDSPLIT$2" $inner -}} + {{- $inner = replaceRE `(?s)()\s*\n\n+(\| )` "$1\n\nSECTIONBANDSPLIT$2" $inner -}} + {{- $inner = replaceRE `(?s)()\s*\n\n+([A-Z][a-z])` "$1\n\nSECTIONBANDSPLIT$2" $inner -}} + {{- range split $inner $m -}} + {{- $block := trim . " \n\r\t" -}} + {{- if not $block -}} + {{- else if hasPrefix $block "<" -}} + {{ $block | safeHTML }} + {{- else -}} + {{ $block | $page.RenderString }} + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/themes/clean-hugo/layouts/partials/section-band-legacy.html b/themes/clean-hugo/layouts/partials/section-band-legacy.html new file mode 100644 index 00000000..c7e14ebc --- /dev/null +++ b/themes/clean-hugo/layouts/partials/section-band-legacy.html @@ -0,0 +1,30 @@ +{{/* Maps legacy swoosh_section shortcode to section_band. */}} +{{- $color := .Get "color" | default (.Get "background" | default "white") -}} +{{- if eq $color "purple" }}{{ $color = "light-purple" }}{{ end -}} +{{- $divider := .Get "divider" | default (.Get "swoosh" | default "none") -}} +{{- $layout := .Get "layout" | default "" -}} +{{- $docsClass := "" -}} +{{- if eq $layout "docs" }}{{ $docsClass = " section-band--docs" }}{{ end -}} +{{- $wrapDocsClass := "" -}} +{{- if eq $layout "docs" }}{{ $wrapDocsClass = " section-band__divider-wrap--docs" }}{{ end -}} + +{{- $inner := trim .InnerDeindent " \n\t\r" -}} +{{- if eq $divider "top" -}} +
+ {{ partial "section-band-divider-top.html" (dict "color" $color) }} +
+{{- end -}} + +{{- if $inner -}} +
+
+ {{ partial "section-band-inner-content.html" (dict "inner" $inner "page" .Page) }} +
+
+{{- end -}} + +{{- if eq $divider "bottom" -}} +
+ {{ partial "section-band-divider-bottom.html" (dict "color" $color) }} +
+{{- end -}} diff --git a/themes/clean-hugo/layouts/partials/section-hero.html b/themes/clean-hugo/layouts/partials/section-hero.html index baee5889..f005f481 100644 --- a/themes/clean-hugo/layouts/partials/section-hero.html +++ b/themes/clean-hugo/layouts/partials/section-hero.html @@ -1,11 +1,26 @@ {{/* - Section listing hero — shared by blog and events index pages. + Section listing hero — shared by blog, events, and splash pages. Expects .Params.header.overlay_image, .Title, .Description. + Uses a sibling .webp when present (same path, .png/.jpg swapped). */}} {{ $headerImg := .Params.header.overlay_image | default "" }} +{{ $webpPath := "" }} +{{ $hasWebp := false }} +{{ if $headerImg }} + {{ $base := replaceRE "\\.(jpg|jpeg|png|gif)$" "" $headerImg }} + {{ $webpPath = printf "%s.webp" $base }} + {{ $webpStatic := printf "static/%s" $webpPath }} + {{ $hasWebp = fileExists $webpStatic }} +{{ end }}

{{ .Title }}

diff --git a/themes/clean-hugo/layouts/partials/swoosh-divider-bottom.html b/themes/clean-hugo/layouts/partials/swoosh-divider-bottom.html deleted file mode 100644 index ef52f0ff..00000000 --- a/themes/clean-hugo/layouts/partials/swoosh-divider-bottom.html +++ /dev/null @@ -1,10 +0,0 @@ -{{/* Curved divider at bottom of a swoosh section (wave down into next section). Pass theme: "purple" or "green" so fill matches the section above. SVG matches pyOpenSci div_purple_bottom (exact viewBox and paths). */}} -{{ $theme := .theme | default "purple" }} - diff --git a/themes/clean-hugo/layouts/partials/swoosh-divider-top.html b/themes/clean-hugo/layouts/partials/swoosh-divider-top.html deleted file mode 100644 index 33f72674..00000000 --- a/themes/clean-hugo/layouts/partials/swoosh-divider-top.html +++ /dev/null @@ -1,8 +0,0 @@ -{{/* Curved divider at top of a swoosh section (wave down from previous section). Pass theme: "purple" or "green" so fill matches the section below. */}} -{{ $theme := .theme | default "purple" }} - diff --git a/themes/clean-hugo/layouts/partials/swoosh-inner-content.html b/themes/clean-hugo/layouts/partials/swoosh-inner-content.html deleted file mode 100644 index 95967667..00000000 --- a/themes/clean-hugo/layouts/partials/swoosh-inner-content.html +++ /dev/null @@ -1,41 +0,0 @@ -{{/* - Render swoosh section inner content without Goldmark breaking shortcode HTML. - - Expects a dict: (dict "inner" .Inner "page" .Page) - - {{< swoosh_section >}} — raw markdown plus rendered shortcode HTML. Splits - on boundaries between markdown and HTML blocks, then renders each segment. - - {{% swoosh_section %}} — inner is already markdown-rendered HTML; pass through - with safeHTML. - - Note: replaceRE replacement strings must be literals so $1/$2 reach the regexp - engine (not Go template variables). -*/}} -{{- $inner := replace .inner "\r\n" "\n" -}} -{{- $page := .page -}} -{{- $trimmed := trim $inner " \n\r\t" -}} -{{- $m := "SWOOSHSPLIT" -}} - -{{- if hasPrefix $trimmed "<" -}} - {{ $inner | safeHTML }} -{{- else -}} - {{- $inner = replaceRE `\n\n+(<(?:div|section|figure|a ))` "\n\nSWOOSHSPLIT$1" $inner -}} - {{- $inner = replaceRE `(?s)(
)\s*\n\n+(### )` "$1\n\nSWOOSHSPLIT$2" $inner -}} - {{- $inner = replaceRE `(?s)()\s*\n\n+(## )` "$1\n\nSWOOSHSPLIT$2" $inner -}} - {{- $inner = replaceRE `(?s)()\s*\n\n+(\| )` "$1\n\nSWOOSHSPLIT$2" $inner -}} - {{- $inner = replaceRE `(?s)()\s*\n\n+([A-Z][a-z])` "$1\n\nSWOOSHSPLIT$2" $inner -}} - {{- $inner = replaceRE `(?s)()\s*\n\n+(### )` "$1\n\nSWOOSHSPLIT$2" $inner -}} - {{- $inner = replaceRE `(?s)()\s*\n\n+(## )` "$1\n\nSWOOSHSPLIT$2" $inner -}} - {{- $inner = replaceRE `(?s)()\s*\n\n+(\| )` "$1\n\nSWOOSHSPLIT$2" $inner -}} - {{- $inner = replaceRE `(?s)()\s*\n\n+([A-Z][a-z])` "$1\n\nSWOOSHSPLIT$2" $inner -}} - {{- range split $inner $m -}} - {{- $block := trim . " \n\r\t" -}} - {{- if not $block -}} - {{- else if hasPrefix $block "<" -}} - {{ $block | safeHTML }} - {{- else -}} - {{ $block | $page.RenderString }} - {{- end -}} - {{- end -}} -{{- end -}} diff --git a/themes/clean-hugo/layouts/shortcodes/impact-cards.html b/themes/clean-hugo/layouts/shortcodes/impact-cards.html index 337ad90e..82d990d5 100644 --- a/themes/clean-hugo/layouts/shortcodes/impact-cards.html +++ b/themes/clean-hugo/layouts/shortcodes/impact-cards.html @@ -1,2 +1,8 @@ -{{/* Shortcode to include impact cards section anywhere in content */}} -{{ partial "impact-cards.html" .Page }} +{{/* Shortcode to include impact cards section anywhere in content. + Optional section: front matter key prefix (e.g. translation → translation_cards). + Optional align: left | center | right (overrides page alignment). */}} +{{ partial "impact-cards.html" (dict + "page" .Page + "section" (.Get "section") + "align" (.Get "align") +) }} diff --git a/themes/clean-hugo/layouts/shortcodes/impact-destinations.html b/themes/clean-hugo/layouts/shortcodes/impact-destinations.html new file mode 100644 index 00000000..ee340b18 --- /dev/null +++ b/themes/clean-hugo/layouts/shortcodes/impact-destinations.html @@ -0,0 +1,5 @@ +{{/* Dark impact destinations band — front matter impact_destinations or section param */}} +{{ partial "impact-destinations.html" (dict + "page" .Page + "section" (.Get "section") +) }} diff --git a/themes/clean-hugo/layouts/shortcodes/metrics-bar.html b/themes/clean-hugo/layouts/shortcodes/metrics-bar.html index f45584fe..4cfd298d 100644 --- a/themes/clean-hugo/layouts/shortcodes/metrics-bar.html +++ b/themes/clean-hugo/layouts/shortcodes/metrics-bar.html @@ -1,8 +1,38 @@ -{{/* Metrics bar shortcode - displays up to 4 stats with bold numbers and smaller text */}} -{{ $stat1 := .Get "stat1" | default "" }} -{{ $stat2 := .Get "stat2" | default "" }} -{{ $stat3 := .Get "stat3" | default "" }} -{{ $stat4 := .Get "stat4" | default "" }} +{{/* + Metrics bar shortcode — shared layout, flexible data input. + + Named preset (live data): + {{< metrics-bar set="volunteer" >}} + {{< metrics-bar set="packages" >}} + + Page front matter: + metrics_set: volunteer + {{< metrics-bar >}} + + Manual stats (static or demo content): + {{< metrics-bar + stat1="**128** blog posts" + stat2="**500+** community members" + >}} +*/}} +{{ $set := .Get "set" | default (.Page.Params.metrics_set | default "") }} +{{ $stats := slice }} + +{{ if $set }} + {{ $scratch := newScratch }} + {{ partial "metrics/build-stats.html" (dict + "context" .Page + "set" $set + "scratch" $scratch + ) }} + {{ $stats = $scratch.Get "stats" | default slice }} +{{ else }} + {{ $stats = slice + (.Get "stat1" | default "") + (.Get "stat2" | default "") + (.Get "stat3" | default "") + (.Get "stat4" | default "") + }} +{{ end }} -{{ $stats := slice $stat1 $stat2 $stat3 $stat4 }} {{ partial "metrics-bar-render.html" (dict "stats" $stats) }} diff --git a/themes/clean-hugo/layouts/shortcodes/section-heading.html b/themes/clean-hugo/layouts/shortcodes/section-heading.html index 4cdb1c9c..5be8615a 100644 --- a/themes/clean-hugo/layouts/shortcodes/section-heading.html +++ b/themes/clean-hugo/layouts/shortcodes/section-heading.html @@ -1,11 +1,16 @@ -{{/* Section heading shortcode - creates a prominent centered heading with subtitle */}} +{{/* Section heading shortcode - prominent heading with optional eyebrow */}} {{ $title := .Get "title" | default "Section Title" }} {{ $subtitle := .Get "subtitle" | default "" }} +{{ $eyebrow := .Get "eyebrow" | default "" }} +{{ $align := .Get "align" | default "center" }} {{ $id := .Get "id" | default "" }} -
+
+ {{ with $eyebrow }} +

{{ . }}

+ {{ end }}

{{ $title }}

{{ if $subtitle }} -
{{ $subtitle }}
+
{{ $subtitle | markdownify }}
{{ end }}
diff --git a/themes/clean-hugo/layouts/shortcodes/section_band.html b/themes/clean-hugo/layouts/shortcodes/section_band.html new file mode 100644 index 00000000..91b40cfb --- /dev/null +++ b/themes/clean-hugo/layouts/shortcodes/section_band.html @@ -0,0 +1,38 @@ +{{/* Block shortcode: full-width colored section band with optional curved divider. + Params: + color — white | light-purple | soft-purple | green | brand-purple + divider — top | bottom | none (curved SVG transition) + layout — docs (contained width; no sidebar bleed) + + Prefer {{< section_band >}} when nesting shortcodes (impact-cards, section-heading). + Use {{% section_band %}} only for markdown prose — not nested shortcodes. +*/}} +{{- $color := .Get "color" | default (.Get "background" | default "white") -}} +{{- if eq $color "purple" }}{{ $color = "light-purple" }}{{ end -}} +{{- $divider := .Get "divider" | default (.Get "swoosh" | default "none") -}} +{{- $layout := .Get "layout" | default "" -}} +{{- $docsClass := "" -}} +{{- if eq $layout "docs" }}{{ $docsClass = " section-band--docs" }}{{ end -}} +{{- $wrapDocsClass := "" -}} +{{- if eq $layout "docs" }}{{ $wrapDocsClass = " section-band__divider-wrap--docs" }}{{ end -}} + +{{- $inner := trim .InnerDeindent " \n\t\r" -}} +{{- if eq $divider "top" -}} +
+ {{ partial "section-band-divider-top.html" (dict "color" $color) }} +
+{{- end -}} + +{{- if $inner -}} +
+
+ {{ partial "section-band-inner-content.html" (dict "inner" $inner "page" .Page) }} +
+
+{{- end -}} + +{{- if eq $divider "bottom" -}} +
+ {{ partial "section-band-divider-bottom.html" (dict "color" $color) }} +
+{{- end -}} diff --git a/themes/clean-hugo/layouts/shortcodes/swoosh_section.html b/themes/clean-hugo/layouts/shortcodes/swoosh_section.html index 32672213..46537863 100644 --- a/themes/clean-hugo/layouts/shortcodes/swoosh_section.html +++ b/themes/clean-hugo/layouts/shortcodes/swoosh_section.html @@ -1,38 +1,2 @@ -{{/* Block shortcode: full-width section with optional curved divider above/below. - Use layout="docs" for contained width (content column only; no sidebar bleed). - Inner content: markdown, shortcodes, or raw HTML. - - Prefer {{< swoosh_section >}} (angle brackets) so markdown headings and - prose render via partial/swoosh-inner-content.html. {{% swoosh_section %}} - also works; nested {{< button >}} output is kept on one line so Goldmark - does not split anchor tags during markdown processing. -*/}} -{{- $bg := .Get "background" | default "white" -}} -{{- $swoosh := .Get "swoosh" | default "none" -}} -{{- $layout := .Get "layout" | default "" -}} -{{- $theme := $bg -}} -{{- $docsClass := "" -}} -{{- if eq $layout "docs" }}{{ $docsClass = " swoosh-section--docs" }}{{ end -}} -{{- $wrapDocsClass := "" -}} -{{- if eq $layout "docs" }}{{ $wrapDocsClass = " swoosh-section__divider-wrap--docs" }}{{ end -}} - -{{- $inner := trim .Inner " \n\t\r" -}} -{{- if eq $swoosh "top" -}} -
- {{ partial "swoosh-divider-top.html" (dict "theme" $theme) }} -
-{{- end -}} - -{{- if $inner -}} -
-
- {{ partial "swoosh-inner-content.html" (dict "inner" .Inner "page" .Page) }} -
-
-{{- end -}} - -{{- if eq $swoosh "bottom" -}} -
- {{ partial "swoosh-divider-bottom.html" (dict "theme" $theme) }} -
-{{- end -}} +{{/* Deprecated alias — use {{< section_band >}} instead. */}} +{{ partial "section-band-legacy.html" . }}