Redesign Story Intelligence Review Centre as tile grid
This commit is contained in:
parent
730537daee
commit
dd4b0badb6
@ -233,6 +233,7 @@ var tests = new (string Name, Action Test)[]
|
|||||||
("Story Intelligence Review Centre route replaces linear review resume", StoryIntelligenceReviewCentreRouteReplacesLinearReviewResume),
|
("Story Intelligence Review Centre route replaces linear review resume", StoryIntelligenceReviewCentreRouteReplacesLinearReviewResume),
|
||||||
("Story Intelligence obsolete create scene workflow is removed", StoryIntelligenceObsoleteCreateSceneWorkflowIsRemoved),
|
("Story Intelligence obsolete create scene workflow is removed", StoryIntelligenceObsoleteCreateSceneWorkflowIsRemoved),
|
||||||
("Story Intelligence Review Centre counts only needs-attention categories", StoryIntelligenceReviewCentreCountsOnlyNeedsAttentionCategories),
|
("Story Intelligence Review Centre counts only needs-attention categories", StoryIntelligenceReviewCentreCountsOnlyNeedsAttentionCategories),
|
||||||
|
("Story Intelligence Review Centre uses independent tile grid", StoryIntelligenceReviewCentreUsesIndependentTileGrid),
|
||||||
("Story Intelligence Review Centre opens with character gate", StoryIntelligenceReviewCentreOpensWithCharacterGate),
|
("Story Intelligence Review Centre opens with character gate", StoryIntelligenceReviewCentreOpensWithCharacterGate),
|
||||||
("Story Intelligence review modules are independent after character gate", StoryIntelligenceReviewModulesAreIndependentAfterCharacterGate),
|
("Story Intelligence review modules are independent after character gate", StoryIntelligenceReviewModulesAreIndependentAfterCharacterGate),
|
||||||
("Story Intelligence downstream review uses completed scene analysis", StoryIntelligenceDownstreamReviewUsesCompletedSceneAnalysis),
|
("Story Intelligence downstream review uses completed scene analysis", StoryIntelligenceDownstreamReviewUsesCompletedSceneAnalysis),
|
||||||
@ -665,6 +666,51 @@ static void StoryIntelligenceReviewCentreCountsOnlyNeedsAttentionCategories()
|
|||||||
Assert(!summary.Contains("Locations identified", StringComparison.Ordinal), "Summary should not present total identified rows as review workload.");
|
Assert(!summary.Contains("Locations identified", StringComparison.Ordinal), "Summary should not present total identified rows as review workload.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void StoryIntelligenceReviewCentreUsesIndependentTileGrid()
|
||||||
|
{
|
||||||
|
var root = PlotLineRoot();
|
||||||
|
var centre = File.ReadAllText(Path.Combine(root, "Views/Onboarding/StoryIntelligenceReviewCentre.cshtml"));
|
||||||
|
var css = File.ReadAllText(Path.Combine(root, "wwwroot/css/onboarding.css"));
|
||||||
|
var tileOrder = new[]
|
||||||
|
{
|
||||||
|
"\"Characters\"",
|
||||||
|
"\"Assets\"",
|
||||||
|
"\"Knowledge\"",
|
||||||
|
"\"Locations\"",
|
||||||
|
"\"Plot Lines & Threads\"",
|
||||||
|
"\"Relationships\"",
|
||||||
|
"ReviewMetrics"
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert(!centre.Contains("_StoryIntelligencePipelineHeader", StringComparison.Ordinal), "Review Centre should not render wizard progress header.");
|
||||||
|
Assert(!centre.Contains("_StoryIntelligencePipelineSummary", StringComparison.Ordinal), "Review Centre should not render separate summary statistics.");
|
||||||
|
Assert(!centre.Contains("story-review-centre-list", StringComparison.Ordinal), "Review Centre should no longer use the sequential row list.");
|
||||||
|
Assert(centre.Contains("story-review-centre-grid", StringComparison.Ordinal), "Review Centre should render a category tile grid.");
|
||||||
|
Assert(centre.Contains("story-review-centre-tile--primary", StringComparison.Ordinal), "Characters tile should have subtle first-action emphasis.");
|
||||||
|
Assert(centre.Contains("Resolve Characters first.", StringComparison.Ordinal), "Header should explain character-first gating compactly.");
|
||||||
|
Assert(centre.Contains("can be reviewed in any order", StringComparison.Ordinal), "Header should communicate independent review order.");
|
||||||
|
Assert(centre.Contains("Locked until Characters are resolved", StringComparison.Ordinal), "Locked dependent tiles should be visible and clearly locked.");
|
||||||
|
Assert(centre.Contains(">Locked</span>", StringComparison.Ordinal), "Locked tile action should render as non-clickable text.");
|
||||||
|
Assert(centre.Contains("Available", StringComparison.Ordinal) && centre.Contains("View Metrics", StringComparison.Ordinal), "Scene Metrics should be available, not a mandatory review workload.");
|
||||||
|
Assert(!centre.Contains("Next", StringComparison.Ordinal) && !centre.Contains("Previous", StringComparison.Ordinal), "Review Centre should not contain wizard navigation.");
|
||||||
|
Assert(!centre.Contains("Core Import", StringComparison.Ordinal) && !centre.Contains("Analyse Manuscript", StringComparison.Ordinal), "Review Centre should not show phase panels.");
|
||||||
|
|
||||||
|
var lastIndex = -1;
|
||||||
|
foreach (var marker in tileOrder)
|
||||||
|
{
|
||||||
|
var index = centre.IndexOf(marker, StringComparison.Ordinal);
|
||||||
|
Assert(index > lastIndex, $"{marker} should appear in the expected tile order.");
|
||||||
|
lastIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert(css.Contains(".story-review-centre-grid", StringComparison.Ordinal), "Review Centre grid CSS should exist.");
|
||||||
|
Assert(css.Contains("grid-template-columns: repeat(3, minmax(0, 1fr))", StringComparison.Ordinal), "Desktop Review Centre should use three columns.");
|
||||||
|
Assert(css.Contains("@media (max-width: 980px)", StringComparison.Ordinal)
|
||||||
|
&& css.Contains("grid-template-columns: repeat(2, minmax(0, 1fr))", StringComparison.Ordinal), "Tablet Review Centre should use two columns.");
|
||||||
|
Assert(css.Contains("@media (max-width: 720px)", StringComparison.Ordinal)
|
||||||
|
&& css.Contains(".story-review-centre-grid {\n grid-template-columns: 1fr;", StringComparison.Ordinal), "Mobile Review Centre should use one column.");
|
||||||
|
}
|
||||||
|
|
||||||
static void StoryIntelligenceReviewCentreOpensWithCharacterGate()
|
static void StoryIntelligenceReviewCentreOpensWithCharacterGate()
|
||||||
{
|
{
|
||||||
var root = PlotLineRoot();
|
var root = PlotLineRoot();
|
||||||
|
|||||||
@ -3,14 +3,14 @@
|
|||||||
ViewData["Title"] = "Story Intelligence Review Centre";
|
ViewData["Title"] = "Story Intelligence Review Centre";
|
||||||
}
|
}
|
||||||
|
|
||||||
<section class="onboarding-shell" aria-labelledby="story-review-centre-title">
|
<section class="story-review-centre-shell" aria-labelledby="story-review-centre-title">
|
||||||
<div class="onboarding-panel onboarding-review-panel story-review-page">
|
<div class="story-review-centre-workspace">
|
||||||
<partial name="_StoryIntelligencePipelineHeader" model="@(new StoryIntelligencePipelineHeaderViewModel { CurrentStage = "Review Centre" })" />
|
<div class="story-review-centre-heading">
|
||||||
|
|
||||||
<div class="onboarding-copy story-review-heading">
|
|
||||||
<p class="eyebrow">Story Intelligence</p>
|
<p class="eyebrow">Story Intelligence</p>
|
||||||
<h1 id="story-review-centre-title">Review Centre</h1>
|
<h1 id="story-review-centre-title">Review Centre</h1>
|
||||||
<p>Your manuscript analysis is complete. Review only the story intelligence that needs an author decision; everything here is saved and can be picked up later.</p>
|
<p>@(Model.CharacterGateSatisfied
|
||||||
|
? "Your manuscript analysis is complete. Choose any category to inspect or review."
|
||||||
|
: "Resolve Characters first. Once character identities are confirmed, the remaining Story Intelligence categories can be reviewed in any order.")</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (TempData["OnboardingStoryIntelligenceError"] is string error)
|
@if (TempData["OnboardingStoryIntelligenceError"] is string error)
|
||||||
@ -22,138 +22,169 @@
|
|||||||
<div class="alert alert-success">@message</div>
|
<div class="alert alert-success">@message</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<partial name="_StoryIntelligencePipelineSummary" model="Model.PipelineDashboard" />
|
<section class="story-review-centre-grid" aria-label="Story Intelligence review categories">
|
||||||
|
|
||||||
<section class="story-review-centre-list" aria-label="Story Intelligence review categories">
|
|
||||||
@ReviewModule(
|
@ReviewModule(
|
||||||
"Characters",
|
"Characters",
|
||||||
Model.CharacterNeedsAttentionCount,
|
Model.CharacterNeedsAttentionCount,
|
||||||
Model.CharacterGateSatisfied ? "Resolved" : "Needs attention",
|
Model.CharacterGateSatisfied,
|
||||||
"Resolve identity questions before reviewing dependent story intelligence.",
|
false,
|
||||||
"Resolve Characters",
|
"Resolve character identities before reviewing dependent Story Intelligence.",
|
||||||
|
Model.CharacterGateSatisfied ? "Review Characters" : "Resolve Characters",
|
||||||
"StoryIntelligenceCharacters",
|
"StoryIntelligenceCharacters",
|
||||||
false)
|
true)
|
||||||
|
|
||||||
@ReviewModule(
|
|
||||||
"Locations",
|
|
||||||
Model.LocationNeedsAttentionCount,
|
|
||||||
Model.PipelineDashboard.LocationStageComplete ? "Reviewed" : AttentionLabel(Model.LocationNeedsAttentionCount),
|
|
||||||
"Places found in the manuscript that may be worth creating, linking, or ignoring.",
|
|
||||||
"Review locations",
|
|
||||||
"StoryIntelligenceLocations",
|
|
||||||
!Model.CharacterGateSatisfied)
|
|
||||||
|
|
||||||
@ReviewModule(
|
@ReviewModule(
|
||||||
"Assets",
|
"Assets",
|
||||||
Model.AssetNeedsAttentionCount,
|
Model.AssetNeedsAttentionCount,
|
||||||
Model.PipelineDashboard.AssetStageComplete ? "Reviewed" : AttentionLabel(Model.AssetNeedsAttentionCount),
|
Model.PipelineDashboard.AssetStageComplete,
|
||||||
"Important objects and possessions detected from generic evidence such as recurrence, ownership, and scene prominence.",
|
!Model.CharacterGateSatisfied,
|
||||||
"Review assets",
|
"Important objects and possessions found in the manuscript.",
|
||||||
"StoryIntelligenceAssets",
|
ModuleAction("Assets", Model.AssetNeedsAttentionCount, Model.PipelineDashboard.AssetStageComplete),
|
||||||
!Model.CharacterGateSatisfied)
|
"StoryIntelligenceAssets")
|
||||||
|
|
||||||
@ReviewModule(
|
|
||||||
"Relationships",
|
|
||||||
Model.RelationshipNeedsAttentionCount,
|
|
||||||
Model.PipelineDashboard.RelationshipStageComplete ? "Reviewed" : AttentionLabel(Model.RelationshipNeedsAttentionCount),
|
|
||||||
"Relationship candidates grouped by the canonical character identities involved.",
|
|
||||||
"Review relationships",
|
|
||||||
"StoryIntelligenceRelationships",
|
|
||||||
!Model.CharacterGateSatisfied)
|
|
||||||
|
|
||||||
@ReviewModule(
|
@ReviewModule(
|
||||||
"Knowledge",
|
"Knowledge",
|
||||||
Model.KnowledgeNeedsAttentionCount,
|
Model.KnowledgeNeedsAttentionCount,
|
||||||
Model.PipelineDashboard.KnowledgeStageComplete ? "Reviewed" : AttentionLabel(Model.KnowledgeNeedsAttentionCount),
|
Model.PipelineDashboard.KnowledgeStageComplete,
|
||||||
"Facts, discoveries, beliefs, and suspicions that need a create, link, merge, or ignore decision.",
|
!Model.CharacterGateSatisfied,
|
||||||
"Review knowledge",
|
"Facts, discoveries, beliefs, and suspicions found in the manuscript.",
|
||||||
"StoryIntelligenceKnowledge",
|
ModuleAction("Knowledge", Model.KnowledgeNeedsAttentionCount, Model.PipelineDashboard.KnowledgeStageComplete),
|
||||||
!Model.CharacterGateSatisfied)
|
"StoryIntelligenceKnowledge")
|
||||||
|
|
||||||
|
@ReviewModule(
|
||||||
|
"Locations",
|
||||||
|
Model.LocationNeedsAttentionCount,
|
||||||
|
Model.PipelineDashboard.LocationStageComplete,
|
||||||
|
!Model.CharacterGateSatisfied,
|
||||||
|
"Places found in the manuscript.",
|
||||||
|
ModuleAction("Locations", Model.LocationNeedsAttentionCount, Model.PipelineDashboard.LocationStageComplete),
|
||||||
|
"StoryIntelligenceLocations")
|
||||||
|
|
||||||
@ReviewModule(
|
@ReviewModule(
|
||||||
"Plot Lines & Threads",
|
"Plot Lines & Threads",
|
||||||
Model.NarrativeNeedsAttentionCount,
|
Model.NarrativeNeedsAttentionCount,
|
||||||
Model.PipelineDashboard.NarrativeStageComplete ? "Reviewed" : AttentionLabel(Model.NarrativeNeedsAttentionCount),
|
Model.PipelineDashboard.NarrativeStageComplete,
|
||||||
"Recurring arcs and threads organised by the narrative hierarchy discovered from scene evidence.",
|
!Model.CharacterGateSatisfied,
|
||||||
"Review plot lines",
|
"Recurring arcs and threads discovered from scene evidence.",
|
||||||
"StoryIntelligenceNarrative",
|
ModuleAction("Plot Lines & Threads", Model.NarrativeNeedsAttentionCount, Model.PipelineDashboard.NarrativeStageComplete),
|
||||||
!Model.CharacterGateSatisfied)
|
"StoryIntelligenceNarrative")
|
||||||
|
|
||||||
<article class="story-review-centre-row">
|
@ReviewModule(
|
||||||
<div>
|
"Relationships",
|
||||||
<h2>Scene Metrics</h2>
|
Model.RelationshipNeedsAttentionCount,
|
||||||
<p>Available from the imported scene analysis. Metrics are auto-applied where configured and do not require a mandatory review step.</p>
|
Model.PipelineDashboard.RelationshipStageComplete,
|
||||||
</div>
|
!Model.CharacterGateSatisfied,
|
||||||
@if (Model.CharacterGateSatisfied)
|
"Character relationships found in scene evidence.",
|
||||||
{
|
ModuleAction("Relationships", Model.RelationshipNeedsAttentionCount, Model.PipelineDashboard.RelationshipStageComplete),
|
||||||
<strong class="story-review-status story-review-status--ready">Available</strong>
|
"StoryIntelligenceRelationships")
|
||||||
<span class="story-review-centre-row__count">@Model.TotalAnalysedScenes.ToString("N0") scenes</span>
|
|
||||||
}
|
@ReviewMetrics(!Model.CharacterGateSatisfied)
|
||||||
else
|
|
||||||
{
|
|
||||||
<strong class="story-review-status story-review-status--active">Resolve Characters first</strong>
|
|
||||||
<span class="story-review-centre-row__count">Locked until Characters are resolved</span>
|
|
||||||
}
|
|
||||||
</article>
|
|
||||||
|
|
||||||
@if (Model.AnalysisIssueCount > 0)
|
@if (Model.AnalysisIssueCount > 0)
|
||||||
{
|
{
|
||||||
<article class="story-review-centre-row">
|
@ReviewModule(
|
||||||
<div>
|
"Analysis Issues",
|
||||||
<h2>Analysis Issues</h2>
|
Model.AnalysisIssueCount,
|
||||||
<p>Some chapters or scenes reported analysis issues. Canonical chapters and scenes remain intact.</p>
|
false,
|
||||||
</div>
|
false,
|
||||||
<strong class="story-review-status story-review-status--warning">Needs attention</strong>
|
"Some chapters or scenes reported analysis issues.",
|
||||||
<a class="btn btn-outline-primary btn-sm" asp-controller="Books" asp-action="Details" asp-route-id="@Model.BookID">Return to book</a>
|
"Return to Book",
|
||||||
<span class="story-review-centre-row__count">@Model.AnalysisIssueCount.ToString("N0") need attention</span>
|
null)
|
||||||
</article>
|
|
||||||
}
|
}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="onboarding-actions">
|
<div class="onboarding-actions story-review-centre-actions">
|
||||||
<a class="btn btn-outline-secondary" asp-controller="Books" asp-action="Details" asp-route-id="@Model.BookID">Return to book</a>
|
<a class="btn btn-outline-secondary" asp-controller="Books" asp-action="Details" asp-route-id="@Model.BookID">Return to Book</a>
|
||||||
<a class="btn btn-outline-primary" asp-controller="Writer" asp-action="Index" asp-route-projectId="@Model.ProjectID">Open writer workspace</a>
|
<a class="btn btn-outline-primary" asp-controller="Writer" asp-action="Index" asp-route-projectId="@Model.ProjectID">Open Writer Workspace</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@functions {
|
@functions {
|
||||||
private string AttentionLabel(int count) => count == 0 ? "No outstanding decisions" : "Needs attention";
|
private string ModuleAction(string title, int count, bool complete)
|
||||||
|
=> count > 0 && !complete ? $"Review {title}" : $"View {title}";
|
||||||
|
|
||||||
|
private string StatusText(string title, int count, bool complete, bool blocked)
|
||||||
|
{
|
||||||
|
if (blocked)
|
||||||
|
{
|
||||||
|
return "Locked until Characters are resolved";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.Equals(title, "Scene Metrics", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
return "Available";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (complete)
|
||||||
|
{
|
||||||
|
return "Complete";
|
||||||
|
}
|
||||||
|
|
||||||
|
return count switch
|
||||||
|
{
|
||||||
|
0 => "No review needed",
|
||||||
|
1 => "1 needs attention",
|
||||||
|
_ => $"{count:N0} need attention"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Microsoft.AspNetCore.Html.IHtmlContent ReviewMetrics(bool blocked)
|
||||||
|
{
|
||||||
|
var status = StatusText("Scene Metrics", Model.TotalAnalysedScenes, false, blocked);
|
||||||
|
var statusClass = blocked
|
||||||
|
? "story-review-centre-tile__status story-review-centre-tile__status--locked"
|
||||||
|
: "story-review-centre-tile__status story-review-centre-tile__status--ready";
|
||||||
|
var actionHtml = blocked
|
||||||
|
? "<span class=\"btn btn-outline-secondary btn-sm disabled\" aria-disabled=\"true\">Locked</span>"
|
||||||
|
: "<span class=\"btn btn-outline-primary btn-sm disabled\" aria-disabled=\"true\">View Metrics</span>";
|
||||||
|
|
||||||
|
return new Microsoft.AspNetCore.Html.HtmlString($$"""
|
||||||
|
<article class="story-review-centre-tile{{(blocked ? " story-review-centre-tile--locked" : string.Empty)}}">
|
||||||
|
<div>
|
||||||
|
<h2>Scene Metrics</h2>
|
||||||
|
<p>Auto-applied metrics from analysed scenes.</p>
|
||||||
|
</div>
|
||||||
|
<strong class="{{statusClass}}">{{System.Net.WebUtility.HtmlEncode(status)}}</strong>
|
||||||
|
{{actionHtml}}
|
||||||
|
</article>
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
private Microsoft.AspNetCore.Html.IHtmlContent ReviewModule(
|
private Microsoft.AspNetCore.Html.IHtmlContent ReviewModule(
|
||||||
string title,
|
string title,
|
||||||
int count,
|
int count,
|
||||||
string status,
|
bool complete,
|
||||||
|
bool blocked,
|
||||||
string description,
|
string description,
|
||||||
string actionLabel,
|
string actionLabel,
|
||||||
string action,
|
string? action,
|
||||||
bool blocked)
|
bool primary = false)
|
||||||
{
|
{
|
||||||
|
var status = StatusText(title, count, complete, blocked);
|
||||||
var statusClass = blocked
|
var statusClass = blocked
|
||||||
? "story-review-status story-review-status--active"
|
? "story-review-centre-tile__status story-review-centre-tile__status--locked"
|
||||||
: count > 0
|
: count > 0 && !complete
|
||||||
? "story-review-status story-review-status--warning"
|
? "story-review-centre-tile__status story-review-centre-tile__status--warning"
|
||||||
: "story-review-status story-review-status--ready";
|
: "story-review-centre-tile__status story-review-centre-tile__status--ready";
|
||||||
var statusText = blocked ? "Resolve Characters first" : status;
|
var tileClass = "story-review-centre-tile"
|
||||||
var countText = blocked
|
+ (primary ? " story-review-centre-tile--primary" : string.Empty)
|
||||||
? "Locked until Characters are resolved"
|
+ (blocked ? " story-review-centre-tile--locked" : string.Empty);
|
||||||
: count == 1
|
var href = action is null
|
||||||
? "1 needs attention"
|
? Url.Action("Details", "Books", new { id = Model.BookID }) ?? "#"
|
||||||
: $"{count:N0} need attention";
|
|
||||||
var disabled = blocked ? " disabled aria-disabled=\"true\"" : string.Empty;
|
|
||||||
var href = blocked
|
|
||||||
? "#"
|
|
||||||
: Url.Action(action, "Onboarding", new { batchId = Model.BatchID }) ?? "#";
|
: Url.Action(action, "Onboarding", new { batchId = Model.BatchID }) ?? "#";
|
||||||
|
var actionHtml = blocked
|
||||||
|
? "<span class=\"btn btn-outline-secondary btn-sm disabled\" aria-disabled=\"true\">Locked</span>"
|
||||||
|
: $"<a class=\"btn btn-outline-primary btn-sm\" href=\"{System.Net.WebUtility.HtmlEncode(href)}\">{System.Net.WebUtility.HtmlEncode(actionLabel)}</a>";
|
||||||
|
|
||||||
return new Microsoft.AspNetCore.Html.HtmlString($$"""
|
return new Microsoft.AspNetCore.Html.HtmlString($$"""
|
||||||
<article class="story-review-centre-row">
|
<article class="{{tileClass}}">
|
||||||
<div>
|
<div>
|
||||||
<h2>{{System.Net.WebUtility.HtmlEncode(title)}}</h2>
|
<h2>{{System.Net.WebUtility.HtmlEncode(title)}}</h2>
|
||||||
<p>{{System.Net.WebUtility.HtmlEncode(description)}}</p>
|
<p>{{System.Net.WebUtility.HtmlEncode(description)}}</p>
|
||||||
</div>
|
</div>
|
||||||
<strong class="{{statusClass}}">{{System.Net.WebUtility.HtmlEncode(statusText)}}</strong>
|
<strong class="{{statusClass}}">{{System.Net.WebUtility.HtmlEncode(status)}}</strong>
|
||||||
<a class="btn btn-outline-primary btn-sm{{(blocked ? " disabled" : string.Empty)}}" href="{{href}}"{{disabled}}>{{System.Net.WebUtility.HtmlEncode(actionLabel)}}</a>
|
{{actionHtml}}
|
||||||
<span class="story-review-centre-row__count">{{System.Net.WebUtility.HtmlEncode(countText)}}</span>
|
|
||||||
</article>
|
</article>
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1384,36 +1384,101 @@ summary.story-review-chapter-heading {
|
|||||||
margin-top: .2rem;
|
margin-top: .2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.story-review-centre-list {
|
.story-review-centre-shell {
|
||||||
display: grid;
|
max-width: 1100px;
|
||||||
gap: .65rem;
|
margin: 0 auto;
|
||||||
|
padding: 2.25rem 1rem 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.story-review-centre-row {
|
.story-review-centre-workspace {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(0, 1fr) auto auto;
|
gap: 1rem;
|
||||||
gap: .75rem 1rem;
|
}
|
||||||
align-items: center;
|
|
||||||
|
.story-review-centre-heading {
|
||||||
|
max-width: 760px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-review-centre-heading h1 {
|
||||||
|
margin: .15rem 0 .35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-review-centre-heading p:not(.eyebrow) {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--bs-secondary-color);
|
||||||
|
font-size: 1.02rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-review-centre-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
gap: .9rem;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-review-centre-tile {
|
||||||
|
min-height: 12rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: .85rem;
|
||||||
border: 1px solid rgba(31, 42, 68, .1);
|
border: 1px solid rgba(31, 42, 68, .1);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: .85rem 1rem;
|
padding: 1rem;
|
||||||
background: rgba(255, 255, 255, .64);
|
background: rgba(255, 255, 255, .64);
|
||||||
}
|
}
|
||||||
|
|
||||||
.story-review-centre-row h2 {
|
.story-review-centre-tile--primary {
|
||||||
|
border-color: rgba(122, 74, 39, .32);
|
||||||
|
box-shadow: 0 10px 24px rgba(122, 74, 39, .08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-review-centre-tile--locked {
|
||||||
|
background: rgba(255, 255, 255, .46);
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-review-centre-tile h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 1.05rem;
|
font-size: 1.05rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.story-review-centre-row p {
|
.story-review-centre-tile p {
|
||||||
margin: .2rem 0 0;
|
margin: .2rem 0 0;
|
||||||
color: var(--bs-secondary-color);
|
color: var(--bs-secondary-color);
|
||||||
|
font-size: .94rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-review-centre-tile__status {
|
||||||
|
display: block;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--bs-body-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-review-centre-tile__status--ready {
|
||||||
|
color: #146c43;
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-review-centre-tile__status--warning {
|
||||||
|
color: #7a4a27;
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-review-centre-tile__status--locked {
|
||||||
|
color: var(--bs-secondary-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.story-review-centre-row__count {
|
.story-review-centre-tile .btn {
|
||||||
grid-column: 1 / -1;
|
align-self: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-review-centre-tile .btn.disabled {
|
||||||
|
pointer-events: none;
|
||||||
color: var(--bs-secondary-color);
|
color: var(--bs-secondary-color);
|
||||||
font-weight: 700;
|
border-color: rgba(31, 42, 68, .16);
|
||||||
|
background: rgba(31, 42, 68, .04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-review-centre-actions {
|
||||||
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.story-scene-preview-list {
|
.story-scene-preview-list {
|
||||||
@ -1972,6 +2037,12 @@ summary.story-review-chapter-heading {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 980px) {
|
||||||
|
.story-review-centre-grid {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 720px) {
|
@media (max-width: 720px) {
|
||||||
.story-pipeline-phase-list,
|
.story-pipeline-phase-list,
|
||||||
.story-database-build ul {
|
.story-database-build ul {
|
||||||
@ -2042,7 +2113,6 @@ summary.story-review-chapter-heading {
|
|||||||
.story-review-summary,
|
.story-review-summary,
|
||||||
.story-review-scene-panel,
|
.story-review-scene-panel,
|
||||||
.story-character-card__body dl,
|
.story-character-card__body dl,
|
||||||
.story-review-centre-row,
|
|
||||||
.story-future-stage-grid,
|
.story-future-stage-grid,
|
||||||
.story-scene-preview dl,
|
.story-scene-preview dl,
|
||||||
.story-live-current,
|
.story-live-current,
|
||||||
@ -2051,6 +2121,10 @@ summary.story-review-chapter-heading {
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.story-review-centre-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
.story-live-progress-heading,
|
.story-live-progress-heading,
|
||||||
.story-review-chapter-heading {
|
.story-review-chapter-heading {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user