feat(ag-p12): getting-started, why, onboarding, glossary, references pages#882
Conversation
… 404 - Rebuild all 5 editorial pages with BaseLayout + WapuuHero + editorial-hero pattern - Add .editorial-hero, .editorial-hero-inner, .editorial-hero-text, .prose-body CSS to global.css - Add .ob-steps/.ob-step/.ob-step-num/.ob-step-body step layout CSS - getting-started.astro: BaseLayout, WapuuHero, 6-step ob-step layout (was AwesomeGithubLayout) - why.astro: BaseLayout, WapuuHero, editorial hero, remove hardcoded dark gradient - onboarding.astro: full 6-chapter page (was redirect to getting-started) - references.astro: BaseLayout, WapuuHero, REFERENCE_GROUPS from glossary lib - glossary/index.astro: BaseLayout, WapuuHero, group-based link list with .wrap container - glossary/[term].astro: BaseLayout, .wrap-prose, related terms chips - 404.astro: wapuu-astropuu.png at 150px centred, back-to-home CTA Closes #881 https://claude.ai/code/session_01TYHRXeGfXMwq5VqsayUVqL
|
Warning Review limit reached
More reviews will be available in 47 minutes and 50 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (10)
📝 WalkthroughWalkthroughThis PR executes Phase 12 of the editorial pages redesign, converting six content pages and the 404 error handler from ChangesEditorial Pages & Layout System Modernisation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
✅ Template check passed after update. Thanks for fixing the PR description. |
There was a problem hiding this comment.
Code Review
This pull request refactors several editorial pages (including the 404, getting-started, glossary, onboarding, references, and why pages) to use a unified BaseLayout and introduces a consistent editorial hero design. While these changes improve the visual layout, they introduce significant CSS duplication and inline styles across multiple files. The feedback focuses on consolidating these duplicated typography and button styles globally within global.css and reusing them via utility classes (such as .btn-primary, .btn-ghost, and a new .btn-pill modifier) to enhance maintainability and consistency.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
|
||
| /* ── Editorial page hero ────────────────────────────────────────── */ | ||
| .editorial-hero { | ||
| padding: clamp(40px, 5vw, 72px) 0 clamp(24px, 3vw, 40px); | ||
| border-bottom: 1px solid var(--hair); | ||
| } | ||
|
|
||
| .editorial-hero-inner { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| gap: 32px; | ||
| max-width: 1320px; | ||
| margin: 0 auto; | ||
| padding: 0 clamp(16px, 4vw, 48px); | ||
| } | ||
|
|
||
| .editorial-hero-text { | ||
| max-width: 600px; | ||
| flex: 1; | ||
| } | ||
|
|
||
| /* Prose body — editorial content below the hero */ | ||
| .prose-body { | ||
| max-width: 820px; | ||
| margin: 0 auto; | ||
| padding: clamp(32px, 4vw, 56px) clamp(16px, 4vw, 40px) 80px; | ||
| } | ||
|
|
||
| /* ── Onboarding step list ───────────────────────────────────────── */ | ||
| .ob-steps { display: flex; flex-direction: column; gap: 32px; margin-top: 32px; } | ||
|
|
||
| .ob-step { | ||
| display: grid; | ||
| grid-template-columns: 48px 1fr; | ||
| gap: 20px; | ||
| align-items: start; | ||
| } | ||
|
|
||
| .ob-step-num { | ||
| width: 48px; height: 48px; | ||
| border-radius: 50%; | ||
| background: var(--accent-soft); | ||
| border: 2px solid var(--accent); | ||
| color: var(--accent); | ||
| display: grid; place-items: center; | ||
| font-family: var(--font-display); | ||
| font-weight: 800; | ||
| font-size: 18px; | ||
| flex: none; | ||
| } | ||
|
|
||
| .ob-step-body h3 { | ||
| font-family: var(--font-display); | ||
| font-weight: 700; | ||
| font-size: 18px; | ||
| margin-bottom: 8px; | ||
| color: var(--fg-1); | ||
| } | ||
|
|
||
| .ob-step-body p { | ||
| font-size: 15px; | ||
| color: var(--fg-2); | ||
| line-height: 1.65; | ||
| margin: 0; | ||
| } | ||
|
|
||
| .ob-step-body .run-pill { margin-top: 12px; } |
There was a problem hiding this comment.
Consolidate the duplicated typography (.eyebrow, .page-h1, .page-lead, .page-lead code) and button styles (.btn-pill) globally under .editorial-hero to avoid massive duplication across multiple editorial pages.
/* ── Editorial page hero ────────────────────────────────────────── */
.editorial-hero {
padding: clamp(40px, 5vw, 72px) 0 clamp(24px, 3vw, 40px);
border-bottom: 1px solid var(--hair);
}
.editorial-hero-inner {
display: flex;
align-items: center;
justify-content: space-between;
gap: 32px;
max-width: 1320px;
margin: 0 auto;
padding: 0 clamp(16px, 4vw, 48px);
}
.editorial-hero-text {
max-width: 600px;
flex: 1;
}
.editorial-hero .eyebrow {
display: inline-block;
font-family: var(--font-mono);
margin-bottom: 12px;
}
.editorial-hero .page-h1 {
margin: 0 0 16px;
}
.editorial-hero .page-lead {
max-width: 520px;
margin: 0;
}
.editorial-hero .page-lead code {
font-family: var(--font-mono);
font-size: .9em;
background: var(--panel-2);
border: 1px solid var(--hair);
border-radius: 5px;
padding: 1px 5px;
color: var(--fg-1);
}
/* Prose body — editorial content below the hero */
.prose-body {
max-width: 820px;
margin: 0 auto;
padding: clamp(32px, 4vw, 56px) clamp(16px, 4vw, 40px) 80px;
}
/* ── Onboarding step list ───────────────────────────────────────── */
.ob-steps { display: flex; flex-direction: column; gap: 32px; margin-top: 32px; }
.ob-step {
display: grid;
grid-template-columns: 48px 1fr;
gap: 20px;
align-items: start;
}
.ob-step-num {
width: 48px; height: 48px;
border-radius: 50%;
background: var(--accent-soft);
border: 2px solid var(--accent);
color: var(--accent);
display: grid; place-items: center;
font-family: var(--font-display);
font-weight: 800;
font-size: 18px;
flex: none;
}
.ob-step-body h3 {
font-family: var(--font-display);
font-weight: 700;
font-size: 18px;
margin-bottom: 8px;
color: var(--fg-1);
}
.ob-step-body p {
font-size: 15px;
color: var(--fg-2);
line-height: 1.65;
margin: 0;
}
.ob-step-body .run-pill { margin-top: 12px; }
/* Pill button modifier */
.btn-pill {
border-radius: var(--radius-pill);
}| <main style="display:flex; flex-direction:column; align-items:center; justify-content:center; min-height:60vh; gap:24px; text-align:center; padding: 48px 24px;"> | ||
| <img | ||
| src={`${base}assets/wapuus/wapuu-astropuu.png`} | ||
| alt="" | ||
| aria-hidden="true" | ||
| style="height:150px; width:auto;" | ||
| loading="lazy" | ||
| /> | ||
| <div> | ||
| <p style="font-family:var(--font-mono); font-size:13px; color:var(--fg-3); margin-bottom:8px; text-transform:uppercase; letter-spacing:.1em;">404</p> | ||
| <h1 style="font-family:var(--font-display); font-weight:800; font-size:clamp(28px,4vw,44px); color:var(--fg-1); margin-bottom:12px; letter-spacing:-.025em;">Page not found</h1> | ||
| <p style="font-size:16px; color:var(--fg-2); max-width:400px; margin:0 auto 28px;"> | ||
| This resource doesn't exist or has moved. Head back to the catalogue. | ||
| </p> | ||
| <a | ||
| class="btn-home" | ||
| href={`${base}`} | ||
| > | ||
| Back to home → | ||
| </a> | ||
| </div> | ||
| </section> | ||
|
|
||
| <section class="section"> | ||
| <h2>Helpful links</h2> | ||
| <div class="card-grid"> | ||
| <article class="card"> | ||
| <h3>Home</h3> | ||
| <p>The short overview of the project and the public site sections.</p> | ||
| </article> | ||
| <article class="card"> | ||
| <h3>WCEU 2026 talk</h3> | ||
| <p>The conference page with the talk outline and the slide source tree.</p> | ||
| </article> | ||
| <article class="card"> | ||
| <h3>Why this exists</h3> | ||
| <p>A concise explanation of the repository-as-control-plane model.</p> | ||
| </article> | ||
| <article class="card"> | ||
| <h3>References</h3> | ||
| <p>Source links and the planning inputs behind the public site.</p> | ||
| </article> | ||
| </div> | ||
| </section> | ||
| </main> | ||
| </BaseLayout> | ||
|
|
||
| <style> | ||
| .btn-home { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| background: var(--c-brand-blue); | ||
| color: #fff; | ||
| padding: 12px 28px; | ||
| border-radius: var(--radius-pill); | ||
| font-size: 15px; | ||
| font-weight: 600; | ||
| text-decoration: none; | ||
| transition: background var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .btn-home:hover { background: #1857D6; } | ||
| </style> |
There was a problem hiding this comment.
Refactor the 404 page to eliminate inline styles and reuse the global design system's .btn-primary and .btn-pill classes. This improves maintainability, consistency, and adheres to CSP best practices.
<main class="not-found-main">
<img
src={`${base}assets/wapuus/wapuu-astropuu.png`}
alt=""
aria-hidden="true"
class="not-found-img"
loading="lazy"
/>
<div class="not-found-content">
<p class="not-found-code">404</p>
<h1 class="not-found-title">Page not found</h1>
<p class="not-found-text">
This resource doesn't exist or has moved. Head back to the catalogue.
</p>
<a
class="btn-primary btn-pill"
href={`${base}`}
>
Back to home →
</a>
</div>
</main>
</BaseLayout>
<style>
.not-found-main {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 60vh;
gap: 24px;
text-align: center;
padding: 48px 24px;
}
.not-found-img {
height: 150px;
width: auto;
}
.not-found-code {
font-family: var(--font-mono);
font-size: 13px;
color: var(--fg-3);
margin-bottom: 8px;
text-transform: uppercase;
letter-spacing: .1em;
}
.not-found-title {
font-family: var(--font-display);
font-weight: 800;
font-size: clamp(28px, 4vw, 44px);
color: var(--fg-1);
margin-bottom: 12px;
letter-spacing: -.025em;
}
.not-found-text {
font-size: 16px;
color: var(--fg-2);
max-width: 400px;
margin: 0 auto 28px;
}
</style>
| <div class="gs-cta-row"> | ||
| <a class="btn-primary" href={`${base}c/agents/`}>Browse the catalogue →</a> | ||
| <a class="btn-ghost" href={`${base}learn/`}>Start learning</a> | ||
| </div> |
There was a problem hiding this comment.
Reuse the global design system's .btn-primary and .btn-ghost classes with the new .btn-pill modifier instead of using local overrides.
<div class="gs-cta-row">
<a class="btn-primary btn-pill" href={`${base}c/agents/`}>Browse the catalogue →</a>
<a class="btn-ghost btn-pill" href={`${base}learn/`}>Start learning</a>
</div>
| <style> | ||
| .gs-container { | ||
| max-width: var(--container-max); | ||
| margin: 0 auto; | ||
| padding: 0 var(--gutter); | ||
| } | ||
|
|
||
| .gs-hero { | ||
| background: linear-gradient(135deg, #0F1014 0%, #181820 100%); | ||
| color: var(--c-white); | ||
| padding: var(--space-40) var(--gutter); | ||
| } | ||
|
|
||
| .gs-eyebrow { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| gap: var(--space-2); | ||
| padding: var(--space-2) var(--space-4); | ||
| background: rgba(123, 231, 255, 0.1); | ||
| border: 1px solid rgba(123, 231, 255, 0.3); | ||
| border-radius: var(--radius-pill); | ||
| font-size: var(--fs-eyebrow); | ||
| color: var(--c-light-blue); | ||
| margin-bottom: var(--space-6); | ||
| font-weight: var(--weight-semibold); | ||
| .eyebrow { | ||
| display: inline-block; | ||
| font-family: var(--font-mono); | ||
| font-size: 12px; | ||
| font-weight: 700; | ||
| text-transform: uppercase; | ||
| letter-spacing: var(--tracking-eyebrow); | ||
| letter-spacing: .1em; | ||
| color: var(--fg-3); | ||
| margin-bottom: 12px; | ||
| } | ||
|
|
||
| .gs-h1 { | ||
| font-size: var(--fs-h1); | ||
| font-weight: var(--weight-extrabold); | ||
| line-height: var(--lh-heading); | ||
| margin: 0 0 var(--space-6) 0; | ||
| color: var(--c-white); | ||
| .page-h1 { | ||
| font-family: var(--font-display); | ||
| font-weight: 800; | ||
| font-size: clamp(30px, 4vw, 46px); | ||
| letter-spacing: -.025em; | ||
| line-height: 1.1; | ||
| color: var(--fg-1); | ||
| margin: 0 0 16px; | ||
| } | ||
|
|
||
| .gs-lead { | ||
| font-size: var(--fs-lead); | ||
| line-height: var(--lh-loose); | ||
| color: var(--c-slate-300); | ||
| .page-lead { | ||
| font-size: clamp(16px, 1.2vw, 18px); | ||
| color: var(--fg-2); | ||
| line-height: 1.6; | ||
| max-width: 520px; | ||
| margin: 0; | ||
| max-width: 60ch; | ||
| } | ||
|
|
||
| .gs-steps-section { | ||
| padding: var(--space-24) var(--gutter); | ||
| background: var(--bg); | ||
| } | ||
|
|
||
| .gs-steps { | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: 0; | ||
| } | ||
|
|
||
| .gs-step { | ||
| display: grid; | ||
| grid-template-columns: 80px 1fr; | ||
| gap: var(--space-8); | ||
| padding: var(--space-12) 0; | ||
| border-bottom: 1px solid var(--border); | ||
| position: relative; | ||
| } | ||
|
|
||
| .gs-step:last-child { | ||
| border-bottom: none; | ||
| } | ||
|
|
||
| .gs-step-number { | ||
| .page-lead code { | ||
| font-family: var(--font-mono); | ||
| font-size: 48px; | ||
| font-weight: var(--weight-bold); | ||
| color: var(--accent); | ||
| opacity: 0.3; | ||
| line-height: 1; | ||
| padding-top: 4px; | ||
| } | ||
|
|
||
| .gs-step-title { | ||
| font-size: var(--fs-h3); | ||
| font-weight: var(--weight-bold); | ||
| margin: 0 0 var(--space-4) 0; | ||
| font-size: .9em; | ||
| background: var(--panel-2); | ||
| border: 1px solid var(--hair); | ||
| border-radius: 5px; | ||
| padding: 1px 5px; | ||
| color: var(--fg-1); | ||
| line-height: var(--lh-heading); | ||
| } | ||
|
|
||
| .gs-step-body { | ||
| font-size: var(--fs-body-lg); | ||
| color: var(--fg-2); | ||
| margin: 0 0 var(--space-6) 0; | ||
| line-height: var(--lh-loose); | ||
| max-width: 60ch; | ||
| } | ||
|
|
||
| .gs-code-block { | ||
| background: var(--bg-alt); | ||
| border: 1px solid var(--border); | ||
| border-radius: var(--radius-md); | ||
| overflow: hidden; | ||
| margin-bottom: var(--space-6); | ||
| max-width: 560px; | ||
| } | ||
|
|
||
| .gs-code-label { | ||
| padding: var(--space-2) var(--space-4); | ||
| font-size: var(--fs-body-sm); | ||
| color: var(--fg-3); | ||
| border-bottom: 1px solid var(--border); | ||
| font-family: var(--font-body); | ||
| font-weight: var(--weight-medium); | ||
| } | ||
|
|
||
| .gs-code-inner { | ||
| .run-pill { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: var(--space-4); | ||
| gap: var(--space-4); | ||
| } | ||
|
|
||
| .gs-code { | ||
| flex-direction: column; | ||
| gap: 4px; | ||
| background: #0d1117; | ||
| color: #d7e2f0; | ||
| border: 1px solid var(--hair); | ||
| border-radius: var(--radius-md); | ||
| padding: 12px 16px; | ||
| margin-top: 12px; | ||
| font-family: var(--font-mono); | ||
| font-size: var(--fs-code); | ||
| color: var(--c-light-blue); | ||
| background: none; | ||
| border: none; | ||
| padding: 0; | ||
| word-break: break-all; | ||
| } | ||
|
|
||
| .gs-copy-btn { | ||
| flex-shrink: 0; | ||
| padding: var(--space-2) var(--space-3); | ||
| background: var(--accent-soft); | ||
| color: var(--accent); | ||
| border: 1px solid var(--accent); | ||
| border-radius: var(--radius-sm); | ||
| font-size: var(--fs-body-sm); | ||
| font-weight: var(--weight-semibold); | ||
| cursor: pointer; | ||
| transition: all var(--dur) var(--ease-out); | ||
| font-family: var(--font-body); | ||
| font-size: 13px; | ||
| } | ||
|
|
||
| .gs-copy-btn:hover { | ||
| background: var(--accent); | ||
| color: var(--accent-contrast); | ||
| .run-label { | ||
| font-size: 11px; | ||
| color: rgba(215, 226, 240, 0.5); | ||
| text-transform: uppercase; | ||
| letter-spacing: .08em; | ||
| } | ||
|
|
||
| .gs-step-note { | ||
| font-size: var(--fs-body-sm); | ||
| color: var(--fg-3); | ||
| margin: 0 0 var(--space-4) 0; | ||
| padding: var(--space-3) var(--space-4); | ||
| background: var(--bg-alt); | ||
| border-left: 3px solid var(--accent); | ||
| border-radius: 0 var(--radius-sm) var(--radius-sm) 0; | ||
| max-width: 60ch; | ||
| .step-note { | ||
| font-size: 13px !important; | ||
| color: var(--fg-3) !important; | ||
| margin-top: 10px !important; | ||
| font-style: italic; | ||
| } | ||
|
|
||
| .gs-step-cta { | ||
| margin-top: var(--space-4); | ||
| .step-cta { | ||
| display: inline-flex; | ||
| margin-top: 12px; | ||
| font-size: 14px; | ||
| padding: 7px 16px; | ||
| border-radius: var(--radius-pill); | ||
| border: 1px solid var(--hair); | ||
| color: var(--accent); | ||
| text-decoration: none; | ||
| font-weight: 600; | ||
| transition: border-color var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .gs-h2 { | ||
| font-size: var(--fs-h2); | ||
| font-weight: var(--weight-bold); | ||
| line-height: var(--lh-heading); | ||
| margin: 0 0 var(--space-4) 0; | ||
| color: var(--fg-1); | ||
| } | ||
| .step-cta:hover { border-color: var(--accent); } | ||
|
|
||
| .gs-next-section { | ||
| padding: var(--space-24) var(--gutter); | ||
| background: var(--bg-alt); | ||
| .gs-cta-block { | ||
| margin-top: 48px; | ||
| padding-top: 32px; | ||
| border-top: 1px solid var(--hair); | ||
| } | ||
|
|
||
| .gs-next-section .gs-lead { | ||
| .gs-cta-block > p { | ||
| font-size: 16px; | ||
| color: var(--fg-2); | ||
| margin-bottom: var(--space-10); | ||
| } | ||
|
|
||
| .gs-next-grid { | ||
| display: grid; | ||
| grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); | ||
| gap: var(--space-6); | ||
| margin: 0 0 16px; | ||
| } | ||
|
|
||
| .gs-next-card { | ||
| .gs-cta-row { | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: var(--space-3); | ||
| padding: var(--space-6); | ||
| background: var(--bg); | ||
| border: 1px solid var(--border); | ||
| border-radius: var(--radius-lg); | ||
| text-decoration: none; | ||
| color: inherit; | ||
| transition: all var(--dur) var(--ease-out); | ||
| gap: 12px; | ||
| flex-wrap: wrap; | ||
| } | ||
|
|
||
| .gs-next-card:hover { | ||
| border-color: var(--accent); | ||
| box-shadow: var(--shadow-md); | ||
| transform: translateY(-2px); | ||
| } | ||
|
|
||
| .gs-next-icon { | ||
| display: flex; | ||
| color: var(--accent); | ||
| .btn-primary { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| background: var(--c-brand-blue); | ||
| color: #fff; | ||
| padding: 10px 22px; | ||
| border-radius: var(--radius-pill); | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| text-decoration: none; | ||
| transition: background var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .gs-next-card h3 { | ||
| font-size: var(--fs-h5); | ||
| font-weight: var(--weight-bold); | ||
| margin: 0; | ||
| color: var(--fg-1); | ||
| } | ||
| .btn-primary:hover { background: #1857D6; } | ||
|
|
||
| .gs-next-card p { | ||
| font-size: var(--fs-body-sm); | ||
| .btn-ghost { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| border: 1px solid var(--hair); | ||
| color: var(--fg-2); | ||
| margin: 0; | ||
| line-height: var(--lh-snug); | ||
| padding: 10px 22px; | ||
| border-radius: var(--radius-pill); | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| text-decoration: none; | ||
| transition: border-color var(--dur) var(--ease-out), color var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| @media (max-width: 768px) { | ||
| .gs-hero { | ||
| padding: var(--space-20) var(--gutter); | ||
|
|
||
| } | ||
|
|
||
| .gs-h1 { | ||
| font-size: var(--fs-h2); | ||
| } | ||
|
|
||
| .gs-step { | ||
| grid-template-columns: 1fr; | ||
| } | ||
|
|
||
| .gs-step-number { | ||
| font-size: 32px; | ||
| } | ||
|
|
||
| .gs-next-grid { | ||
| grid-template-columns: 1fr; | ||
| } | ||
| } | ||
| .btn-ghost:hover { border-color: var(--accent); color: var(--accent); } | ||
| </style> |
There was a problem hiding this comment.
Remove the duplicated typography and button styles from the local <style> block, as they are now handled globally in global.css. Also, remove the unnecessary !important flags from .step-note.
<style>
.run-pill {
display: flex;
flex-direction: column;
gap: 4px;
background: #0d1117;
color: #d7e2f0;
border: 1px solid var(--hair);
border-radius: var(--radius-md);
padding: 12px 16px;
margin-top: 12px;
font-family: var(--font-mono);
font-size: 13px;
}
.run-label {
font-size: 11px;
color: rgba(215, 226, 240, 0.5);
text-transform: uppercase;
letter-spacing: .08em;
}
.step-note {
font-size: 13px;
color: var(--fg-3);
margin-top: 10px;
font-style: italic;
}
.step-cta {
display: inline-flex;
margin-top: 12px;
font-size: 14px;
padding: 7px 16px;
border-radius: var(--radius-pill);
border: 1px solid var(--hair);
color: var(--accent);
text-decoration: none;
font-weight: 600;
transition: border-color var(--dur) var(--ease-out);
}
.step-cta:hover { border-color: var(--accent); }
.gs-cta-block {
margin-top: 48px;
padding-top: 32px;
border-top: 1px solid var(--hair);
}
.gs-cta-block > p {
font-size: 16px;
color: var(--fg-2);
margin: 0 0 16px;
}
.gs-cta-row {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
</style>
| <div class="ob-cta-row"> | ||
| <a class="btn-primary" href={`${base}c/agents/`}>Browse the catalogue →</a> | ||
| <a class="btn-ghost" href={`${base}learn/`}>Learning Centre</a> | ||
| <a class="btn-ghost" href={`${base}getting-started/`}>Step-by-step guide</a> | ||
| </div> |
There was a problem hiding this comment.
Reuse the global design system's .btn-primary and .btn-ghost classes with the new .btn-pill modifier instead of using local overrides.
<div class="ob-cta-row">
<a class="btn-primary btn-pill" href={`${base}c/agents/`}>Browse the catalogue →</a>
<a class="btn-ghost btn-pill" href={`${base}learn/`}>Learning Centre</a>
<a class="btn-ghost btn-pill" href={`${base}getting-started/`}>Step-by-step guide</a>
</div>
| <style> | ||
| .why-container { | ||
| max-width: var(--container-prose); | ||
| margin: 0 auto; | ||
| padding: 0 var(--gutter); | ||
| } | ||
|
|
||
| .why-breadcrumb { | ||
| background: var(--bg); | ||
| border-bottom: 1px solid var(--border); | ||
| padding: var(--space-3) var(--gutter); | ||
| font-size: var(--fs-body-sm); | ||
| } | ||
|
|
||
| .why-breadcrumb div { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: var(--space-3); | ||
| } | ||
|
|
||
| .why-breadcrumb a { color: var(--fg-link); text-decoration: none; } | ||
| .why-breadcrumb a:hover { color: var(--fg-link-hover); } | ||
| .why-breadcrumb span:not([aria-hidden]) { color: var(--fg-2); } | ||
| .why-breadcrumb [aria-hidden] { color: var(--fg-3); } | ||
|
|
||
| .why-hero { | ||
| background: linear-gradient(135deg, #0F1014 0%, #181820 100%); | ||
| color: var(--c-white); | ||
| padding: var(--space-24) var(--gutter); | ||
| } | ||
|
|
||
| .why-eyebrow { | ||
| display: inline-flex; | ||
| padding: var(--space-2) var(--space-4); | ||
| background: rgba(123, 231, 255, 0.1); | ||
| border: 1px solid rgba(123, 231, 255, 0.3); | ||
| border-radius: var(--radius-pill); | ||
| font-size: var(--fs-eyebrow); | ||
| color: var(--c-light-blue); | ||
| margin-bottom: var(--space-6); | ||
| font-weight: var(--weight-semibold); | ||
| .eyebrow { | ||
| display: inline-block; | ||
| font-family: var(--font-mono); | ||
| font-size: 12px; | ||
| font-weight: 700; | ||
| text-transform: uppercase; | ||
| letter-spacing: var(--tracking-eyebrow); | ||
| } | ||
|
|
||
| .why-h1 { | ||
| font-size: var(--fs-h2); | ||
| font-weight: var(--weight-extrabold); | ||
| line-height: var(--lh-heading); | ||
| margin: 0 0 var(--space-6) 0; | ||
| color: var(--c-white); | ||
| letter-spacing: .1em; | ||
| color: var(--fg-3); | ||
| margin-bottom: 12px; | ||
| } | ||
|
|
||
| .why-lead { | ||
| font-size: var(--fs-body-lg); | ||
| color: var(--c-slate-300); | ||
| margin: 0; | ||
| line-height: var(--lh-loose); | ||
| max-width: 60ch; | ||
| } | ||
|
|
||
| .why-section { | ||
| padding: var(--space-20) var(--gutter); | ||
| background: var(--bg); | ||
| } | ||
|
|
||
| .why-prose { | ||
| font-size: var(--fs-body); | ||
| line-height: var(--lh-loose); | ||
| color: var(--fg-2); | ||
| } | ||
|
|
||
| .why-prose h2 { | ||
| font-size: var(--fs-h4); | ||
| font-weight: var(--weight-bold); | ||
| .page-h1 { | ||
| font-family: var(--font-display); | ||
| font-weight: 800; | ||
| font-size: clamp(30px, 4vw, 46px); | ||
| letter-spacing: -.025em; | ||
| line-height: 1.1; | ||
| color: var(--fg-1); | ||
| margin: var(--space-12) 0 var(--space-4) 0; | ||
| margin: 0 0 16px; | ||
| } | ||
|
|
||
| .why-prose h2:first-child { | ||
| margin-top: 0; | ||
| } | ||
|
|
||
| .why-prose p { | ||
| margin: 0 0 var(--space-4) 0; | ||
| max-width: 70ch; | ||
| .page-lead { | ||
| font-size: clamp(16px, 1.2vw, 18px); | ||
| color: var(--fg-2); | ||
| line-height: 1.6; | ||
| max-width: 520px; | ||
| margin: 0; | ||
| } | ||
|
|
||
| .why-prose code { | ||
| .page-lead code { | ||
| font-family: var(--font-mono); | ||
| font-size: 13px; | ||
| background: var(--bg-alt); | ||
| border: 1px solid var(--border); | ||
| padding: 2px 6px; | ||
| border-radius: var(--radius-sm); | ||
| color: var(--accent); | ||
| font-size: .9em; | ||
| background: var(--panel-2); | ||
| border: 1px solid var(--hair); | ||
| border-radius: 5px; | ||
| padding: 1px 5px; | ||
| color: var(--fg-1); | ||
| } | ||
|
|
||
| .why-cta-block { | ||
| margin-top: var(--space-16); | ||
| padding-top: var(--space-12); | ||
| border-top: 1px solid var(--border); | ||
| margin-top: 48px; | ||
| padding-top: 32px; | ||
| border-top: 1px solid var(--hair); | ||
| } | ||
|
|
||
| .why-cta-block h2 { | ||
| font-size: var(--fs-h3); | ||
| font-weight: var(--weight-bold); | ||
| font-family: var(--font-display); | ||
| font-size: clamp(20px, 2vw, 26px); | ||
| font-weight: 700; | ||
| color: var(--fg-1); | ||
| margin: 0 0 var(--space-3) 0; | ||
| margin: 0 0 8px; | ||
| } | ||
|
|
||
| .why-cta-block p { | ||
| font-size: var(--fs-body); | ||
| .why-cta-block > p { | ||
| font-size: 16px; | ||
| color: var(--fg-2); | ||
| margin: 0 0 var(--space-6) 0; | ||
| margin: 0 0 20px; | ||
| } | ||
|
|
||
| .why-cta-buttons { | ||
| .why-cta-row { | ||
| display: flex; | ||
| gap: var(--space-4); | ||
| gap: 12px; | ||
| flex-wrap: wrap; | ||
| } | ||
|
|
||
| @media (max-width: 768px) { | ||
| .why-hero { padding: var(--space-16) var(--gutter); } | ||
| .why-h1 { font-size: var(--fs-h3); } | ||
| .why-cta-buttons { flex-direction: column; } | ||
| .btn-primary { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| background: var(--c-brand-blue); | ||
| color: #fff; | ||
| padding: 10px 22px; | ||
| border-radius: var(--radius-pill); | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| text-decoration: none; | ||
| transition: background var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .btn-primary:hover { background: #1857D6; } | ||
|
|
||
| .btn-ghost { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| border: 1px solid var(--hair); | ||
| color: var(--fg-2); | ||
| padding: 10px 22px; | ||
| border-radius: var(--radius-pill); | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| text-decoration: none; | ||
| transition: border-color var(--dur) var(--ease-out), color var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .btn-ghost:hover { border-color: var(--accent); color: var(--accent); } | ||
| </style> |
There was a problem hiding this comment.
Remove the duplicated typography and button styles from the local <style> block, as they are now handled globally in global.css.
<style>
.why-cta-block {
margin-top: 48px;
padding-top: 32px;
border-top: 1px solid var(--hair);
}
.why-cta-block h2 {
font-family: var(--font-display);
font-size: clamp(20px, 2vw, 26px);
font-weight: 700;
color: var(--fg-1);
margin: 0 0 8px;
}
.why-cta-block > p {
font-size: 16px;
color: var(--fg-2);
margin: 0 0 20px;
}
.why-cta-row {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
</style>
| <style> | ||
| .glossary-container { | ||
| max-width: 800px; | ||
| margin: 0 auto; | ||
| padding: 0 var(--gutter); | ||
| } | ||
|
|
||
| .glossary-container--wide { | ||
| max-width: var(--container-max); | ||
| } | ||
|
|
||
| .glossary-hero { | ||
| background: linear-gradient(135deg, #0F1014 0%, #181820 100%); | ||
| color: var(--c-white); | ||
| padding: var(--space-40) var(--gutter); | ||
| } | ||
|
|
||
| .glossary-eyebrow { | ||
| display: inline-flex; | ||
| padding: var(--space-2) var(--space-4); | ||
| background: rgba(123, 231, 255, 0.1); | ||
| border: 1px solid rgba(123, 231, 255, 0.3); | ||
| border-radius: var(--radius-pill); | ||
| font-size: var(--fs-eyebrow); | ||
| color: var(--c-light-blue); | ||
| margin-bottom: var(--space-6); | ||
| font-weight: var(--weight-semibold); | ||
| .eyebrow { | ||
| display: inline-block; | ||
| font-family: var(--font-mono); | ||
| font-size: 12px; | ||
| font-weight: 700; | ||
| text-transform: uppercase; | ||
| letter-spacing: var(--tracking-eyebrow); | ||
| letter-spacing: .1em; | ||
| color: var(--fg-3); | ||
| margin-bottom: 12px; | ||
| } | ||
|
|
||
| .glossary-h1 { | ||
| font-size: var(--fs-h1); | ||
| font-weight: var(--weight-extrabold); | ||
| line-height: var(--lh-heading); | ||
| margin: 0 0 var(--space-6) 0; | ||
| color: var(--c-white); | ||
| .page-h1 { | ||
| font-family: var(--font-display); | ||
| font-weight: 800; | ||
| font-size: clamp(30px, 4vw, 46px); | ||
| letter-spacing: -.025em; | ||
| line-height: 1.1; | ||
| color: var(--fg-1); | ||
| margin: 0 0 16px; | ||
| } | ||
|
|
||
| .glossary-lead { | ||
| font-size: var(--fs-lead); | ||
| line-height: var(--lh-loose); | ||
| color: var(--c-slate-300); | ||
| .page-lead { | ||
| font-size: clamp(16px, 1.2vw, 18px); | ||
| color: var(--fg-2); | ||
| line-height: 1.6; | ||
| max-width: 520px; | ||
| margin: 0; | ||
| max-width: 60ch; | ||
| } | ||
|
|
||
| .glossary-body { | ||
| padding: var(--space-16) var(--gutter); | ||
| background: var(--bg); | ||
| } | ||
|
|
||
| .glossary-layout { | ||
| display: grid; | ||
| grid-template-columns: 220px 1fr; | ||
| gap: var(--space-12); | ||
| align-items: start; | ||
| } | ||
|
|
||
| .glossary-sidebar { | ||
| position: sticky; | ||
| top: 88px; | ||
| } | ||
|
|
||
| .glossary-sidebar-inner { | ||
| max-width: 820px; | ||
| margin: 0 auto; | ||
| padding: clamp(32px, 4vw, 48px) clamp(16px, 4vw, 40px) 80px; | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: var(--space-1); | ||
| background: var(--bg-alt); | ||
| border: 1px solid var(--border); | ||
| border-radius: var(--radius-lg); | ||
| padding: var(--space-4); | ||
| gap: 36px; | ||
| } | ||
|
|
||
| .glossary-sidebar-title { | ||
| font-size: var(--fs-eyebrow); | ||
| font-weight: var(--weight-semibold); | ||
| color: var(--fg-3); | ||
| .gloss-letter { | ||
| font-family: var(--font-mono); | ||
| font-size: 13px; | ||
| font-weight: 700; | ||
| text-transform: uppercase; | ||
| letter-spacing: var(--tracking-eyebrow); | ||
| padding: var(--space-2) var(--space-3); | ||
| margin-bottom: var(--space-2); | ||
| } | ||
|
|
||
| .glossary-sidebar-link { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: var(--space-2) var(--space-3); | ||
| border-radius: var(--radius-sm); | ||
| font-size: var(--fs-body-sm); | ||
| color: var(--fg-2); | ||
| text-decoration: none; | ||
| transition: all var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .glossary-sidebar-link:hover { | ||
| color: var(--fg-1); | ||
| background: var(--bg-muted); | ||
| } | ||
|
|
||
| .glossary-sidebar-count { | ||
| font-size: 11px; | ||
| background: var(--bg-muted); | ||
| letter-spacing: .1em; | ||
| color: var(--fg-3); | ||
| padding: 1px 6px; | ||
| border-radius: var(--radius-pill); | ||
| } | ||
|
|
||
| .glossary-content { | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: var(--space-16); | ||
| padding-bottom: 8px; | ||
| border-bottom: 1px solid var(--hair); | ||
| margin-bottom: 8px; | ||
| } | ||
|
|
||
| .glossary-group { | ||
| scroll-margin-top: 104px; | ||
| } | ||
|
|
||
| .glossary-group-header { | ||
| margin-bottom: var(--space-8); | ||
| padding-bottom: var(--space-6); | ||
| border-bottom: 2px solid var(--accent); | ||
| } | ||
|
|
||
| .glossary-group-title { | ||
| font-size: var(--fs-h3); | ||
| font-weight: var(--weight-bold); | ||
| margin: 0 0 var(--space-3) 0; | ||
| color: var(--fg-1); | ||
| .gloss-blurb { | ||
| font-size: 13px; | ||
| color: var(--fg-3); | ||
| margin: 0 0 12px; | ||
| line-height: 1.5; | ||
| } | ||
|
|
||
| .glossary-group-blurb { | ||
| font-size: var(--fs-body); | ||
| color: var(--fg-2); | ||
| margin: 0; | ||
| .gloss-list { | ||
| list-style: none; | ||
| padding: 0; margin: 0; | ||
| display: flex; flex-direction: column; gap: 4px; | ||
| } | ||
|
|
||
| .glossary-entries { | ||
| .gloss-link { | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: 0; | ||
| } | ||
|
|
||
| .glossary-entry { | ||
| padding: var(--space-6) 0; | ||
| border-bottom: 1px solid var(--border); | ||
| } | ||
|
|
||
| .glossary-entry:last-child { border-bottom: none; } | ||
|
|
||
| .glossary-term { | ||
| font-size: var(--fs-h5); | ||
| font-weight: var(--weight-bold); | ||
| margin: 0 0 var(--space-3) 0; | ||
| } | ||
|
|
||
| .glossary-term a { | ||
| color: var(--fg-1); | ||
| gap: 3px; | ||
| padding: 12px 14px; | ||
| background: var(--panel); | ||
| border: 1px solid var(--hair); | ||
| border-radius: var(--radius-md); | ||
| text-decoration: none; | ||
| border-bottom: 2px solid transparent; | ||
| transition: border-color var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .glossary-term a:hover { border-bottom-color: var(--accent); } | ||
|
|
||
| .glossary-def { | ||
| font-size: var(--fs-body); | ||
| color: var(--fg); | ||
| margin: 0 0 var(--space-3) 0; | ||
| line-height: var(--lh-loose); | ||
| max-width: 65ch; | ||
| } | ||
|
|
||
| .glossary-why { | ||
| font-size: var(--fs-body-sm); | ||
| color: var(--fg-2); | ||
| margin: 0 0 var(--space-3) 0; | ||
| line-height: var(--lh-loose); | ||
| } | ||
|
|
||
| .glossary-why strong { color: var(--fg-1); } | ||
|
|
||
| .glossary-related { | ||
| display: flex; | ||
| align-items: center; | ||
| flex-wrap: wrap; | ||
| gap: 0; | ||
| font-size: var(--fs-body-sm); | ||
| color: var(--fg-3); | ||
| } | ||
|
|
||
| .glossary-related-label { margin-right: var(--space-2); } | ||
|
|
||
| .glossary-related-link { | ||
| color: var(--fg-link); | ||
| text-decoration: none; | ||
| text-transform: capitalize; | ||
| } | ||
|
|
||
| .glossary-related-link:hover { color: var(--fg-link-hover); } | ||
|
|
||
| @media (max-width: 900px) { | ||
| .glossary-layout { | ||
| grid-template-columns: 1fr; | ||
| } | ||
|
|
||
| .glossary-sidebar { | ||
| position: static; | ||
| } | ||
| } | ||
|
|
||
| @media (max-width: 768px) { | ||
| .glossary-hero { | ||
| padding: var(--space-20) var(--gutter); | ||
|
|
||
| } | ||
|
|
||
| .glossary-h1 { font-size: var(--fs-h2); } | ||
| } | ||
| .gloss-link:hover { border-color: var(--accent); text-decoration: none; } | ||
| .gloss-link strong { font-size: 15px; color: var(--fg-1); } | ||
| .gloss-link span { font-size: 13px; color: var(--fg-3); line-height: 1.45; } | ||
| </style> |
There was a problem hiding this comment.
Remove the duplicated typography styles from the local <style> block, as they are now handled globally in global.css.
<style>
.glossary-body {
max-width: 820px;
margin: 0 auto;
padding: clamp(32px, 4vw, 48px) clamp(16px, 4vw, 40px) 80px;
display: flex;
flex-direction: column;
gap: 36px;
}
.gloss-letter {
font-family: var(--font-mono);
font-size: 13px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: .1em;
color: var(--fg-3);
padding-bottom: 8px;
border-bottom: 1px solid var(--hair);
margin-bottom: 8px;
}
.gloss-blurb {
font-size: 13px;
color: var(--fg-3);
margin: 0 0 12px;
line-height: 1.5;
}
.gloss-list {
list-style: none;
padding: 0; margin: 0;
display: flex; flex-direction: column; gap: 4px;
}
.gloss-link {
display: flex;
flex-direction: column;
gap: 3px;
padding: 12px 14px;
background: var(--panel);
border: 1px solid var(--hair);
border-radius: var(--radius-md);
text-decoration: none;
transition: border-color var(--dur) var(--ease-out);
}
.gloss-link:hover { border-color: var(--accent); text-decoration: none; }
.gloss-link strong { font-size: 15px; color: var(--fg-1); }
.gloss-link span { font-size: 13px; color: var(--fg-3); line-height: 1.45; }
</style>
| <a | ||
| class="btn-ghost" | ||
| style="font-size:13px; padding:6px 14px;" | ||
| href={`${base}glossary/${r.slug}/`} | ||
| > | ||
| {r.term} | ||
| </a> | ||
| ))} |
| <div class="term-footer"> | ||
| <a class="btn-ghost" href={`${base}glossary/`}>← Back to Glossary</a> | ||
| </div> |
| <style> | ||
| .term-container { | ||
| max-width: var(--container-max); | ||
| margin: 0 auto; | ||
| padding: 0 var(--gutter); | ||
| } | ||
|
|
||
| .term-breadcrumb { | ||
| background: var(--bg); | ||
| border-bottom: 1px solid var(--border); | ||
| padding: var(--space-3) var(--gutter); | ||
| font-size: var(--fs-body-sm); | ||
| } | ||
|
|
||
| .term-breadcrumb div { | ||
| max-width: var(--container-max); | ||
| margin: 0 auto; | ||
| .crumb { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: var(--space-3); | ||
| flex-wrap: wrap; | ||
| gap: 8px; | ||
| font-size: 13px; | ||
| color: var(--fg-3); | ||
| margin-bottom: 24px; | ||
| } | ||
|
|
||
| .term-breadcrumb a { color: var(--fg-link); text-decoration: none; } | ||
| .term-breadcrumb a:hover { color: var(--fg-link-hover); } | ||
| .term-breadcrumb span:not([aria-hidden]) { color: var(--fg-2); } | ||
| .term-breadcrumb [aria-hidden] { color: var(--fg-3); } | ||
|
|
||
| .term-hero { | ||
| background: linear-gradient(135deg, #0F1014 0%, #181820 100%); | ||
| color: var(--c-white); | ||
| padding: var(--space-24) var(--gutter); | ||
| } | ||
| .crumb a { color: var(--fg-3); text-decoration: none; } | ||
| .crumb a:hover { color: var(--accent); } | ||
| .sep { color: var(--fg-3); } | ||
|
|
||
| .term-group-badge { | ||
| display: inline-flex; | ||
| padding: var(--space-2) var(--space-4); | ||
| background: rgba(123, 231, 255, 0.1); | ||
| border: 1px solid rgba(123, 231, 255, 0.3); | ||
| border-radius: var(--radius-pill); | ||
| font-size: var(--fs-eyebrow); | ||
| color: var(--c-light-blue); | ||
| margin-bottom: var(--space-6); | ||
| font-weight: var(--weight-semibold); | ||
| .term-group { | ||
| display: inline-block; | ||
| font-family: var(--font-mono); | ||
| font-size: 11px; | ||
| font-weight: 700; | ||
| text-transform: uppercase; | ||
| letter-spacing: var(--tracking-eyebrow); | ||
| } | ||
|
|
||
| .term-h1 { | ||
| font-size: var(--fs-h2); | ||
| font-weight: var(--weight-extrabold); | ||
| line-height: var(--lh-heading); | ||
| margin: 0; | ||
| color: var(--c-white); | ||
| } | ||
|
|
||
| .term-body { | ||
| padding: var(--space-16) var(--gutter); | ||
| background: var(--bg); | ||
| } | ||
|
|
||
| .term-layout { | ||
| display: grid; | ||
| grid-template-columns: 1fr 280px; | ||
| gap: var(--space-12); | ||
| align-items: start; | ||
| } | ||
|
|
||
| .term-main { | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: var(--space-10); | ||
| } | ||
|
|
||
| .term-def-block { | ||
| padding: var(--space-8); | ||
| background: var(--bg-alt); | ||
| border: 1px solid var(--border); | ||
| border-left: 4px solid var(--accent); | ||
| border-radius: var(--radius-lg); | ||
| } | ||
|
|
||
| .term-def { | ||
| font-size: var(--fs-body-lg); | ||
| line-height: var(--lh-loose); | ||
| color: var(--fg-1); | ||
| margin: 0; | ||
| letter-spacing: .1em; | ||
| color: var(--fg-3); | ||
| background: var(--panel-2); | ||
| border: 1px solid var(--hair); | ||
| border-radius: var(--radius-pill); | ||
| padding: 3px 10px; | ||
| margin-bottom: 12px; | ||
| } | ||
|
|
||
| .term-section-title { | ||
| font-size: var(--fs-h5); | ||
| font-weight: var(--weight-bold); | ||
| .page-h1 { | ||
| font-family: var(--font-display); | ||
| font-weight: 800; | ||
| font-size: clamp(28px, 4vw, 44px); | ||
| letter-spacing: -.025em; | ||
| line-height: 1.1; | ||
| color: var(--fg-1); | ||
| margin: 0 0 var(--space-4) 0; | ||
| margin: 8px 0 20px; | ||
| } | ||
|
|
||
| .term-why { | ||
| font-size: var(--fs-body); | ||
| color: var(--fg-2); | ||
| line-height: var(--lh-loose); | ||
| margin: 0; | ||
| } | ||
|
|
||
| .term-related-grid { | ||
| display: grid; | ||
| grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); | ||
| gap: var(--space-4); | ||
| } | ||
|
|
||
| .term-related-card { | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: var(--space-2); | ||
| padding: var(--space-4); | ||
| background: var(--bg-alt); | ||
| border: 1px solid var(--border); | ||
| margin-top: 28px; | ||
| padding: 16px 20px; | ||
| background: var(--panel-2); | ||
| border: 1px solid var(--hair); | ||
| border-radius: var(--radius-md); | ||
| text-decoration: none; | ||
| color: inherit; | ||
| transition: all var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .term-related-card:hover { | ||
| border-color: var(--accent); | ||
| box-shadow: var(--shadow-sm); | ||
| } | ||
|
|
||
| .term-related-card strong { | ||
| font-size: var(--fs-body-sm); | ||
| color: var(--fg-1); | ||
| font-weight: var(--weight-semibold); | ||
| } | ||
|
|
||
| .term-related-card p { | ||
| font-size: var(--fs-body-sm); | ||
| .term-why-label { | ||
| font-family: var(--font-mono); | ||
| font-size: 11px; | ||
| font-weight: 700; | ||
| text-transform: uppercase; | ||
| letter-spacing: .1em; | ||
| color: var(--fg-3); | ||
| margin: 0; | ||
| line-height: var(--lh-snug); | ||
| margin: 0 0 8px; | ||
| } | ||
|
|
||
| .term-sidebar { | ||
| position: sticky; | ||
| top: 88px; | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: var(--space-4); | ||
| .term-why-body { | ||
| font-size: 15px; | ||
| color: var(--fg-2); | ||
| line-height: 1.6; | ||
| margin: 0; | ||
| } | ||
|
|
||
| .term-sidebar-card { | ||
| background: var(--bg-alt); | ||
| border: 1px solid var(--border); | ||
| border-radius: var(--radius-lg); | ||
| padding: var(--space-5); | ||
| .term-related { | ||
| margin-top: 32px; | ||
| padding-top: 24px; | ||
| border-top: 1px solid var(--hair); | ||
| } | ||
|
|
||
| .term-sidebar-title { | ||
| font-size: var(--fs-eyebrow); | ||
| font-weight: var(--weight-semibold); | ||
| color: var(--fg-3); | ||
| .eyebrow { | ||
| font-family: var(--font-mono); | ||
| font-size: 11px; | ||
| font-weight: 700; | ||
| text-transform: uppercase; | ||
| letter-spacing: var(--tracking-eyebrow); | ||
| margin-bottom: var(--space-2); | ||
| } | ||
|
|
||
| .term-sidebar-group { | ||
| font-size: var(--fs-body-sm); | ||
| font-weight: var(--weight-bold); | ||
| color: var(--fg-1); | ||
| margin-bottom: var(--space-2); | ||
| } | ||
|
|
||
| .term-sidebar-blurb { | ||
| font-size: var(--fs-body-sm); | ||
| color: var(--fg-2); | ||
| margin: 0 0 var(--space-4) 0; | ||
| line-height: var(--lh-snug); | ||
| letter-spacing: .1em; | ||
| color: var(--fg-3); | ||
| margin: 0 0 10px; | ||
| } | ||
|
|
||
| .term-sidebar-entries { | ||
| .term-related-chips { | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: var(--space-1); | ||
| border-top: 1px solid var(--border); | ||
| padding-top: var(--space-4); | ||
| gap: 8px; | ||
| flex-wrap: wrap; | ||
| } | ||
|
|
||
| .term-sidebar-entry { | ||
| display: block; | ||
| padding: var(--space-2) var(--space-3); | ||
| font-size: var(--fs-body-sm); | ||
| color: var(--fg-2); | ||
| text-decoration: none; | ||
| border-radius: var(--radius-sm); | ||
| transition: all var(--dur) var(--ease-out); | ||
| .term-footer { | ||
| margin-top: 40px; | ||
| padding-top: 24px; | ||
| border-top: 1px solid var(--hair); | ||
| } | ||
|
|
||
| .term-sidebar-entry:hover { color: var(--fg-1); background: var(--bg-muted); } | ||
| .term-sidebar-entry--active { color: var(--accent); font-weight: var(--weight-semibold); background: var(--accent-soft); } | ||
|
|
||
| .term-back-link { | ||
| display: inline-block; | ||
| font-size: var(--fs-body-sm); | ||
| color: var(--fg-link); | ||
| .btn-ghost { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| border: 1px solid var(--hair); | ||
| color: var(--fg-2); | ||
| padding: 8px 16px; | ||
| border-radius: var(--radius-pill); | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| text-decoration: none; | ||
| font-weight: var(--weight-medium); | ||
| padding: var(--space-3) var(--space-4); | ||
| border: 1px solid var(--border); | ||
| border-radius: var(--radius-md); | ||
| text-align: center; | ||
| transition: all var(--dur) var(--ease-out); | ||
| transition: border-color var(--dur) var(--ease-out), color var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .term-back-link:hover { border-color: var(--accent); color: var(--accent); } | ||
|
|
||
| @media (max-width: 900px) { | ||
| .term-layout { grid-template-columns: 1fr; } | ||
| .term-sidebar { position: static; } | ||
| } | ||
|
|
||
| @media (max-width: 768px) { | ||
| .term-hero { padding: var(--space-16) var(--gutter); } | ||
| } | ||
| .btn-ghost:hover { border-color: var(--accent); color: var(--accent); } | ||
| </style> |
There was a problem hiding this comment.
Remove the duplicated .btn-ghost styles from the local <style> block, as they are now handled globally in global.css.
<style>
.crumb {
display: flex;
align-items: center;
gap: 8px;
font-size: 13px;
color: var(--fg-3);
margin-bottom: 24px;
}
.crumb a { color: var(--fg-3); text-decoration: none; }
.crumb a:hover { color: var(--accent); }
.sep { color: var(--fg-3); }
.term-group {
display: inline-block;
font-family: var(--font-mono);
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: .1em;
color: var(--fg-3);
background: var(--panel-2);
border: 1px solid var(--hair);
border-radius: var(--radius-pill);
padding: 3px 10px;
margin-bottom: 12px;
}
.page-h1 {
margin: 8px 0 20px;
}
.term-why {
margin-top: 28px;
padding: 16px 20px;
background: var(--panel-2);
border: 1px solid var(--hair);
border-radius: var(--radius-md);
}
.term-why-label {
font-family: var(--font-mono);
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: .1em;
color: var(--fg-3);
margin: 0 0 8px;
}
.term-why-body {
font-size: 15px;
color: var(--fg-2);
line-height: 1.6;
margin: 0;
}
.term-related {
margin-top: 32px;
padding-top: 24px;
border-top: 1px solid var(--hair);
}
.eyebrow {
margin: 0 0 10px;
}
.term-related-chips {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.term-footer {
margin-top: 40px;
padding-top: 24px;
border-top: 1px solid var(--hair);
}
</style>
There was a problem hiding this comment.
Pull request overview
This PR rebuilds the Phase 12 editorial/reference pages to use the newer BaseLayout + WapuuHero pattern and a shared 820px prose container, aligning these pages with the current site layout and typography system.
Changes:
- Replaces legacy
AwesomeGithubLayoutusage across editorial pages withBaseLayout+ new.editorial-hero/.prose-bodystyling. - Adds global CSS for the editorial hero and onboarding step layouts.
- Reworks content structure for Getting Started, Why, Onboarding, Glossary (index + term), References, and refreshes the 404 page.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| website/src/styles/global.css | Adds global styling for editorial hero, prose body container, and onboarding step layout. |
| website/src/pages/why.astro | Migrates to BaseLayout + WapuuHero and updates CTA styling/structure. |
| website/src/pages/references.astro | Rebuilds References to render REFERENCE_GROUPS and adopts the editorial hero pattern. |
| website/src/pages/onboarding.astro | Replaces redirect with full onboarding narrative using step layout + CTAs. |
| website/src/pages/glossary/index.astro | Simplifies glossary index into grouped term lists under the editorial hero pattern. |
| website/src/pages/glossary/[term].astro | Rebuilds term detail page layout, adds related-term chips, and simplifies sidebar structure. |
| website/src/pages/getting-started.astro | Rebuilds page as a 6-step guide using the new step layout and hero pattern. |
| website/src/pages/404.astro | Replaces the old 404 layout with a spec-aligned centred wapuu + home CTA. |
| A map of the key files in <code>lightspeedwp/.github</code>. Links open | ||
| the <code>{branch}</code> branch on GitHub. | ||
| </p> | ||
| <a | ||
| href="https://github.com/lightspeedwp/.github/blob/develop/LICENSE" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| class="ref-licence-link" | ||
| > | ||
| Read the full GPL v3 Licence ↗ | ||
| </a> | ||
| </div> | ||
| <WapuuHero page="why" /> | ||
| </div> |
| .btn-primary { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| background: var(--c-brand-blue); | ||
| color: #fff; | ||
| padding: 10px 22px; | ||
| border-radius: var(--radius-pill); | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| text-decoration: none; | ||
| transition: background var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .btn-primary:hover { background: #1857D6; } | ||
|
|
||
| .btn-ghost { |
| .btn-primary { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| background: var(--c-brand-blue); | ||
| color: #fff; | ||
| padding: 10px 22px; | ||
| border-radius: var(--radius-pill); | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| text-decoration: none; | ||
| font-size: var(--fs-body-sm); | ||
| font-weight: var(--weight-medium); | ||
| transition: background var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .ref-licence-link:hover { color: var(--fg-link-hover); } | ||
| .btn-primary:hover { background: #1857D6; } | ||
|
|
| .btn-primary { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| background: var(--c-brand-blue); | ||
| color: #fff; | ||
| padding: 10px 22px; | ||
| border-radius: var(--radius-pill); | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| text-decoration: none; | ||
| transition: background var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .btn-primary:hover { background: #1857D6; } | ||
|
|
| .btn-primary { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| background: var(--c-brand-blue); | ||
| color: #fff; | ||
| padding: 10px 22px; | ||
| border-radius: var(--radius-pill); | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| text-decoration: none; | ||
| transition: background var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .gs-next-card h3 { | ||
| font-size: var(--fs-h5); | ||
| font-weight: var(--weight-bold); | ||
| margin: 0; | ||
| color: var(--fg-1); | ||
| } | ||
| .btn-primary:hover { background: #1857D6; } | ||
|
|
| .step-note { | ||
| font-size: 13px !important; | ||
| color: var(--fg-3) !important; | ||
| margin-top: 10px !important; | ||
| font-style: italic; | ||
| } |
| <BaseLayout title="404 — Page not found — Awesome GitHub"> | ||
| <main style="display:flex; flex-direction:column; align-items:center; justify-content:center; min-height:60vh; gap:24px; text-align:center; padding: 48px 24px;"> |
| transition: background var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .btn-home:hover { background: #1857D6; } |
| <a | ||
| class="btn-ghost" | ||
| style="font-size:13px; padding:6px 14px;" | ||
| href={`${base}glossary/${r.slug}/`} | ||
| > |
| .btn-ghost { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| border: 1px solid var(--hair); | ||
| color: var(--fg-2); | ||
| padding: 8px 16px; | ||
| border-radius: var(--radius-pill); | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| text-decoration: none; | ||
| font-weight: var(--weight-medium); | ||
| padding: var(--space-3) var(--space-4); | ||
| border: 1px solid var(--border); | ||
| border-radius: var(--radius-md); | ||
| text-align: center; | ||
| transition: all var(--dur) var(--ease-out); | ||
| transition: border-color var(--dur) var(--ease-out), color var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .term-back-link:hover { border-color: var(--accent); color: var(--accent); } | ||
|
|
||
| @media (max-width: 900px) { | ||
| .term-layout { grid-template-columns: 1fr; } | ||
| .term-sidebar { position: static; } | ||
| } | ||
|
|
||
| @media (max-width: 768px) { | ||
| .term-hero { padding: var(--space-16) var(--gutter); } | ||
| } | ||
| .btn-ghost:hover { border-color: var(--accent); color: var(--accent); } |
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (9)
website/src/pages/glossary/[term].astro (4)
7-12: ⚡ Quick winSimplify: use
Astro.params.termdirectly instead of duplicating into props.You're returning the same slug in both
params.termandprops.termSlug, then reading from props. Astro's dynamic route params are already available viaAstro.params, so the extra props pass is redundant.🧹 Simplified data fetching
export function getStaticPaths() { - return getAllEntries().map((e) => ({ params: { term: e.slug }, props: { termSlug: e.slug } })); + return getAllEntries().map((e) => ({ params: { term: e.slug } })); } -const { termSlug } = Astro.props; -const entry = getEntry(termSlug); +const entry = getEntry(Astro.params.term);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/src/pages/glossary/`[term].astro around lines 7 - 12, The code duplicates the slug by returning it in props and then reading props.termSlug; instead use Astro.params.term directly. Update getStaticPaths (which currently maps getAllEntries to { params: { term: e.slug }, props: { termSlug: e.slug } }) to stop returning props.termSlug, and change the page to read const term = Astro.params.term and call getEntry(term) (referencing getStaticPaths, Astro.params.term, props.termSlug, getAllEntries, and getEntry to locate the changes).
52-59: 💤 Low valueInline styles on related-term chips — consider a CSS modifier.
You've got
style="font-size:13px; padding:6px 14px;"inline here, but the rest of your styling lives in<style>. A.btn-ghost-smmodifier or similar would keep things centralised.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/src/pages/glossary/`[term].astro around lines 52 - 59, Replace the inline style on the related-term anchor with a CSS modifier class: remove style="font-size:13px; padding:6px 14px;" from the <a class="btn-ghost"> element (the one rendering {r.term}) and add a modifier like "btn-ghost-sm" to the class list; then define the .btn-ghost-sm rule in the component's <style> block with the same font-size and padding so styling is centralized and consistent across related-term chips.
42-42: ⚡ Quick winUse heading elements for "Why it matters" and "Related terms" labels.
Right now these section labels are paragraphs, but semantically they're headings for their respective sections. Switching to
<h2>(or<h3>if you prefer) improves the document outline and helps screen-reader users navigate.📐 Semantic heading structure
{entry.why && ( <div class="term-why"> - <p class="term-why-label">Why it matters</p> + <h2 class="term-why-label">Why it matters</h2> <p class="term-why-body">{entry.why}</p> </div> )} {related.length > 0 && ( <div class="term-related"> - <p class="eyebrow">Related terms</p> + <h2 class="eyebrow">Related terms</h2> <div class="term-related-chips">You may want to tweak the CSS to reset default heading margins if needed.
As per coding guidelines: "Ensure WCAG 2.2 AA minimum accessibility compliance with semantic HTML".
Also applies to: 49-49
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/src/pages/glossary/`[term].astro at line 42, The "Why it matters" and "Related terms" labels are currently paragraphs but should be semantic headings; replace the <p class="term-why-label"> and the corresponding <p class="term-related-label"> elements in glossary/[term].astro with appropriate heading elements (e.g., <h2> or <h3>) to improve document outline and screen-reader navigation, and adjust or add CSS rules for .term-why-label and .term-related-label to reset heading default margins if needed.Source: Coding guidelines
24-24: 💤 Low valueConsider moving inline styles to a CSS class.
The rest of your styles live in the
<style>block, but here you've got padding rules inline. Popping them into a class would keep things tidy and consistent.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/src/pages/glossary/`[term].astro at line 24, The inline padding on the div with class "wrap-prose" should be moved into a named CSS class: create a new class (e.g., "glossary-hero" or similar) in the existing <style> block with the rules padding-top: clamp(32px, 4vw, 56px) and padding-bottom: 80px, then replace the inline style on the <div class="wrap-prose"> by adding that class (e.g., <div class="wrap-prose glossary-hero">) so all styling lives in the stylesheet and no inline styles remain.website/src/pages/glossary/index.astro (1)
40-40: ⚡ Quick winTruncation cuts mid-word — consider word boundaries.
The
slice(0, 100)chops at exactly 100 characters, which can split words awkwardly. For a smoother preview, you might want to find the last space before the limit and trim there.✂️ Suggested word-boundary truncation
- <span>{entry.def.slice(0, 100)}{entry.def.length > 100 ? '…' : ''}</span> + <span>{entry.def.length > 100 ? entry.def.slice(0, entry.def.lastIndexOf(' ', 100)) + '…' : entry.def}</span>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/src/pages/glossary/index.astro` at line 40, The current preview uses entry.def.slice(0, 100) which can cut words mid-word; change the truncation to cut at the last word boundary before the limit by computing a safeCut = (entry.def.length > 100) ? entry.def.slice(0, 100).lastIndexOf(' ') : -1 and then use entry.def.slice(0, safeCut > 0 ? safeCut : 100) + (entry.def.length > 100 ? '…' : ''); update the span rendering that uses entry.def so it uses this computed truncated string (keep entry.def as the source and ensure a fallback when no space is found).website/src/pages/references.astro (1)
25-25: ⚡ Quick winUse the references page key here, not
why.Line 25 currently ties this page to the
whyhero asset.WapuuHeroalready falls back when a page key is unknown, sopage="references"keeps the route-to-hero contract tidy and stops futurewhyart changes sneaking onto the references page.Suggested tweak
- <WapuuHero page="why" /> + <WapuuHero page="references" />🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/src/pages/references.astro` at line 25, The WapuuHero invocation on this page is using the wrong page key: change the prop on the WapuuHero component from page="why" to page="references" so the references route maps to its intended hero asset (WapuuHero already falls back for unknown keys, but using the correct key prevents accidental art bleed from the `why` asset).website/src/pages/getting-started.astro (2)
218-218: ⚡ Quick winUse CSS custom property for consistency.
The
.btn-primary:hoverstyle uses a hardcoded colour#1857D6. For consistency with the global button styles (global.css line 190), usevar(--c-brand-blue-hover)instead.♻️ Proposed fix
- .btn-primary:hover { background: `#1857D6`; } + .btn-primary:hover { background: var(--c-brand-blue-hover); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/src/pages/getting-started.astro` at line 218, Replace the hardcoded hover colour in the .btn-primary:hover rule with the shared CSS custom property used by global button styles: change the value "`#1857D6`" in the .btn-primary:hover selector to use var(--c-brand-blue-hover) so the hover state remains consistent with the global button styling.
165-170: ⚡ Quick winAvoid
!importantby refining specificity.The
.step-noterule uses!importantthree times, which suggests a specificity conflict. Instead of forcing priority with!important, consider increasing the selector specificity (e.g.,.ob-step-body .step-note) or reviewing what's overriding these styles.♻️ Proposed fix
- .step-note { - font-size: 13px !important; - color: var(--fg-3) !important; - margin-top: 10px !important; + .ob-step-body .step-note { + font-size: 13px; + color: var(--fg-3); + margin-top: 10px; font-style: italic; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/src/pages/getting-started.astro` around lines 165 - 170, The .step-note rule is using three !important flags; remove those and resolve the specificity conflict by increasing selector specificity (for example change selector to .ob-step-body .step-note or a more specific parent chain that matches the component structure) or move the rule into the component-scoped stylesheet so it wins naturally; update the CSS selector where .step-note is defined and remove the !important annotations from font-size, color and margin-top so the new selector provides the needed precedence.website/src/pages/why.astro (1)
198-198: ⚡ Quick winUse CSS custom property for consistency.
The
.btn-primary:hoverstyle uses a hardcoded colour#1857D6. For consistency with the global button styles (global.css line 190), usevar(--c-brand-blue-hover)instead.This is the same issue as in getting-started.astro line 218.
♻️ Proposed fix
- .btn-primary:hover { background: `#1857D6`; } + .btn-primary:hover { background: var(--c-brand-blue-hover); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/src/pages/why.astro` at line 198, Replace the hardcoded hover colour in the .btn-primary:hover rule (currently "`#1857D6`") with the CSS custom property used by global button styles (var(--c-brand-blue-hover)); update the .btn-primary:hover declaration in why.astro (and the identical .btn-primary:hover in getting-started.astro) so they reference var(--c-brand-blue-hover) instead of the literal hex value to ensure consistency with global.css.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@website/src/pages/404.astro`:
- Around line 33-47: The .btn-home styles use hardcoded colours; replace the
literal values with theme variables: change color: `#fff` to color:
var(--fg-on-brand) (or your design token for foreground-on-brand) and change the
hover background `#1857D6` to var(--c-brand-blue-hover); update the .btn-home and
.btn-home:hover rules accordingly and ensure the design tokens --fg-on-brand and
--c-brand-blue-hover are defined in your global tokens if they don't already
exist.
In `@website/src/pages/getting-started.astro`:
- Around line 68-91: Step titles in the steps list are using <h3> which skips
the page <h1> and breaks heading hierarchy; change the step title element from
h3 to h2 in the steps.map rendering (the element that renders step.title inside
the ob-step-body) and update the related stylesheet selector(s) that target
.ob-step-body h3 (or similar) to target h2 instead so visual styling remains
unchanged while restoring semantic heading order.
In `@website/src/pages/glossary/`[term].astro:
- Around line 163-176: Add keyboard-visible focus styles for the interactive
selectors that currently only have hover: specifically update the .btn-ghost and
.crumb a rules to include a :focus-visible variant that mirrors the hover accent
(change border-color and color) and adds a clear high-contrast focus ring
(outline or box-shadow) so keyboard users can see focus; use :focus-visible (not
:focus) and ensure the ring thickness and color meet WCAG contrast requirements
and don’t shift layout.
In `@website/src/pages/glossary/index.astro`:
- Around line 116-130: Add keyboard focus indicators by implementing
:focus-visible rules for both .gloss-link and .crumb a: when they receive
keyboard focus, make the focus state visually prominent (e.g., set a clear
outline or border-color matching the hover accent, and/or a visible box-shadow)
and preserve text-decoration none; use :focus-visible (not just :focus) so mouse
interactions aren’t affected, and ensure the styles align with existing hover
styles (.gloss-link:hover uses border-color: var(--accent)) and meet
contrast/accessibility requirements.
In `@website/src/pages/onboarding.astro`:
- Around line 65-68: Replace the wrapper div with a semantic section and bump
the heading level from h3 to h2 for each chapter: change the element that has
class "ob-step" and id `ch-${ch.n}` (currently rendered as <div class="ob-step"
id={`ch-${ch.n}`}>...) to a <section> and update the inner <h3>{ch.title}</h3>
to <h2>{ch.title}</h2> so the document outline is correct and screen
readers/keyboard users get proper headings.
In `@website/src/pages/references.astro`:
- Around line 36-45: The anchor element rendered by the reference row (class
"ref-row", href from refUrl) opens a new browsing context but only shows a
visual ↗ in span "ref-ext" which is aria-hidden — add an accessible cue by
either: 1) adding an aria-label to the anchor that includes the existing
description plus "opens in new tab", or 2) appending a visually-hidden span (not
aria-hidden) after span "ref-desc" with the text "opens in new tab"; apply the
same change to the other reference links mentioned (lines 52-59) so
screen-reader users are informed of the new-tab behavior.
In `@website/src/pages/why.astro`:
- Around line 120-213: Duplicate editorial styles (.eyebrow, .page-h1,
.page-lead, .page-lead code, .btn-primary, .btn-ghost) should be extracted into
a single shared stylesheet and imported by pages instead of duplicated; create a
new editorial-shared.css (or add to global.css), move the block of CSS for those
selectors into it, keep the exact variable references and rules intact, then
remove the duplicated blocks from why.astro and getting-started.astro and add an
import/link to the shared stylesheet in each page (or ensure global.css includes
it) so both pages use the single source of truth.
---
Nitpick comments:
In `@website/src/pages/getting-started.astro`:
- Line 218: Replace the hardcoded hover colour in the .btn-primary:hover rule
with the shared CSS custom property used by global button styles: change the
value "`#1857D6`" in the .btn-primary:hover selector to use
var(--c-brand-blue-hover) so the hover state remains consistent with the global
button styling.
- Around line 165-170: The .step-note rule is using three !important flags;
remove those and resolve the specificity conflict by increasing selector
specificity (for example change selector to .ob-step-body .step-note or a more
specific parent chain that matches the component structure) or move the rule
into the component-scoped stylesheet so it wins naturally; update the CSS
selector where .step-note is defined and remove the !important annotations from
font-size, color and margin-top so the new selector provides the needed
precedence.
In `@website/src/pages/glossary/`[term].astro:
- Around line 7-12: The code duplicates the slug by returning it in props and
then reading props.termSlug; instead use Astro.params.term directly. Update
getStaticPaths (which currently maps getAllEntries to { params: { term: e.slug
}, props: { termSlug: e.slug } }) to stop returning props.termSlug, and change
the page to read const term = Astro.params.term and call getEntry(term)
(referencing getStaticPaths, Astro.params.term, props.termSlug, getAllEntries,
and getEntry to locate the changes).
- Around line 52-59: Replace the inline style on the related-term anchor with a
CSS modifier class: remove style="font-size:13px; padding:6px 14px;" from the <a
class="btn-ghost"> element (the one rendering {r.term}) and add a modifier like
"btn-ghost-sm" to the class list; then define the .btn-ghost-sm rule in the
component's <style> block with the same font-size and padding so styling is
centralized and consistent across related-term chips.
- Line 42: The "Why it matters" and "Related terms" labels are currently
paragraphs but should be semantic headings; replace the <p
class="term-why-label"> and the corresponding <p class="term-related-label">
elements in glossary/[term].astro with appropriate heading elements (e.g., <h2>
or <h3>) to improve document outline and screen-reader navigation, and adjust or
add CSS rules for .term-why-label and .term-related-label to reset heading
default margins if needed.
- Line 24: The inline padding on the div with class "wrap-prose" should be moved
into a named CSS class: create a new class (e.g., "glossary-hero" or similar) in
the existing <style> block with the rules padding-top: clamp(32px, 4vw, 56px)
and padding-bottom: 80px, then replace the inline style on the <div
class="wrap-prose"> by adding that class (e.g., <div class="wrap-prose
glossary-hero">) so all styling lives in the stylesheet and no inline styles
remain.
In `@website/src/pages/glossary/index.astro`:
- Line 40: The current preview uses entry.def.slice(0, 100) which can cut words
mid-word; change the truncation to cut at the last word boundary before the
limit by computing a safeCut = (entry.def.length > 100) ? entry.def.slice(0,
100).lastIndexOf(' ') : -1 and then use entry.def.slice(0, safeCut > 0 ? safeCut
: 100) + (entry.def.length > 100 ? '…' : ''); update the span rendering that
uses entry.def so it uses this computed truncated string (keep entry.def as the
source and ensure a fallback when no space is found).
In `@website/src/pages/references.astro`:
- Line 25: The WapuuHero invocation on this page is using the wrong page key:
change the prop on the WapuuHero component from page="why" to page="references"
so the references route maps to its intended hero asset (WapuuHero already falls
back for unknown keys, but using the correct key prevents accidental art bleed
from the `why` asset).
In `@website/src/pages/why.astro`:
- Line 198: Replace the hardcoded hover colour in the .btn-primary:hover rule
(currently "`#1857D6`") with the CSS custom property used by global button styles
(var(--c-brand-blue-hover)); update the .btn-primary:hover declaration in
why.astro (and the identical .btn-primary:hover in getting-started.astro) so
they reference var(--c-brand-blue-hover) instead of the literal hex value to
ensure consistency with global.css.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro
Run ID: 0831af20-4b1a-4cd5-a561-6ed835ef0151
📒 Files selected for processing (8)
website/src/pages/404.astrowebsite/src/pages/getting-started.astrowebsite/src/pages/glossary/[term].astrowebsite/src/pages/glossary/index.astrowebsite/src/pages/onboarding.astrowebsite/src/pages/references.astrowebsite/src/pages/why.astrowebsite/src/styles/global.css
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Unified Labeling, Status, and Type Assignment
- GitHub Check: copilot-pull-request-reviewer
- GitHub Check: coderabbit-gate
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{php,js,jsx,ts,tsx,css,scss,html}
📄 CodeRabbit inference engine (AGENTS.md)
Follow WordPress Coding Standards (CSS, HTML, JavaScript, PHP) and inline-documentation standards at all times
Files:
website/src/styles/global.css
**/*.{php,html,css,scss}
📄 CodeRabbit inference engine (CLAUDE.md)
Ensure WCAG 2.2 AA minimum accessibility compliance with semantic HTML, keyboard support, and sufficient contrast
Files:
website/src/styles/global.css
🔇 Additional comments (16)
website/src/pages/glossary/index.astro (2)
1-8: LGTM!
10-27: LGTM!website/src/pages/glossary/[term].astro (1)
64-69: LGTM!website/src/pages/404.astro (4)
1-5: LGTM!
7-15: LGTM!
16-27: LGTM!
36-37: WCAG 2.2 AA contrast for.btn-home(404) looks good 👍
- Default:
var(--c-brand-blue)(#1e6aff) on#fff→ 4.60:1 (meets 4.5:1)- Hover:
#1857D6on#fff→ 6.23:1 (meets 4.5:1)website/src/styles/global.css (2)
368-394: LGTM!
406-417: WCAG contrast for.ob-step-numbadge is OK (no change needed)
.ob-step-numusesvar(--accent)text onvar(--accent-soft)background, and the computed contrast ratios are ~4.03:1 (light over--bg) / 3.86:1 (light over--panel-2), and 8.76:1 / 7.53:1 in dark mode—so it meets WCAG 2.2 AA (≥3:1) for large bold text.
.ob-step-body .run-pillinglobal.cssonly setsmargin-top; the rest of the.run-pillstyling lives elsewhere.website/src/pages/getting-started.astro (3)
1-46: LGTM!
49-66: LGTM!
93-100: LGTM!website/src/pages/why.astro (4)
1-11: LGTM!
12-25: LGTM!
27-105: LGTM!
107-115: LGTM!
| .btn-ghost { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| border: 1px solid var(--hair); | ||
| color: var(--fg-2); | ||
| padding: 8px 16px; | ||
| border-radius: var(--radius-pill); | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| text-decoration: none; | ||
| font-weight: var(--weight-medium); | ||
| padding: var(--space-3) var(--space-4); | ||
| border: 1px solid var(--border); | ||
| border-radius: var(--radius-md); | ||
| text-align: center; | ||
| transition: all var(--dur) var(--ease-out); | ||
| transition: border-color var(--dur) var(--ease-out), color var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .term-back-link:hover { border-color: var(--accent); color: var(--accent); } | ||
|
|
||
| @media (max-width: 900px) { | ||
| .term-layout { grid-template-columns: 1fr; } | ||
| .term-sidebar { position: static; } | ||
| } | ||
|
|
||
| @media (max-width: 768px) { | ||
| .term-hero { padding: var(--space-16) var(--gutter); } | ||
| } | ||
| .btn-ghost:hover { border-color: var(--accent); color: var(--accent); } |
There was a problem hiding this comment.
Add :focus-visible styles for keyboard navigation.
The .btn-ghost and .crumb a elements have hover states but no visible focus indicators for keyboard users. This breaks WCAG 2.2 AA compliance — every interactive element needs a clear focus state.
⌨️ Recommended focus styles
.crumb a:hover { color: var(--accent); }
+ .crumb a:focus-visible { color: var(--accent); outline: 2px solid var(--accent); outline-offset: 2px; }
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); }
+ .btn-ghost:focus-visible { border-color: var(--accent); color: var(--accent); outline: 2px solid var(--accent); outline-offset: 2px; }As per coding guidelines: "Ensure WCAG 2.2 AA minimum accessibility compliance with semantic HTML, keyboard support, and sufficient contrast".
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .btn-ghost { | |
| display: inline-flex; | |
| align-items: center; | |
| border: 1px solid var(--hair); | |
| color: var(--fg-2); | |
| padding: 8px 16px; | |
| border-radius: var(--radius-pill); | |
| font-size: 14px; | |
| font-weight: 600; | |
| text-decoration: none; | |
| font-weight: var(--weight-medium); | |
| padding: var(--space-3) var(--space-4); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-md); | |
| text-align: center; | |
| transition: all var(--dur) var(--ease-out); | |
| transition: border-color var(--dur) var(--ease-out), color var(--dur) var(--ease-out); | |
| } | |
| .term-back-link:hover { border-color: var(--accent); color: var(--accent); } | |
| @media (max-width: 900px) { | |
| .term-layout { grid-template-columns: 1fr; } | |
| .term-sidebar { position: static; } | |
| } | |
| @media (max-width: 768px) { | |
| .term-hero { padding: var(--space-16) var(--gutter); } | |
| } | |
| .btn-ghost:hover { border-color: var(--accent); color: var(--accent); } | |
| .btn-ghost { | |
| display: inline-flex; | |
| align-items: center; | |
| border: 1px solid var(--hair); | |
| color: var(--fg-2); | |
| padding: 8px 16px; | |
| border-radius: var(--radius-pill); | |
| font-size: 14px; | |
| font-weight: 600; | |
| text-decoration: none; | |
| transition: border-color var(--dur) var(--ease-out), color var(--dur) var(--ease-out); | |
| } | |
| .btn-ghost:hover { border-color: var(--accent); color: var(--accent); } | |
| .btn-ghost:focus-visible { border-color: var(--accent); color: var(--accent); outline: 2px solid var(--accent); outline-offset: 2px; } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/src/pages/glossary/`[term].astro around lines 163 - 176, Add
keyboard-visible focus styles for the interactive selectors that currently only
have hover: specifically update the .btn-ghost and .crumb a rules to include a
:focus-visible variant that mirrors the hover accent (change border-color and
color) and adds a clear high-contrast focus ring (outline or box-shadow) so
keyboard users can see focus; use :focus-visible (not :focus) and ensure the
ring thickness and color meet WCAG contrast requirements and don’t shift layout.
Source: Coding guidelines
| .gloss-link { | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: 0; | ||
| } | ||
|
|
||
| .glossary-entry { | ||
| padding: var(--space-6) 0; | ||
| border-bottom: 1px solid var(--border); | ||
| } | ||
|
|
||
| .glossary-entry:last-child { border-bottom: none; } | ||
|
|
||
| .glossary-term { | ||
| font-size: var(--fs-h5); | ||
| font-weight: var(--weight-bold); | ||
| margin: 0 0 var(--space-3) 0; | ||
| } | ||
|
|
||
| .glossary-term a { | ||
| color: var(--fg-1); | ||
| gap: 3px; | ||
| padding: 12px 14px; | ||
| background: var(--panel); | ||
| border: 1px solid var(--hair); | ||
| border-radius: var(--radius-md); | ||
| text-decoration: none; | ||
| border-bottom: 2px solid transparent; | ||
| transition: border-color var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .glossary-term a:hover { border-bottom-color: var(--accent); } | ||
|
|
||
| .glossary-def { | ||
| font-size: var(--fs-body); | ||
| color: var(--fg); | ||
| margin: 0 0 var(--space-3) 0; | ||
| line-height: var(--lh-loose); | ||
| max-width: 65ch; | ||
| } | ||
|
|
||
| .glossary-why { | ||
| font-size: var(--fs-body-sm); | ||
| color: var(--fg-2); | ||
| margin: 0 0 var(--space-3) 0; | ||
| line-height: var(--lh-loose); | ||
| } | ||
|
|
||
| .glossary-why strong { color: var(--fg-1); } | ||
|
|
||
| .glossary-related { | ||
| display: flex; | ||
| align-items: center; | ||
| flex-wrap: wrap; | ||
| gap: 0; | ||
| font-size: var(--fs-body-sm); | ||
| color: var(--fg-3); | ||
| } | ||
|
|
||
| .glossary-related-label { margin-right: var(--space-2); } | ||
|
|
||
| .glossary-related-link { | ||
| color: var(--fg-link); | ||
| text-decoration: none; | ||
| text-transform: capitalize; | ||
| } | ||
|
|
||
| .glossary-related-link:hover { color: var(--fg-link-hover); } | ||
|
|
||
| @media (max-width: 900px) { | ||
| .glossary-layout { | ||
| grid-template-columns: 1fr; | ||
| } | ||
|
|
||
| .glossary-sidebar { | ||
| position: static; | ||
| } | ||
| } | ||
|
|
||
| @media (max-width: 768px) { | ||
| .glossary-hero { | ||
| padding: var(--space-20) var(--gutter); | ||
|
|
||
| } | ||
|
|
||
| .glossary-h1 { font-size: var(--fs-h2); } | ||
| } | ||
| .gloss-link:hover { border-color: var(--accent); text-decoration: none; } | ||
| .gloss-link strong { font-size: 15px; color: var(--fg-1); } | ||
| .gloss-link span { font-size: 13px; color: var(--fg-3); line-height: 1.45; } |
There was a problem hiding this comment.
Add :focus-visible styles for keyboard accessibility.
The .gloss-link hover state is lovely, but there's no focus indicator for keyboard users. WCAG 2.2 AA requires visible focus states on all interactive elements. Same goes for .crumb a at Line 82.
⌨️ Recommended focus styles
For .gloss-link:
.gloss-link:hover { border-color: var(--accent); text-decoration: none; }
+ .gloss-link:focus-visible { border-color: var(--accent); outline: 2px solid var(--accent); outline-offset: 2px; }
.gloss-link strong { font-size: 15px; color: var(--fg-1); }And for .crumb a:
.crumb a:hover { color: var(--accent); }
+ .crumb a:focus-visible { color: var(--accent); outline: 2px solid var(--accent); outline-offset: 2px; }As per coding guidelines: "Ensure WCAG 2.2 AA minimum accessibility compliance with semantic HTML, keyboard support, and sufficient contrast".
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .gloss-link { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 0; | |
| } | |
| .glossary-entry { | |
| padding: var(--space-6) 0; | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .glossary-entry:last-child { border-bottom: none; } | |
| .glossary-term { | |
| font-size: var(--fs-h5); | |
| font-weight: var(--weight-bold); | |
| margin: 0 0 var(--space-3) 0; | |
| } | |
| .glossary-term a { | |
| color: var(--fg-1); | |
| gap: 3px; | |
| padding: 12px 14px; | |
| background: var(--panel); | |
| border: 1px solid var(--hair); | |
| border-radius: var(--radius-md); | |
| text-decoration: none; | |
| border-bottom: 2px solid transparent; | |
| transition: border-color var(--dur) var(--ease-out); | |
| } | |
| .glossary-term a:hover { border-bottom-color: var(--accent); } | |
| .glossary-def { | |
| font-size: var(--fs-body); | |
| color: var(--fg); | |
| margin: 0 0 var(--space-3) 0; | |
| line-height: var(--lh-loose); | |
| max-width: 65ch; | |
| } | |
| .glossary-why { | |
| font-size: var(--fs-body-sm); | |
| color: var(--fg-2); | |
| margin: 0 0 var(--space-3) 0; | |
| line-height: var(--lh-loose); | |
| } | |
| .glossary-why strong { color: var(--fg-1); } | |
| .glossary-related { | |
| display: flex; | |
| align-items: center; | |
| flex-wrap: wrap; | |
| gap: 0; | |
| font-size: var(--fs-body-sm); | |
| color: var(--fg-3); | |
| } | |
| .glossary-related-label { margin-right: var(--space-2); } | |
| .glossary-related-link { | |
| color: var(--fg-link); | |
| text-decoration: none; | |
| text-transform: capitalize; | |
| } | |
| .glossary-related-link:hover { color: var(--fg-link-hover); } | |
| @media (max-width: 900px) { | |
| .glossary-layout { | |
| grid-template-columns: 1fr; | |
| } | |
| .glossary-sidebar { | |
| position: static; | |
| } | |
| } | |
| @media (max-width: 768px) { | |
| .glossary-hero { | |
| padding: var(--space-20) var(--gutter); | |
| } | |
| .glossary-h1 { font-size: var(--fs-h2); } | |
| } | |
| .gloss-link:hover { border-color: var(--accent); text-decoration: none; } | |
| .gloss-link strong { font-size: 15px; color: var(--fg-1); } | |
| .gloss-link span { font-size: 13px; color: var(--fg-3); line-height: 1.45; } | |
| .gloss-link { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 3px; | |
| padding: 12px 14px; | |
| background: var(--panel); | |
| border: 1px solid var(--hair); | |
| border-radius: var(--radius-md); | |
| text-decoration: none; | |
| transition: border-color var(--dur) var(--ease-out); | |
| } | |
| .gloss-link:hover { border-color: var(--accent); text-decoration: none; } | |
| .gloss-link:focus-visible { border-color: var(--accent); outline: 2px solid var(--accent); outline-offset: 2px; } | |
| .gloss-link strong { font-size: 15px; color: var(--fg-1); } | |
| .gloss-link span { font-size: 13px; color: var(--fg-3); line-height: 1.45; } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/src/pages/glossary/index.astro` around lines 116 - 130, Add keyboard
focus indicators by implementing :focus-visible rules for both .gloss-link and
.crumb a: when they receive keyboard focus, make the focus state visually
prominent (e.g., set a clear outline or border-color matching the hover accent,
and/or a visible box-shadow) and preserve text-decoration none; use
:focus-visible (not just :focus) so mouse interactions aren’t affected, and
ensure the styles align with existing hover styles (.gloss-link:hover uses
border-color: var(--accent)) and meet contrast/accessibility requirements.
Source: Coding guidelines
| .eyebrow { | ||
| display: inline-block; | ||
| font-family: var(--font-mono); | ||
| font-size: 12px; | ||
| font-weight: 700; | ||
| text-transform: uppercase; | ||
| letter-spacing: var(--tracking-eyebrow); | ||
| } | ||
|
|
||
| .why-h1 { | ||
| font-size: var(--fs-h2); | ||
| font-weight: var(--weight-extrabold); | ||
| line-height: var(--lh-heading); | ||
| margin: 0 0 var(--space-6) 0; | ||
| color: var(--c-white); | ||
| letter-spacing: .1em; | ||
| color: var(--fg-3); | ||
| margin-bottom: 12px; | ||
| } | ||
|
|
||
| .why-lead { | ||
| font-size: var(--fs-body-lg); | ||
| color: var(--c-slate-300); | ||
| margin: 0; | ||
| line-height: var(--lh-loose); | ||
| max-width: 60ch; | ||
| } | ||
|
|
||
| .why-section { | ||
| padding: var(--space-20) var(--gutter); | ||
| background: var(--bg); | ||
| } | ||
|
|
||
| .why-prose { | ||
| font-size: var(--fs-body); | ||
| line-height: var(--lh-loose); | ||
| color: var(--fg-2); | ||
| } | ||
|
|
||
| .why-prose h2 { | ||
| font-size: var(--fs-h4); | ||
| font-weight: var(--weight-bold); | ||
| .page-h1 { | ||
| font-family: var(--font-display); | ||
| font-weight: 800; | ||
| font-size: clamp(30px, 4vw, 46px); | ||
| letter-spacing: -.025em; | ||
| line-height: 1.1; | ||
| color: var(--fg-1); | ||
| margin: var(--space-12) 0 var(--space-4) 0; | ||
| margin: 0 0 16px; | ||
| } | ||
|
|
||
| .why-prose h2:first-child { | ||
| margin-top: 0; | ||
| } | ||
|
|
||
| .why-prose p { | ||
| margin: 0 0 var(--space-4) 0; | ||
| max-width: 70ch; | ||
| .page-lead { | ||
| font-size: clamp(16px, 1.2vw, 18px); | ||
| color: var(--fg-2); | ||
| line-height: 1.6; | ||
| max-width: 520px; | ||
| margin: 0; | ||
| } | ||
|
|
||
| .why-prose code { | ||
| .page-lead code { | ||
| font-family: var(--font-mono); | ||
| font-size: 13px; | ||
| background: var(--bg-alt); | ||
| border: 1px solid var(--border); | ||
| padding: 2px 6px; | ||
| border-radius: var(--radius-sm); | ||
| color: var(--accent); | ||
| font-size: .9em; | ||
| background: var(--panel-2); | ||
| border: 1px solid var(--hair); | ||
| border-radius: 5px; | ||
| padding: 1px 5px; | ||
| color: var(--fg-1); | ||
| } | ||
|
|
||
| .why-cta-block { | ||
| margin-top: var(--space-16); | ||
| padding-top: var(--space-12); | ||
| border-top: 1px solid var(--border); | ||
| margin-top: 48px; | ||
| padding-top: 32px; | ||
| border-top: 1px solid var(--hair); | ||
| } | ||
|
|
||
| .why-cta-block h2 { | ||
| font-size: var(--fs-h3); | ||
| font-weight: var(--weight-bold); | ||
| font-family: var(--font-display); | ||
| font-size: clamp(20px, 2vw, 26px); | ||
| font-weight: 700; | ||
| color: var(--fg-1); | ||
| margin: 0 0 var(--space-3) 0; | ||
| margin: 0 0 8px; | ||
| } | ||
|
|
||
| .why-cta-block p { | ||
| font-size: var(--fs-body); | ||
| .why-cta-block > p { | ||
| font-size: 16px; | ||
| color: var(--fg-2); | ||
| margin: 0 0 var(--space-6) 0; | ||
| margin: 0 0 20px; | ||
| } | ||
|
|
||
| .why-cta-buttons { | ||
| .why-cta-row { | ||
| display: flex; | ||
| gap: var(--space-4); | ||
| gap: 12px; | ||
| flex-wrap: wrap; | ||
| } | ||
|
|
||
| @media (max-width: 768px) { | ||
| .why-hero { padding: var(--space-16) var(--gutter); } | ||
| .why-h1 { font-size: var(--fs-h3); } | ||
| .why-cta-buttons { flex-direction: column; } | ||
| .btn-primary { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| background: var(--c-brand-blue); | ||
| color: #fff; | ||
| padding: 10px 22px; | ||
| border-radius: var(--radius-pill); | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| text-decoration: none; | ||
| transition: background var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .btn-primary:hover { background: #1857D6; } | ||
|
|
||
| .btn-ghost { | ||
| display: inline-flex; | ||
| align-items: center; | ||
| border: 1px solid var(--hair); | ||
| color: var(--fg-2); | ||
| padding: 10px 22px; | ||
| border-radius: var(--radius-pill); | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| text-decoration: none; | ||
| transition: border-color var(--dur) var(--ease-out), color var(--dur) var(--ease-out); | ||
| } | ||
|
|
||
| .btn-ghost:hover { border-color: var(--accent); color: var(--accent); } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift
Extract duplicated editorial styles to a shared location.
The .eyebrow, .page-h1, .page-lead, .page-lead code, .btn-primary, and .btn-ghost styles (lines 120-213) are duplicated almost identically in getting-started.astro (lines 105-233). This violates the DRY principle and creates a maintenance burden — any change must be synchronised across multiple files.
Consider extracting these shared editorial page styles to either:
- global.css (alongside the other editorial classes), or
- A new shared stylesheet like
editorial-shared.css.
This refactor would centralise ~90 lines of duplicated CSS and ensure consistency across all editorial pages (getting-started, why, onboarding, references, glossary).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/src/pages/why.astro` around lines 120 - 213, Duplicate editorial
styles (.eyebrow, .page-h1, .page-lead, .page-lead code, .btn-primary,
.btn-ghost) should be extracted into a single shared stylesheet and imported by
pages instead of duplicated; create a new editorial-shared.css (or add to
global.css), move the block of CSS for those selectors into it, keep the exact
variable references and rules intact, then remove the duplicated blocks from
why.astro and getting-started.astro and add an import/link to the shared
stylesheet in each page (or ensure global.css includes it) so both pages use the
single source of truth.
- Move shared editorial typography (eyebrow, page-h1, page-lead, btn-pill) to global.css; remove duplicated styles from all editorial page <style> blocks - 404: add description prop; use global btn-primary btn-pill (no local .btn-home) - getting-started, onboarding: fix heading hierarchy — step/chapter titles now use h2 instead of h3 (WCAG 2.2 SC 1.3.1); onboarding chapters use <section> - glossary/[term]: simplify getStaticPaths to use Astro.params.term directly; replace inline styles with CSS classes (term-page, term-title, term-related-heading); promote "Why it matters" / "Related terms" labels from <p> to <h2> for screen-reader heading navigation; add .term-chip CSS class (removes inline style on related chips); add :focus-visible on .crumb a - glossary/index: word-boundary truncation for definition previews; add :focus-visible on .gloss-link - references: change WapuuHero page prop from "why" to "references"; add "references" entry to WAPUU_MAP; add sr-only "opens in new tab" cue on external links - global.css: update .ob-step-body selector from h3 → h2; add .sr-only accessibility utility class - CHANGELOG.md: add Phase 12 entry (fixes validate CI) https://claude.ai/code/session_01TYHRXeGfXMwq5VqsayUVqL
🔍 Reviewer Summary for PR #882CI Status: ❌ Recommendations
|
Linked issues
Closes #881
Changelog
Added
.editorial-hero,.editorial-hero-inner,.editorial-hero-text,.prose-bodyCSS classes added toglobal.css.ob-steps,.ob-step,.ob-step-num,.ob-step-bodyCSS added toglobal.cssonboarding.astrorebuilt as a full 6-chapter narrative page (was previously a redirect to/getting-started/)getting-started.astrorebuilt withBaseLayout+WapuuHero+ numbered step layoutwhy.astrorebuilt withBaseLayout+WapuuHero+ editorial hero (removes hardcoded dark gradient)references.astrorebuilt withBaseLayout+WapuuHero+REFERENCE_GROUPSlink listglossary/index.astrorebuilt withBaseLayout+WapuuHero+ group-based term listglossary/[term].astrorebuilt withBaseLayout+.wrap-prose+ related-terms chips404.astrorebuilt to spec:wapuu-astropuu.pngat 150px centred, back-to-home CTAChanged
AwesomeGithubLayouttoBaseLayoutwithWapuuHeroin heroRisk Assessment
Risk Level: Low
Potential Impact: UI-only changes to editorial/reference pages. No data layer, no auth, no shared state touched. Build produces identical page count (333 pages, 0 errors).
Mitigation Steps:
BaseLayout,WapuuHero, and token CSS — no new dependenciesglobal.cssare purely additive (new class names, no overrides)How to Test
Prerequisites
npm ciinwebsite/Test Steps
npm run buildinwebsite/— expect 333 pages, 0 errorsnpm run previewand visit each route:/getting-started— prose container, WapuuHero, 6 numbered steps/why— editorial hero with WapuuHero, no hardcoded dark gradient/onboarding— 6 numbered chapters with accent step circles/references— grouped file list with external links/glossary— grouped term list, WapuuHero present/glossary/control-plane— term definition, "Why it matters" block, related chips/404(any bad route) — wapuu at 150px centred, back-to-home CTAExpected Results
.editorial-hero-innerflex layout (text left, wapuu right).wrap(1320px) container with 820px inner bodyEdge Cases to Verify
/onboardingno longer redirects — renders full 6-chapter pageChecklist (Global DoD / PR)
aria-hidden="true"on all wapuu images per spec)set:htmlused only for known-safe inline stringsPhase 12 summary
5 editorial pages rebuilt with
.wrap-prose(820px) container,BaseLayout,WapuuHero, and.editorial-heropattern from the Phase 12 spec. Replaces allAwesomeGithubLayoutusage on editorial pages. Onboarding page converted from redirect to full 6-chapter narrative. 404 page updated to spec (wapuu at 150px, centred).https://claude.ai/code/session_01TYHRXeGfXMwq5VqsayUVqL