/*! ******************************************** Bocken Theme for webtrees Nord color palette with dark/light mode Based on ArgonLight by jchue / Evan Galli ************************************************/ @use "sass:map"; @use "sass:color"; @import "bootstrap/scss/functions"; @import "config/theme-variables"; @import "config/bootstrap-overrides"; @import "bootstrap/scss/bootstrap"; // ============================================================================ // CSS CUSTOM PROPERTIES — COLOR SYSTEM // Mirrors the homepage app.css approach // ============================================================================ :root { // Nord palette references --nord0: #{$nord0}; --nord1: #{$nord1}; --nord2: #{$nord2}; --nord3: #{$nord3}; --nord4: #{$nord4}; --nord5: #{$nord5}; --nord6: #{$nord6}; --nord7: #{$nord7}; --nord8: #{$nord8}; --nord9: #{$nord9}; --nord10: #{$nord10}; --nord11: #{$nord11}; --nord12: #{$nord12}; --nord13: #{$nord13}; --nord14: #{$nord14}; --nord15: #{$nord15}; // Semantic colors — light mode defaults --color-primary: var(--nord10); --color-primary-hover: var(--nord9); --color-accent: var(--nord11); --color-bg-primary: #f8f6f1; --color-bg-secondary: #efecea; --color-bg-tertiary: #e8e5e1; --color-bg-elevated: #dfdcd8; --color-surface: #efecea; --color-surface-hover: #e8e5e1; --color-text-primary: #2a2a2a; --color-text-secondary: #555; --color-text-tertiary: #777; --color-text-inverse: white; --color-text-on-primary: white; --color-text-muted: #aaa; --color-border: #ddd; --color-border-hover: #bbb; --color-link: var(--nord10); --color-link-visited: var(--nord15); --color-link-hover: var(--nord9); // Header glass bar tokens — dark bar by default --nav-bg: rgba(46, 52, 64, 0.82); --nav-border: rgba(255,255,255,0.08); --nav-shadow: rgba(0,0,0,0.25); --nav-text: #999; --nav-text-hover: white; --nav-text-active: white; --nav-hover-bg: rgba(255,255,255,0.1); --nav-active-bg: rgba(136, 192, 208, 0.25); --nav-btn-border: rgba(255,255,255,0.2); --nav-btn-border-hover: rgba(255,255,255,0.4); --nav-divider: rgba(255,255,255,0.15); // Sex colors --sex-m-bg: #{color.scale($m-color, $lightness: 90%)}; --sex-f-bg: #{color.scale($f-color, $lightness: 90%)}; --sex-u-bg: #{$gray-100}; --sex-x-bg: #{color.scale($x-color, $lightness: 90%)}; --sex-m-color: #{$m-color}; --sex-f-color: #{$f-color}; --sex-u-color: #{$nord3}; --sex-x-color: #{$x-color}; // Transitions --transition-fast: 100ms; --transition-normal: 200ms; } // ============================================================================ // DARK MODE // ============================================================================ // System prefers dark (no user override) @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --color-primary: var(--nord8); --color-primary-hover: var(--nord7); --color-accent: var(--nord11); --color-bg-primary: #000; --color-bg-secondary: #111; --color-bg-tertiary: #1a1a1a; --color-bg-elevated: #222; --color-surface: #1a1a1a; --color-surface-hover: #222; --color-text-primary: #e5e5e5; --color-text-secondary: #aaa; --color-text-tertiary: #888; --color-text-inverse: #111; --color-text-on-primary: #000; --color-text-muted: #555; --color-border: #333; --color-border-hover: #444; --color-link: var(--nord8); --color-link-visited: #c89fb6; --color-link-hover: var(--nord7); --nav-bg: rgba(20, 20, 20, 0.78); --nav-border: rgba(255,255,255,0.06); --sex-m-bg: #{color.scale($m-color, $lightness: -70%)}; --sex-f-bg: #{color.scale($f-color, $lightness: -70%)}; --sex-u-bg: #1a1a1a; --sex-x-bg: #{color.scale($x-color, $lightness: -70%)}; color-scheme: dark; } } // User forced dark :root[data-theme="dark"] { --color-primary: var(--nord8); --color-primary-hover: var(--nord7); --color-accent: var(--nord11); --color-bg-primary: #000; --color-bg-secondary: #111; --color-bg-tertiary: #1a1a1a; --color-bg-elevated: #222; --color-surface: #1a1a1a; --color-surface-hover: #222; --color-text-primary: #e5e5e5; --color-text-secondary: #aaa; --color-text-tertiary: #888; --color-text-inverse: #111; --color-text-on-primary: #000; --color-text-muted: #555; --color-border: #333; --color-border-hover: #444; --color-link: var(--nord8); --color-link-visited: #c89fb6; --color-link-hover: var(--nord7); --nav-bg: rgba(20, 20, 20, 0.78); --nav-border: rgba(255,255,255,0.06); --sex-m-bg: #{color.scale($m-color, $lightness: -70%)}; --sex-f-bg: #{color.scale($f-color, $lightness: -70%)}; --sex-u-bg: #1a1a1a; --sex-x-bg: #{color.scale($x-color, $lightness: -70%)}; color-scheme: dark; } // User forced light :root[data-theme="light"] { --nav-bg: rgba(255, 255, 255, 0.82); --nav-border: rgba(0,0,0,0.08); --nav-shadow: rgba(0,0,0,0.1); --nav-text: #888; --nav-text-hover: #{$nord0}; --nav-text-active: #{$nord0}; --nav-hover-bg: rgba(0,0,0,0.06); --nav-active-bg: rgba(94, 129, 172, 0.15); --nav-btn-border: rgba(0,0,0,0.15); --nav-btn-border-hover: rgba(0,0,0,0.3); --nav-divider: rgba(0,0,0,0.12); } // System light preference (no data-theme set) @media (prefers-color-scheme: light) { :root:not([data-theme]) { --nav-bg: rgba(255, 255, 255, 0.82); --nav-border: rgba(0,0,0,0.08); --nav-shadow: rgba(0,0,0,0.1); --nav-text: #888; --nav-text-hover: #{$nord0}; --nav-text-active: #{$nord0}; --nav-hover-bg: rgba(0,0,0,0.06); --nav-active-bg: rgba(94, 129, 172, 0.15); --nav-btn-border: rgba(0,0,0,0.15); --nav-btn-border-hover: rgba(0,0,0,0.3); --nav-divider: rgba(0,0,0,0.12); } } // ============================================================================ // BASE STYLES — apply CSS custom properties // ============================================================================ body { min-width: map.get($grid-breakpoints, xs); background-color: var(--color-bg-primary) !important; color: var(--color-text-primary) !important; transition: background-color var(--transition-normal), color var(--transition-normal); } // Force background on the global wrapper too .wt-global { background-color: var(--color-bg-primary) !important; } p { font-weight: $font-weight-light; } .wt-footers { text-align: center; } @media (min-width: 1200px) { .container { max-width: 75vw; } } .markdown p { white-space: pre-wrap; } caption { caption-side: top; padding-top: 0; } .dt-layout-table>div { overflow-x: auto; } .dt-column-order { margin: 0 $icon-link-gap; } // ============================================================================ // LINKS — Nord colored // ============================================================================ a { color: var(--color-link); transition: color var(--transition-fast); &:hover, &:focus-visible { color: var(--color-link-hover); } &:visited { color: var(--color-link-visited); } } // ============================================================================ // TABLES // ============================================================================ [dir] table, [dir] .table, [dir] table.table.dataTable { @extend .table; @extend .table-bordered; font-size: $font-size-sm; color: var(--color-text-primary); thead, tfoot, th { background-color: var(--color-bg-secondary); color: var(--color-text-primary); } thead th { @extend .text-uppercase; } td, th { border-color: var(--color-border); &:not(:first-of-type) { border-left: none; } &:not(:last-of-type) { border-right: none; } } table, .table { margin: 0; td, th { border: none; } } &.table-sm { td, th { padding: $table-cell-padding-y-sm $table-cell-padding-x-sm; } } } input[type=text] { @extend .form-control; background-color: var(--color-bg-primary); color: var(--color-text-primary); border-color: var(--color-border); } .alert a { color: inherit; } // Login .hideShowPassword-wrapper { display: flex !important; @extend .input-group; .hideShowPassword-toggle { @extend .btn; @extend .btn-secondary; position: initial !important; margin-top: 0 !important; } } select { @extend .form-select; background-color: var(--color-bg-primary); color: var(--color-text-primary); border-color: var(--color-border); } .select2-container { .input-group>& { flex-basis: 0; flex-grow: 1; flex-shrink: 1; } .select2-selection--single { @extend .form-control; align-items: center; border: $input-border-width solid var(--color-border); height: auto; display: flex; background-color: var(--color-bg-primary); color: var(--color-text-primary); .select2-selection__rendered { color: var(--color-text-primary); flex-grow: 1; } .select2-selection__arrow { flex-basis: content; position: static; b { left: auto; } } } } .select2-dropdown { border: none; box-shadow: $dropdown-box-shadow; background-color: var(--color-bg-elevated); .select2-search__field { @extend .form-control; padding: $input-padding-y $input-padding-x; background-color: var(--color-bg-primary); color: var(--color-text-primary); &:focus { border-color: $input-focus-border-color; } } .select2-results { ul.select2-results__options { margin-bottom: 1rem; li:not(.loading-results):not([role=alert]) { @extend .dropdown-item; color: var(--color-text-primary); } li.select2-results__option--highlighted { background-color: var(--color-surface-hover); } li[aria-selected=true] { background-color: $dropdown-link-active-bg; } } } } .select2-selection, .select2-container { .gallery { margin-right: 1rem; } } [dir] .table-sm { td, th, thead th, tbody th, tbody td { font-size: $font-size-xs; } } [dir] .table-bordered { td, th, thead th, tbody th, tbody td { border-right: $table-border-width solid var(--color-border); } } // Sorting indicators .sorting, .sorting_asc, .sorting_desc { background-clip: padding-box; cursor: pointer; position: relative; &::before, &::after { bottom: 1.2rem; display: block; position: absolute; .table-sm & { bottom: 0.9rem; } } &::before { content: "\2191"; } &::after { content: "\2193"; } } [dir="ltr"] .sorting, [dir="ltr"] .sorting_asc, [dir="ltr"] .sorting_desc { &::before { right: 0.85em; } &::after { right: 0.5em; } } [dir="rtl"] .sorting, [dir="rtl"] .sorting_asc, [dir="rtl"] .sorting_desc { &::before { left: 0.85em; } &::after { left: 0.5em; } } .sorting { &::before, &::after { opacity: 0.3; } i { padding: 0 0.313rem; vertical-align: -0.094rem; } } .sorting_asc { &::before { opacity: 1; } &::after { opacity: 0.3; } } .sorting_desc { &::before { opacity: 0.3; } &::after { opacity: 1; } } // ============================================================================ // ICONS // ============================================================================ [dir] .accordion-header { .wt-icon-collapse, .wt-icon-expand { display: none; } .accordion-button { &:focus { box-shadow: none; } &:not(.collapsed) { &, &:focus { border-color: var(--color-border); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .125); } } } } [dir] .wt-ajax-load:empty { height: 2rem; &::before { content: ''; position: absolute; left: 50%; @extend .spinner-border; } } .wt-footer-powered-by-webtrees { content: url("../img/webtrees.svg"); } .icon-minus { content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512' width='14' height='24'%3E%3Cpath fill='%23212529' d='M108 284c-6.6 0-12-5.4-12-12v-32c0-6.6 5.4-12 12-12h232c6.6 0 12 5.4 12 12v32c0 6.6-5.4 12-12 12H108zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-48 346V86c0-3.3-2.7-6-6-6H54c-3.3 0-6 2.7-6 6v340c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z' class=''%3E%3C/path%3E%3C/svg%3E"); vertical-align: middle; } .icon-plus { content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512' width='14' height='24'%3E%3Cpath fill='%23212529' d='M352 240v32c0 6.6-5.4 12-12 12h-88v88c0 6.6-5.4 12-12 12h-32c-6.6 0-12-5.4-12-12v-88h-88c-6.6 0-12-5.4-12-12v-32c0-6.6 5.4-12 12-12h88v-88c0-6.6 5.4-12 12-12h32c6.6 0 12 5.4 12 12v88h88c6.6 0 12 5.4 12 12zm96-160v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-48 346V86c0-3.3-2.7-6-6-6H54c-3.3 0-6 2.7-6 6v340c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z' class=''%3E%3C/path%3E%3C/svg%3E"); vertical-align: middle; } .icon-mypage { content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512' width='32' height='24'%3E%3Cpath fill='%23212529' d='M528 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h480c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-352 96c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zm112 236.8c0 10.6-10 19.2-22.4 19.2H86.4C74 384 64 375.4 64 364.8v-19.2c0-31.8 30.1-57.6 67.2-57.6h5c12.3 5.1 25.7 8 39.8 8s27.6-2.9 39.8-8h5c37.1 0 67.2 25.8 67.2 57.6v19.2zM512 312c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16zm0-64c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16zm0-64c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16z'%3E%3C/path%3E%3C/svg%3E"); } .icon-pedigree { content: url("../img/icon-pedigree.svg"); } .icon-children { content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='15' height='15' fill='%234C566A'%3E%3Cpath d='M13,2V10H21A8,8 0 0,0 13,2M19.32,15.89C20.37,14.54 21,12.84 21,11H6.44L5.5,9H2V11H4.22C4.22,11 6.11,15.07 6.34,15.42C5.24,16 4.5,17.17 4.5,18.5A3.5,3.5 0 0,0 8,22C9.76,22 11.22,20.7 11.46,19H13.54C13.78,20.7 15.24,22 17,22A3.5,3.5 0 0,0 20.5,18.5C20.5,17.46 20.04,16.53 19.32,15.89M8,20A1.5,1.5 0 0,1 6.5,18.5A1.5,1.5 0 0,1 8,17A1.5,1.5 0 0,1 9.5,18.5A1.5,1.5 0 0,1 8,20M17,20A1.5,1.5 0 0,1 15.5,18.5A1.5,1.5 0 0,1 17,17A1.5,1.5 0 0,1 18.5,18.5A1.5,1.5 0 0,1 17,20Z'%3E%3C/path%3E%3C/svg%3E"); } .icon-indis { content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512' width='24' height='27'%3E%3Cpath fill='%23212529' d='M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z'%3E%3C/path%3E%3C/svg%3E"); } .icon-user_add { content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 512' width='34' height='27'%3E%3Cpath fill='%23212529' d='M624 208h-64v-64c0-8.8-7.2-16-16-16h-32c-8.8 0-16 7.2-16 16v64h-64c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h64v64c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16v-64h64c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16zm-400 48c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z'%3E%3C/path%3E%3C/svg%3E"); } .icon-edit_indi { content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512' width='13.125' height='15'%3E%3Cpath fill='%23212529' d='M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z'%3E%3C/path%3E%3C/svg%3E"); } // Silhouettes .icon-silhouette { mask-size: contain; mask-position: center; mask-repeat: no-repeat; display: block; width: 40px; height: 50px; mask-image: url("../img/silhouette-unknown.svg"); background-color: #888; &.icon-silhouette-m { mask-image: url("../img/silhouette-man.svg"); background-color: $nord9; } &.icon-silhouette-f { mask-image: url("../img/silhouette-woman.svg"); background-color: $nord11; } } .wt-individual-silhouette { content: url("../img/silhouette-unknown.svg"); filter: contrast(5%); &.wt-individual-silhouette-m { content: url("../img/silhouette-man.svg"); } &.wt-individual-silhouette-f { content: url("../img/silhouette-woman.svg"); } } // MIME icons .wt-mime { background: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 503.467 503.467'%3E%3Cpath d='M465.067 123.733v341.333c0 18.773-15.36 34.133-34.133 34.133h-358.4c-18.773 0-34.133-15.36-34.133-34.133V38.4c0-18.773 15.36-34.133 34.133-34.133H345.6V89.6c0 18.773 15.36 34.133 34.133 34.133h85.334z' fill='%23f2edda'/%3E%3Cpath d='M465.067 123.733h-85.333c-18.773 0-34.133-15.36-34.133-34.133V4.267l119.466 119.466z' fill='%23ffd0a1'/%3E%3C/svg%3E"); display: inline-block; height: 3rem; width: 3rem; } // ============================================================================ // BUTTONS // ============================================================================ @each $color, $value in $theme-colors { [dir] .btn-#{$color} { --bs-btn-hover-bg: #{color.adjust($value, $lightness: 5%)}; } } [dir] .btn-link { padding: 0; font-weight: $font-weight-bold; } .btn:not(:last-child) { margin-right: 0.5rem; } .btn-outline-secondary { --#{$prefix}btn-color: var(--color-text-secondary); --#{$prefix}btn-hover-color: var(--color-text-secondary); --#{$prefix}btn-active-color: var(--color-text-secondary); --#{$prefix}btn-disabled-color: var(--color-text-secondary); } .btn-text { --bs-btn-box-shadow: none; } a:hover, .btn-link:hover, .nav-link:hover { color: rgba(var(--#{$prefix}link-color-rgb), var(--#{$prefix}link-opacity, 1)); } .btn-text[data-bs-toggle="collapse"] { vertical-align: baseline; } // ============================================================================ // CARDS — dark mode aware // ============================================================================ .card { border-color: var(--color-border); background-color: var(--color-surface); color: var(--color-text-primary); .card-header { background-color: var(--color-bg-secondary); color: var(--color-text-primary); font-weight: $font-weight-bold; border-bottom-color: var(--color-border); &[id^=name-header-] { font-size: $font-size-lg; } } .card-body { background-color: var(--color-surface); color: var(--color-text-primary); } } @each $color, $value in $theme-colors { .badge.bg-#{$color} { @extend .text-bg-#{$color}; } } // ============================================================================ // HEADER — Floating Glass Bar // Matches the homepage Header.svelte design // ============================================================================ // Kill the default webtrees/bootstrap header completely [dir] body > header { background: transparent !important; box-shadow: none !important; padding: 0 !important; z-index: 1052; position: sticky; top: 0; } // Remove container constraints [dir] .wt-header-container { padding: 12px 0.75rem 0 !important; margin: 0 auto !important; max-width: none !important; } // The glass pill — override Bootstrap .row completely [dir] .wt-header-content { // Kill Bootstrap .row grid behavior --bs-gutter-x: 0 !important; --bs-gutter-y: 0 !important; // Single-line flexbox pill display: flex !important; flex-wrap: nowrap !important; flex-direction: row !important; align-items: center !important; gap: 0.4rem; padding: 0 0.8rem !important; margin: 0 auto !important; width: fit-content; max-width: calc(100% - 1.5rem); height: 3rem; overflow: visible; // Glass morphism border-radius: 100px; background: var(--nav-bg); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); border: 1px solid var(--nav-border); box-shadow: 0 4px 24px var(--nav-shadow); transition: background var(--transition-normal), border-color var(--transition-normal); // Kill Bootstrap .col sizing on all direct children & > * { flex: 0 0 auto !important; width: auto !important; max-width: none !important; padding: 0 !important; } } // Force all nav sections to always be visible (kill any collapse/hide behavior) [dir] .wt-primary-navigation, [dir] .wt-secondary-navigation { display: flex !important; visibility: visible !important; opacity: 1 !important; } // Force nav lists to always be flex row visible .wt-genealogy-menu, .wt-user-menu { display: flex !important; flex-direction: row !important; flex-wrap: nowrap !important; visibility: visible !important; } // Hide elements we replace [dir] .wt-site-title { display: none !important; } [dir] .wt-site-logo { display: none !important; } // Hide the webtrees theme switcher (we have our own) .wt-secondary-navigation .menu-theme { display: none !important; } // Accessibility links — keep functional but hidden .wt-accessibility-links { position: fixed !important; } // Logo injected via JS .bocken-logo-container { order: 0; flex-shrink: 0; display: flex; align-items: center; margin-right: 0.4rem; } .bocken-logo-link { display: flex; align-items: center; text-decoration: none !important; // Dark mode hover: light blue (nord8) &:hover .bocken-logo svg { --fill: #{$nord8} !important; } } // Light mode logo hover: dark blue (nord10) :root[data-theme="light"] .bocken-logo-link:hover .bocken-logo svg { --fill: #{$nord10} !important; } @media (prefers-color-scheme: light) { :root:not([data-theme]) .bocken-logo-link:hover .bocken-logo svg { --fill: #{$nord10} !important; } } .bocken-logo { height: 28px; width: auto; display: flex; align-items: center; svg { height: 28px; width: auto; } } // Separator between primary and secondary nav .bocken-nav-spacer { min-width: 1px !important; width: 1px !important; height: 18px; background: var(--nav-divider); margin: 0 0.2rem; flex-shrink: 0 !important; order: 2 !important; } // Primary Navigation [dir] .wt-primary-navigation { order: 1 !important; flex-grow: 0 !important; .menu-tree .nav-link::before { background-image: url("../img/home-solid.svg"); } .menu-chart .nav-link::before { background-image: url("../img/project-diagram-solid.svg"); } .menu-list .nav-link::before, .menu-fancy-treeview .nav-link::before { background-image: url("../img/list-alt-regular.svg"); } .menu-calendar .nav-link::before { background-image: url("../img/calendar-alt-solid.svg"); } .menu-report .nav-link::before { background-image: url("../img/scroll-solid.svg"); } .menu-search .nav-link::before { background-image: url("../img/search-solid.svg"); } .menu-story .nav-link::before { background-image: url("../img/book-solid.svg"); } .menu-faq .nav-link::before { background-image: url("../img/comments-solid.svg"); } .menu-clippings .nav-link::before { background-image: url("../img/shopping-cart-solid.svg"); } .jp-main-menu-manual .nav-link::before { background-image: url("../img/question-circle-solid.svg"); } } // Secondary Navigation [dir] .wt-secondary-navigation { order: 3 !important; flex-grow: 0 !important; .menu-pending .nav-link::before { background-image: url("../img/shield-alt-solid.svg"); } .menu-mymenu .nav-link::before { background-image: url("../img/user-solid.svg"); } .menu-language .nav-link::before { background-image: url("../img/language-solid.svg"); } .menu-logout .nav-link::before { background-image: url("../img/sign-out-alt-solid.svg"); } .menu-login .nav-link::before { background-image: url("../img/sign-in-alt-solid.svg"); } } // Hide header search (redundant — Search dropdown exists in primary nav) [dir] .wt-header-search { display: none !important; } // Language button: show only 2-letter code (set via JS), never an icon // Styled with round border like the theme toggle (matching homepage ThemeToggle.svelte) .wt-header-content .nav > .nav-item.menu-language > .nav-link { &::before { display: none !important; } // Always show the 2-letter code, even on mobile (override font-size:0) font-size: 0.8rem !important; font-weight: 600; letter-spacing: 0.04em; border: 1px solid var(--nav-btn-border) !important; border-radius: 100px !important; padding: 0.3em 0.5em !important; line-height: 1 !important; transition: all 150ms; &:hover { border-color: var(--nav-btn-border-hover) !important; background: var(--nav-hover-bg) !important; } } // Search form on the start page (injected via JS) .bocken-page-search { max-width: 500px; margin: 0 auto 2rem; .bocken-search-form { display: flex; gap: 0; } .bocken-search-input { flex: 1; padding: 0.6rem 1rem; border: 1px solid var(--color-border); border-radius: 100px 0 0 100px; background: var(--color-surface); color: var(--color-text-primary); font-size: 0.95rem; outline: none; transition: border-color var(--transition-fast); &::placeholder { color: var(--color-text-muted); } &:focus { border-color: var(--color-primary); } } .bocken-search-btn { padding: 0.6rem 1.2rem; border: 1px solid var(--color-border); border-left: 0; border-radius: 0 100px 100px 0; background: var(--color-primary); color: var(--color-text-on-primary); cursor: pointer; transition: background var(--transition-fast); display: flex; align-items: center; &:hover { background: var(--color-primary-hover); } } } // All nav links inside the header — glass bar style .wt-header-content .nav { flex-direction: row !important; flex-wrap: nowrap !important; align-items: center; gap: 0.25rem; } .wt-header-content .nav > .nav-item { display: flex; align-items: center; } .wt-header-content .nav > .nav-item > .nav-link { display: flex; align-items: center; gap: 0.35rem; font-size: 0.8rem; font-family: "Open Sans", Helvetica, sans-serif; font-weight: 400; letter-spacing: 0; transition: all 150ms; color: var(--nav-text) !important; padding: 0.35rem 0.65rem; border-radius: 100px; white-space: nowrap; text-decoration: none; line-height: 1; &:hover { color: var(--nav-text-hover) !important; background: var(--nav-hover-bg); text-decoration: none; } &::before { content: ""; display: block; flex-shrink: 0; width: 1em; height: 1em; background-repeat: no-repeat; background-position: center; background-size: contain; filter: brightness(0) invert(0.6); } // Hide dropdown carets everywhere &.dropdown-toggle::after { display: none !important; } .caret { display: none !important; } // On small screens: icon-only (hide text, show ::before icon) @include media-breakpoint-down(lg) { font-size: 0 !important; padding: 0.45rem !important; &::before { font-size: 0.85rem !important; display: block !important; width: 1.15em; height: 1.15em; } } } // Active nav item highlighting (matching homepage Header.svelte) .wt-header-content .nav > .nav-item.bocken-nav-active > .nav-link { color: var(--nav-text-active) !important; background: var(--nav-active-bg); } // Per-menu icon tint colors for active state (Nord palette, via CSS filter on SVG background icons) // Filters computed with SPSA solver to approximate each Nord color from black .wt-header-content .nav > .nav-item.bocken-nav-active { // nord8 #88C0D0 — home, faq &.menu-tree > .nav-link::before, &.menu-faq > .nav-link::before { filter: brightness(0) saturate(100%) invert(79%) sepia(99%) saturate(1387%) hue-rotate(166deg) brightness(91%) contrast(77%); } // nord14 #A3BE8C — charts &.menu-chart > .nav-link::before { filter: brightness(0) saturate(100%) invert(77%) sepia(20%) saturate(460%) hue-rotate(50deg) brightness(91%) contrast(89%); } // nord7 #8FBCBB — lists &.menu-list > .nav-link::before { filter: brightness(0) saturate(100%) invert(78%) sepia(9%) saturate(884%) hue-rotate(124deg) brightness(94%) contrast(83%); } // nord13 #EBCB8B — calendar &.menu-calendar > .nav-link::before { filter: brightness(0) saturate(100%) invert(79%) sepia(27%) saturate(532%) hue-rotate(0deg) brightness(103%) contrast(85%); } // nord15 #B48EAD — reports &.menu-report > .nav-link::before { filter: brightness(0) saturate(100%) invert(56%) sepia(18%) saturate(501%) hue-rotate(258deg) brightness(106%) contrast(81%); } // nord10 #5E81AC — search &.menu-search > .nav-link::before { filter: brightness(0) saturate(100%) invert(49%) sepia(11%) saturate(1396%) hue-rotate(172deg) brightness(97%) contrast(92%); } // nord12 #D08770 — stories &.menu-story > .nav-link::before { filter: brightness(0) saturate(100%) invert(53%) sepia(60%) saturate(329%) hue-rotate(329deg) brightness(100%) contrast(86%); } // nord11 #BF616A — clippings &.menu-clippings > .nav-link::before { filter: brightness(0) saturate(100%) invert(49%) sepia(27%) saturate(822%) hue-rotate(305deg) brightness(88%) contrast(98%); } } // Dropdown menus within the glass bar .wt-header-content .dropdown-menu { background-color: var(--color-bg-elevated); border: 1px solid var(--color-border); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); border-radius: 0.75rem; box-shadow: 0 8px 32px rgba(0,0,0,0.2); padding: 0.5rem; .dropdown-item { color: var(--color-text-primary); border-radius: 0.5rem; padding: 0.4rem 0.75rem; font-size: 0.8rem; &:hover, &:focus { background-color: var(--nav-hover-bg); color: var(--nav-text-hover); } &.active { background-color: var(--nav-active-bg); color: var(--nav-text-active); } } } // Mobile responsive header @media screen and (max-width: 800px) { [dir] .wt-header-content { gap: 0.25rem; padding: 0.4rem 0.6rem !important; max-width: calc(100% - 1rem); } } // ============================================================================ // THEME TOGGLE BUTTON // ============================================================================ .bocken-theme-toggle-item { display: flex; align-items: center; } .bocken-theme-btn { display: flex !important; align-items: center !important; justify-content: center !important; width: 28px !important; height: 28px !important; padding: 0 !important; border-radius: 100px !important; background: transparent !important; color: var(--nav-text) !important; cursor: pointer; transition: all 150ms; border: 1px solid var(--nav-btn-border) !important; &:hover { color: var(--nav-text-hover) !important; border-color: var(--nav-btn-border-hover) !important; background: var(--nav-hover-bg) !important; } svg, i { width: 14px; height: 14px; stroke-width: 2; } } // ============================================================================ // MAIN CONTENT // ============================================================================ .wt-main-container { @extend .container; margin-top: 2rem; } .wt-page-title { color: var(--color-text-primary) !important; } // ============================================================================ // FOOTER // ============================================================================ #site-footer { background-color: var(--color-bg-secondary); color: var(--color-text-secondary); font-size: $font-size-sm; padding: 2.5rem 0; text-align: center; } // ============================================================================ // BOOTSTRAP OVERRIDES — dark mode aware // ============================================================================ .dropdown-menu { z-index: 2000; background-color: var(--color-bg-elevated); border-color: var(--color-border); color: var(--color-text-primary); } .dropdown-header { color: var(--color-text-tertiary); } [dir] .dropdown-item { color: var(--color-text-primary); &:hover, &:focus { background-color: var(--color-surface-hover); color: var(--color-text-primary); } &.active:hover { background-color: var(--#{$prefix}dropdown-link-active-bg); color: var(--#{$prefix}dropdown-link-active-color); } } .modal { z-index: 1052; } .modal-content { background-color: var(--color-surface); color: var(--color-text-primary); border-color: var(--color-border); } .modal-header { align-items: center; border-bottom-color: var(--color-border); } .modal-footer { border-top-color: var(--color-border); } .list-group { a.list-group-item { border-right: none; border-left: none; border-radius: 0; font-size: $font-size-sm; background-color: var(--color-surface); color: var(--color-text-primary); border-color: var(--color-border); } } .tab-content { padding-top: 0.5rem; } .d-flex.justify-content-between { align-items: center; } // Pagination .pagination { margin-bottom: 0; gap: 5px; .page-link { border-radius: var(--#{$prefix}pagination-border-radius); width: 36px; height: 36px; background-color: var(--color-surface); color: var(--color-text-primary); border-color: var(--color-border); &.first, &[data-dt-idx="first"], &.previous, &[data-dt-idx="previous"], &.next, &[data-dt-idx="next"], &.last, &[data-dt-idx="last"] { visibility: hidden; &::after { @extend .page-link; visibility: visible; position: absolute; inset: 0; display: block; width: 36px; height: 36px; padding-right: 0; padding-left: 0; border-radius: 50%; color: var(--color-text-secondary); font-weight: bold; text-align: center; line-height: 1.6rem; } } &.first::after, &[data-dt-idx="first"]::after { content: "\00AB"; } &.previous::after, &[data-dt-idx="previous"]::after { content: "\2039"; } &.next::after, &[data-dt-idx="next"]::after { content: "\203A"; } &.last::after, &[data-dt-idx="last"]::after { content: "\00BB"; } } } // ============================================================================ // WEBTREES-SPECIFIC // ============================================================================ .starredname { text-decoration: underline; } // Calendar modals div[id^=caldiv] { border-radius: $dropdown-border-radius; box-shadow: $dropdown-box-shadow; padding: 1.25rem 1.375rem; background-color: var(--color-surface); table { border: none !important; } td, tbody td { border-bottom: none; } input, select { @extend .form-control-sm; } tr:first-child td { border-top: none; } table table { margin-top: 0.5rem; td { font-size: .875rem; height: 36px; text-align: center; } tr:not(:first-child) { td { background-color: transparent !important; border: none !important; border-radius: 50%; padding: 3px; transition: all .15s ease; width: 36px; a { color: var(--color-text-tertiary); } &.descriptionbox { background-color: $primary !important; a { color: $white; } } } } tr:first-child td, tr:not(:first-child) td.optionbox { color: var(--color-text-primary); a { color: var(--color-text-primary); } } } } // Sex classes — use CSS variables for dark mode .wt-sex-m { background-color: var(--sex-m-bg); } .wt-sex-f { background-color: var(--sex-f-bg); } .wt-sex-u { background-color: var(--sex-u-bg); } .wt-sex-x { background-color: var(--sex-x-bg); } .wt-icon-sex-m { color: var(--sex-m-color); } .wt-icon-sex-f { color: var(--sex-f-color); } .wt-icon-sex-u { color: var(--sex-u-color); } .wt-icon-sex-x { color: var(--sex-x-color); } // Change indicators [dir] .wt-new, [dir] .wt-old { outline-style: solid; outline-width: 2px; outline-offset: -2px; padding: 5px; th { padding-left: 2.5rem; } th::before { font-size: 1.5rem; font-weight: bold; float: left; margin-left: -1.5rem; margin-top: -0.6rem; } &.wt-new th::before { content: "+"; } &.wt-old th::before { content: "-"; } @each $class in wt-new, wt-old { $color: map.get((wt-new: $nord8, wt-old: $nord12), $class); &.#{$class} { outline-color: $color; th { background-color: color.mix(white, $color, 80%); &::before { color: $color; } } td { background-color: color.mix(white, $color, 90%); } } } } .label { font-weight: $font-weight-bold; } .indent { padding-left: 1rem; } .wt-osk { box-shadow: $box-shadow; display: none; position: fixed; top: 1rem; z-index: 1000; } // Maps .wt-places-tab-wrapper { border-radius: $border-radius; box-shadow: $box-shadow-sm; } .wt-places-tab-wrapper, .wt-place-hierarchy-wrapper, .wt-pedigree-map-wrapper { height: 70vh; &>[class^=col-], .wt-map, .wt-map-sidebar { @include media-breakpoint-up(sm) { height: 100%; } @include media-breakpoint-down(sm) { height: 50%; } } .wt-map-sidebar { padding: 0; overflow-y: auto; li.gchart { border-bottom: $border-width solid var(--color-border); font-size: $font-size-sm !important; padding: 1.5rem; .tab-pane & { font-size: $font-size-xs !important; padding: 1rem; } &:hover { cursor: pointer; } &.messagebox { background-color: var(--color-bg-secondary); } >div { margin-bottom: 0.625rem; } } } } .leaflet-popup { font-family: $font-family-base; font-size: $font-size-xs; a { color: $link-color; &:hover { color: $link-hover-color; } } .leaflet-popup-content-wrapper { border-radius: $border-radius; padding: 0.75rem 1rem; .leaflet-popup-content { margin: 0; div { margin-bottom: 0.5rem; } } } } // Map clusters .marker-cluster-small { background-color: rgba(163, 190, 140, .5); div { background-color: rgba(163, 190, 140, .8); } } .marker-cluster-medium { background-color: rgba(235, 203, 139, .5); div { background-color: rgba(235, 203, 139, .8); } } .marker-cluster-large { background-color: rgba(208, 135, 112, .5); div { background-color: rgba(208, 135, 112, .8); } } .marker-cluster { background-clip: padding-box; border-radius: 20px; div { width: 30px; height: 30px; margin-left: 5px; margin-top: 5px; text-align: center; border-radius: 15px; font-size: 12px; } span { line-height: 30px; } } .leaflet-cluster-anim { .leaflet-marker-icon, .leaflet-marker-shadow { transition: transform 0.3s ease-out, opacity 0.3s ease-in; } } .leaflet-cluster-spider-leg { transition: stroke-dashoffset 0.3s ease-out, stroke-opacity 0.3s ease-in; } // Individual page [dir] .img-thumbnail { text-align: center; } .wt-family-navigator-family .wt-family-navigator-label+td { background-color: inherit; } .wt-chart-box-zoom-dropdown { font-size: $font-size-sm; div[class^=fact_] { padding: 0.5rem 1rem; } } // Interactive tree .tv_out { align-items: center; background-color: var(--color-bg-primary); border-radius: $border-radius; box-shadow: $box-shadow-sm; display: flex; height: 50vh; justify-content: center; min-height: 25vh; max-height: 95vh; overflow: hidden; position: relative; resize: vertical; } // ============================================================================ // DARK MODE — deeper overrides for elements that don't use variables // ============================================================================ @mixin dark-mode-deep { // Bootstrap components that need dark overrides .form-control, .form-select { background-color: var(--color-bg-tertiary); color: var(--color-text-primary); border-color: var(--color-border); &:focus { background-color: var(--color-bg-elevated); color: var(--color-text-primary); border-color: var(--color-primary); } } .input-group-text { background-color: var(--color-bg-elevated); color: var(--color-text-primary); border-color: var(--color-border); } .table { --bs-table-bg: transparent; --bs-table-color: var(--color-text-primary); --bs-table-border-color: var(--color-border); color: var(--color-text-primary); } .table-bordered { border-color: var(--color-border); } .accordion-item { background-color: var(--color-surface); border-color: var(--color-border); color: var(--color-text-primary); } .accordion-button { background-color: var(--color-bg-secondary); color: var(--color-text-primary); &:not(.collapsed) { background-color: var(--color-bg-tertiary); color: var(--color-text-primary); } } .breadcrumb { --bs-breadcrumb-divider-color: var(--color-text-muted); } .breadcrumb-item { color: var(--color-text-secondary); a { color: var(--color-link); } &.active { color: var(--color-text-primary); } } .nav-tabs { border-bottom-color: var(--color-border); .nav-link { color: var(--color-text-secondary); &:hover { border-color: var(--color-border); } &.active { background-color: var(--color-surface); border-color: var(--color-border); color: var(--color-text-primary); } } } .nav-pills .nav-link.active { background-color: var(--color-primary); color: var(--color-text-on-primary); } // Block headers .wt-block-header { color: var(--color-text-primary); border-bottom-color: var(--color-border); } // Nav icon filters for dark mode .wt-header-content .nav > .nav-item > .nav-link::before { filter: brightness(0) invert(0.7); } // Icon brightness .icon-minus, .icon-plus, .icon-indis, .icon-user_add, .icon-edit_indi, .icon-mypage { filter: invert(0.8); } // Ensure dark popups .popover { --bs-popover-bg: var(--color-bg-elevated); --bs-popover-body-color: var(--color-text-primary); --bs-popover-border-color: var(--color-border); } .toast { --bs-toast-bg: var(--color-bg-elevated); --bs-toast-color: var(--color-text-primary); --bs-toast-border-color: var(--color-border); } hr { border-color: var(--color-border); opacity: 1; } // Webtrees-specific dark overrides .optionbox, .descriptionbox { background-color: var(--color-surface); color: var(--color-text-primary); } img { opacity: 0.92; } } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { @include dark-mode-deep; } } :root[data-theme="dark"] { @include dark-mode-deep; } // ============================================================================ // PRINT // ============================================================================ @media print { body { background-color: white !important; color: black !important; } }