fleet-memory/hindsight-docs/src/pages/integrations/index.module.css
Nicolò Boschi 80b1badf74
feat(docs): Integrations Hub + unified page hero (#620)
* fix(security): address all Dependabot vulnerability alerts

Python (uv.lock, pyproject.toml):
- authlib 1.6.6 → 1.6.9 (JWS header injection, OIDC hash binding, Bleichenbacher padding oracle)
- pyasn1 0.6.2 → 0.6.3 (unbounded recursion DoS)
- pyjwt 2.10.1 → 2.12.1 (unknown crit header extensions - also in integration-tests and crewai)
- orjson 3.11.4 → 3.11.7 (deeply nested JSON recursion DoS)
- tornado 6.5.2 → 6.5.5 (multipart DoS, incomplete cookie validation)

npm (package.json, package-lock.json):
- next ^16.1.6 → ^16.1.7 (HTTP smuggling, CSRF bypass, cache DoS, null origin bypass)
- fast-xml-parser override updated to >=5.5.6 (numeric entity expansion bypass)
- undici override added >=7.24.0 (WebSocket overflow, smuggling, CRLF injection, DoS)
- flatted override added >=3.4.0 (unbounded recursion DoS)
- svgo override added >=3.3.3 (DOCTYPE entity expansion DoS)
- dompurify override added >=3.3.2 (XSS vulnerability)

* feat(docs): add Integrations Hub and unified page hero

- Add /integrations page with search, type filter, and card grid
- Integrations defined in a single JSON file (src/data/integrations.json)
  supporting official and community entries with icon, author, and link
- Scrolling integrations banner moved from global navbar to /integrations only
- Remove IntegrationsGrid component; replace all usages with link to hub
- Add PageHero component with full-bleed gradient background, shared across
  Cookbook, FAQ, Best Practices, Changelog, and Blog index pages
- Remove FAQ from top navbar (already in Resources dropdown)
- Move integration changelogs table to bottom of changelog page
2026-03-19 20:29:55 +01:00

408 lines
10 KiB
CSS

/* ── Full-width hero ─────────────────────────────────────────────────────── */
.heroSection {
width: 100%;
padding: 5rem 1.5rem 4rem;
text-align: center;
background: radial-gradient(ellipse 80% 60% at 50% 0%, rgba(0, 116, 217, 0.12) 0%, transparent 70%),
var(--ifm-background-color);
border-bottom: 1px solid var(--ifm-color-emphasis-200);
}
[data-theme='dark'] .heroSection {
background: radial-gradient(ellipse 80% 60% at 50% 0%, rgba(0, 116, 217, 0.18) 0%, transparent 70%),
var(--ifm-background-color);
border-bottom-color: rgba(255, 255, 255, 0.07);
}
.heroTitle {
font-size: 3.2rem;
font-weight: 800;
background: linear-gradient(135deg, #0074d9, #009296);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
letter-spacing: -0.03em;
line-height: 1.1;
margin-bottom: 0.75rem;
}
.heroSubtitle {
font-size: 1.05rem;
color: var(--ifm-color-emphasis-600);
max-width: 500px;
margin: 0 auto 2.25rem;
line-height: 1.7;
}
/* ── Search ──────────────────────────────────────────────────────────────── */
.searchWrapper {
position: relative;
max-width: 640px;
margin: 0 auto;
}
.searchInput {
width: 100%;
box-sizing: border-box;
padding: 1.05rem 3.5rem 1.05rem 1.5rem;
border-radius: 14px;
border: 2px solid var(--ifm-color-emphasis-300);
background: var(--ifm-background-surface-color);
color: var(--ifm-font-color-base);
font-size: 1.1rem;
font-family: inherit;
outline: none;
transition: border-color 0.15s ease, box-shadow 0.15s ease;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
}
.searchInput::placeholder {
color: var(--ifm-color-emphasis-400);
}
.searchInput:focus {
border-color: #0074d9;
box-shadow: 0 0 0 4px rgba(0, 116, 217, 0.15), 0 4px 24px rgba(0, 0, 0, 0.08);
}
[data-theme='dark'] .searchInput {
background: #242428;
border-color: rgba(255, 255, 255, 0.15);
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4);
}
[data-theme='dark'] .searchInput:focus {
border-color: #4da6ff;
box-shadow: 0 0 0 4px rgba(77, 166, 255, 0.18), 0 4px 24px rgba(0, 0, 0, 0.4);
}
.searchClear {
position: absolute;
right: 1rem;
top: 50%;
transform: translateY(-50%);
background: var(--ifm-color-emphasis-200);
border: none;
color: var(--ifm-color-emphasis-600);
cursor: pointer;
font-size: 1rem;
line-height: 1;
width: 24px;
height: 24px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.1s;
}
.searchClear:hover {
background: var(--ifm-color-emphasis-300);
}
/* ── Hero stats ──────────────────────────────────────────────────────────── */
.heroStats {
display: inline-flex;
align-items: center;
gap: 0.6rem;
font-size: 0.82rem;
color: var(--ifm-color-emphasis-500);
margin-top: 1.25rem;
}
.stat strong {
color: var(--ifm-color-emphasis-800);
}
[data-theme='dark'] .stat strong {
color: var(--ifm-color-emphasis-700);
}
.statDivider {
color: var(--ifm-color-emphasis-300);
}
/* ── Page container ──────────────────────────────────────────────────────── */
.page {
max-width: 1200px;
margin: 0 auto;
padding: 2.5rem 1.5rem 5rem;
}
/* ── Toolbar (filters + count) ───────────────────────────────────────────── */
.toolbar {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1.75rem;
flex-wrap: wrap;
gap: 0.75rem;
}
.filterGroup {
display: flex;
align-items: center;
gap: 0.4rem;
}
.filterPill {
display: inline-flex;
align-items: center;
font-size: 0.82rem;
font-weight: 500;
padding: 0.3rem 0.85rem;
border-radius: 999px;
border: 1px solid var(--ifm-color-emphasis-300);
background: transparent;
color: var(--ifm-color-emphasis-700);
cursor: pointer;
transition: all 0.15s ease;
font-family: inherit;
}
.filterPill:hover {
border-color: var(--ifm-color-primary);
color: var(--ifm-color-primary);
}
.filterPillActive {
background: var(--ifm-color-primary);
border-color: var(--ifm-color-primary);
color: #fff !important;
}
[data-theme='dark'] .filterPill {
border-color: rgba(255, 255, 255, 0.15);
color: var(--ifm-color-emphasis-600);
}
/* ── Result count ────────────────────────────────────────────────────────── */
.resultCount {
font-size: 0.8rem;
color: var(--ifm-color-emphasis-400);
margin: 0;
}
/* ── Grid ────────────────────────────────────────────────────────────────── */
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.25rem;
margin-bottom: 4rem;
}
@media (max-width: 996px) {
.grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
.grid { grid-template-columns: 1fr; }
.heroTitle { font-size: 2.2rem; }
}
/* ── Card ────────────────────────────────────────────────────────────────── */
.card {
display: flex;
flex-direction: column;
border-radius: 12px;
border: 1px solid var(--ifm-color-emphasis-200);
background: var(--ifm-background-surface-color);
text-decoration: none !important;
color: inherit;
transition: box-shadow 0.2s ease, transform 0.2s ease;
overflow: hidden;
}
[data-theme='dark'] .card {
background: #1c1c1e;
border-color: rgba(255, 255, 255, 0.07);
}
.card:hover {
transform: translateY(-2px);
box-shadow: 0 6px 24px rgba(0, 116, 217, 0.12);
text-decoration: none !important;
color: inherit;
}
.cardHeader {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem 1.1rem 0;
}
.cardIcon {
width: 36px;
height: 36px;
object-fit: contain;
flex-shrink: 0;
}
.typeBadge {
font-size: 0.63rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
padding: 0.15rem 0.5rem;
border-radius: 999px;
}
.typeBadgeOfficial {
background: rgba(0, 116, 217, 0.12);
color: #0074d9;
}
[data-theme='dark'] .typeBadgeOfficial {
background: rgba(0, 116, 217, 0.2);
color: #4da6ff;
}
.typeBadgeCommunity {
background: rgba(0, 146, 150, 0.12);
color: #009296;
}
[data-theme='dark'] .typeBadgeCommunity {
background: rgba(0, 146, 150, 0.2);
color: #00bcc0;
}
.cardBody {
flex: 1;
padding: 0.85rem 1.1rem 0.75rem;
}
.cardTitle {
font-size: 1rem;
font-weight: 700;
margin: 0 0 0.4rem;
color: var(--ifm-heading-color);
letter-spacing: -0.01em;
border-bottom: none !important;
border-image: none !important;
}
.cardDescription {
font-size: 0.82rem;
color: var(--ifm-color-emphasis-600);
line-height: 1.6;
margin: 0;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.cardFooter {
display: flex;
align-items: center;
padding: 0.65rem 1.1rem 0.9rem;
margin-top: 0.25rem;
border-top: 1px solid var(--ifm-color-emphasis-100);
}
[data-theme='dark'] .cardFooter {
border-top-color: rgba(255, 255, 255, 0.06);
}
.byLine {
display: inline-flex;
align-items: center;
gap: 0.5rem;
font-size: 0.78rem;
font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', Monaco, Consolas, monospace;
color: var(--ifm-color-emphasis-600);
}
.authorIcon {
width: 22px;
height: 22px;
border-radius: 50%;
object-fit: cover;
flex-shrink: 0;
border: 1px solid var(--ifm-color-emphasis-200);
}
[data-theme='dark'] .authorIcon {
border-color: rgba(255, 255, 255, 0.1);
}
.authorName {
font-weight: 500;
}
/* ── Empty state ─────────────────────────────────────────────────────────── */
.empty {
text-align: center;
padding: 4rem 2rem;
color: var(--ifm-color-emphasis-500);
}
.resetButton {
margin-top: 1rem;
padding: 0.4rem 1rem;
border-radius: 6px;
border: 1px solid var(--ifm-color-primary);
background: transparent;
color: var(--ifm-color-primary);
font-size: 0.85rem;
font-family: inherit;
cursor: pointer;
transition: all 0.15s ease;
}
.resetButton:hover {
background: var(--ifm-color-primary);
color: #fff;
}
/* ── Submit banner ───────────────────────────────────────────────────────── */
.submitBanner {
border-radius: 14px;
border: 1px solid var(--ifm-color-emphasis-200);
background: linear-gradient(135deg, rgba(0, 116, 217, 0.06), rgba(0, 146, 150, 0.06));
padding: 2.5rem 2rem;
text-align: center;
}
[data-theme='dark'] .submitBanner {
border-color: rgba(255, 255, 255, 0.08);
background: linear-gradient(135deg, rgba(0, 116, 217, 0.1), rgba(0, 146, 150, 0.1));
}
.submitBannerContent {
max-width: 480px;
margin: 0 auto;
}
.submitBannerTitle {
font-size: 1.3rem;
font-weight: 700;
margin-bottom: 0.5rem;
}
.submitBannerText {
font-size: 0.9rem;
color: var(--ifm-color-emphasis-600);
margin-bottom: 1.25rem;
line-height: 1.6;
}
.submitButton {
display: inline-block;
padding: 0.55rem 1.4rem;
border-radius: 8px;
background: linear-gradient(135deg, #0074d9, #009296);
color: #fff !important;
font-size: 0.9rem;
font-weight: 600;
text-decoration: none !important;
transition: opacity 0.15s ease, transform 0.15s ease;
}
.submitButton:hover {
opacity: 0.9;
transform: translateY(-1px);
color: #fff !important;
}