camper/web/static/camper.css

1166 lines
23 KiB
CSS
Raw Permalink Normal View History

Add the skeleton of the web application It does nothing more than to server a single page that does nothing interesting. This time i do not use a router. Instead, i am trying out a technique i have seen in an article[0] that i have tried in other, smaller, projects and seems to work surprisingly well: it just “cuts off” the URI path by path, passing the request from handler to handler until it finds its way to a handler that actually serves the request. That helps to loosen the coupling between the application and lower handlers, and makes dependencies explicit, because i need to pass the locale, company, etc. down instead of storing them in contexts. Let’s see if i do not regret it on a later date. I also made a lot more packages that in Numerus. In Numerus i actually only have the single pkg package, and it works, kind of, but i notice how i name my methods to avoid clashing instead of using packages for that. That is, instead of pkg.NewApp i now have app.New. Initially i thought that Locale should be inside app, but then there was a circular dependency between app and template. That is why i created a separate package, but now i am wondering if template should be inside app too, but then i would have app.MustRenderTemplate instead of template.MustRender. The CSS is the most bare-bones file i could write because i am focusing in markup right now; Oriol will fill in the file once the application is working. [0]: https://blog.merovius.de/posts/2017-06-18-how-not-to-use-an-http-router/
2023-07-22 22:11:00 +00:00
/**
* SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
* SPDX-FileCopyrightText: 2023 Oriol Carbonell <info@oriolcarbonell.cat>
Add the skeleton of the web application It does nothing more than to server a single page that does nothing interesting. This time i do not use a router. Instead, i am trying out a technique i have seen in an article[0] that i have tried in other, smaller, projects and seems to work surprisingly well: it just “cuts off” the URI path by path, passing the request from handler to handler until it finds its way to a handler that actually serves the request. That helps to loosen the coupling between the application and lower handlers, and makes dependencies explicit, because i need to pass the locale, company, etc. down instead of storing them in contexts. Let’s see if i do not regret it on a later date. I also made a lot more packages that in Numerus. In Numerus i actually only have the single pkg package, and it works, kind of, but i notice how i name my methods to avoid clashing instead of using packages for that. That is, instead of pkg.NewApp i now have app.New. Initially i thought that Locale should be inside app, but then there was a circular dependency between app and template. That is why i created a separate package, but now i am wondering if template should be inside app too, but then i would have app.MustRenderTemplate instead of template.MustRender. The CSS is the most bare-bones file i could write because i am focusing in markup right now; Oriol will fill in the file once the application is working. [0]: https://blog.merovius.de/posts/2017-06-18-how-not-to-use-an-http-router/
2023-07-22 22:11:00 +00:00
* SPDX-License-Identifier: AGPL-3.0-only
*/
*, *::before, *::after {
box-sizing: border-box;
}
*:not(dialog) {
Add the skeleton of the web application It does nothing more than to server a single page that does nothing interesting. This time i do not use a router. Instead, i am trying out a technique i have seen in an article[0] that i have tried in other, smaller, projects and seems to work surprisingly well: it just “cuts off” the URI path by path, passing the request from handler to handler until it finds its way to a handler that actually serves the request. That helps to loosen the coupling between the application and lower handlers, and makes dependencies explicit, because i need to pass the locale, company, etc. down instead of storing them in contexts. Let’s see if i do not regret it on a later date. I also made a lot more packages that in Numerus. In Numerus i actually only have the single pkg package, and it works, kind of, but i notice how i name my methods to avoid clashing instead of using packages for that. That is, instead of pkg.NewApp i now have app.New. Initially i thought that Locale should be inside app, but then there was a circular dependency between app and template. That is why i created a separate package, but now i am wondering if template should be inside app too, but then i would have app.MustRenderTemplate instead of template.MustRender. The CSS is the most bare-bones file i could write because i am focusing in markup right now; Oriol will fill in the file once the application is working. [0]: https://blog.merovius.de/posts/2017-06-18-how-not-to-use-an-http-router/
2023-07-22 22:11:00 +00:00
margin: 0;
}
@font-face {
font-family: 'JetBrains Mono';
font-style: italic;
font-weight: 100;
font-display: swap;
src: local('JetBrains Mono Thin'), url('./fonts/JetBrainsMono-ThinItalic.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: italic;
font-weight: 200;
font-display: swap;
src: local('JetBrains Mono ExtraLight'), url('./fonts/JetBrainsMono-ExtraLightItalic.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: italic;
font-weight: 300;
font-display: swap;
src: local('JetBrains Mono Light'), url('./fonts/JetBrainsMono-LightItalic.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: italic;
font-weight: 400;
font-display: swap;
src: local('JetBrains Mono'), url('./fonts/JetBrainsMono-Italic.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: italic;
font-weight: 500;
font-display: swap;
src: local('JetBrains Mono Medium'), url('./fonts/JetBrainsMono-MediumItalic.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: italic;
font-weight: 600;
font-display: swap;
src: local('JetBrains Mono SemiBoldItalic'), url('./fonts/JetBrainsMono-SemiBoldItalic.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: italic;
font-weight: 700;
font-display: swap;
src: local('JetBrains Mono Bold'), url('./fonts/JetBrainsMono-BoldItalic.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: italic;
font-weight: 800;
font-display: swap;
src: local('JetBrains Mono ExtraBold'), url('./fonts/JetBrainsMono-ExtraBoldItalic.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 100;
font-display: swap;
src: local('JetBrains Mono Thin'), url('./fonts/JetBrainsMono-Thin.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 200;
font-display: swap;
src: local('JetBrains Mono ExtraLight'), url('./fonts/JetBrainsMono-ExtraLight.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 300;
font-display: swap;
src: local('JetBrains Mono Light'), url('./fonts/JetBrainsMono-Light.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 400;
font-display: swap;
src: local('JetBrains Mono'), url('./fonts/JetBrainsMono-Regular.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 500;
font-display: swap;
src: local('JetBrains Mono Medium'), url('./fonts/JetBrainsMono-Medium.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 600;
font-display: swap;
src: local('JetBrains Mono SemiBold'), url('./fonts/JetBrainsMono-SemiBold.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 700;
font-display: swap;
src: local('JetBrains Mono Bold'), url('./fonts/JetBrainsMono-Bold.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 800;
font-display: swap;
src: local('JetBrains Mono ExtraBold'), url('./fonts/JetBrainsMono-ExtraBold.woff2') format('woff2');
Add the skeleton of the web application It does nothing more than to server a single page that does nothing interesting. This time i do not use a router. Instead, i am trying out a technique i have seen in an article[0] that i have tried in other, smaller, projects and seems to work surprisingly well: it just “cuts off” the URI path by path, passing the request from handler to handler until it finds its way to a handler that actually serves the request. That helps to loosen the coupling between the application and lower handlers, and makes dependencies explicit, because i need to pass the locale, company, etc. down instead of storing them in contexts. Let’s see if i do not regret it on a later date. I also made a lot more packages that in Numerus. In Numerus i actually only have the single pkg package, and it works, kind of, but i notice how i name my methods to avoid clashing instead of using packages for that. That is, instead of pkg.NewApp i now have app.New. Initially i thought that Locale should be inside app, but then there was a circular dependency between app and template. That is why i created a separate package, but now i am wondering if template should be inside app too, but then i would have app.MustRenderTemplate instead of template.MustRender. The CSS is the most bare-bones file i could write because i am focusing in markup right now; Oriol will fill in the file once the application is working. [0]: https://blog.merovius.de/posts/2017-06-18-how-not-to-use-an-http-router/
2023-07-22 22:11:00 +00:00
}
html {
font-family: 'JetBrains Mono', monospace;
Add the skeleton of the web application It does nothing more than to server a single page that does nothing interesting. This time i do not use a router. Instead, i am trying out a technique i have seen in an article[0] that i have tried in other, smaller, projects and seems to work surprisingly well: it just “cuts off” the URI path by path, passing the request from handler to handler until it finds its way to a handler that actually serves the request. That helps to loosen the coupling between the application and lower handlers, and makes dependencies explicit, because i need to pass the locale, company, etc. down instead of storing them in contexts. Let’s see if i do not regret it on a later date. I also made a lot more packages that in Numerus. In Numerus i actually only have the single pkg package, and it works, kind of, but i notice how i name my methods to avoid clashing instead of using packages for that. That is, instead of pkg.NewApp i now have app.New. Initially i thought that Locale should be inside app, but then there was a circular dependency between app and template. That is why i created a separate package, but now i am wondering if template should be inside app too, but then i would have app.MustRenderTemplate instead of template.MustRender. The CSS is the most bare-bones file i could write because i am focusing in markup right now; Oriol will fill in the file once the application is working. [0]: https://blog.merovius.de/posts/2017-06-18-how-not-to-use-an-http-router/
2023-07-22 22:11:00 +00:00
font-size: 62.5%;
--camper--color--black: #3f3b37;
--camper--color--dark-gray: #8a8885;
--camper--color--light-gray: #e1dbd6;
--camper--color--white: #ffffff;
--camper--color--yellow: #ffd200;
--camper--color--red: #ff7a53;
--camper--color--rosy: #ffbaa6;
--camper--color--green: #5ae487;
--camper--color--light-green: #9fefb9;
--camper--color--blue: #55bfff;
--camper--color--light-blue: #cbebff;
--camper--color--hay: #ffe673;
--camper--text-color: var(--camper--color--black);
--camper--background-color: var(--camper--color--white);
--camper--header--background-color: #ede9e5;
Add the skeleton of the web application It does nothing more than to server a single page that does nothing interesting. This time i do not use a router. Instead, i am trying out a technique i have seen in an article[0] that i have tried in other, smaller, projects and seems to work surprisingly well: it just “cuts off” the URI path by path, passing the request from handler to handler until it finds its way to a handler that actually serves the request. That helps to loosen the coupling between the application and lower handlers, and makes dependencies explicit, because i need to pass the locale, company, etc. down instead of storing them in contexts. Let’s see if i do not regret it on a later date. I also made a lot more packages that in Numerus. In Numerus i actually only have the single pkg package, and it works, kind of, but i notice how i name my methods to avoid clashing instead of using packages for that. That is, instead of pkg.NewApp i now have app.New. Initially i thought that Locale should be inside app, but then there was a circular dependency between app and template. That is why i created a separate package, but now i am wondering if template should be inside app too, but then i would have app.MustRenderTemplate instead of template.MustRender. The CSS is the most bare-bones file i could write because i am focusing in markup right now; Oriol will fill in the file once the application is working. [0]: https://blog.merovius.de/posts/2017-06-18-how-not-to-use-an-http-router/
2023-07-22 22:11:00 +00:00
}
body {
font-size: 1.6rem;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
body, dialog, .media-picker header, .media-picker footer {
background-color: var(--camper--background-color);
color: var(--camper--text-color);
Add the skeleton of the web application It does nothing more than to server a single page that does nothing interesting. This time i do not use a router. Instead, i am trying out a technique i have seen in an article[0] that i have tried in other, smaller, projects and seems to work surprisingly well: it just “cuts off” the URI path by path, passing the request from handler to handler until it finds its way to a handler that actually serves the request. That helps to loosen the coupling between the application and lower handlers, and makes dependencies explicit, because i need to pass the locale, company, etc. down instead of storing them in contexts. Let’s see if i do not regret it on a later date. I also made a lot more packages that in Numerus. In Numerus i actually only have the single pkg package, and it works, kind of, but i notice how i name my methods to avoid clashing instead of using packages for that. That is, instead of pkg.NewApp i now have app.New. Initially i thought that Locale should be inside app, but then there was a circular dependency between app and template. That is why i created a separate package, but now i am wondering if template should be inside app too, but then i would have app.MustRenderTemplate instead of template.MustRender. The CSS is the most bare-bones file i could write because i am focusing in markup right now; Oriol will fill in the file once the application is working. [0]: https://blog.merovius.de/posts/2017-06-18-how-not-to-use-an-http-router/
2023-07-22 22:11:00 +00:00
}
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
}
input, button, textarea, select {
font: inherit;
}
p, h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
2024-01-15 11:30:13 +00:00
margin: 20px 0;
Add the skeleton of the web application It does nothing more than to server a single page that does nothing interesting. This time i do not use a router. Instead, i am trying out a technique i have seen in an article[0] that i have tried in other, smaller, projects and seems to work surprisingly well: it just “cuts off” the URI path by path, passing the request from handler to handler until it finds its way to a handler that actually serves the request. That helps to loosen the coupling between the application and lower handlers, and makes dependencies explicit, because i need to pass the locale, company, etc. down instead of storing them in contexts. Let’s see if i do not regret it on a later date. I also made a lot more packages that in Numerus. In Numerus i actually only have the single pkg package, and it works, kind of, but i notice how i name my methods to avoid clashing instead of using packages for that. That is, instead of pkg.NewApp i now have app.New. Initially i thought that Locale should be inside app, but then there was a circular dependency between app and template. That is why i created a separate package, but now i am wondering if template should be inside app too, but then i would have app.MustRenderTemplate instead of template.MustRender. The CSS is the most bare-bones file i could write because i am focusing in markup right now; Oriol will fill in the file once the application is working. [0]: https://blog.merovius.de/posts/2017-06-18-how-not-to-use-an-http-router/
2023-07-22 22:11:00 +00:00
}
:any-link {
color: #0000ff;
}
a.missing-translation {
color: #ff0000;
}
body > a[href="#content"], .sr-only {
border: 0;
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute !important;
width: 1px;
word-wrap: normal !important;
}
body > a[href="#content"]:focus {
background-color: #f1f1f1;
border-radius: 3px;
box-shadow: 0 0 2px 2px rgba(0, 0, 0, .6);
clip: auto !important;
clip-path: none;
color: #21759b;
display: block;
font-size: 1.4rem;
font-weight: 700;
height: auto;
left: 5px;
line-height: normal;
padding: 15px 23px 14px;
text-decoration: none;
top: 5px;
width: auto;
z-index: 100000;
}
/* header */
body > header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: var(--camper--header--background-color);
}
body > header, body > nav ul a {
padding: 0 3rem;
}
body > nav {
border-bottom: 1px solid var(--camper--color--light-gray);
}
body > nav ul, body > nav ol {
display: flex;
list-style: none;
padding: 0;
}
body > nav ul li {
flex: 1;
}
body > nav a {
text-decoration: none;
color: inherit;
}
body > nav ul a {
min-height: 8rem;
display: flex;
align-items: center;
}
body > .breadcrumb ol {
padding: .5em 3rem;
gap: .5em;
flex-wrap: wrap;
}
body > .breadcrumb li + li::before {
content: " > ";
}
body > footer {
border-top: 1px solid var(--camper--color--light-gray);
padding: .25em 3rem;
}
body > footer p {
margin: 0;
}
main {
padding: 2rem 3rem;
}
/*<editor-fold desc="table">*/
table:not(.month) {
width: 100%;
border-collapse: collapse;
margin: 2rem 0 0 0;
}
2024-01-15 11:30:13 +00:00
table:not(.month) th, table:not(.month) td {
padding: 10px 0;
border-bottom: .5px solid;
}
table:not(.month) th {
text-align: start;
2024-01-15 11:30:13 +00:00
}
table:not(.month) .numeric, .numeric {
text-align: end;
}
/*</editor-fold>*/
/* user menu */
nav details {
position: relative;
}
nav details summary {
background-color: var(--camper--background-color);
display: flex;
cursor: pointer;
justify-content: center;
align-items: center;
width: 7rem;
height: 7rem;
margin: 1rem 0;
border-radius: 50%;
border: none;
}
nav details summary:hover,
nav details summary:focus,
nav details a:hover,
nav details button:hover {
background-color: var(--camper--color--light-gray);
}
nav details summary img {
width: 4.8rem;
object-fit: contain;
}
nav details summary span {
display: none;
}
nav details summary::-webkit-details-marker {
display: none;
}
nav details[open] summary::before, .invoice-status[open] summary::before {
background-color: var(--camper--header--background-color);
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
content: "";
cursor: default;
z-index: 10;
mix-blend-mode: multiply;
}
nav details ul {
position: absolute;
padding: 1rem 2rem;
list-style: none;
background-color: var(--camper--background-color);
z-index: 20;
right: -1.875em;
}
nav details a:any-link, nav details button {
color: var(--camper--text-color);
font-size: 2rem;
font-style: italic;
height: 5.5rem;
width: 46rem;
padding-left: 2rem;
display: flex;
align-items: center;
border: 0;
text-decoration: none;
text-transform: initial;
cursor: pointer;
}
nav details li + li {
border-top: 1px solid var(--camper--color--dark-gray);
}
/* form */
fieldset {
border: none;
padding: 0;
}
form h2 {
margin-bottom: 1em;
}
label, legend {
display: block;
font-style: italic;
}
fieldset + label, fieldset + fieldset, label + label:not([x-show]), label + fieldset {
margin-top: 1rem;
}
label input, label textarea, label select {
font-style: normal;
}
form fieldset + footer {
margin-top: 3rem;
}
input[type="submit"], button, .button {
min-width: 34rem;
background-color: var(--camper--color--white);
border: 2px solid var(--camper--color--black);
text-transform: uppercase;
display: inline-block;
text-align: center;
padding: 1rem;
}
input[type="text"],
input[type="search"],
input[type="password"],
input[type="email"],
input[type="tel"],
input[type="url"],
input[type="number"],
input[type="date"],
select,
textarea {
background-color: var(--camper--background-color);
border: 1px solid var(--camper--color--black);
border-radius: 0;
padding: .5rem 1rem;
height: 3.5rem;
}
/* login */
#login-form {
background-color: var(--camper--color--hay);
padding: 1.25em;
}
#login-form fieldset {
display: flex;
gap: 2rem;
}
#login-form label {
margin: 0;
}
/* media */
.media-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(26rem, 1fr));
grid-auto-rows: 1fr;
list-style: none;
gap: 1rem;
padding: 0;
}
.media-grid img, .media-grid button {
width: 100%;
height: 100%;
max-height: 26rem;
}
.media-grid button {
min-width: 0;
border: none;
padding: 0;
}
.media-grid img {
object-fit: cover;
}
.media-picker {
min-width: 75vw;
}
.media-picker header, .media-picker footer {
position: sticky;
padding-top: 1rem;
padding-bottom: 1rem;
}
.media-picker header {
top: -1em;
}
.media-picker footer {
bottom: -1em;
}
/*<editor-fold desc="Campground Map">*/
#campground_map .guest-only, #arbres, #zones {
display: none;
}
#campground_map a:hover > path {
fill: var(--camper--color--hay) !important;
}
/*</editor-fold>*/
[class^="icon_"] {
background-size: 2em 2em;
background-repeat: no-repeat;
background-position: center left;
}
.services [class^="icon_"] {
padding-left: 2.5em;
}
.icon-input ul {
padding: 0;
list-style: none;
display: flex;
flex-wrap: wrap;
gap: .25em;
}
.icon-input button {
2024-01-23 23:40:19 +00:00
min-width: 0;
width: 4rem;
height: 4rem;
background-position: center;
}
.icon-input button[aria-pressed="true"], .lang-selector button[aria-pressed="true"] {
background-color: var(--camper--color--hay);
}
2024-01-16 16:37:40 +00:00
/* accommodation type */
fieldset img {
max-width: 400px;
2024-01-16 16:37:40 +00:00
}
/* calendar */
.season-calendar button {
display: flex;
gap: 1em;
border: none;
cursor: pointer;
}
.season-calendar form button:first-child, .season-calendar > header button {
min-width: 0;
}
.season-calendar > header {
display: flex;
gap: 2rem;
justify-content: center;
align-items: center;
}
.season-calendar > header button:first-of-type {
order: -1;
}
.season-calendar > header button:first-of-type::before {
content: "←";
}
.season-calendar > header button:last-of-type::before {
content: "→";
}
.season-calendar > div {
display: grid;
grid-template-columns: repeat(3, auto);
grid-auto-rows: 1fr;
justify-content: center;
align-items: start;
gap: 2em;
}
@media (max-width: 48rem) {
.season-calendar > div {
display: flex;
flex-direction: column;
}
.season-calendar table {
width: 100%;
}
}
.season-calendar table {
border-collapse: collapse;
}
.season-calendar td {
width: calc(100% / 7);
}
.season-calendar time {
display: block;
width: 100%;
min-width: 3rem;
aspect-ratio: 1;
2024-01-15 11:30:13 +00:00
text-indent: 20%;
white-space: nowrap;
2024-01-15 11:30:13 +00:00
overflow: visible;
padding: 3px 0 0 0;
}
.season-calendar [aria-checked] {
border: 2px solid var(--camper--color--black);
position: relative;
}
.season-calendar [aria-checked]::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: block;
background-color: var(--camper--color--black);
border-radius: 50%;
width: .8rem;
height: .8rem;
}
.season-calendar form button:first-child {
position: absolute;
top: 0;
right: 0;
background-color: transparent;
}
.season-calendar form button:hover, .season-calendar form button:first-child:hover {
background-color: var(--camper--color--hay);
}
.season-calendar form button:first-child::before {
content: "✕";
}
.sortable tbody tr td:first-child {
display: flex;
2024-01-15 11:30:13 +00:00
min-height: 70px;
align-items: center;
}
2024-01-18 02:27:07 +00:00
.sortable img {
max-width: 20rem;
border-radius: 5px;
2024-01-18 02:27:07 +00:00
}
#slide-index img {
width: 192px;
aspect-ratio: 4 / 3;
object-fit: cover;
}
.sortable .handle {
display: inline-block;
width: 1.5em;
aspect-ratio: 1;
cursor: grab;
background: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"%3E%3Crect width="256" height="256" fill="none"/%3E%3Ccircle cx="92" cy="60" r="12"/%3E%3Ccircle cx="164" cy="60" r="12"/%3E%3Ccircle cx="92" cy="128" r="12"/%3E%3Ccircle cx="164" cy="128" r="12"/%3E%3Ccircle cx="92" cy="196" r="12"/%3E%3Ccircle cx="164" cy="196" r="12"/%3E%3C/svg%3E') left center no-repeat;
}
.sortable-ghost {
background-color: #aaa;
}
/* snack bar */
#snackbar [role="alert"] {
cursor: pointer;
background-color: var(--camper--color--black);
color: var(--camper--color--white);
padding: 2rem;
min-width: 28.8rem;
max-width: 56.8rem;
border-radius: 2px;
position: fixed;
translate: -50% 100%;
left: 50%;
bottom: 0;
transition: translate;
transition-duration: 300ms;
}
#snackbar [role="alert"].open {
translate: -50%;
}
/*<editor-fold desc="i18n input">*/
[x-cloak] {
display: none !important;
}
.lang-selector {
display: flex;
gap: .25em;
2024-01-15 11:30:13 +00:00
margin: 0 0 5px 0;
}
.lang-selector button {
min-width: auto;
padding: .15em;
margin: 0;
}
label[x-show] > span, label[x-show] > br {
display: none;
}
/*</editor-fold>*/
/*<editor-fold desc="statuses">*/
.invoice-status-created,
.booking-created .booking-status,
.payment-pending .payment-status {
background-color: var(--camper--color--light-blue);
}
.invoice-status-unpaid,
.booking-cancelled .booking-status,
.payment-failed .payment-status {
background-color: var(--camper--color--rosy);
}
.invoice-status-sent,
.booking-confirmed .booking-status,
.payment-preauth .payment-status {
background-color: var(--camper--color--hay);
}
.invoice-status-paid,
.booking-checked-in .booking-status,
.payment-completed .payment-status {
background-color: var(--camper--color--light-green);
}
.booking-invoiced .booking-status,
.payment-refunded .payment-status,
.payment-draft .payment-status,
.payment-voided .payment-status {
background-color: var(--camper--color--light-gray);
}
/*</editor-fold>*/
/*<editor-fold desc="Payment">*/
#payment-heading {
float: left;
}
#payment-actions {
2024-03-25 15:43:58 +00:00
display: flex;
gap: 2ch;
justify-content: end;
}
/*</editor-fold>*/
/*<editor-fold desc="Campsites Booking">*/
#campsites-booking {
“Mockup” for the new booking form It does nothing but compute the total of a booking, much like it does for guests. In fact, i use the same payment relations to do the exact same computation, otherwise i am afraid i will make a mistake in the ACSI or such, now or in future version; better if both are exactly the same. The idea is that once the user creates the booking, i will delete that payment, because it makes no sense to keep it in this case; nobody is going to pay for it. Had to reuse the grid showing the bookings of campsites because employees need to select one or more campsites to book, and need to see which are available. In this case, i have to filter by campsite type and use the arrival and departure dates to filter the months, now up to the day, not just month. Had to change max width of th and td in the grid to take into account that now a month could have a single day, for instance, and the month heading can not stretch the day or booking spans would not be in their correct positions. For that, i needed to access campsiteEntry, bookingEntry, and Month from campsite package, but campsite imports campsite/types, and campsite/types already imports booking for the BookingDates type. To break the cycle, had to move all that to booking and use from campsite; it is mostly unchanged, except for the granularity of dates up to days instead of just months. The design of this form calls for a different way of showing the totals, because here employees have to see the amount next to the input with the units, instead of having a footer with the table. I did not like the idea of having to query the database for that, therefore i “lifter” the payment draft into a struct that both public and admin forms use to show they respective views of the cart.
2024-04-23 19:07:41 +00:00
max-height: 90vh;
overflow: scroll;
}
#campsites-booking table {
width: auto;
}
#campsites-booking .weekend {
background-color: var(--camper--color--rosy);
}
“Mockup” for the new booking form It does nothing but compute the total of a booking, much like it does for guests. In fact, i use the same payment relations to do the exact same computation, otherwise i am afraid i will make a mistake in the ACSI or such, now or in future version; better if both are exactly the same. The idea is that once the user creates the booking, i will delete that payment, because it makes no sense to keep it in this case; nobody is going to pay for it. Had to reuse the grid showing the bookings of campsites because employees need to select one or more campsites to book, and need to see which are available. In this case, i have to filter by campsite type and use the arrival and departure dates to filter the months, now up to the day, not just month. Had to change max width of th and td in the grid to take into account that now a month could have a single day, for instance, and the month heading can not stretch the day or booking spans would not be in their correct positions. For that, i needed to access campsiteEntry, bookingEntry, and Month from campsite package, but campsite imports campsite/types, and campsite/types already imports booking for the BookingDates type. To break the cycle, had to move all that to booking and use from campsite; it is mostly unchanged, except for the granularity of dates up to days instead of just months. The design of this form calls for a different way of showing the totals, because here employees have to see the amount next to the input with the units, instead of having a footer with the table. I did not like the idea of having to query the database for that, therefore i “lifter” the payment draft into a struct that both public and admin forms use to show they respective views of the cart.
2024-04-23 19:07:41 +00:00
#campsites-booking .today {
border-left: 2px solid red;
}
#campsites-booking colgroup {
border-right: 2px solid;
}
#campsites-booking col {
border: 1px solid;
min-width: 2.25ch;
max-width: 2.25ch;
“Mockup” for the new booking form It does nothing but compute the total of a booking, much like it does for guests. In fact, i use the same payment relations to do the exact same computation, otherwise i am afraid i will make a mistake in the ACSI or such, now or in future version; better if both are exactly the same. The idea is that once the user creates the booking, i will delete that payment, because it makes no sense to keep it in this case; nobody is going to pay for it. Had to reuse the grid showing the bookings of campsites because employees need to select one or more campsites to book, and need to see which are available. In this case, i have to filter by campsite type and use the arrival and departure dates to filter the months, now up to the day, not just month. Had to change max width of th and td in the grid to take into account that now a month could have a single day, for instance, and the month heading can not stretch the day or booking spans would not be in their correct positions. For that, i needed to access campsiteEntry, bookingEntry, and Month from campsite package, but campsite imports campsite/types, and campsite/types already imports booking for the BookingDates type. To break the cycle, had to move all that to booking and use from campsite; it is mostly unchanged, except for the granularity of dates up to days instead of just months. The design of this form calls for a different way of showing the totals, because here employees have to see the amount next to the input with the units, instead of having a footer with the table. I did not like the idea of having to query the database for that, therefore i “lifter” the payment draft into a struct that both public and admin forms use to show they respective views of the cart.
2024-04-23 19:07:41 +00:00
width: 2.25ch;
}
#campsites-booking th {
background-color: var(--camper--background-color);
background-clip: padding-box;
}
#campsites-booking thead tr:first-child th, #campsites-booking tbody th {
padding: 0 .5ch;
“Mockup” for the new booking form It does nothing but compute the total of a booking, much like it does for guests. In fact, i use the same payment relations to do the exact same computation, otherwise i am afraid i will make a mistake in the ACSI or such, now or in future version; better if both are exactly the same. The idea is that once the user creates the booking, i will delete that payment, because it makes no sense to keep it in this case; nobody is going to pay for it. Had to reuse the grid showing the bookings of campsites because employees need to select one or more campsites to book, and need to see which are available. In this case, i have to filter by campsite type and use the arrival and departure dates to filter the months, now up to the day, not just month. Had to change max width of th and td in the grid to take into account that now a month could have a single day, for instance, and the month heading can not stretch the day or booking spans would not be in their correct positions. For that, i needed to access campsiteEntry, bookingEntry, and Month from campsite package, but campsite imports campsite/types, and campsite/types already imports booking for the BookingDates type. To break the cycle, had to move all that to booking and use from campsite; it is mostly unchanged, except for the granularity of dates up to days instead of just months. The design of this form calls for a different way of showing the totals, because here employees have to see the amount next to the input with the units, instead of having a footer with the table. I did not like the idea of having to query the database for that, therefore i “lifter” the payment draft into a struct that both public and admin forms use to show they respective views of the cart.
2024-04-23 19:07:41 +00:00
max-width: calc(2.25ch * var(--days));
overflow: hidden;
white-space: nowrap;
}
#campsites-booking thead tr:last-child th {
padding: 0;
text-align: center;
}
#campsites-booking thead,
#campsites-booking tbody th {
position: sticky;
z-index: 10;
}
#campsites-booking thead {
top: 0;
}
#campsites-booking tbody th {
left: 0;
}
#campsites-booking tbody td {
position: relative;
user-select: none;
}
#campsites-booking tbody div {
border: 1px solid;
position: absolute;
z-index: 5;
top: 0;
left: calc(2.25ch * var(--booking-begin, 0) / 2);
bottom: 0;
white-space: nowrap;
overflow: hidden;
width: calc(2.25ch * (var(--booking-nights, 1) + (var(--booking-end, 0) - var(--booking-begin, 0)) / 2) - 1px);
}
#booking-filter, #booking-filter fieldset {
display: flex;
gap: 1ch;
2024-05-03 10:55:43 +00:00
padding-top: 2rem;
}
#booking-filter label, #booking-filter fieldset + fieldset, #booking-filter footer {
margin-top: 0;
}
#booking-filter input[type="number"] {
width: 9ch;
}
#booking-filter footer {
align-self: end;
}
#booking-filter button {
min-width: unset;
padding: .25em 1em;
}
/*</editor-fold>*/
“Mockup” for the new booking form It does nothing but compute the total of a booking, much like it does for guests. In fact, i use the same payment relations to do the exact same computation, otherwise i am afraid i will make a mistake in the ACSI or such, now or in future version; better if both are exactly the same. The idea is that once the user creates the booking, i will delete that payment, because it makes no sense to keep it in this case; nobody is going to pay for it. Had to reuse the grid showing the bookings of campsites because employees need to select one or more campsites to book, and need to see which are available. In this case, i have to filter by campsite type and use the arrival and departure dates to filter the months, now up to the day, not just month. Had to change max width of th and td in the grid to take into account that now a month could have a single day, for instance, and the month heading can not stretch the day or booking spans would not be in their correct positions. For that, i needed to access campsiteEntry, bookingEntry, and Month from campsite package, but campsite imports campsite/types, and campsite/types already imports booking for the BookingDates type. To break the cycle, had to move all that to booking and use from campsite; it is mostly unchanged, except for the granularity of dates up to days instead of just months. The design of this form calls for a different way of showing the totals, because here employees have to see the amount next to the input with the units, instead of having a footer with the table. I did not like the idea of having to query the database for that, therefore i “lifter” the payment draft into a struct that both public and admin forms use to show they respective views of the cart.
2024-04-23 19:07:41 +00:00
/*<editor-fold desc="Booking Form">*/
#booking-form > fieldset {
display: grid;
2024-05-03 10:55:43 +00:00
gap: 5em;
“Mockup” for the new booking form It does nothing but compute the total of a booking, much like it does for guests. In fact, i use the same payment relations to do the exact same computation, otherwise i am afraid i will make a mistake in the ACSI or such, now or in future version; better if both are exactly the same. The idea is that once the user creates the booking, i will delete that payment, because it makes no sense to keep it in this case; nobody is going to pay for it. Had to reuse the grid showing the bookings of campsites because employees need to select one or more campsites to book, and need to see which are available. In this case, i have to filter by campsite type and use the arrival and departure dates to filter the months, now up to the day, not just month. Had to change max width of th and td in the grid to take into account that now a month could have a single day, for instance, and the month heading can not stretch the day or booking spans would not be in their correct positions. For that, i needed to access campsiteEntry, bookingEntry, and Month from campsite package, but campsite imports campsite/types, and campsite/types already imports booking for the BookingDates type. To break the cycle, had to move all that to booking and use from campsite; it is mostly unchanged, except for the granularity of dates up to days instead of just months. The design of this form calls for a different way of showing the totals, because here employees have to see the amount next to the input with the units, instead of having a footer with the table. I did not like the idea of having to query the database for that, therefore i “lifter” the payment draft into a struct that both public and admin forms use to show they respective views of the cart.
2024-04-23 19:07:41 +00:00
grid-template-columns: repeat(4, 1fr);
}
2024-05-03 15:21:20 +00:00
#booking-form > footer {
display: flex;
justify-content: space-between;
}
“Mockup” for the new booking form It does nothing but compute the total of a booking, much like it does for guests. In fact, i use the same payment relations to do the exact same computation, otherwise i am afraid i will make a mistake in the ACSI or such, now or in future version; better if both are exactly the same. The idea is that once the user creates the booking, i will delete that payment, because it makes no sense to keep it in this case; nobody is going to pay for it. Had to reuse the grid showing the bookings of campsites because employees need to select one or more campsites to book, and need to see which are available. In this case, i have to filter by campsite type and use the arrival and departure dates to filter the months, now up to the day, not just month. Had to change max width of th and td in the grid to take into account that now a month could have a single day, for instance, and the month heading can not stretch the day or booking spans would not be in their correct positions. For that, i needed to access campsiteEntry, bookingEntry, and Month from campsite package, but campsite imports campsite/types, and campsite/types already imports booking for the BookingDates type. To break the cycle, had to move all that to booking and use from campsite; it is mostly unchanged, except for the granularity of dates up to days instead of just months. The design of this form calls for a different way of showing the totals, because here employees have to see the amount next to the input with the units, instead of having a footer with the table. I did not like the idea of having to query the database for that, therefore i “lifter” the payment draft into a struct that both public and admin forms use to show they respective views of the cart.
2024-04-23 19:07:41 +00:00
#booking-form fieldset fieldset, #booking-form .colspan {
grid-column: span 2;
}
#booking-form #campsites-booking, #booking-form .error {
“Mockup” for the new booking form It does nothing but compute the total of a booking, much like it does for guests. In fact, i use the same payment relations to do the exact same computation, otherwise i am afraid i will make a mistake in the ACSI or such, now or in future version; better if both are exactly the same. The idea is that once the user creates the booking, i will delete that payment, because it makes no sense to keep it in this case; nobody is going to pay for it. Had to reuse the grid showing the bookings of campsites because employees need to select one or more campsites to book, and need to see which are available. In this case, i have to filter by campsite type and use the arrival and departure dates to filter the months, now up to the day, not just month. Had to change max width of th and td in the grid to take into account that now a month could have a single day, for instance, and the month heading can not stretch the day or booking spans would not be in their correct positions. For that, i needed to access campsiteEntry, bookingEntry, and Month from campsite package, but campsite imports campsite/types, and campsite/types already imports booking for the BookingDates type. To break the cycle, had to move all that to booking and use from campsite; it is mostly unchanged, except for the granularity of dates up to days instead of just months. The design of this form calls for a different way of showing the totals, because here employees have to see the amount next to the input with the units, instead of having a footer with the table. I did not like the idea of having to query the database for that, therefore i “lifter” the payment draft into a struct that both public and admin forms use to show they respective views of the cart.
2024-04-23 19:07:41 +00:00
grid-column: 1 / -1;
}
#booking-form :is(label, fieldset fieldset),
#booking-form .booking-items table {
margin-top: 0;
}
#booking-form :is(input:not([type='checkbox']), select) {
width: 100%;
}
#booking-form :is(.customer-details, .booking-period) {
display: grid;
gap: .5em;
grid-template-columns: 1fr 1fr;
align-content: start;
}
#booking-form .booking-items td {
padding: .3125rem 0;
}
#booking-form .booking-items br {
display: none;
}
#booking-form .booking-items td:first-child input {
width: 6ch;
}
#booking-form h3 {
margin-bottom: 0;
}
/*</editor-fold>*/
/*<editor-fold desc="Check-in guests">*/
#checkin-guests {
display: flex;
flex-direction: column;
}
#checkin-guests :is(label, fieldset) {
margin-top: 0;
}
#checkin-guests br {
display: none;
}
#checkin-guests > fieldset {
counter-reset: guest-count;
}
#checkin-guests > fieldset > fieldset {
counter-increment: guest-count;
position: relative;
display: grid;
grid-template-columns: repeat(4, 1fr);
border-bottom: .5px solid;
padding: 2.25em 0 1em;
column-gap: 1ch;
row-gap: .75em;
}
#checkin-guests > fieldset > fieldset::before {
content: '#' counter(guest-count);
position: absolute;
}
#checkin-guests fieldset fieldset:first-of-type button {
display: none;
}
#checkin-guests fieldset button,
.new-invoice-product .delete-product {
position: absolute;
right: 0;
width: min-content;
min-width: unset;
line-height: 1;
border: none;
cursor: pointer;
}
#checkin-guests > fieldset > fieldset::before,
.new-invoice-product .delete-product,
#checkin-guests fieldset button {
top: .25em;
}
#checkin-guests fieldset button:hover,
.new-invoice-product .delete-product:hover {
background-color: var(--camper--color--light-gray);
}
#checkin-guests fieldset button::before,
.new-invoice-product .delete-product:before {
content: '⌫';
}
#checkin-guests :is(input, select) {
width: 100%;
}
#checkin-guests label:nth-of-type(2), #checkin-guests label:nth-of-type(9) {
grid-column: span 2;
}
#checkin-guests label:last-of-type {
grid-column: 1 / -1;
}
#checkin-guests footer {
display: flex;
justify-content: space-between;
}
2024-05-03 10:55:43 +00:00
#batch-form {
margin-bottom: 2rem;
}
/*</editor-fold>*/
/*<editor-fold desc="Invoices">*/
.filters {
display: none;
}
.filters-visible .filters {
display: initial;
}
.filters > fieldset {
display: flex;
gap: 1rem;
float: none;
margin: 1rem 0 1rem;
padding: 0;
border: none;
}
.filters-visible #filters-toggle {
background-color: var(--camper--header--background-color);
}
.filters label + label {
margin-top: 0;
}
.invoice-data, .product-data {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1ch;
}
.invoice-data label + label, .new-invoice-product label + label {
margin-top: 0;
}
:is(.invoice-data, .new-invoice-product) :is(input, select, textarea) {
width: 100%;
}
.invoice-data label:last-child {
grid-column: 1 / -1;
}
.new-invoice-product {
display: grid;
grid-template-columns: 3fr repeat(4, 1fr);
gap: 1ch;
position: relative;
padding: 2rem 0 0;
margin-top: 3rem;
border-top: 1px solid var(--camper--color--light-gray);
}
.new-invoice-product .delete-product {
position: absolute;
right: 0;
top: .75rem;
}
#invoice-summary {
margin-bottom: 1rem;
}
#invoice-summary th {
text-align: left;
padding: 0 0 0 1rem;
border-bottom: none;
}
#invoice-summary td {
padding: 0.25em 0;
border-bottom: none;
}
#invoice-summary tr:last-child {
background-color: var(--camper--header--background-color);
}
.invoice-status {
position: relative;
}
.invoice-status summary {
height: 3rem;
display: flex;
cursor: pointer;
justify-content: start;
align-items: center;
}
.invoice-status ul {
list-style: none;
background-color: var(--camper--background-color);
z-index: 20;
position: absolute;
top: 0;
left: 100%;
padding: 2rem;
display: flex;
flex-direction: column;
gap: 1rem;
}
.invoice-status button {
border: 0;
min-width: 15rem;
}
[class^='invoice-status-'] {
cursor: pointer;
}
.invoice-download {
text-align: center;
}
.invoice-download a {
color: inherit;
text-decoration: none;
}
/*</editor-fold>*/
/* <editor-fold desc="Contact"> */
:is(#contact-form, #invoice-form) label + label {
margin-top: 0;
}
:is(#contact-form, #invoice-form) :is(input, select) {
width: 100%;
}
:is(#contact-form, #invoice-form) .customer-details {
display: grid;
gap: .5em;
grid-template-columns: repeat(3, 1fr);
align-content: start;
}
:is(#contact-form, #invoice-form) .customer-details label:nth-of-type(4) {
grid-column: 1 / -1;
}
/*</editor-fold>*/