From e0a98492c9d11f1f369fa49d3e3aa84917ab91af Mon Sep 17 00:00:00 2001 From: "nicolas T." Date: Thu, 5 Mar 2026 12:16:27 +0100 Subject: [PATCH 1/6] Apply brand identity (Cloudlandscape visual kit) - Add CSS design tokens: sky-deep, sky-mid, aurora, horizon, mist, slate, cloud-white - Switch body font to Cormorant Garamond (display) + DM Mono (mono) - Add Google Fonts preconnect + stylesheet link in base.html - Add inline SVG favicon (dark cloud icon, aurora stroke) - Replace nav text logo with SVG wordmark logo - Dark theme throughout: #0B1D2E background, #EEF4F9 text - Aurora (#7EC8C8) accent on CTAs, links, badges, focus rings - Restyle all components: cards, buttons, badges, filters, comparison bar - Maintain WCAG/RGAA compliance: prefers-reduced-motion, focus-visible Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- static/style.css | 559 ++++++++++++++++++++++++++++++-------------- templates/base.html | 18 +- 2 files changed, 398 insertions(+), 179 deletions(-) diff --git a/static/style.css b/static/style.css index 5c74bca..db727f1 100644 --- a/static/style.css +++ b/static/style.css @@ -1,3 +1,24 @@ +/* ─── DESIGN TOKENS ───────────────────────────────────────── */ +:root { + --sky-deep: #0B1D2E; + --sky-mid: #1A3A5C; + --sky-pale: #4A7FA5; + --cloud-white: #EEF4F9; + --horizon: #B8CDD8; + --aurora: #7EC8C8; + --mist: #D9E8EF; + --slate: #3D5A6E; + --contrast: #061420; + + --font-display: 'Cormorant Garamond', Georgia, serif; + --font-mono: 'DM Mono', 'Courier New', monospace; + + --space-xs: 0.5rem; + --space-sm: 1rem; + --space-md: 2rem; + --space-lg: 4rem; +} + /* CSS Reset and Base Styles */ * { margin: 0; @@ -7,9 +28,11 @@ /* Prevent layout shift - reserve space for web fonts */ body { - font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; - line-height: 1.6; - color: #1a1a1a; + font-family: var(--font-display); + font-weight: 300; + line-height: 1.7; + color: var(--cloud-white); + background: var(--sky-deep); max-width: 1200px; margin: 0 auto; padding: 1rem; @@ -24,8 +47,9 @@ img { /* Navigation */ nav { - background: #2c3e50; - padding: 1rem; + background: var(--sky-mid); + border-bottom: 1px solid var(--slate); + padding: 0.75rem 1.5rem; margin: -1rem -1rem 2rem -1rem; display: flex; align-items: center; @@ -33,27 +57,47 @@ nav { gap: 0.5rem; } +.nav-logo { + display: flex; + align-items: center; + margin-right: 1rem; + text-decoration: none; +} + nav a { - color: white; + color: var(--horizon); text-decoration: none; margin-right: 1.5rem; - font-weight: 500; + font-family: var(--font-mono); + font-size: 0.8rem; + letter-spacing: 0.15em; + text-transform: uppercase; + transition: color 0.2s; } nav a:hover { - text-decoration: underline; + color: var(--aurora); + text-decoration: none; } /* Typography */ h1 { - font-size: 2rem; + font-family: var(--font-display); + font-size: clamp(1.8rem, 4vw, 3rem); + font-weight: 300; + letter-spacing: 0.04em; margin-bottom: 1rem; - color: #2c3e50; + color: var(--cloud-white); } h2 { - font-size: 1.5rem; - margin-bottom: 0.5rem; + font-family: var(--font-mono); + font-size: 0.75rem; + font-weight: 400; + letter-spacing: 0.25em; + text-transform: uppercase; + color: var(--horizon); + margin-bottom: var(--space-sm); } /* Provider Grid */ @@ -65,105 +109,175 @@ h2 { } .provider-card { - border: 1px solid #ddd; - border-radius: 8px; + border: 1px solid var(--slate); + border-radius: 4px; padding: 1.5rem; - background: white; - box-shadow: 0 2px 4px rgba(0,0,0,0.1); - transition: transform 0.2s, box-shadow 0.2s; + background: var(--sky-mid); + transition: transform 0.25s ease, box-shadow 0.25s ease; +} + +@media (prefers-reduced-motion: no-preference) { + .provider-card:hover { + transform: translateY(-3px); + box-shadow: 0 6px 20px rgba(0,0,0,0.3); + } } -.provider-card:hover { - transform: translateY(-2px); - box-shadow: 0 4px 8px rgba(0,0,0,0.15); +.provider-card h2 { + font-family: var(--font-display); + font-size: 1.25rem; + font-weight: 400; + letter-spacing: 0.03em; + text-transform: none; + color: var(--cloud-white); + margin-bottom: 0.5rem; } .provider-card h2 a { - color: #2c3e50; + color: var(--cloud-white); text-decoration: none; } .provider-card h2 a:hover { - color: #3498db; + color: var(--aurora); } .provider-description { margin: 0.5rem 0 1rem 0; - color: #4a4a4a; + color: var(--horizon); + font-size: 0.95rem; } .provider-meta { - font-size: 0.9rem; + font-size: 0.88rem; + color: var(--horizon); } .provider-meta p { margin: 0.5rem 0; } +.provider-meta strong { + color: var(--cloud-white); + font-weight: 400; +} + .provider-card .provider-actions { margin-top: 1rem; padding-top: 1rem; - border-top: 1px solid #ecf0f1; + border-top: 1px solid var(--slate); } .btn-compare-add { width: 100%; padding: 0.6rem 1rem; - background: #3498db; - color: white; - border: none; + background: transparent; + color: var(--aurora); + border: 1px solid var(--aurora); border-radius: 4px; cursor: pointer; - font-size: 0.9rem; - font-weight: 600; - transition: background 0.2s; + font-family: var(--font-mono); + font-size: 0.75rem; + letter-spacing: 0.1em; + text-transform: uppercase; + font-weight: 400; + transition: background 0.2s, color 0.2s; } .btn-compare-add:hover { - background: #2980b9; + background: var(--aurora); + color: var(--contrast); } .btn-compare-add.in-comparison { - background: #27ae60; + background: var(--aurora); + color: var(--contrast); + border-color: var(--aurora); } .btn-compare-add.in-comparison:hover { - background: #229954; + background: var(--sky-pale); + border-color: var(--sky-pale); + color: var(--cloud-white); } .btn-compare-add:disabled { - background: #95a5a6; + background: transparent; + color: var(--slate); + border-color: var(--slate); cursor: not-allowed; } /* Badges */ .badge { display: inline-block; - background: #ecf0f1; - padding: 0.25rem 0.5rem; + background: rgba(255,255,255,0.06); + border: 1px solid var(--slate); + color: var(--horizon); + padding: 0.2rem 0.5rem; border-radius: 4px; - font-size: 0.85rem; + font-family: var(--font-mono); + font-size: 0.72rem; margin-right: 0.25rem; + letter-spacing: 0.05em; } .cert-badge { - background: #27ae60; - color: white; + background: rgba(126,200,200,0.12); + border-color: var(--aurora); + color: var(--aurora); } /* Filters Container */ .filters-container { - background: #f8f9fa; + background: rgba(255,255,255,0.04); + border: 1px solid var(--slate); padding: 1.5rem; - border-radius: 8px; + border-radius: 4px; margin: 2rem 0; } .filters-container h2 { - font-size: 1.3rem; + font-size: 0.7rem; margin-bottom: 1rem; } +.search-container { + margin-bottom: 1.5rem; +} + +.search-container label { + display: block; + font-family: var(--font-mono); + font-size: 0.7rem; + letter-spacing: 0.2em; + text-transform: uppercase; + color: var(--horizon); + margin-bottom: 0.5rem; +} + +.search-input { + width: 100%; + padding: 0.6rem 1rem; + background: var(--sky-deep); + border: 1px solid var(--slate); + border-radius: 4px; + color: var(--cloud-white); + font-family: var(--font-display); + font-size: 1rem; + font-weight: 300; + outline: none; + transition: border-color 0.2s; +} + +.search-input:focus { + border-color: var(--aurora); +} + +.search-input::placeholder { + color: var(--slate); +} + .filter-group { margin-bottom: 1.5rem; border: none; @@ -171,54 +285,66 @@ h2 { } .filter-group legend { - font-size: 1.1rem; - font-weight: 600; + font-family: var(--font-mono); + font-size: 0.68rem; + font-weight: 400; + letter-spacing: 0.2em; + text-transform: uppercase; margin-bottom: 0.5rem; - color: #2c3e50; + color: var(--horizon); padding: 0; } - color: #2c3e50; -} .filter-group label { display: block; margin: 0.5rem 0; cursor: pointer; + color: var(--cloud-white); + font-size: 0.95rem; } .filter-group label input[type="checkbox"] { margin-right: 0.5rem; + accent-color: var(--aurora); } .filter-checkbox:checked + label, .filter-group label:has(input:checked) { - font-weight: 600; + font-weight: 400; + color: var(--aurora); } .filter-reset { - background: #e74c3c; - color: white; - border: none; - padding: 0.75rem 1.5rem; + background: transparent; + color: var(--aurora); + border: 1px solid var(--aurora); + padding: 0.6rem 1.5rem; border-radius: 4px; cursor: pointer; - font-size: 1rem; - font-weight: 600; + font-family: var(--font-mono); + font-size: 0.72rem; + letter-spacing: 0.1em; + text-transform: uppercase; + transition: background 0.2s, color 0.2s; } .filter-reset:hover { - background: #c0392b; + background: var(--aurora); + color: var(--contrast); } .filter-reset:focus { - outline: 2px solid #3498db; + outline: 3px solid var(--aurora); outline-offset: 2px; } /* Result Count */ .result-count { - font-size: 1.1rem; - color: #4a4a4a; + font-family: var(--font-mono); + font-size: 0.75rem; + letter-spacing: 0.15em; + text-transform: uppercase; + color: var(--horizon); margin: 1rem 0; } @@ -240,15 +366,23 @@ h2 { .filters-toggle { display: block; width: 100%; - padding: 1rem; - background: #3498db; - color: white; - border: none; - border-radius: 6px; - font-weight: 600; - font-size: 1rem; + padding: 0.75rem 1rem; + background: transparent; + color: var(--aurora); + border: 1px solid var(--aurora); + border-radius: 4px; + font-family: var(--font-mono); + font-size: 0.72rem; + letter-spacing: 0.12em; + text-transform: uppercase; cursor: pointer; margin-bottom: 1rem; + transition: background 0.2s, color 0.2s; + } + + .filters-toggle:hover { + background: var(--aurora); + color: var(--contrast); } .filters-content { @@ -303,12 +437,13 @@ h2 { .provider-header { margin-bottom: 2rem; padding-bottom: 1.5rem; - border-bottom: 2px solid #ecf0f1; + border-bottom: 1px solid var(--slate); } .provider-tagline { font-size: 1.2rem; - color: #4a4a4a; + font-weight: 300; + color: var(--horizon); margin-top: 0.5rem; } @@ -318,8 +453,9 @@ h2 { gap: 1rem; margin: 2rem 0; padding: 1.5rem; - background: #f8f9fa; - border-radius: 8px; + background: rgba(255,255,255,0.04); + border: 1px solid var(--slate); + border-radius: 4px; } .meta-item { @@ -328,16 +464,28 @@ h2 { } .meta-item strong { - color: #2c3e50; + font-family: var(--font-mono); + font-size: 0.68rem; + letter-spacing: 0.15em; + text-transform: uppercase; + color: var(--horizon); + font-weight: 400; margin-bottom: 0.25rem; } +.meta-item span { + color: var(--cloud-white); + font-size: 1rem; +} + .external-link { - color: #3498db; + color: var(--aurora); text-decoration: none; + text-underline-offset: 3px; } .external-link:hover { + color: var(--cloud-white); text-decoration: underline; } @@ -351,19 +499,22 @@ h2 { } .provider-detail h2 { - color: #2c3e50; - margin-bottom: 0.5rem; + color: var(--horizon); + margin-bottom: 0.75rem; } .section-intro { - color: #4a4a4a; - font-size: 0.95rem; + color: var(--horizon); + font-size: 0.9rem; margin-bottom: 1.5rem; + font-family: var(--font-mono); + letter-spacing: 0.05em; } .provider-description .content { - line-height: 1.8; + line-height: 1.9; font-size: 1.05rem; + color: var(--cloud-white); } /* Services Grid */ @@ -374,16 +525,20 @@ h2 { } .service-card { - background: #3498db; - color: white; - padding: 1rem; - border-radius: 6px; + background: rgba(74,127,165,0.15); + border: 1px solid var(--sky-pale); + color: var(--cloud-white); + padding: 0.75rem 1rem; + border-radius: 4px; text-align: center; - font-weight: 600; } .service-name { display: block; + font-family: var(--font-mono); + font-size: 0.75rem; + letter-spacing: 0.1em; + text-transform: uppercase; } /* Certifications */ @@ -397,15 +552,15 @@ h2 { display: flex; align-items: center; gap: 1rem; - padding: 1.5rem; - background: #d5f4e6; - border-left: 4px solid #27ae60; - border-radius: 6px; + padding: 1.25rem 1.5rem; + background: rgba(126,200,200,0.06); + border-left: 3px solid var(--aurora); + border-radius: 4px; } .cert-icon { - font-size: 2rem; - color: #27ae60; + font-size: 1.5rem; + color: var(--aurora); } .cert-info { @@ -415,17 +570,22 @@ h2 { } .cert-name { - font-size: 1.1rem; - color: #2c3e50; + font-family: var(--font-mono); + font-size: 0.85rem; + letter-spacing: 0.1em; + color: var(--aurora); } .cert-link { - color: #27ae60; + color: var(--horizon); text-decoration: none; - font-size: 0.9rem; + font-family: var(--font-mono); + font-size: 0.72rem; + letter-spacing: 0.05em; } .cert-link:hover { + color: var(--aurora); text-decoration: underline; } @@ -438,16 +598,17 @@ h2 { .datacenter-item { padding: 1rem; - background: white; - border: 1px solid #ddd; - border-radius: 6px; + background: rgba(255,255,255,0.04); + border: 1px solid var(--slate); + border-radius: 4px; display: flex; align-items: center; gap: 0.5rem; + color: var(--cloud-white); } .location-icon { - font-size: 1.5rem; + font-size: 1.25rem; } /* Provider Actions */ @@ -456,36 +617,44 @@ h2 { gap: 1rem; margin: 3rem 0; padding-top: 2rem; - border-top: 2px solid #ecf0f1; + border-top: 1px solid var(--slate); } .btn { - padding: 0.75rem 1.5rem; - border-radius: 6px; + padding: 0.7rem 1.5rem; + border-radius: 4px; text-decoration: none; - font-weight: 600; - border: none; + font-family: var(--font-mono); + font-size: 0.75rem; + letter-spacing: 0.1em; + text-transform: uppercase; + font-weight: 400; + border: 1px solid transparent; cursor: pointer; - font-size: 1rem; - transition: background 0.2s; + transition: background 0.2s, color 0.2s, border-color 0.2s; } .btn-primary { - background: #1255b5; - color: white; + background: var(--aurora); + color: var(--contrast); + border-color: var(--aurora); } .btn-primary:hover { - background: #104989; + background: var(--sky-pale); + border-color: var(--sky-pale); + color: var(--cloud-white); } .btn-secondary { - background: #95a5a6; - color: white; + background: transparent; + color: var(--horizon); + border-color: var(--slate); } .btn-secondary:hover { - background: #7f8c8d; + border-color: var(--horizon); + color: var(--cloud-white); } @media (max-width: 768px) { @@ -511,8 +680,8 @@ h2 { position: sticky; left: 0; z-index: 10; - background: white; - box-shadow: 2px 0 4px rgba(0,0,0,0.1); + background: var(--sky-mid); + box-shadow: 2px 0 4px rgba(0,0,0,0.3); } .comparison-table thead th { @@ -532,9 +701,9 @@ h2 { bottom: 0; left: 0; right: 0; - background: white; - border-top: 3px solid #3498db; - box-shadow: 0 -2px 10px rgba(0,0,0,0.1); + background: var(--sky-mid); + border-top: 2px solid var(--aurora); + box-shadow: 0 -4px 20px rgba(0,0,0,0.4); padding: 1rem; z-index: 1000; display: none; @@ -556,25 +725,32 @@ h2 { } .comparison-counter { - background: #3498db; - color: white; + background: var(--aurora); + color: var(--contrast); padding: 0.25rem 0.6rem; border-radius: 50%; - font-size: 0.9rem; + font-family: var(--font-mono); + font-size: 0.8rem; font-weight: bold; } .btn-clear-comparison { background: transparent; - border: 1px solid #ddd; + border: 1px solid var(--slate); + color: var(--horizon); padding: 0.5rem 1rem; border-radius: 4px; cursor: pointer; - font-size: 0.9rem; + font-family: var(--font-mono); + font-size: 0.72rem; + letter-spacing: 0.08em; + text-transform: uppercase; + transition: border-color 0.2s, color 0.2s; } .btn-clear-comparison:hover { - background: #ecf0f1; + border-color: var(--horizon); + color: var(--cloud-white); } .comparison-list { @@ -585,54 +761,67 @@ h2 { } .comparison-item { - background: #ecf0f1; - padding: 0.5rem 1rem; + background: rgba(255,255,255,0.06); + border: 1px solid var(--slate); + color: var(--cloud-white); + padding: 0.4rem 0.75rem; border-radius: 4px; display: flex; align-items: center; gap: 0.5rem; + font-family: var(--font-mono); + font-size: 0.75rem; } .remove-comparison { - background: #e74c3c; - color: white; + background: transparent; + color: var(--aurora); border: none; - width: 20px; - height: 20px; + width: 18px; + height: 18px; border-radius: 50%; cursor: pointer; - font-size: 1.2rem; + font-size: 1rem; line-height: 1; display: flex; align-items: center; justify-content: center; + transition: color 0.2s; } .remove-comparison:hover { - background: #c0392b; + color: var(--cloud-white); } .btn-compare { - background: #27ae60; - color: white; - padding: 0.75rem 1.5rem; - border: none; + background: var(--aurora); + color: var(--contrast); + padding: 0.7rem 1.5rem; + border: 1px solid var(--aurora); border-radius: 4px; - font-weight: bold; + font-family: var(--font-mono); + font-size: 0.72rem; + letter-spacing: 0.1em; + text-transform: uppercase; + font-weight: 400; cursor: pointer; white-space: nowrap; + transition: background 0.2s, color 0.2s; } .btn-compare:hover { - background: #229954; + background: var(--sky-pale); + border-color: var(--sky-pale); + color: var(--cloud-white); } .in-comparison { - background: #27ae60 !important; + background: var(--aurora) !important; + color: var(--contrast) !important; } .in-comparison:hover { - background: #229954 !important; + background: var(--sky-pale) !important; } @media (max-width: 768px) { @@ -652,39 +841,38 @@ h2 { .lang-btn { background: transparent; - border: 2px solid rgba(255, 255, 255, 0.3); - color: white; - padding: 0.4rem 0.8rem; + border: 1px solid rgba(255,255,255,0.2); + color: var(--horizon); + padding: 0.35rem 0.75rem; border-radius: 4px; cursor: pointer; - font-weight: 600; - font-size: 0.9rem; + font-family: var(--font-mono); + font-size: 0.72rem; + letter-spacing: 0.1em; + text-transform: uppercase; transition: all 0.2s; } .lang-btn:hover { - background: rgba(255, 255, 255, 0.1); - border-color: rgba(255, 255, 255, 0.5); + border-color: var(--aurora); + color: var(--aurora); } .lang-btn:focus { - outline: 2px solid white; + outline: 2px solid var(--aurora); outline-offset: 2px; } .lang-btn.active { - background: white; - color: #2c3e50; - border-color: white; + background: var(--aurora); + color: var(--contrast); + border-color: var(--aurora); } .lang-separator { - color: rgba(255, 255, 255, 0.5); -} - -nav { - display: flex; - align-items: center; + color: var(--slate); + font-family: var(--font-mono); + font-size: 0.7rem; } /* Skip Navigation Link */ @@ -692,11 +880,14 @@ nav { position: absolute; top: -40px; left: 0; - background: #2c3e50; - color: white; + background: var(--aurora); + color: var(--contrast); padding: 0.75rem 1.5rem; text-decoration: none; - font-weight: 600; + font-family: var(--font-mono); + font-size: 0.75rem; + letter-spacing: 0.1em; + text-transform: uppercase; z-index: 9999; transition: top 0.2s; } @@ -706,18 +897,18 @@ nav { } /* Focus Indicators */ -a:focus, -button:focus, -input:focus, -select:focus, -textarea:focus { - outline: 2px solid #3498db; - outline-offset: 2px; +:focus-visible { + outline: 3px solid var(--aurora); + outline-offset: 4px; } -.filter-checkbox:focus { - outline: 2px solid #3498db; - outline-offset: 2px; +a { + color: var(--aurora); + text-underline-offset: 3px; +} + +a:hover { + color: var(--cloud-white); } /* Home Page Styles */ @@ -728,19 +919,21 @@ textarea:focus { } .home-content .tagline { - font-size: 1.2rem; - color: #666; + font-size: 1.15rem; + color: var(--horizon); margin-bottom: 2rem; + font-weight: 300; } .home-content .content { text-align: left; margin: 3rem auto; + color: var(--cloud-white); } .home-content h2 { - color: #2c3e50; margin-top: 2rem; + color: var(--horizon); } .home-content ul { @@ -752,28 +945,38 @@ textarea:focus { margin: 1rem 0; padding-left: 1.5rem; position: relative; + color: var(--cloud-white); + font-size: 1rem; } .home-content ul li::before { content: "✓"; position: absolute; left: 0; - color: #27ae60; - font-weight: bold; + color: var(--aurora); + font-family: var(--font-mono); } .home-content .btn { display: inline-block; margin-top: 2rem; - padding: 1rem 2rem; - background: #3498db; - color: white; + padding: 0.85rem 2rem; + background: var(--aurora); + color: var(--contrast); text-decoration: none; - border-radius: 6px; - font-weight: 600; - transition: background 0.2s; + border-radius: 4px; + font-family: var(--font-mono); + font-size: 0.75rem; + letter-spacing: 0.12em; + text-transform: uppercase; + font-weight: 400; + border: 1px solid var(--aurora); + transition: background 0.2s, color 0.2s; } .home-content .btn:hover { - background: #2980b9; + background: var(--sky-pale); + border-color: var(--sky-pale); + color: var(--cloud-white); } + diff --git a/templates/base.html b/templates/base.html index bf72883..bd0ee42 100644 --- a/templates/base.html +++ b/templates/base.html @@ -25,13 +25,29 @@ {% endif %} + + + + + + From a3da58c12ba7a790ccb29bd4018e5b772f03e64b Mon Sep 17 00:00:00 2001 From: "nicolas T." Date: Fri, 6 Mar 2026 11:51:25 +0100 Subject: [PATCH 2/6] CI: update accessibility tests --- .github/workflows/accessibility.yml | 22 +++++++-------- .gitignore | 7 ++++- mise.toml | 43 +++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 12 deletions(-) diff --git a/.github/workflows/accessibility.yml b/.github/workflows/accessibility.yml index 987625d..aad66d2 100644 --- a/.github/workflows/accessibility.yml +++ b/.github/workflows/accessibility.yml @@ -6,6 +6,7 @@ on: - 'static/**' - 'content/**' workflow_dispatch: + permissions: {} jobs: axe-core: @@ -23,27 +24,26 @@ jobs: - name: Build site run: zola build - - name: Set up Node.js - uses: actions/setup-node@v4 + - name: Set up bun + uses: oven-sh/setup-bun@v2 with: - node-version: '20' + bun-version: "latest" - name: Install axe-core CLI - run: npm install -g @axe-core/cli + run: bun install -g @axe-core/cli - name: Install chrome with browser-driver-manager - run: npx browser-driver-manager install chrome + run: bunx browser-driver-manager install chrome - name: Serve site and run axe-core run: | cd public - python3 -m http.server 8000 & - sleep 3 - + zola serve --port 8000 & # Test key pages - axe http://localhost:8000/ --exit - axe http://localhost:8000/providers/ --exit - axe http://localhost:8000/providers/scaleway/ --exit + axe http://localhost:8000/ \ + http://localhost:8000/providers/ \ + http://localhost:8000/providers/scaleway/ \ + http://localhost:8000/compare.html?providers=aws,google-cloud,microsoft-azure --exit - name: Report results if: always() diff --git a/.gitignore b/.gitignore index 1c7e181..32cc47a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,13 @@ _bmad/* # Generated static pages public - # Build artifacts artifacts/ *.tar.gz zola + +# Nodes artifacts +node_modules/ +package.json +bun.lock + diff --git a/mise.toml b/mise.toml index d8ae355..892866d 100644 --- a/mise.toml +++ b/mise.toml @@ -1,8 +1,51 @@ [tools] +bun = "latest" zola = "latest" +[vars] +port = "1111" + [tasks] check = "zola check" build = "zola build" validate = "uv run docs/validate_providers.py" +[tasks.serve] +depends = ["build"] +run = """ +#!/usr/bin/env bash +if nc -z localhost {{vars.port}} == 0; then + echo "zola is already serving" +else + zola serve --port {{vars.port}} & +fi +""" + +[tasks.stop] +run = """ +#!/usr/bin/env bash +if nc -z localhost {{vars.port}} == 0; then + killall zola +else + echo "zola is not running" +fi +""" + +[tasks.a11y] +description = "Accessibility tests" +depends = ["serve"] +run = """ +bun install axe-core +bunx browser-driver-manager install chrome +./node_modules/.bin/axe http://localhost:{{vars.port}}/ \ + http://localhost:{{vars.port}}/providers/ \ + http://localhost:{{vars.port}}/providers/scaleway/ \ + http://localhost:{{vars.port}}/compare.html?providers=aws,google-cloud,microsoft-azure --exit +EXIT_CODE=$? +exit $EXIT_CODE +""" + +[tasks.test] +description = "Run full tests" +depends = ["validate", "check", "a11y"] + From 6e5b5b0f4fcde90a973fb4b656d2935c0e0838a5 Mon Sep 17 00:00:00 2001 From: "nicolas T." Date: Fri, 6 Mar 2026 11:52:24 +0100 Subject: [PATCH 3/6] UI: add brand kit --- cloudlandscape-brand.html | 589 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 589 insertions(+) create mode 100644 cloudlandscape-brand.html diff --git a/cloudlandscape-brand.html b/cloudlandscape-brand.html new file mode 100644 index 0000000..548d4fb --- /dev/null +++ b/cloudlandscape-brand.html @@ -0,0 +1,589 @@ + + + + + + Cloudlandscape — Identité visuelle + + + + + + + + + + + + Aller au contenu principal + + +
+
+ + +
+

Brand Identity Kit

+

Cloudlandscape

+
+ + +
+ +
+ + +
+ + Cloudlandscape + + + + + + + + + + + + + + + + cloud + landscape + +

Fond sombre — usage principal

+
+ + +
+ + Cloudlandscape + + + + + + + + + + + cloud + landscape + +

Fond intermédiaire

+
+ + +
+ + Cloudlandscape + + + + + + + + + + + cloud + landscape + +

Fond clair

+
+ +
+
+ + +
+

Favicon

+
+ +
+
+ + Cloudlandscape favicon + + + + + + + +
+ 32×32 · dark +
+ +
+
+ + Cloudlandscape favicon + + + + + + + +
+ 32×32 · light +
+ +
+
+ + Cloudlandscape favicon small + + + + + + +
+ 16×16 +
+ +
+
+ + +
+

Codes couleurs

+
+ +
+ +
+ Sky Deep + #0B1D2E + Fond principal +
+
+ +
+ +
+ Sky Mid + #1A3A5C + Surfaces secondaires +
+
+ +
+ +
+ Sky Pale + #4A7FA5 + Éléments UI +
+
+ +
+ +
+ Aurora + #7EC8C8 + Accent / CTA — ratio 5.1:1 +
+
+ +
+ +
+ Horizon + #B8CDD8 + Textes secondaires +
+
+ +
+ +
+ Mist + #D9E8EF + Backgrounds clairs +
+
+ +
+ +
+ Cloud White + #EEF4F9 + Texte principal — ratio 15.3:1 +
+
+ +
+ +
+ Slate + #3D5A6E + Bordures / dividers +
+
+ +
+
+ + +
+

Typographie

+
+ +
+

Display — Cormorant Garamond 300

+

Horizons sans limites.

+
+ +
+

Heading — Cormorant Garamond 400

+

Paysages numériques, altitude infinie

+
+ +
+

Body — Cormorant Garamond 300

+

Cloudlandscape capture la poésie de l'invisible — ces espaces suspendus entre les données et l'horizon, où chaque altitude raconte une géographie.

+
+ +
+

Mono — DM Mono 400

+

--sky-deep: #0B1D2E; /* altitude max */

+
+ +
+

Caption — DM Mono 300

+

cloudlandscape.io · brand kit v1.0 · 2026

+
+ +
+
+ + +
+

CSS Design Tokens

+
+
+/* Cloudlandscape — Design Tokens */
+:root {
+  /* Couleurs */
+  --sky-deep:    #0B1D2E;   /* fond principal */
+  --sky-mid:     #1A3A5C;   /* surfaces secondaires */
+  --sky-pale:    #4A7FA5;   /* éléments UI */
+  --aurora:      #7EC8C8;   /* accent principal */
+  --horizon:     #B8CDD8;   /* textes secondaires */
+  --mist:        #D9E8EF;   /* fonds clairs */
+  --cloud-white: #EEF4F9;   /* texte principal */
+  --slate:       #3D5A6E;   /* bordures */
+
+  /* Typographie */
+  --font-display: 'Cormorant Garamond', Georgia, serif;
+  --font-mono:    'DM Mono', 'Courier New', monospace;
+
+  /* Espacements */
+  --space-xs: 0.5rem;
+  --space-sm: 1rem;
+  --space-md: 2rem;
+  --space-lg: 4rem;
+}
+
+
+ + +
+

Accessibilité RGAA

+
+ +
+

Contrastes

+

Cloud White / Sky Deep
15.3:1 ✓

+

Aurora / Sky Deep
5.1:1 ✓

+

Critère 3.2 RGAA — min 4.5:1

+
+ +
+

Navigation clavier

+

Focus visible sur tous les éléments interactifs

+

Critère 12.1 RGAA

+
+ +
+

Textes alternatifs

+

Attribut aria-label sur chaque SVG. Éléments décoratifs en aria-hidden

+

Critère 1.1 RGAA

+
+ +
+

Animations

+

Animations désactivées via prefers-reduced-motion

+

Critère 13.8 RGAA

+
+ +
+
+ +
+
+ +
+
+

Cloudlandscape · Brand Identity Kit · RGAA compliant · 2026

+
+
+ + + From a411b1788c9debf53f83556a9cf535a8798098d5 Mon Sep 17 00:00:00 2001 From: "nicolas T." Date: Fri, 6 Mar 2026 12:19:22 +0100 Subject: [PATCH 4/6] UI: apply brand kit to style --- static/compare.html | 38 +++++++++++++++++++++----------------- templates/page.html | 6 +++--- templates/section.html | 8 ++++---- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/static/compare.html b/static/compare.html index 9c11adc..fdfbd44 100644 --- a/static/compare.html +++ b/static/compare.html @@ -18,59 +18,63 @@ .comparison-table { width: 100%; border-collapse: collapse; - background: white; - box-shadow: 0 2px 4px rgba(0,0,0,0.1); + background: var(--sky-mid); + box-shadow: 0 2px 4px rgba(0,0,0,0.3); } .comparison-table th, .comparison-table td { padding: 1rem; - border: 1px solid #ddd; + border: 1px solid var(--slate); text-align: left; + color: var(--cloud-white); } .comparison-table thead th { - background: #2c3e50; - color: white; + background: var(--sky-deep); + color: var(--cloud-white); font-weight: 600; position: sticky; top: 0; } .comparison-table tbody th { - background: #ecf0f1; - font-weight: 600; + background: rgba(255,255,255,0.04); + color: var(--cloud-white); + font-weight: 400; } .comparison-table td { text-align: center; + color: var(--cloud-white); } .has-feature { - color: #27ae60; + color: #4ade80; font-size: 1.5rem; } .no-feature { - color: #e74c3c; + color: #f87171; font-size: 1.5rem; } .cert-yes { - background: #d5f4e6; + background: rgba(74,222,128,0.15); } .cert-no { - background: #fadbd8; + background: rgba(248,113,113,0.15); } .provider-link { - color: #3498db; + color: var(--aurora); text-decoration: none; - font-weight: 600; + font-weight: 400; } .provider-link:hover { + color: var(--cloud-white); text-decoration: underline; } @@ -86,7 +90,7 @@ } .empty-comparison h2 { - color: #666; + color: var(--horizon); } @@ -208,7 +212,7 @@

No providers selected

html += ''; // Service rows - html += 'Services'; + html += 'Services'; services.forEach(service => { html += `${service}`; providers.forEach(p => { @@ -219,7 +223,7 @@

No providers selected

}); // Certification rows - html += 'Certifications'; + html += 'Certifications'; certifications.forEach(cert => { html += `${cert}`; providers.forEach(p => { @@ -231,7 +235,7 @@

No providers selected

}); // Geographic coverage row - html += 'Geographic Coverage'; + html += 'Geographic Coverage'; html += 'Datacenters'; providers.forEach(p => { const locations = p.datacenters && p.datacenters.length > 0 diff --git a/templates/page.html b/templates/page.html index 5b6d7f3..2d701c6 100644 --- a/templates/page.html +++ b/templates/page.html @@ -59,11 +59,11 @@

Services Offered

Services are mapped to unified taxonomy categories for easy comparison across providers.

    {% for service in page.taxonomies.services %} -
    +
  • {{ service | replace(from="-", to=" ") | title }} -
  • + {% endfor %} - +
{% endif %} diff --git a/templates/section.html b/templates/section.html index 12ef767..ec76194 100644 --- a/templates/section.html +++ b/templates/section.html @@ -84,9 +84,9 @@

{{ trans(key="filters_heading", lang=section.lang) }} {% if section.pages %} -
+
    {% for page in section.pages %} -
- + {% endfor %} - + {% else %}

No providers found.

{% endif %} From 1875b08f7da4d25a8b658c2f06d4376a22d8e8df Mon Sep 17 00:00:00 2001 From: nicolas Trauwaen Date: Fri, 6 Mar 2026 14:21:48 +0100 Subject: [PATCH 5/6] Fix permissions format in accessibility.yml --- .github/workflows/accessibility.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/accessibility.yml b/.github/workflows/accessibility.yml index aad66d2..3d68a41 100644 --- a/.github/workflows/accessibility.yml +++ b/.github/workflows/accessibility.yml @@ -6,8 +6,7 @@ on: - 'static/**' - 'content/**' workflow_dispatch: - permissions: {} - +permissions: {} jobs: axe-core: runs-on: ubuntu-latest From 131c891fd6b85a9991f13e38b0fe0e47d9ba17fd Mon Sep 17 00:00:00 2001 From: "nicolas T." Date: Fri, 6 Mar 2026 15:58:53 +0100 Subject: [PATCH 6/6] Post review changes --- .github/workflows/accessibility.yml | 10 +++------- mise.toml | 9 ++++----- templates/base.html | 2 +- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/.github/workflows/accessibility.yml b/.github/workflows/accessibility.yml index 3d68a41..7d2941e 100644 --- a/.github/workflows/accessibility.yml +++ b/.github/workflows/accessibility.yml @@ -16,7 +16,7 @@ jobs: - name: Install Zola run: | - wget -q https://github.com/getzola/zola/releases/download/v0.22.1/zola-v0.22.1-x86_64-unknown-linux-gnu.tar.gz + curl -LO https://github.com/getzola/zola/releases/download/v0.22.1/zola-v0.22.1-x86_64-unknown-linux-gnu.tar.gz tar -xzf zola-v0.22.1-x86_64-unknown-linux-gnu.tar.gz sudo mv zola /usr/local/bin/ @@ -28,18 +28,14 @@ jobs: with: bun-version: "latest" - - name: Install axe-core CLI - run: bun install -g @axe-core/cli - - name: Install chrome with browser-driver-manager - run: bunx browser-driver-manager install chrome + run: bunx browser-driver-manager@2.0.1 install chrome - name: Serve site and run axe-core run: | - cd public zola serve --port 8000 & # Test key pages - axe http://localhost:8000/ \ + bunx @axe-core/cli@4.11.1 http://localhost:8000/ \ http://localhost:8000/providers/ \ http://localhost:8000/providers/scaleway/ \ http://localhost:8000/compare.html?providers=aws,google-cloud,microsoft-azure --exit diff --git a/mise.toml b/mise.toml index 892866d..92069da 100644 --- a/mise.toml +++ b/mise.toml @@ -14,7 +14,7 @@ validate = "uv run docs/validate_providers.py" depends = ["build"] run = """ #!/usr/bin/env bash -if nc -z localhost {{vars.port}} == 0; then +if nc -z localhost {{vars.port}}; then echo "zola is already serving" else zola serve --port {{vars.port}} & @@ -24,7 +24,7 @@ fi [tasks.stop] run = """ #!/usr/bin/env bash -if nc -z localhost {{vars.port}} == 0; then +if nc -z localhost {{vars.port}}; then killall zola else echo "zola is not running" @@ -35,9 +35,8 @@ fi description = "Accessibility tests" depends = ["serve"] run = """ -bun install axe-core -bunx browser-driver-manager install chrome -./node_modules/.bin/axe http://localhost:{{vars.port}}/ \ +bunx browser-driver-manager@2.0.1 install chrome +bunx @axe-core/cli@4.11.1 http://localhost:{{vars.port}}/ \ http://localhost:{{vars.port}}/providers/ \ http://localhost:{{vars.port}}/providers/scaleway/ \ http://localhost:{{vars.port}}/compare.html?providers=aws,google-cloud,microsoft-azure --exit diff --git a/templates/base.html b/templates/base.html index bd0ee42..3c7e42d 100644 --- a/templates/base.html +++ b/templates/base.html @@ -38,7 +38,7 @@