/* Manicule's own layer, over the design system in ds/ (tokens.css and
   components.css). What's here is what only this app has: the library's
   rows, the readers, Focus mode, highlights and the minimap. Colours and
   sizes come from the system's tokens, plus the few below. */

/* Highlighter ink: the focus word yellow, saved highlights green, both
   multiplied into the text like marker on paper. On dark pages they're
   laid over it, fainter. */
:root {
  --mark: #f9dc86;
  --mark-blend: multiply;
  --mark-opacity: 1;
  --highlight-solid: #acf986;
  --highlight: var(--highlight-solid);
  --highlight-blend: multiply;
  --minimap-block: var(--stone-300);
  --minimap-view: red;
  /* What's behind a PDF's pages */
  --desk: var(--stone-200);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --mark-blend: normal;
    --mark-opacity: 0.45;
    --highlight: rgb(172 249 134 / 0.3);
    --highlight-blend: normal;
    --minimap-block: #4a4847;
    --desk: var(--stone-900);
  }
}
:root[data-theme="dark"] {
  --mark-blend: normal;
  --mark-opacity: 0.45;
  --highlight: rgb(172 249 134 / 0.3);
  --highlight-blend: normal;
  --minimap-block: #4a4847;
  --desk: var(--stone-900);
}

/* The mark beside the name: a manicule, the hand that points to a passage
   in old books' margins. Its box keeps the glyph's proportions. */
.brand-mark { width: 29px; height: 14px; flex: none; fill: currentColor; }
.brand { color: var(--fg); }

/* Dropdowns: a details element, its summary the button and a .menu the
   panel, under its right edge (or above, at the sidebar's foot). Closed by
   clicking outside or Escape (menu.js). */
.dropdown { position: relative; }
.dropdown > summary { list-style: none; cursor: pointer; }
.dropdown > summary::-webkit-details-marker { display: none; }
.dropdown > .menu { position: absolute; top: calc(100% + 4px); right: 0; z-index: 30; animation: menu-in var(--duration) var(--ease-out); }
.dropdown--up > .menu { top: auto; bottom: calc(100% + 4px); left: 0; right: 0; }
.dropdown[open] > summary.btn { background: var(--bg-selected); color: var(--fg); }
/* Links and the log-out form's button, drawn as items */
.menu > a, .menu > form > button { display: flex; align-items: center; gap: var(--space-2); width: 100%; min-height: 32px; padding: 0 var(--space-2); border: 0; border-radius: var(--radius-md); background: none; color: var(--fg); text-align: left; }
.menu > a > .i, .menu > form > button > .i { color: var(--fg-muted); }
.menu > a:hover, .menu > form > button:hover { background: var(--bg-hover); }
.menu > form { margin: 0; }
/* A setting: its name, and its switch at the end */
.menu > label.menu-item { justify-content: space-between; gap: var(--space-6); cursor: pointer; }
.menu > [hidden] { display: none; }

/* The shell: the sidebar on wide screens. On a phone it's a bar across the
   top with the name and account, and the tab bar takes its links. */
.main { min-width: 0; }
.sidebar .brand { margin-bottom: var(--space-1); }
.sidebar .account-menu { width: 100%; }
.account .points { color: inherit; }
.account .points .unit { font-size: inherit; }
.tabbar { display: none; }
@media (max-width: 759px) {
  .shell { display: block; }
  .sidebar {
    position: sticky;
    z-index: 25;
    flex-direction: row;
    align-items: center;
    height: auto;
    padding: var(--space-2) var(--space-3) var(--space-2) var(--space-4);
    border-right: 0;
    border-bottom: 1px solid var(--border-subtle);
    background: color-mix(in srgb, var(--bg-subtle) 92%, transparent);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    overflow: visible;
  }
  .sidebar .brand { margin: 0; padding: 0; }
  .sidebar .nav { display: none; }
  .sidebar-foot { margin: 0 0 0 auto; }
  .sidebar .account-menu { width: auto; }
  .sidebar .account { padding: var(--space-1) var(--space-2); }
  .sidebar .account .who { flex: none; }
  .sidebar .account #username { display: none; }
  .sidebar .account .who small { color: var(--fg-secondary); font-size: var(--text-sm); }
  .dropdown--up > .menu { top: calc(100% + 4px); bottom: auto; left: auto; right: 0; }
  .tabbar { display: grid; }
}

/* Page heads: the title, its action across */
.page-head .titles { min-width: 0; flex: 1; }
.empty-line { margin: var(--space-6) 0 0; padding: var(--space-10) var(--space-4); color: var(--fg-muted); text-align: center; }

/* Library */
.library ul { margin: 0; padding: 0; list-style: none; }
.library ul:empty { display: none; }
.page-tabs { margin-bottom: var(--space-4); }
.page-tabs[hidden] { display: none; }
@media (min-width: 760px) {
  .page-tabs { display: none; }
  /* A full page of rows ends at its last one, with nothing under it to
     scroll to on a screen just tall enough for them. */
  .library.page-main { padding-bottom: 0; }
}
.toolbar .end { align-items: center; }
.toolbar .pager { margin-right: var(--space-2); }
.library .sort { display: inline-flex; gap: var(--space-2); }
.library .sort[hidden], .library .filters[hidden], #direction[hidden] { display: none; }
.library .filters button[hidden] { display: none; }
/* Renaming a list on its page: the field in the name's place */
.library h1 .rename { width: 100%; height: auto; margin: -2px 0 -2px -9px; padding: 1px 8px; font: inherit; letter-spacing: inherit; border: 1px solid var(--accent); border-radius: var(--radius-md); background: var(--bg-raised); box-shadow: var(--ring); outline: 0; }

/* List view: a table's columns, a row each, with headings over them. Its
   columns: thumbnail, title and source, progress, last read, menu. */
.list-head, .library ul:not(.grid, .compact) > li {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) 128px 104px 32px;
  align-items: center;
  column-gap: var(--space-3);
}
.list-head {
  height: 36px;
  padding: 0 var(--space-2);
  border-bottom: 1px solid var(--border-subtle);
  color: var(--fg-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}
.list-head > :first-child { grid-column: 1 / 3; }
.list-head[hidden] { display: none; }
.library ul > li {
  position: relative;
  padding: var(--space-3) var(--space-2);
  border-bottom: 1px solid var(--border-subtle);
  transition: background-color var(--duration-fast);
}
.library ul:not(.grid) > li:hover { background: var(--bg-subtle); }
.library .info { min-width: 0; }
.library .info > a {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  font-weight: var(--weight-medium);
  overflow-wrap: anywhere;
}
.library .meta {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  margin-top: 1px;
  color: var(--fg-muted);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
}
.library .meta > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.library .meta > span + span::before { content: "·"; margin-right: 6px; opacity: 0.7; }
.library .meta .time { display: inline-flex; align-items: center; gap: 4px; flex: none; }
.library .meta .time.done { color: var(--success); }
/* In list view the time sits by its progress bar instead */
.library ul:not(.grid, .compact) .meta .time { display: none; }
.library .progress { display: flex; align-items: center; gap: var(--space-3); white-space: nowrap; }
.library .progress .meter { flex: none; width: 56px; }
.library .progress { color: var(--fg-secondary); font-size: var(--text-sm); }
.library .progress.done { gap: 6px; color: var(--success); font-weight: var(--weight-medium); }
.library .when { color: var(--fg-muted); font-size: var(--text-sm); white-space: nowrap; }
.library .actions { display: flex; justify-content: flex-end; }
.library .actions .btn { color: var(--fg-muted); opacity: 0; }
.library li:hover .actions .btn, .library .actions .btn:focus-visible, .library .actions .btn.open { opacity: 1; }
.library .actions .btn.open { background: var(--bg-selected); color: var(--fg); }
@media (hover: none) { .library .actions .btn { opacity: 1; } }
.library li.dragging { opacity: 0.4; }
.library li[draggable="true"] { cursor: grab; }

/* Thumbnails: a PDF's page or cover, an article's picture, or else a tile
   in its site's tint with the site's initial (the title, in a grid). */
.library .thumb-wrap { position: relative; flex: none; }
.library .thumb {
  position: relative;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  overflow: hidden;
  border-radius: var(--radius-md);
  background: var(--bg-muted);
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.06);
}
.library li.pdf .thumb { width: 30px; height: 40px; margin-left: 5px; border-radius: 3px; box-shadow: 0 1px 2px rgb(0 0 0 / 0.12), inset 0 0 0 1px rgb(0 0 0 / 0.06); }
.library .thumb img, .library .thumb canvas { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; object-fit: cover; object-position: top; }
.library li.article .thumb img, .library li.article .thumb canvas { object-position: center; }
.library li.article .thumb img[src*=".gif" i] { visibility: hidden; }
/* A transparent picture is backed in white, in either theme, since such
   pictures are mostly made for white pages; the tile under it would show. */
.library .thumb img { background: #fff; }
.text-thumb { position: absolute; inset: 0; display: grid; place-items: center; font-weight: var(--weight-semibold); }
.text-thumb .initial { font-size: 17px; letter-spacing: -0.02em; }
.text-thumb .t, .text-thumb .s { display: none; }
.library ul:not(.only-finished) .thumb-wrap.finished .thumb > * { opacity: 0.45; }
.library .thumb .spinner { width: 14px; height: 14px; }
.library .thumb-edit {
  position: absolute;
  right: -4px;
  bottom: -4px;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-raised);
  color: var(--fg-secondary);
  box-shadow: var(--shadow-sm);
  opacity: 0;
  transition: opacity var(--duration-fast);
}
.library .thumb-wrap:hover .thumb-edit, .library .thumb-edit:focus-visible { opacity: 1; }
@media (hover: none) { .library .thumb-edit { opacity: 1; } }

/* The link to an article's original: its site's name and a small arrow */
.source { display: inline-flex; align-items: center; gap: 3px; max-width: 100%; color: inherit; }
.source:hover { color: var(--fg); }
.source .name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.source .arrow { width: 12px; height: 12px; flex: none; opacity: 0.7; }

/* Compact view: a line each, no thumbnails, details in columns */
.library ul.compact > li { display: flex; align-items: center; gap: var(--space-3); padding: 7px var(--space-2); }
.library ul.compact .thumb-wrap, .library ul.compact .when { display: none; }
/* Grid and compact views show how far through with the bar alone, as
   their details already say how long is left */
.library ul.compact .progress-time, .library ul.grid .progress-time,
.library ul.compact .progress.done, .library ul.grid .progress.done { display: none; }
.library ul.compact .progress .meter { width: 40px; }
.library ul.compact .info { flex: 1; display: flex; align-items: baseline; gap: var(--space-4); }
.library ul.compact .info > a { flex: 1; min-width: 0; display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.library ul.compact .meta { flex: none; display: grid; grid-template-columns: 10em 6em; gap: var(--space-4); }
.library ul.compact .meta > span::before { content: none; }
.library ul.compact .meta .author { grid-column: 1; }
.library ul.compact .meta .time { grid-column: 2; justify-content: flex-end; }

/* Grid view: covers, a PDF's 3:4 and an article's square, with the title
   set on the tile when there's no picture */
.library ul.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(152px, 1fr)); gap: var(--space-6) var(--space-4); padding-top: var(--space-2); }
.library ul.grid > li { display: grid; grid-template-columns: 100%; align-content: start; gap: var(--space-2); padding: 0; border: 0; }
.library ul.grid .thumb-wrap { grid-area: 1 / 1; width: 100%; }
.library ul.grid .thumb, .library ul.grid li.pdf .thumb { width: 100%; height: auto; aspect-ratio: 3 / 4; margin: 0; border-radius: var(--radius-lg); box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.06), var(--shadow-xs); }
.library ul.grid li.article .thumb, .library ul.grid.mixed li .thumb { aspect-ratio: 1; }
.library ul.grid .text-thumb { place-items: stretch; grid-template-rows: 1fr auto; padding: var(--space-3); text-align: left; }
.library ul.grid .text-thumb .initial { display: none; }
.library ul.grid .text-thumb .t { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 5; overflow: hidden; font-size: 15px; line-height: 19px; letter-spacing: -0.02em; }
.library ul.grid .text-thumb .s { display: block; overflow: hidden; font-size: 11px; line-height: 14px; font-weight: var(--weight-medium); opacity: 0.8; text-overflow: ellipsis; white-space: nowrap; }
.library ul.grid .when { display: none; }
/* The bar sits on the foot of the cover. */
.library ul.grid .progress { grid-area: 1 / 1; align-self: end; z-index: 4; margin: 0 -0.5px -0.5px; pointer-events: none; }
.library ul.grid .progress .meter { flex: 1; height: 3px; }
/* A faint border round the cover's top and sides, just outside it, under
   the bar where they meet; the bar makes its foot. */
.library ul.grid .thumb-wrap::after { content: ""; position: absolute; inset: -1px; z-index: 3; border: 1px solid var(--border-subtle); border-bottom: 0; border-radius: calc(var(--radius-lg) + 1px); pointer-events: none; }
.library ul.grid .info > a { line-height: 19px; }
.library ul.grid .meta { flex-direction: column; align-items: stretch; gap: 0; }
.library ul.grid .meta > span::before { content: none; }
.library ul.grid .actions { position: absolute; top: 6px; right: 6px; z-index: 2; }
.library ul.grid .actions .btn { background: color-mix(in srgb, var(--bg-raised) 88%, transparent); box-shadow: var(--shadow-sm); }
.library ul.grid .thumb-edit { right: 6px; bottom: 10px; }

@media (max-width: 759px) {
  .list-head { display: none; }
  .library ul:not(.grid, .compact) > li { grid-template-columns: 40px minmax(0, 1fr) 32px; }
  .library ul:not(.grid, .compact) .progress, .library ul:not(.grid, .compact) .when { display: none; }
  .library ul:not(.grid, .compact) .meta .time { display: inline-flex; }
  .library ul.compact .meta { grid-template-columns: 5.5em; }
  .library ul.compact .meta .author { display: none; }
  .library ul.compact .meta .time { grid-column: 1; }
  .library ul.grid { grid-template-columns: 1fr 1fr; gap: var(--space-5) var(--space-4); }
  .toolbar .end { margin-left: 0; }
}

/* Book suggestions under the name while renaming a PDF (rename.js) */
.library .rename { display: block; width: 100%; height: 28px; padding: 0 8px; margin-left: -9px; border: 1px solid var(--accent); border-radius: var(--radius-md); background: var(--bg-raised); box-shadow: var(--ring); font-weight: var(--weight-medium); outline: 0; }
.library .rename-wrap { position: relative; }
.library .suggestions {
  position: absolute;
  top: calc(100% + 4px);
  left: -9px;
  z-index: 20;
  width: max(100%, 22rem);
  max-height: 60vh;
  overflow-y: auto;
  padding: var(--space-1);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  background: var(--bg-raised);
  box-shadow: var(--shadow-md);
}
.library .suggestion { display: flex; align-items: center; gap: var(--space-2); padding: 6px var(--space-2); border-radius: var(--radius-md); cursor: pointer; }
.library .suggestion.active { background: var(--bg-hover); }
.library .suggestion .cover { flex: none; width: 24px; height: 36px; border-radius: 2px; object-fit: cover; background: var(--bg-muted); }
.library .suggestion .title { font-weight: var(--weight-medium); line-height: 18px; }
.library .suggestion .meta { margin: 0; }

/* The row, add and lists menus: popovers placed by library.js */
#row-menu, #list-menu, #add-menu { max-width: min(20rem, calc(100vw - 16px)); max-height: 60vh; overflow-y: auto; }
#row-menu:empty { display: none; }
#list-menu .menu-back { color: var(--fg-muted); }
#list-menu .list-choices:not(:empty) { margin: 0 calc(var(--space-1) * -1); padding: var(--space-1); border-top: 1px solid var(--border-subtle); }
#list-menu .toggle { white-space: normal; overflow-wrap: anywhere; cursor: pointer; }
#list-menu form { margin: var(--space-1) calc(var(--space-1) * -1) calc(var(--space-1) * -1); padding: var(--space-2); border-top: 1px solid var(--border-subtle); }
#list-menu .input { height: var(--control-sm); }

/* Adding, in the Add dialog: a picture of it, its name and how far along */
.pane { display: grid; gap: var(--space-2); }
.pane[hidden], .dialog-foot .btn[hidden], .dialog-tabs[hidden] { display: none; }
.dialog-tabs button { display: inline-flex; align-items: center; gap: 6px; }
.dialog-tabs .active { color: var(--fg); }
.dialog-tabs .active::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; border-radius: 2px; background: var(--accent); }
.dropzone > * { pointer-events: none; }
.dropzone.over { border-color: var(--accent); background: var(--accent-subtle); color: var(--fg-secondary); }
.adding-head { display: grid; justify-items: center; gap: var(--space-3); text-align: center; }
.adding-thumb { display: grid; place-items: center; width: min(10rem, 50vw); aspect-ratio: 1; overflow: hidden; border-radius: var(--radius-lg); background: var(--bg-muted); box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.06); }
.adding-thumb img, .adding-thumb canvas { width: 100%; height: 100%; object-fit: cover; }
.adding-thumb canvas { object-position: top; }
.adding-text { max-width: 100%; min-width: 0; }
.adding-name { overflow: hidden; font-weight: var(--weight-medium); text-overflow: ellipsis; white-space: nowrap; }
.adding-state { font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.adding-state.error { color: var(--danger); }
.adding-track { margin-top: var(--space-2); }
.adding-track[hidden] { display: none; }
.adding-fill { width: 0; }
.adding-track.unknown > .adding-fill { width: 30% !important; animation: to-and-fro 1.2s var(--ease-in-out) infinite alternate; }

/* Adding to a list from the library: a search over a short list to pick from */
#library-choices { max-height: 40vh; margin: 0; padding: var(--space-1); overflow-y: auto; list-style: none; border: 1px solid var(--border-subtle); border-radius: var(--radius-lg); }
#library-choices:not(:has(li:not([hidden]))) { display: none; }
#library-choices button { display: flex; align-items: center; gap: var(--space-2); width: 100%; min-height: 34px; padding: 0 var(--space-2); border: 0; border-radius: var(--radius-md); background: none; text-align: left; }
#library-choices button:hover:not(:disabled) { background: var(--bg-hover); }
#library-choices .box { width: 16px; height: 16px; flex: none; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--bg-raised); }
#library-choices button.picked .box { border-color: var(--accent-strong); background: var(--accent-strong) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / 11px no-repeat; }
#library-choices .name { flex: 1; min-width: 0; overflow: hidden; font-weight: var(--weight-medium); text-overflow: ellipsis; white-space: nowrap; }
#library-choices .muted { flex: none; font-size: var(--text-sm); }
#library-empty { margin: 0; text-align: center; }

/* Cropping a thumbnail: a 3:4 frame and a zoom slider */
.thumb-auto { display: flex; }
.thumb-auto #thumb-auto-more { width: 24px; margin-left: -6px; }
.thumb-auto #thumb-auto-more[hidden] { display: none; }
.cropper-frame { display: flex; justify-content: center; height: min(52vh, 360px); }
.cropper-canvas { height: 100%; width: auto; aspect-ratio: 3 / 4; border-radius: var(--radius-md); background: var(--bg-muted); cursor: grab; touch-action: none; }
.cropper-canvas:active { cursor: grabbing; }
.cropper-frame.over .cropper-canvas { outline: 2px dashed var(--accent); outline-offset: 3px; }
.cropper-zoom-row { display: flex; align-items: center; gap: var(--space-3); color: var(--fg-muted); }
.cropper-zoom { flex: 1; accent-color: var(--accent); }

/* Lists page: a tile in the list's tint */
.lists .list-tile { display: grid; place-items: center; }
.lists .list-tile .i { width: 18px; height: 18px; }
.lists ul > li { grid-template-columns: 40px minmax(0, 1fr) 32px !important; }

/* Admin */
.admin .tabs { margin-bottom: var(--space-4); }
.admin .tabs a.active { color: var(--fg); }
.admin .tabs a.active::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; border-radius: 2px; background: var(--accent); }
.admin .status { margin-bottom: var(--space-2); color: var(--fg-muted); font-size: var(--text-sm); }
.admin h2 { margin: 0 0 var(--space-4); font-size: var(--text-xl); line-height: var(--leading-xl); }
.admin h3 { margin: var(--space-10) 0 var(--space-2); font-size: var(--text-lg); line-height: var(--leading-lg); }
.admin .details dd { overflow-wrap: anywhere; }
/* Links in the text's colour, as in the library: orange is for what's on */
.admin .details a, .admin td a { color: var(--fg); font-weight: var(--weight-medium); }
.admin .details a:hover, .admin td a:hover { text-decoration: underline; text-decoration-color: var(--fg-faint); text-underline-offset: 3px; }
.admin .actions { margin-top: var(--space-6); }
.admin .actions .buttons { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.admin .password-form { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: var(--space-3); }
.admin .password-form .input { width: 16rem; }
.admin .password-form[hidden] { display: none; }
.admin .doc-top { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-8); }
.admin .doc-top .thumb { width: 160px; aspect-ratio: 3 / 4; border-radius: var(--radius-lg); object-fit: cover; box-shadow: var(--shadow-sm); }
.admin .doc-top .thumb.square { aspect-ratio: 1; }
.admin .table-wrap { overflow-x: auto; }
.admin .table td, .admin .table th { white-space: nowrap; }
.admin .table .title { max-width: 360px; overflow: hidden; text-overflow: ellipsis; }

/* Logging in and out, and errors */
.solo-brand { justify-content: center; margin: 0 0 var(--space-6); padding: 0; }
.solo-card .muted { margin: 0 0 var(--space-5); }
/* An error: the logo, a title, a line and a way back, in the middle of
   the page without a card */
.error-solo { place-items: center; padding-top: var(--space-8); background: var(--bg); }
.error-card { width: min(360px, 100%); text-align: center; }
.error-card .solo-brand { justify-content: center; margin-bottom: var(--space-8); }
.error-card h1 { margin: 0 0 var(--space-2); font-size: var(--text-xl); line-height: var(--leading-xl); }
.error-card p { margin: 0 0 var(--space-6); color: var(--fg-muted); }

/* The toast's Undo, named for the tests and scripts that find it */
.toast .undo { flex: none; }

/* ==========================================================================
   The readers
   ========================================================================== */

/* The header and heatmap bar lie over the page, so Autohide sliding them
   away doesn't move the text. The page is padded by --top-bars-h, their
   height together, which autohide.js sets; the fallbacks are close. */
body.reader { --header-h: 48px; --top-bars-h: 52px; }
.reader-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 21;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--space-3);
  height: 48px;
  padding: 0 var(--space-3);
  background: var(--bg);
  transition: transform var(--duration-slow) var(--ease-out);
}
.reader-bar .start, .reader-bar .middle, .reader-bar .end { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.reader-bar .end { justify-content: flex-end; }
.reader-bar .back { padding-left: var(--space-2); }
.reader-bar .back .label { overflow: hidden; text-overflow: ellipsis; max-width: 16rem; }
.reader-bar .group input { height: 100%; padding: 0 var(--space-1); border: 0; background: none; color: var(--fg); font-size: var(--text-sm); text-align: center; font-variant-numeric: tabular-nums; -moz-appearance: textfield; appearance: textfield; }
.reader-bar .group input::-webkit-inner-spin-button, .reader-bar .group input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.reader-bar .points { display: inline-flex; align-items: center; gap: 6px; padding: 0 var(--space-2); color: var(--fg-secondary); font-size: var(--text-sm); font-weight: var(--weight-medium); font-variant-numeric: tabular-nums; white-space: nowrap; }
.reader-bar .points::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.reader-bar .points .unit { color: var(--fg-muted); font-weight: var(--weight-regular); }

/* Focus mode's switch: tinted orange while it's on */
.focus-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: var(--control-md);
  padding: 0 var(--space-2) 0 var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-raised);
  box-shadow: var(--shadow-xs);
  font-weight: var(--weight-medium);
  cursor: pointer;
  user-select: none;
  transition: background-color var(--duration) var(--ease-out), border-color var(--duration) var(--ease-out), color var(--duration) var(--ease-out);
}
.focus-toggle > .i { color: var(--fg-muted); transition: color var(--duration) var(--ease-out); }
.focus-toggle:hover { border-color: var(--border-strong); }
.focus-toggle:has(:checked) { border-color: color-mix(in srgb, var(--accent) 45%, transparent); background: var(--accent-subtle); color: var(--accent-text); }
.focus-toggle:has(:checked) > .i { color: var(--accent); }

/* The heatmap: how often each part's been read, under the header (see
   heatmap.js) */
#progress { position: fixed; top: var(--header-h); left: 0; right: 0; z-index: 20; height: 4px; background: var(--bg-muted); box-shadow: 0 1px 0 var(--border-subtle); transition: transform var(--duration-slow) var(--ease-out); }
#progress canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
body.header-hidden .reader-bar { transform: translateY(-100%); }
body.header-hidden #progress { transform: translateY(calc(-1 * var(--header-h))); }
/* Where the header was, to bring it back by hovering */
.header-zone { display: none; }
body.header-hidden .header-zone { position: fixed; top: 0; left: 0; right: 0; z-index: 19; display: block; height: var(--header-h); }

/* A pinch over a reader zooms what's being read, not the page (page.js) */
body.reader #viewer { touch-action: pan-x pan-y; }
html:has(body.reader), body.reader { height: 100%; }
body.reader { display: flex; flex-direction: column; }
body.reader main { position: relative; flex: 1; overflow: hidden; }
#viewer { position: absolute; inset: 0; overflow: auto; }
#message { position: absolute; top: calc(var(--space-8) + var(--top-bars-h)); left: 0; right: 0; margin: 0; padding: 0 var(--space-4); color: var(--fg-muted); text-align: center; }

/* The settings: Vibrate only on touch screens, and the others only where
   they apply */
#focus-stick, .settings .vibrate-toggle { display: none; }
@media (pointer: coarse) {
  .settings .vibrate-toggle:not([hidden]) { display: flex; }
}
@media (max-width: 940px) { .minimap, .settings .minimap-toggle { display: none !important; } }
@media (max-width: 1023px) { .contents, .settings .contents-toggle { display: none !important; } }
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) .settings .dark-pages-toggle { display: none; } }
:root[data-theme="light"] .settings .dark-pages-toggle { display: none; }

/* Just above a phone's width, the article reader's Width control
   leaves no room for Original's label. */
@media (max-width: 899px) {
  .article-reader .reader-bar .original .label { display: none; }
  .article-reader .reader-bar .original { width: var(--control-md); padding: 0; }
}

/* On a phone the readers keep to one line: controls go down to their
   icons, and the PDF's zoom and page count go. */
@media (max-width: 759px) {
  .reader-bar { grid-template-columns: auto 1fr auto; gap: var(--space-1); padding: 0 var(--space-2); }
  .reader-bar .middle { justify-content: center; gap: var(--space-1); }
  .reader-bar .end { gap: 0; }
  .reader-bar .back { width: var(--control-md); padding: 0; }
  .reader-bar .back .label, .reader-bar .original .label, .reader-bar .points .unit,
  #size, .reader-bar .zoom, #fit-page, .reader-bar .width { display: none; }
  .reader-bar .group.fit > * + * { border-left: 0; }
  .reader-bar .original { width: var(--control-md); padding: 0; }
  .focus-toggle { padding: 0 var(--space-2); }
  .reader-bar .points { padding: 0 var(--space-1); }
}

/* The article: one 680px column, its heading and byline over the text */
.article-reader .article { position: relative; max-width: 712px; margin: 0 auto; padding: calc(var(--space-12) + var(--top-bars-h)) var(--space-4) 50vh; overflow-wrap: break-word; isolation: isolate; font-size: 18px; line-height: 1.7; letter-spacing: -0.011em; }
.article-reader .article[hidden] { display: none; }
.article-reader.serif .article { font-family: var(--font-serif); font-feature-settings: normal; letter-spacing: 0; }
.settings .font-choice { margin: var(--space-1) var(--space-1) var(--space-2); white-space: nowrap; }
.font-choice [data-font="serif"] { font-family: var(--font-serif); font-feature-settings: normal; }
.article-reader.serif .article .byline { font-family: var(--font); font-feature-settings: var(--font-features); letter-spacing: var(--tracking); }
.article-reader .article h1 { margin: 0 0 var(--space-4); font-size: 2.1em; line-height: 1.18; letter-spacing: -0.03em; text-wrap: balance; }
.article-reader .byline { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; margin: 0 0 var(--space-10); padding-bottom: var(--space-6); border-bottom: 1px solid var(--border-subtle); color: var(--fg-muted); font-size: var(--text-md); line-height: var(--leading-md); letter-spacing: var(--tracking); }
.article-reader .byline .source { color: var(--fg); font-weight: var(--weight-medium); }
.content h2 { margin: 1.7em 0 0.5em; font-size: 1.3em; line-height: 1.3; letter-spacing: -0.02em; }
.content h3 { margin: 1.5em 0 0.4em; font-size: 1.12em; line-height: 1.35; letter-spacing: -0.015em; }
.content h4, .content h5, .content h6 { margin: 1.4em 0 0.3em; font-size: 1em; }
.content p { margin: 0 0 1.1em; }
.content img, .content video, .content iframe { max-width: 100%; height: auto; border-radius: var(--radius-md); }
.content pre { overflow-x: auto; padding: var(--space-3) var(--space-4); border-radius: var(--radius-lg); background: var(--bg-subtle); font-size: 0.82em; line-height: 1.55; }
.content code { font-size: 0.88em; }
.content figure { margin: 1.5em 0; }
.content figcaption { margin-top: var(--space-2); color: var(--fg-muted); font-size: var(--text-sm); line-height: var(--leading-sm); }
.content blockquote { margin: 1.4em 0; padding-left: 1em; border-left: 1px solid var(--border); color: var(--fg-secondary); }
.content hr { margin: 2em 0; border: 0; border-top: 1px solid var(--border-subtle); }
.content table { display: block; overflow-x: auto; border-collapse: collapse; font-size: 0.88em; }
.content td, .content th { padding: 0.35em 0.6em; border: 1px solid var(--border-subtle); }
/* Links in the text's colour, underlined faintly. Important, as articles
   keep their source's inline styles, which can style a link or what's
   inside it. */
.byline a:not(.source), .byline a:not(.source) *, .content a, .content a * {
  border-bottom: none !important;
  box-shadow: none !important;
  background-image: none !important;
}
.content a { color: inherit; font-weight: var(--weight-medium); text-decoration: underline !important; text-decoration-color: color-mix(in srgb, var(--fg) 30%, transparent) !important; text-decoration-thickness: 1px !important; text-underline-offset: 3px; }
.content a:hover { text-decoration-color: var(--accent) !important; }

/* Contents: left of the column, scrolling on its own when long */
.contents {
  position: absolute;
  top: calc(var(--space-12) + var(--top-bars-h));
  bottom: var(--space-4);
  right: calc(50% + 356px + var(--space-6));
  width: min(220px, calc(50% - 356px - var(--space-10)));
  overflow-y: auto;
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
}
/* Indented by level in contents.js; the section being read has a bar */
.contents a { display: block; padding: 5px 0 5px 12px; border-left: 1px solid var(--border); color: var(--fg-muted); }
.contents a:hover { color: var(--fg); }
.contents a.current { color: var(--fg); font-weight: var(--weight-medium); border-left: 2px solid var(--accent); padding-left: 11px; }

/* Back to the top, bottom right over the page, where the joystick goes
   while Focus is on */
#top { position: absolute; right: var(--space-5); bottom: var(--space-5); z-index: 6; }
@media (pointer: coarse) { body:has(#focus:checked) #top { display: none; } }

/* Highlights sit behind the text, so they tint only around it; the mark
   is over it */
#highlight-layer { position: absolute; inset: 0; z-index: -1; pointer-events: none; }
#highlight-layer div { position: absolute; border-radius: 2px; background: var(--highlight); mix-blend-mode: var(--highlight-blend); }
.article-reader #mark { position: absolute; z-index: 10; mix-blend-mode: var(--mark-blend); opacity: var(--mark-opacity); pointer-events: none; }
.article-reader #mark div { position: absolute; background: var(--mark); box-shadow: 0 0 0 2px var(--mark); }

/* Minimap: just right of the column, hidden where it wouldn't fit. Placed
   in the scrolling view's positioned parent. */
.minimap { position: absolute; left: calc(50% + 356px + var(--space-4)); z-index: 5; width: 100px; overflow: hidden; background: var(--bg); cursor: pointer; user-select: none; -webkit-user-select: none; }
.minimap .copy { transform-origin: top left; pointer-events: none; }
.minimap .copy span.w { color: transparent; background: var(--minimap-block); }
.minimap .copy span.w.hl { background: var(--highlight-solid); }
.minimap .copy span.w.cur { background: var(--mark); }
.minimap .view { position: absolute; left: 0; right: 0; z-index: 1; border: 2px solid var(--minimap-view); border-radius: 3px; cursor: grab; touch-action: none; }
.minimap .view.dragging { cursor: grabbing; }

/* The PDF: pages on a desk of grey, all the way down, as a phone can show
   more than the page's height when its toolbars slide away */
html:has(body.pdf-reader), body.pdf-reader, body.pdf-reader main { background: var(--desk); }
.pdfViewer { padding-top: var(--top-bars-h); }
/* On touch screens the pages can be moved sideways past their edges, as
   far as the middle of the view, to read a column near an edge at the
   middle. A fitted page is centred by reader.js. */
@media (pointer: coarse) {
  .pdfViewer { box-sizing: content-box; width: max-content; min-width: 100%; padding-inline: 50%; }
}
.highlight-layer { position: absolute; inset: 0; pointer-events: none; }
/* On white pages, highlights multiply, which leaves dark text dark */
.highlight-layer div { position: absolute; background: var(--highlight-solid); mix-blend-mode: multiply; }
.pdf-reader #mark { position: absolute; z-index: 10; background: var(--mark); mix-blend-mode: multiply; pointer-events: none; }
/* Dark pages (reader.js): the page's colour before it's drawn, and
   highlights and the mark faint over it */
body.dark-pages .pdfViewer .page { background-color: var(--bg); }
body.dark-pages .highlight-layer div { background: var(--highlight); mix-blend-mode: var(--highlight-blend); }
body.dark-pages #mark { mix-blend-mode: normal; opacity: 0.45; }

/* Over a highlight's first or last edge, which drags to move it */
body.highlight-edge, body.highlight-edge * { cursor: ew-resize !important; }
body.highlight-dragging { user-select: none; -webkit-user-select: none; }

/* The button to save or remove a highlight, over the page (highlights.js) */
.highlight-popup { position: fixed; z-index: 40; padding: var(--space-1); border: 1px solid var(--border-subtle); border-radius: var(--radius-lg); background: var(--bg-raised); box-shadow: var(--shadow-md); user-select: none; -webkit-user-select: none; }
.highlight-popup[hidden] { display: none; }
.highlight-popup button { display: inline-flex; align-items: center; gap: var(--space-2); height: 30px; padding: 0 var(--space-3); border: 0; border-radius: var(--radius-md); background: none; color: var(--fg); font-weight: var(--weight-medium); }
.highlight-popup button::before { content: ""; width: 10px; height: 10px; border-radius: 3px; background: var(--highlight-solid); }
.highlight-popup button:hover { background: var(--bg-hover); }

/* Focus mode's joystick for touch screens (holdStick in focus.js), in the
   bottom right corner while Focus is on: a frosted dial with the speed
   over it while it's held. */
@media (pointer: coarse) {
  body:has(#focus:checked) #focus-stick { display: block; }
}
#focus-stick {
  position: fixed;
  right: calc(20px + env(safe-area-inset-right));
  bottom: calc(28px + env(safe-area-inset-bottom));
  z-index: 20;
  width: 116px;
  height: 116px;
  border: 1px solid var(--border-subtle);
  border-radius: 50%;
  background: color-mix(in srgb, var(--bg-raised) 72%, transparent);
  box-shadow: var(--shadow-md);
  backdrop-filter: blur(10px) saturate(1.2);
  -webkit-backdrop-filter: blur(10px) saturate(1.2);
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
#focus-stick::before { content: ""; position: absolute; inset: 9px; border: 1px dashed color-mix(in srgb, var(--fg-faint) 60%, transparent); border-radius: 50%; }
#focus-stick .dir { position: absolute; top: 50%; translate: 0 -50%; color: var(--fg-faint); pointer-events: none; }
#focus-stick .dir-l { left: 10px; }
#focus-stick .dir-r { right: 10px; }
#focus-stick .knob {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 46px;
  height: 46px;
  margin: -23px 0 0 -23px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 35%, var(--orange-400), var(--accent-strong));
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 22%, transparent), 0 6px 14px -4px rgb(0 0 0 / 0.35), inset 0 1px 0 rgb(255 255 255 / 0.35);
  pointer-events: none;
}
#focus-stick.paused .knob { opacity: 0.5; }
#focus-stick .speed {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 8px);
  translate: -50% 4px;
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  height: 26px;
  padding: 0 10px;
  align-items: center;
  border-radius: var(--radius-full);
  background: var(--inverse-bg);
  color: var(--inverse-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  white-space: nowrap;
  box-shadow: var(--shadow-sm);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--duration) var(--ease-out), translate var(--duration) var(--ease-out);
}
#focus-stick .speed .wpm { color: var(--inverse-fg); font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; }
#focus-stick.holding .speed { opacity: 1; translate: -50% 0; }
