diff --git a/client/index.html b/client/index.html index d3f4092..fb1174c 100644 --- a/client/index.html +++ b/client/index.html @@ -28,7 +28,7 @@ } document.documentElement.setAttribute('data-bs-theme', theme); var style = localStorage.getItem('style_theme'); - var styles = ['umamusume', 'mlp', 'hellgirl', 'kon', 'bocchi', 'evangelion', 'yurucamp', 'spyfamily']; + var styles = ['umamusume', 'mlp', 'hellgirl', 'kon', 'bocchi', 'evangelion', 'yurucamp', 'spyfamily', 'apothecary']; document.documentElement.setAttribute('data-luncher-theme', styles.indexOf(style) >= 0 ? style : 'simple'); } catch (e) { // Fallback pokud localStorage není dostupný diff --git a/client/src/App.tsx b/client/src/App.tsx index 80a3770..ead0a9b 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -18,6 +18,7 @@ import './themes/bocchi.scss'; import './themes/evangelion.scss'; import './themes/yurucamp.scss'; import './themes/spyfamily.scss'; +import './themes/apothecary.scss'; import { faCircleCheck, faNoteSticky, faTrashCan, faComment } from '@fortawesome/free-regular-svg-icons'; import { useSettings } from './context/settings'; import Footer from './components/Footer'; diff --git a/client/src/components/EaterBadge.scss b/client/src/components/EaterBadge.scss index f53ad51..2c84cc0 100644 --- a/client/src/components/EaterBadge.scss +++ b/client/src/components/EaterBadge.scss @@ -105,6 +105,17 @@ box-shadow: 0 0 0 2px #1e6f6c; } +// Styl Apothecary Diaries: emoji na nefritovém disku se zlatým lemem +.eater-badge-apothecary { + display: inline-grid; + place-items: center; + font-size: 15px; + line-height: 1; + border-color: #d9b65e; + background: radial-gradient(circle at 40% 35%, #cfe9dc, #6fae92); + box-shadow: 0 0 0 2px #a8322a; +} + // Odznak a jméno drží na jednom řádku (úzký sloupec „Člen" na stránce objednávek) .user-info:has(.eater-badge) { display: inline-flex; diff --git a/client/src/components/EaterBadge.tsx b/client/src/components/EaterBadge.tsx index 18c1a35..e2e2454 100644 --- a/client/src/components/EaterBadge.tsx +++ b/client/src/components/EaterBadge.tsx @@ -55,6 +55,12 @@ const SXF_LEVELS = [ { minItems: 2, emoji: '🥜', title: 'Úroveň Anya — k obědu ještě hrst buráků (waku waku!)' }, ]; +/** Úrovně ve stylu Apothecary Diaries — emoji na nefritovém disku se zlatým lemem. Seřazeno od nejvyšší úrovně. */ +const APO_LEVELS = [ + { minItems: 3, emoji: '🧪', title: 'Úroveň Maomao — ochutná úplně všechno, hlavně kdyby to bylo otrávené' }, + { minItems: 2, emoji: '🍡', title: 'Úroveň Xiaolan — k obědu ještě sladkosti a klepy z paláce' }, +]; + /** Úrovně podle stylu pro odznaky s emoji. */ const EMOJI_LEVELS: Partial> = { mlp: MLP_LEVELS, @@ -64,6 +70,7 @@ const EMOJI_LEVELS: Partial> = { evangelion: EVA_LEVELS, yurucamp: YC_LEVELS, spyfamily: SXF_LEVELS, + apothecary: APO_LEVELS, }; type Props = { @@ -71,7 +78,7 @@ type Props = { 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△ a Spy × Family. */ +/** 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 a Apothecary Diaries. */ export default function EaterBadge({ items }: Readonly) { const styleTheme = useSettings()?.styleTheme; const isUma = styleTheme === 'umamusume'; diff --git a/client/src/components/WheelConfetti.scss b/client/src/components/WheelConfetti.scss index 032f7b4..756e8c7 100644 --- a/client/src/components/WheelConfetti.scss +++ b/client/src/components/WheelConfetti.scss @@ -716,3 +716,75 @@ } } } + +// ============================================ +// Konfety ve stylu Apothecary Diaries +// ============================================ +.confetti-apo { + filter: drop-shadow(0 3px 3px rgb(58 31 20 / 0.28)); +} + +// Štítky jako papírky na šuplících s léky — mincho a zlatý vnitřní lem +.confetti-apo-badge { + padding: 4px 14px; + border-radius: 3px; + color: #fdf6e6; + box-shadow: inset 0 0 0 2px rgb(217 182 94 / 0.7); + font-family: 'Shippori Mincho', 'Noto Serif JP', serif; + font-weight: 800; + font-size: 1.1rem; + white-space: nowrap; +} + +// Nápis „薬屋のひとりごと" — lakovaná deska se zlatým kováním, vyjede jako svitek +.confetti-apo-banner { + position: absolute; + top: 38%; + left: 50%; + transform: translate(-50%, -50%); + padding: 14px 44px 16px; + font-family: 'Shippori Mincho', 'Noto Serif JP', serif; + font-weight: 800; + font-size: clamp(1.6rem, 6vw, 3.6rem); + letter-spacing: 0.08em; + white-space: nowrap; + color: #fdf6e6; + text-shadow: 0 0 14px rgb(232 165 74 / 0.6); + background: linear-gradient(180deg, #b63a30, #84241d); + border: 2px solid #d9b65e; + outline: 1px solid #d9b65e; + outline-offset: 4px; + border-radius: 4px; + box-shadow: 0 14px 30px rgb(0 0 0 / 0.35); + animation: apo-banner 2.6s ease both; +} + +@keyframes apo-banner { + 0% { clip-path: inset(0 50% 0 50%); opacity: 0; } + 8% { opacity: 1; } + 24%, 80% { clip-path: inset(-20px -20px -20px -20px); opacity: 1; } + 100% { clip-path: inset(-20px -20px -20px -20px); opacity: 0; } +} + +// Postava s hláškou — nefritový disk se zlatým lemem a bublina jako lékařský záznam +.confetti-apothecary-voice { + .confetti-mlp-avatar { + border: 4px solid #d9b65e; + background: radial-gradient(circle at 40% 35%, #cfe9dc, #6fae92); + box-shadow: 0 0 0 3px var(--mlp-speaker, #2f7d62), 0 4px 10px rgb(0 0 0 / 0.3); + } + + .confetti-mlp-bubble { + background: #fbf6ea; + color: #24201c; + border: 1px solid #c9a24a; + border-left: 5px solid var(--mlp-speaker, #a8322a); + border-radius: 4px; + box-shadow: 0 6px 14px rgb(0 0 0 / 0.25); + font-family: 'Shippori Mincho', 'Noto Serif JP', serif; + + p { + font-weight: 700; + } + } +} diff --git a/client/src/components/WheelConfetti.tsx b/client/src/components/WheelConfetti.tsx index b73831e..015b4b2 100644 --- a/client/src/components/WheelConfetti.tsx +++ b/client/src/components/WheelConfetti.tsx @@ -121,6 +121,21 @@ const SXF_SPEAKERS = [ { name: 'Becky Blackbell', emoji: '🎀', color: '#d9a441', quote: 'Anyo, vždyť tohle je úplně jako z romantického dramatu!' }, { name: 'Henry Henderson', emoji: '🎩', color: '#5a4a3a', quote: 'Elegantní volba! Vskutku elegantní!' }, ]; +const APO_EMOJI = ['🌿', '🧪', '🍵', '🏮', '🌸', '🐸', '🍄', '📜', '🪷', '🌙', '💮', '🍡', '🪭', '🐛']; +// Hlášky z Apothecary Diaries (ochutnávání jedů, Nefritový pavilon, zahradní slavnost, Maomaův pohled jako na slimáka...) +const APO_BADGES = ['薬屋のひとりごと', 'Ochutnáno ✓', 'Jed nenalezen', 'Jinshi-sama', 'Nefritový pavilon', 'Zahradní slavnost', 'Bylinky!', 'Vnitřní palác', 'Pohled jako na slimáka', 'Housenice čínská']; +const APO_BADGE_COLORS = ['#a8322a', '#2f7d62', '#b8902e', '#24201c', '#6b5aa6', '#c76a86']; +/** Maomao a obyvatelé vnitřního paláce s „hláškou" po finálním výsledku. */ +const APO_SPEAKERS = [ + { name: 'Maomao', emoji: '🧪', color: '#6f8f6b', quote: 'Žádný jed. Škoda… ale chutnat to bude i tak.' }, + { name: 'Jinshi', emoji: '🌙', color: '#6b5aa6', quote: 'Výborná volba. Jen se na mě, Maomao, nedívej jako na slimáka.' }, + { name: 'Gaoshun', emoji: '🍵', color: '#4f5d6b', quote: 'Zařídím to. Mistře Jinshi, prosím, jezte tentokrát včas.' }, + { name: 'Konkubína Gyokuyou', emoji: '💎', color: '#a8322a', quote: 'Jak báječné! Maomao, ochutnáš to nejdřív za mě, že ano?' }, + { name: 'Xiaolan', emoji: '🍡', color: '#d97a95', quote: 'Maomao, Maomao! Prý tam dávají sladkosti navíc!' }, + { name: 'Luomen', emoji: '🌿', color: '#8a7a5a', quote: 'Moudrá volba. Jen nezapomeň, že i lék může být jedem.' }, + { name: 'Lakan', emoji: '♟️', color: '#7a5c3a', quote: 'Lidi vidím jen jako figurky na desce… ale tahle figurka je k snědku.' }, + { name: 'Konkubína Lishu', emoji: '🌸', color: '#c98fb0', quote: 'J-já si dám to samé… když to Maomao ochutnala.' }, +]; /** Styly, jejichž konfety tvoří emoji a samolepky s hláškami (a po finále promluví postava s emoji). */ const EMOJI_CONFETTI: Partial big && emojiConfetti ? pick(emojiConfetti.speakers) : undefined, diff --git a/client/src/components/modals/SpinWheelModal.scss b/client/src/components/modals/SpinWheelModal.scss index c9e0480..25e7e0b 100644 --- a/client/src/components/modals/SpinWheelModal.scss +++ b/client/src/components/modals/SpinWheelModal.scss @@ -2349,6 +2349,252 @@ } } +// ============================================ +// STYL APOTHECARY DIARIES kola štěstí (dle stylu zvoleného v nastavení). +// Výseče v barvách vnitřního paláce (rumělka, nefrit, zlato, inkoust, +// fialová Jinshiho, švestkový květ), zlaté linky a střed jako zlatá pečeť. +// ============================================ +.spin-wheel-modal.spin-theme-apothecary { + --apo-font: 'Nunito', sans-serif; + --apo-display: 'Shippori Mincho', 'Noto Serif JP', serif; + --apo-vermilion: #a8322a; + --apo-vermilion-deep: #84241d; + --apo-jade: #2f7d62; + --apo-gold: #c9a24a; + --apo-line: #e0d4bb; + --apo-panel: #fffcf4; + --apo-text: #24201c; + --wheel-c0: #a8322a; + --wheel-c1: #2f7d62; + --wheel-c2: #c9a24a; + --wheel-c3: #24201c; + --wheel-c4: #6b5aa6; + --wheel-c5: #c76a86; + --wheel-rim: #3a1f14; + --wheel-hub: #d9b65e; + + font-family: var(--apo-font); + + .modal-content { + border: 1px solid var(--apo-gold); + border-radius: 10px; + overflow: hidden; + background: #f5efe1; + color: var(--apo-text); + } + + .modal-header { + background: + linear-gradient(var(--apo-gold), var(--apo-gold)) left bottom / 100% 2px no-repeat, + linear-gradient(var(--apo-gold), var(--apo-gold)) left bottom 4px / 100% 1px no-repeat, + #24201c; + border-bottom: none; + + h2 { + color: #fdf6e6; + font-family: var(--apo-display); + font-weight: 800; + } + + .btn-close { + filter: invert(1) grayscale(1) brightness(2); + opacity: 0.9; + } + } + + .modal-footer { + border-top: 3px double var(--apo-gold); + } + + .spin-steps span { + font-family: var(--apo-display); + font-weight: 800; + background: #ece3d0; + color: #8b7f70; + border-radius: 3px; + padding: 4px 16px; + + &.active { + background: var(--apo-vermilion); + color: #fdf6e6; + box-shadow: inset 0 0 0 2px rgb(201 162 74 / 0.6); + } + + &.done { + background: var(--apo-jade); + color: #fff; + } + } + + .btn { + font-family: var(--apo-font); + font-weight: 800; + border-radius: 3px; + } + + .btn-primary { + background: var(--apo-vermilion); + border: 1px solid var(--apo-vermilion-deep); + color: #fdf6e6; + box-shadow: inset 0 0 0 2px rgb(201 162 74 / 0.55); + + &:hover:not(:disabled) { + background: var(--apo-vermilion-deep); + color: #fdf6e6; + box-shadow: inset 0 0 0 2px var(--apo-gold), 0 0 12px rgb(201 162 74 / 0.45); + } + + &:disabled { + background: #d8cfbf; + border-color: #d8cfbf; + color: #8b7f70; + box-shadow: none; + } + } + + // Tlačítko roztočení — zlatá pečeť + .spin-button { + font-family: var(--apo-display); + font-size: 1.2rem; + padding: 10px 38px; + } + + .btn-outline-primary { + background: var(--apo-panel); + border: 1px solid var(--apo-gold); + color: var(--apo-vermilion); + + &:hover { + background: #f6e2dc; + color: var(--apo-vermilion); + } + } + + .btn-secondary { + background: var(--apo-jade); + border: 1px solid #22604a; + color: #fff; + } + + .spin-source { + background: #ece3d0; + border-radius: 4px; + + > .btn { + border-radius: 3px !important; + } + + > .btn-outline-primary { + background: transparent; + color: var(--apo-text); + + &:hover { + background: var(--apo-panel); + } + } + } + + .spin-result { + font-weight: 800; + + strong { + color: var(--apo-vermilion); + } + } + + .spin-options { + background: var(--apo-panel); + border: 1px solid var(--apo-line); + border-radius: 8px; + + li:hover { + background: #f4ead6; + } + } + + .spin-options-header { + border-bottom: 3px double var(--apo-gold); + color: var(--apo-vermilion); + font-family: var(--apo-display); + } + + .spin-empty { + border-color: var(--apo-line); + } + + .spin-wheel-pointer { + border-top-color: var(--apo-vermilion); + filter: drop-shadow(0 2px 1px rgb(58 31 20 / 0.4)); + } + + .spin-seg { + stroke: #d9b65e; + stroke-width: 2; + } + + .spin-seg-label { + font-family: var(--apo-display); + font-weight: 800; + } +} + +// Tmavý režim — noc v paláci pod lampiony +[data-bs-theme="dark"] .spin-wheel-modal.spin-theme-apothecary { + --apo-vermilion: #d6503f; + --apo-vermilion-deep: #b53b2d; + --apo-jade: #3f9474; + --apo-gold: #d9b65e; + --apo-line: #3a2e2a; + --apo-panel: #1e1a22; + --apo-text: #f2eadb; + --wheel-c0: #b53b2d; + --wheel-c3: #3a3036; + --wheel-rim: #0e0c10; + + .modal-content { + background: + radial-gradient(circle at 8% 0%, rgb(214 80 63 / 0.22), transparent 35%), + radial-gradient(circle at 92% 0%, rgb(232 165 74 / 0.16), transparent 32%), + #14121a; + } + + .modal-header { + background-color: #0e0c10; + } + + .spin-steps span:not(.active):not(.done) { + background: #29232d; + color: #948a80; + } + + .btn-primary:disabled { + background: #3a3036; + border-color: #3a3036; + color: #948a80; + } + + .btn-outline-primary { + color: #e8a54a; + + &:hover { + background: #3a2618; + color: #f2bd6a; + } + } + + .spin-source { + background: #29232d; + } + + .spin-options li:hover { + background: #29232d; + } + + .spin-options-header { + color: #d9b65e; + } +} + // Ikona kola se při najetí pootočí .spin-wheel-icon { transition: transform 0.4s ease !important; diff --git a/client/src/context/settings.tsx b/client/src/context/settings.tsx index 06d5a51..7e87b90 100644 --- a/client/src/context/settings.tsx +++ b/client/src/context/settings.tsx @@ -13,7 +13,7 @@ const AUTO_ORDER_CHOICE_KEY = 'auto_order_choice'; export type ThemePreference = 'system' | 'light' | 'dark'; /** 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'; +export type StyleTheme = 'simple' | 'umamusume' | 'mlp' | 'hellgirl' | 'kon' | 'bocchi' | 'evangelion' | 'yurucamp' | 'spyfamily' | 'apothecary'; export const STYLE_THEMES: { value: StyleTheme, label: string }[] = [ { value: 'simple', label: 'Jednoduchý' }, @@ -25,6 +25,7 @@ export const STYLE_THEMES: { value: StyleTheme, label: string }[] = [ { value: 'evangelion', label: 'Neon Genesis Evangelion' }, { value: 'yurucamp', label: 'Yuru Camp△' }, { value: 'spyfamily', label: 'Spy × Family' }, + { value: 'apothecary', label: 'Apothecary Diaries' }, ]; export type SettingsContextProps = { @@ -256,7 +257,7 @@ function useProvideSettings(): SettingsContextProps { }, [autoOrderChoice]); // 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) 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) mají vlastní pevnou paletu, accent barvu proto uplatňuje jen jednoduchý styl. useEffect(() => { localStorage.setItem(ACCENT_HUE_KEY, String(accentHue)); if (styleTheme === 'simple') { diff --git a/client/src/games/themeIcons.ts b/client/src/games/themeIcons.ts index 47031b2..415fc1d 100644 --- a/client/src/games/themeIcons.ts +++ b/client/src/games/themeIcons.ts @@ -21,6 +21,8 @@ const ICONS: Record> = { yurucamp: { drawing: '🗺️' }, // Forgerovi: pastelky, kterými Anya kreslí spyfamily: { drawing: '🖍️' }, + // Lékárna Maomao: pero a tuš na recepty + apothecary: { drawing: '🖋️' }, }; /** Styl z — pro místa mimo React kontext nastavení. */ diff --git a/client/src/themes/apothecary.scss b/client/src/themes/apothecary.scss new file mode 100644 index 0000000..6312ee3 --- /dev/null +++ b/client/src/themes/apothecary.scss @@ -0,0 +1,515 @@ +// ============================================ +// STYL "APOTHECARY DIARIES" (volitelný, výchozí je jednoduchý styl) +// Inspirováno anime Kusuriya no Hitorigoto (薬屋のひとりごと). +// Vnitřní palác ve dne: rýžový papír s čínskou mřížkou oken, rumělkově +// červený lak sloupů, nefrit Nefritového pavilonu a zlaté kování. +// Titulek dne jako šuplík lékárnické skříňky Maomao se štítkem a pečetí 薬. +// Tmavý režim = noc v paláci pod červenými lampiony. +// Aktivní, pokud má atribut data-luncher-theme="apothecary". +// ============================================ + +$apo: 'html[data-luncher-theme="apothecary"]'; + +// Čínská mřížka okna — rámeček s vnitřním čtvercem a spojkami (barva jako parametr) +@function apo-lattice($color) { + @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Cpath d='M0 0H40V40H0ZM10 10H30V30H10ZM0 20H10M30 20H40M20 0V10M20 30V40' fill='none' stroke='#{$color}'/%3E%3C/svg%3E"); +} + +// Zlaté kování — dvě tenké zlaté linky (pod hlavičkami a na footeru) +$apo-gold-trim: + linear-gradient(var(--apo-gold), var(--apo-gold)) left bottom / 100% 2px no-repeat, + linear-gradient(var(--apo-gold), var(--apo-gold)) left bottom 4px / 100% 1px no-repeat; + +#{$apo} { + --apo-font: 'Nunito', -apple-system, sans-serif; + --apo-display: 'Shippori Mincho', 'Noto Serif JP', Georgia, serif; + --apo-vermilion: #a8322a; // lakované sloupy paláce + --apo-vermilion-deep: #84241d; + --apo-jade: #2f7d62; // Nefritový pavilon konkubíny Gyokuyou + --apo-jade-deep: #22604a; + --apo-gold: #c9a24a; + --apo-ink: #24201c; + --apo-wood: #5a311f; // lékárnická skříňka + --apo-wood-dark: #3a1f14; + --apo-paper: #f5efe1; + --apo-label: #fbf6ea; + --apo-line: #e0d4bb; + + --luncher-primary: var(--apo-vermilion); + --luncher-primary-hover: var(--apo-vermilion-deep); + --luncher-primary-light: #f6e2dc; + --luncher-bg: var(--apo-paper); + --luncher-bg-card: #fffcf4; + --luncher-bg-hover: #f4ead6; + --luncher-text: var(--apo-ink); + --luncher-text-secondary: #554a3f; + --luncher-text-muted: #8b7f70; + --luncher-border: var(--apo-line); + --luncher-border-light: #ece3d0; + --luncher-navbar-bg: var(--apo-vermilion); + --luncher-navbar-text: #fdf6e6; + --luncher-action-icon: var(--apo-vermilion); + --luncher-buyer-icon: var(--apo-jade); + --luncher-success: var(--apo-jade); + --luncher-warning: #c98d1c; + --luncher-danger: #b3261e; + --luncher-radius-sm: 3px; + --luncher-radius: 6px; + --luncher-radius-lg: 8px; + --luncher-radius-xl: 10px; + --luncher-shadow: 0 2px 8px rgb(58 31 20 / 0.10); + --luncher-shadow-lg: 0 10px 24px rgb(58 31 20 / 0.18); + + &[data-bs-theme="dark"] { + // Noc v paláci — lampiony a zlato + --apo-vermilion: #d6503f; + --apo-vermilion-deep: #b53b2d; + --apo-jade: #5fb894; + --apo-jade-deep: #3f9474; + --apo-gold: #d9b65e; + --apo-label: #e9dfc8; + --apo-line: #3a2e2a; + + --luncher-primary: #e8a54a; // teplé světlo lampionu + --luncher-primary-hover: #f2bd6a; + --luncher-primary-light: #3a2618; + --luncher-bg: #14121a; + --luncher-bg-card: #1e1a22; + --luncher-bg-hover: #29232d; + --luncher-text: #f2eadb; + --luncher-text-secondary: #cdc1ae; + --luncher-text-muted: #948a80; + --luncher-border: var(--apo-line); + --luncher-border-light: #29232a; + --luncher-navbar-bg: #5e1a15; + --luncher-action-icon: #e8a54a; + --luncher-buyer-icon: #5fb894; + --luncher-success: #5fb894; + --luncher-warning: #e8b84a; + --luncher-danger: #e0594a; + --luncher-shadow: 0 4px 14px rgb(0 0 0 / 0.4); + --luncher-shadow-lg: 0 10px 30px rgb(214 80 63 / 0.18); + } + + body { + font-family: var(--apo-font); + background-color: var(--luncher-bg); + // Rýžový papír s mřížkou okna, nahoře teplé denní světlo + background-image: + apo-lattice('%23a8322a14'), + linear-gradient(180deg, #fbf3e0 0, var(--luncher-bg) 360px); + background-size: 40px 40px, 100% 100%; + background-attachment: fixed; + } + + &[data-bs-theme="dark"] body { + // Zlatá mřížka a záře červených lampionů v rozích + background-image: + apo-lattice('%23d9b65e12'), + radial-gradient(circle at 8% 0%, rgb(214 80 63 / 0.28), transparent 32%), + radial-gradient(circle at 92% 0%, rgb(232 165 74 / 0.20), transparent 30%), + linear-gradient(180deg, #1d151a 0, var(--luncher-bg) 420px); + background-size: 40px 40px, 100% 100%, 100% 100%, 100% 100%; + } + + .app-container { + background: transparent; + } + + h1, h2, h3, h4, .navbar-brand { + font-family: var(--apo-display); + font-weight: 800; + } + + .btn { + font-family: var(--apo-font); + } + + // ---------- Navbar: rumělkový lak se zlatým kováním ---------- + .navbar { + background: + $apo-gold-trim, + linear-gradient(180deg, #b63a30, var(--luncher-navbar-bg)) !important; + padding-bottom: calc(var(--bs-navbar-padding-y, 0.5rem) + 5px); + + .navbar-brand { + letter-spacing: 0.04em; + + // Bylinka z lékárny Maomao + &::after { + content: '🌿'; + display: inline-block; + margin-left: 6px; + margin-right: 0.6em; + font-size: 0.75em; + } + } + + .dropdown-menu { + border: 1px solid var(--apo-gold); + border-radius: var(--luncher-radius); + box-shadow: var(--luncher-shadow-lg); + } + } + + &[data-bs-theme="dark"] .navbar { + background: + $apo-gold-trim, + linear-gradient(180deg, #6e2018, var(--luncher-navbar-bg)) !important; + } + + // ---------- Titulek dne: šuplík lékárnické skříňky se štítkem ---------- + .day-navigator .title { + position: relative; + display: inline-block; + margin: 10px 0 22px; + padding: 6px 26px 8px 18px; + font-family: var(--apo-display); + font-weight: 800; + font-size: 1.55rem; + color: var(--apo-ink) !important; + background: var(--apo-label); + border: 1px solid #c9b48a; + border-radius: 2px; + // Dřevěné čelo šuplíku kolem štítku (dole víc místa pro úchyt) + box-shadow: + 0 6px 0 10px var(--apo-wood), + 0 6px 0 12px var(--apo-wood-dark), + 0 14px 22px 12px rgb(58 31 20 / 0.22); + + // Červená pečeť 薬 na štítku + &::before { + content: '薬'; + display: inline-block; + margin-right: 12px; + padding: 2px 5px; + font-size: 0.6em; + line-height: 1.2; + vertical-align: middle; + color: #fff6ea; + background: #b3261e; + border-radius: 3px; + transform: rotate(-5deg); + } + + // Mosazný úchyt šuplíku + &::after { + content: ''; + position: absolute; + left: 50%; + bottom: -17px; + width: 22px; + height: 10px; + margin-left: -11px; + border: 3px solid var(--apo-gold); + border-top: none; + border-radius: 0 0 12px 12px; + box-shadow: 0 2px 2px rgb(0 0 0 / 0.35); + } + + &.text-muted { + color: #6b6257 !important; + background: #e7e0d2; + + &::before { + background: #8b7f70; + } + } + } + + // ---------- Karty podniků: rýžový papír, hlavička jako lakovaný trám ---------- + .restaurant-card { + border: 1px solid var(--apo-line); + border-radius: var(--luncher-radius-lg); + box-shadow: var(--luncher-shadow); + overflow: hidden; + + &:hover { + transform: translateY(-2px); + border-color: var(--apo-gold); + box-shadow: var(--luncher-shadow-lg); + } + + .restaurant-header { + background: + $apo-gold-trim, + apo-lattice('%23ffffff14') 0 0 / 40px 40px, + var(--apo-vermilion); + padding-bottom: 20px; + + // Při najetí nefritová zeleň Nefritového pavilonu + &:hover { + background: + $apo-gold-trim, + apo-lattice('%23ffffff14') 0 0 / 40px 40px, + var(--apo-jade); + } + + h3 { + letter-spacing: 0.03em; + } + + small { + color: rgb(255 255 255 / 0.8); + } + } + } + + &[data-bs-theme="dark"] .restaurant-card .restaurant-header { + &:not(:hover) { + background: + $apo-gold-trim, + apo-lattice('%23d9b65e1a') 0 0 / 40px 40px, + #5e1a15; + } + + &:hover { + background: + $apo-gold-trim, + apo-lattice('%23ffffff14') 0 0 / 40px 40px, + #22604a; + } + } + + .food-table tbody tr:hover > td { + background: #f4ead6; + } + + &[data-bs-theme="dark"] .food-table tbody tr:hover > td { + background: #29232d; + } + + .food-price { + color: var(--apo-vermilion); + font-weight: 800; + } + + &[data-bs-theme="dark"] .food-price { + color: var(--apo-gold); + } + + // ---------- Panely a tabulka voleb ---------- + .choice-section, + .choices-table, + .pizza-section, + .no-votes { + border: 1px solid var(--apo-line); + border-radius: var(--luncher-radius-lg); + box-shadow: var(--luncher-shadow); + } + + .choices-table { + border-collapse: separate; + border-spacing: 0; + } + + // Sloupec s podnikem: štítek na šuplíku s léky + .choices-table > tbody > tr > td:first-child { + background: var(--apo-label); + color: var(--apo-ink); + font-family: var(--apo-display); + font-weight: 800; + border-right: 3px double var(--apo-gold); + } + + &[data-bs-theme="dark"] .choices-table > tbody > tr > td:first-child { + background: #2a2018; + color: var(--apo-gold); + } + + // Bootstrap karty (skupinové objednávky apod.) a seznamy + .card { + border: 1px solid var(--apo-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: 3px double var(--apo-gold); + font-weight: 800; + + &: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(--apo-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(--apo-line); + + &:focus { + border-color: var(--apo-gold); + box-shadow: 0 0 0 3px rgb(201 162 74 / 0.28); + } + } + + // ---------- Tlačítka: lakovaná červeň se zlatým vnitřním lemem ---------- + .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: var(--apo-vermilion); + border: 1px solid var(--apo-vermilion-deep); + color: #fdf6e6; + box-shadow: inset 0 0 0 2px rgb(201 162 74 / 0.55); + + &:hover { + background: var(--apo-vermilion-deep); + border-color: var(--apo-vermilion-deep); + color: #fdf6e6; + box-shadow: inset 0 0 0 2px var(--apo-gold), 0 0 12px rgb(201 162 74 / 0.45); + } + + &:active { + transform: translateY(1px) !important; + } + + &:disabled { + background: #d8cfbf; + border-color: #d8cfbf; + color: #8b7f70; + box-shadow: none; + } + } + + &[data-bs-theme="dark"] .btn-primary { + color: #fff3e4; + + &:disabled { + background: #3a3036; + border-color: #3a3036; + color: #948a80; + } + } + + .btn-outline-primary { + background: var(--luncher-bg-card); + border: 1px solid var(--apo-gold); + color: var(--luncher-primary); + + &:hover { + background: var(--luncher-primary-light); + border-color: var(--apo-gold); + color: var(--luncher-primary); + } + } + + .btn-secondary { + background: var(--apo-jade); + border: 1px solid var(--apo-jade-deep); + color: #fff; + + &:hover { + background: var(--apo-jade-deep); + color: #fff; + } + } + + &[data-bs-theme="dark"] .btn-secondary { + background: #22604a; + border-color: #1a4a39; + + &:hover { + background: #2a7259; + } + } + + .btn-danger { + background: #b3261e; + border: 1px solid #861a14; + } + + .action-icon:hover { + background: var(--luncher-primary-light); + color: var(--luncher-primary); + } + + // ---------- Modaly: inkoustová deska se zlatou mřížkou ---------- + .modal-content { + border: 1px solid var(--apo-gold); + border-radius: var(--luncher-radius-xl); + box-shadow: 0 16px 40px rgb(58 31 20 / 0.3); + overflow: hidden; + } + + .modal-header { + background: + $apo-gold-trim, + apo-lattice('%23c9a24a24') 0 0 / 40px 40px, + #24201c; + border-bottom: none; + padding-bottom: calc(var(--bs-modal-header-padding-y, 1rem) + 5px); + + .modal-title, .modal-title h2 { + color: #fdf6e6; + font-family: var(--apo-display); + font-weight: 800; + } + + .btn-close { + filter: invert(1) grayscale(1) brightness(2); + } + } + + .footer { + border-top: none; + background-image: + linear-gradient(var(--apo-gold), var(--apo-gold)), + linear-gradient(var(--apo-gold), var(--apo-gold)); + background-size: 100% 2px, 100% 1px; + background-position: top, 0 4px; + background-repeat: no-repeat; + + a { + color: #f2d58a; + } + } +} + +@media (max-width: 575.98px) { + #{$apo} .day-navigator .title { + font-size: 1.2rem; + padding: 5px 18px 6px 12px; + } +}