Implemented Phase B guidance/discoverability work.

This commit is contained in:
Nick Beckley 2026-06-19 14:22:02 +01:00
parent 7363d0c128
commit 3b60634667
41 changed files with 1047 additions and 40 deletions

View File

@ -0,0 +1,26 @@
---
title: Assets
category: Scene Inspector
tags: scene inspector, assets, objects, continuity
contextKey: sceneInspector.assets
micro: Record important object, evidence and clue changes in this scene.
quickTitle: Scene assets
quickSummary: Asset events track object states, dependencies, locations and continuity implications for important story items.
screenshot:
---
# Overview
Assets are story objects that matter: letters, weapons, keys, documents, phones, vehicles, evidence, heirlooms, maps or anything whose state or location can affect the plot.
Asset states record what condition or story status the object has. Dependencies record when one asset's usefulness depends on another state. Location tracking records where the object is. Custody records who has responsibility or possession.
# Continuity Implications
Assets create continuity obligations. If a letter is burned, it should not be read later unless another copy exists. If a weapon is with one character, another character needs a reason to use it. If evidence is hidden, discovery should happen in a recorded scene.
# Related Guides
- [Timeline Asset Events](/Help/Article/timeline.assetEvents)
- [Custody](/Help/Article/sceneInspector.custody)
- [Story Assets](/Help/Article/storyAssets.overview)

View File

@ -0,0 +1,16 @@
---
title: Attachments and Research
category: Scene Inspector
tags: scene inspector, attachments, research, references
contextKey: sceneInspector.attachments
micro: Keep scene references and research close to the scene.
quickTitle: Attachments and research
quickSummary: Attachments store files, links and notes that support drafting or revising this scene.
screenshot:
---
# Overview
Attachments are for supporting material: research links, images, maps, interview notes, historical references, sketches or source documents.
Use notes to explain why the attachment matters. Future-you should not have to reopen every file to remember what it was for.

View File

@ -0,0 +1,25 @@
---
title: Character Attributes
category: Scene Inspector
tags: scene inspector, character attributes, injuries, continuity
contextKey: sceneInspector.characterAttributes
micro: Track visible and internal character state changes from this scene forward.
quickTitle: Character attributes
quickSummary: Character attributes record appearance changes, injuries, emotional state and skills so future scenes can remain consistent.
screenshot:
---
# Overview
Character attributes capture changes that may matter after this scene. They can include appearance changes, injuries, clothing, physical condition, emotional state, skills, knowledge notes or other state details.
Use them when a scene changes how a character should be described or understood later. A cut lip, soaked clothes, concealed panic, a learned skill or a visible disguise can all create continuity obligations.
# How Changes Persist
Attribute changes become part of the character's story history. Future scenes can then be checked against what has already been established. If a character is injured in one scene and perfectly fine in the next without explanation, PlotDirector has evidence to help you notice.
# Related Guides
- [Characters](/Help/Article/sceneInspector.characters)
- [Continuity Warnings](/Help/Article/warnings.overview)

View File

@ -0,0 +1,21 @@
---
title: Characters
category: Scene Inspector
tags: scene inspector, characters, appearances, continuity
contextKey: sceneInspector.characters
micro: Record who appears in the scene and what role they play.
quickTitle: Scene characters
quickSummary: Character entries connect a scene to point of view, presence, location and character continuity.
screenshot:
---
# Overview
The Characters section records who appears in the scene, how they participate and where they are. This supports Timeline appearance lanes, character-focused views and continuity checks.
Role tells you whether a character is the point of view, a main participant, a supporting presence or only mentioned. Presence and location details help the story remember who was actually there.
# Related Guides
- [Character Appearances](/Help/Article/timeline.characterAppearances)
- [Character Attributes](/Help/Article/sceneInspector.characterAttributes)

View File

@ -0,0 +1,16 @@
---
title: Scene Checklist
category: Scene Inspector
tags: scene inspector, checklist, revision
contextKey: sceneInspector.checklist
micro: Keep scene-specific tasks visible.
quickTitle: Scene checklist
quickSummary: Checklist items hold small drafting or revision tasks that belong to this scene.
screenshot:
---
# Overview
The checklist is for concrete scene tasks: add sensory detail, check the alibi, rewrite the argument, verify the date, add the missing clue, or trim the ending.
Use it for actions you want to complete, not for permanent story facts. Story facts belong in the relevant scene, character, thread or asset fields.

View File

@ -0,0 +1,26 @@
---
title: Custody
category: Scene Inspector
tags: scene inspector, custody, assets, continuity
contextKey: sceneInspector.custody
micro: Track who has or controls important assets.
quickTitle: Asset custody
quickSummary: Custody records possession, transfer and responsibility for important story items.
screenshot:
---
# Overview
Custody is about who has an asset, controls it, guards it or is responsible for it. It is especially useful for evidence, weapons, keys, letters, documents and valuables.
Custody can differ from location. A car may be parked outside, but one character may hold the keys. A document may be in a safe, but another character may control access.
# Continuity Benefits
Custody helps PlotDirector spot impossible possession. If Beth gives the key to Arun in one scene, Beth should not use it later unless it returns to her or a duplicate exists.
# Related Guides
- [Assets](/Help/Article/sceneInspector.assets)
- [Timeline Asset Events](/Help/Article/timeline.assetEvents)
- [Continuity Warnings](/Help/Article/warnings.overview)

View File

@ -0,0 +1,16 @@
---
title: Scene Dependencies
category: Scene Inspector
tags: scene inspector, dependencies, sequence, continuity
contextKey: sceneInspector.dependencies
micro: Record ordering relationships between scenes.
quickTitle: Scene dependencies
quickSummary: Dependencies explain when one scene must happen before another for logic, causality or continuity.
screenshot:
---
# Overview
Scene dependencies record order requirements. Use them when one scene needs another moment to happen first, or when moving a scene would break cause and effect.
A hard dependency means the order is essential. A soft dependency means the order is recommended but may be revisable.

View File

@ -0,0 +1,14 @@
---
title: Relationship Intensity
category: Scene Inspector
tags: scene inspector, fields, relationships
contextKey: sceneInspector.fields.relationshipIntensity
micro: Record how strong the relationship state is in this scene.
quickTitle: Relationship intensity
quickSummary: Intensity captures the strength of the relationship change, from mild tension to life-altering bond or conflict.
screenshot:
---
# Overview
Use lower values for subtle shifts and higher values for relationship moments that strongly affect choices, trust, attraction, loyalty or conflict.

View File

@ -0,0 +1,14 @@
---
title: Thread Event Type
category: Scene Inspector
tags: scene inspector, fields, threads
contextKey: sceneInspector.fields.threadEventType
micro: Choose what this scene does to the thread.
quickTitle: Thread event type
quickSummary: Pick the narrative function: start, progress, reveal, twist, branch, split, merge, resolve or abandon.
screenshot:
---
# Overview
Choose the event type that explains the scene's narrative purpose for this thread. If the scene only mentions the thread, Progress is often better than Reveal or Resolve.

View File

@ -0,0 +1,14 @@
---
title: Thread Marker Type
category: Scene Inspector
tags: scene inspector, fields, threads
contextKey: sceneInspector.fields.threadMarkerType
micro: Choose the marker used for Timeline display.
quickTitle: Thread marker type
quickSummary: Marker type controls how this thread event appears on Timeline lanes.
screenshot:
---
# Overview
Use marker type to make the Timeline readable. It should match the story beat closely enough that you can scan the lane later and understand the thread's shape.

View File

@ -0,0 +1,44 @@
---
title: Knowledge
category: Scene Inspector
tags: scene inspector, knowledge, secrets, reader knowledge, continuity
contextKey: sceneInspector.knowledge
micro: Track what characters and readers know, suspect or misunderstand.
quickTitle: Character knowledge
quickSummary: Knowledge records discoveries, secrets, mistaken beliefs and reader awareness so reveals and continuity stay coherent.
screenshot:
---
# Overview
Knowledge tracks information as story state. It helps answer: What does this character know now? Are they guessing? Is the reader ahead of them? Did a reveal happen too early or too late?
# Awareness States
Unaware means the character has no meaningful knowledge of the fact.
Suspects means the character has a hunch, clue or suspicion but no reliable proof.
Partially Knows means the character has some truth but not the full picture.
Knows means the character has enough information to act as if the fact is true.
Progression does not always move neatly upward. A character can be misled, lose confidence, discover a partial truth or have a correct belief undermined.
# Confidence
Confidence records certainty. A character may know something confidently, suspect something weakly, or be very confident about a mistaken belief. This distinction is important for dramatic irony and continuity.
# Reader Knows
Reader knowledge is separate from character knowledge. If the reader knows the villain's identity but the protagonist does not, the story is using dramatic irony. If the protagonist knows something the reader does not, the story is withholding information.
# Knowledge Progression
Use knowledge events for reveals, discoveries, corrected assumptions, regressions and secrets changing hands. Continuity warnings can then help find scenes where a character acts on information they should not yet have, or fails to know something they already learned.
# Related Guides
- [Continuity Warnings](/Help/Article/warnings.overview)
- [Story State](/Help/Article/sceneInspector.storyState)
- [Continuity Explorer](/Help/Article/warnings.overview)

View File

@ -0,0 +1,21 @@
---
title: Asset Locations
category: Scene Inspector
tags: scene inspector, locations, assets, continuity
contextKey: sceneInspector.locations
micro: Record where important assets are in this scene.
quickTitle: Asset locations
quickSummary: Asset locations help PlotDirector understand where objects are at this point in the story.
screenshot:
---
# Overview
Asset locations record where an important object is during this scene. Use them when location matters even if custody does not.
This is useful for hidden evidence, parked vehicles, locked rooms, documents left on a desk or objects that can be found later.
# Related Guides
- [Assets](/Help/Article/sceneInspector.assets)
- [Locations](/Help/Article/locations.overview)

View File

@ -0,0 +1,16 @@
---
title: Scene Notes
category: Scene Inspector
tags: scene inspector, notes, drafting, revision
contextKey: sceneInspector.notes
micro: Keep drafting thoughts, research reminders and revision questions with the scene.
quickTitle: Scene notes
quickSummary: Scene notes capture working thoughts that do not belong in story continuity but matter while drafting or revising.
screenshot:
---
# Overview
Notes are for the writer's working memory. Use them for revision questions, research reminders, alternate ideas, emotional intent, line-level concerns or anything you do not want to lose while drafting.
Pinned notes stay prominent. Resolved notes keep the history without continuing to demand attention.

View File

@ -0,0 +1,30 @@
---
title: Scene Inspector
category: Scene Inspector
tags: scene inspector, scenes, continuity, editing
contextKey: sceneInspector.overview
micro: Edit one scene's story purpose, continuity details and writing workflow.
quickTitle: Scene Inspector overview
quickSummary: The Scene Inspector is where a single scene's purpose, time, characters, threads, assets, metrics and continuity evidence are reviewed together.
screenshot:
---
# Overview
The Scene Inspector is the close-up view for one scene. The Timeline shows how scenes relate across the book; the Scene Inspector records what is true inside a specific scene.
Use it to capture story purpose, outcome, time, characters, knowledge, relationships, assets, custody, locations, metrics, warnings, notes and writing workflow. You do not need every section for every scene. The goal is to record the details that matter for the scene's role in the story and for future continuity.
# How To Work With It
Start with the scene's basic shape: title, summary, timing, location, purpose and outcome. Then add the people, objects, plot threads and continuity details that change because this scene exists.
For example, if a character discovers a secret, record it in Knowledge. If a letter changes hands, record it in Assets or Custody. If a relationship turns colder, record a Relationship Event. If the scene pays off a mystery clue, record a Plot Thread Event.
# Related Guides
- [Timeline](/Help/Article/timeline.overview)
- [Knowledge](/Help/Article/sceneInspector.knowledge)
- [Relationships](/Help/Article/sceneInspector.relationships)
- [Threads](/Help/Article/sceneInspector.threads)
- [Assets](/Help/Article/sceneInspector.assets)

View File

@ -0,0 +1,21 @@
---
title: Purpose and Outcome
category: Scene Inspector
tags: scene inspector, scene purpose, outcome, revision
contextKey: sceneInspector.purpose
micro: Clarify why the scene exists and what changes by the end.
quickTitle: Purpose and outcome
quickSummary: Scene purpose and outcome notes help you see what narrative job the scene performs and whether it changes the story.
screenshot:
---
# Overview
Purpose explains the work a scene is doing: setup, reveal, payoff, relationship movement, action, transition, character development or another story function.
Outcome records what is different by the end. The change can be external, emotional, informational or relational. If you cannot name the outcome, the scene may need sharper story movement.
# Related Guides
- [Scene Cards](/Help/Article/timeline.sceneCards)
- [Scenes](/Help/Article/scenes.overview)

View File

@ -0,0 +1,35 @@
---
title: Relationships
category: Scene Inspector
tags: scene inspector, relationships, character arcs, continuity
contextKey: sceneInspector.relationships
micro: Track relationship changes as scene events.
quickTitle: Relationship events
quickSummary: Relationship events show how family, friendship, romance, rivalry, mentorship and professional bonds evolve through scenes.
screenshot:
---
# Overview
Relationships change through scenes. A conversation may deepen trust, expose betrayal, begin attraction, damage a friendship or shift a professional alliance. Recording those changes helps character arcs stay visible.
# Relationship Types
Types describe the shape of the bond: family, friendship, romance, rivalry, mentorship, professional, alliance or another story-specific connection.
# Reciprocity
Relationships can be mutual or one-sided. One character may love, trust, resent or mentor another without the feeling being returned. That asymmetry is often the story.
# Intensity
Intensity records relationship strength. A low-intensity rivalry might be irritation. A high-intensity rivalry might drive major choices. A romance can be quiet but intense, or public but shallow.
# Evolution
Use events when the relationship state changes in this scene. This helps you see whether a breakup has setup, whether forgiveness arrives too quickly, or whether a character behaves as if a relationship has changed before the scene that actually changes it.
# Related Guides
- [Characters](/Help/Article/characters.overview)
- [Character Appearances](/Help/Article/timeline.characterAppearances)

View File

@ -0,0 +1,22 @@
---
title: Story State
category: Scene Inspector
tags: scene inspector, story state, continuity, warnings
contextKey: sceneInspector.storyState
micro: Review the known character and asset state at this point in the story.
quickTitle: Story state
quickSummary: Story State summarises current character and asset continuity evidence around this scene.
screenshot:
---
# Overview
Story State is a continuity snapshot. It helps you see what PlotDirector currently understands about characters and assets at this point in the sequence.
Use it when a warning looks surprising or when you need to check whether the story has enough evidence for a character location, asset holder or important state.
# Related Guides
- [Knowledge](/Help/Article/sceneInspector.knowledge)
- [Assets](/Help/Article/sceneInspector.assets)
- [Continuity Warnings](/Help/Article/warnings.overview)

View File

@ -0,0 +1,25 @@
---
title: Threads
category: Scene Inspector
tags: scene inspector, plot threads, timeline, thread health
contextKey: sceneInspector.threads
micro: Attach plot thread events to the scene.
quickTitle: Scene plot threads
quickSummary: Thread events describe what this scene does for a plot question, mystery, promise, arc or payoff.
screenshot:
---
# Overview
Threads are specific unresolved story concerns. In the Scene Inspector, a thread event records how this scene affects that concern. On the Timeline, those events become lane markers.
Use importance to show how central a thread is. Use lifecycle events to show whether the scene starts, progresses, reveals, twists, branches, splits, merges, resolves or abandons the thread.
# Why It Matters
Thread events prevent story promises from becoming invisible. If a clue is planted, mark it. If the reader receives a reveal, mark it. If a subplot is intentionally abandoned, mark that too so thread health knows the silence is deliberate.
# Related Guides
- [Plot Thread Lanes](/Help/Article/timeline.plotThreadLanes)
- [Thread Health](/Help/Article/timeline.threadHealth)

View File

@ -0,0 +1,21 @@
---
title: Time
category: Scene Inspector
tags: scene inspector, time, continuity, chronology
contextKey: sceneInspector.time
micro: Record when a scene happens and how certain that timing is.
quickTitle: Scene time
quickSummary: Scene time helps chronology, age checks, sequence logic and continuity warnings understand when the scene occurs.
screenshot:
---
# Overview
Time fields tell PlotDirector when a scene happens. Use exact dates when chronology matters, relative time when the draft only needs "later that night" or "three weeks after the funeral", and confidence when the timing is still provisional.
Accurate time helps continuity checks find impossible sequences, age issues, travel gaps and story events that happen in the wrong order.
# Related Guides
- [Continuity Warnings](/Help/Article/warnings.overview)
- [Scene Inspector](/Help/Article/sceneInspector.overview)

View File

@ -0,0 +1,16 @@
---
title: Continuity Warnings
category: Scene Inspector
tags: scene inspector, warnings, continuity
contextKey: sceneInspector.warnings
micro: Review continuity issues related to this scene.
quickTitle: Scene warnings
quickSummary: Continuity warnings highlight possible contradictions or missing evidence for this scene.
screenshot:
---
# Overview
Warnings are prompts for review. They point to places where PlotDirector's recorded evidence suggests something may be missing, contradictory or worth checking.
Dismiss a warning when it is no longer useful. Mark it intentional when the apparent contradiction is a deliberate author choice.

View File

@ -0,0 +1,16 @@
---
title: Writer Workspace
category: Scene Inspector
tags: scene inspector, writer, drafting, workflow
contextKey: sceneInspector.writer
micro: Track drafting progress for this scene.
quickTitle: Writer workspace
quickSummary: Writer Workspace fields connect this scene to drafting priority, word counts, blockers and chapter workflow.
screenshot:
---
# Overview
Writer Workspace fields are practical drafting tools. They help you decide what to write next, estimate effort, record progress and mark blockers.
These fields do not change story continuity. They support the working process around the scene.

View File

@ -0,0 +1,40 @@
---
title: Asset Events
category: Timeline
tags: timeline, assets, custody, continuity, evidence
contextKey: timeline.assetEvents
micro: Track important objects, evidence and documents across scenes.
quickTitle: Asset events
quickSummary: Asset events show where important story objects change state, location or custody so continuity remains visible.
screenshot:
---
# Overview
Asset events represent important changes to objects, evidence, documents, vehicles, weapons, keys, letters, phones, maps or other story items. If an object matters to the plot or continuity, it should have a visible trail.
Tracking assets helps answer questions such as: Who has the letter? Where is the weapon? Has the key been found yet? Could this character know about the document?
# Why It Matters
Objects often create continuity problems because they move quietly. A scene may hand a clue to one character, hide it in a room, destroy it or change its meaning. Asset events make those changes explicit.
Custody and location links help Continuity Explorer and warnings reason about whether the story state makes sense.
# Examples
A letter is discovered in chapter two, stolen in chapter four and read aloud in chapter eight.
A weapon moves from a locked cabinet to a suspect's car.
A key is copied, lost, found and finally used.
A document is forged, signed, hidden and exposed.
A vehicle changes hands and later becomes an alibi problem.
# Related Guides
- [Story Assets](/Help/Article/storyAssets.overview)
- [Asset Custody](/Help/Article/sceneInspector.custody)
- [Continuity Explorer](/Help/Article/warnings.overview)

View File

@ -0,0 +1,32 @@
---
title: Character Appearances
category: Timeline
tags: timeline, characters, appearances, point of view
contextKey: timeline.characterAppearances
micro: See where characters are present and active across the story.
quickTitle: Character appearances
quickSummary: Character appearance lanes show where characters appear, what role they play and how focused views can support character arc review.
screenshot:
---
# Overview
Character appearance markers show where a character is present in the story. They help you see who is active, who disappears for long stretches, and whether a character's role matches the arc you intend.
Presence can mean more than standing in the room. A character may be a point-of-view character, a main participant, a mentioned person or someone whose absence matters.
# How Authors Use This
Focus on one character to review their arc.
Check whether a point-of-view character has enough page presence.
Find long absences that may need a reminder, explanation or deliberate silence.
Compare character activity against relationship, knowledge and attribute changes in the Scene Inspector.
# Related Guides
- [Characters](/Help/Article/characters.overview)
- [Character Attributes](/Help/Article/sceneInspector.characterAttributes)
- [Relationships](/Help/Article/sceneInspector.relationships)

View File

@ -0,0 +1,14 @@
---
title: Timeline Book Filter
category: Timeline
tags: timeline, fields, filters, books
contextKey: timeline.fields.bookFilter
micro: Choose whether the Timeline shows all books or one book.
quickTitle: Book filter
quickSummary: Use the book filter to focus timeline review on one volume without removing project-wide planning data.
screenshot:
---
# Overview
Choose one book when you are revising a single volume. Choose all books when you need series-wide continuity, long-running threads or project pacing.

View File

@ -0,0 +1,14 @@
---
title: Timeline Focus ID
category: Timeline
tags: timeline, fields, focus
contextKey: timeline.fields.focusId
micro: Provide the ID of the story item to focus.
quickTitle: Focus ID
quickSummary: Focus ID is the specific character, asset, plot line, plot thread, location or scene identifier used by focus mode.
screenshot:
---
# Overview
Focus ID is useful when a link or saved view already knows the exact item to highlight. Most day-to-day focusing is easier through filters, lane links or saved views.

View File

@ -0,0 +1,14 @@
---
title: Timeline Focus Type
category: Timeline
tags: timeline, fields, focus
contextKey: timeline.fields.focusType
micro: Choose the kind of story item to highlight.
quickTitle: Focus type
quickSummary: Focus type tells the Timeline whether you want to highlight a character, asset, plot line, plot thread, location or scene.
screenshot:
---
# Overview
Focus type controls what kind of story evidence the Timeline should emphasise. Use it when you know you want one lane, character, object or scene to stand out while the rest remains visible for context.

View File

@ -0,0 +1,14 @@
---
title: Timeline Metric Editing
category: Timeline
tags: timeline, fields, metrics, pacing
contextKey: timeline.fields.metricEdit
micro: Edit metric shape when one metric line is selected.
quickTitle: Metric editing
quickSummary: Show a single metric line when you want to adjust its scene values directly from the Timeline.
screenshot:
---
# Overview
Metric editing is for pacing passes. Show one metric line, then adjust scene values where the shape does not match your intention. Treat the numbers as a writing aid, not a score.

View File

@ -0,0 +1,14 @@
---
title: Saved View Name
category: Timeline
tags: timeline, fields, saved views
contextKey: timeline.fields.savedViewName
micro: Name a reusable Timeline lens.
quickTitle: Saved view name
quickSummary: Give saved views practical names based on the revision question they answer.
screenshot:
---
# Overview
Use names like "Central mystery pass", "Beth relationship arc" or "Warnings review". A clear name makes the view useful when you return during revision.

View File

@ -0,0 +1,40 @@
---
title: Filters and Focus
category: Timeline
tags: timeline, filters, focus, characters, assets, threads
contextKey: timeline.filters
micro: Narrow the Timeline to the story concern you are reviewing.
quickTitle: Filters and focus
quickSummary: Filters change which scenes and lanes are emphasised so you can review a book, character, asset, plot thread or warning pattern.
screenshot:
---
# Overview
Filters help you review a specific part of the story without changing the story itself. They change what is visible or emphasised on the Timeline, so you can answer focused revision questions.
Book, chapter and scene filters narrow the structural scope. Character, asset, plot line, plot thread, location, warning and purpose filters narrow by story evidence. Focus mode highlights the matching scenes and dims the rest.
# Examples
Filter to one book when revising a sequel but keep the project context intact.
Filter to a character to find every scene where they appear, then check whether their emotional state or knowledge changes make sense.
Filter to an asset such as a letter, weapon, key, document, vehicle or piece of evidence to see where it appears, moves or changes custody.
Filter to a thread to trace a mystery question from setup to reveal.
Show warnings only when you are doing a continuity pass and want to move quickly from problem scene to problem scene.
# Things To Remember
Filtering is a lens, not a delete action. Scenes that disappear or dim have not been removed.
If a scene you expect is missing, check whether the scene has the character, asset, location, thread event or purpose attached. The Timeline can only filter by recorded planning evidence.
# Related Guides
- [Saved Views](/Help/Article/timeline.savedViews)
- [Character Appearances](/Help/Article/timeline.characterAppearances)
- [Asset Events](/Help/Article/timeline.assetEvents)

View File

@ -0,0 +1,47 @@
---
title: Metrics
category: Timeline
tags: timeline, metrics, pacing, intensity, emotion
contextKey: timeline.metrics
micro: Use scene metrics to sketch pacing and emotional shape.
quickTitle: Timeline metrics
quickSummary: Metrics are author-defined pacing tools that help you see intensity, tension, emotion, action, mystery and other story qualities across scenes.
screenshot:
---
# Overview
Metrics are author tools, not objective measurements. A value is your judgement about what the scene is doing. The Timeline turns those judgements into a pacing shape so you can see peaks, rests, repetition and contrast.
# Common Metrics
Overall Intensity represents the combined pressure of the scene. Raise it for climaxes, confrontations and major reversals. Lower it for recovery, setup or quiet reflection.
Tension represents suspense, uncertainty and pressure. Raise it when danger, secrets or stakes tighten. Lower it when answers arrive or characters get breathing room.
Emotional Weight represents how strongly the scene lands emotionally. Raise it for grief, confession, betrayal, intimacy or sacrifice. Lower it for lighter connective scenes.
Action represents physical movement and external incident. Raise it for fights, chases, escapes and urgent activity. Lower it for dialogue, planning or introspection.
Darkness represents grimness, threat, moral cost or bleakness. Raise it for cruelty, loss or dread. Lower it when the scene restores safety or warmth.
Romance represents romantic development. Raise it for attraction, intimacy, longing, conflict or commitment. Lower it when romance is not the scene's main work.
Sexual Charge represents sensual or erotic tension. Raise it when desire is deliberately present. Lower it when intimacy is emotional, practical or absent.
Violence represents physical harm or threat. Raise it for combat, injury or brutality. Lower it for scenes without violent pressure.
Hope / Lightness represents relief, optimism, tenderness or brightness. Raise it when the story gives readers air. Lower it when the scene closes down possibility.
Comedy represents humour and comic release. Raise it for jokes, irony, banter or absurdity. Lower it when humour would undercut the intended tone.
Mystery represents unanswered questions, clues and hidden information. Raise it for discoveries, suspicious details and reveals that create more questions. Lower it after answers land.
# How Metrics Help Pacing
Metrics help you compare intention against shape. If every scene is high intensity, readers may feel numb. If a mystery has a long flat stretch, the clue trail may need attention. If hope never rises, the book may feel darker than intended.
# Related Guides
- [Scene Metrics](/Help/Article/sceneMetrics.overview)
- [Story Health Scene Metric Shape](/Help/Article/storyHealth.sceneMetricShape)

View File

@ -0,0 +1,60 @@
---
title: Timeline
category: Timeline
tags: timeline, scenes, continuity, planning, pacing
contextKey: timeline.overview
micro: Understand the Timeline as the planning spine for scenes, continuity and story shape.
quickTitle: What is the Timeline?
quickSummary: The Timeline shows how books, chapters and scenes connect to plot threads, characters, assets, metrics and continuity checks.
screenshot:
---
# Overview
The Timeline is the central planning view for a project. It lays out the story from project to book to chapter to scene, then adds the evidence that helps you see whether the story is developing cleanly: plot threads, character appearances, important assets, scene metrics, locations, warnings and story health signals.
Use it when you want to step back from individual scene editing and ask, "What is happening across the whole story?" A mystery writer might follow the clue trail, a romance writer might watch emotional closeness build and break, and a series writer might check whether an object or secret has stayed consistent across books.
# The Timeline Hierarchy
The project is the full container for the story world. A project may hold one book or a series.
A book is a major narrative unit within the project. Book filters let you focus on one volume without losing project-wide context.
A chapter groups scenes into reading order. On the Timeline, chapters give the scene cards their structure.
A scene is the basic unit of story movement. Scene cards are where PlotDirector brings together purpose, outcome, time, participants, assets, metrics and continuity evidence.
# How Timeline Connects To Other Systems
Plot Threads appear as thread event markers so you can see where questions start, develop, twist, branch and resolve.
Metrics turn individual scene ratings into a visible pacing shape. They help you spot long flat stretches, repeated peaks or scenes that need a quieter beat.
Characters appear in lanes and scene cards so you can follow presence, point of view, activity and continuity.
Assets appear when important objects, clues, weapons, documents or evidence change state, location or custody.
Continuity systems use scene data to produce warnings. The Timeline then makes those warnings visible in context.
Continuity Explorer, Story Health and Analytics use the same planning evidence from scenes, threads, characters, assets and metrics to help you inspect the story from different angles.
# Typical Author Workflows
For a mystery, filter to the investigation thread and check whether clues, reveals and false turns are fairly spaced before the solution.
For a romance, save a view that focuses on the central characters, relationship events and Romance or Emotional Weight metrics. This makes it easier to see whether closeness, conflict and reconciliation have a satisfying rhythm.
For a character arc, focus on one character and follow their appearances, knowledge changes, injuries, emotional state and key relationship scenes.
For continuity, use the Timeline with warnings visible, then open the Scene Inspector for the affected scene and fix the missing location, custody or knowledge detail.
For pacing, compare intensity, tension, action, hope, comedy or mystery across the scene sequence. The numbers are author tools, not objective truth; they help you make your intended shape visible.
# Related Guides
- [Scene Cards](/Help/Article/timeline.sceneCards)
- [Filters and Focus](/Help/Article/timeline.filters)
- [Plot Thread Lanes](/Help/Article/timeline.plotThreadLanes)
- [Scene Inspector](/Help/Article/sceneInspector.overview)
- [Story Health](/Help/Article/storyHealth.overview)

View File

@ -0,0 +1,52 @@
---
title: Plot Thread Lanes
category: Timeline
tags: timeline, plot threads, events, reveals, continuity
contextKey: timeline.plotThreadLanes
micro: Follow plot thread events across scenes.
quickTitle: Plot thread lanes
quickSummary: Plot thread lanes show where story questions begin, develop, twist, branch, merge, resolve or are intentionally abandoned.
screenshot:
---
# Overview
Plot thread lanes turn scattered story promises into a visible path. A lane helps you see whether a mystery, relationship question, political scheme, secret, clue chain or emotional promise is being carried through the scenes.
Each marker is a thread event attached to a scene. The marker is not just a button; it records what the scene does for the reader's expectation.
# Thread Events
Start begins a thread. Use it when the reader first receives a question or promise, such as "Who sent the letter?"
Progress develops the thread without solving it. A suspect lies, a clue deepens the question, or a relationship takes a meaningful step.
Reveal gives the reader or a character new truth. For example, the locked room was opened from inside.
Twist changes the reader's interpretation. The friendly witness is connected to the victim.
Branch creates a new related thread from an existing one. A missing key leads to a second question about who had access.
Split divides one thread into multiple concerns. A conspiracy thread might split into motive, method and cover-up.
Merge brings related threads together. Two apparently separate clues point to the same culprit.
Resolve pays off the thread. The question is answered or the emotional promise is fulfilled.
Abandon marks an intentional drop. Use it when a character gives up, a false trail is deliberately left unresolved, or the story chooses not to answer because that is the point.
# Common Uses
Track a mystery from clue to reveal.
Track a romance from attraction to rupture to reconciliation.
Track a character arc promise from wound to choice to change.
Track a series question that should not vanish between books.
# Related Guides
- [Thread Health](/Help/Article/timeline.threadHealth)
- [Plot Threads](/Help/Article/sceneInspector.threads)
- [Plot Lines](/Help/Article/timeline.plotLines)

View File

@ -0,0 +1,35 @@
---
title: Saved Views
category: Timeline
tags: timeline, saved views, revision, workflow
contextKey: timeline.savedViews
micro: Save useful Timeline filter and visibility combinations.
quickTitle: Saved views
quickSummary: Saved Views let you return to common revision lenses such as one character, one romance arc, one mystery thread or a warnings-only pass.
screenshot:
---
# Overview
Saved Views preserve the current Timeline lens so you can reuse it later. They are useful when you repeatedly return to the same story question during drafting or revision.
A view can capture the active filters and section visibility. For example, you might create a view for one protagonist, another for the romance arc, another for the central mystery, and another for continuity warnings.
# Useful Saved Views
A character-focused view shows one character's scenes, appearances and relevant story evidence.
A romance view can combine the couple, relationship events, romance metrics and emotional weight.
A mystery view can focus on the investigation plot line, thread events, asset evidence and Mystery metric.
A revision view can show warnings, revision status, purpose and pacing while hiding lanes you do not need for that pass.
# Writer Tip
Name views for the question they answer: "Where is Beth's grief visible?" is often more useful than "Beth filter".
# Related Guides
- [Filters and Focus](/Help/Article/timeline.filters)
- [Metrics](/Help/Article/timeline.metrics)

View File

@ -0,0 +1,38 @@
---
title: Scene Cards
category: Timeline
tags: timeline, scenes, cards, continuity
contextKey: timeline.sceneCards
micro: Scene cards are the Timeline's building blocks.
quickTitle: Scene cards
quickSummary: Scene cards show the scenes in reading order and surface the planning details that matter most at timeline level.
screenshot:
---
# Overview
Scene cards represent the story's actual sequence. Each card is one scene in its chapter and book, which makes the cards the foundation of the Timeline.
A card can show the scene number, title, revision status, point of view, time label, location, warning count, dependency count, purpose chips, a short summary and metric highlights. It is intentionally compact: the card is for scanning, while the Scene Inspector is for editing the deeper detail.
# Why They Matter
Scene cards connect the broad outline to the continuity model. When a card shows a location, warning, metric or purpose, it is not just decoration; it is evidence that other systems can use.
For example, if "Beth hides the key" is a scene card, the connected asset event can later explain why another character should not possess that key. If the card has high Mystery and low Action, the pacing shape can show that this scene is doing quiet clue work rather than physical escalation.
# Common Workflows
Open a card when you want to inspect or revise the scene.
Use cards to scan chapter balance: action scene, aftermath scene, clue scene, relationship scene.
Use warning badges to find scenes that need continuity attention.
Use purpose chips and metric summaries to check whether scenes are earning their place in the story.
# Related Guides
- [Timeline](/Help/Article/timeline.overview)
- [Scene Inspector Overview](/Help/Article/sceneInspector.overview)
- [Metrics](/Help/Article/timeline.metrics)

View File

@ -0,0 +1,36 @@
---
title: Thread Health
category: Timeline
tags: timeline, plot threads, story health, warnings
contextKey: timeline.threadHealth
micro: Use thread health warnings to find storylines that may have been forgotten.
quickTitle: Thread health
quickSummary: Thread health helps you spot neglected, dangling, questionably resolved or abandoned plot threads before readers feel the gap.
screenshot:
---
# Overview
Thread health is a revision aid. It looks for plot threads that may have gone quiet for too long, resolved too weakly, or been left dangling after the story promised the reader attention.
A healthy thread has a clear start, meaningful development and an intentional outcome. It does not need constant activity, but its silence should feel deliberate.
# Warning Types
Neglected threads have not appeared for a while. This may be fine for a slow-burn mystery, but it may also mean the thread was forgotten.
Dangling threads have no satisfying resolution yet. They are useful during drafting and risky near the end of a book.
Questionable resolutions suggest the payoff may not have enough setup or may occur in an odd place.
Abandoned threads are marked as intentionally dropped. This can be right for false leads, character failures or unresolved series questions, but the choice should be conscious.
# How To Use It
Use warnings as prompts, not verdicts. If the story intentionally withholds a thread for ten chapters, keep it. If you forgot the thread existed, add a progress, reveal or resolution event where the draft needs one.
# Related Guides
- [Plot Thread Lanes](/Help/Article/timeline.plotThreadLanes)
- [Story Health Plot Thread Health](/Help/Article/storyHealth.plotThreadHealth)
- [Continuity Warnings](/Help/Article/warnings.overview)

View File

@ -33,7 +33,7 @@
<section class="inspector-section scene-overview-card" data-section-title="Overview" data-section-id="inspector-overview" data-inspector-search-text="@($"{Model.SceneTitle} {povCharacter} {primaryLocation} {timeLabel} {revisionStatus} {string.Join(' ', selectedPurposeLabels)}")"> <section class="inspector-section scene-overview-card" data-section-title="Overview" data-section-id="inspector-overview" data-inspector-search-text="@($"{Model.SceneTitle} {povCharacter} {primaryLocation} {timeLabel} {revisionStatus} {string.Join(' ', selectedPurposeLabels)}")">
<div> <div>
<p class="eyebrow">Working context</p> <p class="eyebrow">Working context</p>
<h3>@(string.IsNullOrWhiteSpace(Model.SceneTitle) ? "Untitled scene" : Model.SceneTitle)</h3> <h3>@(string.IsNullOrWhiteSpace(Model.SceneTitle) ? "Untitled scene" : Model.SceneTitle) <help-icon key="sceneInspector.overview" /></h3>
<p class="muted"> <p class="muted">
@if (Model.Chapter is not null) @if (Model.Chapter is not null)
{ {
@ -109,7 +109,7 @@
<div asp-validation-summary="ModelOnly" class="text-danger"></div> <div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="inspector-section" data-section-title="Timing & Structure" data-section-id="inspector-timing"> <div class="inspector-section" data-section-title="Timing & Structure" data-section-id="inspector-timing">
<h3>Timing & Structure</h3> <h3>Timing & Structure <help-icon key="sceneInspector.time" /></h3>
<div class="row g-2"> <div class="row g-2">
<div class="col-4"> <div class="col-4">
<label asp-for="SceneNumber" class="form-label"></label> <label asp-for="SceneNumber" class="form-label"></label>
@ -152,11 +152,11 @@
<h4 class="inspector-subheading">Time</h4> <h4 class="inspector-subheading">Time</h4>
<div class="row g-2"> <div class="row g-2">
<div class="col-sm-6"> <div class="col-sm-6">
<label asp-for="TimeModeID" class="form-label"></label> <label asp-for="TimeModeID" class="form-label">Time mode <help-icon key="sceneInspector.time" mode="inline" /></label>
<select asp-for="TimeModeID" asp-items="Model.TimeModes" class="form-select form-select-sm"></select> <select asp-for="TimeModeID" asp-items="Model.TimeModes" class="form-select form-select-sm"></select>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<label asp-for="TimeConfidenceID" class="form-label"></label> <label asp-for="TimeConfidenceID" class="form-label">Time confidence <help-icon key="sceneInspector.time" mode="inline" /></label>
<select asp-for="TimeConfidenceID" asp-items="Model.TimeConfidences" class="form-select form-select-sm"></select> <select asp-for="TimeConfidenceID" asp-items="Model.TimeConfidences" class="form-select form-select-sm"></select>
</div> </div>
<div class="col-12"> <div class="col-12">
@ -199,7 +199,7 @@
</div> </div>
<div class="inspector-section" data-section-title="Scene Purpose & Outcome" data-section-id="inspector-purpose"> <div class="inspector-section" data-section-title="Scene Purpose & Outcome" data-section-id="inspector-purpose">
<h3>Purposes</h3> <h3>Purposes <help-icon key="sceneInspector.purpose" /></h3>
<div class="purpose-list inspector-purpose-list"> <div class="purpose-list inspector-purpose-list">
@foreach (var purpose in Model.ScenePurposeTypes) @foreach (var purpose in Model.ScenePurposeTypes)
{ {
@ -227,7 +227,7 @@
</div> </div>
<div class="inspector-section" data-section-title="Scene Metrics" data-section-id="inspector-metrics"> <div class="inspector-section" data-section-title="Scene Metrics" data-section-id="inspector-metrics">
<h3>Scene Metrics</h3> <h3>Scene Metrics <help-icon key="timeline.metrics" /></h3>
@if (!Model.Metrics.Any()) @if (!Model.Metrics.Any())
{ {
<div class="empty-panel compact"> <div class="empty-panel compact">
@ -283,7 +283,7 @@
<!-- Scene foundation continues: notes sit immediately after the main scene save form so timing, purpose and metrics still submit together. --> <!-- Scene foundation continues: notes sit immediately after the main scene save form so timing, purpose and metrics still submit together. -->
<section class="inspector-section writer-notes-section" data-section-title="Scene Notes" data-section-id="inspector-notes"> <section class="inspector-section writer-notes-section" data-section-title="Scene Notes" data-section-id="inspector-notes">
<h3>Scene Notes</h3> <h3>Scene Notes <help-icon key="sceneInspector.notes" /></h3>
@if (!Model.Notes.Any()) @if (!Model.Notes.Any())
{ {
<p class="muted">No working notes yet. Capture drafting thoughts, research reminders, or revision questions as they come up.</p> <p class="muted">No working notes yet. Capture drafting thoughts, research reminders, or revision questions as they come up.</p>
@ -354,7 +354,7 @@
<!-- Characters --> <!-- Characters -->
<section class="inspector-section character-section" data-section-title="Characters" data-section-id="inspector-characters"> <section class="inspector-section character-section" data-section-title="Characters" data-section-id="inspector-characters">
<h3>Characters</h3> <h3>Characters <help-icon key="sceneInspector.characters" /></h3>
@if (!Model.SceneCharacters.Any()) @if (!Model.SceneCharacters.Any())
{ {
<p class="muted">No characters attached to this scene yet. Add the people who appear, are mentioned, or meaningfully affect the scene.</p> <p class="muted">No characters attached to this scene yet. Add the people who appear, are mentioned, or meaningfully affect the scene.</p>
@ -542,7 +542,7 @@
</section> </section>
<section class="inspector-section character-section" data-section-title="Character Attributes" data-section-id="inspector-character-attributes"> <section class="inspector-section character-section" data-section-title="Character Attributes" data-section-id="inspector-character-attributes">
<h3>Character Attributes</h3> <h3>Character Attributes <help-icon key="sceneInspector.characterAttributes" /></h3>
@if (Model.CharacterAttributeEvents.Any()) @if (Model.CharacterAttributeEvents.Any())
{ {
<div class="asset-event-list"> <div class="asset-event-list">
@ -590,7 +590,7 @@
</section> </section>
<section class="inspector-section character-section" data-section-title="Character Knowledge" data-section-id="inspector-character-knowledge"> <section class="inspector-section character-section" data-section-title="Character Knowledge" data-section-id="inspector-character-knowledge">
<h3>Character Knowledge</h3> <h3>Character Knowledge <help-icon key="sceneInspector.knowledge" /></h3>
@if (Model.CharacterKnowledge.Any()) @if (Model.CharacterKnowledge.Any())
{ {
<div class="asset-event-list"> <div class="asset-event-list">
@ -637,7 +637,7 @@
</section> </section>
<section class="inspector-section character-section" data-section-title="Relationship Events" data-section-id="inspector-relationships"> <section class="inspector-section character-section" data-section-title="Relationship Events" data-section-id="inspector-relationships">
<h3>Relationship Events</h3> <h3>Relationship Events <help-icon key="sceneInspector.relationships" /></h3>
@if (Model.RelationshipEvents.Any()) @if (Model.RelationshipEvents.Any())
{ {
<div class="asset-event-list"> <div class="asset-event-list">
@ -685,7 +685,7 @@
<div class="col-12"><select class="form-select form-select-sm" name="RelationshipTypeID" asp-items="Model.RelationshipTypeOptions"><option value="">Relationship type</option></select></div> <div class="col-12"><select class="form-select form-select-sm" name="RelationshipTypeID" asp-items="Model.RelationshipTypeOptions"><option value="">Relationship type</option></select></div>
<div class="col-8"><select class="form-select form-select-sm" name="RelationshipStateID" asp-items="Model.RelationshipStateOptions"></select></div> <div class="col-8"><select class="form-select form-select-sm" name="RelationshipStateID" asp-items="Model.RelationshipStateOptions"></select></div>
<div class="col-4"> <div class="col-4">
<label class="form-label">Intensity <output>5</output></label> <label class="form-label">Intensity <output>5</output> <help-icon key="sceneInspector.fields.relationshipIntensity" mode="inline" /></label>
<input class="form-range" name="Intensity" type="range" min="1" max="10" step="1" value="5" oninput="this.previousElementSibling.querySelector('output').value = this.value" /> <input class="form-range" name="Intensity" type="range" min="1" max="10" step="1" value="5" oninput="this.previousElementSibling.querySelector('output').value = this.value" />
</div> </div>
<div class="col-12"> <div class="col-12">
@ -702,7 +702,7 @@
<!-- Plot and story development --> <!-- Plot and story development -->
<section class="inspector-section thread-events-section" data-section-title="Plot Thread Events" data-section-id="inspector-thread-events"> <section class="inspector-section thread-events-section" data-section-title="Plot Thread Events" data-section-id="inspector-thread-events">
<h3>Plot Thread Events <help-icon key="plotThreads.events" /></h3> <h3>Plot Thread Events <help-icon key="sceneInspector.threads" /></h3>
@if (!Model.ThreadEvents.Any()) @if (!Model.ThreadEvents.Any())
{ {
<p class="muted">No plot thread events attached to this scene yet. Add clues, reveals, promises, payoffs, or reversals when the scene touches a thread.</p> <p class="muted">No plot thread events attached to this scene yet. Add clues, reveals, promises, payoffs, or reversals when the scene touches a thread.</p>
@ -740,7 +740,7 @@
} }
<div class="row g-2"> <div class="row g-2">
<div class="col-12"> <div class="col-12">
<label class="form-label" for="PlotEventTypeID-@threadEvent.ThreadEventID">Event type</label> <label class="form-label" for="PlotEventTypeID-@threadEvent.ThreadEventID">Event type <help-icon key="sceneInspector.fields.threadEventType" mode="inline" /></label>
<select class="form-select form-select-sm" id="PlotEventTypeID-@threadEvent.ThreadEventID" name="PlotEventTypeID" data-plot-event-type> <select class="form-select form-select-sm" id="PlotEventTypeID-@threadEvent.ThreadEventID" name="PlotEventTypeID" data-plot-event-type>
<option value="">Choose event type</option> <option value="">Choose event type</option>
@foreach (var eventType in Model.PlotEventTypeOptions) @foreach (var eventType in Model.PlotEventTypeOptions)
@ -808,7 +808,7 @@
</select> </select>
</div> </div>
<div class="col-12"> <div class="col-12">
<label class="form-label" for="EventTypeID-@threadEvent.ThreadEventID">Marker type</label> <label class="form-label" for="EventTypeID-@threadEvent.ThreadEventID">Marker type <help-icon key="sceneInspector.fields.threadMarkerType" mode="inline" /></label>
<select class="form-select form-select-sm" id="EventTypeID-@threadEvent.ThreadEventID" name="EventTypeID"> <select class="form-select form-select-sm" id="EventTypeID-@threadEvent.ThreadEventID" name="EventTypeID">
@foreach (var markerType in Model.ThreadEventTypeOptions) @foreach (var markerType in Model.ThreadEventTypeOptions)
{ {
@ -882,7 +882,7 @@
</select> </select>
</div> </div>
<div class="col-12"> <div class="col-12">
<label class="form-label" for="EventTypeID">Event type</label> <label class="form-label" for="EventTypeID">Event type <help-icon key="sceneInspector.fields.threadEventType" mode="inline" /></label>
<select class="form-select form-select-sm" id="PlotEventTypeID" name="PlotEventTypeID" data-plot-event-type> <select class="form-select form-select-sm" id="PlotEventTypeID" name="PlotEventTypeID" data-plot-event-type>
<option value="">Choose event type</option> <option value="">Choose event type</option>
@foreach (var eventType in Model.PlotEventTypeOptions) @foreach (var eventType in Model.PlotEventTypeOptions)
@ -929,7 +929,7 @@
</select> </select>
</div> </div>
<div class="col-12"> <div class="col-12">
<label class="form-label" for="EventTypeID">Marker type</label> <label class="form-label" for="EventTypeID">Marker type <help-icon key="sceneInspector.fields.threadMarkerType" mode="inline" /></label>
<select class="form-select form-select-sm" id="EventTypeID" name="EventTypeID" asp-items="Model.ThreadEventTypeOptions"></select> <select class="form-select form-select-sm" id="EventTypeID" name="EventTypeID" asp-items="Model.ThreadEventTypeOptions"></select>
</div> </div>
<div class="col-12"> <div class="col-12">
@ -1014,7 +1014,7 @@
</section> </section>
<section class="inspector-section asset-events-section" data-section-title="Story Assets" data-section-id="inspector-asset-events"> <section class="inspector-section asset-events-section" data-section-title="Story Assets" data-section-id="inspector-asset-events">
<h3>Story Assets</h3> <h3>Story Assets <help-icon key="sceneInspector.assets" /></h3>
@if (!Model.AssetEvents.Any()) @if (!Model.AssetEvents.Any())
{ {
<p class="muted">No asset events attached to this scene yet. Add one when an object, clue, secret, or important item changes here.</p> <p class="muted">No asset events attached to this scene yet. Add one when an object, clue, secret, or important item changes here.</p>
@ -1068,7 +1068,7 @@
<select class="form-select form-select-sm" id="NewAssetKindID" name="NewAssetKindID" asp-items="Model.AssetKindOptions"></select> <select class="form-select form-select-sm" id="NewAssetKindID" name="NewAssetKindID" asp-items="Model.AssetKindOptions"></select>
</div> </div>
<div class="col-12"> <div class="col-12">
<label class="form-label" for="AssetEventTypeID">Event type</label> <label class="form-label" for="AssetEventTypeID">Event type <help-icon key="sceneInspector.assets" mode="inline" /></label>
<select class="form-select form-select-sm" id="AssetEventTypeID" name="AssetEventTypeID" asp-items="Model.AssetEventTypeOptions"></select> <select class="form-select form-select-sm" id="AssetEventTypeID" name="AssetEventTypeID" asp-items="Model.AssetEventTypeOptions"></select>
</div> </div>
<div class="col-6"> <div class="col-6">
@ -1098,7 +1098,7 @@
</section> </section>
<section class="inspector-section asset-events-section" data-section-title="Asset Locations" data-section-id="inspector-asset-locations"> <section class="inspector-section asset-events-section" data-section-title="Asset Locations" data-section-id="inspector-asset-locations">
<h3>Asset Locations</h3> <h3>Asset Locations <help-icon key="sceneInspector.locations" /></h3>
@if (!Model.SceneAssetLocations.Any()) @if (!Model.SceneAssetLocations.Any())
{ {
<p class="muted">No assets have been placed in a location for this scene yet.</p> <p class="muted">No assets have been placed in a location for this scene yet.</p>
@ -1154,7 +1154,7 @@
</section> </section>
<section class="inspector-section asset-events-section" data-section-title="Asset Custody" data-section-id="inspector-asset-custody"> <section class="inspector-section asset-events-section" data-section-title="Asset Custody" data-section-id="inspector-asset-custody">
<h3>Asset Custody</h3> <h3>Asset Custody <help-icon key="sceneInspector.custody" /></h3>
@if (!Model.AssetCustodyEvents.Any()) @if (!Model.AssetCustodyEvents.Any())
{ {
<p class="muted">No custody entries attached to this scene yet.</p> <p class="muted">No custody entries attached to this scene yet.</p>
@ -1193,7 +1193,7 @@
<select class="form-select form-select-sm" id="CustodyStoryAssetID" name="StoryAssetID" asp-items="Model.AssetOptions"></select> <select class="form-select form-select-sm" id="CustodyStoryAssetID" name="StoryAssetID" asp-items="Model.AssetOptions"></select>
</div> </div>
<div class="col-6"> <div class="col-6">
<label class="form-label" for="AssetCustodyEventTypeID">Custody event</label> <label class="form-label" for="AssetCustodyEventTypeID">Custody event <help-icon key="sceneInspector.custody" mode="inline" /></label>
<select class="form-select form-select-sm" id="AssetCustodyEventTypeID" name="AssetCustodyEventTypeID" asp-items="Model.AssetCustodyEventTypeOptions"></select> <select class="form-select form-select-sm" id="AssetCustodyEventTypeID" name="AssetCustodyEventTypeID" asp-items="Model.AssetCustodyEventTypeOptions"></select>
</div> </div>
<div class="col-6"> <div class="col-6">
@ -1219,7 +1219,7 @@
</section> </section>
<section class="inspector-section" data-section-title="Story State" data-section-id="inspector-story-state" data-inspector-search-text="@($"Story State {string.Join(' ', Model.StoryState.Characters.Select(x => $"{x.CharacterName} {x.CurrentLocation} {x.State} {x.LastConfirmed}"))} {string.Join(' ', Model.StoryState.Assets.Select(x => $"{x.AssetName} {x.CurrentHolderOrLocation} {x.State} {x.LastConfirmed}"))}")"> <section class="inspector-section" data-section-title="Story State" data-section-id="inspector-story-state" data-inspector-search-text="@($"Story State {string.Join(' ', Model.StoryState.Characters.Select(x => $"{x.CharacterName} {x.CurrentLocation} {x.State} {x.LastConfirmed}"))} {string.Join(' ', Model.StoryState.Assets.Select(x => $"{x.AssetName} {x.CurrentHolderOrLocation} {x.State} {x.LastConfirmed}"))}")">
<h3>Story State</h3> <h3>Story State <help-icon key="sceneInspector.storyState" /></h3>
<h4 class="inspector-subheading">Characters</h4> <h4 class="inspector-subheading">Characters</h4>
@if (!Model.StoryState.Characters.Any()) @if (!Model.StoryState.Characters.Any())
@ -1289,7 +1289,7 @@
<!-- Planning and workflow --> <!-- Planning and workflow -->
<section class="inspector-section writer-workspace-section" data-section-title="Writer Workspace" data-section-id="inspector-writer"> <section class="inspector-section writer-workspace-section" data-section-title="Writer Workspace" data-section-id="inspector-writer">
<div class="inspector-section-heading"> <div class="inspector-section-heading">
<h3>Writer Workspace</h3> <h3>Writer Workspace <help-icon key="sceneInspector.writer" /></h3>
<a class="btn btn-outline-secondary btn-sm" asp-controller="Writer" asp-action="Chapter" asp-route-id="@Model.ChapterID">Chapter workflow</a> <a class="btn btn-outline-secondary btn-sm" asp-controller="Writer" asp-action="Chapter" asp-route-id="@Model.ChapterID">Chapter workflow</a>
</div> </div>
<form asp-controller="Scenes" asp-action="SaveWorkflow" method="post" class="writer-workspace-form"> <form asp-controller="Scenes" asp-action="SaveWorkflow" method="post" class="writer-workspace-form">
@ -1355,7 +1355,7 @@
</section> </section>
<section class="inspector-section writer-checklist-section" data-section-title="Scene Checklist" data-section-id="inspector-checklist"> <section class="inspector-section writer-checklist-section" data-section-title="Scene Checklist" data-section-id="inspector-checklist">
<h3>Scene Checklist</h3> <h3>Scene Checklist <help-icon key="sceneInspector.checklist" /></h3>
<div class="writer-checklist"> <div class="writer-checklist">
@foreach (var item in Model.ChecklistItems) @foreach (var item in Model.ChecklistItems)
{ {
@ -1387,7 +1387,7 @@
</section> </section>
<section class="inspector-section writer-attachments-section" data-section-title="Attachments / Research" data-section-id="inspector-attachments"> <section class="inspector-section writer-attachments-section" data-section-title="Attachments / Research" data-section-id="inspector-attachments">
<h3>Attachments / Research</h3> <h3>Attachments / Research <help-icon key="sceneInspector.attachments" /></h3>
@if (Model.StorageUsage is not null) @if (Model.StorageUsage is not null)
{ {
<p class="muted">Storage used: @Model.StorageUsage.DisplayLabel</p> <p class="muted">Storage used: @Model.StorageUsage.DisplayLabel</p>
@ -1509,7 +1509,7 @@
<!-- Validation --> <!-- Validation -->
<section class="inspector-section warning-inspector-section" data-section-title="Continuity Warnings" data-section-id="inspector-warnings"> <section class="inspector-section warning-inspector-section" data-section-title="Continuity Warnings" data-section-id="inspector-warnings">
<div class="inspector-section-heading"> <div class="inspector-section-heading">
<h3>Continuity Warnings</h3> <h3>Continuity Warnings <help-icon key="sceneInspector.warnings" /></h3>
@if (Model.SceneID > 0 && Model.ReturnProjectID.HasValue) @if (Model.SceneID > 0 && Model.ReturnProjectID.HasValue)
{ {
<form asp-controller="Warnings" asp-action="ValidateScene" method="post"> <form asp-controller="Warnings" asp-action="ValidateScene" method="post">
@ -1571,7 +1571,7 @@
</section> </section>
<section class="inspector-section scene-dependency-section" data-section-title="Scene Dependencies" data-section-id="inspector-dependencies"> <section class="inspector-section scene-dependency-section" data-section-title="Scene Dependencies" data-section-id="inspector-dependencies">
<h3>Scene Dependencies</h3> <h3>Scene Dependencies <help-icon key="sceneInspector.dependencies" /></h3>
<div class="dependency-columns"> <div class="dependency-columns">
<div> <div>
<p class="eyebrow">This scene depends on</p> <p class="eyebrow">This scene depends on</p>

View File

@ -127,11 +127,11 @@
<div class="workspace-heading"> <div class="workspace-heading">
<div> <div>
<p class="eyebrow">Story timeline</p> <p class="eyebrow">Story timeline</p>
<h1>@Model.Project.ProjectName</h1> <h1>@Model.Project.ProjectName <help-icon key="timeline.overview" /></h1>
</div> </div>
<form method="get" class="timeline-filter"> <form method="get" class="timeline-filter">
<input type="hidden" name="ProjectID" value="@Model.Project.ProjectID" /> <input type="hidden" name="ProjectID" value="@Model.Project.ProjectID" />
<select name="BookID" asp-items="Model.BookOptions" class="form-select"> <select name="BookID" asp-items="Model.BookOptions" class="form-select" aria-label="Book filter">
<option value="">All books</option> <option value="">All books</option>
</select> </select>
<button class="btn btn-outline-primary" type="submit">View</button> <button class="btn btn-outline-primary" type="submit">View</button>
@ -161,10 +161,11 @@
<section class="timeline-control-panel" data-timeline-controls> <section class="timeline-control-panel" data-timeline-controls>
<details class="timeline-filter-drawer"> <details class="timeline-filter-drawer">
<summary>Filters and focus</summary> <summary>Filters and focus</summary>
<help-icon key="timeline.filters" mode="inline" />
<form method="get" class="timeline-filter-grid"> <form method="get" class="timeline-filter-grid">
<input type="hidden" name="ProjectID" value="@Model.Project.ProjectID" /> <input type="hidden" name="ProjectID" value="@Model.Project.ProjectID" />
<div> <div>
<label class="form-label">Book</label> <label class="form-label">Book <help-icon key="timeline.fields.bookFilter" mode="inline" /></label>
<select name="BookID" asp-items="Model.BookOptions" class="form-select form-select-sm"> <select name="BookID" asp-items="Model.BookOptions" class="form-select form-select-sm">
<option value="">All books</option> <option value="">All books</option>
</select> </select>
@ -194,19 +195,19 @@
</select> </select>
</div> </div>
<div> <div>
<label class="form-label">Plot line</label> <label class="form-label">Plot line <help-icon key="timeline.plotThreadLanes" mode="inline" /></label>
<select name="PlotLineID" asp-items="Model.PlotLineOptions" class="form-select form-select-sm"><option value="">Any</option></select> <select name="PlotLineID" asp-items="Model.PlotLineOptions" class="form-select form-select-sm"><option value="">Any</option></select>
</div> </div>
<div> <div>
<label class="form-label">Plot thread</label> <label class="form-label">Plot thread <help-icon key="timeline.plotThreadLanes" mode="inline" /></label>
<select name="PlotThreadID" asp-items="Model.PlotThreadOptions" class="form-select form-select-sm"><option value="">Any</option></select> <select name="PlotThreadID" asp-items="Model.PlotThreadOptions" class="form-select form-select-sm"><option value="">Any</option></select>
</div> </div>
<div> <div>
<label class="form-label">Story asset</label> <label class="form-label">Story asset <help-icon key="timeline.assetEvents" mode="inline" /></label>
<select name="StoryAssetID" asp-items="Model.AssetOptions" class="form-select form-select-sm"><option value="">Any</option></select> <select name="StoryAssetID" asp-items="Model.AssetOptions" class="form-select form-select-sm"><option value="">Any</option></select>
</div> </div>
<div> <div>
<label class="form-label">Character</label> <label class="form-label">Character <help-icon key="timeline.characterAppearances" mode="inline" /></label>
<select name="CharacterID" asp-items="Model.CharacterOptions" class="form-select form-select-sm"><option value="">Any</option></select> <select name="CharacterID" asp-items="Model.CharacterOptions" class="form-select form-select-sm"><option value="">Any</option></select>
</div> </div>
<div> <div>
@ -234,7 +235,7 @@
<select name="POVCharacterID" asp-items="Model.PovCharacterOptions" class="form-select form-select-sm"><option value="">Any</option></select> <select name="POVCharacterID" asp-items="Model.PovCharacterOptions" class="form-select form-select-sm"><option value="">Any</option></select>
</div> </div>
<div> <div>
<label class="form-label">Focus type</label> <label class="form-label">Focus type <help-icon key="timeline.fields.focusType" mode="inline" /></label>
<select name="FocusType" class="form-select form-select-sm"> <select name="FocusType" class="form-select form-select-sm">
<option value="">No focus</option> <option value="">No focus</option>
<option value="character" selected="@(Model.Filter.FocusType == "character")">Character</option> <option value="character" selected="@(Model.Filter.FocusType == "character")">Character</option>
@ -246,7 +247,7 @@
</select> </select>
</div> </div>
<div> <div>
<label class="form-label">Focus ID</label> <label class="form-label">Focus ID <help-icon key="timeline.fields.focusId" mode="inline" /></label>
<input name="FocusID" value="@Model.Filter.FocusID" class="form-control form-control-sm" placeholder="Entity ID" /> <input name="FocusID" value="@Model.Filter.FocusID" class="form-control form-control-sm" placeholder="Entity ID" />
</div> </div>
<div class="timeline-filter-checks"> <div class="timeline-filter-checks">
@ -348,6 +349,7 @@
<details class="timeline-control-group"> <details class="timeline-control-group">
<summary>Saved Views</summary> <summary>Saved Views</summary>
<help-icon key="timeline.savedViews" mode="inline" />
<div class="timeline-preset-panel"> <div class="timeline-preset-panel">
<form asp-action="SavePreset" method="post" data-timeline-preset-form> <form asp-action="SavePreset" method="post" data-timeline-preset-form>
<input type="hidden" name="ProjectID" value="@Model.Project.ProjectID" /> <input type="hidden" name="ProjectID" value="@Model.Project.ProjectID" />
@ -375,7 +377,8 @@
<input type="hidden" name="Filter.ShowWarningsOnly" value="@Model.Filter.ShowWarningsOnly.ToString().ToLowerInvariant()" /> <input type="hidden" name="Filter.ShowWarningsOnly" value="@Model.Filter.ShowWarningsOnly.ToString().ToLowerInvariant()" />
<input type="hidden" name="Filter.IncludeDismissedWarnings" value="@Model.Filter.IncludeDismissedWarnings.ToString().ToLowerInvariant()" /> <input type="hidden" name="Filter.IncludeDismissedWarnings" value="@Model.Filter.IncludeDismissedWarnings.ToString().ToLowerInvariant()" />
<input type="hidden" name="Filter.IncludeIntentionalWarnings" value="@Model.Filter.IncludeIntentionalWarnings.ToString().ToLowerInvariant()" /> <input type="hidden" name="Filter.IncludeIntentionalWarnings" value="@Model.Filter.IncludeIntentionalWarnings.ToString().ToLowerInvariant()" />
<input class="form-control form-control-sm" name="PresetName" placeholder="View name" /> <label class="visually-hidden" for="TimelinePresetName">View name <help-icon key="timeline.fields.savedViewName" mode="inline" /></label>
<input class="form-control form-control-sm" id="TimelinePresetName" name="PresetName" placeholder="View name" />
<button class="btn btn-outline-primary btn-sm" type="submit">Save view</button> <button class="btn btn-outline-primary btn-sm" type="submit">Save view</button>
</form> </form>
@if (Model.ViewPresets.Any()) @if (Model.ViewPresets.Any())
@ -416,6 +419,11 @@
</section> </section>
} }
<section class="timeline-scroll-hint" data-timeline-scroll-hint hidden>
<span>Tip: Hold Shift while scrolling to move left and right through the timeline.</span>
<button type="button" class="btn btn-outline-secondary btn-sm" data-timeline-scroll-hint-dismiss>Dismiss</button>
</section>
<details class="timeline-drag-palette" data-drag-palette> <details class="timeline-drag-palette" data-drag-palette>
<summary>Drag Sources</summary> <summary>Drag Sources</summary>
<div class="drag-chip-group"> <div class="drag-chip-group">
@ -597,6 +605,7 @@ else
{ {
<div class="timeline-section-header" data-collapse-target="scene-cards"> <div class="timeline-section-header" data-collapse-target="scene-cards">
<button type="button" data-collapse-toggle="scene-cards">Scene Cards</button> <button type="button" data-collapse-toggle="scene-cards">Scene Cards</button>
<help-icon key="timeline.sceneCards" mode="inline" />
<span>@Model.OrderedScenes.Count scene@(Model.OrderedScenes.Count == 1 ? "" : "s")</span> <span>@Model.OrderedScenes.Count scene@(Model.OrderedScenes.Count == 1 ? "" : "s")</span>
</div> </div>
<div data-collapse-body="scene-cards"> <div data-collapse-body="scene-cards">
@ -740,6 +749,7 @@ else
<div class="metric-timeline-board" data-timeline-section="metrics" style="--scene-count:@timelineColumns.Count"> <div class="metric-timeline-board" data-timeline-section="metrics" style="--scene-count:@timelineColumns.Count">
<div class="lane-board-heading metric-lane-board-heading"> <div class="lane-board-heading metric-lane-board-heading">
<button type="button" data-collapse-toggle="metrics">Metric Shape</button> <button type="button" data-collapse-toggle="metrics">Metric Shape</button>
<help-icon key="timeline.metrics" mode="inline" />
<small>@Model.OrderedScenes.Count scene@(Model.OrderedScenes.Count == 1 ? "" : "s")</small> <small>@Model.OrderedScenes.Count scene@(Model.OrderedScenes.Count == 1 ? "" : "s")</small>
</div> </div>
<div data-collapse-body="metrics"> <div data-collapse-body="metrics">
@ -758,6 +768,7 @@ else
<div class="timeline-metric-edit-toolbar" data-timeline-metric-edit-toolbar> <div class="timeline-metric-edit-toolbar" data-timeline-metric-edit-toolbar>
@Html.AntiForgeryToken() @Html.AntiForgeryToken()
<span class="timeline-metric-edit-status" data-edit-metric-status>Show only one metric line to edit its curve.</span> <span class="timeline-metric-edit-status" data-edit-metric-status>Show only one metric line to edit its curve.</span>
<help-icon key="timeline.fields.metricEdit" mode="inline" />
</div> </div>
</div> </div>
<div class="metric-timeline-row"> <div class="metric-timeline-row">
@ -823,7 +834,9 @@ else
<svg class="plot-lane-svg-overlay" data-plot-line-svg aria-hidden="true"></svg> <svg class="plot-lane-svg-overlay" data-plot-line-svg aria-hidden="true"></svg>
<div class="lane-board-heading plot-lane-board-heading"> <div class="lane-board-heading plot-lane-board-heading">
<button type="button" data-collapse-toggle="plot-lines">Plot line lanes</button> <button type="button" data-collapse-toggle="plot-lines">Plot line lanes</button>
<help-icon key="timeline.plotThreadLanes" mode="inline" />
<small>Thread event markers by scene</small> <small>Thread event markers by scene</small>
<help-icon key="timeline.threadHealth" mode="inline" />
</div> </div>
<div data-collapse-body="plot-lines"> <div data-collapse-body="plot-lines">
@foreach (var group in Model.PlotLanes.GroupBy(x => x.PlotLine.PlotLineTypeName).OrderBy(x => x.Key)) @foreach (var group in Model.PlotLanes.GroupBy(x => x.PlotLine.PlotLineTypeName).OrderBy(x => x.Key))
@ -899,6 +912,7 @@ else
<div class="asset-lane-board" data-timeline-section="assets" style="--scene-count:@timelineColumns.Count"> <div class="asset-lane-board" data-timeline-section="assets" style="--scene-count:@timelineColumns.Count">
<div class="lane-board-heading asset-lane-board-heading"> <div class="lane-board-heading asset-lane-board-heading">
<button type="button" data-collapse-toggle="assets">Story asset lanes</button> <button type="button" data-collapse-toggle="assets">Story asset lanes</button>
<help-icon key="timeline.assetEvents" mode="inline" />
<small>Asset event markers by scene</small> <small>Asset event markers by scene</small>
</div> </div>
<div data-collapse-body="assets"> <div data-collapse-body="assets">
@ -966,6 +980,7 @@ else
<div class="character-lane-board" data-timeline-section="characters" style="--scene-count:@timelineColumns.Count"> <div class="character-lane-board" data-timeline-section="characters" style="--scene-count:@timelineColumns.Count">
<div class="lane-board-heading character-lane-board-heading"> <div class="lane-board-heading character-lane-board-heading">
<button type="button" data-collapse-toggle="characters">Character appearances</button> <button type="button" data-collapse-toggle="characters">Character appearances</button>
<help-icon key="timeline.characterAppearances" mode="inline" />
<small>All project characters, grouped by role and activity</small> <small>All project characters, grouped by role and activity</small>
</div> </div>
<div data-collapse-body="characters"> <div data-collapse-body="characters">

View File

@ -2437,6 +2437,22 @@ body.timeline-inspector-resizing {
background: rgba(47, 111, 99, 0.08); background: rgba(47, 111, 99, 0.08);
} }
.timeline-scroll-hint {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
border: 1px solid rgba(47, 111, 99, 0.22);
border-radius: 10px;
margin-bottom: 16px;
padding: 10px 12px;
background: rgba(47, 111, 99, 0.08);
}
.timeline-scroll-hint[hidden] {
display: none;
}
.timeline-scene-card.filter-dim, .timeline-scene-card.filter-dim,
.timeline-scene-card.focus-dim, .timeline-scene-card.focus-dim,
.lane-dim { .lane-dim {

File diff suppressed because one or more lines are too long

View File

@ -1205,6 +1205,7 @@
const densityKey = "plotline.timeline.density"; const densityKey = "plotline.timeline.density";
const zoomKey = "plotline.timeline.zoom"; const zoomKey = "plotline.timeline.zoom";
const scrollKey = "plotline.timeline.pending-scroll"; const scrollKey = "plotline.timeline.pending-scroll";
const horizontalHintKey = "plotline.timeline.horizontalScrollHint.seen";
const drawerWidthKey = "plotline.timeline.inspectorWidth"; const drawerWidthKey = "plotline.timeline.inspectorWidth";
const scrollContainerSelector = [ const scrollContainerSelector = [
".timeline-shell", ".timeline-shell",
@ -1233,6 +1234,74 @@
const getScrollContainers = () => [...root.querySelectorAll(scrollContainerSelector)]; const getScrollContainers = () => [...root.querySelectorAll(scrollContainerSelector)];
const setupHorizontalScrollHint = () => {
const hint = document.querySelector("[data-timeline-scroll-hint]");
if (!hint) {
return;
}
const dismissButton = hint.querySelector("[data-timeline-scroll-hint-dismiss]");
const readSeen = () => {
try {
return localStorage.getItem(horizontalHintKey) === "true";
} catch {
return false;
}
};
const markSeen = () => {
hint.hidden = true;
try {
localStorage.setItem(horizontalHintKey, "true");
} catch {
// The hint can still disappear for this page view if storage is unavailable.
}
};
if (readSeen()) {
hint.hidden = true;
return;
}
hint.hidden = false;
dismissButton?.addEventListener("click", markSeen);
let isArmed = false;
window.setTimeout(() => {
isArmed = true;
containers.forEach(rememberPosition);
}, 800);
const knownLeft = new WeakMap();
const rememberPosition = (container) => knownLeft.set(container, container.scrollLeft);
const detectHorizontalScroll = (container) => {
if (!isArmed) {
rememberPosition(container);
return;
}
const previous = knownLeft.get(container) ?? container.scrollLeft;
if (Math.abs(container.scrollLeft - previous) > 4) {
markSeen();
return;
}
rememberPosition(container);
};
const containers = [workspace, ...getScrollContainers()];
containers.forEach((container) => {
rememberPosition(container);
container.addEventListener("wheel", (event) => {
if (event.shiftKey && Math.abs(event.deltaY) > Math.abs(event.deltaX)) {
event.preventDefault();
container.scrollLeft += event.deltaY;
markSeen();
}
}, { passive: false });
container.addEventListener("scroll", () => detectHorizontalScroll(container), { passive: true });
});
};
const drawerWidthBounds = () => { const drawerWidthBounds = () => {
const availableWidth = root.getBoundingClientRect().width || window.innerWidth; const availableWidth = root.getBoundingClientRect().width || window.innerWidth;
const minimum = Math.min(420, Math.max(320, availableWidth - 360)); const minimum = Math.min(420, Math.max(320, availableWidth - 360));
@ -1255,6 +1324,8 @@
window.addEventListener("resize", () => applyDrawerWidth(localStorage.getItem(drawerWidthKey))); window.addEventListener("resize", () => applyDrawerWidth(localStorage.getItem(drawerWidthKey)));
} }
setupHorizontalScrollHint();
inspectorResizer?.addEventListener("pointerdown", (event) => { inspectorResizer?.addEventListener("pointerdown", (event) => {
event.preventDefault(); event.preventDefault();
document.body.classList.add("timeline-inspector-resizing"); document.body.classList.add("timeline-inspector-resizing");

File diff suppressed because one or more lines are too long