From af2b407c529dd354c4d99de1dfbfe9995b84a9fc Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Sun, 17 May 2026 18:05:16 +0800 Subject: [PATCH] Use generated css, common to the project --- .gitignore | 3 +- .gitlab-ci.yml | 3 +- .woodpecker.yaml | 3 +- assets/scss/bootstrap.scss | 970 ++++++++++++++++++++++++++++++++++ config.yml | 23 + i18n/en.yaml | 2 +- i18n/fr.yaml | 2 +- layouts/_default/single.html | 72 ++- layouts/partials/head.html | 20 +- layouts/partials/nav.html | 6 +- package-lock.json | 90 ++++ package.json | 11 + static/css/custom.css | 159 +++--- static/fonts/Montserrat.woff2 | Bin 19172 -> 0 bytes 14 files changed, 1237 insertions(+), 127 deletions(-) create mode 100644 assets/scss/bootstrap.scss create mode 100644 package-lock.json create mode 100644 package.json delete mode 100644 static/fonts/Montserrat.woff2 diff --git a/.gitignore b/.gitignore index 132a090..d0d6966 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ public/ -resources/ \ No newline at end of file +resources/ +node_modules/ \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d68917a..56f2b44 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,7 +1,7 @@ # # All available Hugo versions are listed under https://gitlab.com/pages/hugo/container_registry. # -image: hugomods/hugo:base +image: hugomods/hugo:node-non-root stages: - build @@ -9,6 +9,7 @@ stages: pages: stage: build script: + - npm ci - hugo artifacts: paths: diff --git a/.woodpecker.yaml b/.woodpecker.yaml index 7bc94f9..69d8b64 100644 --- a/.woodpecker.yaml +++ b/.woodpecker.yaml @@ -6,8 +6,9 @@ when: steps: - name: build - image: hugomods/hugo:base + image: hugomods/hugo:exts-node commands: + - npm ci - hugo environment: HUGO_ENVIRONMENT: production diff --git a/assets/scss/bootstrap.scss b/assets/scss/bootstrap.scss new file mode 100644 index 0000000..771ce6b --- /dev/null +++ b/assets/scss/bootstrap.scss @@ -0,0 +1,970 @@ +// ============================================================================ +// happyDomain × Bootstrap 5 — SCSS Customization +// ---------------------------------------------------------------------------- +// Drop-in override for a Bootstrap 5 (>=5.3) build. +// +// Usage: +// 1. Have Bootstrap's SCSS source available (`bootstrap/scss/...`) +// 2. Compile this file as your single entry point: +// sass happydomain-bootstrap.scss happydomain-bootstrap.css +// 3. Include the compiled CSS. +// +// Targets Bootstrap 5.3+ (uses the `$theme-colors`, `$utilities`, +// `data-bs-theme` and color-mode CSS-var system). +// ============================================================================ + +// ───────────────────────────────────────────────────────────────────────────── +// 1. FONTS — Brand display + UI + Mono +// ───────────────────────────────────────────────────────────────────────────── + + +// ───────────────────────────────────────────────────────────────────────────── +// 2. BRAND TOKENS (mirror of colors_and_type.css — kept as Sass scalars so +// they can drive Bootstrap maps before `@import "bootstrap"`.) +// ───────────────────────────────────────────────────────────────────────────── + +// — Brand plum ramp ────────────────────────────────────────────────────────── +$hd-plum-50: #f7f1fa; +$hd-plum-100: #ecdcf2; +$hd-plum-200: #d6b1e3; +$hd-plum-300: #b985ce; +$hd-plum-400: #985bb3; +$hd-plum-500: #743b91; +$hd-plum-600: #54206c; +$hd-plum-700: #360b48; // BRAND DARK ANCHOR +$hd-plum-800: #240630; +$hd-plum-900: #14031c; + +// — Brand dark semantic roles (plum surface system) ─────────────────────────── +$hd-brand-dark: $hd-plum-700; // canonical plum surface +$hd-brand-dark-hover: $hd-plum-800; // deepen on hover/active +$hd-brand-dark-fg: $hd-plum-50; // primary text on plum surface +$hd-brand-dark-muted: $hd-plum-200; // secondary text / eyebrows on plum surface +$hd-brand-dark-border: $hd-plum-600; // dividers within plum surfaces +$hd-brand-dark-subtle: $hd-plum-50; // subtle plum tint on light backgrounds + +// — Dark mode canvas (plum-tinted, replaces green-tinted #0c0f0e) ───────────── +$hd-bg-canvas-dark: #0f0a11; + +// — Brand green ramp ────────────────────────────────────────────────────────── +$hd-green-50: #edfaf5; +$hd-green-100: #d0f2e6; +$hd-green-200: #9de4ca; +$hd-green-300: #56c8a4; +$hd-green-400: #2dba93; +$hd-green-500: #1cb487; // PRIMARY +$hd-green-600: #17a377; +$hd-green-700: #128f67; +$hd-green-800: #0d7254; +$hd-green-900: #084d38; + +// — Neutrals (light) ───────────────────────────────────────────────────────── +$hd-bg-canvas: #ffffff; +$hd-bg-default: #fafafa; +$hd-bg-subtle: #f4f4f5; +$hd-bg-inset: #eeeeef; + +$hd-fg-1: #0a0a0b; +$hd-fg-2: #3f3f46; +$hd-fg-3: #71717a; +$hd-fg-4: #a1a1aa; + +$hd-border-1: #e4e4e7; +$hd-border-2: #d1d1d6; +$hd-border-3: #a1a1aa; + +// — Semantic ───────────────────────────────────────────────────────────────── +$hd-success: $hd-green-500; +$hd-success-bg: $hd-green-50; +$hd-danger: #e5484d; +$hd-danger-bg: #fff1f2; +$hd-warning: #f59e0b; +$hd-warning-bg: #fffbeb; +$hd-info: #0ea5e9; +$hd-info-bg: #f0f9ff; + +// — Focus ring ─────────────────────────────────────────────────────────────── +$hd-focus-ring: rgba(28, 180, 135, 0.22); + +// ───────────────────────────────────────────────────────────────────────────── +// 3. BOOTSTRAP VARIABLE OVERRIDES +// (declared BEFORE importing bootstrap/scss/variables) +// ───────────────────────────────────────────────────────────────────────────── + +// ── Color system ──────────────────────────────────────────────────────────── +// Re-point Bootstrap's $green to our brand ramp so the generated utilities +// (`text-success`, `bg-success`, etc) match exactly. +$primary: $hd-green-500; +$secondary: $hd-fg-3; +$success: $hd-green-500; +$info: $hd-info; +$warning: $hd-warning; +$danger: $hd-danger; +$light: $hd-bg-subtle; +$dark: $hd-fg-1; + +// Bootstrap 5.3 builds its grayscale from $gray-* — align it to Zinc-ish. +$white: #ffffff; +$gray-100: $hd-bg-subtle; +$gray-200: $hd-bg-inset; +$gray-300: $hd-border-1; +$gray-400: $hd-border-2; +$gray-500: $hd-border-3; +$gray-600: $hd-fg-3; +$gray-700: $hd-fg-2; +$gray-800: #27272a; +$gray-900: $hd-fg-1; +$black: #000000; + +// Custom theme color: "accent" — same green but available as a separate slot +// so designers can use `.btn-accent`, `.text-accent`, etc. +$custom-theme-colors: ( + "accent": $hd-green-500, + "brand": $hd-green-500, + "plum": $hd-plum-500, +); + +// ── Body / surfaces ───────────────────────────────────────────────────────── +$body-bg: $hd-bg-default; +$body-color: $hd-fg-2; +$body-secondary-color: $hd-fg-3; +$body-secondary-bg: $hd-bg-subtle; +$body-tertiary-color: $hd-fg-4; +$body-tertiary-bg: $hd-bg-inset; +$body-emphasis-color: $hd-fg-1; + +// ── Borders ───────────────────────────────────────────────────────────────── +$border-color: $hd-border-1; +$border-color-translucent: $hd-border-1; + +$border-radius: 6px; // --hd-radius +$border-radius-sm: 4px; // --hd-radius-sm +$border-radius-lg: 8px; // --hd-radius-md +$border-radius-xl: 12px; // --hd-radius-lg +$border-radius-xxl: 12px; +$border-radius-pill: 9999px; + +// ── Links ─────────────────────────────────────────────────────────────────── +$link-color: $hd-green-500; +$link-hover-color: $hd-green-700; +$link-decoration: none; +$link-hover-decoration: underline; + +// ── Typography ────────────────────────────────────────────────────────────── +$font-family-sans-serif: + "Hanken Grotesk Variable", + "Hanken Grotesk", + system-ui, + -apple-system, + "Segoe UI", + Roboto, + sans-serif; +$font-family-monospace: + "JetBrains Mono Variable", JetBrainsMono, "Fantasque Sans Mono", "SFMono-Regular", Menlo, + Consolas, monospace; +$font-family-base: $font-family-sans-serif; + +$font-size-root: null; // honour browser default +$font-size-base: 0.9375rem; // 15px — --hd-text-base +$font-size-sm: 0.8125rem; // --hd-text-sm +$font-size-lg: 1.0625rem; // --hd-text-md + +$font-weight-lighter: 300; +$font-weight-light: 300; +$font-weight-normal: 400; +$font-weight-medium: 500; +$font-weight-semibold: 600; +$font-weight-bold: 700; +$font-weight-base: $font-weight-normal; + +$line-height-base: 1.5; // --hd-leading-normal +$line-height-sm: 1.375; // --hd-leading-snug +$line-height-lg: 1.625; // --hd-leading-relaxed + +// Heading scale (matches --hd-text-*xl) +$h1-font-size: 2.25rem; // --hd-text-3xl +$h2-font-size: 1.875rem; // --hd-text-2xl +$h3-font-size: 1.5rem; // --hd-text-xl +$h4-font-size: 1.25rem; // --hd-text-lg +$h5-font-size: 1.0625rem; // --hd-text-md +$h6-font-size: 0.9375rem; // --hd-text-base + +$headings-font-family: $font-family-sans-serif; +$headings-font-weight: 600; +$headings-line-height: 1.2; +$headings-color: $hd-fg-1; + +$display-font-family: "Quicksand Variable", "Quicksand", sans-serif; +$display-font-weight: 700; +$display-line-height: 1.2; + +$small-font-size: 0.8125rem; +$text-muted: $hd-fg-3; + +// ── Spacing (Bootstrap's spacer scale — kept default, but explicit) ───────── +$spacer: 1rem; +$spacers: ( + 0: 0, + 1: $spacer * 0.25, + // 4px + 2: $spacer * 0.5, + // 8px + 3: $spacer * 0.75, + // 12px + 4: $spacer, + // 16px + 5: $spacer * 1.25, + // 20px + 6: $spacer * 1.5, + // 24px + 7: $spacer * 2, + // 32px + 8: $spacer * 2.5, + // 40px + 9: $spacer * 3, + // 48px + 10: $spacer * 4, + // 64px + 11: $spacer * 5, // 80px +); + +// ── Shadows — flat system, separation by border ───────────────────────────── +$enable-shadows: false; +$enable-gradients: false; +$enable-rounded: true; +$enable-transitions: true; +$enable-reduced-motion: true; +$enable-smooth-scroll: true; + +$box-shadow: none; +$box-shadow-sm: none; +$box-shadow-lg: none; +$box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.04); + +// ── Focus ring ────────────────────────────────────────────────────────────── +$focus-ring-width: 3px; +$focus-ring-opacity: 1; +$focus-ring-color: $hd-focus-ring; +$focus-ring-blur: 0; +$focus-ring-box-shadow: 0 0 0 $focus-ring-width $focus-ring-color; + +// ── Components ────────────────────────────────────────────────────────────── + +// Buttons +$btn-font-weight: 500; +$btn-border-radius: $border-radius; +$btn-border-radius-sm: $border-radius-sm; +$btn-border-radius-lg: $border-radius-lg; +$btn-padding-y: 0.5rem; +$btn-padding-x: 0.875rem; +$btn-focus-width: 3px; +$btn-focus-box-shadow: $focus-ring-box-shadow; +$btn-disabled-opacity: 0.5; +$btn-transition: + color 0.12s ease-in-out, + background-color 0.12s ease-in-out, + border-color 0.12s ease-in-out; + +// Forms +$input-bg: $hd-bg-canvas; +$input-color: $hd-fg-1; +$input-border-color: $hd-border-1; +$input-border-radius: $border-radius; +$input-border-radius-sm: $border-radius-sm; +$input-border-radius-lg: $border-radius-lg; +$input-padding-y: 0.5rem; +$input-padding-x: 0.75rem; +$input-placeholder-color: $hd-fg-4; +$input-focus-border-color: $hd-green-400; +$input-focus-box-shadow: $focus-ring-box-shadow; +$input-box-shadow: $box-shadow-inset; + +$form-label-color: $hd-fg-2; +$form-label-font-weight: 500; +$form-label-font-size: $font-size-sm; + +$form-check-input-border: 1px solid $hd-border-2; +$form-check-input-checked-bg-color: $hd-green-500; +$form-check-input-focus-box-shadow: $focus-ring-box-shadow; + +// Cards +$card-border-color: $hd-border-1; +$card-border-radius: $border-radius-lg; +$card-inner-border-radius: subtract($card-border-radius, 1px); +$card-cap-bg: $hd-bg-subtle; +$card-cap-color: $hd-fg-1; +$card-bg: $hd-bg-canvas; +$card-box-shadow: none; +$card-spacer-y: 1rem; +$card-spacer-x: 1.25rem; + +// Navbar +$navbar-padding-y: 0.75rem; +$navbar-light-color: $hd-fg-2; +$navbar-light-hover-color: $hd-fg-1; +$navbar-light-active-color: $hd-green-700; +$navbar-light-brand-color: $hd-fg-1; +$navbar-light-brand-hover-color: $hd-fg-1; + +// Dropdowns +$dropdown-bg: $hd-bg-canvas; +$dropdown-border-color: $hd-border-1; +$dropdown-border-radius: $border-radius-lg; +$dropdown-box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06); +$dropdown-link-hover-bg: $hd-bg-subtle; +$dropdown-link-active-bg: $hd-green-50; +$dropdown-link-active-color: $hd-green-700; + +// Modals +$modal-content-bg: $hd-bg-canvas; +$modal-content-border-color: $hd-border-1; +$modal-content-border-radius: $border-radius-xl; +$modal-content-box-shadow-xs: 0 8px 24px rgba(0, 0, 0, 0.08); +$modal-content-box-shadow-sm-up: 0 16px 48px rgba(0, 0, 0, 0.12); +$modal-backdrop-bg: #0a0a0b; +$modal-backdrop-opacity: 0.4; + +// Alerts +$alert-border-radius: $border-radius; +$alert-border-width: 1px; +$alert-padding-y: 0.75rem; +$alert-padding-x: 1rem; + +// Badges +$badge-font-size: 0.75em; +$badge-font-weight: 600; +$badge-padding-y: 0.25em; +$badge-padding-x: 0.5em; +$badge-border-radius: $border-radius-sm; + +// Tables +$table-border-color: $hd-border-1; +$table-striped-bg: $hd-bg-subtle; +$table-hover-bg: $hd-bg-subtle; +$table-color: $hd-fg-2; + +// Code +$code-color: $hd-green-700; +$code-font-size: 0.9em; +$kbd-bg: $hd-fg-1; +$pre-color: $hd-fg-2; + +// Tooltip / popover +$tooltip-bg: $hd-fg-1; +$tooltip-color: $hd-bg-canvas; +$tooltip-border-radius: $border-radius-sm; +$tooltip-font-size: $font-size-sm; +$popover-bg: $hd-bg-canvas; +$popover-border-color: $hd-border-1; +$popover-border-radius: $border-radius-lg; +$popover-box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06); + +// ───────────────────────────────────────────────────────────────────────────── +// 4. BOOTSTRAP IMPORT +// Adjust this path to your `bootstrap/scss/` location. +// ───────────────────────────────────────────────────────────────────────────── + +@import "bootstrap/scss/functions"; +@import "bootstrap/scss/variables"; +@import "bootstrap/scss/variables-dark"; +@import "bootstrap/scss/maps"; +@import "bootstrap/scss/mixins"; +@import "bootstrap/scss/utilities"; + +// Extend $theme-colors with our custom slots +$theme-colors: map-merge($theme-colors, $custom-theme-colors); + +// Now pull the rest of Bootstrap in +@import "bootstrap/scss/root"; +@import "bootstrap/scss/reboot"; +@import "bootstrap/scss/type"; +@import "bootstrap/scss/images"; +@import "bootstrap/scss/containers"; +@import "bootstrap/scss/grid"; +@import "bootstrap/scss/tables"; +@import "bootstrap/scss/forms"; +@import "bootstrap/scss/buttons"; +@import "bootstrap/scss/transitions"; +@import "bootstrap/scss/dropdown"; +@import "bootstrap/scss/button-group"; +@import "bootstrap/scss/nav"; +@import "bootstrap/scss/navbar"; +@import "bootstrap/scss/card"; +@import "bootstrap/scss/accordion"; +@import "bootstrap/scss/breadcrumb"; +@import "bootstrap/scss/pagination"; +@import "bootstrap/scss/badge"; +@import "bootstrap/scss/alert"; +@import "bootstrap/scss/progress"; +@import "bootstrap/scss/list-group"; +@import "bootstrap/scss/close"; +@import "bootstrap/scss/toasts"; +@import "bootstrap/scss/modal"; +@import "bootstrap/scss/tooltip"; +@import "bootstrap/scss/popover"; +@import "bootstrap/scss/carousel"; +@import "bootstrap/scss/spinners"; +@import "bootstrap/scss/offcanvas"; +@import "bootstrap/scss/placeholders"; +@import "bootstrap/scss/helpers"; +@import "bootstrap/scss/utilities/api"; + +// ───────────────────────────────────────────────────────────────────────────── +// 5. happyDomain CSS CUSTOM PROPERTIES +// Exposed alongside Bootstrap's so existing `--hd-*` references keep working. +// ───────────────────────────────────────────────────────────────────────────── + +:root, +[data-bs-theme="light"] { + // Plum ramp + --hd-plum-50: #{$hd-plum-50}; + --hd-plum-100: #{$hd-plum-100}; + --hd-plum-200: #{$hd-plum-200}; + --hd-plum-300: #{$hd-plum-300}; + --hd-plum-400: #{$hd-plum-400}; + --hd-plum-500: #{$hd-plum-500}; + --hd-plum-600: #{$hd-plum-600}; + --hd-plum-700: #{$hd-plum-700}; + --hd-plum-800: #{$hd-plum-800}; + --hd-plum-900: #{$hd-plum-900}; + + // Brand dark roles + --hd-brand-dark: #{$hd-brand-dark}; + --hd-brand-dark-hover: #{$hd-brand-dark-hover}; + --hd-brand-dark-fg: #{$hd-brand-dark-fg}; + --hd-brand-dark-muted: #{$hd-brand-dark-muted}; + --hd-brand-dark-border: #{$hd-brand-dark-border}; + --hd-brand-dark-subtle: #{$hd-brand-dark-subtle}; + + // Brand ramp + --hd-green-50: #{$hd-green-50}; + --hd-green-100: #{$hd-green-100}; + --hd-green-200: #{$hd-green-200}; + --hd-green-300: #{$hd-green-300}; + --hd-green-400: #{$hd-green-400}; + --hd-green-500: #{$hd-green-500}; + --hd-green-600: #{$hd-green-600}; + --hd-green-700: #{$hd-green-700}; + --hd-green-800: #{$hd-green-800}; + --hd-green-900: #{$hd-green-900}; + + // Surfaces + --hd-bg-canvas: #{$hd-bg-canvas}; + --hd-bg-default: #{$hd-bg-default}; + --hd-bg-subtle: #{$hd-bg-subtle}; + --hd-bg-inset: #{$hd-bg-inset}; + --hd-bg-overlay: rgba(0, 0, 0, 0.04); + + // Foreground + --hd-fg-1: #{$hd-fg-1}; + --hd-fg-2: #{$hd-fg-2}; + --hd-fg-3: #{$hd-fg-3}; + --hd-fg-4: #{$hd-fg-4}; + --hd-fg-inverse: #ffffff; + + // Borders + --hd-border-1: #{$hd-border-1}; + --hd-border-2: #{$hd-border-2}; + --hd-border-3: #{$hd-border-3}; + + // Accent + --hd-accent: #{$hd-green-500}; + --hd-accent-hover: #{$hd-green-600}; + --hd-accent-fg: #ffffff; + --hd-accent-subtle: #{$hd-green-50}; + --hd-accent-muted: #{$hd-green-100}; + --hd-accent-border: #{$hd-green-200}; + --hd-focus-ring: #{$hd-focus-ring}; + + // Semantic + --hd-success: #{$hd-success}; + --hd-success-bg: #{$hd-success-bg}; + --hd-danger: #{$hd-danger}; + --hd-danger-bg: #{$hd-danger-bg}; + --hd-warning: #{$hd-warning}; + --hd-warning-bg: #{$hd-warning-bg}; + --hd-info: #{$hd-info}; + --hd-info-bg: #{$hd-info-bg}; + + // DNS diff + --hd-diff-add: #{$hd-green-500}; + --hd-diff-add-bg: #{$hd-green-50}; + --hd-diff-add-line: #{$hd-green-100}; + --hd-diff-del: #{$hd-danger}; + --hd-diff-del-bg: #{$hd-danger-bg}; + --hd-diff-del-line: #ffd6d8; + --hd-diff-mod: #{$hd-warning}; + --hd-diff-mod-bg: #{$hd-warning-bg}; + + // Fonts + --hd-font-brand: "Quicksand Variable", "Quicksand", sans-serif; + --hd-font-ui: "DM Sans", system-ui, -apple-system, sans-serif; + --hd-font-mono: "DM Mono", "SFMono-Regular", Consolas, monospace; + + // Radii + --hd-radius-none: 0; + --hd-radius-xs: 2px; + --hd-radius-sm: 4px; + --hd-radius: 6px; + --hd-radius-md: 8px; + --hd-radius-lg: 12px; + --hd-radius-full: 9999px; + + // Shadows + --hd-shadow-none: none; + --hd-shadow-focus: 0 0 0 3px var(--hd-focus-ring); + --hd-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.04); +} + +// ───────────────────────────────────────────────────────────────────────────── +// 6. DARK MODE (Bootstrap 5.3 `data-bs-theme="dark"`) +// Mirrors the dark-mode block in colors_and_type.css. +// ───────────────────────────────────────────────────────────────────────────── + +[data-bs-theme="dark"] { + // Bootstrap CSS vars + --bs-body-bg: #111514; // content default (green-tinted surfaces unchanged) + --bs-body-bg-rgb: 17, 21, 20; + --bs-body-color: #b8c4bf; + --bs-body-color-rgb: 184, 196, 191; + --bs-emphasis-color: #f4f7f6; + --bs-secondary-color: #7a9189; + --bs-secondary-bg: #181d1b; + --bs-tertiary-color: #4a5e58; + --bs-tertiary-bg: #1e2422; + --bs-dark: #f4f7f6; + --bs-dark-rgb: 244, 247, 246; + --bs-light: #1e2422; + --bs-light-rgb: 30, 36, 34; + + --bs-border-color: #1f2c27; + --bs-border-color-translucent: rgba(255, 255, 255, 0.1); + --bs-link-color: #22d3a3; + --bs-link-color-rgb: 34, 211, 163; + --bs-link-hover-color: #56c8a4; + --bs-code-color: #56c8a4; + --bs-primary: #22d3a3; + --bs-primary-rgb: 34, 211, 163; + --bs-primary-bg-subtle: #0d2a22; + --bs-primary-border-subtle: #1a5c47; + --bs-primary-text-emphasis: #56c8a4; + --bs-success: #22d3a3; + --bs-success-rgb: 34, 211, 163; + --bs-success-bg-subtle: #0d2a22; + --bs-danger: #f87171; + --bs-danger-rgb: 248, 113, 113; + --bs-danger-bg-subtle: #2a1010; + --bs-warning: #fbbf24; + --bs-warning-rgb: 251, 191, 36; + --bs-warning-bg-subtle: #2a1f00; + --bs-info: #38bdf8; + --bs-info-rgb: 56, 189, 248; + --bs-info-bg-subtle: #0c1e2a; + + // happyDomain CSS vars + --hd-bg-canvas: #{$hd-bg-canvas-dark}; // plum-tinted, replaces green #0c0f0e + --hd-bg-default: #111514; + --hd-bg-subtle: #181d1b; + --hd-bg-inset: #1e2422; + --hd-bg-overlay: rgba(255, 255, 255, 0.04); + + --hd-fg-1: #f4f7f6; + --hd-fg-2: #b8c4bf; + --hd-fg-3: #7a9189; + --hd-fg-4: #4a5e58; + --hd-fg-inverse: #0c0f0e; + + --hd-border-1: #1f2c27; + --hd-border-2: #293c36; + --hd-border-3: #3a5249; + + --hd-accent: #22d3a3; + --hd-accent-hover: #1cb487; + --hd-accent-fg: #0c0f0e; + --hd-accent-subtle: #0d2a22; + --hd-accent-muted: #0f3329; + --hd-accent-border: #1a5c47; + --hd-focus-ring: rgba(34, 211, 163, 0.25); + + --hd-success: #22d3a3; + --hd-success-bg: #0d2a22; + --hd-danger: #f87171; + --hd-danger-bg: #2a1010; + --hd-warning: #fbbf24; + --hd-warning-bg: #2a1f00; + --hd-info: #38bdf8; + --hd-info-bg: #0c1e2a; + + --hd-diff-add: #22d3a3; + --hd-diff-add-bg: #0d2a22; + --hd-diff-add-line: #0f3329; + --hd-diff-del: #f87171; + --hd-diff-del-bg: #2a1010; + --hd-diff-del-line: #3a1515; + --hd-diff-mod: #fbbf24; + --hd-diff-mod-bg: #2a1f00; + + --hd-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.3); +} + +[data-bs-theme="dark"] .form-switch .form-check-input:not(:checked):not(:focus) { + --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255%2C255%2C255%2C.25%29'/%3e%3c/svg%3e"); +} + +[data-bs-theme="dark"] .modal-content { + --bs-modal-bg: var(--hd-bg-canvas); + --bs-modal-color: var(--hd-fg-2); + --bs-modal-border-color: var(--hd-border-1); + --bs-modal-header-border-color: var(--hd-border-1); + --bs-modal-footer-border-color: var(--hd-border-1); +} + +[data-bs-theme="dark"] .table { + --bs-table-color: var(--hd-fg-2); + --bs-table-bg: transparent; + --bs-table-border-color: var(--hd-border-1); + --bs-table-striped-color: var(--hd-fg-2); + --bs-table-striped-bg: rgba(255, 255, 255, 0.03); + --bs-table-hover-color: var(--hd-fg-1); + --bs-table-hover-bg: rgba(255, 255, 255, 0.04); + --bs-table-active-bg: rgba(255, 255, 255, 0.06); +} + +// ───────────────────────────────────────────────────────────────────────────── +// 7. COMPONENT REFINEMENTS — small tweaks to align Bootstrap with the system +// ───────────────────────────────────────────────────────────────────────────── + +// Use brand font for `.display-*` headings +.display-1, +.display-2, +.display-3, +.display-4, +.display-5, +.display-6 { + font-family: var(--hd-font-brand); + letter-spacing: -0.02em; +} + +// Tighten button hover — flat system, no shadow lift +.btn-primary, +.btn-success { + --bs-btn-bg: var(--hd-accent); + --bs-btn-border-color: var(--hd-accent); + --bs-btn-hover-bg: var(--hd-accent-hover); + --bs-btn-hover-border-color: var(--hd-accent-hover); + --bs-btn-active-bg: var(--hd-accent-hover); + --bs-btn-active-border-color: var(--hd-accent-hover); + --bs-btn-color: var(--hd-accent-fg); + --bs-btn-hover-color: var(--hd-accent-fg); + --bs-btn-active-color: var(--hd-accent-fg); +} + +.btn-outline-primary { + --bs-btn-color: var(--hd-accent); + --bs-btn-border-color: var(--hd-accent-border); + --bs-btn-hover-bg: var(--hd-accent-subtle); + --bs-btn-hover-border-color: var(--hd-accent); + --bs-btn-hover-color: var(--hd-accent-hover); + --bs-btn-active-bg: var(--hd-accent); + --bs-btn-active-border-color: var(--hd-accent); + --bs-btn-active-color: var(--hd-accent-fg); +} + +// Inputs: subtle inset, focus ring uses brand +.form-control, +.form-select { + background-color: var(--hd-bg-canvas); + border-color: var(--hd-border-1); + color: var(--hd-fg-1); + &:focus { + background-color: var(--hd-bg-canvas); + border-color: var(--hd-accent); + color: var(--hd-fg-1); + box-shadow: 0 0 0 3px var(--hd-focus-ring); + } +} + +.input-group-text { + background-color: var(--hd-bg-subtle); + border-color: var(--hd-border-1); + color: var(--hd-fg-2); +} + +// Card: flat, 1px border separation +.card { + --bs-card-bg: var(--hd-bg-canvas); + --bs-card-border-color: var(--hd-border-1); + box-shadow: none; +} + +[data-bs-theme="dark"] .offcanvas, +[data-bs-theme="dark"] .offcanvas-sm, +[data-bs-theme="dark"] .offcanvas-md, +[data-bs-theme="dark"] .offcanvas-lg, +[data-bs-theme="dark"] .offcanvas-xl, +[data-bs-theme="dark"] .offcanvas-xxl { + --bs-offcanvas-bg: var(--hd-bg-subtle); + --bs-offcanvas-border-color: var(--hd-border-1); + --bs-offcanvas-color: var(--hd-fg-2); +} + +[data-bs-theme="dark"] .dropdown-menu { + --bs-dropdown-bg: var(--hd-bg-subtle); + --bs-dropdown-border-color: var(--hd-border-1); + --bs-dropdown-color: var(--hd-fg-2); + --bs-dropdown-link-color: var(--hd-fg-2); + --bs-dropdown-link-hover-bg: var(--hd-bg-inset); + --bs-dropdown-link-hover-color: var(--hd-fg-1); + --bs-dropdown-link-active-bg: var(--hd-accent-subtle); + --bs-dropdown-link-active-color: var(--hd-accent); + --bs-dropdown-divider-bg: var(--hd-border-1); +} + +[data-bs-theme="dark"] .card { + --bs-card-bg: var(--hd-bg-canvas); + --bs-card-cap-bg: var(--hd-bg-default); + --bs-card-cap-color: var(--hd-fg-1); + --bs-card-color: var(--hd-fg-2); + --bs-card-border-color: var(--hd-border-1); +} + +// Alerts: tint background + colored border to match diff/semantic system +.alert-success { + background-color: var(--hd-success-bg); + border-color: var(--hd-accent-border); + color: #0d6651; +} +.alert-danger { + background-color: var(--hd-danger-bg); + border-color: var(--hd-diff-del-line); + color: #9b2c2f; +} +.alert-warning { + background-color: var(--hd-warning-bg); + border-color: #fcd34d; + color: #92400e; +} +.alert-info { + background-color: var(--hd-info-bg); + border-color: #bae6fd; + color: #075985; +} + +[data-bs-theme="dark"] { + .btn-light { + --bs-btn-bg: var(--hd-bg-inset); + --bs-btn-border-color: var(--hd-border-2); + --bs-btn-color: var(--hd-fg-1); + --bs-btn-hover-bg: var(--hd-bg-subtle); + --bs-btn-hover-border-color: var(--hd-border-1); + --bs-btn-hover-color: var(--hd-fg-1); + --bs-btn-active-bg: var(--hd-bg-default); + --bs-btn-active-border-color: var(--hd-border-1); + --bs-btn-active-color: var(--hd-fg-1); + } + + .btn-dark { + --bs-btn-bg: var(--hd-fg-1); + --bs-btn-border-color: var(--hd-fg-1); + --bs-btn-color: var(--hd-fg-inverse); + --bs-btn-hover-bg: var(--hd-fg-2); + --bs-btn-hover-border-color: var(--hd-fg-2); + --bs-btn-hover-color: var(--hd-fg-inverse); + --bs-btn-active-bg: var(--hd-fg-2); + --bs-btn-active-border-color: var(--hd-fg-2); + --bs-btn-active-color: var(--hd-fg-inverse); + } + + .alert-success { + color: var(--hd-success); + border-color: var(--hd-accent-border); + } + .alert-danger { + color: var(--hd-danger); + border-color: var(--hd-diff-del-line); + } + .alert-warning { + color: var(--hd-warning); + border-color: rgba(251, 191, 36, 0.4); + } + .alert-info { + color: var(--hd-info); + border-color: rgba(56, 189, 248, 0.35); + } +} + +// Code styling +code, +.hd-code { + font-family: var(--hd-font-mono); + background: var(--hd-bg-subtle); + border: 1px solid var(--hd-border-1); + border-radius: var(--hd-radius-xs); + padding: 0.1em 0.35em; + color: var(--hd-fg-1); +} + +// Focus visibility — system-wide +:focus-visible { + outline: none; + box-shadow: var(--hd-shadow-focus); +} + +// Brand-dark surface — hero blocks, inverse cards, marketing slabs, quote panels +.hd-brand-dark-surface { + background-color: var(--hd-brand-dark); + color: var(--hd-brand-dark-fg); + + // Eyebrows, labels, secondary copy inside a plum surface + .hd-muted, + .text-muted, + small { + color: var(--hd-brand-dark-muted) !important; + } + + // Dividers within the surface + hr, + .hd-divider { + border-color: var(--hd-brand-dark-border); + opacity: 1; + } + + // Green CTA on plum background — the accent sings here + .btn-primary, + .btn-success, + .btn-accent { + --bs-btn-bg: var(--hd-accent); + --bs-btn-border-color: var(--hd-accent); + --bs-btn-hover-bg: var(--hd-accent-hover); + --bs-btn-hover-border-color: var(--hd-accent-hover); + --bs-btn-color: var(--hd-accent-fg); + --bs-btn-hover-color: var(--hd-accent-fg); + } + + &:hover { + background-color: var(--hd-brand-dark-hover); + } +} + +// Subtle plum callout — quote blocks, testimonials, light-page accents +.hd-brand-subtle-surface { + background-color: var(--hd-brand-dark-subtle); + border: 1px solid #{$hd-plum-100}; + border-radius: var(--hd-radius-md); + + .hd-eyebrow, + .hd-label { + color: #{$hd-plum-500}; + } + + h2, + h3, + h4 { + color: #{$hd-plum-800}; + } + + p, + .hd-body { + color: #{$hd-plum-600}; + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// 8. BRAND TYPOGRAPHY UTILITIES (parity with colors_and_type.css) +// ───────────────────────────────────────────────────────────────────────────── + +.hd-display { + font-family: var(--hd-font-brand); + font-weight: 700; + line-height: 1.2; + letter-spacing: -0.02em; +} +.hd-h1 { + font-family: var(--hd-font-ui); + font-size: 2.25rem; + font-weight: 700; + line-height: 1.2; + letter-spacing: -0.02em; + color: var(--hd-fg-1); +} +.hd-h2 { + font-family: var(--hd-font-ui); + font-size: 1.875rem; + font-weight: 600; + line-height: 1.2; + color: var(--hd-fg-1); +} +.hd-h3 { + font-family: var(--hd-font-ui); + font-size: 1.5rem; + font-weight: 600; + line-height: 1.375; + color: var(--hd-fg-1); +} +.hd-body { + font-family: var(--hd-font-ui); + font-size: 0.9375rem; + line-height: 1.625; + color: var(--hd-fg-2); +} +.hd-small { + font-family: var(--hd-font-ui); + font-size: 0.8125rem; + line-height: 1.5; + color: var(--hd-fg-3); +} +.hd-label { + font-family: var(--hd-font-ui); + font-size: 0.6875rem; + font-weight: 500; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--hd-fg-3); +} +.hd-mono { + font-family: var(--hd-font-mono); + font-size: 0.8125rem; + line-height: 1.625; + color: var(--hd-fg-2); +} + +// ───────────────────────────────────────────────────────────────────────────── +// 9. DNS DIFF UTILITIES — happyDomain-specific +// ───────────────────────────────────────────────────────────────────────────── + +.hd-diff-add { + background: var(--hd-diff-add-bg); + border-left: 3px solid var(--hd-diff-add); + color: var(--hd-diff-add); +} +.hd-diff-del { + background: var(--hd-diff-del-bg); + border-left: 3px solid var(--hd-diff-del); + color: var(--hd-diff-del); +} +.hd-diff-mod { + background: var(--hd-diff-mod-bg); + border-left: 3px solid var(--hd-diff-mod); + color: var(--hd-diff-mod); +} + +// Plum text-bg helper (Bootstrap doesn't generate this for custom theme colors) +.text-bg-plum { + color: color-contrast($hd-plum-500) !important; + background-color: $hd-plum-500 !important; +} + +// DNS record-type chip (e.g. A, AAAA, MX, TXT, CNAME) +.hd-record-type { + display: inline-block; + font-family: var(--hd-font-mono); + font-size: 0.6875rem; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; + padding: 0.15em 0.45em; + border-radius: var(--hd-radius-sm); + background: var(--hd-bg-inset); + color: var(--hd-fg-2); + border: 1px solid var(--hd-border-1); +} diff --git a/config.yml b/config.yml index 01d22d6..3434441 100644 --- a/config.yml +++ b/config.yml @@ -153,6 +153,29 @@ menu: url: "https://blog.happydomain.org/" weight: 30 +module: + mounts: + - source: content + target: content + - source: static + target: static + - source: layouts + target: layouts + - source: data + target: data + - source: assets + target: assets + - source: i18n + target: i18n + - source: archetypes + target: archetypes + - source: node_modules/@fontsource-variable/hanken-grotesk + target: static/fonts/hanken-grotesk + - source: node_modules/@fontsource-variable/jetbrains-mono + target: static/fonts/jetbrains-mono + - source: node_modules/@fontsource-variable/quicksand + target: static/fonts/quicksand + markup: goldmark: renderer: diff --git a/i18n/en.yaml b/i18n/en.yaml index d7d9bf6..0a6a43a 100644 --- a/i18n/en.yaml +++ b/i18n/en.yaml @@ -1,6 +1,6 @@ - id: slogan translation: | - All your domains. One interface. + All your domains. One interface. - id: lead translation: "is a free web interface that brings all your domain names together in one simple space." diff --git a/i18n/fr.yaml b/i18n/fr.yaml index a0547ed..3aa8b2d 100644 --- a/i18n/fr.yaml +++ b/i18n/fr.yaml @@ -1,6 +1,6 @@ - id: slogan translation: | - Tous vos domaines. Une interface. + Tous vos domaines. Une interface. - id: lead translation: "est une interface web libre qui rassemble tous vos noms de domaine dans un endroit simple." diff --git a/layouts/_default/single.html b/layouts/_default/single.html index 111d4b8..6c95ec5 100644 --- a/layouts/_default/single.html +++ b/layouts/_default/single.html @@ -1,51 +1,39 @@ - + + {{ partial "head.html" . }} - {{ partial "head.html" . }} + +
+ {{ partial "nav.html" . }} {{ partial "breadcrumbs.html" . }} - +
+ {{ if isset .Params "id" }} {{ partial .Params.id . }} {{ else + }} -
+
+ {{ if .Params.toc }} + + {{ end }} - {{ partial "nav.html" . }} - - {{ partial "breadcrumbs.html" . }} - -
- {{ if isset .Params "id" }} - - {{ partial .Params.id . }} - - {{ else }} - -
- - {{ if .Params.toc }} - - {{ end }} - -
- {{ .Content }} -
+
{{ .Content }}
+
+ + {{ end }} +
+
- + - {{ end }} -
- - -
- - - {{ partial "footer.html" . }} - - {{ partial "scripts.html" . }} - - + {{ partial "footer.html" . }} {{ partial "scripts.html" . }} + diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 0caf396..389a012 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -49,15 +49,21 @@ - - + + + + - - {{ if and (isset .Site.Params "style") .Site.Params.style }} - - {{ else }} - + + {{ $scss := resources.Get "scss/bootstrap.scss" }} + {{ $opts := dict "transpiler" "libsass" "includePaths" (slice "node_modules") }} + {{ $css := $scss | css.Sass $opts }} + {{ if hugo.IsProduction }} + {{ $css = $css | minify | fingerprint }} {{ end }} + + + diff --git a/layouts/partials/nav.html b/layouts/partials/nav.html index 1bf1bb3..f082153 100644 --- a/layouts/partials/nav.html +++ b/layouts/partials/nav.html @@ -3,7 +3,11 @@ id="mainnav" >
- + + div { - color: #f8f9fa; + color: var(--hd-accent-fg); } .anchor { @@ -89,7 +69,7 @@ a.card:hover { } .carousel { - background-color: #430c59; + background-color: var(--hd-plum-700); } .text-hilight { @@ -104,13 +84,13 @@ a.card:hover { bottom: 5vh; right: 5vw; border-radius: 5px; - background-color: #9332bbee; + background-color: color-mix(in srgb, var(--hd-plum-400) 93%, transparent); z-index: 1023; max-width: 98%; } #voxppl a:hover { text-decoration: none; - background-color: #9332bb; + background-color: var(--hd-plum-400); } img { @@ -118,23 +98,22 @@ img { } #features .card { - background-color: white; + background-color: var(--hd-bg-canvas); border-radius: 10px; padding-top: 3px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05); transition: transform 0.3s; - border-top: 4px solid var(--primary); + border-top: 4px solid var(--hd-accent); } #features .col:nth-child(even) .card { - border-top: 4px solid var(--secondary); + border-top: 4px solid var(--hd-brand-dark); } #features .card:hover { transform: translateY(-10px); } - #discover .steps { display: flex; justify-content: space-between; @@ -144,13 +123,17 @@ img { } #discover .steps::before { - content: ''; + content: ""; position: absolute; top: 25px; left: 10%; width: 80%; height: 2px; - background: linear-gradient(to right, var(--primary) 0%, var(--secondary) 100%); + background: linear-gradient( + to right, + var(--hd-accent) 0%, + var(--hd-brand-dark) 100% + ); z-index: 1; } @@ -162,7 +145,11 @@ img { } #discover .step-number { - background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%); + background: linear-gradient( + 135deg, + var(--hd-accent) 0%, + var(--hd-brand-dark) 100% + ); color: white; width: 50px; height: 50px; @@ -181,20 +168,25 @@ img { } #discover .step p { - color: var(--gray); + color: var(--hd-fg-3); } #cta { padding: 100px 0; - background: linear-gradient(135deg, var(--secondary) 0%, var(--primary) 100%); + background: linear-gradient( + 135deg, + var(--hd-brand-dark) 0%, + var(--hd-accent) 100% + ); color: white; text-align: center; position: relative; overflow: hidden; } -#cta::before, #cta::after { - content: ''; +#cta::before, +#cta::after { + content: ""; position: absolute; width: 300px; height: 300px; @@ -224,7 +216,7 @@ img { } footer { - border-top: 3px solid #9332bb; + border-top: 3px solid var(--hd-plum-400); } .footer-links { @@ -250,17 +242,40 @@ footer { animation: floatinghouse 6s linear infinite; } @keyframes floatinghouse { - 0% { top: 0; left: 0; } - 10% { top: -2px; } - 20% { top: -4px; } - 30% { top: -6px; } - 40% { top: -2px; } - 50% { top: 0px; } - 60% { top: 4px; } - 70% { top: 6px; } - 80% { top: 8px; } - 90% { top: 4px; } - 100% { top: 0; } + 0% { + top: 0; + left: 0; + } + 10% { + top: -2px; + } + 20% { + top: -4px; + } + 30% { + top: -6px; + } + 40% { + top: -2px; + } + 50% { + top: 0px; + } + 60% { + top: 4px; + } + 70% { + top: 6px; + } + 80% { + top: 8px; + } + 90% { + top: 4px; + } + 100% { + top: 0; + } } @media (min-width: 768px) { @@ -268,6 +283,6 @@ footer { width: 50% !important; } #community > div > div:first-child { - border-right: 1px solid #9332bb; + border-right: 1px solid var(--hd-plum-400); } } diff --git a/static/fonts/Montserrat.woff2 b/static/fonts/Montserrat.woff2 deleted file mode 100644 index 70788c2732074a4a752cb2e0410d49fb1b067cc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19172 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