feat: nový vzhled Hatsune Miku
CI / Generate TypeScript types (push) Successful in 10s
CI / Server unit tests (push) Successful in 26s
CI / Build server (push) Successful in 28s
CI / Build client (push) Successful in 42s
CI / Playwright E2E tests (push) Successful in 1m54s
CI / Build and push Docker image (push) Successful in 45s
CI / Notify (push) Successful in 2s
CI / Generate TypeScript types (push) Successful in 10s
CI / Server unit tests (push) Successful in 26s
CI / Build server (push) Successful in 28s
CI / Build client (push) Successful in 42s
CI / Playwright E2E tests (push) Successful in 1m54s
CI / Build and push Docker image (push) Successful in 45s
CI / Notify (push) Successful in 2s
This commit is contained in:
10 files changed
+931
-6
No files matched your search
+2
-2
@@ -11,7 +11,7 @@
|
|||||||
<link rel="manifest" href="/manifest.json" />
|
<link rel="manifest" href="/manifest.json" />
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link href="https://fonts.googleapis.com/css2?family=M+PLUS+Rounded+1c:wght@500;800&family=Nunito:wght@600;800;900&family=Fredoka:wght@500;600;700&family=Shippori+Mincho:wght@600;700;800&family=Zen+Maru+Gothic:wght@500;700;900&family=Yusei+Magic&family=Dela+Gothic+One&family=Barlow+Condensed:wght@500;600;700&family=Kiwi+Maru:wght@400;500&family=Playfair+Display:ital,wght@0,800;1,800&family=Courier+Prime:wght@700&family=Cormorant+Garamond:wght@600;700&family=Baloo+2:wght@600;800&family=Metal+Mania&family=Klee+One:wght@600&display=swap" rel="stylesheet" />
|
<link href="https://fonts.googleapis.com/css2?family=M+PLUS+Rounded+1c:wght@500;800&family=Nunito:wght@600;800;900&family=Fredoka:wght@500;600;700&family=Shippori+Mincho:wght@600;700;800&family=Zen+Maru+Gothic:wght@500;700;900&family=Yusei+Magic&family=Dela+Gothic+One&family=Barlow+Condensed:wght@500;600;700&family=Kiwi+Maru:wght@400;500&family=Playfair+Display:ital,wght@0,800;1,800&family=Courier+Prime:wght@700&family=Cormorant+Garamond:wght@600;700&family=Baloo+2:wght@600;800&family=Metal+Mania&family=Klee+One:wght@600&family=Exo+2:wght@700;800&display=swap" rel="stylesheet" />
|
||||||
<title>Luncher</title>
|
<title>Luncher</title>
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
}
|
}
|
||||||
document.documentElement.setAttribute('data-bs-theme', theme);
|
document.documentElement.setAttribute('data-bs-theme', theme);
|
||||||
var style = localStorage.getItem('style_theme');
|
var style = localStorage.getItem('style_theme');
|
||||||
var styles = ['umamusume', 'mlp', 'hellgirl', 'kon', 'bocchi', 'evangelion', 'yurucamp', 'spyfamily', 'apothecary', 'frieren', 'mlpg5', 'aggretsuko', 'sumikko', 'gudetama'];
|
var styles = ['umamusume', 'mlp', 'hellgirl', 'kon', 'bocchi', 'evangelion', 'yurucamp', 'spyfamily', 'apothecary', 'frieren', 'mlpg5', 'aggretsuko', 'sumikko', 'gudetama', 'miku'];
|
||||||
document.documentElement.setAttribute('data-luncher-theme', styles.indexOf(style) >= 0 ? style : 'simple');
|
document.documentElement.setAttribute('data-luncher-theme', styles.indexOf(style) >= 0 ? style : 'simple');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Fallback pokud localStorage není dostupný
|
// Fallback pokud localStorage není dostupný
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import './themes/mlpg5.scss';
|
|||||||
import './themes/aggretsuko.scss';
|
import './themes/aggretsuko.scss';
|
||||||
import './themes/sumikko.scss';
|
import './themes/sumikko.scss';
|
||||||
import './themes/gudetama.scss';
|
import './themes/gudetama.scss';
|
||||||
|
import './themes/miku.scss';
|
||||||
import { faCircleCheck, faNoteSticky, faTrashCan, faComment } from '@fortawesome/free-regular-svg-icons';
|
import { faCircleCheck, faNoteSticky, faTrashCan, faComment } from '@fortawesome/free-regular-svg-icons';
|
||||||
import { useSettings } from './context/settings';
|
import { useSettings } from './context/settings';
|
||||||
import Footer from './components/Footer';
|
import Footer from './components/Footer';
|
||||||
|
|||||||
@@ -175,6 +175,17 @@
|
|||||||
box-shadow: 0 0 0 2px #f5b301;
|
box-shadow: 0 0 0 2px #f5b301;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Styl Hatsune Miku: emoji v bílém kroužku s tyrkysovou září
|
||||||
|
.eater-badge-miku {
|
||||||
|
display: inline-grid;
|
||||||
|
place-items: center;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1;
|
||||||
|
border-color: #fff;
|
||||||
|
background: radial-gradient(circle at 40% 35%, #ffffff, #dff5f3);
|
||||||
|
box-shadow: 0 0 0 2px #39c5bb, 0 0 8px rgb(57 197 187 / 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
// Odznak a jméno drží na jednom řádku (úzký sloupec „Člen" na stránce objednávek)
|
// Odznak a jméno drží na jednom řádku (úzký sloupec „Člen" na stránce objednávek)
|
||||||
.user-info:has(.eater-badge) {
|
.user-info:has(.eater-badge) {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|||||||
@@ -91,6 +91,12 @@ const GT_LEVELS = [
|
|||||||
{ minItems: 2, emoji: '🥓', title: 'Úroveň slaniny — k obědu ještě plátek slaniny… ale jen jako deka' },
|
{ minItems: 2, emoji: '🥓', title: 'Úroveň slaniny — k obědu ještě plátek slaniny… ale jen jako deka' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/** Úrovně ve stylu Hatsune Miku — emoji v kroužku s tyrkysovou září. Seřazeno od nejvyšší úrovně. */
|
||||||
|
const MIKU_LEVELS = [
|
||||||
|
{ minItems: 3, emoji: '🍨', title: 'Úroveň Kaito — po obědě ještě zmrzlina, klidně i v zimě' },
|
||||||
|
{ minItems: 2, emoji: '🥬', title: 'Úroveň Miku — k obědu ještě pórek, ať se dá točit nad hlavou' },
|
||||||
|
];
|
||||||
|
|
||||||
/** Úrovně podle stylu pro odznaky s emoji. */
|
/** Úrovně podle stylu pro odznaky s emoji. */
|
||||||
const EMOJI_LEVELS: Partial<Record<StyleTheme, typeof MLP_LEVELS>> = {
|
const EMOJI_LEVELS: Partial<Record<StyleTheme, typeof MLP_LEVELS>> = {
|
||||||
mlp: MLP_LEVELS,
|
mlp: MLP_LEVELS,
|
||||||
@@ -106,6 +112,7 @@ const EMOJI_LEVELS: Partial<Record<StyleTheme, typeof MLP_LEVELS>> = {
|
|||||||
aggretsuko: AGG_LEVELS,
|
aggretsuko: AGG_LEVELS,
|
||||||
sumikko: SK_LEVELS,
|
sumikko: SK_LEVELS,
|
||||||
gudetama: GT_LEVELS,
|
gudetama: GT_LEVELS,
|
||||||
|
miku: MIKU_LEVELS,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -113,7 +120,7 @@ type Props = {
|
|||||||
items: number,
|
items: number,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Odznak s postavou u strávníků s více jídly — jen ve stylech Umamusume, My Little Pony, Hell Girl, K-ON!, Bocchi the Rock!, Evangelion, Yuru Camp△, Spy × Family, Apothecary Diaries, Frieren, My Little Pony G5, Aggretsuko, Sumikko Gurashi a Gudetama. */
|
/** Odznak s postavou u strávníků s více jídly — jen ve stylech Umamusume, My Little Pony, Hell Girl, K-ON!, Bocchi the Rock!, Evangelion, Yuru Camp△, Spy × Family, Apothecary Diaries, Frieren, My Little Pony G5, Aggretsuko, Sumikko Gurashi, Gudetama a Hatsune Miku. */
|
||||||
export default function EaterBadge({ items }: Readonly<Props>) {
|
export default function EaterBadge({ items }: Readonly<Props>) {
|
||||||
const styleTheme = useSettings()?.styleTheme;
|
const styleTheme = useSettings()?.styleTheme;
|
||||||
const isUma = styleTheme === 'umamusume';
|
const isUma = styleTheme === 'umamusume';
|
||||||
|
|||||||
@@ -1191,3 +1191,87 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// Konfety ve stylu Hatsune Miku
|
||||||
|
// ============================================
|
||||||
|
.confetti-miku {
|
||||||
|
filter: drop-shadow(0 0 6px rgb(57 197 187 / 0.6)) drop-shadow(0 3px 3px rgb(0 0 0 / 0.2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Štítky jako noty z piano rollu — zaoblený obdélník se světlejším horním okrajem
|
||||||
|
.confetti-miku-badge {
|
||||||
|
padding: 3px 14px 4px;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid rgb(255 255 255 / 0.5);
|
||||||
|
box-shadow: inset 0 2px 0 rgb(255 255 255 / 0.3);
|
||||||
|
color: #fff;
|
||||||
|
font-family: 'Exo 2', 'Nunito', sans-serif;
|
||||||
|
font-weight: 800;
|
||||||
|
font-size: 1.15rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nápis „♪ 初音ミク ♪" — velkoplošná obrazovka na koncertě, světla pulzují do rytmu
|
||||||
|
.confetti-miku-banner {
|
||||||
|
position: absolute;
|
||||||
|
top: 38%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
padding: 16px 48px 22px;
|
||||||
|
font-family: 'Exo 2', 'Nunito', sans-serif;
|
||||||
|
font-weight: 800;
|
||||||
|
font-size: clamp(2rem, 7vw, 4.2rem);
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
white-space: nowrap;
|
||||||
|
color: #e9fffd;
|
||||||
|
text-shadow: 0 0 10px #39c5bb, 0 0 26px #39c5bb;
|
||||||
|
background:
|
||||||
|
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='98' height='10'%3E%3Crect width='98' height='10' fill='%23ffffff'/%3E%3Cpath d='M14 0V10M28 0V10M42 0V10M56 0V10M70 0V10M84 0V10M98 0V10' stroke='%239aa3a8'/%3E%3Cpath d='M10 0h8v6h-8zM24 0h8v6h-8zM52 0h8v6h-8zM66 0h8v6h-8zM80 0h8v6h-8z' fill='%232b2f33'/%3E%3C/svg%3E") left bottom / 98px 10px repeat-x,
|
||||||
|
#0b0d10;
|
||||||
|
border: 2px solid #39c5bb;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 0 0 4px rgb(225 40 133 / 0.5), 0 0 40px rgb(57 197 187 / 0.6);
|
||||||
|
animation: miku-banner 2.6s ease both;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes miku-banner {
|
||||||
|
0% { transform: translate(-50%, -50%) scale(0.4); opacity: 0; }
|
||||||
|
12% { transform: translate(-50%, -50%) scale(1.05); opacity: 1; }
|
||||||
|
18%, 80% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
|
||||||
|
// Pulz do rytmu
|
||||||
|
30%, 54% { box-shadow: 0 0 0 4px rgb(225 40 133 / 0.8), 0 0 60px rgb(57 197 187 / 0.9); }
|
||||||
|
42%, 66% { box-shadow: 0 0 0 4px rgb(225 40 133 / 0.4), 0 0 30px rgb(57 197 187 / 0.5); }
|
||||||
|
100% { transform: translate(-50%, -50%) scale(0.92); opacity: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vocaloid s hláškou — kruh s tyrkysovou září a bublina jako okno editoru
|
||||||
|
.confetti-miku-voice {
|
||||||
|
.confetti-mlp-avatar {
|
||||||
|
border: 3px solid #fff;
|
||||||
|
background: radial-gradient(circle at 40% 35%, #ffffff, #dff5f3);
|
||||||
|
box-shadow: 0 0 0 3px var(--mlp-speaker, #39c5bb), 0 0 18px rgb(57 197 187 / 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.confetti-mlp-bubble {
|
||||||
|
background: #ffffff;
|
||||||
|
color: #263036;
|
||||||
|
border: 1px solid #d8e3e6;
|
||||||
|
border-top: 4px solid var(--mlp-speaker, #39c5bb);
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 8px 20px rgb(0 0 0 / 0.25);
|
||||||
|
font-family: 'Nunito', sans-serif;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-family: 'Exo 2', 'Nunito', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
border-right-color: #d8e3e6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -211,6 +211,21 @@ const GT_SPEAKERS = [
|
|||||||
{ name: 'Gudetama v ramenu', emoji: '🍜', color: '#d9a066', quote: 'Plavu si tu v ramenu… vývar je teplý, nechce se mi ven.' },
|
{ name: 'Gudetama v ramenu', emoji: '🍜', color: '#d9a066', quote: 'Plavu si tu v ramenu… vývar je teplý, nechce se mi ven.' },
|
||||||
{ name: 'Gudetama na rýži', emoji: '🍚', color: '#a3927c', quote: 'Na rýži se leží nejlíp… itadakimasu… zítra.' },
|
{ name: 'Gudetama na rýži', emoji: '🍚', color: '#a3927c', quote: 'Na rýži se leží nejlíp… itadakimasu… zítra.' },
|
||||||
];
|
];
|
||||||
|
const MIKU_EMOJI = ['🎵', '🎶', '🎤', '🥬', '💙', '🎹', '🎧', '✨', '🍊', '🍌', '🐟', '🍨', '🌟', '🎼'];
|
||||||
|
// Hlášky z fandomu Vocaloidů (Ievan Polkka, World is Mine, Senbonzakura, 39 = „děkuji"...)
|
||||||
|
const MIKU_BADGES = ['初音ミク', '01', 'Ievan Polkka', 'World is Mine', 'Senbonzakura', 'Magical Mirai', 'Pórek!', '39!', 'Miku Miku Beam!', 'Přídavek!'];
|
||||||
|
const MIKU_BADGE_COLORS = ['#39c5bb', '#138f87', '#e12885', '#3a3f44', '#e0245e', '#3a6fd8'];
|
||||||
|
/** Vocaloidi (a Teto) s „hláškou" po finálním výsledku. */
|
||||||
|
const MIKU_SPEAKERS = [
|
||||||
|
{ name: 'Hatsune Miku', emoji: '🥬', color: '#39c5bb', quote: 'To zní skvěle! Po obědě vám zazpívám — a přinesu pórek!' },
|
||||||
|
{ name: 'Kagamine Rin', emoji: '🍊', color: '#f2a900', quote: 'Já chci tohle! A pak pomeranč. Hned!' },
|
||||||
|
{ name: 'Kagamine Len', emoji: '🍌', color: '#d9b31a', quote: 'Dobře, souhlasím… ale banán si dám jako dezert.' },
|
||||||
|
{ name: 'Megurine Luka', emoji: '🐟', color: '#e88aa8', quote: 'Elegantní volba. Nemají tam náhodou tuňáka?' },
|
||||||
|
{ name: 'Kaito', emoji: '🍨', color: '#3a6fd8', quote: 'Super! A po obědě zmrzlina. Jo, i když je říjen.' },
|
||||||
|
{ name: 'Meiko', emoji: '🍶', color: '#c8302c', quote: 'Výborně, a k tomu jedno saké… je přece po práci, ne? …Není?' },
|
||||||
|
{ name: 'GUMI', emoji: '🥕', color: '#6fbf3a', quote: 'Mrkvičku si k tomu dám taky! Ať mám hlas jako zvonek.' },
|
||||||
|
{ name: 'Kasane Teto', emoji: '🥖', color: '#d9405e', quote: 'Já si dám bagetu. Jako vždycky. Jsem přece Teto!' },
|
||||||
|
];
|
||||||
/** Styly, jejichž konfety tvoří emoji a samolepky s hláškami (a po finále promluví postava s emoji). */
|
/** Styly, jejichž konfety tvoří emoji a samolepky s hláškami (a po finále promluví postava s emoji). */
|
||||||
const EMOJI_CONFETTI: Partial<Record<WheelTheme, {
|
const EMOJI_CONFETTI: Partial<Record<WheelTheme, {
|
||||||
prefix: string, badges: string[], colors: string[], emoji: string[],
|
prefix: string, badges: string[], colors: string[], emoji: string[],
|
||||||
@@ -230,6 +245,7 @@ const EMOJI_CONFETTI: Partial<Record<WheelTheme, {
|
|||||||
aggretsuko: { prefix: 'confetti-agg', badges: AGG_BADGES, colors: AGG_BADGE_COLORS, emoji: AGG_EMOJI, speakers: AGG_SPEAKERS, banner: '🤘 RAAAAAH!!! 🎤' },
|
aggretsuko: { prefix: 'confetti-agg', badges: AGG_BADGES, colors: AGG_BADGE_COLORS, emoji: AGG_EMOJI, speakers: AGG_SPEAKERS, banner: '🤘 RAAAAAH!!! 🎤' },
|
||||||
sumikko: { prefix: 'confetti-sk', badges: SK_BADGES, colors: SK_BADGE_COLORS, emoji: SK_EMOJI, speakers: SK_SPEAKERS, banner: '🍤 すみっコぐらし 🐧' },
|
sumikko: { prefix: 'confetti-sk', badges: SK_BADGES, colors: SK_BADGE_COLORS, emoji: SK_EMOJI, speakers: SK_SPEAKERS, banner: '🍤 すみっコぐらし 🐧' },
|
||||||
gudetama: { prefix: 'confetti-gt', badges: GT_BADGES, colors: GT_BADGE_COLORS, emoji: GT_EMOJI, speakers: GT_SPEAKERS, banner: '🍳 ぐでたま… 🥓' },
|
gudetama: { prefix: 'confetti-gt', badges: GT_BADGES, colors: GT_BADGE_COLORS, emoji: GT_EMOJI, speakers: GT_SPEAKERS, banner: '🍳 ぐでたま… 🥓' },
|
||||||
|
miku: { prefix: 'confetti-miku', badges: MIKU_BADGES, colors: MIKU_BADGE_COLORS, emoji: MIKU_EMOJI, speakers: MIKU_SPEAKERS, banner: '♪ 初音ミク ♪' },
|
||||||
};
|
};
|
||||||
const DURATION_MS = 6400;
|
const DURATION_MS = 6400;
|
||||||
|
|
||||||
@@ -383,7 +399,7 @@ export default function WheelConfetti({ theme, burstKey, big = false }: Readonly
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [burstKey]);
|
}, [burstKey]);
|
||||||
|
|
||||||
// Ostatní tematické styly: hlášku pronese náhodná postava (Mane 6, Ai Enma, Houkago Tea Time, Kessoku Band, piloti NERV, Nokuru, Forgerovi, vnitřní palác, družina Frieren, poníci z Maretime Bay, kancelář Retsuko, postavičky z koutků, Gudetama...)
|
// Ostatní tematické styly: hlášku pronese náhodná postava (Mane 6, Ai Enma, Houkago Tea Time, Kessoku Band, piloti NERV, Nokuru, Forgerovi, vnitřní palác, družina Frieren, poníci z Maretime Bay, kancelář Retsuko, postavičky z koutků, Gudetama, Vocaloidi...)
|
||||||
const emojiConfetti = EMOJI_CONFETTI[theme];
|
const emojiConfetti = EMOJI_CONFETTI[theme];
|
||||||
const emojiSpeaker = useMemo(
|
const emojiSpeaker = useMemo(
|
||||||
() => big && emojiConfetti ? pick(emojiConfetti.speakers) : undefined,
|
() => big && emojiConfetti ? pick(emojiConfetti.speakers) : undefined,
|
||||||
|
|||||||
@@ -3914,6 +3914,262 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// STYL HATSUNE MIKU kola štěstí (dle stylu zvoleného v nastavení).
|
||||||
|
// Výseče v barvách Vocaloidů (Miku, Luka, Rin, Kaito, Meiko, šedá rukávů),
|
||||||
|
// bílé linky a střed jako reproduktor s tyrkysovým lemem.
|
||||||
|
// ============================================
|
||||||
|
.spin-wheel-modal.spin-theme-miku {
|
||||||
|
--miku-font: 'Nunito', sans-serif;
|
||||||
|
--miku-display: 'Exo 2', 'Nunito', sans-serif;
|
||||||
|
--miku-teal: #39c5bb;
|
||||||
|
--miku-teal-deep: #138f87;
|
||||||
|
--miku-teal-ink: #137a7f;
|
||||||
|
--miku-pink: #e12885;
|
||||||
|
--miku-grey: #3a3f44;
|
||||||
|
--miku-line: #d8e3e6;
|
||||||
|
--miku-panel: #ffffff;
|
||||||
|
--miku-text: #263036;
|
||||||
|
--wheel-c0: #2fb3a9;
|
||||||
|
--wheel-c1: #e12885;
|
||||||
|
--wheel-c2: #5a6268;
|
||||||
|
--wheel-c3: #e0a000;
|
||||||
|
--wheel-c4: #3a6fd8;
|
||||||
|
--wheel-c5: #c8302c;
|
||||||
|
--wheel-rim: #3a3f44;
|
||||||
|
--wheel-hub: #2b2f33;
|
||||||
|
|
||||||
|
font-family: var(--miku-font);
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
border: 1px solid var(--miku-line);
|
||||||
|
border-radius: 16px;
|
||||||
|
overflow: hidden;
|
||||||
|
background:
|
||||||
|
linear-gradient(90deg, rgb(57 197 187 / 0.12) 1px, transparent 1px) 0 0 / 88px 100%,
|
||||||
|
repeating-linear-gradient(180deg, #f6fafb 0 22px, #edf3f5 22px 44px);
|
||||||
|
color: var(--miku-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
background:
|
||||||
|
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='98' height='10'%3E%3Crect width='98' height='10' fill='%23ffffff'/%3E%3Cpath d='M14 0V10M28 0V10M42 0V10M56 0V10M70 0V10M84 0V10M98 0V10' stroke='%239aa3a8'/%3E%3Cpath d='M10 0h8v6h-8zM24 0h8v6h-8zM52 0h8v6h-8zM66 0h8v6h-8zM80 0h8v6h-8z' fill='%232b2f33'/%3E%3C/svg%3E") left bottom / 98px 10px repeat-x,
|
||||||
|
linear-gradient(var(--miku-teal), var(--miku-teal)) left bottom 10px / 100% 3px no-repeat,
|
||||||
|
linear-gradient(180deg, #454b51, var(--miku-grey));
|
||||||
|
border-bottom: none;
|
||||||
|
padding-bottom: calc(var(--bs-modal-header-padding-y, 1rem) + 13px);
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: #fff;
|
||||||
|
font-family: var(--miku-display);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-close {
|
||||||
|
filter: invert(1) grayscale(1) brightness(2);
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-footer {
|
||||||
|
border-top: 1px solid var(--miku-line);
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-steps span {
|
||||||
|
font-family: var(--miku-display);
|
||||||
|
font-weight: 700;
|
||||||
|
background: #e3eaed;
|
||||||
|
color: #8a979e;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 3px 16px;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: var(--miku-teal-deep);
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 0 10px rgb(57 197 187 / 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.done {
|
||||||
|
background: var(--miku-pink);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
font-family: var(--miku-font);
|
||||||
|
font-weight: 800;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background: linear-gradient(180deg, #23a99f, var(--miku-teal-deep));
|
||||||
|
border: 1px solid #0e7a73;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background: linear-gradient(180deg, #2fb3a9, #179a91);
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 0 0 3px rgb(57 197 187 / 0.3), 0 0 16px rgb(57 197 187 / 0.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background: #cfd8dc;
|
||||||
|
border-color: #cfd8dc;
|
||||||
|
color: #8a979e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tlačítko roztočení — „play"
|
||||||
|
.spin-button {
|
||||||
|
font-family: var(--miku-display);
|
||||||
|
font-weight: 800;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
padding: 10px 38px;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '▶ ';
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline-primary {
|
||||||
|
background: var(--miku-panel);
|
||||||
|
border: 1px solid var(--miku-teal);
|
||||||
|
color: var(--miku-teal-ink);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #e0f6f4;
|
||||||
|
color: var(--miku-teal-ink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background: var(--miku-pink);
|
||||||
|
border: 1px solid #b81e6c;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-source {
|
||||||
|
background: #e3eaed;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
> .btn {
|
||||||
|
border-radius: 6px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .btn-outline-primary {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--miku-text);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--miku-panel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-result {
|
||||||
|
font-weight: 800;
|
||||||
|
|
||||||
|
strong {
|
||||||
|
color: var(--miku-teal-ink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-options {
|
||||||
|
background: var(--miku-panel);
|
||||||
|
border: 1px solid var(--miku-line);
|
||||||
|
border-radius: 12px;
|
||||||
|
|
||||||
|
li:hover {
|
||||||
|
background: #eef8f7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-options-header {
|
||||||
|
border-bottom: 2px solid var(--miku-teal);
|
||||||
|
color: var(--miku-teal-ink);
|
||||||
|
font-family: var(--miku-display);
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-empty {
|
||||||
|
border-color: var(--miku-line);
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-wheel-pointer {
|
||||||
|
border-top-color: var(--miku-pink);
|
||||||
|
filter: drop-shadow(0 0 4px rgb(225 40 133 / 0.6));
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-wheel-hub {
|
||||||
|
stroke: var(--miku-teal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-seg {
|
||||||
|
stroke: #fff;
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-seg-label {
|
||||||
|
font-family: var(--miku-display);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tmavý režim — koncert
|
||||||
|
[data-bs-theme="dark"] .spin-wheel-modal.spin-theme-miku {
|
||||||
|
--miku-teal-ink: #5fd6cd;
|
||||||
|
--miku-line: #23303a;
|
||||||
|
--miku-panel: #14191d;
|
||||||
|
--miku-text: #eef4f6;
|
||||||
|
--wheel-c2: #3a4248;
|
||||||
|
--wheel-rim: #050607;
|
||||||
|
--wheel-hub: #050607;
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
border-color: #23303a;
|
||||||
|
background:
|
||||||
|
linear-gradient(115deg, transparent 38%, rgb(57 197 187 / 0.10) 46%, transparent 54%),
|
||||||
|
linear-gradient(-115deg, transparent 38%, rgb(225 40 133 / 0.09) 46%, transparent 54%),
|
||||||
|
#0b0d10;
|
||||||
|
box-shadow: 0 0 30px rgb(57 197 187 / 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
background:
|
||||||
|
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='98' height='10'%3E%3Crect width='98' height='10' fill='%23ffffff'/%3E%3Cpath d='M14 0V10M28 0V10M42 0V10M56 0V10M70 0V10M84 0V10M98 0V10' stroke='%239aa3a8'/%3E%3Cpath d='M10 0h8v6h-8zM24 0h8v6h-8zM52 0h8v6h-8zM66 0h8v6h-8zM80 0h8v6h-8z' fill='%232b2f33'/%3E%3C/svg%3E") left bottom / 98px 10px repeat-x,
|
||||||
|
linear-gradient(var(--miku-teal), var(--miku-teal)) left bottom 10px / 100% 2px no-repeat,
|
||||||
|
#101417;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-steps span:not(.active):not(.done) {
|
||||||
|
background: #1b2328;
|
||||||
|
color: #82919a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:disabled {
|
||||||
|
background: #23303a;
|
||||||
|
border-color: #23303a;
|
||||||
|
color: #82919a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline-primary:hover {
|
||||||
|
background: #12302e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-source {
|
||||||
|
background: #1b2328;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-options li:hover {
|
||||||
|
background: #1b2328;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-seg {
|
||||||
|
stroke: #0b0d10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Ikona kola se při najetí pootočí
|
// Ikona kola se při najetí pootočí
|
||||||
.spin-wheel-icon {
|
.spin-wheel-icon {
|
||||||
transition: transform 0.4s ease !important;
|
transition: transform 0.4s ease !important;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const AUTO_ORDER_CHOICE_KEY = 'auto_order_choice';
|
|||||||
export type ThemePreference = 'system' | 'light' | 'dark';
|
export type ThemePreference = 'system' | 'light' | 'dark';
|
||||||
|
|
||||||
/** Vizuální styl aplikace (nezávislý na světlém/tmavém režimu). */
|
/** Vizuální styl aplikace (nezávislý na světlém/tmavém režimu). */
|
||||||
export type StyleTheme = 'simple' | 'umamusume' | 'mlp' | 'hellgirl' | 'kon' | 'bocchi' | 'evangelion' | 'yurucamp' | 'spyfamily' | 'apothecary' | 'frieren' | 'mlpg5' | 'aggretsuko' | 'sumikko' | 'gudetama';
|
export type StyleTheme = 'simple' | 'umamusume' | 'mlp' | 'hellgirl' | 'kon' | 'bocchi' | 'evangelion' | 'yurucamp' | 'spyfamily' | 'apothecary' | 'frieren' | 'mlpg5' | 'aggretsuko' | 'sumikko' | 'gudetama' | 'miku';
|
||||||
|
|
||||||
export const STYLE_THEMES: { value: StyleTheme, label: string }[] = [
|
export const STYLE_THEMES: { value: StyleTheme, label: string }[] = [
|
||||||
{ value: 'simple', label: 'Jednoduchý' },
|
{ value: 'simple', label: 'Jednoduchý' },
|
||||||
@@ -31,6 +31,7 @@ export const STYLE_THEMES: { value: StyleTheme, label: string }[] = [
|
|||||||
{ value: 'aggretsuko', label: 'Aggretsuko' },
|
{ value: 'aggretsuko', label: 'Aggretsuko' },
|
||||||
{ value: 'sumikko', label: 'Sumikko Gurashi' },
|
{ value: 'sumikko', label: 'Sumikko Gurashi' },
|
||||||
{ value: 'gudetama', label: 'Gudetama' },
|
{ value: 'gudetama', label: 'Gudetama' },
|
||||||
|
{ value: 'miku', label: 'Hatsune Miku' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export type SettingsContextProps = {
|
export type SettingsContextProps = {
|
||||||
@@ -262,7 +263,7 @@ function useProvideSettings(): SettingsContextProps {
|
|||||||
}, [autoOrderChoice]);
|
}, [autoOrderChoice]);
|
||||||
|
|
||||||
// Aplikuje accent barvy při změně hue nebo přepnutí světlý/tmavý.
|
// Aplikuje accent barvy při změně hue nebo přepnutí světlý/tmavý.
|
||||||
// Tematické styly (Umamusume, My Little Pony, Hell Girl, K-ON!, Bocchi the Rock!, Evangelion, Yuru Camp△, Spy × Family, Apothecary Diaries, Frieren, My Little Pony G5, Aggretsuko, Sumikko Gurashi, Gudetama) mají vlastní pevnou paletu, accent barvu proto uplatňuje jen jednoduchý styl.
|
// Tematické styly (Umamusume, My Little Pony, Hell Girl, K-ON!, Bocchi the Rock!, Evangelion, Yuru Camp△, Spy × Family, Apothecary Diaries, Frieren, My Little Pony G5, Aggretsuko, Sumikko Gurashi, Gudetama, Hatsune Miku) mají vlastní pevnou paletu, accent barvu proto uplatňuje jen jednoduchý styl.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
localStorage.setItem(ACCENT_HUE_KEY, String(accentHue));
|
localStorage.setItem(ACCENT_HUE_KEY, String(accentHue));
|
||||||
if (styleTheme === 'simple') {
|
if (styleTheme === 'simple') {
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ const ICONS: Record<StyleTheme, Record<GameId, string>> = {
|
|||||||
sumikko: { drawing: '✏️' },
|
sumikko: { drawing: '✏️' },
|
||||||
// Vajíčko — kreslit se mu ale stejně nechce
|
// Vajíčko — kreslit se mu ale stejně nechce
|
||||||
gudetama: { drawing: '🥚' },
|
gudetama: { drawing: '🥚' },
|
||||||
|
// Klávesy zpěvového editoru
|
||||||
|
miku: { drawing: '🎹' },
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Styl z <html data-luncher-theme> — pro místa mimo React kontext nastavení. */
|
/** Styl z <html data-luncher-theme> — pro místa mimo React kontext nastavení. */
|
||||||
|
|||||||
@@ -0,0 +1,547 @@
|
|||||||
|
// ============================================
|
||||||
|
// STYL "HATSUNE MIKU" (volitelný, výchozí je jednoduchý styl)
|
||||||
|
// Inspirováno virtuální zpěvačkou Hatsune Miku (初音ミク).
|
||||||
|
// Světlý režim = zpěvový editor Vocaloid: pozadí jako piano roll, Mikina
|
||||||
|
// tyrkysová, šedá z rukávů, růžová a červené „01" z jejího ramene.
|
||||||
|
// Hlavičky lemuje pruh klávesnice, u loga poskakuje ekvalizér.
|
||||||
|
// Tmavý režim = koncert Magical Mirai: černé pódium, reflektory a dole
|
||||||
|
// moře tyrkysových a růžových světelných tyčinek.
|
||||||
|
// Aktivní, pokud má <html> atribut data-luncher-theme="miku".
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
$miku: 'html[data-luncher-theme="miku"]';
|
||||||
|
|
||||||
|
// Pruh klávesnice — jedna oktáva (7 bílých a 5 černých kláves), opakuje se vodorovně
|
||||||
|
$miku-keys: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='98' height='10'%3E%3Crect width='98' height='10' fill='%23ffffff'/%3E%3Cpath d='M14 0V10M28 0V10M42 0V10M56 0V10M70 0V10M84 0V10M98 0V10' stroke='%239aa3a8'/%3E%3Cpath d='M10 0h8v6h-8zM24 0h8v6h-8zM52 0h8v6h-8zM66 0h8v6h-8zM80 0h8v6h-8z' fill='%232b2f33'/%3E%3C/svg%3E");
|
||||||
|
|
||||||
|
// Světelné tyčinky publika (tyrkysové a růžová) se září, opakují se vodorovně
|
||||||
|
$miku-glowsticks: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='56'%3E%3Cg stroke-linecap='round'%3E%3Cpath d='M12 56L18 24' stroke='%2339c5bb' stroke-opacity='.25' stroke-width='9'/%3E%3Cpath d='M12 56L18 24' stroke='%237ff0e6' stroke-width='3'/%3E%3Cpath d='M38 56L34 18' stroke='%23e12885' stroke-opacity='.25' stroke-width='9'/%3E%3Cpath d='M38 56L34 18' stroke='%23ff7ab8' stroke-width='3'/%3E%3Cpath d='M60 56L64 28' stroke='%2339c5bb' stroke-opacity='.25' stroke-width='9'/%3E%3Cpath d='M60 56L64 28' stroke='%237ff0e6' stroke-width='3'/%3E%3C/g%3E%3C/svg%3E");
|
||||||
|
|
||||||
|
#{$miku} {
|
||||||
|
--miku-font: 'Nunito', -apple-system, sans-serif;
|
||||||
|
--miku-display: 'Exo 2', 'Nunito', sans-serif;
|
||||||
|
--miku-teal: #39c5bb; // Mikina tyrkysová
|
||||||
|
--miku-teal-deep: #138f87;
|
||||||
|
--miku-teal-ink: #137a7f;
|
||||||
|
--miku-pink: #e12885;
|
||||||
|
--miku-grey: #3a3f44; // rukávy a sukně
|
||||||
|
--miku-red: #e0245e; // „01" na rameni
|
||||||
|
--miku-line: #d8e3e6;
|
||||||
|
|
||||||
|
--luncher-primary: var(--miku-teal-ink);
|
||||||
|
--luncher-primary-hover: #0e5f63;
|
||||||
|
--luncher-primary-light: #e0f6f4;
|
||||||
|
--luncher-bg: #f3f7f8;
|
||||||
|
--luncher-bg-card: #ffffff;
|
||||||
|
--luncher-bg-hover: #eef8f7;
|
||||||
|
--luncher-text: #263036;
|
||||||
|
--luncher-text-secondary: #4f5d66;
|
||||||
|
--luncher-text-muted: #8a979e;
|
||||||
|
--luncher-border: var(--miku-line);
|
||||||
|
--luncher-border-light: #e8eff1;
|
||||||
|
--luncher-navbar-bg: var(--miku-grey);
|
||||||
|
--luncher-navbar-text: #ffffff;
|
||||||
|
--luncher-action-icon: var(--miku-teal-ink);
|
||||||
|
--luncher-buyer-icon: var(--miku-pink);
|
||||||
|
--luncher-success: #2a9d6a;
|
||||||
|
--luncher-warning: #e0a000;
|
||||||
|
--luncher-danger: var(--miku-red);
|
||||||
|
--luncher-radius-sm: 6px;
|
||||||
|
--luncher-radius: 10px;
|
||||||
|
--luncher-radius-lg: 12px;
|
||||||
|
--luncher-radius-xl: 16px;
|
||||||
|
--luncher-shadow: 0 3px 12px rgb(38 48 54 / 0.08);
|
||||||
|
--luncher-shadow-lg: 0 0 0 1px var(--miku-teal), 0 10px 26px rgb(57 197 187 / 0.25);
|
||||||
|
|
||||||
|
&[data-bs-theme="dark"] {
|
||||||
|
// Koncert Magical Mirai
|
||||||
|
--miku-teal-ink: #5fd6cd;
|
||||||
|
--miku-line: #23303a;
|
||||||
|
|
||||||
|
--luncher-primary: #5fd6cd;
|
||||||
|
--luncher-primary-hover: #8ae6df;
|
||||||
|
--luncher-primary-light: #12302e;
|
||||||
|
--luncher-bg: #0b0d10;
|
||||||
|
--luncher-bg-card: #14191d;
|
||||||
|
--luncher-bg-hover: #1b2328;
|
||||||
|
--luncher-text: #eef4f6;
|
||||||
|
--luncher-text-secondary: #c2ced4;
|
||||||
|
--luncher-text-muted: #82919a;
|
||||||
|
--luncher-border-light: #1b2328;
|
||||||
|
--luncher-navbar-bg: #050607;
|
||||||
|
--luncher-action-icon: #5fd6cd;
|
||||||
|
--luncher-buyer-icon: #ff7ab8;
|
||||||
|
--luncher-success: #5fd69a;
|
||||||
|
--luncher-warning: #ffc04d;
|
||||||
|
--luncher-danger: #ff5c8a;
|
||||||
|
--luncher-shadow: 0 4px 16px rgb(0 0 0 / 0.5);
|
||||||
|
--luncher-shadow-lg: 0 0 0 1px var(--miku-teal), 0 0 28px rgb(57 197 187 / 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: var(--miku-font);
|
||||||
|
background-color: var(--luncher-bg);
|
||||||
|
// Piano roll — střídavé pruhy tónů a dobové linky
|
||||||
|
background-image:
|
||||||
|
linear-gradient(90deg, rgb(57 197 187 / 0.14) 1px, transparent 1px),
|
||||||
|
repeating-linear-gradient(180deg, #f6fafb 0 22px, #edf3f5 22px 44px);
|
||||||
|
background-size: 88px 100%, 100% 44px;
|
||||||
|
background-attachment: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-bs-theme="dark"] body {
|
||||||
|
// Reflektory nad pódiem a moře světelných tyčinek dole
|
||||||
|
background-image:
|
||||||
|
#{$miku-glowsticks},
|
||||||
|
linear-gradient(115deg, transparent 38%, rgb(57 197 187 / 0.10) 46%, transparent 54%),
|
||||||
|
linear-gradient(-115deg, transparent 38%, rgb(225 40 133 / 0.09) 46%, transparent 54%),
|
||||||
|
radial-gradient(ellipse 60% 40% at 50% -10%, rgb(57 197 187 / 0.22), transparent 70%),
|
||||||
|
linear-gradient(0deg, rgb(57 197 187 / 0.12), transparent 140px);
|
||||||
|
background-size: 72px 56px, 100% 100%, 100% 100%, 100% 100%, 100% 100%;
|
||||||
|
background-position: left bottom, 0 0, 0 0, 0 0, 0 0;
|
||||||
|
background-repeat: repeat-x, no-repeat, no-repeat, no-repeat, no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-container {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, .navbar-brand {
|
||||||
|
font-family: var(--miku-display);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
font-family: var(--miku-font);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Navbar: šedá jako rukávy, tyrkysový lem a ekvalizér ----------
|
||||||
|
.navbar {
|
||||||
|
background:
|
||||||
|
linear-gradient(var(--miku-teal), var(--miku-teal)) left bottom / 100% 3px no-repeat,
|
||||||
|
linear-gradient(180deg, #454b51, var(--luncher-navbar-bg)) !important;
|
||||||
|
padding-bottom: calc(var(--bs-navbar-padding-y, 0.5rem) + 3px);
|
||||||
|
border-bottom: none;
|
||||||
|
box-shadow: 0 2px 14px rgb(57 197 187 / 0.35);
|
||||||
|
|
||||||
|
.navbar-brand {
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
|
||||||
|
// Ekvalizér — právě hraje
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
width: 15px;
|
||||||
|
height: 16px;
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-right: 0.6em;
|
||||||
|
vertical-align: -1px;
|
||||||
|
background-image:
|
||||||
|
linear-gradient(var(--miku-teal), var(--miku-teal)),
|
||||||
|
linear-gradient(var(--miku-pink), var(--miku-pink)),
|
||||||
|
linear-gradient(var(--miku-teal), var(--miku-teal)),
|
||||||
|
linear-gradient(var(--miku-teal), var(--miku-teal));
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 0 100%, 4px 100%, 8px 100%, 12px 100%;
|
||||||
|
background-size: 3px 40%, 3px 90%, 3px 60%, 3px 30%;
|
||||||
|
animation: miku-eq 0.9s ease-in-out infinite alternate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
border: 1px solid var(--miku-line);
|
||||||
|
border-radius: var(--luncher-radius);
|
||||||
|
box-shadow: var(--luncher-shadow-lg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-bs-theme="dark"] .navbar {
|
||||||
|
background:
|
||||||
|
linear-gradient(var(--miku-teal), var(--miku-teal)) left bottom / 100% 2px no-repeat,
|
||||||
|
var(--luncher-navbar-bg) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Titulek dne: tyrkysová nota z piano rollu se značkou „01" ----------
|
||||||
|
.day-navigator .title {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 6px 28px 8px;
|
||||||
|
font-family: var(--miku-display);
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 1.65rem;
|
||||||
|
letter-spacing: 0.01em;
|
||||||
|
color: #ffffff !important;
|
||||||
|
text-shadow: 0 1px 0 rgb(0 0 0 / 0.2);
|
||||||
|
background: linear-gradient(180deg, #5fd6cd, var(--miku-teal) 60%, #2fb3a9);
|
||||||
|
border: 1px solid #2a9d95;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 0 4px rgb(57 197 187 / 0.2), 0 8px 18px rgb(57 197 187 / 0.3);
|
||||||
|
|
||||||
|
// Červené „01" z Mikina ramene
|
||||||
|
&::before {
|
||||||
|
content: '01';
|
||||||
|
position: absolute;
|
||||||
|
left: -12px;
|
||||||
|
top: -12px;
|
||||||
|
padding: 1px 6px;
|
||||||
|
font-size: 0.45em;
|
||||||
|
font-weight: 800;
|
||||||
|
line-height: 1.4;
|
||||||
|
color: #fff;
|
||||||
|
background: var(--miku-red);
|
||||||
|
border-radius: 4px;
|
||||||
|
text-shadow: none;
|
||||||
|
transform: rotate(-8deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nota, která z titulku vylétá
|
||||||
|
&::after {
|
||||||
|
content: '♪';
|
||||||
|
position: absolute;
|
||||||
|
right: -20px;
|
||||||
|
top: -6px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
color: var(--miku-pink);
|
||||||
|
text-shadow: none;
|
||||||
|
animation: miku-note 2.6s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.text-muted {
|
||||||
|
color: #f4f7f8 !important;
|
||||||
|
background: linear-gradient(180deg, #c3ccd0, #aab5ba);
|
||||||
|
border-color: #98a4aa;
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
background: #8a979e;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-bs-theme="dark"] .day-navigator .title {
|
||||||
|
box-shadow: 0 0 0 4px rgb(57 197 187 / 0.15), 0 0 26px rgb(57 197 187 / 0.55);
|
||||||
|
|
||||||
|
&.text-muted {
|
||||||
|
color: #c2ced4 !important;
|
||||||
|
background: #1b2328;
|
||||||
|
border-color: #2c3a42;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Karty podniků: šedá hlavička s tyrkysovým lemem a klávesnicí ----------
|
||||||
|
.restaurant-card {
|
||||||
|
border: 1px solid var(--miku-line);
|
||||||
|
border-radius: var(--luncher-radius-lg);
|
||||||
|
box-shadow: var(--luncher-shadow);
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
border-color: var(--miku-teal);
|
||||||
|
box-shadow: var(--luncher-shadow-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.restaurant-header {
|
||||||
|
background:
|
||||||
|
#{$miku-keys} left bottom / 98px 10px repeat-x,
|
||||||
|
linear-gradient(var(--miku-teal), var(--miku-teal)) left bottom 10px / 100% 3px no-repeat,
|
||||||
|
linear-gradient(180deg, #454b51, var(--miku-grey));
|
||||||
|
padding-bottom: 28px;
|
||||||
|
|
||||||
|
// Při najetí se rozsvítí tyrkysově
|
||||||
|
&:hover {
|
||||||
|
background:
|
||||||
|
#{$miku-keys} left bottom / 98px 10px repeat-x,
|
||||||
|
linear-gradient(var(--miku-pink), var(--miku-pink)) left bottom 10px / 100% 3px no-repeat,
|
||||||
|
linear-gradient(135deg, #2fb3a9, var(--miku-teal-deep));
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
color: rgb(255 255 255 / 0.78);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-bs-theme="dark"] .restaurant-card .restaurant-header:not(:hover) {
|
||||||
|
background:
|
||||||
|
#{$miku-keys} left bottom / 98px 10px repeat-x,
|
||||||
|
linear-gradient(var(--miku-teal), var(--miku-teal)) left bottom 10px / 100% 2px no-repeat,
|
||||||
|
#101417;
|
||||||
|
}
|
||||||
|
|
||||||
|
.food-table tbody tr:hover > td {
|
||||||
|
background: #eef8f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-bs-theme="dark"] .food-table tbody tr:hover > td {
|
||||||
|
background: #1b2328;
|
||||||
|
}
|
||||||
|
|
||||||
|
.food-price {
|
||||||
|
color: var(--miku-teal-ink);
|
||||||
|
font-family: var(--miku-display);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Panely a tabulka voleb ----------
|
||||||
|
.choice-section,
|
||||||
|
.choices-table,
|
||||||
|
.pizza-section,
|
||||||
|
.no-votes {
|
||||||
|
border: 1px solid var(--miku-line);
|
||||||
|
border-radius: var(--luncher-radius-lg);
|
||||||
|
box-shadow: var(--luncher-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.choices-table {
|
||||||
|
border-collapse: separate;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sloupec s podnikem: tyrkysová stopa
|
||||||
|
.choices-table > tbody > tr > td:first-child {
|
||||||
|
background: #e0f6f4;
|
||||||
|
color: var(--miku-teal-ink);
|
||||||
|
font-family: var(--miku-display);
|
||||||
|
font-weight: 700;
|
||||||
|
border-right: 3px solid var(--miku-teal);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-bs-theme="dark"] .choices-table > tbody > tr > td:first-child {
|
||||||
|
background: #12302e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bootstrap karty (skupinové objednávky apod.) a seznamy
|
||||||
|
.card {
|
||||||
|
border: 1px solid var(--miku-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(--luncher-primary-light);
|
||||||
|
border-bottom: 2px solid var(--miku-teal);
|
||||||
|
font-weight: 700;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
border-radius: calc(var(--luncher-radius-lg) - 1px) calc(var(--luncher-radius-lg) - 1px) 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: 1px solid var(--miku-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: 1px solid var(--miku-line);
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: var(--miku-teal);
|
||||||
|
box-shadow: 0 0 0 3px rgb(57 197 187 / 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Tlačítka: tyrkysová, při najetí zazáří jako tyčinka ----------
|
||||||
|
.btn {
|
||||||
|
border-radius: var(--luncher-radius-sm);
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
transition: transform 0.15s ease, box-shadow 0.2s ease, background 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background: linear-gradient(180deg, #23a99f, var(--miku-teal-deep));
|
||||||
|
border: 1px solid #0e7a73;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(180deg, #2fb3a9, #179a91);
|
||||||
|
border-color: #0e7a73;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 0 0 3px rgb(57 197 187 / 0.3), 0 0 16px rgb(57 197 187 / 0.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: translateY(1px) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background: #cfd8dc;
|
||||||
|
border-color: #cfd8dc;
|
||||||
|
color: #8a979e;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-bs-theme="dark"] .btn-primary:disabled {
|
||||||
|
background: #23303a;
|
||||||
|
border-color: #23303a;
|
||||||
|
color: #82919a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline-primary {
|
||||||
|
background: var(--luncher-bg-card);
|
||||||
|
border: 1px solid var(--miku-teal);
|
||||||
|
color: var(--luncher-primary);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--luncher-primary-light);
|
||||||
|
border-color: var(--miku-teal);
|
||||||
|
color: var(--luncher-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sekundární — růžová ze stužek ve vlasech
|
||||||
|
.btn-secondary {
|
||||||
|
background: var(--miku-pink);
|
||||||
|
border: 1px solid #b81e6c;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #c81f75;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 0 14px rgb(225 40 133 / 0.45);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-danger {
|
||||||
|
background: var(--miku-red);
|
||||||
|
border: 1px solid #b01a48;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-icon:hover {
|
||||||
|
background: var(--luncher-primary-light);
|
||||||
|
color: var(--luncher-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Modaly: šedé okno editoru s klávesnicí ----------
|
||||||
|
.modal-content {
|
||||||
|
border: 1px solid var(--miku-line);
|
||||||
|
border-radius: var(--luncher-radius-xl);
|
||||||
|
box-shadow: 0 16px 40px rgb(38 48 54 / 0.3);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
background:
|
||||||
|
#{$miku-keys} left bottom / 98px 10px repeat-x,
|
||||||
|
linear-gradient(var(--miku-teal), var(--miku-teal)) left bottom 10px / 100% 3px no-repeat,
|
||||||
|
linear-gradient(180deg, #454b51, var(--miku-grey));
|
||||||
|
border-bottom: none;
|
||||||
|
padding-bottom: calc(var(--bs-modal-header-padding-y, 1rem) + 13px);
|
||||||
|
|
||||||
|
.modal-title, .modal-title h2 {
|
||||||
|
color: #fff;
|
||||||
|
font-family: var(--miku-display);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-close {
|
||||||
|
filter: invert(1) grayscale(1) brightness(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-bs-theme="dark"] {
|
||||||
|
.modal-content {
|
||||||
|
border-color: #23303a;
|
||||||
|
box-shadow: 0 0 30px rgb(57 197 187 / 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
background:
|
||||||
|
#{$miku-keys} left bottom / 98px 10px repeat-x,
|
||||||
|
linear-gradient(var(--miku-teal), var(--miku-teal)) left bottom 10px / 100% 2px no-repeat,
|
||||||
|
#101417;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
border-top: none;
|
||||||
|
background-image: $miku-keys;
|
||||||
|
background-size: 98px 10px;
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
background-position: top;
|
||||||
|
padding-top: 26px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--miku-teal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ekvalizér — sloupce střídavě poskakují
|
||||||
|
@keyframes miku-eq {
|
||||||
|
0% { background-size: 3px 40%, 3px 90%, 3px 60%, 3px 30%; }
|
||||||
|
25% { background-size: 3px 80%, 3px 50%, 3px 30%, 3px 70%; }
|
||||||
|
50% { background-size: 3px 30%, 3px 70%, 3px 90%, 3px 50%; }
|
||||||
|
75% { background-size: 3px 70%, 3px 30%, 3px 50%, 3px 90%; }
|
||||||
|
100% { background-size: 3px 50%, 3px 80%, 3px 40%, 3px 60%; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nota vylétá a mizí
|
||||||
|
@keyframes miku-note {
|
||||||
|
0% { transform: translate(0, 4px) rotate(-10deg); opacity: 0; }
|
||||||
|
20% { opacity: 1; }
|
||||||
|
70% { opacity: 1; }
|
||||||
|
100% { transform: translate(8px, -16px) rotate(12deg); opacity: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 575.98px) {
|
||||||
|
#{$miku} .day-navigator .title {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
padding: 5px 20px 6px;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
right: -14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
#{$miku} .navbar .navbar-brand::after,
|
||||||
|
#{$miku} .day-navigator .title::after {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user