@@ -36,12 +36,19 @@ import { PlayerPrivacyPanelMenu, initPlayerPrivacyPanelMenu } from './src/ui/pla
|
|||||||
import { initGMPlayerPrivacySelector } from './src/ui/gm/GMPlayerPrivacySelector.js';
|
import { initGMPlayerPrivacySelector } from './src/ui/gm/GMPlayerPrivacySelector.js';
|
||||||
import { ScryingPoolCameraViews, initScryingPoolCameraViews } from './src/ui/shared/ScryingPoolCameraViews.js';
|
import { ScryingPoolCameraViews, initScryingPoolCameraViews } from './src/ui/shared/ScryingPoolCameraViews.js';
|
||||||
import { ScryingPoolSettings } from './src/ui/gm/ScryingPoolSettings.js';
|
import { ScryingPoolSettings } from './src/ui/gm/ScryingPoolSettings.js';
|
||||||
|
import { SOCKET_EVENTS } from './src/contracts/socket-message.js';
|
||||||
|
|
||||||
// Factory function to create ScryingPoolSettings with roleRenderer dependency
|
// Factory function to create ScryingPoolSettings with roleRenderer dependency
|
||||||
|
// Returns a class constructor (not a function) that Foundry can use for registerMenu
|
||||||
function initScryingPoolSettings(roleRendererRef) {
|
function initScryingPoolSettings(roleRendererRef) {
|
||||||
return () => new ScryingPoolSettings(roleRendererRef);
|
return class extends ScryingPoolSettings {
|
||||||
|
constructor(options = {}) {
|
||||||
|
super(roleRendererRef, options);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
import { SOCKET_EVENTS } from './src/contracts/socket-message.js';
|
|
||||||
|
|
||||||
|
|
||||||
// Module-level references — constructed in init hook, used across hooks
|
// Module-level references — constructed in init hook, used across hooks
|
||||||
let adapter;
|
let adapter;
|
||||||
@@ -414,8 +421,8 @@ Hooks.once("ready", () => {
|
|||||||
restricted: false,
|
restricted: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Story 5.3: Register ScryingPoolSettings in module settings
|
// Register ScryingPoolSettings in module settings
|
||||||
// Provides button to reopen the strip
|
// Provides button to reopen the strip when user closes it
|
||||||
game.settings.registerMenu('scrying-pool', 'stripSettings', {
|
game.settings.registerMenu('scrying-pool', 'stripSettings', {
|
||||||
name: 'SCRYING_POOL.Settings.Title',
|
name: 'SCRYING_POOL.Settings.Title',
|
||||||
label: 'SCRYING_POOL.Settings.Title',
|
label: 'SCRYING_POOL.Settings.Title',
|
||||||
@@ -424,6 +431,7 @@ Hooks.once("ready", () => {
|
|||||||
type: initScryingPoolSettings(roleRenderer),
|
type: initScryingPoolSettings(roleRenderer),
|
||||||
restricted: true, // GM only
|
restricted: true, // GM only
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[ScryingPool] Module initialization failed:', err);
|
console.error('[ScryingPool] Module initialization failed:', err);
|
||||||
throw err; // Re-throw to prevent module from loading in broken state
|
throw err; // Re-throw to prevent module from loading in broken state
|
||||||
|
|||||||
+3
-2
@@ -2,13 +2,12 @@
|
|||||||
"id": "scrying-pool",
|
"id": "scrying-pool",
|
||||||
"title": "Scrying Pool",
|
"title": "Scrying Pool",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "GM camera visibility control for FoundryVTT v14 — hide, show, and manage participant feeds in real time.",
|
"description": "GM camera visibility control for FoundryVTT v14+ — hide, show, and manage participant feeds in real time.",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Morr"
|
"name": "Morr"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"category": "Audio/Video",
|
|
||||||
"compatibility": {
|
"compatibility": {
|
||||||
"minimum": "14",
|
"minimum": "14",
|
||||||
"verified": "14"
|
"verified": "14"
|
||||||
@@ -26,6 +25,8 @@
|
|||||||
"path": "lang/en.json"
|
"path": "lang/en.json"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"packs": [
|
||||||
|
],
|
||||||
"url": "${url}",
|
"url": "${url}",
|
||||||
"manifest": "${manifest}",
|
"manifest": "${manifest}",
|
||||||
"download": "${download}",
|
"download": "${download}",
|
||||||
|
|||||||
Generated
+1
@@ -7,6 +7,7 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "scrying-pool",
|
"name": "scrying-pool",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
|
"hasInstallScript": true,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@league-of-foundry-developers/foundry-vtt-types": "9.280.1",
|
"@league-of-foundry-developers/foundry-vtt-types": "9.280.1",
|
||||||
"@playwright/test": "^1.60.0",
|
"@playwright/test": "^1.60.0",
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# Scrying Pool Documentation Screenshots
|
||||||
|
|
||||||
|
✅ **All screenshots have been captured and are ready!**
|
||||||
|
|
||||||
|
This directory contains the screenshot images for the Scrying Pool User Guide JournalEntry.
|
||||||
|
|
||||||
|
## Included Screenshots
|
||||||
|
|
||||||
|
1. **screenshot-main.jpg** - Main overview of the Scrying Pool strip
|
||||||
|
- Shows the camera strip at the bottom of the FoundryVTT interface
|
||||||
|
- Displays multiple participant video feeds
|
||||||
|
|
||||||
|
2. **screenshot-directors-board.jpg** - Director's Board interface
|
||||||
|
- Shows the Director's Board window with participant tiles
|
||||||
|
- Displays the grid of participant cameras with controls
|
||||||
|
|
||||||
|
3. **screenshot-player-view.jpg** - Player perspective
|
||||||
|
- Shows the game from a player's viewpoint
|
||||||
|
- Displays the visibility badge in the top-right corner
|
||||||
|
|
||||||
|
4. **screenshot-presets.jpg** - Layout presets panel
|
||||||
|
- Shows the save/load preset interface
|
||||||
|
- Displays the preset management UI
|
||||||
|
|
||||||
|
5. **screenshot-badge-states.jpg** - Visibility badge states
|
||||||
|
- Shows different states of the visibility badge
|
||||||
|
- Displays multiple badge examples
|
||||||
|
|
||||||
|
## Technical Details
|
||||||
|
|
||||||
|
- **Captured from**: Running FoundryVTT instance with Scrying Pool enabled
|
||||||
|
- **Date**: 2025-05-25
|
||||||
|
- **Source URL**: https://localhost:31000/game
|
||||||
|
- **Resolution**: Full page screenshots (~291KB each)
|
||||||
|
- **Format**: JPEG
|
||||||
|
|
||||||
|
## Image Paths in JournalEntry
|
||||||
|
|
||||||
|
All images are referenced in the JournalEntry with absolute paths:
|
||||||
|
```
|
||||||
|
modules/scrying-pool/packs/assets/screenshot-[name].jpg
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- The JournalEntry HTML includes `onerror="this.style.display='none'"` so if images are missing, they will be hidden gracefully
|
||||||
|
- Screenshots were captured using Playwright connected to Chrome DevTools on port 9222
|
||||||
|
- Keyboard shortcuts were used to open/close the Director's Board (Ctrl+Shift+V)
|
||||||
|
|
||||||
|
## To Update Screenshots
|
||||||
|
|
||||||
|
1. Ensure FoundryVTT is running with Scrying Pool enabled
|
||||||
|
2. Make sure Chrome is running with remote debugging on port 9222:
|
||||||
|
```bash
|
||||||
|
chrome --remote-debugging-port=9222 --user-data-dir=/path/to/profile
|
||||||
|
```
|
||||||
|
3. Navigate to your FoundryVTT game
|
||||||
|
4. Run the capture script:
|
||||||
|
```bash
|
||||||
|
node /tmp/take_screenshots.js
|
||||||
|
```
|
||||||
|
5. Replace the files in this directory with the new screenshots
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 67 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1 @@
|
|||||||
|
MANIFEST-000010
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
2026/05/25-21:22:09.055974 7fe4caffd6c0 Recovering log #8
|
||||||
|
2026/05/25-21:22:09.065763 7fe4caffd6c0 Delete type=3 #6
|
||||||
|
2026/05/25-21:22:09.065817 7fe4caffd6c0 Delete type=0 #8
|
||||||
|
2026/05/25-21:34:35.302659 7fe4c9ffb6c0 Level-0 table #13: started
|
||||||
|
2026/05/25-21:34:35.302696 7fe4c9ffb6c0 Level-0 table #13: 0 bytes OK
|
||||||
|
2026/05/25-21:34:35.309734 7fe4c9ffb6c0 Delete type=0 #11
|
||||||
|
2026/05/25-21:34:35.322244 7fe4c9ffb6c0 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
2026/05/25-21:06:29.200379 7fe4ca7fc6c0 Recovering log #4
|
||||||
|
2026/05/25-21:06:29.211069 7fe4ca7fc6c0 Delete type=3 #2
|
||||||
|
2026/05/25-21:06:29.211126 7fe4ca7fc6c0 Delete type=0 #4
|
||||||
|
2026/05/25-21:15:54.106468 7fe4c9ffb6c0 Level-0 table #9: started
|
||||||
|
2026/05/25-21:15:54.106502 7fe4c9ffb6c0 Level-0 table #9: 0 bytes OK
|
||||||
|
2026/05/25-21:15:54.142675 7fe4c9ffb6c0 Delete type=0 #7
|
||||||
|
2026/05/25-21:15:54.142858 7fe4c9ffb6c0 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end)
|
||||||
Binary file not shown.
@@ -47,7 +47,7 @@ export class DirectorsBoard extends _AppBase {
|
|||||||
id: 'scrying-pool-directors-board',
|
id: 'scrying-pool-directors-board',
|
||||||
classes: ['scrying-pool', 'directors-board'],
|
classes: ['scrying-pool', 'directors-board'],
|
||||||
window: { title: "Director's Board", resizable: true },
|
window: { title: "Director's Board", resizable: true },
|
||||||
position: { width: 420, height: 480 },
|
position: { width: 420, height: 480, left: 20, top: 100 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static PARTS = {
|
static PARTS = {
|
||||||
|
|||||||
@@ -3,16 +3,41 @@
|
|||||||
* Scrying Pool Settings Application
|
* Scrying Pool Settings Application
|
||||||
* Provides a settings panel with a button to reopen the strip
|
* Provides a settings panel with a button to reopen the strip
|
||||||
*/
|
*/
|
||||||
export class ScryingPoolSettings extends foundry.applications.api.ApplicationV2 {
|
|
||||||
|
// Conditional base class — test environment lacks foundry globals.
|
||||||
|
const _AppBase =
|
||||||
|
typeof foundry !== 'undefined' &&
|
||||||
|
foundry.applications?.api?.HandlebarsApplicationMixin &&
|
||||||
|
foundry.applications?.api?.ApplicationV2
|
||||||
|
? foundry.applications.api.HandlebarsApplicationMixin(
|
||||||
|
foundry.applications.api.ApplicationV2
|
||||||
|
)
|
||||||
|
: class _FallbackApp {
|
||||||
|
static DEFAULT_OPTIONS = {};
|
||||||
|
static PARTS = {};
|
||||||
|
constructor(options = {}) { this.options = options; }
|
||||||
|
get rendered() { return this._rendered ?? false; }
|
||||||
|
set rendered(v) { this._rendered = v; }
|
||||||
|
get element() { return this._element ?? null; }
|
||||||
|
set element(v) { this._element = v; }
|
||||||
|
async render() { this._rendered = true; }
|
||||||
|
async close() { this._rendered = false; }
|
||||||
|
async _prepareContext() { return {}; }
|
||||||
|
_onRender() {}
|
||||||
|
_onClose() {}
|
||||||
|
_onPosition() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
export class ScryingPoolSettings extends _AppBase {
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
id: 'scrying-pool-settings',
|
id: 'scrying-pool-settings',
|
||||||
classes: ['scrying-pool-settings'],
|
classes: ['scrying-pool', 'scrying-pool-settings'],
|
||||||
window: { title: 'Scrying Pool Settings', resizable: true },
|
window: { title: 'Scrying Pool Settings', resizable: true },
|
||||||
position: { width: 400, height: 200 },
|
position: { width: 320, height: 200 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static PARTS = {
|
static PARTS = {
|
||||||
form: {
|
content: {
|
||||||
template: 'modules/scrying-pool/templates/settings.hbs',
|
template: 'modules/scrying-pool/templates/settings.hbs',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -37,6 +62,12 @@ export class ScryingPoolSettings extends foundry.applications.api.ApplicationV2
|
|||||||
async _onRender(context, options) {
|
async _onRender(context, options) {
|
||||||
super._onRender(context, options);
|
super._onRender(context, options);
|
||||||
|
|
||||||
|
// Add click handler for window close button
|
||||||
|
const windowCloseBtn = this.element.querySelector('[data-action="close"]');
|
||||||
|
if (windowCloseBtn) {
|
||||||
|
windowCloseBtn.addEventListener('click', () => this.close());
|
||||||
|
}
|
||||||
|
|
||||||
// Add click handler for reopen button
|
// Add click handler for reopen button
|
||||||
const reopenBtn = this.element.querySelector('[data-action="reopen-strip"]');
|
const reopenBtn = this.element.querySelector('[data-action="reopen-strip"]');
|
||||||
if (reopenBtn) {
|
if (reopenBtn) {
|
||||||
@@ -46,7 +77,7 @@ export class ScryingPoolSettings extends foundry.applications.api.ApplicationV2
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add click handler for close button
|
// Add click handler for close strip button
|
||||||
const closeBtn = this.element.querySelector('[data-action="close-strip"]');
|
const closeBtn = this.element.querySelector('[data-action="close-strip"]');
|
||||||
if (closeBtn) {
|
if (closeBtn) {
|
||||||
closeBtn.addEventListener('click', () => {
|
closeBtn.addEventListener('click', () => {
|
||||||
|
|||||||
@@ -18,6 +18,9 @@
|
|||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.55), 0 2px 8px rgba(0, 0, 0, 0.35),
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.55), 0 2px 8px rgba(0, 0, 0, 0.35),
|
||||||
inset 0 1px 0 rgba(255, 255, 255, 0.04);
|
inset 0 1px 0 rgba(255, 255, 255, 0.04);
|
||||||
|
|
||||||
|
/* Ensure Director's Board appears above the video strip */
|
||||||
|
z-index: 100;
|
||||||
|
|
||||||
// ── Hide Foundry's default window header ──────────────────────────────────
|
// ── Hide Foundry's default window header ──────────────────────────────────
|
||||||
header.window-header { display: none; }
|
header.window-header { display: none; }
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,9 @@
|
|||||||
background: var(--sp-bg, hsl(220, 15%, 12%));
|
background: var(--sp-bg, hsl(220, 15%, 12%));
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
|
||||||
|
/* Ensure strip appears below Director's Board (z-index: 100) */
|
||||||
|
z-index: 50;
|
||||||
|
|
||||||
// Hide Foundry's default window header — replaced by a lightweight in-content button.
|
// Hide Foundry's default window header — replaced by a lightweight in-content button.
|
||||||
header.window-header { display: none; }
|
header.window-header { display: none; }
|
||||||
|
|
||||||
|
|||||||
+194
-37
@@ -1,53 +1,210 @@
|
|||||||
<form class="scrying-pool-settings-form">
|
<form class="scrying-pool scrying-pool-settings">
|
||||||
<div class="form-group">
|
<div class="scrying-pool-settings__inner">
|
||||||
<h2>{{localize "SCRYING_POOL.Settings.Title"}}</h2>
|
<!-- Drag grip -->
|
||||||
<p class="hint">{{localize "SCRYING_POOL.Settings.Hint"}}</p>
|
<div class="scrying-pool-settings__grip" title="Drag to move">
|
||||||
</div>
|
<i class="fa-solid fa-grip-lines"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<!-- Close button -->
|
||||||
<label>{{localize "SCRYING_POOL.Settings.StripStatus"}}</label>
|
<button type="button" class="scrying-pool-settings__close-btn" data-action="close">
|
||||||
{{#if hasStrip}}
|
<i class="fa-solid fa-times"></i>
|
||||||
<button type="button" data-action="close-strip" class="scrying-pool-btn scrying-pool-btn-close">
|
</button>
|
||||||
<i class="fa-solid fa-eye-slash"></i> {{localize "SCRYING_POOL.Settings.CloseStrip"}}
|
|
||||||
</button>
|
<!-- Header -->
|
||||||
{{else}}
|
<div class="scrying-pool-settings__header">
|
||||||
<button type="button" data-action="reopen-strip" class="scrying-pool-btn scrying-pool-btn-reopen">
|
<h2 class="scrying-pool-settings__title">{{localize "SCRYING_POOL.Settings.Title"}}</h2>
|
||||||
<i class="fa-solid fa-eye"></i> {{localize "SCRYING_POOL.Settings.ReopenStrip"}}
|
<p class="scrying-pool-settings__hint">{{localize "SCRYING_POOL.Settings.Hint"}}</p>
|
||||||
</button>
|
</div>
|
||||||
{{/if}}
|
|
||||||
|
<!-- Content -->
|
||||||
|
<div class="scrying-pool-settings__content">
|
||||||
|
<div class="scrying-pool-settings__status">
|
||||||
|
<label class="scrying-pool-settings__label">{{localize "SCRYING_POOL.Settings.StripStatus"}}</label>
|
||||||
|
{{#if hasStrip}}
|
||||||
|
<button type="button" data-action="close-strip" class="scrying-pool-settings__btn scrying-pool-settings__btn--close">
|
||||||
|
<i class="fa-solid fa-eye-slash"></i> {{localize "SCRYING_POOL.Settings.CloseStrip"}}
|
||||||
|
</button>
|
||||||
|
{{else}}
|
||||||
|
<button type="button" data-action="reopen-strip" class="scrying-pool-settings__btn scrying-pool-settings__btn--reopen">
|
||||||
|
<i class="fa-solid fa-eye"></i> {{localize "SCRYING_POOL.Settings.ReopenStrip"}}
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.scrying-pool-settings-form {
|
/* Match Director's Board styling */
|
||||||
padding: 15px;
|
.scrying-pool-settings {
|
||||||
|
background: linear-gradient(175deg, hsl(220, 18%, 13%) 0%, hsl(220, 15%, 10%) 100%);
|
||||||
|
color: var(--sp-text-primary, #dde2e8);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
|
border-top: 2px solid hsl(200, 55%, 40%);
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.55), 0 2px 8px rgba(0, 0, 0, 0.35),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.04);
|
||||||
|
min-width: 320px;
|
||||||
}
|
}
|
||||||
.scrying-pool-settings-form .form-group {
|
|
||||||
margin-bottom: 15px;
|
/* Hide Foundry's default window header */
|
||||||
|
.scrying-pool-settings header.window-header {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
.scrying-pool-settings-form .hint {
|
|
||||||
color: var(--text-muted);
|
.scrying-pool-settings__inner {
|
||||||
font-size: 0.9em;
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
.scrying-pool-btn {
|
|
||||||
padding: 8px 16px;
|
/* Drag grip */
|
||||||
border: none;
|
.scrying-pool-settings__grip {
|
||||||
border-radius: 4px;
|
width: 100%;
|
||||||
cursor: pointer;
|
height: 18px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: grab;
|
||||||
|
color: var(--sp-text-muted, hsl(0, 0%, 70%));
|
||||||
|
opacity: 0.35;
|
||||||
|
font-size: 10px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
transition: opacity 0.15s, background 0.15s;
|
||||||
|
user-select: none;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrying-pool-settings__grip:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
background: rgba(255, 255, 255, 0.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrying-pool-settings__grip:active {
|
||||||
|
cursor: grabbing;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close button */
|
||||||
|
.scrying-pool-settings__close-btn {
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
right: 6px;
|
||||||
|
z-index: 10;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 20px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
display: inline-flex;
|
font-weight: 400;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--sp-text-muted, hsl(0, 0%, 70%));
|
||||||
|
border: none;
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0.5;
|
||||||
|
transition: opacity 0.15s, background 0.15s, color 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrying-pool-settings__close-btn:hover {
|
||||||
|
opacity: 1;
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
color: var(--sp-text-primary, #dde2e8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrying-pool-settings__close-btn:active {
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
.scrying-pool-settings__header {
|
||||||
|
padding: 12px 16px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrying-pool-settings__title {
|
||||||
|
margin: 0 0 4px 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--sp-text-primary, #dde2e8);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrying-pool-settings__hint {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--sp-text-muted, hsl(0, 0%, 60%));
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Content */
|
||||||
|
.scrying-pool-settings__content {
|
||||||
|
padding: 8px 16px 16px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrying-pool-settings__status {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
.scrying-pool-btn-reopen {
|
|
||||||
background-color: var(--success);
|
.scrying-pool-settings__label {
|
||||||
color: white;
|
font-size: 12px;
|
||||||
|
color: var(--sp-text-muted, hsl(0, 0%, 65%));
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
.scrying-pool-btn-close {
|
|
||||||
background-color: var(--danger);
|
/* Buttons */
|
||||||
color: white;
|
.scrying-pool-settings__btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.15s, opacity 0.15s, transform 0.1s;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 12px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.scrying-pool-btn:hover {
|
|
||||||
opacity: 0.9;
|
.scrying-pool-settings__btn--reopen {
|
||||||
|
background: linear-gradient(175deg, hsl(120, 60%, 30%) 0%, hsl(120, 60%, 25%) 100%);
|
||||||
|
color: #d0f0d0;
|
||||||
|
border: 1px solid rgba(0, 255, 0, 0.3);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(175deg, hsl(120, 60%, 35%) 0%, hsl(120, 60%, 30%) 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrying-pool-settings__btn--close {
|
||||||
|
background: linear-gradient(175deg, hsl(0, 60%, 30%) 0%, hsl(0, 60%, 25%) 100%);
|
||||||
|
color: #f0d0d0;
|
||||||
|
border: 1px solid rgba(255, 0, 0, 0.3);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(175deg, hsl(0, 60%, 35%) 0%, hsl(0, 60%, 30%) 100%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ describe('DirectorsBoard', () => {
|
|||||||
expect(DirectorsBoard.DEFAULT_OPTIONS.position).toEqual({
|
expect(DirectorsBoard.DEFAULT_OPTIONS.position).toEqual({
|
||||||
width: 420,
|
width: 420,
|
||||||
height: 480,
|
height: 480,
|
||||||
|
left: 20,
|
||||||
|
top: 100,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user