Deploy Aether Garden application
Browse files- app.py +117 -58
- ui/book_display.py +10 -8
- ui/styles.css +333 -3
app.py
CHANGED
|
@@ -333,7 +333,12 @@ def filter_entities(location_filter, type_filter, status_filter, search):
|
|
| 333 |
|
| 334 |
|
| 335 |
def filter_book(entry_type, search):
|
| 336 |
-
return render_book_of_ages(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 337 |
|
| 338 |
|
| 339 |
def chat_with_soul(soul_id: str, player_message: str) -> str:
|
|
@@ -557,50 +562,52 @@ def build_app() -> gr.Blocks:
|
|
| 557 |
|
| 558 |
with gr.Tabs(elem_id="tome-spreads", elem_classes=["realm-tabs"]) as tabs:
|
| 559 |
with gr.Tab("The Realm", id="realm"):
|
| 560 |
-
|
| 561 |
-
|
| 562 |
-
|
| 563 |
-
|
| 564 |
-
|
| 565 |
-
|
| 566 |
-
|
| 567 |
-
|
| 568 |
-
|
| 569 |
-
|
| 570 |
-
|
| 571 |
-
|
| 572 |
-
|
| 573 |
-
|
| 574 |
-
|
| 575 |
-
|
| 576 |
-
|
| 577 |
-
|
| 578 |
-
|
| 579 |
-
|
| 580 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 581 |
)
|
| 582 |
-
|
| 583 |
-
|
|
|
|
|
|
|
| 584 |
)
|
| 585 |
-
|
| 586 |
-
|
| 587 |
-
|
| 588 |
-
with gr.Column(scale=2, elem_classes=["sidebar-panel", "tome-page-right"]):
|
| 589 |
-
current_event = gr.HTML(value=render_current_event())
|
| 590 |
-
activity_feed = gr.HTML(value=render_activity_feed())
|
| 591 |
-
with gr.Accordion("⚡ Advance the World Now", open=False):
|
| 592 |
-
gr.HTML('<p style="color:var(--realm-text-tertiary);font-size:0.82rem;margin-bottom:0.6rem;">Manually trigger one simulation tick — the world will generate a new event, run soul encounters, and update memories in real time.</p>')
|
| 593 |
-
live_tick_btn = gr.Button("Run simulation tick →", variant="secondary", size="sm")
|
| 594 |
-
tick_result = gr.HTML()
|
| 595 |
|
| 596 |
location_select = gr.Dropdown(
|
| 597 |
choices=[(l["name"], l["id"]) for l in get_all_locations()],
|
| 598 |
label="Explore Location",
|
| 599 |
-
visible=
|
| 600 |
)
|
| 601 |
|
| 602 |
-
featured_chars = gr.HTML(value=render_featured_characters())
|
| 603 |
-
|
| 604 |
with gr.Tab("Explore the Realm", id="places"):
|
| 605 |
_all_locs = get_all_locations()
|
| 606 |
_default_loc_id = _all_locs[0]["id"] if _all_locs else None
|
|
@@ -645,26 +652,35 @@ def build_app() -> gr.Blocks:
|
|
| 645 |
soul_card = gr.HTML()
|
| 646 |
|
| 647 |
with gr.Tab("Book of Ages", id="book"):
|
| 648 |
-
with gr.
|
| 649 |
-
|
| 650 |
-
|
| 651 |
-
(
|
| 652 |
-
|
| 653 |
-
|
| 654 |
-
|
| 655 |
-
|
| 656 |
-
|
| 657 |
-
|
| 658 |
-
|
| 659 |
-
|
| 660 |
-
|
| 661 |
-
|
| 662 |
-
|
| 663 |
-
|
| 664 |
-
|
| 665 |
-
|
| 666 |
-
|
| 667 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 668 |
|
| 669 |
with gr.Tab("Bonds and Alliances", id="bonds"):
|
| 670 |
gr.HTML(
|
|
@@ -676,6 +692,7 @@ def build_app() -> gr.Blocks:
|
|
| 676 |
rel_graph = gr.HTML(value=render_relationship_graph())
|
| 677 |
|
| 678 |
with gr.Tab("Souls of the Garden", id="entities"):
|
|
|
|
| 679 |
with gr.Row():
|
| 680 |
loc_filter = gr.Dropdown(
|
| 681 |
choices=["all"] + [l["name"] for l in get_all_locations()],
|
|
@@ -962,11 +979,13 @@ def build_app() -> gr.Blocks:
|
|
| 962 |
panels.forEach((panel, i) => {
|
| 963 |
const active = i === panelIndex;
|
| 964 |
panel.style.setProperty('display', active ? 'flex' : 'none', 'important');
|
|
|
|
| 965 |
panel.style.setProperty('height', active ? '565px' : '0', 'important');
|
| 966 |
panel.style.setProperty('max-height', active ? '565px' : '0', 'important');
|
| 967 |
-
panel.style.setProperty('overflow',
|
| 968 |
panel.setAttribute('aria-hidden', active ? 'false' : 'true');
|
| 969 |
});
|
|
|
|
| 970 |
const pad = document.getElementById('aether-walk-pad');
|
| 971 |
if (pad && panelIndex !== 1) {
|
| 972 |
pad.classList.remove('visible', 'explore-only');
|
|
@@ -1149,6 +1168,44 @@ def build_app() -> gr.Blocks:
|
|
| 1149 |
setActivePanel(sections[currentSpread].panel);
|
| 1150 |
};
|
| 1151 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1152 |
const wireOpening = () => {
|
| 1153 |
const gate = document.getElementById('realm-opening');
|
| 1154 |
if (!gate || gate.dataset.bound) return;
|
|
@@ -1258,6 +1315,7 @@ def build_app() -> gr.Blocks:
|
|
| 1258 |
|
| 1259 |
wireOpening();
|
| 1260 |
wireTomeNav();
|
|
|
|
| 1261 |
|
| 1262 |
const bind = () => {
|
| 1263 |
document.querySelectorAll('#world-map [data-location-id]').forEach((node) => {
|
|
@@ -1446,6 +1504,7 @@ def build_app() -> gr.Blocks:
|
|
| 1446 |
wireDioramaFrames();
|
| 1447 |
wireWalkPad();
|
| 1448 |
updateWalkPadVisibility();
|
|
|
|
| 1449 |
}).observe(document.body, { childList: true, subtree: true });
|
| 1450 |
setInterval(updateWalkPadVisibility, 800);
|
| 1451 |
|
|
|
|
| 333 |
|
| 334 |
|
| 335 |
def filter_book(entry_type, search):
|
| 336 |
+
return render_book_of_ages(
|
| 337 |
+
entry_type=entry_type,
|
| 338 |
+
search=search,
|
| 339 |
+
limit=8,
|
| 340 |
+
include_header=False,
|
| 341 |
+
)
|
| 342 |
|
| 343 |
|
| 344 |
def chat_with_soul(soul_id: str, player_message: str) -> str:
|
|
|
|
| 562 |
|
| 563 |
with gr.Tabs(elem_id="tome-spreads", elem_classes=["realm-tabs"]) as tabs:
|
| 564 |
with gr.Tab("The Realm", id="realm"):
|
| 565 |
+
with gr.Column(elem_classes=["tome-spread-shell"]):
|
| 566 |
+
with gr.Row(elem_classes=["tome-spread-row"]):
|
| 567 |
+
with gr.Column(scale=1, elem_classes=["tome-page-left", "tome-printed-page"]):
|
| 568 |
+
world_map = gr.HTML(
|
| 569 |
+
value=render_world_map(),
|
| 570 |
+
elem_id="world-map",
|
| 571 |
+
)
|
| 572 |
+
location_panel = gr.HTML(
|
| 573 |
+
value=render_location_panel(None),
|
| 574 |
+
)
|
| 575 |
+
|
| 576 |
+
with gr.Column(scale=1, elem_classes=["tome-page-right", "tome-printed-page"]):
|
| 577 |
+
current_event = gr.HTML(value=render_current_event())
|
| 578 |
+
activity_feed = gr.HTML(value=render_activity_feed(limit=3))
|
| 579 |
+
|
| 580 |
+
with gr.Column(elem_classes=["tome-offpage-store"]):
|
| 581 |
+
world_vignette = gr.HTML(value=render_world_vignette())
|
| 582 |
+
realm_pulse = gr.HTML(value=render_realm_pulse())
|
| 583 |
+
realm_diorama = gr.HTML(value="")
|
| 584 |
+
map_pick = gr.Textbox(visible=False, elem_id="map_location_pick")
|
| 585 |
+
with gr.Accordion("How this world works", open=False):
|
| 586 |
+
gr.HTML(
|
| 587 |
+
'<div class="how-it-works">'
|
| 588 |
+
'<p><b>1 · You summon.</b> Describe anything below and an AI gives it a name, '
|
| 589 |
+
'a look, goals, fears, and a home among the eight places.</p>'
|
| 590 |
+
'<p><b>2 · The world lives on its own.</b> Every hour, even when no one is here, '
|
| 591 |
+
'the souls wander, meet, form bonds, and the land throws up strange events.</p>'
|
| 592 |
+
'<p><b>3 · Nothing is forgotten.</b> Every arrival, meeting, and event is written '
|
| 593 |
+
'into the Book of Ages forever. Turn the page to <b>Explore</b> or open the '
|
| 594 |
+
'<b>Book of Ages</b> for the full chronicle.</p>'
|
| 595 |
+
'</div>'
|
| 596 |
)
|
| 597 |
+
with gr.Accordion("⚡ Advance the World Now", open=False):
|
| 598 |
+
gr.HTML(
|
| 599 |
+
'<p class="tome-muted">Manually trigger one simulation tick — the world will '
|
| 600 |
+
'generate a new event, run soul encounters, and update memories in real time.</p>'
|
| 601 |
)
|
| 602 |
+
live_tick_btn = gr.Button("Run simulation tick →", variant="secondary", size="sm")
|
| 603 |
+
tick_result = gr.HTML()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 604 |
|
| 605 |
location_select = gr.Dropdown(
|
| 606 |
choices=[(l["name"], l["id"]) for l in get_all_locations()],
|
| 607 |
label="Explore Location",
|
| 608 |
+
visible=False,
|
| 609 |
)
|
| 610 |
|
|
|
|
|
|
|
| 611 |
with gr.Tab("Explore the Realm", id="places"):
|
| 612 |
_all_locs = get_all_locations()
|
| 613 |
_default_loc_id = _all_locs[0]["id"] if _all_locs else None
|
|
|
|
| 652 |
soul_card = gr.HTML()
|
| 653 |
|
| 654 |
with gr.Tab("Book of Ages", id="book"):
|
| 655 |
+
with gr.Column(elem_classes=["tome-spread-shell"]):
|
| 656 |
+
with gr.Row(elem_classes=["tome-spread-row"]):
|
| 657 |
+
with gr.Column(scale=1, elem_classes=["tome-page-left", "tome-printed-page", "tome-book-index"]):
|
| 658 |
+
gr.HTML(
|
| 659 |
+
'<div class="tome-printed-heading">'
|
| 660 |
+
'<h2 class="book-title">Book of Ages</h2>'
|
| 661 |
+
'<p class="book-subtitle">Every creation, encounter, and event — remembered forever</p>'
|
| 662 |
+
'</div>'
|
| 663 |
+
)
|
| 664 |
+
book_filter = gr.Dropdown(
|
| 665 |
+
choices=[
|
| 666 |
+
("All", "all"),
|
| 667 |
+
("Arrivals", "arrival"),
|
| 668 |
+
("Interactions", "interaction"),
|
| 669 |
+
("Events", "world_event"),
|
| 670 |
+
("Milestones", "milestone"),
|
| 671 |
+
("Dreams", "dream_fragment"),
|
| 672 |
+
],
|
| 673 |
+
value="all",
|
| 674 |
+
label="Filter",
|
| 675 |
+
)
|
| 676 |
+
book_search = gr.Textbox(
|
| 677 |
+
placeholder="Search by name...",
|
| 678 |
+
label="Search",
|
| 679 |
+
)
|
| 680 |
+
with gr.Column(scale=1, elem_classes=["tome-page-right", "tome-printed-page"]):
|
| 681 |
+
book_display = gr.HTML(
|
| 682 |
+
value=render_book_of_ages(limit=8, include_header=False)
|
| 683 |
+
)
|
| 684 |
|
| 685 |
with gr.Tab("Bonds and Alliances", id="bonds"):
|
| 686 |
gr.HTML(
|
|
|
|
| 692 |
rel_graph = gr.HTML(value=render_relationship_graph())
|
| 693 |
|
| 694 |
with gr.Tab("Souls of the Garden", id="entities"):
|
| 695 |
+
featured_chars = gr.HTML(value=render_featured_characters())
|
| 696 |
with gr.Row():
|
| 697 |
loc_filter = gr.Dropdown(
|
| 698 |
choices=["all"] + [l["name"] for l in get_all_locations()],
|
|
|
|
| 979 |
panels.forEach((panel, i) => {
|
| 980 |
const active = i === panelIndex;
|
| 981 |
panel.style.setProperty('display', active ? 'flex' : 'none', 'important');
|
| 982 |
+
panel.style.setProperty('flex-direction', 'column', 'important');
|
| 983 |
panel.style.setProperty('height', active ? '565px' : '0', 'important');
|
| 984 |
panel.style.setProperty('max-height', active ? '565px' : '0', 'important');
|
| 985 |
+
panel.style.setProperty('overflow', 'hidden', 'important');
|
| 986 |
panel.setAttribute('aria-hidden', active ? 'false' : 'true');
|
| 987 |
});
|
| 988 |
+
wirePageExpand();
|
| 989 |
const pad = document.getElementById('aether-walk-pad');
|
| 990 |
if (pad && panelIndex !== 1) {
|
| 991 |
pad.classList.remove('visible', 'explore-only');
|
|
|
|
| 1168 |
setActivePanel(sections[currentSpread].panel);
|
| 1169 |
};
|
| 1170 |
|
| 1171 |
+
const wirePageExpand = () => {
|
| 1172 |
+
document.querySelectorAll('.tome-page-left, .tome-page-right').forEach((page) => {
|
| 1173 |
+
if (page.querySelector(':scope > .tome-expand-btn')) return;
|
| 1174 |
+
const side = page.classList.contains('tome-page-left') ? 'left' : 'right';
|
| 1175 |
+
const btn = document.createElement('button');
|
| 1176 |
+
btn.type = 'button';
|
| 1177 |
+
btn.className = 'tome-expand-btn';
|
| 1178 |
+
btn.dataset.expand = side;
|
| 1179 |
+
btn.setAttribute('aria-label', `Expand ${side} page`);
|
| 1180 |
+
btn.title = `Expand ${side} page`;
|
| 1181 |
+
btn.textContent = '⛶';
|
| 1182 |
+
btn.addEventListener('click', (e) => {
|
| 1183 |
+
e.preventDefault();
|
| 1184 |
+
e.stopPropagation();
|
| 1185 |
+
const root = document.querySelector('.gradio-container');
|
| 1186 |
+
if (!root) return;
|
| 1187 |
+
const cls = `tome-expanded-${side}`;
|
| 1188 |
+
const on = root.classList.toggle(cls);
|
| 1189 |
+
root.classList.remove(side === 'left' ? 'tome-expanded-right' : 'tome-expanded-left');
|
| 1190 |
+
if (!on) root.classList.remove(cls);
|
| 1191 |
+
});
|
| 1192 |
+
page.insertBefore(btn, page.firstChild);
|
| 1193 |
+
});
|
| 1194 |
+
|
| 1195 |
+
if (!document.getElementById('tome-expand-backdrop')) {
|
| 1196 |
+
const backdrop = document.createElement('button');
|
| 1197 |
+
backdrop.id = 'tome-expand-backdrop';
|
| 1198 |
+
backdrop.type = 'button';
|
| 1199 |
+
backdrop.className = 'tome-expand-backdrop';
|
| 1200 |
+
backdrop.setAttribute('aria-label', 'Close expanded page');
|
| 1201 |
+
backdrop.addEventListener('click', () => {
|
| 1202 |
+
const root = document.querySelector('.gradio-container');
|
| 1203 |
+
root?.classList.remove('tome-expanded-left', 'tome-expanded-right');
|
| 1204 |
+
});
|
| 1205 |
+
document.body.appendChild(backdrop);
|
| 1206 |
+
}
|
| 1207 |
+
};
|
| 1208 |
+
|
| 1209 |
const wireOpening = () => {
|
| 1210 |
const gate = document.getElementById('realm-opening');
|
| 1211 |
if (!gate || gate.dataset.bound) return;
|
|
|
|
| 1315 |
|
| 1316 |
wireOpening();
|
| 1317 |
wireTomeNav();
|
| 1318 |
+
wirePageExpand();
|
| 1319 |
|
| 1320 |
const bind = () => {
|
| 1321 |
document.querySelectorAll('#world-map [data-location-id]').forEach((node) => {
|
|
|
|
| 1504 |
wireDioramaFrames();
|
| 1505 |
wireWalkPad();
|
| 1506 |
updateWalkPadVisibility();
|
| 1507 |
+
wirePageExpand();
|
| 1508 |
}).observe(document.body, { childList: true, subtree: true });
|
| 1509 |
setInterval(updateWalkPadVisibility, 800);
|
| 1510 |
|
ui/book_display.py
CHANGED
|
@@ -25,6 +25,7 @@ def render_book_of_ages(
|
|
| 25 |
entry_type: str = "all",
|
| 26 |
search: str = "",
|
| 27 |
limit: int = 40,
|
|
|
|
| 28 |
) -> str:
|
| 29 |
entries = get_entries(limit=limit, entry_type=entry_type if entry_type != "all" else None, search=search or None)
|
| 30 |
|
|
@@ -44,14 +45,15 @@ def render_book_of_ages(
|
|
| 44 |
if entry_type == "dream_fragment":
|
| 45 |
subtitle = "Dreams of the Valley — fragments that surfaced while giants slept"
|
| 46 |
|
| 47 |
-
parts = [
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
|
|
|
| 55 |
|
| 56 |
for entry in entries:
|
| 57 |
if entry["world_day"] != current_day:
|
|
|
|
| 25 |
entry_type: str = "all",
|
| 26 |
search: str = "",
|
| 27 |
limit: int = 40,
|
| 28 |
+
include_header: bool = True,
|
| 29 |
) -> str:
|
| 30 |
entries = get_entries(limit=limit, entry_type=entry_type if entry_type != "all" else None, search=search or None)
|
| 31 |
|
|
|
|
| 45 |
if entry_type == "dream_fragment":
|
| 46 |
subtitle = "Dreams of the Valley — fragments that surfaced while giants slept"
|
| 47 |
|
| 48 |
+
parts = ['<div class="book-container">']
|
| 49 |
+
if include_header:
|
| 50 |
+
parts.extend([
|
| 51 |
+
'<div class="book-header">',
|
| 52 |
+
'<h2 class="book-title">Book of Ages</h2>',
|
| 53 |
+
f'<p class="book-subtitle">{subtitle}</p>',
|
| 54 |
+
"</div>",
|
| 55 |
+
])
|
| 56 |
+
parts.append('<div class="book-entries">')
|
| 57 |
|
| 58 |
for entry in entries:
|
| 59 |
if entry["world_day"] != current_day:
|
ui/styles.css
CHANGED
|
@@ -2937,8 +2937,10 @@ body,
|
|
| 2937 |
height: 565px !important;
|
| 2938 |
max-height: 565px !important;
|
| 2939 |
min-height: 0 !important;
|
| 2940 |
-
overflow:
|
| 2941 |
-
padding: 0.
|
|
|
|
|
|
|
| 2942 |
}
|
| 2943 |
|
| 2944 |
.realm-tabs [role="tabpanel"] > .column,
|
|
@@ -3138,7 +3140,7 @@ body,
|
|
| 3138 |
.realm-tabs [role="tabpanel"] {
|
| 3139 |
height: 565px !important;
|
| 3140 |
max-height: 565px !important;
|
| 3141 |
-
overflow:
|
| 3142 |
}
|
| 3143 |
|
| 3144 |
.realm-opening-inner {
|
|
@@ -3639,3 +3641,331 @@ body,
|
|
| 3639 |
border-radius: 10px;
|
| 3640 |
overflow: hidden;
|
| 3641 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2937 |
height: 565px !important;
|
| 2938 |
max-height: 565px !important;
|
| 2939 |
min-height: 0 !important;
|
| 2940 |
+
overflow: hidden !important;
|
| 2941 |
+
padding: 0.5rem 0.85rem 0.75rem !important;
|
| 2942 |
+
display: flex !important;
|
| 2943 |
+
flex-direction: column !important;
|
| 2944 |
}
|
| 2945 |
|
| 2946 |
.realm-tabs [role="tabpanel"] > .column,
|
|
|
|
| 3140 |
.realm-tabs [role="tabpanel"] {
|
| 3141 |
height: 565px !important;
|
| 3142 |
max-height: 565px !important;
|
| 3143 |
+
overflow: hidden !important;
|
| 3144 |
}
|
| 3145 |
|
| 3146 |
.realm-opening-inner {
|
|
|
|
| 3641 |
border-radius: 10px;
|
| 3642 |
overflow: hidden;
|
| 3643 |
}
|
| 3644 |
+
|
| 3645 |
+
/* -------------------------------------------------------------------------- */
|
| 3646 |
+
/* Living book spread — no scroll, printed pages, expand option */
|
| 3647 |
+
/* -------------------------------------------------------------------------- */
|
| 3648 |
+
.tome-offpage-store {
|
| 3649 |
+
display: none !important;
|
| 3650 |
+
height: 0 !important;
|
| 3651 |
+
max-height: 0 !important;
|
| 3652 |
+
overflow: hidden !important;
|
| 3653 |
+
visibility: hidden !important;
|
| 3654 |
+
pointer-events: none !important;
|
| 3655 |
+
margin: 0 !important;
|
| 3656 |
+
padding: 0 !important;
|
| 3657 |
+
}
|
| 3658 |
+
|
| 3659 |
+
.tome-spread-shell {
|
| 3660 |
+
flex: 1 1 auto;
|
| 3661 |
+
min-height: 0;
|
| 3662 |
+
display: flex;
|
| 3663 |
+
flex-direction: column;
|
| 3664 |
+
overflow: hidden;
|
| 3665 |
+
}
|
| 3666 |
+
|
| 3667 |
+
.tome-spread-row {
|
| 3668 |
+
flex: 1 1 auto;
|
| 3669 |
+
min-height: 0 !important;
|
| 3670 |
+
max-height: 100% !important;
|
| 3671 |
+
align-items: stretch !important;
|
| 3672 |
+
overflow: hidden !important;
|
| 3673 |
+
gap: 0 !important;
|
| 3674 |
+
margin: 0 !important;
|
| 3675 |
+
}
|
| 3676 |
+
|
| 3677 |
+
.tome-spread-row > .column,
|
| 3678 |
+
.tome-spread-row > .gr-column {
|
| 3679 |
+
min-height: 0 !important;
|
| 3680 |
+
max-height: 100% !important;
|
| 3681 |
+
overflow: hidden !important;
|
| 3682 |
+
}
|
| 3683 |
+
|
| 3684 |
+
.tome-printed-page {
|
| 3685 |
+
position: relative;
|
| 3686 |
+
display: flex !important;
|
| 3687 |
+
flex-direction: column !important;
|
| 3688 |
+
min-height: 0 !important;
|
| 3689 |
+
max-height: 100% !important;
|
| 3690 |
+
overflow: hidden !important;
|
| 3691 |
+
padding: 0.85rem 1.15rem 0.75rem !important;
|
| 3692 |
+
background:
|
| 3693 |
+
radial-gradient(ellipse 110px 85px at 94% 90%, rgba(72, 44, 18, 0.14) 0%, transparent 64%),
|
| 3694 |
+
radial-gradient(ellipse 95px 75px at 6% 12%, rgba(58, 34, 14, 0.1) 0%, transparent 58%),
|
| 3695 |
+
radial-gradient(ellipse 80px 60px at 88% 8%, rgba(54, 32, 12, 0.08) 0%, transparent 55%),
|
| 3696 |
+
radial-gradient(circle at 5% 38%, rgba(88, 62, 32, 0.09) 0 2px, transparent 3px),
|
| 3697 |
+
radial-gradient(circle at 94% 62%, rgba(78, 54, 28, 0.08) 0 2px, transparent 3px),
|
| 3698 |
+
linear-gradient(168deg, #ebe0c4 0%, #e0d0aa 45%, #d4c094 100%);
|
| 3699 |
+
box-shadow: inset 0 0 28px rgba(88, 56, 24, 0.08);
|
| 3700 |
+
isolation: isolate;
|
| 3701 |
+
}
|
| 3702 |
+
|
| 3703 |
+
.tome-printed-page::before {
|
| 3704 |
+
content: "";
|
| 3705 |
+
position: absolute;
|
| 3706 |
+
inset: 0;
|
| 3707 |
+
pointer-events: none;
|
| 3708 |
+
z-index: 0;
|
| 3709 |
+
opacity: 0.4;
|
| 3710 |
+
background:
|
| 3711 |
+
repeating-linear-gradient(
|
| 3712 |
+
0deg,
|
| 3713 |
+
transparent,
|
| 3714 |
+
transparent 2px,
|
| 3715 |
+
rgba(62, 40, 18, 0.02) 2px,
|
| 3716 |
+
rgba(62, 40, 18, 0.02) 3px
|
| 3717 |
+
),
|
| 3718 |
+
radial-gradient(ellipse 100% 90% at 50% 50%, transparent 58%, rgba(48, 30, 14, 0.08) 100%);
|
| 3719 |
+
mix-blend-mode: multiply;
|
| 3720 |
+
}
|
| 3721 |
+
|
| 3722 |
+
.tome-printed-page > * {
|
| 3723 |
+
position: relative;
|
| 3724 |
+
z-index: 1;
|
| 3725 |
+
min-height: 0;
|
| 3726 |
+
}
|
| 3727 |
+
|
| 3728 |
+
.tome-page-left {
|
| 3729 |
+
padding-right: 2.4rem !important;
|
| 3730 |
+
padding-left: 0.5rem !important;
|
| 3731 |
+
border-right: 1px solid rgba(98, 62, 28, 0.12);
|
| 3732 |
+
}
|
| 3733 |
+
|
| 3734 |
+
.tome-page-right {
|
| 3735 |
+
padding-left: 2.4rem !important;
|
| 3736 |
+
padding-right: 0.5rem !important;
|
| 3737 |
+
}
|
| 3738 |
+
|
| 3739 |
+
.tome-expand-btn {
|
| 3740 |
+
position: absolute;
|
| 3741 |
+
top: 0.35rem;
|
| 3742 |
+
right: 0.4rem;
|
| 3743 |
+
z-index: 6;
|
| 3744 |
+
width: 1.65rem;
|
| 3745 |
+
height: 1.65rem;
|
| 3746 |
+
border: 1px solid rgba(98, 62, 28, 0.35);
|
| 3747 |
+
border-radius: 6px;
|
| 3748 |
+
background: rgba(248, 239, 216, 0.72);
|
| 3749 |
+
color: #5c4228;
|
| 3750 |
+
font-size: 0.72rem;
|
| 3751 |
+
line-height: 1;
|
| 3752 |
+
cursor: pointer;
|
| 3753 |
+
opacity: 0.55;
|
| 3754 |
+
transition: opacity 0.2s ease, background 0.2s ease;
|
| 3755 |
+
}
|
| 3756 |
+
|
| 3757 |
+
.tome-page-right .tome-expand-btn {
|
| 3758 |
+
right: auto;
|
| 3759 |
+
left: 0.4rem;
|
| 3760 |
+
}
|
| 3761 |
+
|
| 3762 |
+
.tome-printed-page:hover .tome-expand-btn {
|
| 3763 |
+
opacity: 1;
|
| 3764 |
+
}
|
| 3765 |
+
|
| 3766 |
+
.tome-expand-btn:hover {
|
| 3767 |
+
background: rgba(240, 214, 150, 0.9);
|
| 3768 |
+
}
|
| 3769 |
+
|
| 3770 |
+
.tome-expand-backdrop {
|
| 3771 |
+
display: none;
|
| 3772 |
+
position: fixed;
|
| 3773 |
+
inset: 0;
|
| 3774 |
+
z-index: 2190;
|
| 3775 |
+
border: 0;
|
| 3776 |
+
background: rgba(8, 5, 3, 0.62);
|
| 3777 |
+
cursor: pointer;
|
| 3778 |
+
}
|
| 3779 |
+
|
| 3780 |
+
.gradio-container.tome-expanded-left .tome-expand-backdrop,
|
| 3781 |
+
.gradio-container.tome-expanded-right .tome-expand-backdrop {
|
| 3782 |
+
display: block;
|
| 3783 |
+
}
|
| 3784 |
+
|
| 3785 |
+
.gradio-container.tome-expanded-left .tome-page-left,
|
| 3786 |
+
.gradio-container.tome-expanded-right .tome-page-right {
|
| 3787 |
+
position: fixed !important;
|
| 3788 |
+
z-index: 2200 !important;
|
| 3789 |
+
top: 50% !important;
|
| 3790 |
+
left: 50% !important;
|
| 3791 |
+
transform: translate(-50%, -50%) !important;
|
| 3792 |
+
width: min(920px, 92vw) !important;
|
| 3793 |
+
max-width: 92vw !important;
|
| 3794 |
+
height: min(82vh, 680px) !important;
|
| 3795 |
+
max-height: 82vh !important;
|
| 3796 |
+
overflow: auto !important;
|
| 3797 |
+
padding: 1.5rem 1.75rem !important;
|
| 3798 |
+
border: 1px solid rgba(98, 62, 28, 0.45) !important;
|
| 3799 |
+
box-shadow: 0 28px 80px rgba(8, 4, 2, 0.55) !important;
|
| 3800 |
+
}
|
| 3801 |
+
|
| 3802 |
+
.gradio-container.tome-expanded-left .tome-page-right,
|
| 3803 |
+
.gradio-container.tome-expanded-right .tome-page-left {
|
| 3804 |
+
opacity: 0.12;
|
| 3805 |
+
pointer-events: none;
|
| 3806 |
+
}
|
| 3807 |
+
|
| 3808 |
+
/* Printed ink — content sits on paper, not in UI cards */
|
| 3809 |
+
.tome-printed-page .current-event,
|
| 3810 |
+
.tome-printed-page .activity-feed,
|
| 3811 |
+
.tome-printed-page .location-panel,
|
| 3812 |
+
.tome-printed-page .book-container,
|
| 3813 |
+
.tome-printed-page .book-entries {
|
| 3814 |
+
background: transparent !important;
|
| 3815 |
+
box-shadow: none !important;
|
| 3816 |
+
border: none !important;
|
| 3817 |
+
border-radius: 0 !important;
|
| 3818 |
+
}
|
| 3819 |
+
|
| 3820 |
+
.tome-printed-page .current-event {
|
| 3821 |
+
padding: 0 0 0.65rem !important;
|
| 3822 |
+
margin: 0 0 0.5rem !important;
|
| 3823 |
+
border-bottom: 1px solid rgba(98, 62, 28, 0.22) !important;
|
| 3824 |
+
}
|
| 3825 |
+
|
| 3826 |
+
.tome-printed-page .event-label,
|
| 3827 |
+
.tome-printed-page .event-title,
|
| 3828 |
+
.tome-printed-page .event-text,
|
| 3829 |
+
.tome-printed-page .event-locations {
|
| 3830 |
+
color: #3d2a16 !important;
|
| 3831 |
+
text-shadow: 0 1px 0 rgba(255, 236, 196, 0.2);
|
| 3832 |
+
}
|
| 3833 |
+
|
| 3834 |
+
.tome-printed-page .event-label {
|
| 3835 |
+
color: #7a5a28 !important;
|
| 3836 |
+
font-family: 'IM Fell English', serif !important;
|
| 3837 |
+
}
|
| 3838 |
+
|
| 3839 |
+
.tome-printed-page .activity-feed {
|
| 3840 |
+
padding: 0 !important;
|
| 3841 |
+
margin: 0 !important;
|
| 3842 |
+
overflow: hidden !important;
|
| 3843 |
+
}
|
| 3844 |
+
|
| 3845 |
+
.tome-printed-page .feed-item {
|
| 3846 |
+
padding: 0.4rem 0 !important;
|
| 3847 |
+
border-bottom: 1px solid rgba(98, 62, 28, 0.16) !important;
|
| 3848 |
+
background: transparent !important;
|
| 3849 |
+
}
|
| 3850 |
+
|
| 3851 |
+
.tome-printed-page .feed-content {
|
| 3852 |
+
color: #3d2a16 !important;
|
| 3853 |
+
font-family: 'IM Fell English', serif !important;
|
| 3854 |
+
font-size: 0.88rem !important;
|
| 3855 |
+
line-height: 1.45 !important;
|
| 3856 |
+
display: -webkit-box;
|
| 3857 |
+
-webkit-line-clamp: 2;
|
| 3858 |
+
-webkit-box-orient: vertical;
|
| 3859 |
+
overflow: hidden;
|
| 3860 |
+
}
|
| 3861 |
+
|
| 3862 |
+
.tome-printed-page .feed-day {
|
| 3863 |
+
color: #8a6424 !important;
|
| 3864 |
+
font-family: 'Cinzel', serif !important;
|
| 3865 |
+
}
|
| 3866 |
+
|
| 3867 |
+
.tome-printed-page #world-map,
|
| 3868 |
+
.tome-printed-page .realm-map {
|
| 3869 |
+
flex: 1 1 auto;
|
| 3870 |
+
min-height: 0;
|
| 3871 |
+
max-height: 360px;
|
| 3872 |
+
width: 100% !important;
|
| 3873 |
+
border: 1px solid rgba(98, 62, 28, 0.28) !important;
|
| 3874 |
+
border-radius: 2px !important;
|
| 3875 |
+
box-shadow: inset 0 0 18px rgba(58, 36, 14, 0.12) !important;
|
| 3876 |
+
background: rgba(12, 18, 14, 0.92) !important;
|
| 3877 |
+
}
|
| 3878 |
+
|
| 3879 |
+
.tome-printed-page .location-panel {
|
| 3880 |
+
padding: 0.45rem 0 0 !important;
|
| 3881 |
+
margin: 0 !important;
|
| 3882 |
+
font-family: 'IM Fell English', serif !important;
|
| 3883 |
+
font-style: italic;
|
| 3884 |
+
font-size: 0.82rem !important;
|
| 3885 |
+
color: #5c4228 !important;
|
| 3886 |
+
}
|
| 3887 |
+
|
| 3888 |
+
.tome-printed-page .location-panel * {
|
| 3889 |
+
color: #5c4228 !important;
|
| 3890 |
+
}
|
| 3891 |
+
|
| 3892 |
+
.tome-book-index .tome-printed-heading {
|
| 3893 |
+
margin-bottom: 0.75rem;
|
| 3894 |
+
padding-bottom: 0.65rem;
|
| 3895 |
+
border-bottom: 1px solid rgba(98, 62, 28, 0.22);
|
| 3896 |
+
}
|
| 3897 |
+
|
| 3898 |
+
.tome-book-index .book-title {
|
| 3899 |
+
margin: 0 0 0.35rem;
|
| 3900 |
+
font-size: 1.35rem !important;
|
| 3901 |
+
color: #7a5a28 !important;
|
| 3902 |
+
}
|
| 3903 |
+
|
| 3904 |
+
.tome-book-index .book-subtitle {
|
| 3905 |
+
margin: 0;
|
| 3906 |
+
font-family: 'IM Fell English', serif;
|
| 3907 |
+
font-style: italic;
|
| 3908 |
+
font-size: 0.88rem;
|
| 3909 |
+
color: #5c4228;
|
| 3910 |
+
}
|
| 3911 |
+
|
| 3912 |
+
.tome-printed-page .book-entries {
|
| 3913 |
+
column-count: 1 !important;
|
| 3914 |
+
column-gap: 0 !important;
|
| 3915 |
+
overflow: hidden !important;
|
| 3916 |
+
max-height: 100%;
|
| 3917 |
+
}
|
| 3918 |
+
|
| 3919 |
+
.tome-printed-page .book-entry {
|
| 3920 |
+
break-inside: avoid;
|
| 3921 |
+
margin-bottom: 0.55rem !important;
|
| 3922 |
+
padding-bottom: 0.45rem !important;
|
| 3923 |
+
border-bottom: 1px solid rgba(98, 62, 28, 0.14) !important;
|
| 3924 |
+
background: transparent !important;
|
| 3925 |
+
}
|
| 3926 |
+
|
| 3927 |
+
.tome-printed-page .entry-content {
|
| 3928 |
+
font-family: 'IM Fell English', serif !important;
|
| 3929 |
+
font-size: 0.86rem !important;
|
| 3930 |
+
line-height: 1.45 !important;
|
| 3931 |
+
display: -webkit-box;
|
| 3932 |
+
-webkit-line-clamp: 3;
|
| 3933 |
+
-webkit-box-orient: vertical;
|
| 3934 |
+
overflow: hidden;
|
| 3935 |
+
}
|
| 3936 |
+
|
| 3937 |
+
.tome-printed-page .book-day-header {
|
| 3938 |
+
font-family: 'Cinzel', serif !important;
|
| 3939 |
+
color: #8a6424 !important;
|
| 3940 |
+
margin: 0.35rem 0 !important;
|
| 3941 |
+
}
|
| 3942 |
+
|
| 3943 |
+
/* Aged spread binding — worn parchment across both pages */
|
| 3944 |
+
.realm-tabs [role="tabpanel"] {
|
| 3945 |
+
background:
|
| 3946 |
+
radial-gradient(ellipse 130px 100px at 3% 92%, rgba(72, 44, 18, 0.1) 0%, transparent 62%),
|
| 3947 |
+
radial-gradient(ellipse 120px 95px at 97% 8%, rgba(58, 34, 14, 0.09) 0%, transparent 60%),
|
| 3948 |
+
linear-gradient(90deg,
|
| 3949 |
+
#e8d8b4 0%,
|
| 3950 |
+
#e2d0a6 44.5%,
|
| 3951 |
+
#c9a87a 48.8%,
|
| 3952 |
+
#8e6840 49.8%,
|
| 3953 |
+
#6b4a2c 50%,
|
| 3954 |
+
#8e6840 50.2%,
|
| 3955 |
+
#c9a87a 51.2%,
|
| 3956 |
+
#e2d0a6 55.5%,
|
| 3957 |
+
#ebe2c6 100%) !important;
|
| 3958 |
+
}
|
| 3959 |
+
|
| 3960 |
+
.realm-tabs [role="tabpanel"]::-webkit-scrollbar {
|
| 3961 |
+
display: none !important;
|
| 3962 |
+
width: 0 !important;
|
| 3963 |
+
height: 0 !important;
|
| 3964 |
+
}
|
| 3965 |
+
|
| 3966 |
+
.tome-muted {
|
| 3967 |
+
font-family: 'IM Fell English', serif;
|
| 3968 |
+
font-style: italic;
|
| 3969 |
+
font-size: 0.82rem;
|
| 3970 |
+
color: #5c4228;
|
| 3971 |
+
}
|