pagetop/assets/css/basic.css
Manuel Cillero c47724bb68 ✨ (base): Implementa Navbar con funcionalidad base
Añade `Navbar::with_position()` y `navbar::Position` al núcleo, con las
clases de Basic para barras fijas y pegajosas, y `navbar::Item::form()`
para mostrar un formulario dentro de la barra.

Las barras sin botón de despliegue (`Simple` y `SimpleBrandLeft`) ya no
colapsan: el punto de corte no les afecta y su menú se mantiene en
línea, con salto de línea si no cabe. En Bootsier usan `navbar-expand` y
`SimpleBrandLeft` agrupa los contenidos junto a la marca.
2026-09-21 16:27:44 +02:00

1259 lines
31 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

:root {
/* Font families */
--val-font-sans: system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif;
--val-font-serif: Georgia,"Times New Roman",serif;
--val-font-monospace: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;
--val-font-family: var(--val-font-sans);
/* Font size */
--val-fs--base: 1rem;
/* Font weight */
--val-fw--base: 400;
/* Line height */
--val-lh--base: 1.5;
/* Core Colors */
--val-color--primary: #0d6efd;
--val-color--secondary: #6c757d;
--val-color--success: #198754;
--val-color--info: #0dcaf0;
--val-color--warning: #ffc107;
--val-color--danger: #dc3545;
/* Other Colors */
--val-color--bg: #fafafa;
--val-color--bg--muted: #dee2e6;
--val-color--text: #212529;
--val-color--text--muted: color-mix(in srgb, var(--val-color--text) 50%, var(--val-color--bg));
--val-color--switch-off: #adb5bd;
--val-color--border: #212529;
}
*, *::before, *::after {
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
font-family: var(--val-font-family);
font-size: var(--val-fs--base);
font-weight: var(--val-fw--base);
line-height: var(--val-lh--base);
color: var(--val-color--text);
background-color: var(--val-color--bg);
-webkit-tap-highlight-color: transparent;
}
/* Header, Aside, Content and Footer are stacked in that order, using the full available width. */
.wrapper {
display: flex;
flex-direction: column;
}
/*
* Badge component
*/
.badge {
display: inline-block;
padding: 0.3em 0.6em;
font-size: 0.8125rem;
font-weight: 600;
line-height: 1;
color: #fff;
background-color: var(--val-color--secondary);
border-radius: 0.375rem;
white-space: nowrap;
}
.badge-info,
.badge-warning {
color: #000;
}
.badge-primary { background-color: var(--val-color--primary); }
.badge-neutral { background-color: var(--val-color--secondary); }
.badge-success { background-color: var(--val-color--success); }
.badge-info { background-color: var(--val-color--info); }
.badge-warning { background-color: var(--val-color--warning); }
.badge-severe { background-color: var(--val-color--danger); }
/*
* Brand component
*/
.brand {
display: inline-flex;
align-items: center;
gap: 0.5rem;
color: var(--val-color--text);
font-size: 1.75rem;
font-weight: 600;
text-decoration: none;
}
.brand .image {
display: flex;
}
/*
* Breadcrumb component
*/
.breadcrumb {
display: flex;
flex-wrap: wrap;
list-style: none;
margin: 0 0 1rem;
padding: 0.75rem 1rem;
font-size: 0.875rem;
}
.breadcrumb-item + .breadcrumb-item {
padding-left: 0.5rem;
}
.breadcrumb-item + .breadcrumb-item::before {
float: left;
padding-right: 0.5rem;
color: var(--val-color--text--muted);
content: "/";
}
.breadcrumb-item.active {
color: var(--val-color--text--muted);
}
.breadcrumb-item a {
color: var(--val-color--text);
text-decoration: none;
}
.breadcrumb-item a:hover {
text-decoration: underline;
}
/* Base geometry of .dropdown-button/.dropdown-toggle (see "Dropdown component" below). It is
* declared here, before "Buttons", so that the .button-sm/.button-lg/.button-* classes win the
* specificity tie against it when combined on the same element (CSS resolves a tie by order of
* appearance in the file, not by the order of the classes in the HTML). */
.dropdown-button,
.dropdown-toggle {
padding: 0.5rem 0.75rem;
font: inherit;
color: var(--val-color--text);
background-color: transparent;
border: 1px solid var(--val-color--border);
border-radius: 0.375rem;
cursor: pointer;
}
/*
* Buttons
*/
.button {
display: inline-block;
padding: 0.5rem 1.25rem;
font-size: var(--val-fs--base);
font-weight: 600;
line-height: var(--val-lh--base);
color: #fff;
background-color: var(--val-color--primary);
border: 1px solid var(--val-color--primary);
border-radius: 0.375rem;
text-decoration: none;
cursor: pointer;
transition: background-color .15s ease-in-out, border-color .15s ease-in-out;
}
.button:hover {
background-color: color-mix(in srgb, var(--val-color--primary) 85%, black);
border-color: color-mix(in srgb, var(--val-color--primary) 85%, black);
}
.button:disabled {
opacity: 0.65;
cursor: default;
}
.button::-moz-focus-inner {
border: 0;
}
.button-sm {
padding: 0.25rem 0.75rem;
font-size: 0.875rem;
}
.button-lg {
padding: 0.75rem 1.5rem;
font-size: 1.25rem;
}
.button-primary,
.button-neutral,
.button-success,
.button-severe {
color: #fff;
}
.button-info,
.button-warning {
color: #000;
}
.button-primary { background-color: var(--val-color--primary); border-color: var(--val-color--primary); }
.button-neutral { background-color: var(--val-color--secondary); border-color: var(--val-color--secondary); }
.button-success { background-color: var(--val-color--success); border-color: var(--val-color--success); }
.button-info { background-color: var(--val-color--info); border-color: var(--val-color--info); }
.button-warning { background-color: var(--val-color--warning); border-color: var(--val-color--warning); }
.button-severe { background-color: var(--val-color--danger); border-color: var(--val-color--danger); }
.button-primary:hover { background-color: color-mix(in srgb, var(--val-color--primary) 85%, black); border-color: color-mix(in srgb, var(--val-color--primary) 85%, black); }
.button-neutral:hover { background-color: color-mix(in srgb, var(--val-color--secondary) 85%, black); border-color: color-mix(in srgb, var(--val-color--secondary) 85%, black); }
.button-success:hover { background-color: color-mix(in srgb, var(--val-color--success) 85%, black); border-color: color-mix(in srgb, var(--val-color--success) 85%, black); }
.button-info:hover { background-color: color-mix(in srgb, var(--val-color--info) 85%, black); border-color: color-mix(in srgb, var(--val-color--info) 85%, black); }
.button-warning:hover { background-color: color-mix(in srgb, var(--val-color--warning) 85%, black); border-color: color-mix(in srgb, var(--val-color--warning) 85%, black); }
.button-severe:hover { background-color: color-mix(in srgb, var(--val-color--danger) 85%, black); border-color: color-mix(in srgb, var(--val-color--danger) 85%, black); }
.button-outline-primary,
.button-outline-neutral,
.button-outline-success,
.button-outline-info,
.button-outline-warning,
.button-outline-severe {
background-color: transparent;
}
.button-outline-primary { border-color: var(--val-color--primary); color: var(--val-color--primary); }
.button-outline-neutral { border-color: var(--val-color--secondary); color: var(--val-color--secondary); }
.button-outline-success { border-color: var(--val-color--success); color: var(--val-color--success); }
.button-outline-info { border-color: var(--val-color--info); color: var(--val-color--info); }
.button-outline-warning { border-color: var(--val-color--warning); color: var(--val-color--warning); }
.button-outline-severe { border-color: var(--val-color--danger); color: var(--val-color--danger); }
.button-outline-primary:hover { background-color: var(--val-color--primary); border-color: var(--val-color--primary); color: #fff; }
.button-outline-neutral:hover { background-color: var(--val-color--secondary); border-color: var(--val-color--secondary); color: #fff; }
.button-outline-success:hover { background-color: var(--val-color--success); border-color: var(--val-color--success); color: #fff; }
.button-outline-info:hover { background-color: var(--val-color--info); border-color: var(--val-color--info); color: #000; }
.button-outline-warning:hover { background-color: var(--val-color--warning); border-color: var(--val-color--warning); color: #000; }
.button-outline-severe:hover { background-color: var(--val-color--danger); border-color: var(--val-color--danger); color: #fff; }
.button-link {
font-weight: 400;
color: var(--val-color--primary);
background-color: transparent;
border-color: transparent;
text-decoration: underline;
}
.button-link:hover {
color: color-mix(in srgb, var(--val-color--primary) 85%, black);
background-color: transparent;
border-color: transparent;
}
.button-link:disabled {
color: var(--val-color--text--muted);
}
.button-set {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
/*
* Container component
*/
/* Classes added by the `Container` component from `Width`. All of them are centered and fill the
* available width; `.container` and `.container-{name}` also get a maximum width from the
* breakpoint they name (`.container` from the first one). The minimum widths match the default
* `Theme::breakpoint_entry()` table, so a child theme that renames or resizes the breakpoints must
* also redefine these classes. */
.container,
.container-fluid,
.container-sm,
.container-md,
.container-lg,
.container-xl,
.container-xxl,
.container-xxxl {
width: 100%;
margin-inline: auto;
padding-inline: 1rem;
}
@media (width >= 576px) {
.container,
.container-sm {
max-width: 540px;
}
}
@media (width >= 768px) {
.container,
.container-sm,
.container-md {
max-width: 720px;
}
}
@media (width >= 992px) {
.container,
.container-sm,
.container-md,
.container-lg {
max-width: 960px;
}
}
@media (width >= 1200px) {
.container,
.container-sm,
.container-md,
.container-lg,
.container-xl {
max-width: 1140px;
}
}
@media (width >= 1400px) {
.container,
.container-sm,
.container-md,
.container-lg,
.container-xl,
.container-xxl {
max-width: 1320px;
}
}
@media (width >= 1920px) {
.container,
.container-sm,
.container-md,
.container-lg,
.container-xl,
.container-xxl,
.container-xxxl {
max-width: 1800px;
}
}
/*
* Dialog component
*/
.dialog {
padding: 0;
width: 100%;
max-width: 32rem;
color: var(--val-color--text);
background-color: var(--val-color--bg);
border: none;
border-radius: 0.5rem;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
}
.dialog::backdrop {
background-color: rgba(0, 0, 0, 0.5);
}
.dialog-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
padding: 1rem 1.25rem;
border-bottom: 1px solid color-mix(in srgb, var(--val-color--border) 15%, var(--val-color--bg));
}
.dialog-title {
margin: 0;
font-size: 1.125rem;
font-weight: 600;
}
.dialog-close {
width: 1.5rem;
height: 1.5rem;
padding: 0;
line-height: 1;
color: var(--val-color--text--muted);
background-color: transparent;
border: none;
cursor: pointer;
}
.dialog-close::before {
content: "\2715";
}
.dialog-close:hover {
color: var(--val-color--text);
}
.dialog-body {
padding: 1.25rem;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
gap: 0.5rem;
padding: 1rem 1.25rem;
border-top: 1px solid color-mix(in srgb, var(--val-color--border) 15%, var(--val-color--bg));
}
/*
* Dropdown component
*/
.dropdown {
position: relative;
display: inline-block;
}
/* The base geometry of .dropdown-button/.dropdown-toggle lives next to "Buttons" (before this
* section), so that the .button-sm/.button-lg/.button-* classes win the specificity tie against it
* (CSS resolves a tie by order of appearance in the file, not by the order of the classes in the
* HTML). */
.dropdown-toggle::after {
content: "\25BC";
display: inline-block;
margin-left: 0.35em;
font-size: 0.8em;
transition: transform .15s ease-in-out;
}
.dropdown:has(> .dropdown-menu.show) > .dropdown-toggle::after {
transform: rotate(180deg);
}
.dropdown-menu {
position: absolute;
z-index: 1000;
top: 100%;
left: 0;
min-width: 12rem;
margin: 0.25rem 0 0;
padding: 0.5rem 0;
list-style: none;
background-color: var(--val-color--bg);
border: 1px solid color-mix(in srgb, var(--val-color--border) 15%, var(--val-color--bg));
border-radius: 0.375rem;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
/* Closed by default */
display: none;
}
.dropdown-menu.show {
display: block;
}
/* Options and headers stay on one line, so the menu grows to fit the longest one. */
.dropdown-item {
display: block;
width: 100%;
padding: 0.375rem 1rem;
text-align: left;
white-space: nowrap;
color: var(--val-color--text);
text-decoration: none;
background-color: transparent;
border: none;
font: inherit;
cursor: pointer;
}
.dropdown-item:hover {
background-color: color-mix(in srgb, var(--val-color--text) 8%, transparent);
}
.dropdown-item.active {
color: var(--val-color--primary);
font-weight: 600;
}
.dropdown-item.disabled {
color: var(--val-color--text--muted);
pointer-events: none;
}
.dropdown-item-text {
display: block;
padding: 0.375rem 1rem;
color: var(--val-color--text--muted);
}
.dropdown-header {
display: block;
padding: 0.5rem 1rem 0.25rem;
margin: 0;
white-space: nowrap;
font-size: 0.8125rem;
font-weight: 600;
color: var(--val-color--text--muted);
}
.dropdown-divider {
height: 0;
margin: 0.5rem 0;
border: none;
border-top: 1px solid var(--val-color--border);
}
/* Utility: visually hidden but still accessible to assistive technology */
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/*
* Form components
*/
.form-required {
color: var(--val-color--danger);
margin-left: 0.25rem;
}
.form-label {
display: block;
margin-top: 1em;
}
.form-text {
font-size: 0.9375rem;
color: var(--val-color--text--muted);
}
.form-field > select.form-select,
.form-field > input.form-control,
.form-field > input.form-range,
.form-field > textarea.form-control {
display: block;
padding: 0.25rem 0.5rem;
width: 100%;
}
fieldset {
margin: 2rem 0 1rem;
background: var(--val-color--bg);
}
fieldset > legend {
background-color: var(--val-color--bg);
border: 2px groove threedface;
padding: 0 0.5em;
}
.form-check {
display: flex;
align-items: center;
gap: 0.5rem;
min-height: 1.5rem;
margin-bottom: 0.25rem;
}
.form-check-inline {
display: inline-flex;
margin-right: 1rem;
}
.form-check-reverse {
flex-direction: row-reverse;
justify-content: flex-start;
text-align: right;
}
.form-check-input {
flex-shrink: 0;
cursor: pointer;
}
.form-check-label {
cursor: pointer;
}
.form-switch .form-check-input {
appearance: none;
-webkit-appearance: none;
width: 2em;
height: 1em;
background-color: var(--val-color--switch-off);
border-radius: 1em;
position: relative;
cursor: pointer;
transition: background-color .15s ease-in-out;
}
.form-switch .form-check-input::after {
content: "";
position: absolute;
width: 1em;
height: 1em;
background-color: white;
border-radius: 50%;
top: 0;
left: 0;
transition: transform .15s ease-in-out;
box-shadow: 0 0 0 1px rgba(0, 0, 0, .25);
}
.form-switch .form-check-input:checked {
background-color: var(--val-color--primary);
}
.form-switch .form-check-input:checked::after {
transform: translateX(1em);
}
input:disabled,
input:disabled + label {
cursor: default !important;
}
input:disabled + label {
color: var(--val-color--text--muted);
}
.form-field > select.form-select,
.form-field > input.form-control,
.form-field > textarea.form-control {
border: 1px solid var(--val-color--border);
border-radius: 0.375rem;
background-color: #fff;
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
.form-field > select.form-select:focus,
.form-field > input.form-control:focus,
.form-field > textarea.form-control:focus {
outline: none;
border-color: var(--val-color--primary);
box-shadow: 0 0 0 0.2rem color-mix(in srgb, var(--val-color--primary) 25%, transparent);
}
/*
* Image component
*/
.image {
vertical-align: middle;
}
.image-fluid {
max-width: 100%;
height: auto;
}
.image-thumbnail {
max-width: 100%;
height: auto;
padding: 0.25rem;
background-color: var(--val-color--bg);
border: 1px solid var(--val-color--border);
border-radius: 0.375rem;
}
/*
* Messages component
*/
.message {
padding: 0.75rem 1rem;
margin-bottom: 1rem;
border: 1px solid transparent;
border-radius: 0.375rem;
}
.message-info {
color: color-mix(in srgb, var(--val-color--info) 40%, black);
background-color: color-mix(in srgb, var(--val-color--info) 15%, var(--val-color--bg));
border-color: color-mix(in srgb, var(--val-color--info) 40%, var(--val-color--bg));
}
.message-warning {
color: color-mix(in srgb, var(--val-color--warning) 40%, black);
background-color: color-mix(in srgb, var(--val-color--warning) 15%, var(--val-color--bg));
border-color: color-mix(in srgb, var(--val-color--warning) 40%, var(--val-color--bg));
}
.message-error {
color: color-mix(in srgb, var(--val-color--danger) 40%, black);
background-color: color-mix(in srgb, var(--val-color--danger) 15%, var(--val-color--bg));
border-color: color-mix(in srgb, var(--val-color--danger) 40%, var(--val-color--bg));
}
/*
* Nav component
*/
.nav {
display: flex;
align-items: center;
gap: 0.25rem;
list-style: none;
margin: 0;
padding: 0;
}
.nav-item {
position: relative;
}
.nav-link {
display: block;
padding: 0.5rem 0.75rem;
color: var(--val-color--text);
text-decoration: none;
border-radius: 0.375rem;
}
.nav-link:hover {
background-color: color-mix(in srgb, var(--val-color--text) 8%, transparent);
}
.nav-link.active {
color: var(--val-color--primary);
font-weight: 600;
}
.nav-link.disabled {
color: var(--val-color--text--muted);
pointer-events: none;
}
/* The toggle of a dropdown inside a `Nav` looks like the other links: it drops the border that a
* standalone `Dropdown` toggle has (see "Dropdown component"). */
.nav-link.dropdown-toggle {
width: 100%;
text-align: start;
border: 0;
}
.nav-start {
justify-content: flex-start;
}
.nav-center {
justify-content: center;
}
.nav-end {
justify-content: flex-end;
}
.nav-vertical {
flex-direction: column;
align-items: stretch;
}
.nav-fill > .nav-item {
flex: 1 1 auto;
text-align: center;
}
.nav-justified > .nav-item {
flex-basis: 0;
flex-grow: 1;
text-align: center;
}
/*
* Navbar component
*/
.navbar {
display: flex;
align-items: center;
gap: 1rem;
padding: 0.5rem 1rem;
}
.navbar-toggle {
display: none;
padding: 0.25rem 0.5rem;
font-size: 1.25rem;
line-height: 1;
color: inherit;
background-color: transparent;
border: 1px solid var(--val-color--border);
border-radius: 0.375rem;
cursor: pointer;
}
.navbar-toggle::before {
content: "\2630";
}
/* Pushes the toggle (`BrandLeft`) or the brand (`BrandRight`) to the far end of the bar. */
.brand ~ .navbar-toggle,
.navbar-toggle ~ .brand {
margin-inline-start: auto;
}
.navbar-content {
display: flex;
align-items: center;
gap: 1rem;
flex: 1 1 auto;
}
/* A bar without a toggle button never stacks its `.nav` items in a column, so they wrap onto
* another line when they don't fit instead of overflowing the bar. */
.navbar-content .nav {
flex-wrap: wrap;
}
.navbar-text {
color: var(--val-color--text--muted);
}
/*
* Navbar position, from the `navbar::Position` classes. `.navbar` has no background of its own, so
* a bar taken out of the flow (fixed) or pinned while scrolling (sticky) gets one, or the content
* passing underneath would show through.
*/
.navbar.fixed-top,
.navbar.fixed-bottom,
.navbar.sticky-top,
.navbar.sticky-bottom {
background-color: var(--val-color--bg);
}
.navbar.fixed-top,
.navbar.fixed-bottom {
position: fixed;
right: 0;
left: 0;
z-index: 1030;
}
.navbar.fixed-top {
top: 0;
}
.navbar.fixed-bottom {
bottom: 0;
}
.navbar.sticky-top,
.navbar.sticky-bottom {
position: sticky;
z-index: 1020;
}
.navbar.sticky-top {
top: 0;
}
.navbar.sticky-bottom {
bottom: 0;
}
/*
* A navbar with a toggle button collapses below the breakpoint set by its `navbar-expand-{name}`
* class, added by the `Navbar` component. `navbar-expand` alone (a breakpoint with no minimum
* width) never collapses and needs no rules, since the base rules above are the expanded layout.
* The widths below match the default `Theme::breakpoint_entry()` table, so a child theme that
* renames or resizes the breakpoints must also redefine these classes.
*
* While collapsed, the `.nav` items are stacked in a column, so a dropdown menu inside it is laid
* out in the flow (`position: static`) to push down the following items instead of covering them.
* A navbar without a toggle button has nothing to collapse: its `.nav` items stay in a row.
*/
@media (width < 576px) {
.navbar-expand-sm {
flex-wrap: wrap;
}
.navbar-expand-sm:has(.navbar-toggle) .navbar-toggle {
display: inline-block;
}
.navbar-expand-sm:has(.navbar-toggle) .navbar-content {
order: 1;
display: none;
flex-direction: column;
align-items: stretch;
width: 100%;
}
.navbar-expand-sm:has(.navbar-toggle) .navbar-content.show {
display: flex;
}
.navbar-expand-sm:has(.navbar-toggle) .nav {
flex-direction: column;
align-items: stretch;
width: 100%;
}
.navbar-expand-sm:has(.navbar-toggle) .nav .dropdown-menu {
position: static;
box-shadow: none;
}
}
@media (width < 768px) {
.navbar-expand-md {
flex-wrap: wrap;
}
.navbar-expand-md:has(.navbar-toggle) .navbar-toggle {
display: inline-block;
}
.navbar-expand-md:has(.navbar-toggle) .navbar-content {
order: 1;
display: none;
flex-direction: column;
align-items: stretch;
width: 100%;
}
.navbar-expand-md:has(.navbar-toggle) .navbar-content.show {
display: flex;
}
.navbar-expand-md:has(.navbar-toggle) .nav {
flex-direction: column;
align-items: stretch;
width: 100%;
}
.navbar-expand-md:has(.navbar-toggle) .nav .dropdown-menu {
position: static;
box-shadow: none;
}
}
@media (width < 992px) {
.navbar-expand-lg {
flex-wrap: wrap;
}
.navbar-expand-lg:has(.navbar-toggle) .navbar-toggle {
display: inline-block;
}
.navbar-expand-lg:has(.navbar-toggle) .navbar-content {
order: 1;
display: none;
flex-direction: column;
align-items: stretch;
width: 100%;
}
.navbar-expand-lg:has(.navbar-toggle) .navbar-content.show {
display: flex;
}
.navbar-expand-lg:has(.navbar-toggle) .nav {
flex-direction: column;
align-items: stretch;
width: 100%;
}
.navbar-expand-lg:has(.navbar-toggle) .nav .dropdown-menu {
position: static;
box-shadow: none;
}
}
@media (width < 1200px) {
.navbar-expand-xl {
flex-wrap: wrap;
}
.navbar-expand-xl:has(.navbar-toggle) .navbar-toggle {
display: inline-block;
}
.navbar-expand-xl:has(.navbar-toggle) .navbar-content {
order: 1;
display: none;
flex-direction: column;
align-items: stretch;
width: 100%;
}
.navbar-expand-xl:has(.navbar-toggle) .navbar-content.show {
display: flex;
}
.navbar-expand-xl:has(.navbar-toggle) .nav {
flex-direction: column;
align-items: stretch;
width: 100%;
}
.navbar-expand-xl:has(.navbar-toggle) .nav .dropdown-menu {
position: static;
box-shadow: none;
}
}
@media (width < 1400px) {
.navbar-expand-xxl {
flex-wrap: wrap;
}
.navbar-expand-xxl:has(.navbar-toggle) .navbar-toggle {
display: inline-block;
}
.navbar-expand-xxl:has(.navbar-toggle) .navbar-content {
order: 1;
display: none;
flex-direction: column;
align-items: stretch;
width: 100%;
}
.navbar-expand-xxl:has(.navbar-toggle) .navbar-content.show {
display: flex;
}
.navbar-expand-xxl:has(.navbar-toggle) .nav {
flex-direction: column;
align-items: stretch;
width: 100%;
}
.navbar-expand-xxl:has(.navbar-toggle) .nav .dropdown-menu {
position: static;
box-shadow: none;
}
}
@media (width < 1920px) {
.navbar-expand-xxxl {
flex-wrap: wrap;
}
.navbar-expand-xxxl:has(.navbar-toggle) .navbar-toggle {
display: inline-block;
}
.navbar-expand-xxxl:has(.navbar-toggle) .navbar-content {
order: 1;
display: none;
flex-direction: column;
align-items: stretch;
width: 100%;
}
.navbar-expand-xxxl:has(.navbar-toggle) .navbar-content.show {
display: flex;
}
.navbar-expand-xxxl:has(.navbar-toggle) .nav {
flex-direction: column;
align-items: stretch;
width: 100%;
}
.navbar-expand-xxxl:has(.navbar-toggle) .nav .dropdown-menu {
position: static;
box-shadow: none;
}
}
/*
* Pager component
*/
.pager {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 1rem;
margin: 1rem 0;
padding: 0 1rem;
}
.pager-align-start {
justify-content: flex-start;
}
.pager-align-center {
justify-content: center;
}
.pager-align-end {
justify-content: flex-end;
}
.pager-summary {
color: var(--val-color--text--muted);
font-size: 0.8125rem;
align-self: flex-start;
margin-inline-end: auto;
}
.pager-align-start .pager-summary {
order: 1;
margin-inline-end: 0;
margin-inline-start: auto;
}
.pager-align-center .pager-summary {
order: 1;
flex-basis: 100%;
text-align: center;
margin-inline-end: 0;
}
.pagination {
display: flex;
align-items: center;
gap: 0.25rem;
list-style: none;
margin: 0;
padding: 0;
}
.pagination a {
display: flex;
align-items: center;
justify-content: center;
min-width: 1.5rem;
padding: 0.375rem 0.625rem;
border-radius: 0.375rem;
color: var(--val-color--text);
text-decoration: none;
}
.pagination a:hover {
background-color: color-mix(in srgb, var(--val-color--text) 8%, transparent);
}
.pagination .active a {
color: #fff;
background-color: var(--val-color--primary);
}
.pagination .disabled a {
color: var(--val-color--text--muted);
pointer-events: none;
cursor: default;
}
.page-ellipsis {
padding: 0.375rem 0.25rem;
color: var(--val-color--text--muted);
}
/* .page-link-icon shows the navigation text of the previous/next buttons. The full accessible text
goes separately, in the link's aria-label. So replacing the visible text with other content does
not affect accessibility, e.g. to use "‹"/"›" you can apply:
.page-link-icon {
display: inline-block;
font-size: 0;
}
.page-previous .page-link-icon::before {
content: "‹";
font-size: 1rem;
display: inline-block;
transform: translateY(-0.15em) scale(1.5);
}
.page-next .page-link-icon::before {
content: "›";
font-size: 1rem;
display: inline-block;
transform: translateY(-0.15em) scale(1.5);
}
*/
.pager-jump {
display: flex;
align-items: center;
}
.pager-jump:focus-within {
border-radius: 0.375rem;
box-shadow: 0 0 0 0.2rem color-mix(in srgb, var(--val-color--primary) 25%, transparent);
}
.pager-jump-input > input.form-control:focus,
.pager-jump-button:focus {
outline: none;
box-shadow: none;
}
.pager-jump-input > input.form-control {
width: calc(var(--pager-jump-width, 1ch) + 2.5rem);
padding: 0.375rem 0.625rem;
line-height: var(--val-lh--base);
border: 0;
border-start-end-radius: 0;
border-end-end-radius: 0;
background-color: var(--val-color--bg--muted);
}
.pager-jump-input > input.form-control {
text-align: center;
appearance: textfield;
-moz-appearance: textfield;
}
.pager-jump-input > input.form-control::-webkit-outer-spin-button,
.pager-jump-input > input.form-control::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.pager-jump-button {
padding: 0.375rem 0.625rem;
border: 0;
border-start-start-radius: 0;
border-end-start-radius: 0;
}
.pager-jump-button:hover {
background-color: color-mix(in srgb, var(--val-color--primary) 85%, black);
}
/*
* Table component
*/
.table-responsive {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.table {
width: 100%;
border-collapse: collapse;
text-align: left;
}
.table th,
.table td {
padding: 0.5rem 0.75rem;
border-bottom: 1px solid color-mix(in srgb, var(--val-color--border) 15%, var(--val-color--bg));
}
.table thead th {
border-bottom-width: 2px;
font-weight: 600;
}
.table-sort {
color: inherit;
text-decoration: none;
}
.table-sort:hover {
text-decoration: underline;
}
.table-sort::after {
content: "\25BC";
margin-left: 0.25rem;
font-size: 0.8em;
opacity: 0.15;
}
.table-sort-asc::after {
content: "\25B2";
font-size: 0.8em;
opacity: 1;
}
.table-sort-desc::after {
content: "\25BC";
font-size: 0.8em;
opacity: 1;
}
.table-empty {
text-align: center;
font-style: italic;
color: var(--val-color--text--muted);
}
/*
* Region Footer
*/
.region-footer {
padding: .75rem 0 3rem;
text-align: center;
}
/*
* pagetop-user: login page
*/
.user-login-page {
display: flex;
align-items: center;
justify-content: center;
min-height: 70vh;
padding: 2rem 1rem;
background: radial-gradient(
ellipse 120% 60% at 50% -10%,
color-mix(in srgb, var(--val-color--primary) 18%, var(--val-color--bg)) 0%,
var(--val-color--bg) 70%
);
}
.user-login-card {
width: 100%;
max-width: 24rem;
padding: 2rem;
background-color: #fff;
border-radius: 0.75rem;
box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.15);
}
.user-login-card .form-label {
margin-top: 1.25rem;
}
.user-login-card .button {
display: block;
width: 100%;
margin-top: 1.5rem;
}
.user-admin-table-wrapper {
margin: 1.5rem 0;
}
.user-admin-table {
font-size: 0.9375rem;
}
.user-admin-permission-list {
list-style: none;
padding-left: 0;
}
.user-admin-permission-granted {
font-weight: 600;
}
.user-admin-permission-missing {
color: var(--val-color--text--muted);
}
.user-form-error {
padding: 0.625rem 0.875rem;
margin-bottom: 1rem;
color: #fff;
background-color: var(--val-color--danger);
border-radius: 0.375rem;
font-size: 0.9375rem;
}
.user-register-link,
.user-reset-link {
margin-top: 1rem;
text-align: center;
font-size: 0.9375rem;
}