🎨 (basic): Organiza estilos de Basic e Intro
Divide `basic.css` en parciales SCSS bajo `assets/scss/basic/`, integra `normalize.css` en `basic.min.css` y compila `intro.scss` por separado a `intro.min.css`.
This commit is contained in:
parent
b5da11777a
commit
c848b97450
30 changed files with 1612 additions and 1812 deletions
1267
assets/css/basic.css
1267
assets/css/basic.css
File diff suppressed because it is too large
Load diff
|
|
@ -1,525 +0,0 @@
|
|||
:root {
|
||||
--intro-bg-img: url('/pagetop/img/intro-header.jpg');
|
||||
--intro-bg-img-set: image-set(url('/pagetop/img/intro-header.avif') type('image/avif'), url('/pagetop/img/intro-header.webp') type('image/webp'), var(--intro-bg-img) type('image/jpeg'));
|
||||
--intro-bg-img-sm: url('/pagetop/img/intro-header-sm.jpg');
|
||||
--intro-bg-img-sm-set: image-set(url('/pagetop/img/intro-header-sm.avif') type('image/avif'), url('/pagetop/img/intro-header-sm.webp') type('image/webp'), var(--intro-bg-img-sm) type('image/jpeg'));
|
||||
--intro-bg-color: #7a430e;
|
||||
--intro-bg-block-1: #ffb84b;
|
||||
--intro-bg-block-2: #ffc66f;
|
||||
--intro-bg-block-3: #ffd493;
|
||||
--intro-bg-block-4: #ffe3b7;
|
||||
--intro-bg-block-5: #fff1db;
|
||||
--intro-bg-block-6: #ffffff;
|
||||
--intro-color: #1a202c;
|
||||
--intro-color-gray: #e8e3da;
|
||||
--intro-color-link: #8b2500;
|
||||
--intro-focus-outline: 2px solid var(--intro-color-link);
|
||||
--intro-focus-outline-offset: 2px;
|
||||
--intro-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
body {
|
||||
overflow-x: clip;
|
||||
}
|
||||
|
||||
/*
|
||||
* Media queries: 768px and 992px match the default `Md` and `Lg` breakpoints of the core.
|
||||
*/
|
||||
|
||||
.intro {
|
||||
position: relative;
|
||||
color: var(--intro-color);
|
||||
background-color: var(--intro-bg-color);
|
||||
|
||||
left: 50%;
|
||||
right: 50%;
|
||||
margin-left: -50vw;
|
||||
margin-right: -50vw;
|
||||
width: 100vw;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.intro section {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/*
|
||||
* Intro Header
|
||||
*/
|
||||
|
||||
.intro-header {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
width: 100%;
|
||||
max-width: 80rem;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 4rem;
|
||||
background-image: var(--intro-bg-img-sm);
|
||||
background-image: var(--intro-bg-img-sm-set);
|
||||
background-position: top center;
|
||||
background-position-y: -1rem;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.intro-header-body {
|
||||
padding: 0;
|
||||
background: none;
|
||||
}
|
||||
.intro-header-title {
|
||||
margin: 0 0 0 1.5rem;
|
||||
text-align: left;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
color: #dceefb;
|
||||
padding: clamp(0rem, -5.4892rem + 23.4206vw, 9.5rem) 1rem 1rem;
|
||||
font-size: clamp(1.5rem, 0.7231rem + 3.3149vw, 3.375rem);
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
line-height: 110%;
|
||||
text-shadow: 0 0.125rem 0.1875rem rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.intro-header-title > span {
|
||||
background: linear-gradient(180deg, #ddff95 30%, #ffb84b 100%);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
font-size: clamp(2.25rem, 1.3177rem + 3.9779vw, 6.5rem);
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: 135%;
|
||||
text-shadow: none;
|
||||
}
|
||||
.intro-header-img {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
}
|
||||
.intro-header-mascot {
|
||||
margin: 2rem;
|
||||
flex-shrink: 1;
|
||||
width: 280px;
|
||||
height: 280px;
|
||||
}
|
||||
@media (width >= 992px) {
|
||||
.intro-header {
|
||||
background-image: var(--intro-bg-img);
|
||||
background-image: var(--intro-bg-img-set);
|
||||
}
|
||||
.intro-header-title {
|
||||
padding: 0 2rem 2.6rem 2rem;
|
||||
}
|
||||
.intro-header-img {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.intro-header-mascot {
|
||||
margin-right: 12rem;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Intro Content
|
||||
*/
|
||||
|
||||
.intro-content {
|
||||
height: auto;
|
||||
margin-top: 1.6rem;
|
||||
width: 100%;
|
||||
}
|
||||
.intro-content-body {
|
||||
box-sizing: border-box;
|
||||
max-width: 80rem;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.intro-content-body:before,
|
||||
.intro-content-body:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(130deg, rgba(13, 44, 91, 0) 0%, #ddff95 77.4%);
|
||||
margin: 0 -1.2rem;
|
||||
filter: blur(2.75rem);
|
||||
opacity: 0.8;
|
||||
inset: unset;
|
||||
}
|
||||
.intro-content-body:before {
|
||||
top: -1rem;
|
||||
}
|
||||
.intro-content-body:after {
|
||||
bottom: -1rem;
|
||||
}
|
||||
@media (width < 768px) {
|
||||
.intro-content-body {
|
||||
margin-top: -9.8rem;
|
||||
}
|
||||
}
|
||||
@media (width >= 992px) {
|
||||
.intro-content {
|
||||
margin-top: 0;
|
||||
}
|
||||
.intro-content-body {
|
||||
margin-top: -5.7rem;
|
||||
}
|
||||
.intro-content-body:before,
|
||||
.intro-content-body:after {
|
||||
inset: 11.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
.intro-button {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.intro-button-link {
|
||||
background: #7f1d1d;
|
||||
background-image: linear-gradient(to bottom, rgba(255,0,0,0.8), rgba(255,255,255,0));
|
||||
background-position: top left, center;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 0.75rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.3;
|
||||
text-decoration: none !important;
|
||||
transition: transform 0.3s ease-in-out !important;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
min-width: 28.875rem;
|
||||
min-height: 7.6875rem;
|
||||
outline: none;
|
||||
}
|
||||
.intro-button-link:focus-visible {
|
||||
outline: var(--intro-focus-outline);
|
||||
outline-offset: var(--intro-focus-outline-offset);
|
||||
}
|
||||
.intro-button-link::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -13.125rem;
|
||||
left: -10rem;
|
||||
height: 26.25rem;
|
||||
width: 26.25rem;
|
||||
background: linear-gradient(135deg, #ec7bae 50.41%, #9600b8 70.41%);
|
||||
transform: rotate(45deg);
|
||||
transition: transform 0.3s ease-in-out;
|
||||
z-index: 5;
|
||||
}
|
||||
.intro-button-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
transition: all 0.5s ease-in-out;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
padding: 1rem 1.5rem;
|
||||
text-align: left;
|
||||
color: white;
|
||||
font-size: 1.65rem;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 130.023%;
|
||||
letter-spacing: 0.0075rem;
|
||||
}
|
||||
.intro-button-text strong {
|
||||
font-size: 2.625rem;
|
||||
font-weight: 600;
|
||||
line-height: 130.023%;
|
||||
letter-spacing: 0.013125rem;
|
||||
}
|
||||
.intro-button-link span {
|
||||
position: absolute;
|
||||
display: block;
|
||||
pointer-events: none;
|
||||
}
|
||||
.intro-button-link span:nth-child(1) {
|
||||
height: 8px;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: linear-gradient(to right, rgba(0, 0, 0, 0), #f6e58d);
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
transform: translateX(-100%);
|
||||
animation: span1 8s linear infinite;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
@keyframes span1 {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
.intro-button-link span:nth-child(2) {
|
||||
width: 8px;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), #f6e58d);
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
transform: translateY(100%);
|
||||
animation: span2 4s linear infinite;
|
||||
animation-delay: 5s;
|
||||
}
|
||||
@keyframes span2 {
|
||||
0% {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
}
|
||||
.intro-button-link span:nth-child(3) {
|
||||
height: 8px;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(to left, rgba(0, 0, 0, 0), #f6e58d);
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
transform: translateX(100%);
|
||||
animation: span3 8s linear infinite;
|
||||
animation-delay: 7s;
|
||||
}
|
||||
@keyframes span3 {
|
||||
0% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
}
|
||||
.intro-button-link:hover span {
|
||||
animation-play-state: paused;
|
||||
}
|
||||
@media (width < 768px) {
|
||||
.intro-header {
|
||||
padding-bottom: 9rem;;
|
||||
}
|
||||
.intro-button-link {
|
||||
height: 6.25rem;
|
||||
min-width: auto;
|
||||
border-radius: 0;
|
||||
}
|
||||
.intro-button-text {
|
||||
display: inline;
|
||||
padding-top: .5rem;
|
||||
}
|
||||
}
|
||||
@media (width >= 768px) {
|
||||
.intro-button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
max-width: 29.375rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.intro-button-link:hover {
|
||||
transition: all .5s;
|
||||
transform: rotate(-3deg) scale(1.125);
|
||||
}
|
||||
}
|
||||
|
||||
.intro-text {
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
margin-bottom: 0;
|
||||
background: #fff;
|
||||
position: relative;
|
||||
}
|
||||
.intro-text-body {
|
||||
padding: 2.5rem 1.063rem 0.75rem;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
.intro-text-lead {
|
||||
width: 100%;
|
||||
font-size: 1.5rem;
|
||||
margin: 0 0 1.5rem;
|
||||
}
|
||||
@media (width >= 768px) {
|
||||
.intro-button + .intro-text-body {
|
||||
padding-top: 7rem;
|
||||
}
|
||||
}
|
||||
@media (width >= 992px) {
|
||||
.intro-header {
|
||||
padding-bottom: 9rem;;
|
||||
}
|
||||
.intro-text,
|
||||
.intro-text-body {
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
.intro-text {
|
||||
box-shadow: var(--intro-shadow);
|
||||
max-width: min(60rem, 100vw - 4rem);
|
||||
margin: 0 auto 6rem;
|
||||
}
|
||||
.intro-text-narrow {
|
||||
max-width: min(50rem, 100vw - 4rem);
|
||||
}
|
||||
.intro-text-wide {
|
||||
max-width: min(67rem, 100vw - 4rem);
|
||||
}
|
||||
.intro-text-full {
|
||||
max-width: min(74rem, 100vw - 4rem);
|
||||
}
|
||||
.intro-text-body {
|
||||
padding-left: 4.5rem;
|
||||
padding-right: 4.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.intro-text-body .block {
|
||||
position: relative;
|
||||
}
|
||||
.intro-text-body .block-title {
|
||||
margin: 1em 0 .8em;
|
||||
}
|
||||
.intro-text-body .block-title span {
|
||||
display: inline-block;
|
||||
padding: 10px 30px 14px;
|
||||
margin: 30px 20px 0;
|
||||
background: white;
|
||||
border: 5px solid;
|
||||
border-radius: 30px;
|
||||
box-shadow: 0 0 0 5px white, inset 0 0 0 5px white;
|
||||
border-color: orangered;
|
||||
transform: rotate(-3deg) translateY(-25%);
|
||||
}
|
||||
.intro-text-body .block-title:before {
|
||||
content: "";
|
||||
height: 5px;
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
left: -15%;
|
||||
width: 130%;
|
||||
z-index: -5;
|
||||
background: orangered;
|
||||
box-shadow: 0 0 0 5px white, 0 -10px 0 5px white;
|
||||
transform: rotate(2deg) translateY(-50%);
|
||||
transform-origin: top left;
|
||||
}
|
||||
.intro-text-body .block-title:after {
|
||||
content: "";
|
||||
height: 120%;
|
||||
position: absolute;
|
||||
top: 42px;
|
||||
left: -25%;
|
||||
width: 150%;
|
||||
z-index: -10;
|
||||
background: var(--intro-bg-block-1);
|
||||
transform: rotate(2deg);
|
||||
}
|
||||
.intro-text-body .block:nth-of-type(6n+1) .block-title:after {
|
||||
background: var(--intro-bg-block-1);
|
||||
}
|
||||
.intro-text-body .block:nth-of-type(6n+2) .block-title:after {
|
||||
background: var(--intro-bg-block-2);
|
||||
}
|
||||
.intro-text-body .block:nth-of-type(6n+3) .block-title:after {
|
||||
background: var(--intro-bg-block-3);
|
||||
}
|
||||
.intro-text-body .block:nth-of-type(6n+4) .block-title:after {
|
||||
background: var(--intro-bg-block-4);
|
||||
}
|
||||
.intro-text-body .block:nth-of-type(6n+5) .block-title:after {
|
||||
background: var(--intro-bg-block-5);
|
||||
}
|
||||
.intro-text-body .block:nth-of-type(6n+6) .block-title:after {
|
||||
background: var(--intro-bg-block-6);
|
||||
}
|
||||
|
||||
#intro-badges {
|
||||
min-height: 3.2rem;
|
||||
text-align: center;
|
||||
visibility: hidden;
|
||||
}
|
||||
#intro-badges img {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
#intro-release:not([src]) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* Intro Footer
|
||||
*/
|
||||
|
||||
.intro-footer {
|
||||
width: 100%;
|
||||
background-color: black;
|
||||
color: var(--intro-color-gray);
|
||||
padding-bottom: 2rem;
|
||||
}
|
||||
|
||||
.intro-footer-body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
margin: 0 auto;
|
||||
padding: 0 10.625rem;
|
||||
max-width: 80rem;
|
||||
}
|
||||
.intro-footer-body a:visited {
|
||||
color: var(--intro-color-gray);
|
||||
}
|
||||
/* The footer has its own dark surface, so its links don't inherit the theme's link colors. */
|
||||
.intro-footer-links a {
|
||||
color: currentColor;
|
||||
text-decoration: underline;
|
||||
transition: font-size 0.2s, text-decoration-color 0.2s;
|
||||
}
|
||||
.intro-footer-links a:focus-visible {
|
||||
outline: var(--intro-focus-outline);
|
||||
outline-offset: var(--intro-focus-outline-offset);
|
||||
}
|
||||
.intro-footer-links a:hover,
|
||||
.intro-footer-links a:hover:visited {
|
||||
text-decoration-color: var(--intro-color-link);
|
||||
}
|
||||
.intro-footer-logo,
|
||||
.intro-footer-links {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
.intro-footer-logo {
|
||||
max-height: 12.625rem;
|
||||
}
|
||||
.intro-footer-logo svg {
|
||||
width: 100%;
|
||||
}
|
||||
.intro-footer-links {
|
||||
gap: 1.875rem;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
@media (width < 768px) {
|
||||
.intro-footer-logo {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media (width < 992px) {
|
||||
.intro-footer-body {
|
||||
padding: 0 1rem;
|
||||
}
|
||||
}
|
||||
41
assets/scss/basic.scss
Normal file
41
assets/scss/basic.scss
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// PageTop Basic theme styles.
|
||||
//
|
||||
// Compiled by `build.rs` into `static/css/basic.min.css`. Comments written with `//` never reach
|
||||
// the compiled file, so they can be as long as needed.
|
||||
//
|
||||
// The partials are emitted in the order they are loaded here, which matters when two rules tie on
|
||||
// specificity: the later one wins.
|
||||
|
||||
// Third-party reset (normalize.css v8.0.1, MIT), copied verbatim. It goes first so that every
|
||||
// rule of the theme can override it.
|
||||
@use "basic/normalize";
|
||||
|
||||
// Custom properties and base styles.
|
||||
@use "basic/root";
|
||||
@use "basic/base";
|
||||
|
||||
// Components, in alphabetical order. `buttons` must go before `dropdown` and `nav`, see the notes
|
||||
// in `basic/_buttons.scss`.
|
||||
@use "basic/badge";
|
||||
@use "basic/brand";
|
||||
@use "basic/breadcrumb";
|
||||
@use "basic/buttons";
|
||||
@use "basic/container";
|
||||
@use "basic/dialog";
|
||||
@use "basic/dropdown";
|
||||
@use "basic/form";
|
||||
@use "basic/image";
|
||||
@use "basic/messages";
|
||||
@use "basic/nav";
|
||||
@use "basic/navbar";
|
||||
@use "basic/pager";
|
||||
@use "basic/table";
|
||||
|
||||
// Theme regions.
|
||||
@use "basic/regions";
|
||||
|
||||
// Styles for the pages of the `pagetop-user` extension.
|
||||
@use "basic/user";
|
||||
|
||||
// Utilities go last so they win over any component rule they are combined with.
|
||||
@use "basic/utilities";
|
||||
21
assets/scss/basic/_badge.scss
Normal file
21
assets/scss/basic/_badge.scss
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
.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); }
|
||||
23
assets/scss/basic/_base.scss
Normal file
23
assets/scss/basic/_base.scss
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
*, *::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;
|
||||
}
|
||||
12
assets/scss/basic/_brand.scss
Normal file
12
assets/scss/basic/_brand.scss
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
.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;
|
||||
}
|
||||
27
assets/scss/basic/_breadcrumb.scss
Normal file
27
assets/scss/basic/_breadcrumb.scss
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
.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;
|
||||
}
|
||||
25
assets/scss/basic/_breakpoints.scss
Normal file
25
assets/scss/basic/_breakpoints.scss
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Breakpoints of the Basic theme, used to generate the responsive classes of `Container` and
|
||||
// `Navbar`. They match the default `Theme::breakpoint_entry()` table (`xs` has no minimum width, so
|
||||
// it is left out), so a child theme that renames or resizes the breakpoints must also redefine the
|
||||
// classes generated from them.
|
||||
//
|
||||
// This partial emits no CSS on its own.
|
||||
|
||||
$breakpoints: (
|
||||
sm: 576px,
|
||||
md: 768px,
|
||||
lg: 992px,
|
||||
xl: 1200px,
|
||||
xxl: 1400px,
|
||||
xxxl: 1920px,
|
||||
);
|
||||
|
||||
// Maximum width of `.container` and `.container-{name}` from each breakpoint on.
|
||||
$container-max-widths: (
|
||||
sm: 540px,
|
||||
md: 720px,
|
||||
lg: 960px,
|
||||
xl: 1140px,
|
||||
xxl: 1320px,
|
||||
xxxl: 1800px,
|
||||
);
|
||||
120
assets/scss/basic/_buttons.scss
Normal file
120
assets/scss/basic/_buttons.scss
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
// Base geometry of .dropdown-button/.dropdown-toggle (the rest is in `_dropdown.scss`). It is
|
||||
// declared here, before the button classes, so that .button-sm/.button-lg/.button-* 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;
|
||||
}
|
||||
|
||||
.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,
|
||||
.button.disabled {
|
||||
opacity: 0.65;
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
.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,
|
||||
.button-link.disabled {
|
||||
color: var(--val-color--text--muted);
|
||||
}
|
||||
|
||||
.button-set {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
32
assets/scss/basic/_container.scss
Normal file
32
assets/scss/basic/_container.scss
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
@use "sass:list";
|
||||
@use "sass:map";
|
||||
@use "breakpoints" as bp;
|
||||
|
||||
// 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).
|
||||
|
||||
$named: ();
|
||||
@each $name in map.keys(bp.$breakpoints) {
|
||||
$named: list.append($named, ".container-#{$name}", comma);
|
||||
}
|
||||
|
||||
.container,
|
||||
.container-fluid,
|
||||
#{$named} {
|
||||
width: 100%;
|
||||
margin-inline: auto;
|
||||
padding-inline: 1rem;
|
||||
}
|
||||
|
||||
// From each breakpoint on, `.container` and every `.container-{name}` up to that breakpoint take
|
||||
// its maximum width, while the larger ones stay fluid until their own breakpoint is reached.
|
||||
$sized: (".container");
|
||||
@each $name, $width in bp.$breakpoints {
|
||||
$sized: list.append($sized, ".container-#{$name}", comma);
|
||||
@media (width >= $width) {
|
||||
#{$sized} {
|
||||
max-width: map.get(bp.$container-max-widths, $name);
|
||||
}
|
||||
}
|
||||
}
|
||||
57
assets/scss/basic/_dialog.scss
Normal file
57
assets/scss/basic/_dialog.scss
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
.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));
|
||||
}
|
||||
93
assets/scss/basic/_dropdown.scss
Normal file
93
assets/scss/basic/_dropdown.scss
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
.dropdown {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
// The base geometry of .dropdown-button/.dropdown-toggle lives at the top of `_buttons.scss`, which
|
||||
// is loaded before this partial, so that .button-sm/.button-lg/.button-* 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;
|
||||
}
|
||||
// Anchors the menu's right edge to the button's right edge, so it opens inwards.
|
||||
.dropdown-menu-end {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
110
assets/scss/basic/_form.scss
Normal file
110
assets/scss/basic/_form.scss
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
.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);
|
||||
}
|
||||
15
assets/scss/basic/_image.scss
Normal file
15
assets/scss/basic/_image.scss
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
.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;
|
||||
}
|
||||
24
assets/scss/basic/_messages.scss
Normal file
24
assets/scss/basic/_messages.scss
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
.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));
|
||||
}
|
||||
61
assets/scss/basic/_nav.scss
Normal file
61
assets/scss/basic/_nav.scss
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
.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 `_buttons.scss`).
|
||||
.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;
|
||||
}
|
||||
118
assets/scss/basic/_navbar.scss
Normal file
118
assets/scss/basic/_navbar.scss
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
@use "breakpoints" as bp;
|
||||
|
||||
.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.
|
||||
//
|
||||
// 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.
|
||||
@each $name, $width in bp.$breakpoints {
|
||||
@media (width < $width) {
|
||||
.navbar-expand-#{$name} {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.navbar-expand-#{$name}:has(.navbar-toggle) {
|
||||
.navbar-toggle {
|
||||
display: inline-block;
|
||||
}
|
||||
.navbar-content {
|
||||
order: 1;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
width: 100%;
|
||||
}
|
||||
.navbar-content.show {
|
||||
display: flex;
|
||||
}
|
||||
.nav {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
width: 100%;
|
||||
}
|
||||
.nav .dropdown-menu {
|
||||
position: static;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
133
assets/scss/basic/_pager.scss
Normal file
133
assets/scss/basic/_pager.scss
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
.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);
|
||||
}
|
||||
4
assets/scss/basic/_regions.scss
Normal file
4
assets/scss/basic/_regions.scss
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
.region-footer {
|
||||
padding: .75rem 0 3rem;
|
||||
text-align: center;
|
||||
}
|
||||
27
assets/scss/basic/_root.scss
Normal file
27
assets/scss/basic/_root.scss
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
: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;
|
||||
}
|
||||
51
assets/scss/basic/_table.scss
Normal file
51
assets/scss/basic/_table.scss
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
.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);
|
||||
}
|
||||
68
assets/scss/basic/_user.scss
Normal file
68
assets/scss/basic/_user.scss
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
.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;
|
||||
}
|
||||
12
assets/scss/basic/_utilities.scss
Normal file
12
assets/scss/basic/_utilities.scss
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// 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;
|
||||
}
|
||||
522
assets/scss/intro.scss
Normal file
522
assets/scss/intro.scss
Normal file
|
|
@ -0,0 +1,522 @@
|
|||
// Styles of the `Intro` component.
|
||||
//
|
||||
// Compiled by `build.rs` into `static/css/intro.min.css`, apart from `basic.scss`: the component
|
||||
// loads them on its own, whatever the active theme is.
|
||||
|
||||
:root {
|
||||
--intro-bg-img: url('/pagetop/img/intro-header.jpg');
|
||||
--intro-bg-img-set: image-set(url('/pagetop/img/intro-header.avif') type('image/avif'), url('/pagetop/img/intro-header.webp') type('image/webp'), var(--intro-bg-img) type('image/jpeg'));
|
||||
--intro-bg-img-sm: url('/pagetop/img/intro-header-sm.jpg');
|
||||
--intro-bg-img-sm-set: image-set(url('/pagetop/img/intro-header-sm.avif') type('image/avif'), url('/pagetop/img/intro-header-sm.webp') type('image/webp'), var(--intro-bg-img-sm) type('image/jpeg'));
|
||||
--intro-bg-color: #7a430e;
|
||||
--intro-bg-block-1: #ffb84b;
|
||||
--intro-bg-block-2: #ffc66f;
|
||||
--intro-bg-block-3: #ffd493;
|
||||
--intro-bg-block-4: #ffe3b7;
|
||||
--intro-bg-block-5: #fff1db;
|
||||
--intro-bg-block-6: #ffffff;
|
||||
--intro-color: #1a202c;
|
||||
--intro-color-gray: #e8e3da;
|
||||
--intro-color-link: #8b2500;
|
||||
--intro-focus-outline: 2px solid var(--intro-color-link);
|
||||
--intro-focus-outline-offset: 2px;
|
||||
--intro-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
body {
|
||||
overflow-x: clip;
|
||||
}
|
||||
|
||||
// Media queries: 768px and 992px match the default `Md` and `Lg` breakpoints of the core.
|
||||
|
||||
.intro {
|
||||
position: relative;
|
||||
color: var(--intro-color);
|
||||
background-color: var(--intro-bg-color);
|
||||
|
||||
left: 50%;
|
||||
right: 50%;
|
||||
margin-left: -50vw;
|
||||
margin-right: -50vw;
|
||||
width: 100vw;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.intro section {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
// Intro Header
|
||||
|
||||
.intro-header {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
width: 100%;
|
||||
max-width: 80rem;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 4rem;
|
||||
background-image: var(--intro-bg-img-sm);
|
||||
background-image: var(--intro-bg-img-sm-set);
|
||||
background-position: top center;
|
||||
background-position-y: -1rem;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.intro-header-body {
|
||||
padding: 0;
|
||||
background: none;
|
||||
}
|
||||
.intro-header-title {
|
||||
margin: 0 0 0 1.5rem;
|
||||
text-align: left;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
color: #dceefb;
|
||||
padding: clamp(0rem, -5.4892rem + 23.4206vw, 9.5rem) 1rem 1rem;
|
||||
font-size: clamp(1.5rem, 0.7231rem + 3.3149vw, 3.375rem);
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
line-height: 110%;
|
||||
text-shadow: 0 0.125rem 0.1875rem rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.intro-header-title > span {
|
||||
background: linear-gradient(180deg, #ddff95 30%, #ffb84b 100%);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
font-size: clamp(2.25rem, 1.3177rem + 3.9779vw, 6.5rem);
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: 135%;
|
||||
text-shadow: none;
|
||||
}
|
||||
.intro-header-img {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
}
|
||||
.intro-header-mascot {
|
||||
margin: 2rem;
|
||||
flex-shrink: 1;
|
||||
width: 280px;
|
||||
height: 280px;
|
||||
}
|
||||
@media (width >= 992px) {
|
||||
.intro-header {
|
||||
background-image: var(--intro-bg-img);
|
||||
background-image: var(--intro-bg-img-set);
|
||||
}
|
||||
.intro-header-title {
|
||||
padding: 0 2rem 2.6rem 2rem;
|
||||
}
|
||||
.intro-header-img {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.intro-header-mascot {
|
||||
margin-right: 12rem;
|
||||
}
|
||||
}
|
||||
|
||||
// Intro Content
|
||||
|
||||
.intro-content {
|
||||
height: auto;
|
||||
margin-top: 1.6rem;
|
||||
width: 100%;
|
||||
}
|
||||
.intro-content-body {
|
||||
box-sizing: border-box;
|
||||
max-width: 80rem;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.intro-content-body:before,
|
||||
.intro-content-body:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(130deg, rgba(13, 44, 91, 0) 0%, #ddff95 77.4%);
|
||||
margin: 0 -1.2rem;
|
||||
filter: blur(2.75rem);
|
||||
opacity: 0.8;
|
||||
inset: unset;
|
||||
}
|
||||
.intro-content-body:before {
|
||||
top: -1rem;
|
||||
}
|
||||
.intro-content-body:after {
|
||||
bottom: -1rem;
|
||||
}
|
||||
@media (width < 768px) {
|
||||
.intro-content-body {
|
||||
margin-top: -9.8rem;
|
||||
}
|
||||
}
|
||||
@media (width >= 992px) {
|
||||
.intro-content {
|
||||
margin-top: 0;
|
||||
}
|
||||
.intro-content-body {
|
||||
margin-top: -5.7rem;
|
||||
}
|
||||
.intro-content-body:before,
|
||||
.intro-content-body:after {
|
||||
inset: 11.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
.intro-button {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.intro-button-link {
|
||||
background: #7f1d1d;
|
||||
background-image: linear-gradient(to bottom, rgba(255,0,0,0.8), rgba(255,255,255,0));
|
||||
background-position: top left, center;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 0.75rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.3;
|
||||
text-decoration: none !important;
|
||||
transition: transform 0.3s ease-in-out !important;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
min-width: 28.875rem;
|
||||
min-height: 7.6875rem;
|
||||
outline: none;
|
||||
}
|
||||
.intro-button-link:focus-visible {
|
||||
outline: var(--intro-focus-outline);
|
||||
outline-offset: var(--intro-focus-outline-offset);
|
||||
}
|
||||
.intro-button-link::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -13.125rem;
|
||||
left: -10rem;
|
||||
height: 26.25rem;
|
||||
width: 26.25rem;
|
||||
background: linear-gradient(135deg, #ec7bae 50.41%, #9600b8 70.41%);
|
||||
transform: rotate(45deg);
|
||||
transition: transform 0.3s ease-in-out;
|
||||
z-index: 5;
|
||||
}
|
||||
.intro-button-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
transition: all 0.5s ease-in-out;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
padding: 1rem 1.5rem;
|
||||
text-align: left;
|
||||
color: white;
|
||||
font-size: 1.65rem;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 130.023%;
|
||||
letter-spacing: 0.0075rem;
|
||||
}
|
||||
.intro-button-text strong {
|
||||
font-size: 2.625rem;
|
||||
font-weight: 600;
|
||||
line-height: 130.023%;
|
||||
letter-spacing: 0.013125rem;
|
||||
}
|
||||
.intro-button-link span {
|
||||
position: absolute;
|
||||
display: block;
|
||||
pointer-events: none;
|
||||
}
|
||||
.intro-button-link span:nth-child(1) {
|
||||
height: 8px;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: linear-gradient(to right, rgba(0, 0, 0, 0), #f6e58d);
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
transform: translateX(-100%);
|
||||
animation: span1 8s linear infinite;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
@keyframes span1 {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
.intro-button-link span:nth-child(2) {
|
||||
width: 8px;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), #f6e58d);
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
transform: translateY(100%);
|
||||
animation: span2 4s linear infinite;
|
||||
animation-delay: 5s;
|
||||
}
|
||||
@keyframes span2 {
|
||||
0% {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
}
|
||||
.intro-button-link span:nth-child(3) {
|
||||
height: 8px;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(to left, rgba(0, 0, 0, 0), #f6e58d);
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
transform: translateX(100%);
|
||||
animation: span3 8s linear infinite;
|
||||
animation-delay: 7s;
|
||||
}
|
||||
@keyframes span3 {
|
||||
0% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
}
|
||||
.intro-button-link:hover span {
|
||||
animation-play-state: paused;
|
||||
}
|
||||
@media (width < 768px) {
|
||||
.intro-header {
|
||||
padding-bottom: 9rem;;
|
||||
}
|
||||
.intro-button-link {
|
||||
height: 6.25rem;
|
||||
min-width: auto;
|
||||
border-radius: 0;
|
||||
}
|
||||
.intro-button-text {
|
||||
display: inline;
|
||||
padding-top: .5rem;
|
||||
}
|
||||
}
|
||||
@media (width >= 768px) {
|
||||
.intro-button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
max-width: 29.375rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.intro-button-link:hover {
|
||||
transition: all .5s;
|
||||
transform: rotate(-3deg) scale(1.125);
|
||||
}
|
||||
}
|
||||
|
||||
.intro-text {
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
margin-bottom: 0;
|
||||
background: #fff;
|
||||
position: relative;
|
||||
}
|
||||
.intro-text-body {
|
||||
padding: 2.5rem 1.063rem 0.75rem;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
.intro-text-lead {
|
||||
width: 100%;
|
||||
font-size: 1.5rem;
|
||||
margin: 0 0 1.5rem;
|
||||
}
|
||||
@media (width >= 768px) {
|
||||
.intro-button + .intro-text-body {
|
||||
padding-top: 7rem;
|
||||
}
|
||||
}
|
||||
@media (width >= 992px) {
|
||||
.intro-header {
|
||||
padding-bottom: 9rem;;
|
||||
}
|
||||
.intro-text,
|
||||
.intro-text-body {
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
.intro-text {
|
||||
box-shadow: var(--intro-shadow);
|
||||
max-width: min(60rem, 100vw - 4rem);
|
||||
margin: 0 auto 6rem;
|
||||
}
|
||||
.intro-text-narrow {
|
||||
max-width: min(50rem, 100vw - 4rem);
|
||||
}
|
||||
.intro-text-wide {
|
||||
max-width: min(67rem, 100vw - 4rem);
|
||||
}
|
||||
.intro-text-full {
|
||||
max-width: min(74rem, 100vw - 4rem);
|
||||
}
|
||||
.intro-text-body {
|
||||
padding-left: 4.5rem;
|
||||
padding-right: 4.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.intro-text-body .block {
|
||||
position: relative;
|
||||
}
|
||||
.intro-text-body .block-title {
|
||||
margin: 1em 0 .8em;
|
||||
}
|
||||
.intro-text-body .block-title span {
|
||||
display: inline-block;
|
||||
padding: 10px 30px 14px;
|
||||
margin: 30px 20px 0;
|
||||
background: white;
|
||||
border: 5px solid;
|
||||
border-radius: 30px;
|
||||
box-shadow: 0 0 0 5px white, inset 0 0 0 5px white;
|
||||
border-color: orangered;
|
||||
transform: rotate(-3deg) translateY(-25%);
|
||||
}
|
||||
.intro-text-body .block-title:before {
|
||||
content: "";
|
||||
height: 5px;
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
left: -15%;
|
||||
width: 130%;
|
||||
z-index: -5;
|
||||
background: orangered;
|
||||
box-shadow: 0 0 0 5px white, 0 -10px 0 5px white;
|
||||
transform: rotate(2deg) translateY(-50%);
|
||||
transform-origin: top left;
|
||||
}
|
||||
.intro-text-body .block-title:after {
|
||||
content: "";
|
||||
height: 120%;
|
||||
position: absolute;
|
||||
top: 42px;
|
||||
left: -25%;
|
||||
width: 150%;
|
||||
z-index: -10;
|
||||
background: var(--intro-bg-block-1);
|
||||
transform: rotate(2deg);
|
||||
}
|
||||
.intro-text-body .block:nth-of-type(6n+1) .block-title:after {
|
||||
background: var(--intro-bg-block-1);
|
||||
}
|
||||
.intro-text-body .block:nth-of-type(6n+2) .block-title:after {
|
||||
background: var(--intro-bg-block-2);
|
||||
}
|
||||
.intro-text-body .block:nth-of-type(6n+3) .block-title:after {
|
||||
background: var(--intro-bg-block-3);
|
||||
}
|
||||
.intro-text-body .block:nth-of-type(6n+4) .block-title:after {
|
||||
background: var(--intro-bg-block-4);
|
||||
}
|
||||
.intro-text-body .block:nth-of-type(6n+5) .block-title:after {
|
||||
background: var(--intro-bg-block-5);
|
||||
}
|
||||
.intro-text-body .block:nth-of-type(6n+6) .block-title:after {
|
||||
background: var(--intro-bg-block-6);
|
||||
}
|
||||
|
||||
#intro-badges {
|
||||
min-height: 3.2rem;
|
||||
text-align: center;
|
||||
visibility: hidden;
|
||||
}
|
||||
#intro-badges img {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
#intro-release:not([src]) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Intro Footer
|
||||
|
||||
.intro-footer {
|
||||
width: 100%;
|
||||
background-color: black;
|
||||
color: var(--intro-color-gray);
|
||||
padding-bottom: 2rem;
|
||||
}
|
||||
|
||||
.intro-footer-body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
margin: 0 auto;
|
||||
padding: 0 10.625rem;
|
||||
max-width: 80rem;
|
||||
}
|
||||
.intro-footer-body a:visited {
|
||||
color: var(--intro-color-gray);
|
||||
}
|
||||
// The footer has its own dark surface, so its links don't inherit the theme's link colors.
|
||||
.intro-footer-links a {
|
||||
color: currentColor;
|
||||
text-decoration: underline;
|
||||
transition: font-size 0.2s, text-decoration-color 0.2s;
|
||||
}
|
||||
.intro-footer-links a:focus-visible {
|
||||
outline: var(--intro-focus-outline);
|
||||
outline-offset: var(--intro-focus-outline-offset);
|
||||
}
|
||||
.intro-footer-links a:hover,
|
||||
.intro-footer-links a:hover:visited {
|
||||
text-decoration-color: var(--intro-color-link);
|
||||
}
|
||||
.intro-footer-logo,
|
||||
.intro-footer-links {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
.intro-footer-logo {
|
||||
max-height: 12.625rem;
|
||||
}
|
||||
.intro-footer-logo svg {
|
||||
width: 100%;
|
||||
}
|
||||
.intro-footer-links {
|
||||
gap: 1.875rem;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
@media (width < 768px) {
|
||||
.intro-footer-logo {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media (width < 992px) {
|
||||
.intro-footer-body {
|
||||
padding: 0 1rem;
|
||||
}
|
||||
}
|
||||
15
build.rs
15
build.rs
|
|
@ -1,14 +1,21 @@
|
|||
use pagetop_build::{StaticFilesBundle, compile_scss, copy_dir, minify_js};
|
||||
use pagetop_build::{StaticFilesBundle, compile_scss, copy_dir, copy_file, minify_js};
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
// Regenera `static/` desde cero sólo si hay cambios en `assets/`.
|
||||
println!("cargo:rerun-if-changed=assets");
|
||||
let _ = std::fs::remove_dir_all("static");
|
||||
|
||||
copy_dir("assets", "static")?;
|
||||
// Copia sin transformar. `assets/scss/` queda fuera porque sólo contiene fuentes SCSS.
|
||||
copy_file("assets/banner.png", "static/banner.png")?;
|
||||
copy_file("assets/favicon.ico", "static/favicon.ico")?;
|
||||
copy_dir("assets/img", "static/img")?;
|
||||
copy_dir("assets/js", "static/js")?;
|
||||
|
||||
// CSS: genera la variante minificada de `basic.css` del tema Basic.
|
||||
compile_scss("assets/css/basic.css", "static/css/basic.min.css")?;
|
||||
// CSS: compila los estilos del tema Basic.
|
||||
compile_scss("assets/scss/basic.scss", "static/css/basic.min.css")?;
|
||||
|
||||
// CSS: compila los estilos del componente `Intro`, independientes del tema.
|
||||
compile_scss("assets/scss/intro.scss", "static/css/intro.min.css")?;
|
||||
|
||||
// JS: minifica el manejo de `Dialog` del tema Basic.
|
||||
minify_js(
|
||||
|
|
|
|||
|
|
@ -114,12 +114,7 @@ impl Extension for Aliner {
|
|||
impl Theme for Aliner {
|
||||
fn before_render_page_body(&self, page: &mut Page) {
|
||||
page.alter_assets(
|
||||
StyleSheet::from("/pagetop/css/normalize.css")
|
||||
.with_version("8.0.1")
|
||||
.with_weight(-99),
|
||||
)
|
||||
.alter_assets(
|
||||
StyleSheet::from("/pagetop/css/basic.css")
|
||||
StyleSheet::from("/pagetop/css/basic.min.css")
|
||||
.with_version(PAGETOP_VERSION)
|
||||
.with_weight(-99),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -107,7 +107,9 @@ impl Component for Intro {
|
|||
}
|
||||
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
cx.alter_assets(StyleSheet::from("/pagetop/css/intro.css").with_version(PAGETOP_VERSION));
|
||||
cx.alter_assets(
|
||||
StyleSheet::from("/pagetop/css/intro.min.css").with_version(PAGETOP_VERSION),
|
||||
);
|
||||
if *self.kind() == intro::Kind::PageTop {
|
||||
cx.alter_assets(JavaScript::on_load_async("intro-js", |cx|
|
||||
util::indoc!(r#"
|
||||
|
|
|
|||
|
|
@ -15,11 +15,6 @@ impl Extension for Basic {
|
|||
impl Theme for Basic {
|
||||
fn before_render_page_body(&self, page: &mut Page) {
|
||||
page.alter_assets(
|
||||
StyleSheet::from("/pagetop/css/normalize.css")
|
||||
.with_version("8.0.1")
|
||||
.with_weight(-99),
|
||||
)
|
||||
.alter_assets(
|
||||
StyleSheet::from("/pagetop/css/basic.min.css")
|
||||
.with_version(PAGETOP_VERSION)
|
||||
.with_weight(-99),
|
||||
|
|
|
|||
|
|
@ -110,10 +110,7 @@ use std::ops::Deref;
|
|||
/// fn before_render_page_body(&self, page: &mut Page) {
|
||||
/// page
|
||||
/// .alter_assets(
|
||||
/// StyleSheet::from("/pagetop/css/normalize.css").with_version("8.0.1")
|
||||
/// )
|
||||
/// .alter_assets(
|
||||
/// StyleSheet::from("/pagetop/css/basic.css").with_version(PAGETOP_VERSION),
|
||||
/// StyleSheet::from("/pagetop/css/basic.min.css").with_version(PAGETOP_VERSION),
|
||||
/// )
|
||||
/// .alter_assets(
|
||||
/// StyleSheet::from("/mytheme/styles.css").with_version(env!("CARGO_PKG_VERSION")),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue