/*
 * Retroprose: the retro screen.
 * Shared by List files and (feature 4) the editor. Theme tokens follow
 * docs/reference/retroprose-demo.html and directives/editor_build.md.
 * No inline styles anywhere: the Content Security Policy blocks them.
 */

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/ibm-plex-mono-latin-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/ibm-plex-mono-latin-ext-400.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/ibm-plex-mono-latin-600.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/ibm-plex-mono-latin-ext-600.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/ibm-plex-mono-latin-700.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/ibm-plex-mono-latin-ext-700.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* The other fonts for the text (View, Font). Only the text uses them:
 * the menus, status line and key bar stay in IBM Plex Mono. A browser
 * fetches a font only when something on the page uses it. All are
 * monospaced, and --tch below gives each one's width. */
@font-face {
  font-family: "Courier Prime";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/courier-prime-latin-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Courier Prime";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/courier-prime-latin-ext-400.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Courier Prime";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/courier-prime-latin-700.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Courier Prime";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/courier-prime-latin-ext-700.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Atkinson Hyperlegible Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/atkinson-hyperlegible-mono-latin-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Atkinson Hyperlegible Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/atkinson-hyperlegible-mono-latin-ext-400.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Atkinson Hyperlegible Mono";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/atkinson-hyperlegible-mono-latin-700.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Atkinson Hyperlegible Mono";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/atkinson-hyperlegible-mono-latin-ext-700.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-latin-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-latin-ext-400.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-latin-700.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-latin-ext-700.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* The VGA screen font: one file, with Latin, Greek and Cyrillic. It has
 * no bold, so bold text shows only brighter, as on a DOS screen (Paper
 * draws a bold, below). */
@font-face {
  font-family: "IBM VGA 8x16";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/ibm-vga-8x16-plus.woff") format("woff");
}

/* ---------- Themes ----------
 * --dim is for borders and rules only (3.7:1 on blue). Never use it for text.
 * --mark is the dimmed text of Markdown marks, at least 4.5:1 in each theme.
 * --text is the user's text size (14 to 28). --scale is the screen size
 * (View, Screen size): small, medium or large, on top of the text size.
 * Everything sized from --size, em or ch follows it. */
:root {
  --bg: #0000AA; --fg: #AAAAAA; --hi: #FFFFFF; --head: #FFFF55; --acc: #55FFFF; --dim: #7777FF; --mark: #9090FF;
  --inv-bg: #AAAAAA; --inv-fg: #0000AA; --focus: #FFFF55; --sel-bg: #AAAAAA; --sel-fg: #0000AA;
  --font: "IBM Plex Mono", ui-monospace, "Cascadia Mono", Consolas, "Courier New", monospace;
  --text: 16px; --scale: 1.25; --size: calc(var(--text) * var(--scale)); --lh: 1.5; --bw: 700;
  /* The text's font (View, Font) and the width of one of its characters
   * in em, so --col is one column of the text. The 80 columns, and the
   * gutter that lines the menu bar, status line and key bar up with
   * column 1, are measured in the text's font, whatever the frame uses. */
  --tfont: var(--font); --tch: .6; --col: calc(var(--tch) * var(--size));
  --gutter: max(16px, calc((100% - 80 * var(--col)) / 2));
  /* The width of the pages outside the editor: the dashboard, and the
   * List files and Writing stats pages (the account page matches it). */
  --page: 112ch;
}
:root[data-skin="green"] {
  --bg: #001800; --fg: #33FF66; --hi: #D2FFDC; --head: #D2FFDC; --acc: #8CFFAA; --dim: #23933F; --mark: #23933F;
  --inv-bg: #33FF66; --inv-fg: #000000; --focus: #D2FFDC; --sel-bg: #33FF66; --sel-fg: #000000;
  --font: "IBM Plex Mono", "Courier New", monospace;
}
:root[data-skin="amber"] {
  --bg: #1A1000; --fg: #FFB000; --hi: #FFE6B0; --head: #FFE6B0; --acc: #FFCF5C; --dim: #9A6B00; --mark: #A57400;
  --inv-bg: #FFB000; --inv-fg: #000000; --focus: #FFE6B0; --sel-bg: #FFB000; --sel-fg: #000000;
  --font: "IBM Plex Mono", "Courier New", monospace;
}
:root[data-skin="paper"] {
  --bg: #FFFFFF; --fg: #222222; --hi: #000000; --head: #000000; --acc: #0000AA; --dim: #8A8A8A; --mark: #737373;
  --inv-bg: #222222; --inv-fg: #FFFFFF; --focus: #0000AA; --sel-bg: #0000AA; --sel-fg: #FFFFFF;
  --lh: 1.6; --bw: 700;
}
:root[data-size="14"] { --text: 14px; } :root[data-size="15"] { --text: 15px; } :root[data-size="16"] { --text: 16px; }
:root[data-size="17"] { --text: 17px; } :root[data-size="18"] { --text: 18px; } :root[data-size="19"] { --text: 19px; }
:root[data-size="20"] { --text: 20px; } :root[data-size="21"] { --text: 21px; } :root[data-size="22"] { --text: 22px; }
:root[data-size="23"] { --text: 23px; } :root[data-size="24"] { --text: 24px; } :root[data-size="25"] { --text: 25px; }
:root[data-size="26"] { --text: 26px; } :root[data-size="27"] { --text: 27px; } :root[data-size="28"] { --text: 28px; }
/* Medium (1.25) is the default. Each size is a step of .25 from the next.
 * Tap targets keep their 24px least size (WCAG 2.5.8) on the small screen. */
:root[data-screen="small"] { --scale: 1; } :root[data-screen="large"] { --scale: 1.5; }
/* A phone's screen is small already, so it has the small screen size,
 * whatever the account's (a desktop's Large made a phone's text huge).
 * The text size still counts. On a phone's touch screen the text is at
 * least 16px, as Safari on an iPhone zooms into smaller text being
 * edited. The same queries are in phone.js. */
@media (max-width: 560px), (pointer: coarse) and (max-height: 500px) {
  :root[data-screen] { --scale: 1; }
}
@media (pointer: coarse) and (max-width: 560px), (pointer: coarse) and (max-height: 500px) {
  :root { --size: max(16px, calc(var(--text) * var(--scale))); }
}
/* View, Font: the text's font. --tch is each font's character width
 * (its advance over its em), read from the font files: keep them in
 * step if a font is replaced. Letters a font lacks come from Plex. */
:root[data-font="courier"] { --tfont: "Courier Prime", var(--font); --tch: calc(1228 / 2048); }
:root[data-font="atkinson"] { --tfont: "Atkinson Hyperlegible Mono", var(--font); --tch: .632; }
:root[data-font="jetbrains"] { --tfont: "JetBrains Mono", var(--font); --tch: .6; }
:root[data-font="vga"] { --tfont: "IBM VGA 8x16", var(--font); --tch: .5; }
/* The VGA font has no bold, and a drawn one would be wider than its
 * column in some browsers, so bold shows by the brighter colour, as on a
 * DOS screen. Paper's brightest shade is too close to its text for that,
 * so there the browser draws the bold. */
:root[data-font="vga"]:not([data-skin="paper"]) :is(.rp-bold, .rp-head) { font-weight: 400; }
[hidden] { display: none !important; }

/* ---------- Page ---------- */
*, *::before, *::after { box-sizing: border-box; }
/* Scrollbars in screen colours. scrollbar-color is inherited, so this
 * reaches every scrolling panel on every page. Menus and dialogs set
 * their own, below. */
html { height: 100%; background: var(--bg); scrollbar-color: var(--dim) var(--bg); }
body {
  height: 100%;
  margin: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  font-size: var(--size);
  line-height: var(--lh);
  -webkit-text-size-adjust: 100%;
  padding-top: env(safe-area-inset-top, 0px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; margin: 0; cursor: pointer; text-align: left; }
a { color: inherit; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }

.rp-skip {
  position: absolute; left: 16px; top: -10rem; z-index: 50;
  padding: .25em 1ch; background: var(--focus); color: #000000; font-weight: var(--bw); text-decoration: none;
}
.rp-skip:focus { top: .5rem; outline: 3px solid var(--hi); outline-offset: 0; }

/* ---------- Status line ----------
 * Not a live region: messages are copied to #live. The space above it
 * lets long text stop short of the line, not run into it. The text is
 * bright (--hi: white on blue, the theme's brightest shade elsewhere). */
.status {
  flex: none;
  color: var(--hi);
  display: flex;
  justify-content: space-between;
  gap: 2ch;
  min-height: calc(var(--size) * var(--lh));
  white-space: nowrap;
  padding: .75em var(--gutter) .25em;
  font-size: clamp(calc(13px * var(--scale)), 3.8vw, var(--size));
}
.status .l { overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 1; }
/* A document's folders shorten before its name (statusline.js), so a
 * phone shows "A:\NO…\CHAPTER ONE.MD", not "A:\NOVEL\C…". */
.status .l.split { display: flex; }
.status .l.split > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.status .l.split .head { flex: 0 1000 auto; }
.status .l.split .tail { flex: 0 1 auto; }
.status .r { flex: none; }
.status .on { color: var(--hi); font-weight: var(--bw); }
.status .u { text-decoration: underline; text-underline-offset: .2em; }
/* The save state: "Saved 14:32", with a short form for narrow screens
 * that is empty for the usual "Saved", so the file name keeps the room. */
.status .save > span { margin-right: 2ch; }
/* The document is open in another tab or on another device. */
.status .also { margin-right: 2ch; color: var(--head); }
.status .save .short { display: none; }
@media (max-width: 560px) {
  .status .docn { display: none; }
  .status .save .long { display: none; }
  .status .save .short:not(:empty) { display: inline; }
}
.prompt { color: var(--hi); display: flex; gap: 1ch; align-items: baseline; }
.prompt b { font-weight: var(--bw); }
/* "Block on" flashes a few times, then shows steady: blinking that stops
 * within 5 seconds (WCAG 2.2.2). Steady when the browser asks for less motion. */
.status .l.blink { color: var(--hi); animation: rp-blink 1s steps(1) 4; }
.prompt button { padding: 0 .25ch; color: var(--hi); min-height: 24px; }
.prompt button:hover { background: var(--inv-bg); color: var(--inv-fg); }
.ask input {
  flex: 1; min-width: 0; min-height: 24px;
  background: transparent; color: var(--hi); caret-color: var(--hi);
  font: inherit; border: 0; border-bottom: 1px solid var(--dim); border-radius: 0; padding: 0;
}
.ask input:focus-visible { outline: none; border-bottom: 2px solid var(--focus); }
/* Safari on an iPhone zooms the page into a text box smaller than 16px,
 * as the status line's is on the small screen size. */
@media (pointer: coarse) and (max-width: 560px), (pointer: coarse) and (max-height: 500px) {
  input, select, textarea, .ask input { font-size: max(16px, 1em); }
  /* Down to the top of the on-screen keyboard where the browser lays it
   * over the page (keyboard.js), so the status line and key bar show. */
  body { height: var(--keyboard-fit, 100%); }
}

/* ---------- List files ---------- */
.lf {
  flex: 1;
  min-height: 0;
  display: flex;
  padding: 8px var(--gutter) 4px;
}
.box {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  border: 3px double var(--fg);
}
.box-bar {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0 2ch;
  background: var(--inv-bg);
  color: var(--inv-fg);
  padding: 0 1ch;
}
.box-bar h1 { font: inherit; font-weight: var(--bw); margin: 0; }
/* The links wrap: on a phone they would otherwise make the box, and the
 * page, wider than the screen. */
.box-bar ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0 2ch; }
.box-bar a { display: inline-block; min-height: 24px; text-decoration: underline; text-underline-offset: .2em; }
.box-bar a:hover { background: var(--inv-fg); color: var(--inv-bg); }
.box-bar :focus-visible { outline: 2px solid var(--inv-fg); outline-offset: 0; }
/* The links between the pages: the page on screen is bold, not underlined. */
.box-bar a[aria-current="page"] { font-weight: var(--bw); text-decoration: none; }
/* Sign out is a form (a POST), with a button that looks like the links
 * beside it (app/Views/partials/app_nav.php). */
.rp-nav form { display: inline; margin: 0; }
.rp-nav__out { display: inline-block; min-height: 24px; margin: 0; padding: 0; border: 0; background: none; color: inherit; font: inherit; text-decoration: underline; text-underline-offset: .2em; cursor: pointer; }
.box-bar .rp-nav__out:hover { background: var(--inv-fg); color: var(--inv-bg); }

/* The List files and Writing stats pages: as wide as the dashboard. Over
 * the editor they keep to the 80 columns of the text. */
.rp-page .lf { padding-left: max(16px, calc((100% - var(--page)) / 2)); padding-right: max(16px, calc((100% - var(--page)) / 2)); }

.meta { flex: none; display: flex; flex-wrap: wrap; gap: 0 3ch; padding: .25em 1ch; border-bottom: 1px solid var(--dim); }
.meta .w { flex-basis: 100%; overflow-wrap: anywhere; color: var(--hi); }
/* The disk bar (graphics.js): used space hatched in the bright colour,
 * free space plain, in a frame, then the percentage as text. The lines
 * reach at least 3:1 with the screen in every theme. */
.meta .disk { flex-basis: 100%; min-width: 0; display: flex; align-items: center; gap: 1ch; }
.disk .bar { flex: 1; min-width: 0; height: .9em; border: 1px solid var(--fg); }
.disk pattern rect { fill: var(--hi); }
.disk .edge { stroke: var(--hi); stroke-width: 2; }
.disk > span:last-child { flex: none; }

.list { flex: 1; min-height: 6em; overflow: auto; padding: .25em 0; outline: none; }
.list:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 11ch 15ch;
  gap: 1ch;
  min-height: 24px;
  padding: 0 1ch;
  cursor: pointer;
}
.row .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Pixel icons (graphics.js), drawn in the row's own colour, so they
 * invert with the chosen row. Folders are in the heading colour. */
.row .ico { display: inline-block; width: 1em; height: 1em; margin-right: 1ch; vertical-align: -.15em; fill: currentColor; shape-rendering: crispEdges; }
.row .ico-dir, .row .ico-trash, .row .ico-lock, .row .ico-unlock { color: var(--head); }
:is(.row.cur, :not([aria-multiselectable="true"]) > .row[aria-selected="true"]) .ico, .row.away .ico { color: inherit; }
/* The file or folder picked up with 9 Move: in the accent colour, with
 * <Move> in place of its size. */
.row.moving:not(.cur) :is(.nm, .sz, .ico) { color: var(--acc); }
.row .nm .path { color: var(--acc); }
.row .sz { text-align: right; white-space: nowrap; }
.row .dt { white-space: nowrap; }
.row.dir .nm, .row.dir .sz { color: var(--hi); }
/* Offline: a document with no copy on this device. Its size reads <Online>. */
.row.away .nm, .row.away .sz { color: var(--mark); }
/* The chosen row is inverted. In List files, which can have several
 * rows selected, the chosen row is .cur and the selected rows are the
 * marked ones. The other lists choose one row, with aria-selected. */
:is(.row.cur, :not([aria-multiselectable="true"]) > .row[aria-selected="true"]), :is(.row.cur, :not([aria-multiselectable="true"]) > .row[aria-selected="true"]) :is(.nm, .sz, .path) {
  background: var(--inv-bg); color: var(--inv-fg);
}
/* A marked row (List files): a * before its icon, as DOS word processors
 * showed it, and its name in the bright colour, so it never relies on
 * colour alone. */
.row .mk { display: inline-block; width: 1ch; color: var(--hi); }
[aria-multiselectable="true"] > .row[aria-selected="true"]:not(.cur) :is(.nm, .sz) { color: var(--hi); font-weight: var(--bw); }
/* Dragging: the rows being dragged are dim, and the folder they would
 * drop into has a dashed frame and the accent colour. */
.row.dragged:not(.cur) :is(.nm, .sz, .dt, .ico, .mk) { color: var(--dim); }
.row.drop-on { outline: 2px dashed var(--acc); outline-offset: -2px; }
.row.drop-on:not(.cur) :is(.nm, .sz, .ico) { color: var(--acc); }
.empty { padding: 0 1ch; }
@media (max-width: 560px) {
  .row { grid-template-columns: minmax(0, 1fr) 9ch; }
  .row .dt { display: none; }
}
/* List files on a phone: the names get the width. No sizes, <Dir> or
 * <Trash>, only <Move>, <Lock> and <Online> (.note). Of the details at
 * the top, the disk bar and the directory. The page's title is the bold
 * link, so the heading is for screen readers only. */
@media (max-width: 560px), (pointer: coarse) and (max-height: 500px) {
  #flist .row { grid-template-columns: minmax(0, 1fr) auto; }
  #flist .row .sz:not(.note) { display: none; }
  #lf-meta > span:not([class]) { display: none; }
  .box-bar:has(.rp-nav) > h1 { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}

/* Revisions: the same list, with why each was kept after the date, and
 * the text of one revision, read only, in place of the list. */
.revs .row .path { margin-left: 2ch; }
.revs .row .dt { text-align: right; }
@media (max-width: 560px) {
  /* The date needs the room. The size is still read out with each row. */
  .revs .row { grid-template-columns: minmax(0, 1fr); }
  .revs .row .sz { display: none; }
}
/* Key settings: the action, its classic key and its modern key. */
.keysets .row { grid-template-columns: minmax(0, 1fr) 13ch 21ch; }
.keysets .row .kc, .keysets .row .km { white-space: nowrap; }
.keysets .row.changed .kc, .keysets .row.changed .km { color: var(--hi); }
.keysets .row[aria-selected="true"] .kc, .keysets .row[aria-selected="true"] .km { color: var(--inv-fg); }
@media (max-width: 560px) {
  .keysets .row { grid-template-columns: minmax(0, 1fr) 12ch; }
  .keysets .row .km { display: none; }
}

.rv-text {
  flex: 1;
  min-height: 6em;
  overflow: auto;
  padding: .25em 1ch;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  outline: none;
}
.rv-text:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }

/* Print preview: white A4 sheets on the screen colour, each with a thin
 * rule and a hard shadow, like the dialogs of the account pages. The
 * document inside keeps the export template's own style sheet
 * (export-styles/{template}), whose rules all sit inside .rp-doc. Its
 * sizes are in points, so the screen size zooms the whole sheet, and the
 * lines break in the same places at each size. A percentage width is
 * not zoomed, so a sheet still fits a narrow screen. */
:root { --sheet-shadow: #000000; }
:root[data-skin="green"], :root[data-skin="amber"], :root[data-skin="paper"] { --sheet-shadow: var(--dim); }
.pv-pages {
  flex: 1;
  min-height: 6em;
  overflow: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  padding: 16px 1ch 32px;
  outline: none;
}
.pv-pages:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.pv-pages .empty { align-self: stretch; }
.sheet {
  flex: none;
  box-sizing: border-box;
  width: min(100%, 210mm);
  aspect-ratio: 210 / 297;
  padding: clamp(16px, 6vw, 25mm);
  background: #ffffff;
  color: #000000;
  border: 1px solid var(--dim);
  box-shadow: 8px 8px 0 var(--sheet-shadow);
  font-size: 16px;
  letter-spacing: normal;
  zoom: var(--scale);
}
.sheet .rp-doc :focus-visible { outline: 2px solid #0000aa; outline-offset: 2px; }
@media (max-width: 560px) {
  .sheet { box-shadow: 4px 4px 0 var(--sheet-shadow); }
}

/* Help, On a phone: only on a phone's touch screen (phone.js has the query). */
.help-phone { display: none; }
@media (pointer: coarse) and (max-width: 560px), (pointer: coarse) and (max-height: 500px) {
  .help-phone { display: block; }
}
.help-body .help-code { font: inherit; color: var(--acc); margin: 0 0 .6em 2ch; white-space: pre-wrap; }

/* Files dragged over the page: a double frame round the screen shows
 * that they will upload when dropped. It is ::before because the
 * scanlines use ::after, and some settings turn those off. */
.dropping body::before {
  content: "";
  position: fixed;
  inset: 4px;
  z-index: 40;
  border: 3px double var(--hi);
  pointer-events: none;
}

.foot {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0 2ch;
  padding: .25em 1ch;
  border-top: 1px solid var(--dim);
}
.foot button { padding: .2em 0; min-height: 24px; white-space: nowrap; }
.foot button b { color: var(--hi); font-weight: var(--bw); }
.foot button:hover { background: var(--inv-bg); color: var(--inv-fg); }
.foot button:hover b { color: inherit; }
.foot button[aria-pressed="true"] { color: var(--hi); }

/* ---------- Editor ----------
 * CodeMirror 6 in the retro screen. The 80-column page sits in the middle,
 * with a DOS cursor (cursor.js: a full block with the character at the
 * cursor inverted inside it) and the native selection, shown inverted
 * like a DOS block. The #text prefix
 * (and #note-text, the footnote screen's editor) outranks CodeMirror's
 * own theme. */
.doc { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.doc .text { flex: 1; min-height: 0; display: flex; }
:is(#text, #note-text) .cm-editor { flex: 1; min-width: 0; height: 100%; background: var(--bg); color: var(--fg); }
:is(#text, #note-text) .cm-editor.cm-focused { outline: none; }
:is(#text, #note-text) .cm-scroller {
  font-family: var(--tfont);
  line-height: var(--lh);
  padding: 0 var(--gutter);
  scrollbar-width: thin;
}
:is(#text, #note-text) .cm-content { padding: 1em 0 3em; color: var(--fg); caret-color: transparent; }
/* The cursor: a block the height of the character and one column wide
 * (wider for a wide letter), in the colour of the character under it
 * (--cursor, from cursor.js), with its own copy of the character in the
 * background colour. */
:is(#text, #note-text) .cm-cursor {
  width: 1ch; margin-left: 0; border-left: 0;
  background: var(--cursor, var(--fg)); color: var(--bg);
  white-space: pre; overflow: hidden; text-align: center;
}
/* The other cursors (View, Cursor) are the same block cut down, so the
 * part of the character inside them still shows inverted: the lower
 * half, a thick underline, or a thin upright line at the left of the
 * character, where the next letter goes. */
:root[data-cursor="half"] :is(#text, #note-text) .cm-cursor { clip-path: inset(50% 0 0 0); }
:root[data-cursor="underline"] :is(#text, #note-text) .cm-cursor { clip-path: inset(calc(100% - max(3px, .2em)) 0 0 0); }
:root[data-cursor="line"] :is(#text, #note-text) .cm-cursor { clip-path: inset(0 calc(100% - max(2px, .12em)) 0 0); }
:is(#text, #note-text) .cm-line { padding: 0; }
:is(#text, #note-text) .cm-content ::selection, :is(#text, #note-text) .cm-content::selection { background: var(--sel-bg); color: var(--sel-fg); }

/* The ruler at the top of the text (View, Ruler): one cell 1ch wide for
 * each of the 80 columns, in the text's own font and size, so it keeps
 * to the columns. The numbers are text, so they use --mark (4.5:1). The
 * ticks are drawn and use --dim. The cursor's column has a bright tick.
 * The cells are clipped at the right on a narrow screen. */
.ruler-bar { flex: none; overflow: hidden; padding: .6em var(--gutter) 0; font-family: var(--tfont); }
/* A phone shows a third of the 80 columns, so the ruler means little
 * there and is gone, space and all. View, Ruler is left out too. */
@media (max-width: 560px), (pointer: coarse) and (max-height: 500px) {
  .ruler-bar { display: none; }
}
.ruler-bar .cells { display: flex; width: 80ch; border-bottom: 1px solid var(--dim); }
.ruler-bar .c { flex: none; position: relative; width: 1ch; height: 1.25em; }
.ruler-bar .c::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: calc(50% - .5px);
  width: 1px;
  height: .2em;
  background: var(--dim);
}
.ruler-bar .five::after { height: .4em; }
.ruler-bar .at::after { left: calc(50% - 1px); width: 2px; height: .6em; background: var(--hi); }
.ruler-bar .n {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font);
  font-size: max(10px, .6em);
  line-height: 1;
  white-space: nowrap;
  color: var(--mark);
}

/* The footnote screen (Ctrl+F7): a bar with the footnote's number over
 * the note's own editor, which looks the same as the document. */
.note-bar {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0 2ch;
  padding: 0 var(--gutter);
  background: var(--inv-bg);
  color: var(--inv-fg);
}
.note-bar h1 { font: inherit; margin: 0; font-weight: var(--bw); }
.note-bar button { min-height: 24px; padding: 0 1ch; margin-right: -1ch; }
.note-bar button:hover { text-decoration: underline; }
.note-bar button:focus-visible { outline: 2px solid var(--inv-fg); outline-offset: -2px; }

/* Undelete (F1) shows the deletion at the cursor, and Replace with
 * Confirm shows the match it is asking about, as an inverted block. */
.rp-undel, .rp-found { background: var(--inv-bg); color: var(--inv-fg); }
.rp-undel { white-space: pre-wrap; }

/* Markdown marks dimmed, formatted text bright, as in the demo. A span
 * inside a mark is only ever part of the mark, so it takes the mark colour. */
.rp-mark, .rp-mark span { color: var(--mark); font-weight: 400; }
.rp-bold { color: var(--hi); font-weight: var(--bw); }
.rp-ital { color: var(--hi); text-decoration: underline; text-underline-offset: .2em; }
.rp-head { color: var(--head); font-weight: var(--bw); }
.rp-acc, .rp-table, .rp-quote, .rp-note { color: var(--acc); }
/* A link's words: the accent colour, underlined. Its marks and address are dimmed as .rp-mark. */
.rp-link { color: var(--acc); text-decoration: underline; text-underline-offset: .2em; }
/* Aligned text ("::: centre", "::: right" and "::: justify"): the lines between the fences */
#text .cm-line.rp-centre { text-align: center; }
#text .cm-line.rp-right { text-align: right; }
#text .cm-line.rp-justify { text-align: justify; }
/* DOS screens could not show italic, so the retro themes underline it.
 * Paper shows true italic (docs/design.md, Document format). */
:root[data-skin="paper"] .rp-ital { text-decoration: none; font-style: italic; }
/* Spell check: a wavy line, set lower than the underline for italic, so
 * the two can be told apart by shape as well as colour. Each colour has
 * at least 3:1 contrast with its screen (light red on blue is 4.2:1). */
:root { --spell: #FF5555; }
:root[data-skin="green"], :root[data-skin="amber"] { --spell: var(--hi); }
:root[data-skin="paper"] { --spell: #C00000; }
.rp-spell {
  text-decoration: underline wavy var(--spell);
  text-decoration-thickness: 1.5px;
  text-decoration-skip-ink: none;
  text-underline-offset: .32em;
}

/* Page breaks (pagebreaks.js): a line across the column where a page is
 * full, a double line on the row under \newpage, and the next page's number
 * in the middle. The lines are drawn in --dim, like the ruler's, so they
 * never add to the width. The number is text, so it uses --mark (4.5:1),
 * on a patch of the screen colour that breaks the line around it. */
.rp-pg {
  display: inline-block;
  width: 100%;
  vertical-align: top;
  text-align: center;
  text-indent: 0;
  text-decoration: none;
  font-weight: 400;
  color: var(--mark);
  user-select: none;
  background: linear-gradient(var(--dim), var(--dim)) 0 50% / 100% 1px no-repeat;
}
.rp-hpg {
  background:
    linear-gradient(var(--dim), var(--dim)) 0 calc(50% - 2px) / 100% 1px no-repeat,
    linear-gradient(var(--dim), var(--dim)) 0 calc(50% + 2px) / 100% 1px no-repeat;
}
/* The number is the size of the ruler's numbers, centred on the line. */
.rp-pg span { padding: 0 1ch; background: var(--bg); font-size: max(10px, .6em); vertical-align: middle; }
/* View, Page numbers off: nothing shows, line or number, and the text
 * reads as if the rule were not there, with no blank row or extra space. */
:root[data-page-numbers="off"] .rp-pg { display: none; }

/* ---------- Reveal codes (Alt+F3 or F9) ----------
 * A pane under the text, as in the demo: an inverted ruler with the tab
 * stops, then the Markdown as codes. The item at the cursor is a solid
 * block. Codes use --acc, which reaches 4.5:1 in each theme. */
.codes { flex: none; height: 38%; min-height: 5em; display: flex; flex-direction: column; font-family: var(--tfont); }
.ruler {
  flex: none;
  height: calc(1em * var(--lh));
  overflow: hidden;
  white-space: pre;
  padding: 0 var(--gutter);
  background: var(--inv-bg);
  color: var(--inv-fg);
}
/* Tab stops are drawn, not a glyph: the fonts have no triangle, and a
 * fallback font would not keep to the 1ch columns. */
.ruler .stop { display: inline-block; width: 1ch; height: .6em; background: currentColor; clip-path: polygon(50% 0, 90% 100%, 10% 100%); }
.codeview {
  flex: 1;
  min-height: 0;
  position: relative;
  overflow: auto;
  padding: .25em var(--gutter) .5em;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  cursor: text;
  scrollbar-width: thin;
}
/* ---------- Outline (Alt+F5) ----------
 * The headings in a pane 28 columns wide on the left (outline.js). It
 * never takes columns from the text. Beside the text (data-outline="side"
 * on <html>, set only while the editor screen shows), the pane is a
 * column of its own the full height of the screen, and the page has a
 * left margin as wide as it. The menu bar, ruler, text, status line and
 * key bar then centre in the space that is left, with their own gutters.
 * --ow is 28 columns of the text (--col), in the text's own font and
 * size, whatever the pane's font is. Where the pane does not fit beside 80
 * columns, it opens over the text (data-mode="over"). .ol-probe is 80
 * columns wide, for outline.js to measure. */
:root { --ow: calc(28 * var(--col)); }
#editor { position: relative; }
.ol-probe { position: absolute; top: 0; left: 0; width: calc(80 * var(--col)); height: 0; visibility: hidden; pointer-events: none; }
:root[data-outline="side"] body { padding-left: var(--ow); }
:root[data-outline="side"] .outline { position: fixed; }
/* The dialogs (Export, Link) sit in the top layer, outside the body's
 * margin, so they start after the pane too and centre over the text. */
:root[data-outline="side"] .dlg { left: var(--ow); max-width: calc(100vw - var(--ow) - 32px); }
.outline {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: 5;
  width: var(--ow);
  max-width: calc(100% - 48px);
  display: flex;
  flex-direction: column;
  padding: .6em 0 .5em;
  background: var(--bg);
  border-right: 1px solid var(--acc);
}
.outline[data-mode="over"] { border-right: 3px double var(--acc); }
/* The pane stays 28 columns of the text wide, and its own text is
 * smaller: the title bars seven eighths of the text size, the headings,
 * the message with no headings and the stats three quarters. Both follow
 * the text size and screen size (em). */
.ol-bar, .ol-stats h2 { font-size: .875em; }
.ol-tree, .ol-none, .ol-stats dl { font-size: .75em; }
.ol-nav { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.ol-bar { flex: none; display: flex; justify-content: space-between; align-items: baseline; gap: 1ch; padding: 0 1ch .5em; }
.ol-bar h2 { margin: 0; font-size: 1em; font-weight: var(--bw); color: var(--acc); }
/* On Windows, Chrome and Edge smooth text with coloured fringes
 * (ClearType), which make bold text in the pale accent colours look as
 * if it glows. A layer of their own makes them smooth these titles in
 * grey (10 October 2026). */
.ol-bar h2, .ol-stats h2 { will-change: transform; }
.ol-bar button { min-height: 24px; white-space: nowrap; }
.ol-bar button b { background: var(--inv-bg); color: var(--inv-fg); font-weight: 400; padding: 0 .35ch; }
.ol-bar button:hover { text-decoration: underline; text-underline-offset: .2em; }
.ol-none { margin: 0; padding: 0 1ch; }
.ol-tree { flex: 1; min-height: 0; overflow: auto; outline: none; scrollbar-width: thin; }
.ol-tree:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.ol-row { display: flex; align-items: baseline; min-height: 24px; padding-right: 1ch; cursor: pointer; white-space: nowrap; }
.ol-row.l2 { padding-left: 1ch; }
.ol-row.l3 { padding-left: 2ch; }
/* The + or - that opens or closes a heading: at least 24px wide to tap. */
.ol-sign { flex: none; width: max(3ch, 24px); text-align: center; color: var(--acc); }
.ol-words { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ol-row.l1 .ol-words { color: var(--hi); }
.ol-row:hover .ol-words { text-decoration: underline; text-underline-offset: .2em; }
/* The heading the cursor is in is inverted. While the user is in the
 * outline, the inverted bar is the chosen heading, and the cursor's
 * heading is bold in the heading colour instead. */
.ol-row.cur, .ol-row.on { background: var(--inv-bg); }
.ol-row.cur :is(.ol-sign, .ol-words), .ol-row.on :is(.ol-sign, .ol-words) { color: var(--inv-fg); }
.ol-tree:focus .ol-row.cur:not(.on) { background: none; }
.ol-tree:focus .ol-row.cur:not(.on) .ol-words { color: var(--head); font-weight: var(--bw); }
.ol-tree:focus .ol-row.cur:not(.on) .ol-sign { color: var(--acc); }
/* Document stats (docstats.js): at the foot of the pane, under a rule,
 * label on the left and figure on the right. Selected and the section
 * are words, so they sit one column in, under Words. On a short screen
 * the stats take at most half the pane and scroll. */
.ol-stats { flex: none; max-height: 50%; overflow-y: auto; scrollbar-width: thin; margin-top: .5em; padding: .5em 1ch 0; border-top: 1px solid var(--acc); }
.ol-stats h2 { margin: 0 0 .25em; font-weight: var(--bw); color: var(--acc); }
.ol-stats dl { margin: 0; }
.ol-stats dl > div { display: flex; justify-content: space-between; align-items: baseline; gap: 1ch; }
.ol-stats dl > div.sub { padding-left: 1ch; }
.ol-stats dt { flex: none; }
.ol-stats dd { margin: 0; color: var(--hi); text-align: right; }

.codeview .c { color: var(--acc); cursor: pointer; }
.codeview .sel { background: var(--sel-bg); color: var(--sel-fg); }
.codeview .cur { background: var(--inv-bg); color: var(--inv-fg); }

/* ---------- Menu colours ----------
 * Blue and paper: a grey panel with black text, the hot key letter in
 * red, a red bar on the chosen item and a black shadow, as in DOS word
 * processors of the time. The red is darker than CGA red so the letters
 * reach 4.5:1 on the grey (#800000 on #AAAAAA is 4.7:1, white on
 * #AA0000 is 7.7:1). Green and amber are monochrome screens, so their
 * menus stay in screen colours with a double border and the hot key
 * letters bright. */
:root {
  --mbar-bg: #AAAAAA; --mbar-fg: #000000; --mbar-key: #800000; --mbar-on-bg: #AA0000; --mbar-on-fg: #FFFFFF;
  --drop-bg: #AAAAAA; --drop-fg: #000000; --drop-key: #800000; --drop-on-bg: #AA0000; --drop-on-fg: #FFFFFF;
  --drop-tick: #000000; --drop-off: #555555; --drop-line: #555555;
  --drop-edge: 0 none; --drop-shadow: 8px 8px 0 #000000;
}
:root[data-skin="green"], :root[data-skin="amber"] {
  --mbar-bg: var(--inv-bg); --mbar-fg: var(--inv-fg); --mbar-key: inherit; --mbar-on-bg: var(--inv-fg); --mbar-on-fg: var(--inv-bg);
  --drop-bg: var(--bg); --drop-fg: var(--fg); --drop-key: var(--hi); --drop-on-bg: var(--inv-bg); --drop-on-fg: var(--inv-fg);
  --drop-tick: var(--hi); --drop-off: var(--dim); --drop-line: var(--dim);
  --drop-edge: 3px double var(--fg); --drop-shadow: none;
}
/* Grey on white is too faint an edge on its own (WCAG 1.4.11). */
:root[data-skin="paper"] { --drop-edge: 1px solid #555555; --drop-shadow: 6px 6px 0 var(--dim); }

/* ---------- Menu bar (Alt+=) and word goal ----------
 * The top line holds the menu bar and, at the right, the word goal
 * (goal.js). It has the menu bar's colours while the menu bar shows,
 * and the screen's own colours when only the goal does. With neither
 * it is gone, space and all.
 * Each menu name has 1ch of space either side for its highlight, so the
 * bar starts 1ch early and the names line up with column 1 of the text.
 * .hk is the hot key letter (menus.js). */
.topbar {
  flex: none;
  position: relative;
  z-index: 6;
  display: flex;
  align-items: center;
  gap: 2ch;
  padding: 0 var(--gutter);
  font-size: clamp(calc(14px * var(--scale)), 4vw, var(--size));
  --goal-frame: var(--fg);
  --goal-fill: var(--hi);
}
.topbar:has(> .menubar[hidden]):has(> .word-goal[hidden]) { display: none; }
.topbar:has(> .menubar:not([hidden])) {
  background: var(--mbar-bg);
  color: var(--mbar-fg);
  --goal-frame: var(--mbar-fg);
  --goal-fill: var(--mbar-fg);
}
.menubar { flex: 1; min-width: 0; margin-left: -1ch; }
/* The word goal: a short bar, hatched until the goal is met and solid
 * after, then the percentage. A button, to change the goal. */
.word-goal {
  flex: none;
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 1ch;
  min-height: 24px;
  padding: 0;
  color: var(--goal-frame);
}
.word-goal .bar { width: 10ch; height: .9em; border: 1px solid var(--goal-frame); color: var(--goal-fill); }
.word-goal pattern rect { fill: var(--goal-fill); }
.word-goal .edge { stroke: var(--goal-fill); stroke-width: 2; }
.word-goal .pc { min-width: 4ch; text-align: right; }
.word-goal.met .pc { font-weight: var(--bw); }
.word-goal:hover .pc, .word-goal:focus-visible .pc { text-decoration: underline; text-underline-offset: .2em; }
.word-goal:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
/* On a phone a shorter bar, so the menu names keep more of the line. */
@media (max-width: 560px) {
  .topbar { gap: 1ch; }
  .word-goal .bar { width: 5ch; }
}
.mbar { display: flex; flex-wrap: wrap; }
.mwrap { position: relative; }
.mtop { padding: 0 1ch; min-height: 24px; }
.mtop .hk { color: var(--mbar-key); }
/* The chosen name (open, or with focus after Alt+=) has the red bar. */
.mtop[aria-expanded="true"], .mtop:hover, .mtop:focus-visible { background: var(--mbar-on-bg); color: var(--mbar-on-fg); outline: none; }
.mtop[aria-expanded="true"] .hk, .mtop:hover .hk, .mtop:focus-visible .hk { color: inherit; }
.drop {
  scrollbar-color: var(--drop-line) var(--drop-bg);
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 7;
  min-width: 26ch;
  max-width: calc(100vw - 16px);
  padding: 2px 0;
  background: var(--drop-bg);
  color: var(--drop-fg);
  border: var(--drop-edge);
  box-shadow: var(--drop-shadow);
}
.drop.r { left: auto; right: 0; }
.drop [role^="menuitem"] {
  display: grid;
  grid-template-columns: 2ch 1fr auto;
  gap: 0 1ch;
  width: 100%;
  min-height: 24px;
  padding: 0 1ch;
  white-space: nowrap;
}
.drop [role^="menuitem"]:hover, .drop [role^="menuitem"]:focus {
  background: var(--drop-on-bg); color: var(--drop-on-fg); outline: none;
}
.drop .tick { color: var(--drop-tick); }
.drop .hk, .drop.spellmenu .k { color: var(--drop-key); }
.drop [role^="menuitem"]:hover :is(.tick, .hk, .k), .drop [role^="menuitem"]:focus :is(.tick, .hk, .k) { color: inherit; }
.drop .sep { border-top: 1px solid var(--drop-line); margin: 2px 0; }
/* The hot letter is underlined as well as coloured, so it never relies
 * on colour alone (WCAG 1.4.1): in a drop-down it can be any letter. */
.mtop .hk, .drop .hk { text-decoration: underline; text-underline-offset: .15em; }
/* A submenu (►) drops out beside its item: to the right, to the left
 * (.l) near the right of the screen, or under the item (.under) where
 * neither fits, as on a phone. Its item keeps the bar while it is open. */
.drop .msub { position: relative; }
.drop.sub { top: -4px; left: 100%; min-width: 20ch; }
.drop.sub.l { left: auto; right: 100%; }
/* Under the item it covers the whole width, so no tick of the menu
 * behind it shows beside one of its items. */
.drop.sub.under { top: 100%; left: 0; right: 0; min-width: 0; }
.drop [aria-expanded="true"] { background: var(--drop-on-bg); color: var(--drop-on-fg); }
.drop [aria-expanded="true"] :is(.tick, .hk, .k) { color: inherit; }
/* Phones (phone.js has the same queries). The menus are a sheet as wide
 * as the screen, under all the menu names, so a drop-down never covers
 * a name. A submenu opens in its menu's place, under a row that goes
 * back (.back). */
@media (max-width: 560px), (pointer: coarse) and (max-height: 500px) {
  .menubar .mwrap { position: static; }
  .menubar .mwrap > .drop { left: 0; right: 0; min-width: 0; max-width: none; overflow-y: auto; overscroll-behavior: contain; }
  .drop .back {
    display: grid; grid-template-columns: 2ch 1fr; gap: 0 1ch; align-items: center;
    width: 100%; min-height: 24px; padding: 0 1ch; margin-bottom: 2px;
    border-bottom: 1px solid var(--drop-line); font-weight: var(--bw);
  }
  .drop .back:hover, .drop .back:focus { background: var(--drop-on-bg); color: var(--drop-on-fg); outline: none; }
}
/* A phone's touch screen: rows a thumb can hit, and no function keys,
 * which a phone has none of. A submenu keeps its ►. */
@media (pointer: coarse) and (max-width: 560px), (pointer: coarse) and (max-height: 500px) {
  .mtop, .drop [role^="menuitem"] { min-height: 44px; align-items: center; }
  .menubar .drop .k:not(.arrow) { display: none; }
  /* The rows of List files, Revisions and Key settings, their keys at
   * the foot, and Yes and No on the status line. */
  .row { min-height: 44px; align-items: center; }
  .foot button, .prompt button { min-height: 44px; }
}
/* The right-click menu of a misspelt word (spell.js), placed under the
 * word by script. Its hot keys are the letters and numbers on the right. */
.drop.spellmenu { position: fixed; top: 0; left: 0; z-index: 8; min-width: 22ch; font-size: var(--size); }
/* The right-click menu of List files and the dashboard (popmenu.js),
 * placed beside the pointer by script. Its keys are on the right. */
.drop.popmenu { position: fixed; top: 0; left: 0; z-index: 9; min-width: 22ch; }
.drop.popmenu .k { color: var(--drop-key); }
.drop .spelltitle { margin: -2px 0 2px; padding: 0 1ch; background: var(--drop-fg); color: var(--drop-bg); white-space: nowrap; }
/* The thesaurus box (thesaurus.js): the spelling menu's look, with the
 * meanings in a list that scrolls, and each meaning's part of speech
 * and first word as a heading. */
.drop.thes { min-width: 28ch; }
.drop.thes .thlist { max-height: min(55vh, 24em); overflow-y: auto; overscroll-behavior: contain; }
.drop .thhead { margin-top: 2px; padding: 0 1ch; color: var(--drop-key); white-space: nowrap; }
.drop [aria-disabled="true"] { color: var(--drop-off); cursor: default; }
.drop [aria-disabled="true"]:hover { background: none; color: var(--drop-off); }

/* ---------- Key bar ----------
 * One group of keys at a time (keybar.js), inside the same 80 columns as
 * the text, from column 1, as in DOS programs. The bar keeps the text's
 * font size so --gutter and ch match the text. Only the buttons are
 * smaller. More sits at the right-hand end. The labels are bright, like
 * the status line, so hover underlines rather than brightens. */
.fkeys {
  flex: none;
  color: var(--hi);
  display: flex;
  flex-wrap: wrap;
  column-gap: 1.5ch;
  padding: 0 var(--gutter) .4em;
  border-top: 1px solid var(--dim);
}
.fkeys button {
  display: flex;
  gap: .5ch;
  align-items: baseline;
  min-height: 32px;
  padding: .35em 0;
  white-space: nowrap;
  font-size: clamp(calc(13px * var(--scale)), 3.6vw, calc(var(--size) * .85));
}
.fkeys .more { margin-left: auto; }
/* The modifier of the group on show (Shift+, Alt+ or Ctrl+), before its
 * keys, as the rows of a key template were labelled. */
.fkeys .fk-mod {
  align-self: center;
  white-space: nowrap;
  font-size: clamp(calc(13px * var(--scale)), 3.6vw, calc(var(--size) * .85));
}
.fkeys b { background: var(--inv-bg); color: var(--inv-fg); font-weight: 400; padding: 0 .35ch; }
.fkeys button:hover { text-decoration: underline; text-underline-offset: .2em; }
.fkeys button[aria-pressed="true"] { font-weight: var(--bw); text-decoration: underline; text-underline-offset: .2em; }

/* ---------- The key bar on a phone (phonekeys.js) ----------
 * Only on a phone's touch screen, in place of the one above. Keys a
 * thumb can hit, in the screen's own colours, framed like the keys of a
 * key template, lit (inverted) while on. More opens a sheet over the
 * text with the rest, drawn like a List files box. */
.pkeys {
  flex: none;
  position: relative;
  color: var(--hi);
  padding: 4px var(--gutter);
  border-top: 1px solid var(--dim);
  font-size: clamp(calc(13px * var(--scale)), 3.8vw, calc(var(--size) * .85));
}
.pk-row { display: flex; flex-wrap: wrap; gap: 4px; }
.pk-row button { flex: 1 1 auto; }
.pkeys button { min-height: 44px; padding: 0 1ch; text-align: center; white-space: nowrap; }
.pk-row button, .pk-grid button { border: 1px solid var(--dim); }
.pkeys button[aria-pressed="true"], .pkeys [aria-expanded="true"] { background: var(--inv-bg); color: var(--inv-fg); }
.pkeys button:active { text-decoration: underline; text-underline-offset: .2em; }
.pk-more {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  z-index: 7;
  max-height: min(70vh, calc(100dvh - 140px));
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--bg);
  border: 3px double var(--fg);
  border-bottom: 0;
}
.pk-more .box-bar { position: sticky; top: 0; align-items: center; }
.pk-more h2 { font: inherit; font-weight: var(--bw); margin: 0; }
.pk-more .pk-close { text-decoration: underline; text-underline-offset: .2em; }
.pk-body { padding: 0 1ch .5em; }
.pk-more h3 { font: inherit; font-weight: var(--bw); color: var(--head); margin: .5em 0 .25em; }
.pk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(11ch, 1fr)); gap: 4px; }

/* ---------- Export dialog ----------
 * In the middle of the screen, over the dimmed document, in the colours
 * of the pull-down menus: a grey panel with a black shadow on blue and
 * paper, a double border in screen colours on green and amber. The
 * brackets show the chosen format and template, and the bar shows the
 * one with focus, as in the menus. The radio buttons themselves are
 * hidden but still take focus and are read out (exports.js). */
.dlg {
  scrollbar-color: var(--drop-line) var(--drop-bg);
  width: max-content;
  max-width: calc(100vw - 32px);
  max-height: calc(100dvh - 32px);
  margin: auto;
  padding: 0;
  overflow: auto;
  background: var(--drop-bg);
  color: var(--drop-fg);
  border: var(--drop-edge);
  box-shadow: var(--drop-shadow);
}
/* Dark enough to show on green and amber, whose screens are near black already */
.dlg::backdrop { background: rgba(0, 0, 0, .8); }
.dlg form { margin: 0; }
/* The title bar, with Close at its right, as on every dialog in the app.
 * Esc, Close or a click outside closes it: there is no Cancel in the
 * foot. Close shows in the panel's colours when it has focus, because
 * the chosen item's colour is the bar's own on green and amber. */
.dlg-bar { display: flex; align-items: flex-start; background: var(--drop-fg); color: var(--drop-bg); }
.dlg-title { flex: 1; min-width: 0; margin: 0; padding: 0 1ch; font: inherit; font-weight: var(--bw); overflow-wrap: anywhere; }
.dlg-close { flex: none; min-height: 24px; padding: 0 1ch; border-left: 1px solid var(--drop-bg); font-weight: var(--bw); white-space: nowrap; }
.dlg-close:hover, .dlg-close:focus { background: var(--drop-bg); color: var(--drop-fg); outline: none; }
.dlg-doc { margin: 0; padding: .25em 1ch 0; overflow-wrap: anywhere; }
.dlg-body { display: flex; flex-wrap: wrap; gap: .5em 3ch; padding: .25em 0 .5em; }
.dlg fieldset { flex: 1 1 auto; margin: 0; padding: 0; border: 0; min-width: 18ch; }
.dlg legend { padding: 0 1ch; font-weight: var(--bw); }
.dlg label { position: relative; display: flex; gap: 1ch; align-items: baseline; min-height: 24px; padding: 0 1ch; white-space: nowrap; cursor: pointer; }
.dlg label input { position: absolute; left: 0; top: 0; width: 1px; height: 1px; margin: 0; opacity: 0; pointer-events: none; }
.dlg .dot::before { content: "( )"; white-space: pre; }
.dlg input:checked + .dot::before { content: "(\2022)"; }
.dlg label b, .dlg-foot b { color: var(--drop-key); font-weight: var(--bw); }
/* "Changes not saved. Save them? (Yes) No" (unsaved.js) takes the foot's
 * place, in the panel's colours rather than the status line's. Before the
 * rule below, so Yes and No still invert with focus. */
.prompt.unsaved { flex-wrap: wrap; }
.dlg-foot .prompt { color: inherit; padding-left: 1ch; }
.dlg-foot .prompt button { color: inherit; }
.dlg label:hover, .dlg label:has(input:focus), .dlg-foot button:hover, .dlg-foot button:focus {
  background: var(--drop-on-bg); color: var(--drop-on-fg); outline: none;
}
.dlg label:hover b, .dlg label:has(input:focus) b, .dlg-foot button:hover b, .dlg-foot button:focus b { color: inherit; }
.dlg fieldset:disabled label { color: var(--drop-off); cursor: default; }
.dlg fieldset:disabled label:hover { background: none; color: var(--drop-off); }
.dlg fieldset:disabled b { color: inherit; }
.dlg-note { margin: .25em 0 0; padding: 0 1ch; max-width: 22ch; }
.dlg-foot { display: flex; flex-wrap: wrap; gap: 0 1ch; padding: .25em 0; border-top: 1px solid var(--drop-line); }
.dlg-foot button { min-height: 24px; padding: 0 1ch; white-space: nowrap; }

/* The link box (links.js): Text and Address, with a hint and an error
 * under the address. The field with focus shows inverted, as the chosen
 * item does in the menus. */
.dlg-fields { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: .25em 1ch; align-items: baseline; width: min(64ch, calc(100vw - 48px)); padding: .5em 1ch; }
.dlg .dlg-fields label { display: block; min-height: 0; padding: 0; cursor: default; font-weight: var(--bw); }
.dlg .dlg-fields label:hover { background: none; color: inherit; }
.dlg-fields input { width: 100%; min-height: 24px; padding: 0 .5ch; border: 0; border-bottom: 2px solid var(--drop-fg); border-radius: 0; background: transparent; color: var(--drop-fg); font: inherit; }
.dlg-fields input:focus { outline: none; background: var(--drop-on-bg); color: var(--drop-on-fg); border-bottom-color: var(--drop-on-bg); }
.dlg-hint, .dlg-error { grid-column: 2; margin: 0; overflow-wrap: anywhere; }
.dlg-error { font-weight: var(--bw); }
.dlg-error::before { content: "\25BA  "; } /* ► */

/* Properties (properties.js): three tabs, File, Export and Templates,
 * with the Link box's fields. The chosen tab shows like the title bar,
 * and the tab with focus like the chosen menu item. The top edge stays
 * put when a taller or shorter tab is chosen, so only the foot moves. */
.pr { width: min(64ch, calc(100vw - 32px)); margin: min(10vh, 80px) auto auto; max-height: calc(100dvh - min(10vh, 80px) - 16px); }
.pr-tabs { display: flex; flex-wrap: wrap; gap: 0 1ch; padding: .25em 1ch 0; border-bottom: 1px solid var(--drop-line); }
.pr-tabs [role="tab"] { min-height: 24px; padding: 0 1ch; white-space: nowrap; }
.pr-tabs [aria-selected="true"] { background: var(--drop-fg); color: var(--drop-bg); font-weight: var(--bw); }
.pr-tabs [role="tab"]:hover, .pr-tabs [role="tab"]:focus { background: var(--drop-on-bg); color: var(--drop-on-fg); outline: none; }
.pr .dlg-fields { width: auto; grid-template-columns: 11ch minmax(0, 1fr); }
/* A label longer than its column, such as About the author, goes onto two lines. */
.pr .dlg-fields > label { white-space: normal; }
/* Article and Letter, and the ebook cover: a box edge with the name in the line, as DOS dialogs drew them. */
.pr fieldset.dlg-fields { min-width: 0; margin: .25em 0 0; padding: 0 1ch .5em; border: 0; border-top: 1px solid var(--drop-line); }
.pr [hidden] { display: none; }
.dlg-fields textarea { display: block; width: 100%; min-height: 24px; padding: 0 .5ch; border: 0; border-bottom: 2px solid var(--drop-fg); border-radius: 0; background: transparent; color: var(--drop-fg); font: inherit; line-height: inherit; resize: vertical; }
.dlg-fields textarea:focus { outline: none; background: var(--drop-on-bg); color: var(--drop-on-fg); border-bottom-color: var(--drop-on-bg); }
.dlg-fields input:read-only, .dlg-fields textarea:read-only { border-bottom-style: dotted; }
.pr-note { max-width: none; margin: 0; padding: .25em 1ch .5em; }
.pr-facts { grid-column: 1 / -1; display: grid; grid-template-columns: 11ch minmax(0, 1fr); gap: 0 1ch; margin: .25em 0 0; }
.pr-facts dt { font-weight: var(--bw); }
.pr-facts dd { margin: 0; overflow-wrap: anywhere; }

/* A list box and a tick box in a dialog's fields (the Copyright tab of
 * Properties). The tick box is hidden, and [X] or [ ] shows its state,
 * as (•) or ( ) shows a radio button's. */
.dlg-fields select { width: 100%; min-height: 24px; padding: 0 .5ch; border: 0; border-bottom: 2px solid var(--drop-fg); border-radius: 0; background: var(--drop-bg); color: var(--drop-fg); font: inherit; }
.dlg-fields select:focus { outline: none; background: var(--drop-on-bg); color: var(--drop-on-fg); border-bottom-color: var(--drop-on-bg); }
.dlg-fields option { background: var(--drop-bg); color: var(--drop-fg); }
.dlg .chk::before { content: "[ ]"; white-space: pre; }
.dlg input:checked + .chk::before { content: "[X]"; }
.dlg .dlg-fields .pr-check { display: flex; gap: 1ch; min-height: 24px; padding: 0 .5ch; font-weight: normal; cursor: pointer; }
.dlg .dlg-fields .pr-check:hover, .dlg .dlg-fields .pr-check:has(input:focus) { background: var(--drop-on-bg); color: var(--drop-on-fg); }
.dlg .dlg-fields .pr-check:has(input:disabled) { color: var(--drop-off); cursor: default; background: none; }

/* The cover colours on the EPUB tab: their rows sit in the fields' grid,
 * and all go while the cover is off. Each is a field wide enough for
 * #1B2A4A, and the colour picker beside it as a swatch in a frame. Their
 * labels are inside .pr-cover, so they need their own rule to wrap. */
.pr-cover { display: contents; }
.pr .pr-cover > label { white-space: normal; }
.pr-colour { display: flex; align-items: center; gap: 1ch; }

/* The sign in box (signin.js), for a session that ended while the editor
 * was open: the Link box's fields, with a line of words above them, the
 * reason under them, and the forgotten password link in the foot looking
 * like the foot's buttons (still underlined, so it reads as a link). */
.si .dlg-doc { max-width: min(64ch, calc(100vw - 48px)); }
.si-sent { grid-column: 1 / -1; margin: 0; overflow-wrap: anywhere; }
.si-error { margin: 0; padding: 0 1ch .5em; }
.dlg-foot a { display: inline-flex; align-items: center; min-height: 24px; padding: 0 1ch; color: inherit; white-space: nowrap; }
.dlg-foot a:hover, .dlg-foot a:focus { background: var(--drop-on-bg); color: var(--drop-on-fg); outline: none; }
.pr .pr-colour input[type="text"] { flex: none; width: 9ch; }
.pr .pr-colour input[type="color"] { flex: none; width: 4ch; height: 24px; padding: 2px; border: 1px solid var(--drop-fg); background: transparent; cursor: pointer; }
.pr-colour input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
.pr-colour input[type="color"]::-webkit-color-swatch { border: 0; border-radius: 0; }
.pr-colour input[type="color"]::-moz-color-swatch { border: 0; border-radius: 0; }
.pr .pr-colour input[type="color"]:hover, .pr .pr-colour input[type="color"]:focus { outline: 2px solid var(--drop-fg); outline-offset: 1px; background: transparent; }
.pr .pr-colour input[type="color"]:disabled { border-style: dotted; cursor: default; outline: none; }

.pr-error { padding: 0 1ch .25em; }

/* ---------- Help screen ---------- */
.help-body { flex: 1; min-height: 0; overflow: auto; padding: .5em 1ch; }
.help-body:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.help-body h2 { font: inherit; font-weight: var(--bw); color: var(--hi); margin: 1em 0 .25em; }
.help-body p, .help-body ul { margin: 0 0 .6em; }
.help-body ul { padding-left: 2ch; }
.help-body code { font: inherit; color: var(--acc); }
/* The About screen (app/Views/editor/_about.php): the credits as a list
 * of short entries, each with its website and, where one goes with the
 * copy we send, its licence. */
.about-name { color: var(--head); font-weight: var(--bw); }
.help-body .credits { list-style: none; padding-left: 0; }
.credits li { margin: 0 0 .75em; }
.cr-name { display: block; color: var(--hi); font-weight: var(--bw); }
.cr-what { display: block; }
.cr-links { display: flex; flex-wrap: wrap; gap: 0 2ch; }
.cr-links a { display: inline-block; min-height: 24px; color: var(--hi); text-decoration: underline; text-underline-offset: .2em; }
.cr-links a:hover { background: var(--inv-bg); color: var(--inv-fg); }
.cr-links a:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
/* ---------- Writing stats (Alt+F8) ----------
 * The numbers bright, the names in the text colour, headings in the
 * heading colour. The charts (charts.js) are drawn like the disk bar:
 * hatched in the bright colour inside a thin frame, solid where the goal
 * was met, words deleted in dots of the accent colour, and the goal as a
 * dashed line in the heading colour. Every line and fill reaches 3:1
 * with the screen in each theme. */
.st-body { flex: 1; min-height: 0; overflow: auto; padding: .5em 1ch 1em; }
.st-body:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.st-body h2 { font: inherit; font-weight: var(--bw); color: var(--head); margin: 0 0 .25em; }
.st-body p { margin: 0 0 .5em; }
.st-sec + .st-sec { margin-top: 1.25em; }
.st-sum { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 0 2ch; margin: 0; }
.st-sum dd { margin: 0; color: var(--hi); }
.st-chart { margin: .25em 0; }
.st-top { color: var(--hi); }
.st-ends { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 0 2ch; }
.stats .box { min-width: 0; }
.st-cols7 { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); text-align: center; }
.st-hours { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.st-months { display: grid; grid-template-columns: repeat(53, minmax(0, 1fr)); white-space: nowrap; }
.st-note { margin-top: 1.25em; }
.cols { display: block; width: 100%; height: 7em; border: 1px solid var(--fg); }
.hbar { display: block; flex: 1; width: 100%; min-width: 0; height: .9em; border: 1px solid var(--fg); }
.year { display: block; width: 100%; height: auto; }
:is(.cols, .hbar, .year) .ink { fill: var(--hi); }
:is(.cols, .hbar, .year) .acc { fill: var(--acc); }
:is(.cols, .hbar) .met, .year .solid { fill: var(--hi); }
.cols .goal { stroke: var(--head); stroke-width: 2; stroke-dasharray: 6 4; }
.cols .base { stroke: var(--fg); stroke-width: 1; }
.cols .hit { fill: transparent; }
.hbar .edge { stroke: var(--hi); stroke-width: 2; }
.year .none { fill: none; stroke: var(--dim); stroke-width: 1; }
.year .day { stroke: var(--dim); stroke-width: 1; }
.yearkey { display: inline-flex; align-items: center; gap: 1ch; }
.yearkey .year { width: 6em; }
.meta .goalbar .hbar { flex: 1; }
.st-bars { list-style: none; margin: 0; padding: 0; }
.st-bars li { display: grid; grid-template-columns: 10ch minmax(0, 1fr) 9ch; gap: 1ch; align-items: center; }
.st-bars .n { text-align: right; color: var(--hi); }
.st-bars .short { display: none; }
.st-docs { width: 100%; border-collapse: collapse; table-layout: fixed; }
.st-docs th, .st-docs td { padding: 0 1ch 0 0; text-align: left; font-weight: 400; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.st-docs thead th { font-weight: var(--bw); color: var(--hi); border-bottom: 1px solid var(--dim); }
.st-docs thead th:first-child { width: 40%; }
.st-docs .n { text-align: right; color: var(--hi); }
.st-docs thead .n { width: 11ch; }
.st-docs .b { width: 20%; }
.st-docs tbody .nm { color: var(--fg); }
@media (max-width: 560px) {
  .st-sum { grid-template-columns: minmax(0, 1fr); }
  .st-sum dd { margin-bottom: .25em; padding-left: 2ch; }
  /* The bars and words deleted give the names room. */
  .st-docs :is(th, td):is(:nth-child(3), :nth-child(4)) { display: none; }
  .st-docs thead .n { width: 10ch; }
  .st-bars li { grid-template-columns: 4ch minmax(0, 1fr) 7ch; }
  .st-bars .long { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .st-bars .short { display: inline; }
}
/* ---------- No connection (offline.html, sent by the service worker) ---------- */
.offline .foot a { display: inline-block; min-height: 24px; padding: .2em 0; color: var(--hi); text-decoration: underline; text-underline-offset: .2em; }
.offline .foot a:hover { background: var(--inv-bg); color: var(--inv-fg); }

/* ---------- Error pages (app/Views/errors/html/_screen.php) and offline.html ----------
 * A big pixel title, a DOS prompt answering, then plain words. The
 * titles are SVGs made by resources/error-titles/make_titles.py from the
 * VGA font: two bands (bright over accent) with a hard shadow. The actions
 * look like the List files foot: the key bright, then the word. */
.err-body { padding: 1em 2ch; }
.err-body > * { max-width: 64ch; }
.err-title { font: inherit; margin: .5em 0 1.5em; }
.rp-pix { display: block; max-width: 100%; height: auto; }
.rp-pix .b1 { stop-color: var(--hi); }
.rp-pix .b2 { stop-color: var(--acc); }
.rp-pix .sh { fill: var(--sheet-shadow); }
.err-dos { margin: 0 0 1.5em; font-family: "IBM VGA 8x16", var(--font); font-size: var(--size); line-height: 1.25; white-space: pre-wrap; overflow-wrap: anywhere; }
.err-dos .pr, .err-dos .cur { color: var(--hi); }
.err-dos .cur { animation: rp-blink 1s steps(1) 3; }
.err-detail { margin-top: 1.5em; padding: .25em 1ch; border: 1px dashed var(--dim); overflow-wrap: anywhere; }
.err-detail h2 { font: inherit; font-weight: var(--bw); color: var(--head); margin: 0; }
.err-detail p { margin: 0; }
.err .foot a { display: inline-block; min-height: 24px; padding: .2em 0; color: var(--fg); text-decoration: none; white-space: nowrap; }
.err .foot :is(a, button) b { color: var(--hi); font-weight: var(--bw); }
.err .foot a:hover { background: var(--inv-bg); color: var(--inv-fg); }
.err .foot a:hover b { color: inherit; }

.keys { border-collapse: collapse; margin: 0 0 .5em; }
.keys th { text-align: left; font-weight: var(--bw); color: var(--hi); padding: 0 3ch 0 0; border-bottom: 1px solid var(--dim); }
.keys td { padding: 0 3ch 0 0; vertical-align: top; }
.keys .hk { color: var(--hi); white-space: nowrap; }
.keys .hm { color: var(--acc); white-space: nowrap; }

/* ---------- Start screen ---------- */
.splash {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1em;
  background: var(--bg);
  color: var(--fg);
}
.splash-box { border: 3px double var(--fg); padding: 1.5em 3ch; text-align: center; max-width: 100%; }
.splash p { margin: 0; }
.splash .big { color: var(--hi); font-size: 2em; line-height: 1.2; font-weight: var(--bw); letter-spacing: .15em; }
.splash .hint { color: var(--hi); }
.splash .cursor { color: var(--head); animation: rp-blink 1s steps(1) 3; }
.splash.gone { opacity: 0; visibility: hidden; transition: opacity .35s, visibility 0s .35s; }
@keyframes rp-blink { 50% { opacity: 0; } }

/* ---------- Scanlines for the screen themes ----------
 * Optional (View, Scanlines), and never when the browser asks
 * for more contrast or less motion, or in forced colours. The lighter
 * the screen, the fainter the lines, because dark lines show more. */
:root { --scan: rgba(0, 0, 0, .08); }
:root[data-skin="green"], :root[data-skin="amber"] { --scan: rgba(0, 0, 0, .15); }
:root[data-skin="paper"] { --scan: rgba(0, 0, 0, .05); }
:root:not([data-effects="off"]) body::after,
:root:not([data-effects="off"]) dialog > form::after {
  content: "";
  pointer-events: none;
  background: repeating-linear-gradient(to bottom, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 2px, var(--scan) 3px);
}
:root:not([data-effects="off"]) body::after { position: fixed; inset: 0; z-index: 40; }
/* A modal dialog sits in the top layer, above body::after, so it draws
 * its own lines. Its form holds all of it and scrolls with it. */
dialog > form { position: relative; }
:root:not([data-effects="off"]) dialog > form::after { position: absolute; inset: 0; }
@media (prefers-contrast: more), (prefers-reduced-motion: reduce), (forced-colors: active) {
  :root body::after, :root dialog > form::after { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .splash.gone { transition: none; }
  .splash .cursor { animation: none; }
  .status .l.blink { animation: none; }
  .err-dos .cur { animation: none; }
  :is(#text, #note-text) .cm-cursorLayer { animation: none; }
}

@media (forced-colors: active) {
  .box { border-color: CanvasText; }
  .splash-box { border-color: CanvasText; }
  .rp-pix .ink { fill: CanvasText; }
  .rp-pix .sh { display: none; }
  :is(#text, #note-text) .cm-cursor { forced-color-adjust: none; background: Highlight; color: HighlightText; }
  .err-detail { border-color: CanvasText; }
  .drop { border: 1px solid CanvasText; box-shadow: none; }
  .drop [role^="menuitem"]:focus, .mtop:focus { outline: 2px solid Highlight; outline-offset: -2px; }
  .dlg { border: 1px solid CanvasText; box-shadow: none; }
  .dlg-bar { border-bottom: 1px solid CanvasText; }
  .dlg label:has(input:focus), .dlg-foot button:focus, .dlg-foot a:focus, .dlg-close:focus { outline: 2px solid Highlight; outline-offset: -2px; }
  .dlg-close { border-left-color: CanvasText; }
  .dlg-fields input:focus, .dlg-fields textarea:focus, .dlg-fields select:focus { outline: 2px solid Highlight; outline-offset: 0; }
  .pr-tabs [aria-selected="true"] { border: 1px solid CanvasText; border-bottom-width: 3px; }
  .pr-tabs [role="tab"]:focus { outline: 2px solid Highlight; outline-offset: -2px; }
  .fkeys b { border: 1px solid CanvasText; }
  /* The phone's key bar: a key that is on, or More while open, stays lit. */
  .pkeys button[aria-pressed="true"], .pkeys [aria-expanded="true"] { forced-color-adjust: none; background: Highlight; color: HighlightText; }
  .pk-more { border-color: CanvasText; }
  .drop .back:focus { outline: 2px solid Highlight; outline-offset: -2px; }
  .disk .bar { forced-color-adjust: none; border-color: CanvasText; background: Canvas; }
  .disk pattern rect { fill: CanvasText; }
  .word-goal .bar { forced-color-adjust: none; border-color: ButtonText; background: Canvas; color: ButtonText; }
  .word-goal pattern rect { fill: ButtonText; }
  .word-goal .edge { stroke: ButtonText; }
  .disk .edge { stroke: CanvasText; }
  :is(.cols, .hbar, .year) { forced-color-adjust: none; border-color: CanvasText; background: Canvas; }
  :is(.cols, .hbar, .year) :is(.ink, .acc), :is(.cols, .hbar) .met, .year .solid { fill: CanvasText; }
  :is(.cols, .hbar) :is(.goal, .base, .edge), .year :is(.none, .day) { stroke: CanvasText; }
  :is(.row.cur, :not([aria-multiselectable="true"]) > .row[aria-selected="true"]) { outline: 2px solid Highlight; outline-offset: -2px; }
  .row.drop-on { outline: 2px dashed Highlight; }
  .box-bar { border-bottom: 1px solid CanvasText; }
  .ruler { border-top: 1px solid CanvasText; border-bottom: 1px solid CanvasText; }
  .ruler .stop { forced-color-adjust: none; background: CanvasText; }
  .ruler-bar .cells { border-bottom-color: CanvasText; }
  .ruler-bar .c::after { forced-color-adjust: none; background: CanvasText; }
  .ruler-bar .at::after { background: Highlight; }
  .outline { border-right-color: CanvasText; }
  .ol-stats { border-top-color: CanvasText; }
  .ol-row.cur, .ol-row.on { forced-color-adjust: none; background: Highlight; }
  .ol-row.cur :is(.ol-sign, .ol-words), .ol-row.on :is(.ol-sign, .ol-words) { forced-color-adjust: none; color: HighlightText; }
  .ol-tree:focus .ol-row.cur:not(.on), .ol-tree:focus .ol-row.cur:not(.on) :is(.ol-sign, .ol-words) { forced-color-adjust: auto; }
  .codeview .cur { forced-color-adjust: none; background: Highlight; color: HighlightText; }
  .codeview .sel { forced-color-adjust: none; background: Highlight; color: HighlightText; }
  .rp-undel, .rp-found { forced-color-adjust: none; background: Highlight; color: HighlightText; }
  .note-bar { border-bottom: 1px solid CanvasText; }
  .sheet { border-color: CanvasText; box-shadow: none; }
}
