/* ========================================================= 小镇角落小店 · Catppuccin Userstyles + UX tokens Flavors: Mocha (default, cozy dark) / Latte (light) Spacing: 4/8/12/16/24/32 · Radius: 8/12/16/999 ========================================================= */ /* --- Catppuccin Mocha (default) --- */ :root, [data-flavor="mocha"] { --ctp-rosewater: #f5e0dc; --ctp-flamingo: #f2cdcd; --ctp-pink: #f5c2e7; --ctp-mauve: #cba6f7; --ctp-red: #f38ba8; --ctp-maroon: #eba0ac; --ctp-peach: #fab387; --ctp-yellow: #f9e2af; --ctp-green: #a6e3a1; --ctp-teal: #94e2d5; --ctp-sky: #89dceb; --ctp-sapphire: #74c7ec; --ctp-blue: #89b4fa; --ctp-lavender: #b4befe; --ctp-text: #cdd6f4; --ctp-subtext1: #bac2de; --ctp-subtext0: #a6adc8; --ctp-overlay2: #9399b2; --ctp-overlay1: #7f849c; --ctp-overlay0: #6c7086; --ctp-surface2: #585b70; --ctp-surface1: #45475a; --ctp-surface0: #313244; --ctp-base: #1e1e2e; --ctp-mantle: #181825; --ctp-crust: #11111b; --bg: var(--ctp-base); --bg-deep: var(--ctp-crust); --bg-elevated: var(--ctp-mantle); --surface: var(--ctp-surface0); --surface-2: var(--ctp-surface1); --border: color-mix(in srgb, var(--ctp-overlay0) 45%, transparent); --border-strong: var(--ctp-surface2); --text: var(--ctp-text); --text-muted: var(--ctp-subtext0); --text-faint: var(--ctp-overlay1); --accent: var(--ctp-peach); --accent-2: var(--ctp-pink); --accent-soft: color-mix(in srgb, var(--ctp-peach) 18%, var(--ctp-surface0)); --on-accent: #11111b; --ok: var(--ctp-green); --warn: var(--ctp-yellow); --danger: var(--ctp-red); --info: var(--ctp-blue); --focus: var(--ctp-lavender); --shadow: 0 12px 40px color-mix(in srgb, var(--ctp-crust) 65%, transparent); --shadow-sm: 0 4px 14px color-mix(in srgb, var(--ctp-crust) 45%, transparent); --glow: 0 0 0 3px color-mix(in srgb, var(--ctp-peach) 35%, transparent); --radius-sm: 8px; --radius: 14px; --radius-lg: 18px; --radius-pill: 999px; --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 24px; --space-6: 32px; --font: "JetBrains Mono", "SF Mono", "Cascadia Code", "PingFang SC", "Microsoft YaHei", "Noto Sans SC", ui-sans-serif, system-ui, sans-serif; --font-ui: "Inter", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans SC", system-ui, sans-serif; --stage-floor-a: color-mix(in srgb, var(--ctp-surface0) 80%, var(--ctp-base)); --stage-floor-b: color-mix(in srgb, var(--ctp-surface1) 55%, var(--ctp-base)); } /* --- Catppuccin Latte (light) --- */ [data-flavor="latte"] { --ctp-rosewater: #dc8a78; --ctp-flamingo: #dd7878; --ctp-pink: #ea76cb; --ctp-mauve: #8839ef; --ctp-red: #d20f39; --ctp-maroon: #e64553; --ctp-peach: #fe640b; --ctp-yellow: #df8e1d; --ctp-green: #40a02b; --ctp-teal: #179299; --ctp-sky: #04a5e5; --ctp-sapphire: #209fb5; --ctp-blue: #1e66f5; --ctp-lavender: #7287fd; --ctp-text: #4c4f69; --ctp-subtext1: #5c5f77; --ctp-subtext0: #6c6f85; --ctp-overlay2: #7c7f93; --ctp-overlay1: #8c8fa1; --ctp-overlay0: #9ca0b0; --ctp-surface2: #acb0be; --ctp-surface1: #bcc0cc; --ctp-surface0: #ccd0da; --ctp-base: #eff1f5; --ctp-mantle: #e6e9ef; --ctp-crust: #dce0e8; --bg: var(--ctp-base); --bg-deep: var(--ctp-crust); --bg-elevated: #ffffff; --surface: #ffffff; --surface-2: var(--ctp-mantle); --border: color-mix(in srgb, var(--ctp-overlay0) 55%, transparent); --border-strong: var(--ctp-surface1); --text: var(--ctp-text); --text-muted: var(--ctp-subtext0); --text-faint: var(--ctp-overlay1); --accent: var(--ctp-peach); --accent-2: var(--ctp-mauve); --accent-soft: color-mix(in srgb, var(--ctp-peach) 14%, #fff); --on-accent: #ffffff; --ok: var(--ctp-green); --warn: var(--ctp-yellow); --danger: var(--ctp-red); --info: var(--ctp-blue); --focus: var(--ctp-lavender); --shadow: 0 12px 32px color-mix(in srgb, var(--ctp-overlay0) 28%, transparent); --shadow-sm: 0 4px 12px color-mix(in srgb, var(--ctp-overlay0) 18%, transparent); --glow: 0 0 0 3px color-mix(in srgb, var(--ctp-mauve) 30%, transparent); --stage-floor-a: #f8f9fc; --stage-floor-b: #eef0f6; } /* --- Reset / base --- */ *, *::before, *::after { box-sizing: border-box; } html, body { margin: 0; min-height: 100%; color: var(--text); font-family: var(--font-ui); font-size: 15px; line-height: 1.5; background: radial-gradient(ellipse 80% 50% at 10% -10%, color-mix(in srgb, var(--ctp-mauve) 18%, transparent), transparent 55%), radial-gradient(ellipse 60% 40% at 90% 0%, color-mix(in srgb, var(--ctp-peach) 14%, transparent), transparent 50%), radial-gradient(ellipse 50% 30% at 50% 100%, color-mix(in srgb, var(--ctp-pink) 10%, transparent), transparent 45%), var(--bg); background-attachment: fixed; -webkit-font-smoothing: antialiased; } [v-cloak] { display: none !important; } :focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; } ::selection { background: color-mix(in srgb, var(--ctp-mauve) 40%, transparent); color: var(--text); } #app { max-width: 1240px; margin: 0 auto; padding: var(--space-4) var(--space-4) var(--space-6); } /* --- Top bar --- */ .topbar { display: grid; grid-template-columns: minmax(200px, 1.2fr) minmax(0, 1.4fr) auto; gap: var(--space-3) var(--space-4); align-items: center; margin-bottom: var(--space-5); padding: var(--space-3) var(--space-4); background: color-mix(in srgb, var(--bg-elevated) 88%, transparent); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); backdrop-filter: blur(12px); } .brand { display: flex; gap: var(--space-3); align-items: center; min-width: 0; } .logo { width: 48px; height: 48px; flex-shrink: 0; border-radius: var(--radius); background: linear-gradient(145deg, var(--ctp-peach), var(--ctp-pink)); display: grid; place-items: center; font-size: 1.35rem; box-shadow: var(--shadow-sm), inset 0 1px 0 color-mix(in srgb, #fff 25%, transparent); } .brand h1 { margin: 0; font-size: 1.2rem; font-weight: 700; letter-spacing: 0.01em; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .brand .guide, .brand p { margin: 2px 0 0; color: var(--text-muted); font-size: 0.82rem; line-height: 1.35; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } .phase-track { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; } .phase-pill { font-size: 0.72rem; font-weight: 600; letter-spacing: 0.04em; padding: 0.28rem 0.65rem; border-radius: var(--radius-pill); border: 1px solid var(--border); background: var(--surface); color: var(--text-faint); transition: color 0.15s, background 0.15s, border-color 0.15s, box-shadow 0.15s; } .phase-pill.on { color: var(--ctp-crust); border-color: transparent; background: linear-gradient(135deg, var(--ctp-peach), var(--ctp-pink)); box-shadow: 0 4px 14px color-mix(in srgb, var(--ctp-peach) 35%, transparent); } .top-meta { display: flex; flex-wrap: wrap; gap: 0.4rem 0.65rem; align-items: center; justify-content: flex-end; color: var(--text-muted); font-size: 0.88rem; } .top-meta strong { color: var(--text); font-weight: 700; } .money-pill { background: var(--accent-soft); color: var(--accent); font-weight: 700; font-variant-numeric: tabular-nums; padding: 0.22rem 0.65rem; border-radius: var(--radius-pill); border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent); } .flavor-switch { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius-pill); overflow: hidden; background: var(--surface); } .flavor-switch button { border: 0; border-radius: 0; background: transparent; color: var(--text-muted); padding: 0.28rem 0.7rem; font-size: 0.75rem; font-weight: 600; } .flavor-switch button[aria-pressed="true"] { background: color-mix(in srgb, var(--ctp-mauve) 28%, var(--surface)); color: var(--text); } /* --- Layout --- */ .shell { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: var(--space-4); align-items: start; } /* --- Stage --- */ .stage-card { position: relative; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow); } .stage-bg { position: absolute; inset: 0; background-size: cover; background-position: center; opacity: 0.22; pointer-events: none; filter: saturate(1.05); } .stage-card.light-warm .stage-bg { filter: sepia(0.2) saturate(1.15); opacity: 0.28; } .stage-card.light-cool .stage-bg { filter: hue-rotate(20deg) brightness(1.05); opacity: 0.26; } .stage-card.light-off .stage-bg { filter: brightness(0.4) saturate(0.5); opacity: 0.18; } canvas { position: relative; display: block; width: 100%; height: auto; background: linear-gradient(180deg, var(--stage-floor-a), var(--stage-floor-b)); } .mood-bar { position: relative; display: flex; gap: var(--space-2); align-items: center; padding: 0.7rem 1rem; border-top: 1px solid var(--border); background: color-mix(in srgb, var(--bg-elevated) 92%, var(--surface)); color: var(--text-muted); font-size: 0.92rem; } .live { margin-left: auto; font-size: 0.78rem; font-weight: 700; color: var(--ctp-teal); background: color-mix(in srgb, var(--ctp-teal) 14%, transparent); padding: 0.15rem 0.55rem; border-radius: var(--radius-pill); } .live.dim { color: var(--text-faint); background: var(--surface); font-weight: 500; } /* Guest rail */ .guest-rail { border-top: 1px solid var(--border); background: var(--bg-deep); padding: 0.65rem 0.85rem 0.8rem; } .rail-title { font-size: 0.72rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-faint); font-weight: 700; margin-bottom: 0.45rem; } .rail-body { display: flex; gap: 0.5rem; overflow-x: auto; padding-bottom: 2px; scrollbar-width: thin; scrollbar-color: var(--surface-2) transparent; } .guest-card { display: flex; gap: 0.45rem; align-items: center; min-width: 152px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 0.4rem 0.55rem; transition: border-color 0.15s, box-shadow 0.15s, opacity 0.15s; } .guest-card.here { border-color: color-mix(in srgb, var(--ctp-peach) 55%, var(--border)); box-shadow: 0 0 0 2px color-mix(in srgb, var(--ctp-peach) 22%, transparent); } .guest-card.left { opacity: 0.5; } .guest-card img, .avatar-fallback { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; flex-shrink: 0; } .avatar-fallback { display: grid; place-items: center; background: linear-gradient(145deg, var(--ctp-mauve), var(--ctp-blue)); color: var(--ctp-crust); font-weight: 700; font-size: 0.9rem; } .guest-card b { display: block; font-size: 0.86rem; color: var(--text); } .guest-card small { color: var(--text-muted); font-size: 0.72rem; } .rail-empty { color: var(--text-faint); font-size: 0.88rem; padding: 0.35rem 0; } /* Floaters / toasts */ .floaters { pointer-events: none; position: absolute; left: 50%; top: 16%; transform: translateX(-50%); z-index: 5; display: flex; flex-direction: column; gap: 0.35rem; align-items: center; } .floater { background: color-mix(in srgb, var(--bg-elevated) 94%, transparent); border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 0.35rem 0.85rem; font-weight: 700; color: var(--text); animation: rise 1.5s ease-out forwards; box-shadow: var(--shadow-sm); backdrop-filter: blur(8px); } .floater.sale { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 45%, var(--border)); } .floater.enter { color: var(--ctp-peach); border-color: color-mix(in srgb, var(--ctp-peach) 40%, var(--border)); } @keyframes rise { from { opacity: 0; transform: translateY(12px); } 20% { opacity: 1; } to { opacity: 0; transform: translateY(-28px); } } .toast-stack { position: fixed; right: var(--space-4); bottom: var(--space-4); z-index: 40; display: flex; flex-direction: column; gap: 0.4rem; max-width: min(320px, 92vw); } .toast { background: var(--bg-elevated); border: 1px solid var(--border); border-left: 3px solid var(--ctp-lavender); border-radius: var(--radius); padding: 0.7rem 0.85rem; box-shadow: var(--shadow); animation: slidein 0.22s ease-out; font-size: 0.9rem; color: var(--text); } .toast.sale { border-left-color: var(--ok); } .toast.enter { border-left-color: var(--ctp-peach); } .toast.err { border-left-color: var(--danger); color: var(--danger); } .toast.phase { border-left-color: var(--ctp-mauve); } @keyframes slidein { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } } /* --- HUD cards --- */ .hud { display: flex; flex-direction: column; gap: var(--space-3); } .card { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: var(--space-4); box-shadow: var(--shadow-sm); } .card h2 { margin: 0 0 var(--space-3); font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-faint); font-weight: 700; } .stat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-2); margin-bottom: var(--space-3); } .stat-grid div { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.5rem 0.35rem; text-align: center; } .stat-grid em { display: block; font-style: normal; color: var(--text-faint); font-size: 0.7rem; margin-bottom: 2px; } .stat-grid b { font-size: 1.05rem; font-variant-numeric: tabular-nums; color: var(--text); } /* Atmosphere bars */ .atm { display: grid; grid-template-columns: 48px 1fr 34px; gap: 0.4rem; align-items: center; font-size: 0.8rem; margin-bottom: 0.4rem; color: var(--text-muted); } .bar { height: 8px; background: var(--surface); border-radius: var(--radius-pill); overflow: hidden; border: 1px solid var(--border); } .bar > i { display: block; height: 100%; background: linear-gradient(90deg, var(--ctp-mauve), var(--ctp-peach)); border-radius: var(--radius-pill); transition: width 0.35s ease; } .pct { color: var(--text-faint); text-align: right; font-variant-numeric: tabular-nums; font-size: 0.75rem; } /* Buttons & forms */ .btn-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.45rem; } .btn-grid.three { grid-template-columns: repeat(3, 1fr); } button, select { font: inherit; border-radius: var(--radius-pill); border: 1px solid var(--border); background: var(--surface); color: var(--text); padding: 0.5rem 0.85rem; cursor: pointer; transition: background 0.12s, border-color 0.12s, box-shadow 0.12s, opacity 0.12s; } button:hover:not(:disabled) { border-color: var(--border-strong); background: var(--surface-2); } button:active:not(:disabled) { transform: translateY(1px); } button:disabled { opacity: 0.42; cursor: not-allowed; } button.primary { background: linear-gradient(135deg, var(--ctp-peach), var(--ctp-pink)); border-color: transparent; color: var(--on-accent); font-weight: 700; box-shadow: 0 6px 18px color-mix(in srgb, var(--ctp-peach) 30%, transparent); } button.primary:hover:not(:disabled) { filter: brightness(1.05); background: linear-gradient(135deg, var(--ctp-peach), var(--ctp-pink)); } button.ghost { background: transparent; border-color: var(--border); color: var(--text-muted); } button.ghost:hover:not(:disabled) { background: var(--surface); color: var(--text); } button.active { border-color: color-mix(in srgb, var(--ctp-mauve) 55%, var(--border)); background: color-mix(in srgb, var(--ctp-mauve) 22%, var(--surface)); color: var(--ctp-lavender); font-weight: 650; } button.big { width: 100%; padding: 0.9rem 1rem; font-size: 1.05rem; margin: 0.2rem 0 0.55rem; border-radius: var(--radius); } button.wide { width: 100%; border-radius: var(--radius); } button.stable { transition: background 0.12s, border-color 0.12s; } button.stable:active { transform: none; } select { min-width: 0; width: 100%; appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--text-faint) 50%), linear-gradient(135deg, var(--text-faint) 50%, transparent 50%); background-position: calc(100% - 16px) calc(50% - 2px), calc(100% - 11px) calc(50% - 2px); background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; padding-right: 1.6rem; } .speed-row { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; margin-top: 0.65rem; color: var(--text-muted); font-size: 0.88rem; } .speed-row select { width: auto; min-width: 7.5rem; } .form-row { display: grid; grid-template-columns: 1fr auto; gap: 0.4rem; margin-bottom: 0.45rem; } .form-row.triple { grid-template-columns: 1fr 1fr auto; } .hint { margin: 0 0 0.5rem; font-size: 0.78rem; color: var(--warn); background: color-mix(in srgb, var(--warn) 12%, var(--surface)); border: 1px solid color-mix(in srgb, var(--warn) 28%, var(--border)); border-radius: var(--radius-sm); padding: 0.4rem 0.6rem; line-height: 1.4; } .hint.ok { color: var(--ok); background: color-mix(in srgb, var(--ok) 12%, var(--surface)); border-color: color-mix(in srgb, var(--ok) 28%, var(--border)); } .light-row { margin-top: 0.55rem; } .hero-actions .hint { margin-bottom: 0.55rem; } /* Log */ .log { list-style: none; margin: 0; padding: 0; max-height: 180px; overflow: auto; font-size: 0.84rem; color: var(--text-muted); scrollbar-width: thin; scrollbar-color: var(--surface-2) transparent; } .log li { padding: 0.4rem 0; border-bottom: 1px dashed color-mix(in srgb, var(--border) 80%, transparent); } .log li:first-child { color: var(--text); font-weight: 600; } /* Loading */ .loading { min-height: 50vh; display: grid; place-items: center; gap: 0.7rem; color: var(--text-muted); text-align: center; } .spinner { width: 40px; height: 40px; border-radius: 50%; border: 3px solid var(--surface); border-top-color: var(--ctp-peach); animation: spin 0.75s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* Modal */ .modal { position: fixed; inset: 0; background: color-mix(in srgb, var(--ctp-crust) 62%, transparent); display: grid; place-items: center; padding: var(--space-4); z-index: 30; backdrop-filter: blur(6px); } .modal-card { width: min(440px, 100%); background: var(--bg-elevated); border-radius: var(--radius-lg); border: 1px solid var(--border); padding: 1.35rem 1.4rem 1.25rem; box-shadow: var(--shadow); } .modal-kicker { color: var(--ctp-mauve); font-size: 0.75rem; letter-spacing: 0.14em; text-transform: uppercase; font-weight: 700; } .modal-card h2 { margin: 0.3rem 0 0.65rem; color: var(--text); text-transform: none; letter-spacing: 0; font-size: 1.25rem; } .modal-card .lead { color: var(--text); margin: 0 0 0.5rem; } .modal-card .diary { color: var(--text-muted); font-style: italic; margin: 0 0 1rem; } .night-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.45rem; margin-bottom: 0.85rem; } .night-stats div { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); text-align: center; padding: 0.55rem 0.3rem; } .night-stats em { display: block; font-style: normal; color: var(--text-faint); font-size: 0.72rem; } .vibe { color: var(--text-muted); font-size: 0.9rem; } .help-list { margin: 0.4rem 0 1rem; padding-left: 1.2rem; color: var(--text-muted); line-height: 1.75; } .help-list b { color: var(--text); } /* Footer */ .foot { margin-top: var(--space-5); text-align: center; color: var(--text-faint); font-size: 0.8rem; } .foot a { color: var(--ctp-lavender); text-decoration: none; } .foot a:hover { text-decoration: underline; } /* Responsive */ @media (max-width: 960px) { .topbar { grid-template-columns: 1fr; } .top-meta { justify-content: flex-start; } .phase-track { justify-content: flex-start; } .shell { grid-template-columns: 1fr; } .form-row.triple { grid-template-columns: 1fr; } } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } }