chore: rename app from Solitaire Quest to Ferrous Solitaire

Replace all display-name occurrences across web pages, Rust source,
docs, and Cargo metadata. Update localStorage token key from sq_token
to fs_token. Tagline "Klondike Solitaire" retained as genre descriptor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-05-13 17:04:45 -07:00
parent ea58f5dd64
commit 8325bf6cf7
39 changed files with 56 additions and 56 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
# Solitaire Quest — Architecture Document # Ferrous Solitaire — Architecture Document
> **Version:** 1.3 > **Version:** 1.3
> **Language:** Rust (Edition 2024) > **Language:** Rust (Edition 2024)
@@ -34,7 +34,7 @@
## 1. Project Overview ## 1. Project Overview
Solitaire Quest is a cross-platform Klondike Solitaire game written in Rust, targeting macOS, Windows, and Linux desktops. It features a full progression system with XP, levels, achievements, daily challenges, and an optional self-hosted sync server so statistics and progress are available across all of a player's devices. Ferrous Solitaire is a cross-platform Klondike Solitaire game written in Rust, targeting macOS, Windows, and Linux desktops. It features a full progression system with XP, levels, achievements, daily challenges, and an optional self-hosted sync server so statistics and progress are available across all of a player's devices.
### Sync Backend by Platform ### Sync Backend by Platform
+1 -1
View File
@@ -1,6 +1,6 @@
# Changelog # Changelog
All notable changes to Solitaire Quest are documented here. The format is All notable changes to Ferrous Solitaire are documented here. The format is
based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this
project follows [Semantic Versioning](https://semver.org/). project follows [Semantic Versioning](https://semver.org/).
+3 -3
View File
@@ -1,6 +1,6 @@
# Credits # Credits
Solitaire Quest is MIT-licensed (see [LICENSE](LICENSE)). It is built on top of Ferrous Solitaire is MIT-licensed (see [LICENSE](LICENSE)). It is built on top of
the work of many open-source projects and a small handful of third-party the work of many open-source projects and a small handful of third-party
assets. This file lists every component that ships in the binary or in the assets. This file lists every component that ships in the binary or in the
`assets/` directory. `assets/` directory.
@@ -43,7 +43,7 @@ copyleft code is statically linked into the game binary.
| File(s) | Source | License | | File(s) | Source | License |
|---|---|---| |---|---|---|
| `solitaire_engine/assets/themes/default/{suit}_{rank}.svg` (52 SVGs) | [hayeah/playing-cards-assets](https://github.com/hayeah/playing-cards-assets) | MIT | | `solitaire_engine/assets/themes/default/{suit}_{rank}.svg` (52 SVGs) | [hayeah/playing-cards-assets](https://github.com/hayeah/playing-cards-assets) | MIT |
| `solitaire_engine/assets/themes/default/back.svg` | Original — Solitaire Quest | MIT (this project) | | `solitaire_engine/assets/themes/default/back.svg` | Original — Ferrous Solitaire | MIT (this project) |
| `assets/cards/faces/{RANK}{SUIT}.png` (52 PNGs) | Pre-rendered from the same `playing-cards-assets` SVGs | MIT (passed through from hayeah) | | `assets/cards/faces/{RANK}{SUIT}.png` (52 PNGs) | Pre-rendered from the same `playing-cards-assets` SVGs | MIT (passed through from hayeah) |
| `assets/cards/backs/back_0.png` `back_4.png` | Original — generated by `solitaire_assetgen::gen_art` | MIT (this project) | | `assets/cards/backs/back_0.png` `back_4.png` | Original — generated by `solitaire_assetgen::gen_art` | MIT (this project) |
@@ -107,6 +107,6 @@ Audio files are MIT-licensed alongside the rest of this project.
backs, every audio file) are original work covered by this project's MIT backs, every audio file) are original work covered by this project's MIT
license. license.
If you redistribute Solitaire Quest, you must ship this `CREDITS.md` and the If you redistribute Ferrous Solitaire, you must ship this `CREDITS.md` and the
`LICENSE` file alongside the binary so the MIT (project + hayeah card art) `LICENSE` file alongside the binary so the MIT (project + hayeah card art)
and OFL (FiraMono) notices remain visible to end users. and OFL (FiraMono) notices remain visible to end users.
+1 -1
View File
@@ -1,4 +1,4 @@
# Solitaire Quest # Ferrous Solitaire
A cross-platform Klondike Solitaire game written in Rust, with a card-theme A cross-platform Klondike Solitaire game written in Rust, with a card-theme
system, full progression (XP / levels / achievements / daily challenges), and system, full progression (XP / levels / achievements / daily challenges), and
+1 -1
View File
@@ -1,4 +1,4 @@
# Solitaire Quest — Self-Hosting Guide # Ferrous Solitaire — Self-Hosting Guide
## Prerequisites ## Prerequisites
+2 -2
View File
@@ -1,4 +1,4 @@
# Solitaire Quest — Session Handoff # Ferrous Solitaire — Session Handoff
**Last updated:** 2026-05-12 — Leaderboard display name shipped (`03be4fc`). All commits pushed to origin. **Last updated:** 2026-05-12 — Leaderboard display name shipped (`03be4fc`). All commits pushed to origin.
@@ -150,7 +150,7 @@ Items missing from the doc:
## Resume prompt ## Resume prompt
``` ```
You are a senior Rust + Bevy developer working on Solitaire Quest. You are a senior Rust + Bevy developer working on Ferrous Solitaire.
Working directory: <Rusty_Solitaire clone path>. Working directory: <Rusty_Solitaire clone path>.
Branch: master. v0.23.0 is the current version (HEAD: 03be4fc). Fully pushed. Branch: master. v0.23.0 is the current version (HEAD: 03be4fc). Fully pushed.
+2 -2
View File
@@ -1,4 +1,4 @@
# Solitaire Quest — Session Handoff (ARCHIVED) # Ferrous Solitaire — Session Handoff (ARCHIVED)
> **This file is from Phase 2 (2026-04-25, 242 tests). It is kept for historical > **This file is from Phase 2 (2026-04-25, 242 tests). It is kept for historical
> reference only. The authoritative session handoff is at the repo root: > reference only. The authoritative session handoff is at the repo root:
@@ -24,7 +24,7 @@ All seven Cargo crates created and compiling cleanly:
| `solitaire_engine` | Stub | Bevy ECS systems — all plugins added in Phase 3 | | `solitaire_engine` | Stub | Bevy ECS systems — all plugins added in Phase 3 |
| `solitaire_server` | Stub | Axum sync server — implemented in Phase 8C | | `solitaire_server` | Stub | Axum sync server — implemented in Phase 8C |
| `solitaire_gpgs` | Compile-time stub | Google Play Games bridge — Android only, JNI in Phase: Android | | `solitaire_gpgs` | Compile-time stub | Google Play Games bridge — Android only, JNI in Phase: Android |
| `solitaire_app` | Working | Opens blank Bevy window titled "Solitaire Quest" at 1280×800 | | `solitaire_app` | Working | Opens blank Bevy window titled "Ferrous Solitaire" at 1280×800 |
Fast compile profiles, `assets/` directory structure, and `.env.example` are all in place. Fast compile profiles, `assets/` directory structure, and `.env.example` are all in place.
+1 -1
View File
@@ -2,7 +2,7 @@
> **Date:** 2026-04-28 > **Date:** 2026-04-28
> **Author:** Claude Code > **Author:** Claude Code
> **Scope:** Feasibility analysis for porting Solitaire Quest to Android using cargo-mobile2 > **Scope:** Feasibility analysis for porting Ferrous Solitaire to Android using cargo-mobile2
--- ---
@@ -1,4 +1,4 @@
# Solitaire Quest — Phase 1 + 2: Workspace & Core Game Engine # Ferrous Solitaire — Phase 1 + 2: Workspace & Core Game Engine
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
@@ -555,7 +555,7 @@ fn main() {
.add_plugins( .add_plugins(
DefaultPlugins.set(WindowPlugin { DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window { primary_window: Some(Window {
title: "Solitaire Quest".into(), title: "Ferrous Solitaire".into(),
resolution: (1280.0, 800.0).into(), resolution: (1280.0, 800.0).into(),
..default() ..default()
}), }),
@@ -571,7 +571,7 @@ fn main() {
```bash ```bash
cargo run -p solitaire_app --features bevy/dynamic_linking cargo run -p solitaire_app --features bevy/dynamic_linking
``` ```
Expected: A blank Bevy window titled "Solitaire Quest" opens. Press Escape or close the window to exit. No panics or errors in the terminal. Expected: A blank Bevy window titled "Ferrous Solitaire" opens. Press Escape or close the window to exit. No panics or errors in the terminal.
--- ---
@@ -1210,7 +1210,7 @@ fn main() {
.add_plugins( .add_plugins(
DefaultPlugins.set(WindowPlugin { DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window { primary_window: Some(Window {
title: "Solitaire Quest".into(), title: "Ferrous Solitaire".into(),
resolution: (1280.0, 800.0).into(), resolution: (1280.0, 800.0).into(),
..default() ..default()
}), }),
+1 -1
View File
@@ -11,7 +11,7 @@
### Infrastructure ### Infrastructure
- Two machines (or VMs) referred to as **Machine A** and **Machine B** throughout this runbook. Both must be able to reach the sync server over the network. - Two machines (or VMs) referred to as **Machine A** and **Machine B** throughout this runbook. Both must be able to reach the sync server over the network.
- A running Solitaire Quest sync server reachable at a known URL, e.g. `https://solitaire.example.com`. See `README_SERVER.md` for setup. - A running Ferrous Solitaire sync server reachable at a known URL, e.g. `https://solitaire.example.com`. See `README_SERVER.md` for setup.
- Verify the server is live before starting: - Verify the server is live before starting:
```bash ```bash
+1 -1
View File
@@ -3,7 +3,7 @@
> **Why this exists.** The 24 mockups in this directory are mobile > **Why this exists.** The 24 mockups in this directory are mobile
> (390 × 844 logical, iPhone 14 Pro frame) with one exception > (390 × 844 logical, iPhone 14 Pro frame) with one exception
> (`home-menu-desktop.html`). The Stitch project that produced them > (`home-menu-desktop.html`). The Stitch project that produced them
> is named "Solitaire Quest *Mobile* Redesign" — the mobile-first > is named "Ferrous Solitaire *Mobile* Redesign" — the mobile-first
> framing was deliberate when the new Android target opened, but > framing was deliberate when the new Android target opened, but
> desktop is still the primary delivery surface. Porting the mobile > desktop is still the primary delivery surface. Porting the mobile
> mockups 1:1 would land a 390-px-wide column floating in the middle > mockups 1:1 would land a 390-px-wide column floating in the middle
+1 -1
View File
@@ -87,7 +87,7 @@ required = true
name = "android.permission.INTERNET" name = "android.permission.INTERNET"
[package.metadata.android.application] [package.metadata.android.application]
label = "Solitaire Quest" label = "Ferrous Solitaire"
# Launcher icon — references the density-bucketed mipmap resource above. # Launcher icon — references the density-bucketed mipmap resource above.
icon = "@mipmap/ic_launcher" icon = "@mipmap/ic_launcher"
# `debuggable` defaults to false on release builds; cargo-apk flips it # `debuggable` defaults to false on release builds; cargo-apk flips it
+1 -1
View File
@@ -106,7 +106,7 @@ pub fn run() {
DefaultPlugins DefaultPlugins
.set(WindowPlugin { .set(WindowPlugin {
primary_window: Some(Window { primary_window: Some(Window {
title: "Solitaire Quest".into(), title: "Ferrous Solitaire".into(),
// X11/Wayland WM_CLASS so taskbar managers group // X11/Wayland WM_CLASS so taskbar managers group
// multiple windows of this app correctly. // multiple windows of this app correctly.
name: Some("solitaire-quest".into()), name: Some("solitaire-quest".into()),
+1 -1
View File
@@ -1,4 +1,4 @@
//! Generates PNG assets for Solitaire Quest. //! Generates PNG assets for Ferrous Solitaire.
//! //!
//! Produces: //! Produces:
//! - 52 card face PNGs (120×168) — one per card, with rank, suit symbol, and //! - 52 card face PNGs (120×168) — one per card, with rank, suit symbol, and
+1 -1
View File
@@ -49,7 +49,7 @@ pub enum SyncBackend {
#[default] #[default]
#[serde(rename = "local")] #[serde(rename = "local")]
Local, Local,
/// Sync with a self-hosted Solitaire Quest server. /// Sync with a self-hosted Ferrous Solitaire server.
#[serde(rename = "solitaire_server")] #[serde(rename = "solitaire_server")]
SolitaireServer { SolitaireServer {
/// Base URL of the server, e.g. `"https://solitaire.example.com"`. /// Base URL of the server, e.g. `"https://solitaire.example.com"`.
+2 -2
View File
@@ -6,7 +6,7 @@
//! | Struct | Backend | //! | Struct | Backend |
//! |---|---| //! |---|---|
//! | [`LocalOnlyProvider`] | No-op; used when sync is disabled | //! | [`LocalOnlyProvider`] | No-op; used when sync is disabled |
//! | [`SolitaireServerClient`] | Self-hosted Solitaire Quest server (JWT auth) | //! | [`SolitaireServerClient`] | Self-hosted Ferrous Solitaire server (JWT auth) |
//! //!
//! Use [`provider_for_backend`] to obtain a `Box<dyn SyncProvider + Send + Sync>` //! Use [`provider_for_backend`] to obtain a `Box<dyn SyncProvider + Send + Sync>`
//! without matching on [`SyncBackend`] anywhere else in the codebase. //! without matching on [`SyncBackend`] anywhere else in the codebase.
@@ -55,7 +55,7 @@ impl SyncProvider for LocalOnlyProvider {
// SolitaireServerClient // SolitaireServerClient
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/// HTTP sync client for the self-hosted Solitaire Quest server. /// HTTP sync client for the self-hosted Ferrous Solitaire server.
/// ///
/// Authenticates via JWT stored in the OS keychain. On a 401 response the /// Authenticates via JWT stored in the OS keychain. On a 401 response the
/// client automatically attempts a token refresh and retries the request once /// client automatically attempts a token refresh and retries the request once
+1 -1
View File
@@ -1,4 +1,4 @@
//! SVG builder for the Solitaire Quest application icon. //! SVG builder for the Ferrous Solitaire application icon.
//! //!
//! Renders the project's signature `▌RS` Terminal mark (the same //! Renders the project's signature `▌RS` Terminal mark (the same
//! cursor-block + monogram pair used on the splash boot-screen and //! cursor-block + monogram pair used on the splash boot-screen and
+1 -1
View File
@@ -1,4 +1,4 @@
//! Bevy integration layer for Solitaire Quest. //! Bevy integration layer for Ferrous Solitaire.
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
pub mod android_clipboard; pub mod android_clipboard;
+3 -3
View File
@@ -9,7 +9,7 @@
//! //!
//! Slides: //! Slides:
//! //!
//! 1. **Welcome** — brief introduction to Solitaire Quest. //! 1. **Welcome** — brief introduction to Ferrous Solitaire.
//! 2. **How to play** — drag-and-drop, double-click, and right-click hints. //! 2. **How to play** — drag-and-drop, double-click, and right-click hints.
//! 3. **Keyboard shortcuts** — a summary pulled from the same canonical list //! 3. **Keyboard shortcuts** — a summary pulled from the same canonical list
//! used in `HelpScreen`. Accelerators: `Esc` anywhere in the flow skips //! used in `HelpScreen`. Accelerators: `Esc` anywhere in the flow skips
@@ -292,10 +292,10 @@ fn spawn_slide(commands: &mut Commands, index: u8, font_res: Option<&FontResourc
/// Slide 1 — Welcome. /// Slide 1 — Welcome.
fn spawn_slide_welcome(commands: &mut Commands, font_res: Option<&FontResource>) { fn spawn_slide_welcome(commands: &mut Commands, font_res: Option<&FontResource>) {
spawn_modal(commands, OnboardingScreen, Z_ONBOARDING, |card| { spawn_modal(commands, OnboardingScreen, Z_ONBOARDING, |card| {
spawn_modal_header(card, "Welcome to Solitaire Quest", font_res); spawn_modal_header(card, "Welcome to Ferrous Solitaire", font_res);
spawn_modal_body_text( spawn_modal_body_text(
card, card,
"Solitaire Quest is a free, offline-first Klondike Solitaire game. \ "Ferrous Solitaire is a free, offline-first Klondike Solitaire game. \
Play classic draw-1 or draw-3 Klondike, earn XP, unlock achievements, \ Play classic draw-1 or draw-3 Klondike, earn XP, unlock achievements, \
and compete on the leaderboard. Your progress is saved locally \ and compete on the leaderboard. Your progress is saved locally \
optional sync to your own server keeps it in step across all your devices.", optional sync to your own server keeps it in step across all your devices.",
+2 -2
View File
@@ -2343,7 +2343,7 @@ fn sync_row(
row, row,
SettingsButton::ConnectSync, SettingsButton::ConnectSync,
"Connect", "Connect",
"Connect to a self-hosted Solitaire Quest sync server.".to_string(), "Connect to a self-hosted Ferrous Solitaire sync server.".to_string(),
button_font, button_font,
); );
} }
@@ -2920,7 +2920,7 @@ mod tests {
.expect("Connect button should spawn with a Tooltip when backend is Local"); .expect("Connect button should spawn with a Tooltip when backend is Local");
assert_eq!( assert_eq!(
connect_tip.as_ref(), connect_tip.as_ref(),
"Connect to a self-hosted Solitaire Quest sync server.", "Connect to a self-hosted Ferrous Solitaire sync server.",
"ConnectSync tooltip must use the canonical microcopy" "ConnectSync tooltip must use the canonical microcopy"
); );
} }
+3 -3
View File
@@ -2,7 +2,7 @@
//! //!
//! On app start the engine spawns a fullscreen, high-Z overlay that //! On app start the engine spawns a fullscreen, high-Z overlay that
//! reads the Terminal-style "boot screen" — an accent-coloured cursor block, the //! reads the Terminal-style "boot screen" — an accent-coloured cursor block, the
//! "Solitaire Quest" wordmark, a short fixture boot log, a progress //! "Ferrous Solitaire" wordmark, a short fixture boot log, a progress
//! bar, and a footer with the design-system palette swatches and the //! bar, and a footer with the design-system palette swatches and the
//! build version. The overlay fades in over 300 ms, holds for ~1 s, //! build version. The overlay fades in over 300 ms, holds for ~1 s,
//! then fades out for 300 ms before despawning. The deal animation //! then fades out for 300 ms before despawning. The deal animation
@@ -383,7 +383,7 @@ fn spawn_header_section(parent: &mut ChildSpawnerCommands, font_handle: &Handle<
)); ));
hdr.spawn(( hdr.spawn((
SplashFadable { base_color: TEXT_PRIMARY }, SplashFadable { base_color: TEXT_PRIMARY },
Text::new("Solitaire Quest"), Text::new("Ferrous Solitaire"),
title_font, title_font,
TextColor(transparent(TEXT_PRIMARY)), TextColor(transparent(TEXT_PRIMARY)),
)); ));
@@ -1170,7 +1170,7 @@ mod tests {
"expected the cursor block (▌) on the splash, got: {texts:?}" "expected the cursor block (▌) on the splash, got: {texts:?}"
); );
assert!( assert!(
texts.iter().any(|t| t == "Solitaire Quest"), texts.iter().any(|t| t == "Ferrous Solitaire"),
"expected the wordmark on the splash, got: {texts:?}" "expected the wordmark on the splash, got: {texts:?}"
); );
assert!( assert!(
+1 -1
View File
@@ -1,4 +1,4 @@
//! Backend-agnostic sync plugin for Solitaire Quest. //! Backend-agnostic sync plugin for Ferrous Solitaire.
//! //!
//! On startup, the plugin spawns an async pull task on [`AsyncComputeTaskPool`] //! On startup, the plugin spawns an async pull task on [`AsyncComputeTaskPool`]
//! that fetches the remote payload from the active [`SyncProvider`]. Once the //! that fetches the remote payload from the active [`SyncProvider`]. Once the
+1 -1
View File
@@ -84,7 +84,7 @@ mod tests {
ThemeMeta { ThemeMeta {
id: "default".into(), id: "default".into(),
name: "Default".into(), name: "Default".into(),
author: "Solitaire Quest".into(), author: "Ferrous Solitaire".into(),
version: "1.0.0".into(), version: "1.0.0".into(),
card_aspect: (2, 3), card_aspect: (2, 3),
} }
+1 -1
View File
@@ -268,7 +268,7 @@ mod tests {
let meta = ThemeMeta { let meta = ThemeMeta {
id: "default".into(), id: "default".into(),
name: "Default".into(), name: "Default".into(),
author: "Solitaire Quest".into(), author: "Ferrous Solitaire".into(),
version: "1.0.0".into(), version: "1.0.0".into(),
card_aspect: (2, 3), card_aspect: (2, 3),
}; };
+1 -1
View File
@@ -115,7 +115,7 @@ fn default_entry() -> ThemeEntry {
meta: ThemeMeta { meta: ThemeMeta {
id: "default".to_string(), id: "default".to_string(),
name: "Default".to_string(), name: "Default".to_string(),
author: "Solitaire Quest".to_string(), author: "Ferrous Solitaire".to_string(),
version: "1.0".to_string(), version: "1.0".to_string(),
card_aspect: (2, 3), card_aspect: (2, 3),
}, },
+1 -1
View File
@@ -1,6 +1,6 @@
//! Keyboard focus ring for modal buttons (Phase 1). //! Keyboard focus ring for modal buttons (Phase 1).
//! //!
//! Solitaire Quest's 11 modals (Help, Stats, Achievements, Settings, //! Ferrous Solitaire's 11 modals (Help, Stats, Achievements, Settings,
//! Profile, Leaderboard, Pause, Forfeit confirm, GameOver, Confirm new //! Profile, Leaderboard, Pause, Forfeit confirm, GameOver, Confirm new
//! game, Onboarding) ship without any keyboard focus support. Phase 1 //! game, Onboarding) ship without any keyboard focus support. Phase 1
//! gives every button spawned via [`crate::ui_modal::spawn_modal_button`] //! gives every button spawned via [`crate::ui_modal::spawn_modal_button`]
+1 -1
View File
@@ -1,4 +1,4 @@
//! Solitaire Quest sync server library. //! Ferrous Solitaire sync server library.
//! //!
//! Exposes [`build_router`] so integration tests can construct the full Axum //! Exposes [`build_router`] so integration tests can construct the full Axum
//! application against an in-memory SQLite database without starting a real //! application against an in-memory SQLite database without starting a real
+1 -1
View File
@@ -1,4 +1,4 @@
//! Solitaire Quest sync server entry point. //! Ferrous Solitaire sync server entry point.
//! //!
//! Reads configuration from environment variables (via `dotenvy`), initialises //! Reads configuration from environment variables (via `dotenvy`), initialises
//! the SQLite database, runs migrations, then starts the Axum HTTP server. //! the SQLite database, runs migrations, then starts the Axum HTTP server.
+1 -1
View File
@@ -1,4 +1,4 @@
/* Solitaire Quest interactive game page. /* Ferrous Solitaire interactive game page.
Palette mirrors the Bevy app's Terminal (base16-eighties) design system. Palette mirrors the Bevy app's Terminal (base16-eighties) design system.
Card faces/backs are PNG images served from /assets/cards/. */ Card faces/backs are PNG images served from /assets/cards/. */
+2 -2
View File
@@ -3,14 +3,14 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Solitaire Quest — Play</title> <title>Ferrous Solitaire — Play</title>
<link rel="stylesheet" href="/web/game.css"> <link rel="stylesheet" href="/web/game.css">
</head> </head>
<body> <body>
<header> <header>
<div class="hud-left"> <div class="hud-left">
<a href="/" class="home-link" title="Home">&#8592;</a> <a href="/" class="home-link" title="Home">&#8592;</a>
<span class="logo">Solitaire Quest</span> <span class="logo">Ferrous Solitaire</span>
<span id="hud-seed" class="muted"></span> <span id="hud-seed" class="muted"></span>
</div> </div>
<div class="hud-center"> <div class="hud-center">
+1 -1
View File
@@ -1,4 +1,4 @@
// Solitaire Quest — interactive browser game. // Ferrous Solitaire — interactive browser game.
// //
// Architecture: // Architecture:
// - `SolitaireGame` (Rust/WASM via solitaire_core) owns all rule logic. // - `SolitaireGame` (Rust/WASM via solitaire_core) owns all rule logic.
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Solitaire Quest</title> <title>Ferrous Solitaire</title>
<style> <style>
@font-face { @font-face {
font-family: "FiraMono"; font-family: "FiraMono";
@@ -119,7 +119,7 @@
</style> </style>
</head> </head>
<body> <body>
<div class="logo">Solitaire Quest</div> <div class="logo">Ferrous Solitaire</div>
<div class="tagline">Klondike Solitaire</div> <div class="tagline">Klondike Solitaire</div>
<nav class="cards"> <nav class="cards">
+2 -2
View File
@@ -3,12 +3,12 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Solitaire Quest — Replay</title> <title>Ferrous Solitaire — Replay</title>
<link rel="stylesheet" href="/web/replay.css"> <link rel="stylesheet" href="/web/replay.css">
</head> </head>
<body> <body>
<header> <header>
<h1>Solitaire Quest <span class="muted">— Replay</span></h1> <h1>Ferrous Solitaire <span class="muted">— Replay</span></h1>
<div id="caption" class="muted">Loading…</div> <div id="caption" class="muted">Loading…</div>
</header> </header>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Solitaire Quest — Leaderboard</title> <title>Ferrous Solitaire — Leaderboard</title>
<style> <style>
@font-face { @font-face {
font-family: "FiraMono"; font-family: "FiraMono";
@@ -99,7 +99,7 @@
</table> </table>
</main> </main>
<script> <script>
const TOKEN_KEY = 'sq_token'; const TOKEN_KEY = 'fs_token';
function fmtTime(secs) { function fmtTime(secs) {
if (!secs) return '—'; if (!secs) return '—';
const m = Math.floor(secs / 60), s = secs % 60; const m = Math.floor(secs / 60), s = secs % 60;
+1 -1
View File
@@ -1,4 +1,4 @@
/* Solitaire Quest replay viewer Terminal (base16-eighties) palette, /* Ferrous Solitaire replay viewer Terminal (base16-eighties) palette,
matching the Bevy desktop/Android app's ui_theme.rs tokens exactly. */ matching the Bevy desktop/Android app's ui_theme.rs tokens exactly. */
:root { :root {
+1 -1
View File
@@ -1,4 +1,4 @@
// Solitaire Quest replay viewer. // Ferrous Solitaire replay viewer.
// //
// Pulls the replay JSON from `/api/replays/:id`, hands it to the // Pulls the replay JSON from `/api/replays/:id`, hands it to the
// `solitaire_wasm` ReplayPlayer (which owns a real solitaire_core // `solitaire_wasm` ReplayPlayer (which owns a real solitaire_core
+1 -1
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Solitaire Quest — Recent Replays</title> <title>Ferrous Solitaire — Recent Replays</title>
<style> <style>
@font-face { @font-face {
font-family: "FiraMono"; font-family: "FiraMono";
+1 -1
View File
@@ -1,4 +1,4 @@
//! Shared API types and merge logic for Solitaire Quest. //! Shared API types and merge logic for Ferrous Solitaire.
//! //!
//! This crate is the contract between the game client (`solitaire_data`) and //! This crate is the contract between the game client (`solitaire_data`) and
//! the sync server (`solitaire_server`). Changing any public type here is a //! the sync server (`solitaire_server`). Changing any public type here is a