Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/components/BlogTestCTA.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* Copy uses Cercol product vocabulary only (never academic instrument names).
*/
import { Link } from 'react-router-dom'
import { Card, SectionLabel } from './ui'
import { Card, SectionLabel, DisplayHeading } from './ui'
import { trackEvent } from '../lib/api'

// Localized copy. es/fr/de/da are flagged for human review in the PR.
Expand Down Expand Up @@ -59,12 +59,12 @@ export default function BlogTestCTA({ slug, lang = 'en', category, compact = fal
return (
<Card accent="blue" className={`max-w-3xl ${compact ? 'p-4 my-8' : 'p-6 mt-12'}`}>
{!compact && <SectionLabel color="blue" className="mb-2">Cèrcol</SectionLabel>}
<p
<DisplayHeading
as="p"
className={`font-bold text-gray-900 ${compact ? 'text-base mb-2' : 'text-xl mb-1'}`}
style={{ fontFamily: 'var(--mm-font-display)' }}
>
{heading}
</p>
</DisplayHeading>
{!compact && <p className="text-sm text-gray-500 leading-relaxed mb-4">{c.p}</p>}
<Link
to="/new-moon"
Expand Down
19 changes: 19 additions & 0 deletions src/components/report/MethodologyNote.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* MethodologyNote — the small muted disclaimer footnote rendered at the bottom
* of every report surface (Full Moon, First Quarter, New Moon, Last Quarter).
*
* Centralizes the shared card string so all report pages render an identical
* note instead of repeating the className and inline color in each file.
*/
import { colors } from '../../design/tokens'

export default function MethodologyNote({ children }) {
return (
<div
className="bg-gray-100 rounded px-5 py-4 text-xs leading-relaxed"
style={{ color: colors.textMuted }}
>
{children}
</div>
)
}
1 change: 1 addition & 0 deletions src/components/report/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export { default as RoleCard } from './RoleCard'
export { default as RadarDataCard } from './RadarDataCard'
export { RoleComparisonView } from './RoleComparisonView'
export { SurprisesPanel } from './SurprisesPanel'
export { default as MethodologyNote } from './MethodologyNote'
17 changes: 17 additions & 0 deletions src/components/ui/DisplayHeading.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* DisplayHeading — a heading rendered in the mm-design display family
* (Playfair Display via --mm-font-display).
*
* Centralizes the repeated `style={{ fontFamily: 'var(--mm-font-display)' }}`
* so call sites no longer carry the inline font style. Output is identical to
* the previous markup: the same tag, the same className, the same font family.
*
* Pass the element via `as` (defaults to h2) and styling via className.
*/
export default function DisplayHeading({ as: Tag = 'h2', className = '', children, ...rest }) {
return (
<Tag className={className} style={{ fontFamily: 'var(--mm-font-display)' }} {...rest}>
{children}
</Tag>
)
}
1 change: 1 addition & 0 deletions src/components/ui/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export { default as Button } from './Button'
export { default as Card } from './Card'
export { default as Badge } from './Badge'
export { default as SectionLabel } from './SectionLabel'
export { default as DisplayHeading } from './DisplayHeading'
13 changes: 13 additions & 0 deletions src/design/gradients.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Shared gradient constants.
*
* mm-design has no token for the dark-blue gradient stop (#00297a), so the
* brand-blue gradient lives here in ONE place rather than being copy-pasted
* across pages. The light stop uses the mm-design blue token; only the dark
* stop is a local literal.
*
* If mm-design later adds a matching dark-blue token, replace the literal
* below and this stays the single source of truth.
*/
export const BRAND_BLUE_GRADIENT =
'linear-gradient(135deg, var(--mm-color-blue) 0%, #00297a 100%)'
21 changes: 8 additions & 13 deletions src/pages/BlogIndexPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
import { Link, useLocation } from 'react-router-dom'
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { SectionLabel } from '../components/ui'
import { SectionLabel, DisplayHeading } from '../components/ui'
import { BRAND_BLUE_GRADIENT } from '../design/gradients'
import { getBlogPosts } from '../lib/api'
import { normalizeUnsplashUrl } from '../utils/unsplash'

Expand Down Expand Up @@ -177,12 +178,9 @@ export default function BlogIndexPage() {
<SectionLabel color="blue" className="mb-3">
{t('blog.label')}
</SectionLabel>
<h1
className="text-3xl font-bold text-gray-900 mb-3"
style={{ fontFamily: 'var(--mm-font-display)' }}
>
<DisplayHeading as="h1" className="text-3xl font-bold text-gray-900 mb-3">
{t('blog.heading')}
</h1>
</DisplayHeading>
<p className="text-sm text-gray-600 leading-relaxed mb-6 max-w-xl">
{t('blog.subtitle')}
</p>
Expand Down Expand Up @@ -307,22 +305,19 @@ export default function BlogIndexPage() {
) : (
<div
className="w-full h-full"
style={{
background:
'linear-gradient(135deg, var(--mm-color-blue) 0%, #00297a 100%)',
}}
style={{ background: BRAND_BLUE_GRADIENT }}
/>
)}
</div>

{/* Card body */}
<div className="px-5 py-4 flex flex-col flex-1">
<h2
<DisplayHeading
as="h2"
className="text-sm font-bold text-gray-900 mb-2 leading-snug group-hover:text-[var(--mm-color-blue)] transition-colors"
style={{ fontFamily: 'var(--mm-font-display)' }}
>
{localise(post.title)}
</h2>
</DisplayHeading>
{desc && (
<p className="text-xs text-gray-600 leading-relaxed line-clamp-3 mb-3">
{desc}
Expand Down
9 changes: 3 additions & 6 deletions src/pages/FaqPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Uses HTML details/summary for accessible accordion without JS state.
*/
import { useTranslation } from 'react-i18next'
import { SectionLabel } from '../components/ui'
import { SectionLabel, DisplayHeading } from '../components/ui'
import { usePageMeta } from '../hooks/usePageMeta'

const SECTIONS = [
Expand Down Expand Up @@ -71,12 +71,9 @@ export default function FaqPage() {
<SectionLabel color="blue" className="mb-3">
{t('faq.label')}
</SectionLabel>
<h1
className="text-3xl font-bold text-gray-900 mb-8"
style={{ fontFamily: 'var(--mm-font-display)' }}
>
<DisplayHeading as="h1" className="text-3xl font-bold text-gray-900 mb-8">
{t('faq.heading')}
</h1>
</DisplayHeading>

{SECTIONS.map(({ labelKey, keys }) => (
<FaqSection key={labelKey} label={t(labelKey)}>
Expand Down
6 changes: 2 additions & 4 deletions src/pages/FirstQuarterResultsPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { useAuth } from '../context/AuthContext'
import { colors } from '../design/tokens'
import RoleProbabilityBars from '../components/RoleProbabilityBars'
import { Card, Button, Badge, SectionLabel } from '../components/ui'
import { DimensionRow, FacetAccordion, ReportPageHeader, RoleCard, RadarDataCard } from '../components/report'
import { DimensionRow, FacetAccordion, ReportPageHeader, RoleCard, RadarDataCard, MethodologyNote } from '../components/report'
import InstrumentNudge from '../components/InstrumentNudge'


Expand Down Expand Up @@ -173,9 +173,7 @@ export default function FirstQuarterResultsPage() {
</div>

{/* Disclaimer */}
<div className="bg-gray-100 rounded px-5 py-4 text-xs leading-relaxed" style={{ color: colors.textMuted }}>
{t('fqResults.disclaimer')}
</div>
<MethodologyNote>{t('fqResults.disclaimer')}</MethodologyNote>

</div>
</main>
Expand Down
6 changes: 2 additions & 4 deletions src/pages/FullMoonResultsPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { useAuth } from '../context/AuthContext'
import { colors } from '../design/tokens'
import RoleProbabilityBars from '../components/RoleProbabilityBars'
import { Card, Button, Badge, SectionLabel } from '../components/ui'
import { DimensionRow, FacetAccordion, ReportPageHeader, RoleCard, RadarDataCard, RoleComparisonView, SurprisesPanel } from '../components/report'
import { DimensionRow, FacetAccordion, ReportPageHeader, RoleCard, RadarDataCard, RoleComparisonView, SurprisesPanel, MethodologyNote } from '../components/report'

const MIN_WITNESSES_FOR_REPORT = 2

Expand Down Expand Up @@ -384,9 +384,7 @@ export default function FullMoonResultsPage() {
</div>

{/* Disclaimer */}
<div className="bg-gray-100 rounded px-5 py-4 text-xs leading-relaxed" style={{ color: colors.textMuted }}>
{t('fmResults.disclaimer')}
</div>
<MethodologyNote>{t('fmResults.disclaimer')}</MethodologyNote>

</div>
</main>
Expand Down
6 changes: 2 additions & 4 deletions src/pages/LastQuarterPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
zscoresToRaw,
} from '../utils/team-narrative'
import { RoleIcon, LastQuarterIcon, DimensionIcon, ChevronRightIcon } from '../components/MoonIcons'
import { DimensionRow, ReportPageHeader, RadarDataCard } from '../components/report'
import { DimensionRow, ReportPageHeader, RadarDataCard, MethodologyNote } from '../components/report'
import RadarChart from '../components/RadarChart'
import { Card, SectionLabel, Button } from '../components/ui'
import { colors, ROLE_COLORS, DOMAIN_ICON_CLASSES, BALANCE_COLORS } from '../design/tokens'
Expand Down Expand Up @@ -516,9 +516,7 @@ export default function LastQuarterPage() {
</div>

{/* Disclaimer */}
<div className="bg-gray-100 rounded px-5 py-4 text-xs leading-relaxed" style={{ color: colors.textMuted }}>
{t('fmResults.disclaimer')}
</div>
<MethodologyNote>{t('fmResults.disclaimer')}</MethodologyNote>

</div>
</main>
Expand Down
6 changes: 2 additions & 4 deletions src/pages/NewMoonResultsPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { useAuth } from '../context/AuthContext'
import { colors } from '../design/tokens'
import { Card, Button, SectionLabel } from '../components/ui'
import { NewMoonIcon } from '../components/MoonIcons'
import { DimensionRow, ReportPageHeader, RadarDataCard } from '../components/report'
import { DimensionRow, ReportPageHeader, RadarDataCard, MethodologyNote } from '../components/report'
import InstrumentNudge from '../components/InstrumentNudge'


Expand Down Expand Up @@ -128,9 +128,7 @@ export default function NewMoonResultsPage() {
</div>

{/* Disclaimer */}
<div className="bg-gray-100 rounded px-5 py-4 text-xs leading-relaxed" style={{ color: colors.textMuted }}>
{t('newMoonResults.disclaimer')}
</div>
<MethodologyNote>{t('newMoonResults.disclaimer')}</MethodologyNote>

</div>
</main>
Expand Down
4 changes: 2 additions & 2 deletions src/pages/RolesPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const ROLES = [
{ key: 'R12', accent: 'text-gray-600', bg: 'bg-gray-50' }, // Badger B- V-
]

function RoleCard({ roleKey, accent, bg, t }) {
function RoleSummaryCard({ roleKey, accent, bg, t }) {
const name = t(`roles.${roleKey}.name`)
const ca = t(`roles.${roleKey}.ca`)
const essence = t(`roles.${roleKey}.essence`)
Expand Down Expand Up @@ -121,7 +121,7 @@ export default function RolesPage() {
</h2>
<div className="flex flex-col gap-4">
{ROLES.map(({ key, accent, bg }) => (
<RoleCard key={key} roleKey={key} accent={accent} bg={bg} t={t} />
<RoleSummaryCard key={key} roleKey={key} accent={accent} bg={bg} t={t} />
))}
</div>
</section>
Expand Down
26 changes: 10 additions & 16 deletions src/pages/blog/BlogArticlePage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { marked } from 'marked'
import { getBlogPost, getBlogPosts, trackBlogView } from '../../lib/api'
import { normalizeUnsplashUrl } from '../../utils/unsplash'
import BlogTestCTA from '../../components/BlogTestCTA'
import { DisplayHeading } from '../../components/ui'
import { BRAND_BLUE_GRADIENT } from '../../design/gradients'

// Configure marked with custom renderers once at module load time
marked.use({
Expand Down Expand Up @@ -533,21 +535,16 @@ export default function BlogArticlePage() {
) : (
<div
className="absolute inset-0"
style={{
background: 'linear-gradient(135deg, var(--mm-color-blue) 0%, #00297a 100%)',
}}
style={{ background: BRAND_BLUE_GRADIENT }}
/>
)}
</div>

{/* Article header */}
<header className="mb-8 max-w-3xl">
<h1
className="text-3xl font-bold text-gray-900 mb-3 leading-tight"
style={{ fontFamily: 'var(--mm-font-display)' }}
>
<DisplayHeading as="h1" className="text-3xl font-bold text-gray-900 mb-3 leading-tight">
{title}
</h1>
</DisplayHeading>
{description && (
<p className="text-base text-gray-500 mb-3 leading-relaxed">{description}</p>
)}
Expand Down Expand Up @@ -688,12 +685,9 @@ export default function BlogArticlePage() {
{/* Related articles */}
{relatedPosts.length > 0 && (
<section className="mt-16 pt-10 border-t max-w-3xl">
<h2
className="text-xl font-bold text-gray-900 mb-6"
style={{ fontFamily: 'var(--mm-font-display)' }}
>
<DisplayHeading as="h2" className="text-xl font-bold text-gray-900 mb-6">
{RELATED_LABEL[urlLang] || RELATED_LABEL.en}
</h2>
</DisplayHeading>
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-4">
{relatedPosts.map(p => {
const relatedHref = urlLang === 'en' ? `/blog/${p.slug}` : `/${urlLang}/blog/${p.slug}`
Expand All @@ -703,12 +697,12 @@ export default function BlogArticlePage() {
to={relatedHref}
className="group block rounded-xl border p-4 hover:shadow-md transition-shadow bg-white"
>
<h3
<DisplayHeading
as="h3"
className="text-sm font-semibold text-gray-900 mb-1 group-hover:underline leading-snug"
style={{ fontFamily: 'var(--mm-font-display)' }}
>
{localise(p.title, urlLang)}
</h3>
</DisplayHeading>
{localise(p.description, urlLang) && (
<p className="text-xs text-gray-500 leading-relaxed line-clamp-2">
{localise(p.description, urlLang)}
Expand Down
Loading