Serve the rulebook as a static HTML page from FastAPI
Replace the SPA Rules route with a self-contained src/pirats/rules.html served at GET /rules (registered before the SPA mount, included in package data for the Nix build). Plain anchor links replace the scrollIntoView workaround since there's no hash router to fight. The corner Rules link and splash-page link now point at /rules, and the Vite dev server proxies /rules to the backend like /api. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,18 +4,37 @@
|
||||
import Join from './pages/Join.svelte';
|
||||
import Dashboard from './pages/Dashboard.svelte';
|
||||
import Admin from './pages/Admin.svelte';
|
||||
import Rules from './pages/Rules.svelte';
|
||||
|
||||
const routes = {
|
||||
'/': Home,
|
||||
'/game/:id/join': Join,
|
||||
'/game/:id/player/:pid': Dashboard,
|
||||
'/game/:id/admin': Admin,
|
||||
'/rules': Rules,
|
||||
};
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<Router {routes} />
|
||||
<a class="rules-corner-link" href="#/rules" target="_blank" rel="noopener" title="Open the rulebook in a new tab">📖 Rules</a>
|
||||
<a class="rules-corner-link" href="/rules" target="_blank" rel="noopener" title="Open the rulebook in a new tab">📖 Rules</a>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
.rules-corner-link {
|
||||
position: fixed;
|
||||
top: 12px;
|
||||
left: 16px;
|
||||
z-index: 1001;
|
||||
padding: 6px 14px;
|
||||
border-radius: 16px;
|
||||
background: rgba(10, 15, 25, 0.9);
|
||||
border: 1px solid var(--glass-border-focus);
|
||||
color: var(--neon-cyan);
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
font-family: var(--font-heading);
|
||||
}
|
||||
.rules-corner-link:hover {
|
||||
background: rgba(0, 242, 254, 0.1);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -9,4 +9,3 @@
|
||||
@import './assets/css/card.css';
|
||||
@import './assets/css/upkeep.css';
|
||||
@import './assets/css/admin.css';
|
||||
@import './assets/css/rules.css';
|
||||
|
||||
@@ -1,242 +0,0 @@
|
||||
/* --- Rules Page --- */
|
||||
.rules-page {
|
||||
max-width: 860px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 1rem 4rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.rules-page .glass-panel {
|
||||
padding: 1.5rem 2rem;
|
||||
}
|
||||
|
||||
.rules-header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.rules-header h1 {
|
||||
font-family: var(--font-heading);
|
||||
color: var(--gold);
|
||||
font-size: 2.4rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.rules-subtitle {
|
||||
color: var(--text-primary);
|
||||
font-size: 1.15rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.rules-credits {
|
||||
color: var(--text-muted);
|
||||
font-size: 0.85rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.rules-credits a {
|
||||
color: var(--neon-cyan);
|
||||
}
|
||||
|
||||
.playtest-note {
|
||||
margin-top: 0.75rem;
|
||||
padding: 0.5rem 1rem;
|
||||
border: 1px dashed var(--glass-border);
|
||||
border-radius: 8px;
|
||||
color: var(--gold);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.rules-toc h2 {
|
||||
font-family: var(--font-heading);
|
||||
color: var(--gold);
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.rules-toc ul {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.rules-toc ul ul {
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.rules-toc li {
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
.rules-toc button {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--neon-cyan);
|
||||
cursor: pointer;
|
||||
font-family: var(--font-body);
|
||||
font-size: 1rem;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.rules-toc button:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.rules-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.rules-body section {
|
||||
scroll-margin-top: 1rem;
|
||||
}
|
||||
|
||||
.rules-body h2 {
|
||||
font-family: var(--font-heading);
|
||||
color: var(--gold);
|
||||
font-size: 1.8rem;
|
||||
margin-bottom: 1rem;
|
||||
border-bottom: 1px solid var(--glass-border);
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.rules-body h3 {
|
||||
font-family: var(--font-heading);
|
||||
color: var(--text-primary);
|
||||
font-size: 1.35rem;
|
||||
margin: 1.5rem 0 0.75rem;
|
||||
scroll-margin-top: 1rem;
|
||||
}
|
||||
|
||||
.rules-body h4 {
|
||||
color: var(--gold);
|
||||
font-size: 1.1rem;
|
||||
margin: 1.25rem 0 0.5rem;
|
||||
}
|
||||
|
||||
.rules-body h5 {
|
||||
color: var(--text-primary);
|
||||
font-size: 1rem;
|
||||
margin: 1rem 0 0.5rem;
|
||||
}
|
||||
|
||||
.objective-note {
|
||||
color: var(--text-muted);
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.rules-body p {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.rules-body ul,
|
||||
.rules-body ol {
|
||||
margin: 0 0 0.75rem 1.5rem;
|
||||
}
|
||||
|
||||
.rules-body li {
|
||||
margin-bottom: 0.35rem;
|
||||
}
|
||||
|
||||
.rules-body .aside {
|
||||
color: var(--text-muted);
|
||||
font-style: italic;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
.technique-examples {
|
||||
list-style: none;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.rules-body table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 0.75rem 0 1rem;
|
||||
background: rgba(7, 11, 18, 0.5);
|
||||
border: 1px solid var(--glass-border);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.rules-body th,
|
||||
.rules-body td {
|
||||
padding: 0.5rem 0.75rem;
|
||||
border-bottom: 1px solid rgba(212, 175, 55, 0.1);
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.rules-body thead th {
|
||||
color: var(--gold);
|
||||
font-family: var(--font-heading);
|
||||
}
|
||||
|
||||
.obstacle-chart th {
|
||||
width: 2.5rem;
|
||||
text-align: center;
|
||||
color: var(--gold);
|
||||
font-family: var(--font-heading);
|
||||
}
|
||||
|
||||
.suit-ways th {
|
||||
width: 7.5rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.suit-red {
|
||||
color: var(--red-suit);
|
||||
}
|
||||
|
||||
.suit-black {
|
||||
color: var(--black-suit);
|
||||
}
|
||||
|
||||
.rules-body details {
|
||||
border: 1px solid var(--glass-border);
|
||||
border-radius: 8px;
|
||||
padding: 0.75rem 1rem;
|
||||
}
|
||||
|
||||
.rules-body details summary {
|
||||
cursor: pointer;
|
||||
color: var(--neon-cyan);
|
||||
font-weight: 600;
|
||||
padding: 0.25rem 0;
|
||||
}
|
||||
|
||||
.rules-body details[open] summary {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.signature {
|
||||
color: var(--gold);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.back-to-top {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* --- Always-available rules corner link (rendered by App.svelte) --- */
|
||||
.rules-corner-link {
|
||||
position: fixed;
|
||||
top: 12px;
|
||||
left: 16px;
|
||||
z-index: 1001;
|
||||
padding: 6px 14px;
|
||||
border-radius: 16px;
|
||||
background: rgba(10, 15, 25, 0.9);
|
||||
border: 1px solid var(--glass-border-focus);
|
||||
color: var(--neon-cyan);
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
font-family: var(--font-heading);
|
||||
}
|
||||
|
||||
.rules-corner-link:hover {
|
||||
background: rgba(0, 242, 254, 0.1);
|
||||
}
|
||||
@@ -56,6 +56,6 @@
|
||||
</div>
|
||||
|
||||
<div class="links mt-4">
|
||||
<a href="#/rules" class="text-muted">Read the Rules</a>
|
||||
<a href="/rules" class="text-muted">Read the Rules</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,10 @@ export default defineConfig({
|
||||
'/api': {
|
||||
target: 'http://127.0.0.1:8000',
|
||||
changeOrigin: true,
|
||||
},
|
||||
'/rules': {
|
||||
target: 'http://127.0.0.1:8000',
|
||||
changeOrigin: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user