Refer to various aspects of "IMMORTAL: Gates of Pyre" from this external reference!
+
+
+
Cooldown Demo
+
+ Click Me
+
+
@@ -42,6 +51,18 @@
.mainContainer {
padding-bottom: 32px;
}
+ .cooldown-demo {
+ margin-top: 32px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 12px;
+ }
+ .cooldown-demo-label {
+ font-size: 1rem;
+ font-weight: 600;
+ color: var(--text-secondary, #aaa);
+ }
.mainTitle {
font-size: 2.2rem;
@@ -62,4 +83,11 @@
grid-template-columns: 1fr;
}
}
-
\ No newline at end of file
+
+
+@code {
+ private Task OnCooldownClick()
+ {
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/docs/.obsidian/workspace.json b/docs/.obsidian/workspace.json
index 1ce87e7..f956ad5 100644
--- a/docs/.obsidian/workspace.json
+++ b/docs/.obsidian/workspace.json
@@ -42,12 +42,12 @@
"state": {
"type": "markdown",
"state": {
- "file": "Build Calculator CmdLine.md",
+ "file": "Feature Proposals.md",
"mode": "source",
"source": false
},
"icon": "lucide-file",
- "title": "Build Calculator CmdLine"
+ "title": "Feature Proposals"
}
}
],
@@ -225,10 +225,11 @@
},
"active": "68e1ba2b54081b9a",
"lastOpenFiles": [
- "Device MAUI Pages Setup.md",
+ "cooldown-button.md",
"Build Calculator CmdLine.md",
- "Feature Proposals.md",
"_Tasks Kanban.base",
+ "Device MAUI Pages Setup.md",
+ "Feature Proposals.md",
"Tasks/Worker Income UI and Tests.md",
"Tasks/Update the Reference Tables with Telerik.md",
"Tasks/WebAssembly back to Azure.md",
@@ -251,7 +252,6 @@
"Tasks/Highest Alloy and Ether Tests.md",
"Tasks/Get AI to Add easy Test Tasks.md",
"Tasks/Helper Tutorial Info Improvements.md",
- "Tasks/Fix Entity Recursion Error - Parent.md",
"Tasks",
"Images/Pasted image 20260601093510.png",
"Images/Pasted image 20260601083333.png",
diff --git a/docs/cooldown-button.md b/docs/cooldown-button.md
new file mode 100644
index 0000000..5bc85c2
--- /dev/null
+++ b/docs/cooldown-button.md
@@ -0,0 +1,111 @@
+# Cooldown Button Component
+
+A square Blazor button with a 12-second cooldown animation: when clicked, the button greys out and a circular transparency wedge dials open clockwise, progressively revealing the normal button state underneath.
+
+---
+
+## Visual Design
+
+The button has two visual states:
+
+**Idle state** – A solid square button with the project's standard `--paper` background and `--primary` border. Hover inverts or brightens the paper. Click triggers a brief scale-down.
+
+**Cooldown state** – The native button fades to `opacity: 0` while an absolutely-positioned overlay covers it. The overlay uses a `conic-gradient` CSS mask to create a "dialling open" effect. A number in the centre shows the remaining seconds.
+
+---
+
+## Core Technique: Conic-Gradient Mask
+
+The cooldown reveal is accomplished with a **conic-gradient mask** applied to the overlay `
`:
+
+```
+mask-image: conic-gradient(
+ transparent 0deg,
+ transparent {angle}deg,
+ #000 {angle}deg,
+ #000 360deg
+);
+```
+
+- **`transparent`** – lets the button underneath show through (revealed area)
+- **`#000` (black)** – fully masks the overlay, making it visible (greyed-out area)
+
+At `angle = 0deg`, transparent covers nothing and the mask is entirely black → the overlay is fully opaque (button completely greyed out).
+
+At `angle = 360deg`, transparent covers the full circle and black covers nothing → the overlay is fully transparent (button completely visible).
+
+The angle animates linearly from 0 to 360 over the cooldown duration. Because `conic-gradient` starts at the 12 o'clock position and sweeps clockwise, the reveal begins at the top of the button and rotates around, like a clock hand or a dial opening.
+
+---
+
+## Implementation Architecture
+
+### Component Parameters
+
+| Parameter | Type | Default | Description |
+|------------------|-------------------|---------|------------------------------------|
+| `ChildContent` | `RenderFragment` | `null` | Text or content inside the button |
+| `OnClick` | `EventCallback` | — | Fired when the button is clicked |
+| `CooldownSeconds`| `int` | `12` | Duration of the cooldown in seconds|
+| `Size` | `int` | `120` | Width and height in pixels (square)|
+
+### Timer Loop
+
+A `System.Timers.Timer` fires every ~33 ms (≈30 fps) during the cooldown:
+
+```
+OnTick:
+ elapsed = UtcNow - startTime
+ if elapsed >= CooldownSeconds → end cooldown, dispose timer
+ _elapsedAngle = (elapsed / CooldownSeconds) * 360
+ _remainingSeconds = CooldownSeconds - (int)elapsed
+ InvokeAsync(StateHasChanged)
+```
+
+On each tick, `_elapsedAngle` is written into the overlay's inline `style` attribute, causing Blazor to re-render the `mask-image`. The timer is disposed in `Dispose()` to prevent leaks.
+
+### Disposal
+
+The component implements `IDisposable` to clean up the timer when the component is removed from the render tree. This follows the same pattern used by `SearchDialogComponent` and `BuildChartComponent` elsewhere in the codebase.
+
+---
+
+## CSS Masking Details
+
+Two vendor-prefixed properties are set to ensure cross-browser support:
+
+```
+mask-image: conic-gradient(...);
+-webkit-mask-image: conic-gradient(...);
+```
+
+The overlay uses `pointer-events: none` and `user-select: none` so that interaction passes through to the button underneath (which is disabled and transparent).
+
+An `rgba(22, 22, 24, 0.82)` semi-transparent background on the overlay produces the greyed-out appearance. The mask controls *where* this background is visible.
+
+---
+
+## Usage on the Home Page
+
+The component is added to `Pages/Pages/Home/HomePage.razor` inside the first `PaperComponent`:
+
+```razor
+
+ Click Me
+
+```
+
+The `OnCooldownClick` handler in the page's `@code` block currently returns `Task.CompletedTask` (a no-op). This is the extension point where real work (e.g. triggering a game action, calling an API, showing a toast) would go.
+
+---
+
+## Adapting the Component
+
+- **Change cooldown duration** – set `CooldownSeconds` to any positive integer.
+- **Change button size** – set `Size` to any pixel dimension (button remains square).
+- **Custom content** – pass any Blazor markup as `ChildContent` (text, icons, spinners).
+- **Handle the click** – attach a handler to `OnClick` that returns `Task` or `void`.
+
+The `--cooldown-size` CSS custom property is set inline on the wrapper so that the label, overlay, and button all scale together.