Files
plotzilla/frontend/src/style.css
T

1580 lines
29 KiB
CSS

/* Dark, blue-toned theme. The editor reproduces the printed page: 8.5in
wide (8.27in on A4), Courier 12pt, 1.5in left margin. Indents match
internal/layout so text wraps exactly like the PDF. 1ch = one Courier
character = 0.1in. */
:root {
--bg: #070c18;
--bg-2: #0b1324;
--surface: #0f1a2f;
--surface-2: #14223c;
/* Floating layers over the script (menus, suggestions, status bar) are
opaque: script text showing through them is unreadable. */
--popover: #13203a;
--border: rgb(120 160 255 / 0.1);
--border-strong: rgb(120 160 255 / 0.18);
--text: #dbe5f7;
--text-2: #a9b8d4;
--muted: #6a7fa3;
--accent: #4f8dff;
--accent-2: #7cb0ff;
--accent-soft: rgb(79 141 255 / 0.14);
--glow: 0 0 0 1px rgb(79 141 255 / 0.35), 0 6px 24px rgb(40 100 255 / 0.25);
--ok: #5eead4;
--warn: #fbbf24;
--error: #f87171;
/* Find: every match, and the selected one. */
--match: rgb(251 191 36 / 0.22);
--match-active: rgb(251 191 36 / 0.5);
--paper: #0e1830;
--paper-edge: rgb(124 176 255 / 0.08);
--paper-text: #e3ebf9;
--placeholder: #3b4d72;
--selection: rgb(79 141 255 / 0.35);
--gap: 36px;
--t-scene: #60a5fa;
--t-action: #94a3b8;
--t-character: #a5b4fc;
--t-parenthetical: #7dd3fc;
--t-dialogue: #38bdf8;
--t-transition: #818cf8;
--t-shot: #93c5fd;
--t-intertitle: #f0abfc;
--t-centered: #c7d2fe;
--t-section: #c4b5fd;
--t-synopsis: #8aa0c4;
/* Writer's notes (never printed). */
--note: #fde68a;
--note-bg: rgb(251 191 36 / 0.12);
/* Revision colours: the industry paper colours, as a dot or a text tint. */
--rev-white: #e5e7eb;
--rev-white-bg: rgb(229 231 235 / 0.16);
--rev-blue: #60a5fa;
--rev-blue-bg: rgb(96 165 250 / 0.2);
--rev-pink: #f9a8d4;
--rev-pink-bg: rgb(249 168 212 / 0.18);
--rev-yellow: #fde047;
--rev-yellow-bg: rgb(253 224 71 / 0.16);
--rev-green: #86efac;
--rev-green-bg: rgb(134 239 172 / 0.16);
--rev-goldenrod: #eab308;
--rev-goldenrod-bg: rgb(234 179 8 / 0.18);
--rev-buff: #e7c9a0;
--rev-buff-bg: rgb(231 201 160 / 0.18);
--rev-salmon: #fa8072;
--rev-salmon-bg: rgb(250 128 114 / 0.18);
--rev-cherry: #f43f5e;
--rev-cherry-bg: rgb(244 63 94 / 0.2);
--radius: 10px;
--ease: cubic-bezier(0.2, 0.8, 0.2, 1);
--script-font: 'Courier Prime', 'Courier Final Draft', 'Courier New', 'Nimbus Mono PS', 'Liberation Mono', monospace;
--ui-font: 'Inter', 'Cantarell', system-ui, 'Noto Sans', sans-serif;
color-scheme: dark;
}
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
margin: 0;
}
/* The window is frameless and transparent: the body is the window, with
rounded corners (square when maximised, or when no compositor makes the
window transparent). */
html {
background: transparent;
}
body {
display: flex;
flex-direction: column;
background:
radial-gradient(1200px 600px at 70% -10%, rgb(40 90 220 / 0.18), transparent 60%),
radial-gradient(900px 500px at -10% 110%, rgb(30 60 160 / 0.14), transparent 60%),
var(--bg);
color: var(--text);
font: 13px/1.45 var(--ui-font);
overflow: hidden;
user-select: none;
-webkit-font-smoothing: antialiased;
border-radius: 12px;
box-shadow: inset 0 0 0 1px rgb(150 180 255 / 0.12);
}
body.maximized {
border-radius: 0;
box-shadow: none;
}
body.opaque {
border-radius: 0;
}
button,
select,
input,
textarea {
font: inherit;
color: inherit;
}
svg {
width: 18px;
height: 18px;
display: block;
}
kbd {
font: 11px var(--ui-font);
padding: 1px 5px;
border-radius: 4px;
background: var(--surface-2);
border: 1px solid var(--border-strong);
color: var(--text-2);
}
* {
scrollbar-width: thin;
scrollbar-color: rgb(120 160 255 / 0.18) transparent;
}
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-thumb {
background: rgb(120 160 255 / 0.14);
border-radius: 10px;
border: 3px solid transparent;
background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover {
background-color: rgb(120 160 255 / 0.28);
}
::-webkit-scrollbar-track {
background: transparent;
}
/* -------------------------------------------------------------- topbar */
.topbar {
display: flex;
align-items: center;
gap: 18px;
height: 54px;
padding: 0 14px 0 18px;
background: linear-gradient(to bottom, rgb(15 26 47 / 0.9), rgb(11 19 36 / 0.75));
border-bottom: 1px solid var(--border);
backdrop-filter: blur(14px);
position: relative;
z-index: 5;
transition: opacity 0.35s var(--ease);
--wails-draggable: drag;
}
.topbar button,
.topbar input,
.menu {
--wails-draggable: no-drag;
}
.topbar > * {
transition: opacity 0.2s;
}
/* Unfocused window: dim the header bar, as GTK header bars do. */
body.backdrop .topbar > * {
opacity: 0.55;
}
/* Window buttons, Adwaita style: small round buttons with a soft fill. */
.win-controls {
display: flex;
align-items: center;
gap: 12px;
}
.win-controls[hidden] {
display: none;
}
.win-button {
display: grid;
place-items: center;
width: 24px;
height: 24px;
padding: 0;
border: 0;
border-radius: 50%;
color: var(--text);
background: rgb(150 180 255 / 0.12);
cursor: pointer;
transition: background 0.15s, transform 0.1s;
}
.win-button svg {
width: 16px;
height: 16px;
stroke-width: 2;
}
.win-button:hover {
background: rgb(150 180 255 / 0.22);
}
.win-button:active {
background: rgb(150 180 255 / 0.3);
transform: scale(0.94);
}
.brand {
display: flex;
align-items: center;
gap: 8px;
font-weight: 700;
font-size: 15px;
letter-spacing: 0.01em;
}
/* The application icon (frontend/public/favicon.svg), which draws its own
rounded tile. */
.brand .logo {
width: 30px;
height: 30px;
border-radius: 7px;
box-shadow: 0 4px 14px rgb(59 130 246 / 0.4);
}
.doc {
display: flex;
align-items: center;
gap: 10px;
min-width: 0;
padding-left: 16px;
border-left: 1px solid var(--border);
}
.doc-name {
color: var(--text-2);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 280px;
}
.save-state {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 11.5px;
color: var(--muted);
padding: 3px 10px;
border-radius: 999px;
background: rgb(255 255 255 / 0.03);
border: 1px solid var(--border);
transition: color 0.3s, border-color 0.3s;
}
.save-state:empty {
display: none;
}
.save-state::before {
content: '';
width: 6px;
height: 6px;
border-radius: 50%;
background: currentColor;
transition: background 0.3s;
}
.save-state[data-state='saved'] {
color: var(--ok);
}
.save-state[data-state='dirty'] {
color: var(--warn);
}
.save-state[data-state='saving'],
.save-state[data-state='draft'] {
color: var(--accent-2);
}
.save-state[data-state='saving']::before {
animation: pulse 0.9s ease-in-out infinite;
}
@keyframes pulse {
50% {
opacity: 0.25;
}
}
.spacer {
flex: 1;
}
.tools {
display: flex;
align-items: center;
gap: 6px;
}
.tools .group {
display: flex;
align-items: center;
gap: 2px;
padding: 3px;
border-radius: 12px;
background: rgb(255 255 255 / 0.025);
border: 1px solid var(--border);
}
.tools button {
position: relative;
display: grid;
place-items: center;
height: 32px;
min-width: 32px;
padding: 0 7px;
border: 0;
border-radius: 9px;
background: transparent;
color: var(--text-2);
cursor: pointer;
transition: background 0.18s var(--ease), color 0.18s var(--ease), transform 0.12s var(--ease);
}
.tools button:hover {
background: var(--accent-soft);
color: var(--text);
}
.tools button:active {
transform: scale(0.94);
}
.tools button.on {
color: var(--accent-2);
background: var(--accent-soft);
}
.type-button {
display: flex !important;
align-items: center;
gap: 8px;
min-width: 150px !important;
padding: 0 10px !important;
font-weight: 500;
color: var(--text) !important;
}
.type-button .chev {
margin-left: auto;
color: var(--muted);
}
.type-button .chev svg {
width: 14px;
height: 14px;
}
.type-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--dot, var(--t-action));
box-shadow: 0 0 10px var(--dot, var(--t-action));
flex-shrink: 0;
}
/* Tooltips */
[data-tip]::after {
content: attr(data-tip);
position: absolute;
top: calc(100% + 10px);
left: 50%;
translate: -50% -4px;
padding: 5px 9px;
border-radius: 7px;
white-space: nowrap;
font-size: 11.5px;
font-weight: 500;
color: var(--text);
background: #1a2a4a;
border: 1px solid var(--border-strong);
box-shadow: 0 8px 24px rgb(0 0 0 / 0.4);
opacity: 0;
pointer-events: none;
transition: opacity 0.15s, translate 0.15s var(--ease);
transition-delay: 0s;
z-index: 20;
}
[data-tip]:hover::after {
opacity: 1;
translate: -50% 0;
transition-delay: 0.45s;
}
.tools .group:last-child [data-tip]::after {
left: auto;
right: 0;
translate: 0 -4px;
}
.tools .group:last-child [data-tip]:hover::after {
translate: 0 0;
}
/* ----------------------------------------------------------------- menu */
.menu {
position: fixed;
z-index: 30;
margin: 0;
padding: 6px;
list-style: none;
min-width: 230px;
border-radius: 12px;
background: var(--popover);
border: 1px solid var(--border-strong);
box-shadow: 0 18px 48px rgb(0 0 0 / 0.5);
animation: pop 0.16s var(--ease);
}
.menu li {
display: flex;
align-items: center;
gap: 10px;
padding: 7px 10px;
border-radius: 8px;
cursor: pointer;
color: var(--text-2);
}
.menu li:hover,
.menu li.active {
background: var(--accent-soft);
color: var(--text);
}
.menu li kbd {
margin-left: auto;
}
.menu[hidden] {
display: none;
}
.menu li.sep {
height: 1px;
margin: 5px 4px;
padding: 0;
background: var(--border-strong);
cursor: default;
}
.menu li.disabled {
color: var(--muted);
cursor: default;
}
.menu li.disabled:hover {
background: none;
color: var(--muted);
}
.menu li.strong {
font-weight: 600;
color: var(--text);
}
.menu li .check {
width: 16px;
flex-shrink: 0;
color: var(--accent-2);
}
.menu li .check svg {
width: 16px;
height: 16px;
}
/* Popup menus follow the pointer; the type menu keeps its fixed width. */
.menu.popup {
min-width: 200px;
max-width: 380px;
}
@keyframes pop {
from {
opacity: 0;
transform: translateY(-4px) scale(0.98);
}
}
/* ----------------------------------------------------------------- main */
.main {
flex: 1;
display: flex;
min-height: 0;
}
.navigator {
width: 280px;
flex-shrink: 0;
display: flex;
flex-direction: column;
background: rgb(11 19 36 / 0.6);
border-right: 1px solid var(--border);
transition: margin 0.35s var(--ease), opacity 0.35s var(--ease);
}
body.no-navigator .navigator,
body.focus-mode .navigator {
margin-left: -280px;
opacity: 0;
pointer-events: none;
}
.nav-head {
display: flex;
align-items: center;
justify-content: space-between;
padding: 18px 18px 10px;
}
.nav-head h2 {
margin: 0;
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.count:empty {
display: none;
}
.count {
font-size: 11px;
color: var(--muted);
padding: 1px 8px;
border-radius: 999px;
background: var(--accent-soft);
}
#scene-list {
flex: 1;
overflow-y: auto;
list-style: none;
margin: 0;
padding: 0 10px 12px;
}
#scene-list li {
display: grid;
grid-template-columns: 30px 1fr auto;
align-items: center;
gap: 10px;
padding: 8px 10px;
margin-bottom: 2px;
border-radius: 10px;
cursor: pointer;
color: var(--text-2);
transition: background 0.18s var(--ease), color 0.18s var(--ease);
}
#scene-list li:hover {
background: rgb(255 255 255 / 0.035);
color: var(--text);
}
#scene-list li.active {
background: linear-gradient(90deg, rgb(79 141 255 / 0.2), rgb(79 141 255 / 0.05));
color: var(--text);
box-shadow: inset 2px 0 0 var(--accent);
}
#scene-list .num {
display: grid;
place-items: center;
height: 22px;
border-radius: 7px;
font-size: 11px;
font-weight: 600;
color: var(--accent-2);
background: var(--accent-soft);
font-variant-numeric: tabular-nums;
}
#scene-list .text {
font-size: 12px;
font-weight: 500;
letter-spacing: 0.02em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#scene-list .page {
font-size: 11px;
color: var(--muted);
font-variant-numeric: tabular-nums;
}
/* Outline: sections group the scenes, synopses sit under them. */
#scene-list li.nav-section,
#scene-list li.nav-synopsis {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#scene-list li.nav-section {
margin-top: 8px;
padding: 8px 10px 6px;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--t-section);
}
#scene-list li.nav-section[data-level='2'] {
padding-left: 20px;
}
#scene-list li.nav-section[data-level='3'] {
padding-left: 30px;
}
#scene-list li.nav-synopsis {
margin-top: -4px;
padding: 0 10px 8px 50px;
font-size: 11.5px;
font-style: italic;
color: var(--muted);
}
.empty[hidden] {
display: none;
}
.empty {
margin: 4px 18px 12px;
color: var(--muted);
font-size: 12px;
line-height: 1.7;
}
.nav-foot {
padding: 14px 18px;
border-top: 1px solid var(--border);
}
.switch {
display: flex;
align-items: center;
gap: 10px;
cursor: pointer;
color: var(--text-2);
font-size: 12px;
}
.switch input {
display: none;
}
.switch .track {
position: relative;
width: 32px;
height: 18px;
border-radius: 999px;
background: var(--surface-2);
border: 1px solid var(--border-strong);
transition: background 0.2s var(--ease);
}
.switch .thumb {
position: absolute;
top: 2px;
left: 2px;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--muted);
transition: transform 0.22s var(--ease), background 0.22s;
}
.switch input:checked + .track {
background: var(--accent);
border-color: var(--accent);
}
.switch input:checked + .track .thumb {
transform: translateX(14px);
background: #fff;
}
.workspace {
position: relative;
flex: 1;
min-width: 0;
display: flex;
}
.scroller {
flex: 1;
overflow: auto;
padding: 40px 24px 50vh;
scroll-behavior: smooth;
}
/* ------------------------------------------------------------------ hud */
.hud {
position: absolute;
left: 50%;
bottom: 18px;
translate: -50% 0;
display: flex;
align-items: center;
gap: 12px;
padding: 7px 16px;
border-radius: 999px;
font-size: 12px;
color: var(--text-2);
background: var(--popover);
border: 1px solid var(--border-strong);
box-shadow: 0 12px 36px rgb(0 0 0 / 0.45);
white-space: nowrap;
transition: opacity 0.35s var(--ease), translate 0.35s var(--ease);
font-variant-numeric: tabular-nums;
}
.hud .sep {
width: 1px;
height: 14px;
background: var(--border-strong);
}
.hud-type {
display: flex;
align-items: center;
gap: 7px;
font-weight: 600;
color: var(--text);
}
.hud-type::before {
content: '';
width: 7px;
height: 7px;
border-radius: 50%;
background: var(--dot, var(--t-action));
box-shadow: 0 0 8px var(--dot, var(--t-action));
}
.hud-hint {
color: var(--muted);
white-space: pre;
}
.hud-rev {
display: flex;
align-items: center;
gap: 7px;
}
.hud-rev[hidden] {
display: none;
}
.hud-rev::before {
content: '';
width: 7px;
height: 7px;
border-radius: 50%;
background: var(--dot, var(--muted));
}
/* The bar stays in place, invisible and over the page, so hovering the top
edge brings it back. */
body.focus-mode .topbar {
opacity: 0;
margin-bottom: -54px;
}
body.focus-mode .topbar:hover {
opacity: 1;
}
body.focus-mode .hud {
opacity: 0;
translate: -50% 8px;
}
body.focus-mode .hud:hover {
opacity: 1;
translate: -50% 0;
}
/* --------------------------------------------------------------- search */
.search {
position: absolute;
top: 14px;
right: 22px;
z-index: 4;
display: flex;
align-items: flex-start;
gap: 4px;
padding: 6px;
border-radius: 12px;
background: var(--popover);
border: 1px solid var(--border-strong);
box-shadow: 0 18px 48px rgb(0 0 0 / 0.5);
animation: pop 0.16s var(--ease);
}
.search[hidden] {
display: none;
}
.search-fields {
display: flex;
flex-direction: column;
gap: 6px;
}
.search-row {
display: flex;
align-items: center;
gap: 2px;
}
.search[data-mode='find'] .replace-row {
display: none;
}
.search input {
width: 250px;
height: 30px;
margin-right: 4px;
padding: 0 10px;
border: 1px solid var(--border-strong);
border-radius: 8px;
background: var(--bg-2);
outline: none;
user-select: text;
transition: border-color 0.18s, box-shadow 0.18s;
}
.search input:focus {
border-color: var(--accent);
box-shadow: 0 0 0 3px var(--accent-soft);
}
.search[data-state='none'] #search-input {
border-color: var(--error);
}
/* The count sits inside the find field, on its right edge. */
.search-count {
min-width: 64px;
margin-left: -78px;
margin-right: 14px;
font-size: 11.5px;
text-align: right;
color: var(--muted);
pointer-events: none;
font-variant-numeric: tabular-nums;
}
.search[data-state='none'] .search-count {
color: var(--error);
}
.search input#search-input {
padding-right: 78px;
}
.search button {
position: relative;
display: grid;
place-items: center;
height: 30px;
min-width: 30px;
padding: 0 6px;
border: 0;
border-radius: 8px;
background: transparent;
color: var(--text-2);
cursor: pointer;
transition: background 0.18s var(--ease), color 0.18s var(--ease), transform 0.12s var(--ease);
}
.search button svg {
width: 17px;
height: 17px;
}
.search button:hover {
background: var(--accent-soft);
color: var(--text);
}
.search button:active {
transform: scale(0.94);
}
.search button.on {
color: var(--accent-2);
background: var(--accent-soft);
}
.search button:focus-visible {
outline: 2px solid var(--accent-2);
outline-offset: 1px;
}
.search .text-button {
padding: 0 12px;
font-size: 12px;
font-weight: 500;
border: 1px solid var(--border-strong);
}
.search-toggle svg {
transition: transform 0.2s var(--ease);
}
.search[data-mode='replace'] .search-toggle svg {
transform: rotate(90deg);
}
.search .sep {
width: 1px;
height: 18px;
margin: 0 4px;
background: var(--border-strong);
}
/* Tooltips of the search bar open below it, aligned to the right edge. */
.search [data-tip]::after {
left: auto;
right: 0;
translate: 0 -4px;
}
.search [data-tip]:hover::after {
translate: 0 0;
}
.search-match {
background: var(--match);
border-radius: 2px;
}
.search-match.active {
background: var(--match-active);
box-shadow: 0 0 0 1px var(--warn);
}
/* ------------------------------------------------------------ spelling */
.misspelled {
text-decoration: underline wavy var(--error);
text-decoration-skip-ink: none;
text-underline-offset: 3px;
}
/* ------------------------------------------------------ notes, revisions */
.note {
color: var(--note);
background: var(--note-bg);
border-radius: 3px;
text-transform: none;
font-style: italic;
}
.rev {
background: var(--rev-bg);
border-radius: 2px;
}
.rev[data-color='white'] {
--rev-bg: var(--rev-white-bg);
}
.rev[data-color='blue'] {
--rev-bg: var(--rev-blue-bg);
}
.rev[data-color='pink'] {
--rev-bg: var(--rev-pink-bg);
}
.rev[data-color='yellow'] {
--rev-bg: var(--rev-yellow-bg);
}
.rev[data-color='green'] {
--rev-bg: var(--rev-green-bg);
}
.rev[data-color='goldenrod'] {
--rev-bg: var(--rev-goldenrod-bg);
}
.rev[data-color='buff'] {
--rev-bg: var(--rev-buff-bg);
}
.rev[data-color='salmon'] {
--rev-bg: var(--rev-salmon-bg);
}
.rev[data-color='cherry'] {
--rev-bg: var(--rev-cherry-bg);
}
/* ---------------------------------------------------------------- paper */
/* The text is 6in wide on every paper size; the right margin takes the rest. */
.paper {
--page-width: 8.5in;
width: var(--page-width);
min-height: 11in;
margin: 0 auto;
padding: 1in calc(var(--page-width) - 7.5in) 1in 1.5in;
background: var(--paper);
color: var(--paper-text);
border-radius: 4px;
box-shadow:
0 0 0 1px var(--paper-edge),
0 30px 80px rgb(0 0 0 / 0.45),
0 0 120px rgb(40 100 255 / 0.06);
user-select: text;
animation: rise 0.5s var(--ease);
}
@keyframes rise {
from {
opacity: 0;
transform: translateY(10px);
}
}
.ProseMirror {
font-family: var(--script-font);
font-size: 12pt;
line-height: 12pt;
outline: none;
counter-reset: scene;
caret-color: var(--accent-2);
}
.ProseMirror ::selection {
background: var(--selection);
}
.el {
margin: 12pt 0 0;
position: relative;
min-height: 12pt;
}
.ProseMirror > .el:first-child,
.page-break + .el,
.page-break + .dual {
margin-top: 0;
}
.el-scene {
margin-top: 24pt;
width: 60ch;
text-transform: uppercase;
counter-increment: scene;
color: #f4f7ff;
letter-spacing: 0.01em;
}
.el-scene::before {
content: counter(scene);
position: absolute;
left: -0.85in;
width: 0.5in;
text-align: right;
color: var(--muted);
font-weight: 400;
font-size: 10pt;
}
.el-scene[data-scene-number]::before {
content: attr(data-scene-number);
}
.el-action {
width: 60ch;
}
.el-character {
margin-left: 2.2in;
width: 38ch;
text-transform: uppercase;
--indent: 2.2in;
}
.el-parenthetical {
margin-top: 0;
margin-left: 1.6in;
width: 25ch;
padding-left: 1ch;
text-indent: -1ch;
color: var(--text-2);
--indent: calc(1.6in + 1ch);
}
.el-dialogue {
margin-top: 0;
margin-left: 1in;
width: 35ch;
--indent: 1in;
}
.el-transition {
width: 60ch;
text-align: right;
text-transform: uppercase;
}
.el-centered {
width: 60ch;
text-align: center;
}
.el-shot {
width: 60ch;
text-transform: uppercase;
}
.paper[data-paper='a4'] {
--page-width: 8.27in;
min-height: 11.69in;
}
.el-intertitle {
width: 60ch;
text-align: center;
text-transform: uppercase;
}
/* Outline elements are not printed: their marker sits in the margin. */
.el-section {
margin-top: 24pt;
width: 60ch;
color: var(--t-section);
font-weight: 700;
}
.el-synopsis {
width: 60ch;
color: var(--t-synopsis);
font-style: italic;
}
.el-section::before,
.el-synopsis::before {
content: '#';
position: absolute;
left: -0.85in;
width: 0.5in;
text-align: right;
color: var(--muted);
font-weight: 400;
font-style: normal;
}
.el-section[data-level='2']::before {
content: '##';
}
.el-section[data-level='3']::before,
.el-section[data-level='4']::before,
.el-section[data-level='5']::before,
.el-section[data-level='6']::before {
content: '###';
}
.el-synopsis::before {
content: '=';
}
/* Dual dialogue: two columns starting 1.5in and 4.5in from the page edge. */
.dual {
display: grid;
grid-template-columns: 30ch 30ch;
margin-top: 12pt;
position: relative;
}
.dual::before {
content: '';
position: absolute;
left: -0.25in;
top: 0;
bottom: 0;
width: 2px;
border-radius: 2px;
background: linear-gradient(var(--accent), transparent);
opacity: 0.5;
}
.dual-col > .el:first-child {
margin-top: 0;
}
.dual .el-character {
margin-left: 10ch;
width: 20ch;
}
.dual .el-parenthetical {
margin-left: 3ch;
width: 21ch;
}
.dual .el-dialogue {
margin-left: 0;
width: 27ch;
}
.dual-col:last-child .el-dialogue {
width: 28ch;
}
/* Placeholder naming the element type of the empty line under the cursor. */
.is-empty::after {
content: attr(data-placeholder);
position: absolute;
top: 0;
left: 0;
right: 0;
color: var(--placeholder);
font-style: italic;
font-weight: 400;
text-transform: none;
text-indent: 0;
pointer-events: none;
}
.el-parenthetical.is-empty::after {
left: 1ch;
}
/* ----------------------------------------------------------- page break */
.page-break {
display: block;
position: relative;
width: var(--page-width);
height: calc(1.6in + var(--gap));
margin: 0 0 0 calc(-1.5in - var(--indent, 0in));
text-indent: 0;
text-align: left;
font-weight: 400;
user-select: none;
pointer-events: none;
background: linear-gradient(
to bottom,
var(--paper) 0.6in,
var(--bg) 0.6in,
var(--bg) calc(0.6in + var(--gap)),
var(--paper) calc(0.6in + var(--gap))
);
}
.page-break::before {
content: '';
position: absolute;
left: 0;
right: 0;
top: 0.6in;
height: var(--gap);
background: radial-gradient(60% 100% at 50% 50%, rgb(79 141 255 / 0.08), transparent);
}
.page-break .page-forced {
position: absolute;
left: 1.5in;
top: calc(0.6in + var(--gap) + 0.5in - 12pt);
color: var(--accent-2);
font-family: var(--ui-font);
font-size: 11px;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
}
.page-break .page-number {
position: absolute;
right: calc(var(--page-width) - 7.5in);
top: calc(0.6in + var(--gap) + 0.5in - 12pt);
color: var(--muted);
font-family: var(--script-font);
font-size: 12pt;
}
/* -------------------------------------------------------- autocomplete */
.autocomplete {
position: fixed;
z-index: 10;
margin: 0;
padding: 5px;
list-style: none;
min-width: 200px;
max-width: 440px;
background: var(--popover);
border: 1px solid var(--border-strong);
border-radius: 12px;
box-shadow: 0 18px 48px rgb(0 0 0 / 0.5);
font-family: var(--script-font);
font-size: 12pt;
animation: pop 0.14s var(--ease);
}
.autocomplete li {
padding: 5px 10px;
border-radius: 8px;
cursor: pointer;
white-space: pre;
color: var(--text-2);
transition: background 0.12s;
}
.autocomplete li.active {
background: linear-gradient(90deg, var(--accent), #5b7cfa);
color: #fff;
}
/* ------------------------------------------------------------- dialogs */
dialog {
border: 1px solid var(--border-strong);
border-radius: 16px;
padding: 26px;
width: 580px;
background: linear-gradient(to bottom, var(--surface-2), var(--surface));
color: var(--text);
box-shadow: 0 30px 90px rgb(0 0 0 / 0.6), 0 0 0 1px rgb(0 0 0 / 0.3);
}
dialog[open] {
animation: pop 0.2s var(--ease);
}
dialog::backdrop {
background: rgb(3 7 18 / 0.6);
backdrop-filter: blur(4px);
}
dialog h2 {
margin: 0 0 18px;
font-size: 17px;
font-weight: 600;
}
dialog label {
display: flex;
flex-direction: column;
gap: 6px;
margin-bottom: 14px;
font-size: 12px;
font-weight: 500;
color: var(--muted);
flex: 1;
}
dialog label.check {
flex-direction: row;
align-items: center;
gap: 10px;
color: var(--text);
font-size: 13px;
cursor: pointer;
}
dialog label[hidden] {
display: none;
}
dialog label.inline {
flex-direction: row;
align-items: center;
gap: 12px;
color: var(--text);
font-size: 13px;
}
dialog input[type='checkbox'] {
accent-color: var(--accent);
width: 16px;
height: 16px;
}
dialog .row {
display: flex;
gap: 14px;
}
dialog .sub {
margin-top: 6px;
}
dialog input:not([type='checkbox']),
dialog select,
dialog textarea {
padding: 9px 11px;
border: 1px solid var(--border-strong);
border-radius: 9px;
background: rgb(4 9 20 / 0.5);
color: var(--text);
resize: vertical;
outline: none;
transition: border-color 0.18s, box-shadow 0.18s;
}
dialog input:not([type='checkbox']):focus,
dialog select:focus,
dialog textarea:focus {
border-color: var(--accent);
box-shadow: 0 0 0 3px rgb(79 141 255 / 0.2);
}
dialog .muted {
color: var(--muted);
margin: -10px 0 18px;
}
dialog menu {
display: flex;
justify-content: flex-end;
gap: 10px;
margin: 10px 0 0;
padding: 0;
}
dialog menu button {
padding: 8px 18px;
border-radius: 9px;
border: 1px solid var(--border-strong);
background: rgb(255 255 255 / 0.03);
cursor: pointer;
font-weight: 500;
transition: background 0.18s, box-shadow 0.18s, transform 0.12s;
}
dialog menu button:hover {
background: rgb(255 255 255 / 0.07);
}
dialog menu button:active {
transform: scale(0.97);
}
dialog menu button.primary {
background: linear-gradient(135deg, #3b82f6, #5b6cf6);
border-color: transparent;
color: #fff;
box-shadow: 0 6px 20px rgb(59 130 246 / 0.35);
}
dialog menu button.primary:hover {
box-shadow: var(--glow);
}
dialog menu button[hidden] {
display: none;
}
dialog menu button.primary.destructive {
background: linear-gradient(135deg, #e5484d, #c8354a);
box-shadow: 0 6px 20px rgb(229 72 77 / 0.3);
}
dialog menu button.primary.destructive:hover {
box-shadow: 0 0 0 1px rgb(229 72 77 / 0.5), 0 6px 24px rgb(229 72 77 / 0.35);
}
dialog.message {
width: 440px;
}
dialog.message p {
margin: -6px 0 18px;
color: var(--text-2);
line-height: 1.55;
white-space: pre-wrap;
user-select: text;
}
/* Progress of a download or a translation. The bar is scaled, not resized,
so only transform is animated; without a total it sweeps back and forth. */
.progress {
height: 6px;
margin: -4px 0 18px;
border-radius: 3px;
background: var(--accent-soft);
overflow: hidden;
}
.progress-bar {
height: 100%;
border-radius: 3px;
background: var(--accent);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.3s var(--ease);
}
.progress[data-state='busy'] .progress-bar {
width: 30%;
transform: none;
animation: sweep 1.2s var(--ease) infinite alternate;
}
@keyframes sweep {
from {
translate: 0;
}
to {
translate: 233%;
}
}
dialog menu button:focus-visible {
outline: 2px solid var(--accent-2);
outline-offset: 2px;
}