Files
Luncher/client/src/themes/chiikawa.scss
T
mates 882a2f38a7
CI / Generate TypeScript types (push) Successful in 10s
CI / Server unit tests (push) Successful in 27s
CI / Build server (push) Successful in 29s
CI / Build client (push) Successful in 42s
CI / Playwright E2E tests (push) Successful in 1m58s
CI / Build and push Docker image (push) Successful in 46s
CI / Notify (push) Successful in 2s
feat: nový vzhled Chiikawa
2026-10-27 11:21:44 +01:00

649 lines
20 KiB
SCSS

// ============================================
// STYL "CHIIKAWA" (volitelný, výchozí je jednoduchý styl)
// Inspirováno mangou a anime Chiikawa (ちいかわ) od Nagana.
// Světlý režim = pastelová louka, kde se pleje plevel: krémové nebe,
// dole trsy trávy, silné hnědošedé obrysy jako v manze a tvary jako mochi.
// Karty podniků se střídají v barvách Chiikawy, Hachiware a Usagi, každá
// s obličejem postavy; zpoza titulku dne vykukuje Chiikawa.
// Tmavý režim = hvězdná noc s měsícem, pastelové akcenty září.
// Aktivní, pokud má <html> atribut data-luncher-theme="chiikawa".
// ============================================
$ck: 'html[data-luncher-theme="chiikawa"]';
// Obličeje postav (bílá Chiikawa s kulatýma ušima, Hachiware s modrou „čepičkou", žlutá Usagi s dlouhýma ušima),
// trsy trávy s kytičkou a hvězdná obloha
$ck-chiikawa: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Cg stroke='%234a3f3a' stroke-width='1.8' stroke-linejoin='round'%3E%3Ccircle cx='10' cy='11' r='5' fill='%23fff'/%3E%3Ccircle cx='30' cy='11' r='5' fill='%23fff'/%3E%3Cellipse cx='20' cy='24' rx='16' ry='13' fill='%23fff'/%3E%3Cg stroke='none'%3E%3Ccircle cx='14' cy='23' r='2' fill='%233a302c'/%3E%3Ccircle cx='26' cy='23' r='2' fill='%233a302c'/%3E%3Cellipse cx='10' cy='28' rx='3.2' ry='1.8' fill='%23f7a8b8'/%3E%3Cellipse cx='30' cy='28' rx='3.2' ry='1.8' fill='%23f7a8b8'/%3E%3C/g%3E%3Cpath d='M18 27q2 2 4 0' fill='none' stroke-width='1.4'/%3E%3C/g%3E%3C/svg%3E");
$ck-hachiware: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Cg stroke='%234a3f3a' stroke-width='1.8' stroke-linejoin='round'%3E%3Cpath d='M6 17L9 4L17 11Z' fill='%237aa3d6'/%3E%3Cpath d='M34 17L31 4L23 11Z' fill='%237aa3d6'/%3E%3Cellipse cx='20' cy='24' rx='16' ry='13' fill='%23fff'/%3E%3Cpath d='M5.5 20Q8 11 20 11Q32 11 34.5 20L22.5 20L20 25L17.5 20Z' fill='%237aa3d6' stroke='none'/%3E%3Cg stroke='none'%3E%3Ccircle cx='14' cy='23' r='2' fill='%233a302c'/%3E%3Ccircle cx='26' cy='23' r='2' fill='%233a302c'/%3E%3Cellipse cx='10' cy='28' rx='3.2' ry='1.8' fill='%23f7a8b8'/%3E%3Cellipse cx='30' cy='28' rx='3.2' ry='1.8' fill='%23f7a8b8'/%3E%3C/g%3E%3Cpath d='M17 28q1.5 1.6 3 0q1.5 1.6 3 0' fill='none' stroke-width='1.3'/%3E%3C/g%3E%3C/svg%3E");
$ck-usagi: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Cg stroke='%234a3f3a' stroke-width='1.8' stroke-linejoin='round'%3E%3Cellipse cx='14' cy='9' rx='3.6' ry='8.5' fill='%23f7e08a'/%3E%3Cellipse cx='26' cy='9' rx='3.6' ry='8.5' fill='%23f7e08a'/%3E%3Cellipse cx='20' cy='25' rx='15' ry='12' fill='%23f7e08a'/%3E%3Cg stroke='none'%3E%3Ccircle cx='14' cy='23' r='2' fill='%233a302c'/%3E%3Ccircle cx='26' cy='23' r='2' fill='%233a302c'/%3E%3Cellipse cx='10' cy='28' rx='3.2' ry='1.8' fill='%23f7a8b8'/%3E%3Cellipse cx='30' cy='28' rx='3.2' ry='1.8' fill='%23f7a8b8'/%3E%3C/g%3E%3Cellipse cx='20' cy='29' rx='2' ry='2.4' fill='%23c2455f' stroke-width='1.2'/%3E%3C/g%3E%3C/svg%3E");
$ck-grass: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90' height='28'%3E%3Cpath d='M0 28Q5 14 8 28Q12 8 16 28Q19 16 22 28ZM50 28Q53 18 56 28Q60 6 64 28Q68 14 71 28Q74 20 76 28Z' fill='%239fd18b'/%3E%3Ccircle cx='38' cy='22' r='3' fill='%23fff' stroke='%23f7a8b8' stroke-width='2'/%3E%3C/svg%3E");
$ck-stars: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cg fill='%23fff6c8'%3E%3Ccircle cx='20' cy='30' r='1.4'/%3E%3Ccircle cx='90' cy='14' r='1'/%3E%3Ccircle cx='130' cy='70' r='1.6'/%3E%3Ccircle cx='60' cy='100' r='1'/%3E%3Ccircle cx='110' cy='140' r='1.2'/%3E%3Ccircle cx='30' cy='140' r='0.9'/%3E%3C/g%3E%3Cpath d='M75 60l2 5 5 2-5 2-2 5-2-5-5-2 5-2z' fill='%23ffe58f'/%3E%3C/svg%3E");
#{$ck} {
--ck-font: 'Zen Maru Gothic', 'Nunito', sans-serif;
--ck-display: 'Hachi Maru Pop', 'Zen Maru Gothic', sans-serif;
--ck-ink: #4a3f3a; // obrys jako kresba v manze
--ck-pink: #f7a8b8; // ruměnec Chiikawy
--ck-pink-deep: #c94f74;
--ck-blue: #7aa3d6; // Hachiware
--ck-blue-light: #e3eefb;
--ck-yellow: #f7e08a; // Usagi
--ck-yellow-light: #fff6d2;
--ck-white-pink: #fff1f4; // Chiikawa
--ck-green: #9fd18b; // tráva na pletí
--ck-line: #4a3f3a;
--ck-soft-line: #eadcd6;
--luncher-primary: var(--ck-pink-deep);
--luncher-primary-hover: #b03f62;
--luncher-primary-light: #ffe6ec;
--luncher-bg: #fff8f2;
--luncher-bg-card: #ffffff;
--luncher-bg-hover: #fff1f4;
--luncher-text: var(--ck-ink);
--luncher-text-secondary: #6b5d57;
--luncher-text-muted: #a3938c;
--luncher-border: var(--ck-soft-line);
--luncher-border-light: #f4e9e4;
--luncher-navbar-bg: #ffe3ea;
--luncher-navbar-text: var(--ck-ink);
--luncher-action-icon: var(--ck-pink-deep);
--luncher-buyer-icon: #4a78b5;
--luncher-success: #5a9e4a;
--luncher-warning: #d9a21a;
--luncher-danger: #d9534f;
--luncher-radius-sm: 14px;
--luncher-radius: 18px;
--luncher-radius-lg: 22px;
--luncher-radius-xl: 26px;
--luncher-shadow: 0 3px 0 var(--ck-line);
--luncher-shadow-lg: 0 5px 0 var(--ck-line), 0 10px 22px rgb(74 63 58 / 0.15);
&[data-bs-theme="dark"] {
// Noc pod hvězdami — postavičky už spí
--ck-line: #12152b;
--ck-soft-line: #3a4170;
--ck-white-pink: #3a2f4a;
--ck-blue-light: #283a5c;
--ck-yellow-light: #463f2a;
--luncher-primary: #ff9fb8;
--luncher-primary-hover: #ffbfcf;
--luncher-primary-light: #3d2a42;
--luncher-bg: #1b1f3a;
--luncher-bg-card: #262b4d;
--luncher-bg-hover: #2f355c;
--luncher-text: #f4eef6;
--luncher-text-secondary: #cfc8dc;
--luncher-text-muted: #8e8aab;
--luncher-border-light: #2f355c;
--luncher-navbar-bg: #2a2f55;
--luncher-navbar-text: #f4eef6;
--luncher-action-icon: #ff9fb8;
--luncher-buyer-icon: #9cc3f0;
--luncher-success: #9fd18b;
--luncher-warning: #f7e08a;
--luncher-danger: #ff8a8a;
--luncher-shadow: 0 3px 0 var(--ck-line), 0 6px 16px rgb(0 0 0 / 0.3);
--luncher-shadow-lg: 0 5px 0 var(--ck-line), 0 0 24px rgb(255 159 184 / 0.25);
}
body {
font-family: var(--ck-font);
background-color: var(--luncher-bg);
// Pastelová louka — nahoře růžové nebe, dole trsy trávy s kytičkami
background-image:
#{$ck-grass},
radial-gradient(circle at 15% 0%, rgb(247 168 184 / 0.25), transparent 40%),
radial-gradient(circle at 85% 10%, rgb(122 163 214 / 0.18), transparent 40%),
linear-gradient(180deg, #fff8f2 60%, #f2fae9);
background-size: 90px 28px, 100% 100%, 100% 100%, 100% 100%;
background-position: left bottom, 0 0, 0 0, 0 0;
background-repeat: repeat-x, no-repeat, no-repeat, no-repeat;
background-attachment: fixed;
}
&[data-bs-theme="dark"] body {
// Hvězdná noc s měsícem
background-image:
radial-gradient(circle at 88% 8%, #fff6c8 0 22px, rgb(255 246 200 / 0.25) 24px, transparent 70px),
#{$ck-stars},
linear-gradient(180deg, #1b1f3a, #232a52);
background-size: 100% 100%, 160px 160px, 100% 100%;
background-repeat: no-repeat, repeat, no-repeat;
}
.app-container {
background: transparent;
}
h1, h2, h3, h4, .navbar-brand {
font-family: var(--ck-display);
font-weight: 400;
}
.btn {
font-family: var(--ck-font);
}
// ---------- Navbar: pastelově růžový, u loga obličej Chiikawy ----------
.navbar {
background: var(--luncher-navbar-bg) !important;
border-bottom: 2.5px solid var(--ck-line);
box-shadow: 0 3px 0 rgb(74 63 58 / 0.12);
.navbar-brand {
letter-spacing: 0.02em;
&::after {
content: '';
display: inline-block;
width: 26px;
height: 26px;
margin-left: 6px;
margin-right: 0.6em;
vertical-align: -5px;
background: $ck-chiikawa center / contain no-repeat;
transform-origin: 50% 100%;
animation: ck-wobble 3.2s ease-in-out infinite;
}
}
.dropdown-menu {
border: 2px solid var(--ck-line);
border-radius: var(--luncher-radius);
box-shadow: var(--luncher-shadow);
}
}
&[data-bs-theme="dark"] .navbar {
border-bottom-color: #3a4170;
box-shadow: 0 3px 14px rgb(0 0 0 / 0.35);
}
// ---------- Titulek dne: mochi štítek s ruměncem, zpoza vykukuje Chiikawa ----------
.day-navigator .title {
position: relative;
display: inline-block;
padding: 8px 40px 8px;
margin-top: 14px;
font-family: var(--ck-display);
font-size: 1.6rem;
color: var(--ck-ink) !important;
background:
radial-gradient(ellipse 9px 5px at 26px 58%, var(--ck-pink) 98%, transparent),
radial-gradient(ellipse 9px 5px at calc(100% - 26px) 58%, var(--ck-pink) 98%, transparent),
#ffffff;
border: 2.5px solid var(--ck-line);
border-radius: 999px;
box-shadow: 0 4px 0 var(--ck-line);
// Chiikawa vykukuje zpoza štítku
&::after {
content: '';
position: absolute;
right: 26px;
top: -27px;
width: 34px;
height: 34px;
background: $ck-chiikawa center / contain no-repeat;
// Spodní část, která by překryla štítek, se ořízne — vypadá to, že je schovaná za ním
clip-path: inset(0 0 7px 0);
animation: ck-peek 4s ease-in-out infinite;
}
// Jiskřička radosti
&::before {
content: '✦';
position: absolute;
left: -18px;
top: -10px;
font-size: 0.7em;
color: #e0b93a;
animation: ck-twinkle 1.8s ease-in-out infinite;
}
&.text-muted {
color: var(--luncher-text-muted) !important;
background: #f6efeb;
border-color: #c9bab3;
box-shadow: 0 4px 0 #c9bab3;
// Jiný den — Chiikawa spí a nevykukuje
&::after,
&::before {
display: none;
}
}
}
&[data-bs-theme="dark"] .day-navigator .title {
color: #f4eef6 !important;
background:
radial-gradient(ellipse 9px 5px at 26px 58%, rgb(247 168 184 / 0.7) 98%, transparent),
radial-gradient(ellipse 9px 5px at calc(100% - 26px) 58%, rgb(247 168 184 / 0.7) 98%, transparent),
#3a4170;
border-color: #12152b;
box-shadow: 0 4px 0 #12152b, 0 0 22px rgb(255 159 184 / 0.25);
&.text-muted {
color: var(--luncher-text-muted) !important;
background: #262b4d;
box-shadow: 0 4px 0 #12152b;
}
}
// ---------- Karty podniků: střídají se Chiikawa, Hachiware a Usagi ----------
.restaurant-card {
--ck-card-bg: var(--ck-white-pink);
--ck-card-face: #{$ck-chiikawa};
border: 2.5px solid var(--ck-line);
border-radius: var(--luncher-radius-lg);
box-shadow: var(--luncher-shadow);
overflow: hidden;
background: var(--luncher-bg-card);
transition: transform 0.2s cubic-bezier(.3, 1.6, .5, 1), box-shadow 0.2s ease;
&:hover {
transform: translateY(-3px);
box-shadow: var(--luncher-shadow-lg);
}
.restaurant-header {
background: var(--ck-card-bg);
border-bottom: 2.5px solid var(--ck-line);
// Obličej postavy vpravo v hlavičce
&::after {
content: '';
flex: none;
width: 38px;
height: 38px;
background: var(--ck-card-face) center / contain no-repeat;
transition: transform 0.25s cubic-bezier(.3, 1.6, .5, 1);
}
&:hover {
background: var(--ck-card-bg);
filter: brightness(0.97);
&::after {
transform: translateY(-3px) rotate(-8deg);
}
}
h3 {
color: var(--ck-ink);
font-family: var(--ck-display);
font-weight: 400;
}
small {
color: #8a7a73;
}
}
}
[class*="col"]:nth-child(3n+2) > .restaurant-card {
--ck-card-bg: var(--ck-blue-light);
--ck-card-face: #{$ck-hachiware};
}
[class*="col"]:nth-child(3n) > .restaurant-card {
--ck-card-bg: var(--ck-yellow-light);
--ck-card-face: #{$ck-usagi};
}
&[data-bs-theme="dark"] .restaurant-card {
border-color: #12152b;
.restaurant-header {
border-bottom-color: #12152b;
h3 {
color: #f4eef6;
}
small {
color: #b4aecb;
}
}
}
.food-table {
--bs-table-bg: transparent;
}
.food-table tbody tr:hover > td {
background: #fff1f4;
}
&[data-bs-theme="dark"] .food-table tbody tr:hover > td {
background: #2f355c;
}
.food-price {
color: var(--ck-pink-deep);
font-weight: 900;
}
&[data-bs-theme="dark"] .food-price {
color: #ff9fb8;
}
// ---------- Panely a tabulka voleb ----------
.choice-section,
.choices-table,
.pizza-section,
.no-votes {
border: 2.5px solid var(--ck-line);
border-radius: var(--luncher-radius-lg);
box-shadow: var(--luncher-shadow);
}
.choices-table,
.choices-table .nested-table {
--bs-table-bg: var(--luncher-bg-card);
}
.choices-table {
border-collapse: separate;
border-spacing: 0;
}
// Sloupec s podnikem: růžová tvářička
.choices-table > tbody > tr > td:first-child {
background: var(--ck-white-pink);
color: var(--ck-pink-deep);
font-family: var(--ck-display);
border-right: 2.5px dashed var(--ck-pink);
}
&[data-bs-theme="dark"] {
.choice-section,
.choices-table,
.pizza-section,
.no-votes,
.card {
border-color: #12152b;
}
.choices-table > tbody > tr > td:first-child {
color: #ff9fb8;
}
}
// Bootstrap karty (skupinové objednávky apod.) a seznamy
.card {
border: 2.5px solid var(--ck-line);
border-radius: var(--luncher-radius-lg);
box-shadow: var(--luncher-shadow);
overflow: hidden;
background: var(--luncher-bg-card);
// Rozbalovací výběr z nabídky nesmí karta oříznout
&:has(.select-search-container) {
overflow: visible;
}
> .card-header {
background: var(--ck-white-pink);
border-bottom: 2px dashed var(--ck-pink);
font-family: var(--ck-display);
&:first-child {
border-radius: calc(var(--luncher-radius-lg) - 2px) calc(var(--luncher-radius-lg) - 2px) 0 0;
}
}
.table {
--bs-table-bg: transparent;
margin-bottom: 0;
> :last-child > tr:last-child > * {
border-bottom-width: 0;
}
}
}
.list-group {
border-radius: var(--luncher-radius);
overflow: hidden;
border: 2px solid var(--ck-line);
> .list-group-item {
border-left: none;
border-right: none;
&:first-child {
border-top: none;
}
&:last-child {
border-bottom: none;
}
}
}
.form-select, .form-control,
input[type="text"], input[type="email"], input[type="password"] {
border-radius: var(--luncher-radius-sm);
border: 2px solid var(--ck-soft-line);
&:focus {
border-color: var(--ck-pink-deep);
box-shadow: 0 0 0 3px rgb(247 168 184 / 0.45);
}
}
// ---------- Tlačítka: nálepky ve tvaru mochi, při najetí poskočí ----------
.btn {
border-radius: 999px;
font-weight: 900;
letter-spacing: 0.02em;
transition: transform 0.18s cubic-bezier(.3, 1.6, .5, 1), box-shadow 0.18s ease, background 0.2s ease;
}
.btn-primary {
background: var(--ck-pink-deep);
border: 2px solid var(--ck-line);
color: #fff;
box-shadow: 0 3px 0 var(--ck-line);
&:hover {
background: #d6608a;
border-color: var(--ck-line);
color: #fff;
transform: translateY(-2px);
box-shadow: 0 5px 0 var(--ck-line);
}
&:active {
transform: translateY(2px) !important;
box-shadow: 0 1px 0 var(--ck-line);
}
&:disabled {
background: #f1e6e2;
border-color: #c9bab3;
color: #a3938c;
box-shadow: none;
}
}
.btn-outline-primary {
background: var(--luncher-bg-card);
border: 2px solid var(--ck-line);
color: var(--ck-pink-deep);
box-shadow: 0 3px 0 var(--ck-line);
&:hover {
background: var(--ck-white-pink);
border-color: var(--ck-line);
color: var(--ck-pink-deep);
transform: translateY(-2px);
}
}
// Sekundární — modrá jako Hachiware
.btn-secondary {
background: var(--ck-blue);
border: 2px solid var(--ck-line);
color: #fff;
box-shadow: 0 3px 0 var(--ck-line);
&:hover {
background: #6a93c8;
border-color: var(--ck-line);
color: #fff;
transform: translateY(-2px);
}
}
.btn-danger {
border: 2px solid var(--ck-line);
box-shadow: 0 3px 0 var(--ck-line);
}
.action-icon:hover {
background: var(--luncher-primary-light);
color: var(--luncher-primary);
}
// Tmavý režim: světlé pastelové akcenty potřebují tmavý text
&[data-bs-theme="dark"] {
.btn-primary {
background: #ff9fb8;
color: #2a1f33;
&:hover {
background: #ffbfcf;
color: #2a1f33;
}
&:disabled {
background: #2f355c;
border-color: #12152b;
color: #8e8aab;
}
}
.btn-outline-primary {
color: #ff9fb8;
&:hover {
background: #3d2a42;
color: #ff9fb8;
}
}
.btn-secondary {
background: #9cc3f0;
color: #1b1f3a;
&:hover {
background: #b6d4f5;
color: #1b1f3a;
}
}
.react-datepicker__day--selected,
.react-datepicker__day--keyboard-selected {
color: #2a1f33;
}
}
// ---------- Modaly: velká nálepka s obrysem ----------
.modal-content {
border: 2.5px solid var(--ck-line);
border-radius: var(--luncher-radius-xl);
box-shadow: 0 6px 0 var(--ck-line), 0 18px 40px rgb(74 63 58 / 0.25);
overflow: hidden;
}
.modal-header {
background: var(--luncher-navbar-bg);
border-bottom: 2.5px solid var(--ck-line);
.modal-title, .modal-title h2 {
color: var(--ck-ink);
font-family: var(--ck-display);
font-weight: 400;
}
}
&[data-bs-theme="dark"] {
.modal-content {
border-color: #12152b;
box-shadow: 0 6px 0 #12152b, 0 0 30px rgb(255 159 184 / 0.15);
}
.modal-header {
border-bottom-color: #12152b;
.modal-title, .modal-title h2 {
color: #f4eef6;
}
}
}
// Patička — pruh trávy, kde se pleje plevel
.footer {
border-top: 2.5px solid var(--ck-line);
background:
#{$ck-grass} left top / 90px 28px repeat-x,
var(--luncher-navbar-bg);
padding-top: 34px;
a {
color: var(--ck-pink-deep);
}
}
&[data-bs-theme="dark"] .footer {
border-top-color: #12152b;
background: var(--luncher-navbar-bg);
padding-top: 16px;
a {
color: #ff9fb8;
}
}
}
// Chiikawa se kolébá ze strany na stranu
@keyframes ck-wobble {
0%, 100% { transform: rotate(0deg); }
20% { transform: rotate(-10deg); }
40% { transform: rotate(8deg); }
55% { transform: rotate(0deg); }
}
// Vykukování zpoza štítku — schová se a zase vykoukne (ořez se posouvá s ní)
@keyframes ck-peek {
0%, 15% { transform: translateY(18px); clip-path: inset(0 0 25px 0); }
30%, 75% { transform: translateY(0); clip-path: inset(0 0 7px 0); }
85% { transform: translateY(-2px); clip-path: inset(0 0 5px 0); }
100% { transform: translateY(18px); clip-path: inset(0 0 25px 0); }
}
@keyframes ck-twinkle {
0%, 100% { transform: scale(0.7) rotate(0deg); opacity: 0.4; }
50% { transform: scale(1.15) rotate(20deg); opacity: 1; }
}
@media (max-width: 575.98px) {
#{$ck} .day-navigator .title {
font-size: 1.25rem;
padding: 6px 30px;
}
}
@media (prefers-reduced-motion: reduce) {
#{$ck} .navbar .navbar-brand::after,
#{$ck} .day-navigator .title::after,
#{$ck} .day-navigator .title::before {
animation: none;
}
}