/* writings.io — the one stylesheet for every page (React pages link it,
 * the plain-HTML work route inlines a <link> to it too). Design tokens from
 * the approved synthesis palette (design canvas page S, D3 base); the warm
 * accent's final hue is still the owner's open tweak. */

@font-face {
  font-family: "Source Serif 4";
  src: url("/fonts/source-serif-4-latin.woff2") format("woff2");
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
}
@font-face {
  font-family: "Source Serif 4";
  src: url("/fonts/source-serif-4-italic-latin.woff2") format("woff2");
  font-style: italic;
  font-weight: 200 900;
  font-display: swap;
}
@font-face {
  font-family: "Instrument Sans";
  src: url("/fonts/instrument-sans-latin.woff2") format("woff2");
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
}
@font-face {
  font-family: "Instrument Sans";
  src: url("/fonts/instrument-sans-italic-latin.woff2") format("woff2");
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
}

:root {
  --bg: #f5f4f1;
  --panel: #ffffff;
  --ink: #1c1b19;
  --muted: #67645e;
  --hair: #e3e1db;
  --accent: #a8622d;
  /* accent used AS text — darkened for WCAG AA on every light surface it
   * sits on, including the accent-soft chip fill (4.82:1 there) */
  --accent-text: #96561f;
  /* text color ON accent-filled surfaces (buttons) */
  --accent-contrast: #ffffff;
  --accent-soft: #f5e9de;
  --danger: #a03030;

  --font-serif: "Source Serif 4", Georgia, serif;
  --font-ui: "Instrument Sans", system-ui, sans-serif;

  --measure: 62ch;
  --reading-size: 1.125rem;
  --reading-leading: 1.75;

  /* --- the scales -------------------------------------------------------
   * Added 2026-08-27. Before them this stylesheet carried 13 radii, 31 font
   * sizes, 6 shadows and a mix of px and rem for the same spacing — every
   * component had decided for itself. These are the steps a component picks
   * from, and `test/tokens.test.ts` fails on a raw value where a step
   * exists, so the drift cannot start again.
   *
   * The steps are few on purpose. Wanting a value between two of them is
   * nearly always a sign that one of the two is the right answer. */

  /* Corners. Anything that holds content is --r-lg, anything you press or
   * type into is --r-md, --r-pill is for chips, --r-circle for avatars. */
  --r-xs: 4px;
  --r-sm: 6px;
  --r-md: 8px;
  --r-lg: 12px;
  --r-xl: 16px;
  --r-pill: 999px;
  --r-circle: 50%;

  /* Spacing, in rem so it answers to the reader's font size. */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4rem;

  /* Interface type. The corpus does not use this scale — reading text is
   * sized by --reading-size and nothing else. */
  --t-xs: 0.72rem;
  --t-sm: 0.8rem;
  --t-md: 0.875rem;
  --t-lg: 1rem;
  --t-xl: 1.125rem;

  /* Display type, always the serif. */
  --d-sm: 1.25rem;
  --d-md: 1.5rem;
  --d-lg: 2rem;
  --d-xl: 2.75rem;

  /* Elevation: resting, floating, over. Three, because a surface is either
   * on the page, above it, or covering it — there is no fourth state. */
  --e-1: 0 1px 2px rgba(28, 27, 25, 0.06);
  --e-2: 0 8px 24px rgba(28, 27, 25, 0.12);
  --e-3: 0 24px 60px rgba(28, 27, 25, 0.2);

  /* The one focus ring, and the one set of durations. */
  --ring: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
  --motion-fast: var(--motion-fast);
  --motion-med: var(--motion-med);
  --ease: cubic-bezier(0.22, 1, 0.36, 1);

  /* --control is the resting height of a button or field; --control-touch
   * is the 44px floor a finger needs, used by primary actions and on
   * phones. */
  --control: 36px;
  --control-touch: 44px;
}

@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"] {
    --bg: #15181a;
    --panel: #1d2124;
    --ink: #e6e7e5;
    --muted: #9aa09b;
    --hair: #2b3033;
    --accent: #e09b63;
    --accent-text: #e09b63;
    --accent-contrast: #2e1f16;
    --accent-soft: #2e241b;
    --danger: #e08a8a;

    /* Shadow on a dark ground needs depth; the light alphas read as haze. */
    --e-1: 0 1px 2px rgba(0, 0, 0, 0.4);
    --e-2: 0 8px 24px rgba(0, 0, 0, 0.5);
    --e-3: 0 24px 60px rgba(0, 0, 0, 0.6);
  }
}
:root[data-theme="dark"] {
  --bg: #15181a;
  --panel: #1d2124;
  --ink: #e6e7e5;
  --muted: #9aa09b;
  --hair: #2b3033;
  --accent: #e09b63;
  --accent-text: #e09b63;
  --accent-contrast: #2e1f16;
  --accent-soft: #2e241b;
  --danger: #e08a8a;

  /* Shadow on a dark ground needs depth; the light alphas read as haze. */
  --e-1: 0 1px 2px rgba(0, 0, 0, 0.4);
  --e-2: 0 8px 24px rgba(0, 0, 0, 0.5);
  --e-3: 0 24px 60px rgba(0, 0, 0, 0.6);
}

* {
  box-sizing: border-box;
}

/* field baseline (owner order 2026-08-26: "Notion-style inputs") — every
 * text field shares one calm look: hairline border, quiet background, a
 * soft accent ring on focus. Components only override deliberately. */
input[type="text"],
input[type="search"],
input[type="email"],
textarea,
select {
  font: inherit;
  font-family: var(--font-ui);
  font-size: var(--t-lg);
  color: var(--ink);
  background: var(--panel);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  min-block-size: var(--control);
  padding: var(--s-2) var(--s-3);
  transition:
    border-color var(--motion-fast),
    box-shadow var(--motion-fast),
    background var(--motion-fast);
}
input[type="text"]:hover,
input[type="search"]:hover,
input[type="email"]:hover,
textarea:hover,
select:hover {
  border-color: color-mix(in srgb, var(--hair) 40%, var(--muted));
}
input[type="text"]:focus,
input[type="search"]:focus,
input[type="email"]:focus,
textarea:focus,
select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--ring);
}
::placeholder {
  color: var(--muted);
  opacity: 0.8;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-ui);
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--accent-text);
  text-decoration: none;
}
a:hover {
  color: var(--accent);
}
a:focus-visible {
  text-decoration: underline;
}

/* One focus ring, for everything reachable by keyboard. `:where()` keeps it
 * at zero specificity, so any component that needs its own can simply say
 * so without an !important. */
:where(a, button, summary, [tabindex], input, select, textarea):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  inset-inline-start: -9999px;
}
.skip-link:focus {
  inset-inline-start: 16px;
  inset-block-start: 16px;
  background: var(--panel);
  padding: 8px 12px;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  z-index: 10;
}

/* --- site chrome (bar + tab strip stick together) ------------------------- */

.site-chrome {
  position: sticky;
  inset-block-start: 0;
  z-index: 5;
}

.site-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: 10px 24px;
  background: var(--bg);
  border-block-end: 1px solid var(--hair);
}
.site-bar .brand {
  font-size: var(--t-md);
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0.01em;
}
.site-bar .brand:hover {
  text-decoration: none;
  color: var(--accent-text);
}
.site-bar .bar-actions {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.site-bar button {
  border: 1px solid var(--hair);
  background: var(--panel);
  color: var(--ink);
  border-radius: var(--r-md);
  min-block-size: 32px;
  padding: 4px 10px;
  font-family: inherit;
  font-size: var(--t-sm);
  cursor: pointer;
}
.site-bar button:hover {
  color: var(--accent-text);
}
.lang-icon span {
  font-size: var(--t-xs);
  line-height: 1;
}
.lang-icon span + span {
  margin-inline-start: 3px;
  opacity: 0.75;
}

.lang-popover {
  position: fixed;
  inset: auto;
  inset-block-start: 52px;
  inset-inline-end: 16px;
  min-inline-size: 15rem;
  margin: 0;
  padding: 8px;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  background: var(--panel);
  color: var(--ink);
  box-shadow: var(--e-2);
}
.lang-popover .popover-title {
  margin: 4px 6px 8px;
  font-size: var(--t-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.lang-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s-4);
  padding: 8px 6px;
  border-radius: var(--r-sm);
  color: var(--ink);
  font-size: var(--t-md);
}
a.lang-row:hover {
  background: var(--accent-soft);
  text-decoration: none;
}
.lang-row.current > span:first-child {
  font-weight: 600;
}
.lang-row .lang-source {
  font-size: var(--t-sm);
  color: var(--muted);
}
.lang-row.coming {
  color: var(--muted);
}

/* --- work tab strip (account state; tabs + search field, owner 2026-08-25) -- */

.tab-strip {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  padding: 6px 24px;
  background: var(--bg);
  border-block-end: 1px solid var(--hair);
  overflow-x: auto;
}
/* The way back to the library (owner order 2026-08-27). It sits at the
 * strip's left edge on every page, which is why the bar above no longer
 * carries a Library link: one door, always in the same place. The divider
 * separates it from the tabs without needing a second border colour. */
.tab-home {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  flex-shrink: 0;
  min-block-size: var(--control);
  padding-inline: var(--s-3);
  margin-inline-end: var(--s-2);
  border-inline-end: 1px solid var(--hair);
  border-radius: var(--r-md) 0 0 var(--r-md);
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  color: var(--muted);
  transition: color var(--motion-fast);
}
.tab-home:hover,
.tab-home.current {
  color: var(--accent-text);
}

.tab-strip .tab {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--bg);
  font-size: var(--t-sm);
  white-space: nowrap;
  flex-shrink: 0;
}
.tab-strip .tab.current {
  background: var(--panel);
  border-color: var(--accent);
}
.tab-strip .tab > a {
  color: var(--ink);
  padding: 5px 4px 5px 12px;
  max-inline-size: 14rem;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tab-strip .tab > a:hover {
  color: var(--accent-text);
  text-decoration: none;
}
/* The × on a tab. It was a bare button with a text × and the tab's own
 * padding, so it read as a stray character rather than a control and its hit
 * area wandered with the label (owner, 2026-08-27). It is a round target of
 * its own now, quiet until the tab is hovered, and it turns to the alarm
 * colour under the pointer so the act it performs is legible before it
 * happens. */
.tab-close button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 18px;
  block-size: 18px;
  padding: 0;
  border: none;
  border-radius: var(--r-circle);
  background: transparent;
  font-family: inherit;
  font-size: var(--t-sm);
  line-height: 1;
  color: var(--muted);
  opacity: 0;
  cursor: pointer;
  transition:
    opacity var(--motion-fast),
    background var(--motion-fast),
    color var(--motion-fast);
}
.tab:hover .tab-close button,
.tab.current .tab-close button,
.tab-row:hover .tab-close button,
.tab-close button:focus-visible {
  opacity: 1;
}
.tab-close button:hover {
  background: color-mix(in srgb, var(--danger) 14%, transparent);
  color: var(--danger);
}
button.tab.tab-more {
  font-family: inherit;
  color: var(--muted);
  padding: var(--s-1) var(--s-3);
  cursor: pointer;
}
button.tab.tab-more:hover {
  color: var(--accent-text);
}
.tabs-popover {
  inset-block-start: 92px;
  inset-inline-end: auto;
  inset-inline-start: 16px;
  max-block-size: 60vh;
  overflow-y: auto;
}
.tab-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s-3);
  border-radius: var(--r-sm);
}
.tab-row > a {
  color: var(--ink);
  font-size: var(--t-md);
  padding: 8px 6px;
  flex-grow: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tab-row > a:hover {
  color: var(--accent-text);
  text-decoration: none;
}
.tab-row.current > a {
  font-weight: 600;
}
.tab-close-all {
  margin-inline-start: auto;
  flex-shrink: 0;
}
.tab-close-all button {
  border: none;
  background: none;
  font-family: inherit;
  font-size: var(--t-sm);
  color: var(--muted);
  padding: 5px 8px;
  cursor: pointer;
  border-radius: var(--r-sm);
}
.tab-close-all button:hover {
  color: var(--accent-text);
}

/* --- home (continue reading + recently read, owner 2026-08-25) ------------- */

/* --- bar search + live work suggestions ----------------------------------- */

.bar-search {
  position: relative;
  flex: 1;
  max-inline-size: 26rem;
  margin-inline: auto;
}
.bar-search input {
  inline-size: 100%;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--t-md);
  padding: 6px 12px;
  min-block-size: 32px;
  box-sizing: border-box;
}
.bar-search input::placeholder {
  color: var(--muted);
}
.bar-suggest {
  position: absolute;
  inset-inline: 0;
  inset-block-start: calc(100% + 6px);
  margin: 0;
  padding: 6px;
  list-style: none;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  background: var(--panel);
  box-shadow: var(--e-2);
  z-index: 6;
}
.bar-suggest[hidden] {
  display: none;
}
.bar-suggest a {
  display: flex;
  justify-content: space-between;
  gap: var(--s-3);
  padding: 7px 8px;
  border-radius: var(--r-sm);
  color: var(--ink);
  font-size: var(--t-md);
}
.bar-suggest a:hover,
.bar-suggest a:focus-visible {
  background: var(--accent-soft);
  text-decoration: none;
}
.bar-suggest .suggest-author {
  color: var(--muted);
  font-size: var(--t-sm);
}

/* --- search page ----------------------------------------------------------- */

.search-page {
  max-inline-size: 44rem;
  margin-inline: auto;
  padding: 40px 24px 96px;
}
.search-page h1 {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: var(--d-md);
  margin: 0 0 20px;
}
.search-form {
  display: flex;
  gap: var(--s-2);
}
.search-form input[type="search"] {
  flex: 1;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--t-lg);
  padding: 10px 14px;
  box-sizing: border-box;
}
.search-meta {
  display: flex;
  justify-content: space-between;
  gap: var(--s-4);
  margin-block: 14px 26px;
  font-size: var(--t-sm);
  color: var(--muted);
}
.search-meta a {
  text-decoration: underline;
}
.did-you-mean {
  margin: 0 0 20px;
  font-size: var(--t-lg);
}
.work-hits {
  margin-block-end: 28px;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: 6px;
}
.work-hits a {
  display: flex;
  justify-content: space-between;
  gap: var(--s-4);
  padding: 10px;
  border-radius: var(--r-sm);
  color: var(--ink);
}
.work-hits a:hover {
  background: var(--accent-soft);
  text-decoration: none;
}
.work-hits .hit-author {
  color: var(--muted);
  font-size: var(--t-sm);
  flex-shrink: 0;
}
.hit {
  padding: 14px 0;
  border-block-start: 1px solid var(--hair);
}
.hit .hit-work {
  font-size: var(--t-sm);
  color: var(--muted);
  margin: 0 0 4px;
}
.hit .hit-snippet {
  font-family: var(--font-serif);
  font-size: var(--t-lg);
  line-height: 1.6;
  margin: 0;
  color: var(--ink);
}
.hit a {
  color: inherit;
  display: block;
}
.hit a:hover {
  text-decoration: none;
}
.hit a:hover .hit-snippet {
  color: var(--accent-text);
}
mark {
  background: var(--accent-soft);
  color: inherit;
  border-radius: var(--r-xs);
}
.search-more-row {
  display: flex;
  justify-content: center;
  margin-block: 32px;
}

/* --- shared page primitives (home, login) --------------------------------- */

.page-narrow {
  max-inline-size: 26rem;
  margin-inline: auto;
  padding: 96px 24px;
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
}
.page-narrow h1 {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: var(--d-md);
  margin: 0;
}
.muted {
  color: var(--muted);
  margin: 0;
  font-size: var(--t-md);
}
.notice {
  color: var(--accent-text);
  margin: 0;
  font-size: var(--t-md);
}
.field-label {
  font-size: var(--t-sm);
  color: var(--muted);
}
/* The large field variant, for the forms a page is *about* — sign-in,
 * settings. It inherits border, radius, colours and focus ring from the
 * element baseline above and changes only its size; before 2026-08-27 it
 * restated all of them and disagreed with the baseline on two. */
.text-input {
  inline-size: 100%;
  min-block-size: var(--control-touch);
  padding: var(--s-2) var(--s-3);
}
/* The two shared buttons. Everything they have in common is written once;
 * the variants differ only in how loud they are. Until 2026-08-27 neither
 * declared a hover or a focus state at all, so the portal's two most-used
 * controls were the only ones that did not answer to the pointer. */
.button-primary,
.button-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-block-size: var(--control-touch);
  padding: 0 var(--s-4);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  font-family: inherit;
  font-size: var(--t-lg);
  text-decoration: none;
  cursor: pointer;
  transition:
    background var(--motion-fast),
    border-color var(--motion-fast),
    color var(--motion-fast);
}
.button-primary {
  background: var(--accent);
  color: var(--accent-contrast);
}
.button-primary:hover {
  background: var(--accent-text);
  color: var(--accent-contrast);
}
.button-secondary {
  border-color: var(--hair);
  background: var(--panel);
  color: var(--ink);
}
.button-secondary:hover {
  border-color: var(--accent);
  color: var(--accent-text);
}
.button-primary:active,
.button-secondary:active {
  transform: translateY(1px);
}
.button-primary[disabled],
.button-secondary[disabled] {
  opacity: 0.55;
  cursor: default;
  transform: none;
}
.form-stack {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

/* --- library ------------------------------------------------------------- */

/* Same width as the home page it is embedded in — at 40rem it read as a
 * narrow column inside a wide one (owner, 2026-08-27). */
.library {
  max-inline-size: 72rem;
  margin-inline: auto;
  padding: var(--s-6) var(--s-5) var(--s-8);
}
.library h1 {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: var(--d-lg);
  margin: 0 0 32px;
}
.library h2 {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: var(--d-sm);
  margin: 40px 0 4px;
}
/* library v2: work cards + language chips (one entry per work) */
.work-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
  gap: var(--s-3);
  margin: 0.75rem 0 1.5rem;
}
.work-card {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: 0.9rem 1rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  background: var(--panel);
}
.work-card-title {
  font-family: var(--font-serif);
  font-size: var(--t-xl);
  color: var(--ink);
  text-decoration: none;
}
.work-card-title:hover {
  color: var(--accent-text);
}
.lang-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}
/* Codes rather than names (owner order 2026-08-27): two characters at any
 * number of languages, where the spelled-out names were already crowding the
 * rows at two. The name lives in the tooltip and the accessible label. */
.lang-chips a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: 2.1rem;
  font-family: var(--font-ui);
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: 0.03em;
  padding: 0.12rem var(--s-2);
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  color: var(--muted);
  text-decoration: none;
  transition:
    border-color var(--motion-fast),
    color var(--motion-fast);
}
.lang-chips a:hover {
  color: var(--accent-text);
  border-color: var(--accent);
}
.msg-year {
  border-block-start: 1px solid var(--hair);
}
.msg-year summary {
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: var(--t-lg);
  color: var(--ink);
  padding: 0.65rem 0.25rem;
}
.msg-count {
  color: var(--muted);
  font-size: var(--t-sm);
  margin-inline-start: 0.35rem;
}
.msg-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.msg-title {
  flex: 1;
  min-inline-size: 0;
}

/* One row per message. The title takes the space and the chips sit at the
 * end, so titles of different lengths still line up down the column — before
 * this the spelled-out language names pushed each row's title around. */
.msg-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s-4);
  padding: var(--s-2) var(--s-1) var(--s-2) var(--s-4);
  border-block-start: 1px solid color-mix(in srgb, var(--hair) 55%, transparent);
}
.msg-row:first-child {
  border-block-start: none;
}
.msg-row:hover {
  background: var(--panel);
}
.msg-row > a {
  color: var(--ink);
  text-decoration: none;
}
.msg-row > a:hover {
  color: var(--accent-text);
}

/* --- reading page -------------------------------------------------------- */

.reader {
  max-inline-size: calc(var(--measure) + 8rem);
  margin-inline: auto;
  padding: 48px 24px 120px;
}

.reader header.work-head {
  margin-block-end: 48px;
}
.reader header.work-head .author {
  font-family: var(--font-serif);
  font-size: var(--t-lg);
  color: var(--muted);
  margin: 0 0 6px;
}
.reader header.work-head h1 {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: var(--d-lg);
  line-height: 1.25;
  margin: 0;
}
.reader header.work-head .work-meta {
  margin-block-start: 10px;
  font-size: var(--t-sm);
  color: var(--muted);
}
/* links inside running meta text need more than color to stand apart */
.reader header.work-head .work-meta a {
  text-decoration: underline;
}

.reading {
  font-family: var(--font-serif);
  font-size: var(--reading-size);
  line-height: var(--reading-leading);
  max-inline-size: var(--measure);
}

.reading h2 {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: var(--d-sm);
  line-height: 1.35;
  margin-block: 2.2em 0.9em;
}

.paragraph {
  position: relative;
  margin-block: 0 1.1em;
  /* The number hangs in the left gutter and the actions in the right one, and
   * `content-visibility` below makes this box a paint-containment boundary.
   * Paint containment clips — and stops hit-testing — everything outside the
   * box, so both were invisible and the save and cite buttons unclickable on
   * every paragraph except the anchored one (measured in the browser,
   * 2026-08-28: elementFromPoint over the button returned the div).
   * The box therefore has to reach across both gutters; the negative margins
   * hand the width straight back, so the text column does not move. */
  padding-inline: 3.2rem 2.4rem;
  margin-inline: -3.2rem -2.4rem;
  /* per-block contain-intrinsic-size is set inline from the text length */
  content-visibility: auto;
}

/* Jumping to a paragraph anchor renders everything — estimated sizes would
 * make the fragment scroll land far off (set via inline script on <html>). */
.anchored .paragraph {
  content-visibility: visible;
}

.paragraph > .pnum {
  position: absolute;
  /* the gutter is this box's padding now, not space outside it */
  inset-inline-start: 0;
  inset-block-start: 0.35em;
  inline-size: 2.4rem;
  text-align: end;
  font-family: var(--font-ui);
  font-size: var(--t-xs);
  color: var(--muted);
}

.paragraph p {
  margin: 0;
}

.paragraph .invocation {
  font-style: italic;
}

.paragraph:target {
  background: var(--accent-soft);
  border-radius: var(--r-sm);
  outline: 6px solid var(--accent-soft);
}

.paragraph .p-actions {
  position: absolute;
  inset-inline-end: 0;
  inset-block-start: 0.2em;
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  opacity: 0;
  transition: opacity var(--motion-fast);
}
.paragraph:hover .p-actions,
.paragraph:focus-within .p-actions {
  opacity: 1;
}
.p-actions a,
.p-actions button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 28px;
  block-size: 28px;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--muted);
  cursor: pointer;
  font-size: var(--t-sm);
  padding: 0;
}
.p-actions a:hover,
.p-actions button:hover {
  color: var(--accent-text);
  text-decoration: none;
}

.endnotes {
  margin-block-start: 4rem;
  border-block-start: 1px solid var(--hair);
  padding-block-start: 1.5rem;
}
.endnotes h2 {
  font-size: var(--t-xl);
}
.endnotes .paragraph {
  font-size: var(--t-lg);
}

@media (max-width: 52rem) {
  /* number and actions join the flow here, so the paragraph keeps no gutters */
  .paragraph {
    padding-inline: 0;
    margin-inline: 0;
  }
  .paragraph > .pnum {
    position: static;
    display: block;
    text-align: start;
    inline-size: auto;
    margin-block-end: 0.15em;
  }
  /* actions appear on tap (focus) — owner decision 2026-08-25 */
  .paragraph .p-actions {
    position: static;
    flex-direction: row;
    display: none;
    opacity: 1;
    margin-block-start: 0.4em;
  }
  .paragraph:focus-within .p-actions {
    display: flex;
  }
}

/* --- parallel view (reading.parallel) ------------------------------------ */

/* One rule, two names. Both spellings are in the markup and neither is
 * worth a sweep of its own; what mattered was that they stopped being two
 * definitions that could drift apart. */
.sr-only,
.visually-hidden {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.reader.parallel {
  /* two columns + a center gutter wide enough for the right column's hanging
   * numbers (3.2rem) and the left column's action buttons (2.4rem) */
  --gutter: 6.5rem;
  max-inline-size: calc(2 * 38rem + var(--gutter) + 7rem);
  padding-inline: 3.5rem;
}
.parallel-grid {
  max-inline-size: none;
}
.parallel-grid .unit {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: var(--gutter);
  content-visibility: auto;
  /* per-unit contain-intrinsic-size is set inline from the text length */
}
.anchored .parallel-grid .unit {
  content-visibility: visible;
}
/* blocks size themselves — the unit is the visibility boundary here */
.parallel-grid .paragraph {
  content-visibility: visible;
  /* This grid fills the viewport, so there is no room beside the columns for
   * the gutters the single-column reader carries — the negative margins would
   * push the left column's number off-screen. So this view keeps the geometry
   * it had: the numbers hang outside the box, which the *unit's* containment
   * clips for the left column while the right column's fall in the column gap
   * and show. Half-visible numbers here are a layout question of their own,
   * recorded in TASKS.md; this rule makes sure the reader fix does not quietly
   * answer it. */
  padding-inline: 0;
  margin-inline: 0;
}
.parallel-grid .paragraph > .pnum {
  inset-inline-start: -3.2rem;
}
.parallel-grid .paragraph .p-actions {
  inset-inline-end: -2.4rem;
}
.parallel-grid .col-heads {
  font-family: var(--font-ui);
  font-size: var(--t-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-block-end: 2.5rem;
  content-visibility: visible;
}
.parallel-grid .cell.empty {
  color: var(--hair);
  font-family: var(--font-ui);
}

@media (max-width: 68rem) {
  .reader.parallel {
    max-inline-size: calc(var(--measure) + 8rem);
    padding-inline: 24px;
  }
  .parallel-grid {
    max-inline-size: var(--measure);
  }
  .parallel-grid .unit {
    grid-template-columns: 1fr;
  }
  .parallel-grid .col-heads,
  .parallel-grid .cell.empty {
    display: none;
  }
  /* stacked: the second language reads slightly indented under the first */
  .parallel-grid .cell:nth-child(2) {
    padding-inline-start: 1.4rem;
  }
}

/* --- print --------------------------------------------------------------- */

@media print {
  :root {
    --bg: #ffffff;
    --ink: #000000;
  }
  .skip-link,
  nav.site,
  .no-print,
  .paragraph .p-actions {
    display: none;
  }
  .paragraph {
    break-inside: avoid;
    content-visibility: visible;
  }
  .parallel-grid .unit {
    content-visibility: visible;
  }
  .reader {
    padding: 0;
  }
  a {
    color: inherit;
  }
}

/* --- compilations (study.collections, owner go 2026-08-26) ------------- */

.bar-link {
  font-family: var(--font-ui);
  font-size: var(--t-md);
  color: var(--muted);
  text-decoration: none;
  margin-inline-start: 0.25rem;
}
.bar-link:hover {
  color: var(--accent-text);
}

/* covers: centered emoji on a preset pastel — same tones in both themes */
/* The cover backgrounds are the same eight pastels in both themes, so the
 * glyph on them cannot follow the theme either. It did, and in dark it
 * inherited `--ink` — a near-white symbol on light sand, about 1.05:1, which
 * is invisible. Colour emoji hid the bug because they carry their own
 * colours; a text glyph like ✦ simply vanished. Found 2026-08-28 when the
 * third pane put a cover next to a dark surface. */
.comp-cover {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 3rem;
  height: 3rem;
  border-radius: var(--r-lg);
  font-size: var(--d-md);
  line-height: 1;
  color: #2b2419;
}
.comp-cover-large {
  width: 4.5rem;
  height: 4.5rem;
  border-radius: var(--r-xl);
  font-size: var(--d-xl);
}
.cover-sand {
  background: #ece2d3;
}
.cover-terracotta {
  background: #e9cbb8;
}
.cover-gold {
  background: #ecdcae;
}
.cover-sage {
  background: #d5ddc8;
}
.cover-sky {
  background: #cfdde6;
}
.cover-lavender {
  background: #d8d3e6;
}
.cover-rose {
  background: #e8cfd4;
}
.cover-slate {
  background: #d3d7db;
}

.comp-create {
  display: flex;
  gap: var(--s-2);
  margin: 1.5rem 0;
  max-width: 28rem;
}
.comp-create input[type="text"] {
  flex-grow: 1;
  font: inherit;
  font-family: var(--font-ui);
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--ink);
}

.comp-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: var(--s-3);
  margin: 1.5rem 0;
}
.comp-card {
  display: flex;
  gap: var(--s-3);
  align-items: center;
  padding: 0.75rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  background: var(--panel);
  text-decoration: none;
  color: var(--ink);
}
.comp-card:hover {
  border-color: var(--accent);
}
.comp-card-title {
  display: block;
  font-family: var(--font-serif);
  font-size: var(--t-xl);
}
.comp-card-meta {
  display: block;
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  color: var(--muted);
  margin-top: 0.15rem;
}

.comp-detail .comp-head {
  display: flex;
  gap: var(--s-5);
  align-items: flex-start;
  text-align: start;
}
.comp-intro {
  font-family: var(--font-serif);
  color: var(--ink);
  margin-top: 0.5rem;
}

.comp-edit {
  margin: 1.5rem 0;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: 0.75rem 1rem;
  background: var(--panel);
  font-family: var(--font-ui);
}
.comp-edit summary {
  cursor: pointer;
  color: var(--muted);
}
.comp-edit-form {
  display: grid;
  gap: var(--s-4);
  margin-top: 1rem;
}
.comp-edit-form label {
  display: grid;
  gap: var(--s-1);
  font-size: var(--t-md);
  color: var(--muted);
}
.comp-edit-form input[type="text"],
.comp-edit-form textarea {
  font: inherit;
  font-family: var(--font-ui);
  padding: 0.45rem 0.65rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--ink);
}
.comp-emoji-input {
  max-width: 6rem;
}
.comp-edit-form fieldset {
  border: none;
  padding: 0;
  margin: 0;
  font-size: var(--t-md);
  color: var(--muted);
}
.comp-edit-form legend {
  margin-bottom: 0.4rem;
}
.comp-colors {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  align-items: center;
}
.comp-color {
  display: inline-grid;
  place-items: center;
  width: 1.7rem;
  height: 1.7rem;
  border-radius: var(--r-circle);
  margin-inline-end: 0.5rem;
  cursor: pointer;
  vertical-align: middle;
}
.comp-color input {
  appearance: none;
  margin: 0;
  width: 100%;
  height: 100%;
  border-radius: var(--r-circle);
  cursor: pointer;
}
.comp-color:has(input:checked) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.comp-color:has(input:focus-visible) {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}
.comp-visibility label {
  display: block;
  color: var(--ink);
  margin-bottom: 0.3rem;
}
.comp-visibility input {
  margin-inline-end: 0.4rem;
}

.comp-items {
  list-style: none;
  padding: 0;
  margin: 2rem 0;
  display: grid;
  gap: var(--s-4);
}
.comp-item {
  position: relative;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: 1rem 1.25rem;
  background: var(--panel);
}
.comp-item-work a {
  text-decoration: none;
  color: var(--ink);
}
.comp-item-title {
  display: block;
  font-family: var(--font-serif);
  font-size: var(--t-xl);
}
.comp-item-work a:hover .comp-item-title {
  color: var(--accent-text);
}
.comp-item-text {
  font-family: var(--font-serif);
  font-size: var(--reading-size);
  line-height: var(--reading-leading);
  margin: 0 0 0.5rem;
  color: var(--ink);
}
a.comp-item-meta {
  text-decoration: none;
}
a.comp-item-meta:hover {
  color: var(--accent-text);
}
.comp-item-meta {
  display: inline-block;
  font-family: var(--font-ui);
  font-size: var(--t-md);
  color: var(--accent-text);
}
.comp-item-note {
  font-family: var(--font-ui);
  font-size: var(--t-md);
  font-style: italic;
  color: var(--muted);
  margin: 0.5rem 0 0;
}
.comp-item-controls {
  position: absolute;
  top: 0.6rem;
  inset-inline-end: 0.6rem;
  display: flex;
  gap: var(--s-1);
}
.comp-item-controls button {
  font: inherit;
  font-family: var(--font-ui);
  font-size: var(--t-md);
  line-height: 1;
  padding: 0.25rem 0.45rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-sm);
  background: var(--panel);
  color: var(--muted);
  cursor: pointer;
}
.comp-item-controls button:hover:not(:disabled) {
  color: var(--accent-text);
  border-color: var(--accent);
}
.comp-item-controls button:disabled {
  opacity: 0.35;
  cursor: default;
}

.comp-shares {
  margin: 2rem 0;
  font-family: var(--font-ui);
}
.comp-share-row {
  display: flex;
  gap: var(--s-3);
  align-items: center;
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--hair);
  font-size: var(--t-lg);
}
.comp-share-row button,
.comp-share-grant button,
.comp-share-grant select {
  font: inherit;
  font-family: var(--font-ui);
  padding: 0.35rem 0.7rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--ink);
  cursor: pointer;
}
.comp-share-row button:hover {
  color: var(--accent-text);
  border-color: var(--accent);
}
.comp-share-grant {
  display: flex;
  gap: var(--s-2);
  margin-top: 0.9rem;
  flex-wrap: wrap;
}
.comp-share-grant input[type="email"] {
  font: inherit;
  font-family: var(--font-ui);
  padding: 0.35rem 0.65rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--ink);
  flex-grow: 1;
  max-width: 18rem;
}

.comp-actions {
  display: flex;
  gap: var(--s-5);
  align-items: center;
  flex-wrap: wrap;
  margin: 2.5rem 0;
  font-family: var(--font-ui);
  font-size: var(--t-lg);
}
.comp-delete {
  font: inherit;
  font-family: var(--font-ui);
  border: none;
  background: none;
  color: var(--danger);
  cursor: pointer;
  padding: 0;
}
.comp-delete:hover {
  filter: brightness(0.85);
}

.work-head-actions {
  margin-top: 0.75rem;
}
.comp-add {
  font: inherit;
  font-family: var(--font-ui);
  font-size: var(--t-md);
  padding: 0.35rem 0.8rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  background: var(--panel);
  color: var(--muted);
  cursor: pointer;
}
.comp-add:hover {
  color: var(--accent-text);
  border-color: var(--accent);
}
/* the compilation picker (Spotify-style, owner order 2026-08-26) */
.comp-picker {
  width: min(22rem, 92vw);
  padding: 0.9rem;
}
.picker-filter {
  width: 100%;
  margin-bottom: 0.6rem;
}
.picker-new {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: 0.35rem 0.4rem 0.75rem;
  border-bottom: 1px solid var(--hair);
  margin-bottom: 0.5rem;
}
.picker-new input[type="text"] {
  flex-grow: 1;
  min-width: 0;
  border: none;
  background: transparent;
  padding: 0.35rem 0.2rem;
}
.picker-new input[type="text"]:focus {
  box-shadow: none;
}
.picker-new button {
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  padding: 0.32rem 0.75rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  background: var(--panel);
  color: var(--ink);
  cursor: pointer;
}
.picker-new button:hover {
  border-color: var(--accent);
  color: var(--accent-text);
}
.picker-rows {
  display: grid;
  max-height: 19rem;
  overflow-y: auto;
}
.picker-rows form[hidden] {
  display: none;
}
.picker-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: 100%;
  padding: 0.4rem;
  border: none;
  border-radius: var(--r-lg);
  background: transparent;
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: var(--t-lg);
  text-align: left;
  cursor: pointer;
  transition: background var(--motion-fast);
}
.picker-row:hover {
  background: var(--bg);
}
.picker-cover {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: var(--r-md);
  font-size: var(--t-xl);
  background: var(--bg);
}
/* Only once a preset colour is on it: without one the tile sits on the page
 * background, which does follow the theme, so the glyph must follow it too. */
.picker-cover[data-cover] {
  color: #2b2419;
}
.picker-cover-new {
  color: var(--muted);
  border: 1px dashed var(--hair);
  background: transparent;
}
.picker-cover[data-cover="sand"] {
  background: #ece2d3;
}
.picker-cover[data-cover="terracotta"] {
  background: #e9cbb8;
}
.picker-cover[data-cover="gold"] {
  background: #ecdcae;
}
.picker-cover[data-cover="sage"] {
  background: #d5ddc8;
}
.picker-cover[data-cover="sky"] {
  background: #cfdde6;
}
.picker-cover[data-cover="lavender"] {
  background: #d8d3e6;
}
.picker-cover[data-cover="rose"] {
  background: #e8cfd4;
}
.picker-cover[data-cover="slate"] {
  background: #d3d7db;
}
.picker-title {
  display: grid;
  gap: var(--s-1);
  flex-grow: 1;
  min-width: 0;
}
.picker-count {
  font-size: var(--t-xs);
  color: var(--muted);
}
.picker-state {
  flex-shrink: 0;
  font-size: var(--t-lg);
  color: var(--muted);
}
.picker-row.in .picker-state {
  color: var(--accent-text);
}

/* pressed save button mirrors the saved state */
.paragraph .p-actions button[aria-pressed="true"] {
  color: var(--accent-text);
}

.export-list section {
  margin-bottom: 1.75rem;
}

/* --- public landing + waitlist (release.waitlist) ---------------------- */

.landing {
  position: relative;
  overflow: hidden;
  min-height: 100dvh;
  background: var(--bg);
  font-family: var(--font-ui);
}
.waves {
  position: absolute;
  inset-inline: 0;
  top: 26rem;
  pointer-events: none;
  color: var(--accent);
}
.wave-band {
  position: absolute;
  inset-inline: 0;
  height: 140px;
  overflow: hidden;
}
.wave-band-1 {
  top: 0;
  opacity: 0.5;
}
.wave-band-2 {
  top: 2.5rem;
  opacity: 0.3;
}
.wave-band-3 {
  top: 5rem;
  opacity: 0.16;
}
.wave {
  position: absolute;
  inset-inline-start: 0;
  width: 200%;
  height: 140px;
}
@keyframes drift {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}
.drift-1 {
  animation: drift 26s linear infinite;
}
.drift-2 {
  animation: drift 38s linear infinite reverse;
}
.drift-3 {
  animation: drift 52s linear infinite;
}
@keyframes rise-in {
  from {
    opacity: 0;
    transform: translateY(26px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.landing-hero {
  animation: rise-in 0.9s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.landing-teaser {
  animation: rise-in 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.25s both;
}
@media (prefers-reduced-motion: reduce) {
  .drift-1,
  .drift-2,
  .drift-3,
  .landing-hero,
  .landing-teaser {
    animation: none;
  }
}

.landing-bar {
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: center;
  max-width: 72rem;
  margin: 0 auto;
  padding: 1.6rem 1.5rem;
}
.landing-brand {
  font-weight: 600;
  color: var(--ink);
}
.landing-soon {
  color: var(--muted);
  font-size: var(--t-md);
}
.landing-signin {
  color: var(--muted);
  font-size: var(--t-md);
  margin-inline-start: 1.25rem;
  text-decoration: none;
}
.landing-signin:hover {
  color: var(--accent-text);
}

.landing-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-5);
  text-align: center;
  max-width: 55rem;
  margin: 0 auto;
  padding: 5rem 1.5rem 12rem;
}
.landing-kicker {
  font-size: var(--t-xs);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent-text);
  margin: 0;
}
.landing-hero h1 {
  font-family: var(--font-serif);
  font-size: clamp(2.4rem, 7vw, 4.6rem);
  line-height: 1.08;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0;
}
.landing-hero h1 em {
  font-style: italic;
}
.landing-sub {
  font-size: var(--t-xl);
  line-height: 1.65;
  color: var(--muted);
  max-width: 35rem;
  margin: 0;
}
.landing-form {
  display: flex;
  gap: var(--s-3);
  width: 28rem;
  max-width: 100%;
}
.landing-form input[type="email"] {
  flex-grow: 1;
  font: inherit;
  padding: 0.8rem 1rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  background: var(--panel);
  color: var(--ink);
}
.landing-form .button-primary {
  white-space: nowrap;
}
.landing-trap {
  position: absolute;
  inset-inline-start: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
}
.landing-joined {
  font-size: var(--t-lg);
  color: var(--accent-text);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  background: var(--panel);
  padding: 0.8rem 1.4rem;
  margin: 0;
}
.landing-invalid {
  color: var(--danger);
  font-size: var(--t-md);
  margin: 0;
}
/* The one line of scripture on the page, set as what it is. The publishers
 * stay unnamed until the rights are settled (owner, 2026-08-27): the
 * quotation may be used, the names may not. */
.landing-epigraph {
  /* The hero is centred, so the quote is too. A rule down its left edge
     would point at nothing. */
  margin: var(--s-5) auto var(--s-6);
  max-inline-size: 34rem;
  text-align: center;
}
.landing-epigraph blockquote {
  margin: 0;
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--d-sm);
  line-height: 1.45;
  color: var(--ink);
}
.landing-epigraph figcaption {
  margin-block-start: var(--s-2);
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  color: var(--muted);
}
.landing-close h2 {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: var(--d-md);
  margin: 0 0 var(--s-5);
}

.landing-micro {
  font-size: var(--t-sm);
  color: var(--muted);
  margin: 0;
}

.landing-teaser {
  position: relative;
  max-width: 46rem;
  margin: 0 auto;
  padding: 0 1.5rem 7rem;
}
.landing-teaser::before {
  content: "";
  position: absolute;
  inset: -2.5rem -5rem;
  background: radial-gradient(closest-side, var(--accent-soft), transparent);
  opacity: 0.8;
}
.teaser-card {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--hair);
  border-radius: var(--r-xl);
  box-shadow: var(--e-3);
  padding: 2rem 2.4rem;
  transform: rotate(-0.6deg);
}
.teaser-langs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 2.6rem;
  font-size: var(--t-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 1rem;
}
.teaser-columns {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 2.6rem;
}
.teaser-lines {
  display: grid;
  gap: var(--s-2);
  align-content: start;
}
.teaser-line {
  display: block;
  block-size: 0.55rem;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--muted) 22%, transparent);
}
.teaser-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s-6);
  margin-top: 1.2rem;
}
.teaser-cite {
  inline-size: 34%;
  background: color-mix(in srgb, var(--muted) 32%, transparent);
}
.teaser-source {
  font-size: var(--t-xs);
  color: var(--accent-text);
  white-space: nowrap;
}

.landing-benefits {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-4);
  max-width: 64rem;
  margin: 0 auto;
  padding: 0 1.5rem 6rem;
}
.landing-benefits > div {
  background: var(--panel);
  border: 1px solid var(--hair);
  border-radius: var(--r-xl);
  padding: 1.6rem;
}
.landing-benefits h2 {
  font-family: var(--font-serif);
  font-size: var(--t-xl);
  font-weight: 500;
  color: var(--ink);
  margin: 0 0 0.6rem;
}
.landing-benefits p {
  font-size: var(--t-md);
  line-height: 1.6;
  color: var(--muted);
  margin: 0;
}
@media (max-width: 44rem) {
  .landing-benefits {
    grid-template-columns: 1fr;
  }
}

.landing-close {
  position: relative;
  display: flex;
  justify-content: center;
  padding: 0 1.5rem 7rem;
}
@media (max-width: 34rem) {
  .landing-form {
    flex-direction: column;
  }
  .teaser-card {
    padding: 1.4rem 1.2rem;
  }
  .teaser-columns,
  .teaser-langs {
    column-gap: 1.2rem;
  }
}

/* merged work hits on the search page */
.work-hit {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s-4);
  flex-wrap: wrap;
  padding: 0.55rem 0.25rem;
  border-block-start: 1px solid var(--hair);
}
.work-hit > a {
  color: var(--ink);
  text-decoration: none;
  display: flex;
  gap: var(--s-3);
  align-items: baseline;
}
.work-hit > a:hover {
  color: var(--accent-text);
}

/* visible language switch in the work head (segmented control) */
.lang-segments {
  display: inline-flex;
  margin-top: 0.9rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  overflow: hidden;
  font-family: var(--font-ui);
  font-size: var(--t-md);
}
.lang-segments a {
  padding: 0.35rem 0.95rem;
  color: var(--muted);
  text-decoration: none;
  border-inline-start: 1px solid var(--hair);
}
.lang-segments a:first-child {
  border-inline-start: none;
}
.lang-segments a:hover {
  color: var(--accent-text);
}
.lang-segments a[aria-current="true"] {
  background: var(--accent-soft);
  color: var(--accent-text);
}

/* command palette (⌘K) */
.bar-kbd {
  position: absolute;
  inset-inline-end: 0.7rem;
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--font-ui);
  font-size: var(--t-xs);
  color: var(--muted);
  border: 1px solid var(--hair);
  border-radius: var(--r-xs);
  padding: 0.05rem 0.35rem;
  pointer-events: none;
}
.bar-search form {
  position: relative;
}
.kbar {
  width: min(38rem, 92vw);
  margin: 12vh auto auto;
  padding: 0.9rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-xl);
  background: var(--panel);
  color: var(--ink);
  box-shadow: var(--e-3);
}
.kbar::backdrop {
  background: rgba(20, 16, 10, 0.45);
}
.kbar input[type="search"] {
  width: 100%;
  font: inherit;
  font-family: var(--font-ui);
  font-size: var(--t-xl);
  padding: 0.65rem 0.85rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  background: var(--bg);
  color: var(--ink);
}
.kbar-list {
  list-style: none;
  margin: 0.6rem 0 0;
  padding: 0;
  max-height: 45vh;
  overflow-y: auto;
}
.kbar-list a {
  display: flex;
  justify-content: space-between;
  gap: var(--s-4);
  padding: 0.5rem 0.6rem;
  border-radius: var(--r-md);
  color: var(--ink);
  text-decoration: none;
  font-family: var(--font-ui);
  font-size: var(--t-lg);
}
.kbar-list a:hover,
.kbar-list a:focus-visible {
  background: var(--accent-soft);
  color: var(--accent-text);
}
.kbar-list .suggest-author {
  color: var(--muted);
  font-size: var(--t-sm);
  flex-shrink: 0;
}
.kbar-hint {
  margin: 0.6rem 0 0;
  font-family: var(--font-ui);
  font-size: var(--t-xs);
  color: var(--muted);
}
@media (max-width: 44rem) {
  .bar-kbd {
    display: none;
  }
}

/* --- user-adjustable accent (owner decision 2026-08-26) ----------------- */
/* terracotta is the base token set; presets override it per theme. All
   text/contrast values are WCAG-AA-checked against their grounds. */

:root[data-accent="gold"] {
  --accent: #8a6a10;
  --accent-text: #7a6113;
  --accent-contrast: #ffffff;
  --accent-soft: #f1ead2;
}
:root[data-accent="orange"] {
  --accent: #b3541a;
  --accent-text: #aa4e13;
  --accent-contrast: #ffffff;
  --accent-soft: #f7e7da;
}
@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"][data-accent="gold"] {
    --accent: #d9b34a;
    --accent-text: #d9b34a;
    --accent-contrast: #2a230e;
    --accent-soft: #2b2514;
  }
  :root[data-theme="auto"][data-accent="orange"] {
    --accent: #ec8f4b;
    --accent-text: #ec8f4b;
    --accent-contrast: #2e1c0e;
    --accent-soft: #2f2114;
  }
}
:root[data-theme="dark"][data-accent="gold"] {
  --accent: #d9b34a;
  --accent-text: #d9b34a;
  --accent-contrast: #2a230e;
  --accent-soft: #2b2514;
}
:root[data-theme="dark"][data-accent="orange"] {
  --accent: #ec8f4b;
  --accent-text: #ec8f4b;
  --accent-contrast: #2e1c0e;
  --accent-soft: #2f2114;
}

/* accent picker (welcome + settings) */
.accent-picker {
  display: flex;
  gap: var(--s-4);
  border: none;
  padding: 0;
  margin: 0;
  font-family: var(--font-ui);
}
.accent-option {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-2);
  cursor: pointer;
  color: var(--muted);
  font-size: var(--t-sm);
}
.accent-option .swatch {
  display: block;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: var(--r-circle);
}
.swatch-terracotta {
  background: #a8622d;
}
.swatch-gold {
  background: #8a6a10;
}
.swatch-orange {
  background: #b3541a;
}
.accent-option input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.accent-option:has(input:checked) .swatch {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.accent-option:has(input:checked) {
  color: var(--ink);
}
.accent-option:has(input:focus-visible) .swatch {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

/* Portal language (reading.i18n): plain radio pills, same weight as the
   accent choice — it is a preference, not a mode switch. */
.locale-choice {
  display: flex;
  gap: var(--s-3);
  border: none;
  padding: 0;
  margin: 0;
  font-family: var(--font-ui);
}
.locale-option {
  cursor: pointer;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  padding: 0.35rem 0.9rem;
  font-size: var(--t-md);
  color: var(--muted);
}
.locale-option input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.locale-option:has(input:checked) {
  color: var(--accent-text);
  border-color: var(--accent);
}
.locale-option:has(input:focus-visible) {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.welcome-step {
  margin-block-start: var(--s-6);
}
.welcome-step h2 {
  font-family: var(--font-serif);
  font-size: var(--d-sm);
  font-weight: 500;
  margin: 0 0 var(--s-2);
}
.welcome-step > p {
  margin: 0 0 var(--s-3);
}
.welcome-actions {
  margin-block-start: var(--s-6);
}

.welcome {
  max-width: 34rem;
  margin: 0 auto;
  padding: 5rem 1.5rem;
  display: grid;
  gap: var(--s-5);
  font-family: var(--font-ui);
}
.welcome h1 {
  font-family: var(--font-serif);
  font-size: var(--d-xl);
  font-weight: 500;
  margin: 0;
}
.settings {
  max-width: 34rem;
  margin: 0 auto;
  padding: 2.5rem 1.5rem;
  display: grid;
  gap: var(--s-5);
  font-family: var(--font-ui);
}
.settings h1 {
  font-family: var(--font-serif);
  font-size: var(--d-lg);
  font-weight: 500;
  margin: 0;
}
.bar-search-btn {
  display: none;
  align-items: center;
  justify-content: center;
  width: 2.1rem;
  height: 2.1rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--muted);
  cursor: pointer;
  margin-inline: auto;
}
.bar-search-btn:hover {
  color: var(--accent-text);
  border-color: var(--accent);
}
@media (max-width: 44rem) {
  .bar-search {
    display: none;
  }
  .bar-search-btn {
    display: inline-flex;
  }
}

/* --- account popover (canvas page U) ------------------------------------ */
.account-btn {
  width: 1.8rem;
  height: 1.8rem;
  border-radius: var(--r-pill);
  border: none;
  background: var(--accent-soft);
  color: var(--accent-text);
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.account-initial {
  cursor: default;
}
/* With a name the control stops being a circle: a name needs room, and a
 * round badge holding six letters is a circle pretending. */
.account-btn.account-named {
  inline-size: auto;
  border-radius: var(--r-pill);
  padding-inline: var(--s-3);
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  font-weight: 500;
}
.account-address {
  display: block;
  font-size: var(--t-xs);
  color: var(--muted);
}

.account-popover {
  min-width: 16rem;
  padding: 0.5rem;
}
.account-head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin: 0 0 0.35rem;
  padding: 0.35rem 0.5rem 0.65rem;
  border-bottom: 1px solid var(--hair);
}
.account-email {
  font-family: var(--font-ui);
  font-size: var(--t-md);
  color: var(--ink);
  overflow-wrap: anywhere;
}
.account-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s-4);
  padding: 0.5rem 0.55rem;
  border-radius: var(--r-md);
  font-family: var(--font-ui);
  font-size: var(--t-md);
  color: var(--ink);
  text-decoration: none;
}
a.account-row:hover {
  background: var(--accent-soft);
  color: var(--accent-text);
}
.account-row.current {
  color: var(--accent-text);
}
.account-row.coming {
  color: var(--muted);
}
.account-nav-rows {
  display: none;
}
.account-signout {
  border-top: 1px solid var(--hair);
  margin-top: 0.35rem;
  padding-top: 0.35rem;
}
.account-signout button {
  display: block;
  width: 100%;
  text-align: start;
  padding: 0.5rem 0.55rem;
  border: none;
  border-radius: var(--r-md);
  background: none;
  font-family: var(--font-ui);
  font-size: var(--t-md);
  color: var(--ink);
  cursor: pointer;
}
.account-signout button:hover {
  background: var(--accent-soft);
  color: var(--accent-text);
}
.bar-link.current {
  color: var(--accent-text);
}
@media (max-width: 44rem) {
  .bar-link {
    display: none;
  }
  .account-nav-rows {
    display: grid;
    border-bottom: 1px solid var(--hair);
    margin-bottom: 0.35rem;
    padding-bottom: 0.35rem;
  }
}

/* library shelf quick-nav + fully clickable cards */
.shelf-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin: 0.75rem 0 1.25rem;
}
.shelf-nav a {
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  padding: 0.25rem 0.75rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  color: var(--muted);
  text-decoration: none;
}
.shelf-nav a:hover {
  color: var(--accent-text);
  border-color: var(--accent);
}
.work-card {
  position: relative;
}
.work-card:hover {
  border-color: var(--accent);
}
.work-card-title::after {
  content: "";
  position: absolute;
  inset: 0;
}
.work-card .lang-chips {
  position: relative;
  z-index: 1;
}

/* compilation detail affordances */
.back-link {
  font-family: var(--font-ui);
  font-size: var(--t-md);
  color: var(--muted);
  text-decoration: none;
}
.back-link:hover {
  color: var(--accent-text);
}
.comp-edit summary {
  display: inline-flex;
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  font-size: var(--t-md);
}
.comp-edit summary:hover {
  color: var(--accent-text);
  border-color: var(--accent);
}

/* table of contents (reading.library) */
.work-toc {
  margin-top: 1.25rem;
  text-align: start;
  font-family: var(--font-ui);
}
.work-toc summary {
  display: inline-flex;
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  font-size: var(--t-md);
  color: var(--muted);
  cursor: pointer;
}
.work-toc summary:hover {
  color: var(--accent-text);
  border-color: var(--accent);
}
.work-toc ol {
  list-style: none;
  margin: 0.9rem 0 0;
  padding: 0;
  display: grid;
  gap: var(--s-1);
  max-height: 22rem;
  overflow-y: auto;
}
.work-toc a {
  display: block;
  padding: 0.3rem 0.5rem;
  border-radius: var(--r-sm);
  font-size: var(--t-lg);
  color: var(--ink);
  text-decoration: none;
}
.work-toc a:hover {
  background: var(--accent-soft);
  color: var(--accent-text);
}

/* search filters */
.search-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
  margin: 0.9rem 0 1.25rem;
  font-family: var(--font-ui);
}
.filter-label {
  font-size: var(--t-sm);
  color: var(--muted);
  margin-inline-end: 0.25rem;
}
.filter-chip {
  font-size: var(--t-sm);
  padding: 0.22rem 0.7rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  color: var(--muted);
  text-decoration: none;
}
.filter-chip:hover {
  color: var(--accent-text);
  border-color: var(--accent);
}
.filter-chip.current {
  background: var(--accent-soft);
  color: var(--accent-text);
  border-color: var(--accent);
}
.filter-in-work {
  font-family: var(--font-ui);
  font-size: var(--t-xs);
  padding: 0.12rem 0.55rem;
  border: 1px dashed var(--hair);
  border-radius: var(--r-pill);
  color: var(--muted);
  text-decoration: none;
}
.filter-in-work:hover {
  color: var(--accent-text);
  border-color: var(--accent);
}

/* selection highlight bar (study.collections) */
.sel-bar {
  position: absolute;
  z-index: 30;
  background: var(--panel);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  box-shadow: var(--e-2);
  padding: 0.2rem;
}
.sel-bar button {
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  padding: 0.3rem 0.7rem;
  border: none;
  border-radius: var(--r-sm);
  background: none;
  color: var(--ink);
  cursor: pointer;
}
.sel-bar button:hover:not(:disabled) {
  background: var(--accent-soft);
  color: var(--accent-text);
}

/* stored highlight inside a compilation entry */
.comp-item-text mark {
  background: var(--accent-soft);
  color: inherit;
  border-radius: var(--r-xs);
  padding: 0 0.1em;
}

/* settings sections (data export, account deletion) */
/* One rhythm for every setting (rebuilt 2026-08-27). Each section is a
 * heading, a sentence, a control and its save button, and the spacing is set
 * here rather than at the call site — which is what the page was doing, with
 * inline margins that disagreed with each other. */
.settings-section {
  border-block-start: 1px solid var(--hair);
  padding-block: var(--s-5) 0;
  margin-block-end: var(--s-5);
}
.settings-section h2,
.settings-section > summary {
  font-family: var(--font-serif);
  font-size: var(--d-sm);
  font-weight: 500;
  margin: 0 0 var(--s-2);
}
.settings-section > p {
  margin: 0 0 var(--s-4);
  max-inline-size: 42rem;
}
.settings-form {
  margin: 0;
}
.settings-actions {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  margin-block-start: var(--s-4);
}
.settings-saved {
  font-size: var(--t-sm);
  color: var(--muted);
}

/* Folded shut, because a destructive control that is simply there every time
 * dulls its own warning by repetition. */
.settings-danger > summary {
  cursor: pointer;
  color: var(--danger);
}
.settings-danger[open] > summary {
  margin-block-end: var(--s-4);
}
.settings-danger {
  --hair-danger: color-mix(in srgb, var(--danger) 40%, var(--hair));
  border-block-start-color: var(--hair-danger);
}
.delete-confirm {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--t-md);
  color: var(--muted);
  margin-bottom: 0.9rem;
}
.delete-confirm input {
  font: inherit;
  font-family: var(--font-ui);
  padding: 0.35rem 0.65rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--ink);
  max-width: 10rem;
}

/* per-entry notes in a compilation */
.comp-note {
  margin-top: 0.6rem;
  font-family: var(--font-ui);
}
.comp-note summary {
  font-size: var(--t-sm);
  color: var(--muted);
  cursor: pointer;
}
.comp-note summary:hover {
  color: var(--accent-text);
}
.comp-note form {
  display: grid;
  gap: var(--s-2);
  margin-top: 0.5rem;
  max-width: 32rem;
}
.comp-note textarea {
  font: inherit;
  font-family: var(--font-ui);
  font-size: var(--t-md);
  padding: 0.45rem 0.65rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--ink);
  resize: vertical;
}
.comp-note button {
  justify-self: start;
  font: inherit;
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  padding: 0.3rem 0.8rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--ink);
  cursor: pointer;
}
.comp-note button:hover {
  color: var(--accent-text);
  border-color: var(--accent);
}

/* add-to-list shortcut on library cards */
.work-card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  flex-wrap: wrap;
}
.work-card-add {
  position: relative;
  z-index: 1;
  display: flex;
  gap: var(--s-1);
  opacity: 0;
  transition: opacity var(--motion-fast);
}
.work-card:hover .work-card-add,
.work-card:focus-within .work-card-add {
  opacity: 1;
}
.work-card-add select,
.work-card-add button {
  font-family: var(--font-ui);
  font-size: var(--t-xs);
  padding: 0.1rem 0.4rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-sm);
  background: var(--panel);
  color: var(--muted);
  cursor: pointer;
  max-width: 8rem;
}
.work-card-add button:hover,
.work-card-add select:hover {
  color: var(--accent-text);
  border-color: var(--accent);
}
@media (hover: none) {
  .work-card-add {
    opacity: 1;
  }
}

/* Compilations at the account cluster (right side of the bar) */
.bar-link-right {
  margin-left: auto;
}
.bar-actions .bar-link {
  white-space: nowrap;
}
@media (max-width: 720px) {
  .bar-link-right {
    display: none; /* the account popover carries the link on narrow screens */
  }
}

/* theme switch inside the account popover */
.account-theme {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.account-theme button {
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  padding: 0.22rem 0.7rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  background: var(--panel);
  color: var(--ink);
  cursor: pointer;
}
.account-theme button:hover {
  border-color: var(--accent);
  color: var(--accent-text);
}

/* side-by-side toggle at the tab strip's right edge (VS Code pattern) */
.tab-split {
  display: grid;
  place-items: center;
  margin-left: auto;
  padding: 0.25rem 0.4rem;
  border-radius: var(--r-sm);
  color: var(--muted);
}
.tab-split:hover {
  color: var(--accent-text);
  background: var(--panel);
}
.tab-split.current {
  color: var(--accent-text);
  background: var(--accent-soft);
}
.tab-strip .tab-close-all + .tab-split {
  margin-left: 0.3rem;
}

/* screen-reader-only text */
/* ── the signed-in home: shelf hub + embedded library ─────────────── */
.home {
  max-width: 72rem;
  margin: 0 auto;
  padding: 1.5rem 1.5rem 4rem;
}
.home-welcome {
  margin: 1.5rem 0;
}
.home-row {
  margin-top: 1.6rem;
}
.home-rowhead {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
}
.home-rowhead h2,
.library-head h2 {
  font-family: var(--font-serif);
  font-size: var(--d-sm);
  font-weight: 600;
  margin: 0 0 0.6rem;
}
.home-rowhead-clear button {
  border: none;
  background: none;
  padding: 0;
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  color: var(--muted);
  cursor: pointer;
  transition: color var(--motion-fast);
}
.home-rowhead-clear button:hover {
  color: var(--danger);
}

.home-all {
  margin-left: auto;
  font-size: var(--t-md);
}
.home-byline {
  color: var(--muted);
  font-size: var(--t-sm);
}

/* horizontal shelf — scrolls sideways, snaps, keyboard-scrollable */
/* Netflix-style row (owner decision 2026-08-26). It scrolls, and the bar is
 * hidden (owner order 2026-08-27) — a scrollbar under a row of cards reads as
 * chrome the reader has to manage. Snapping is what replaces it: a card is
 * always whole at the edge, so there is never a sliver hinting at more
 * without showing it. Keyboard and trackpad scrolling are untouched. */
.shelf {
  display: flex;
  gap: var(--s-3);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  padding-block-end: var(--s-2);
}
.shelf::-webkit-scrollbar {
  display: none;
}
.shelf > * {
  scroll-snap-align: start;
}
/* tabbing through the cards scrolls the strip natively — the focused card
 * gets the ring, not the container */
.shelf-card-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.shelf-card {
  position: relative;
  flex: 0 0 11rem;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
}
.shelf-card-link {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  flex-grow: 1;
  background: var(--panel);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: 0.8rem 0.85rem 0.7rem;
  color: var(--ink);
  min-height: 6rem;
  transition:
    border-color var(--motion-fast),
    box-shadow var(--motion-fast);
}
.shelf-card-link:hover {
  border-color: var(--accent);
  box-shadow: var(--e-1);
}
.shelf-title {
  font-family: var(--font-serif);
  font-size: var(--t-lg);
  line-height: 1.3;
}
.shelf-meta {
  color: var(--muted);
  font-size: var(--t-xs);
}
.shelf-progress {
  display: block;
  margin-top: auto;
  height: 3px;
  border-radius: var(--r-xs);
  background: var(--hair);
  position: relative;
  overflow: hidden;
}
.shelf-progress::after {
  content: "";
  position: absolute;
  inset: 0;
  width: var(--p, 0%);
  background: var(--accent);
  border-radius: var(--r-xs);
}
.shelf-card .comp-cover {
  width: 2.2rem;
  height: 2.2rem;
  border-radius: var(--r-md);
  font-size: var(--t-xl);
  margin-bottom: 0.2rem;
}
.shelf-new {
  align-items: center;
  justify-content: center;
  text-align: center;
  color: var(--muted);
  border-style: dashed;
  font-family: var(--font-ui);
  font-size: var(--t-md);
}
.shelf-remove {
  position: absolute;
  top: 0.35rem;
  right: 0.35rem;
  opacity: 0;
  transition: opacity var(--motion-fast);
}
.shelf-card:hover .shelf-remove,
.shelf-card:focus-within .shelf-remove {
  opacity: 1;
}
.shelf-remove button {
  border: none;
  background: var(--bg);
  color: var(--muted);
  border-radius: var(--r-circle);
  width: 1.3rem;
  height: 1.3rem;
  line-height: 1;
  cursor: pointer;
}
.shelf-remove button:hover {
  color: var(--danger);
}
@media (hover: none) {
  .shelf-remove {
    opacity: 1;
  }
}

/* the embedded library: heading row with the view toggle */
.home .library {
  margin-top: 2.2rem;
  padding: 0;
}
.library-head {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  border-top: 1px solid var(--hair);
  padding-top: 1.4rem;
}
.view-toggle {
  border: none;
  padding: 0;
  margin: 0;
  margin-left: auto;
  display: flex;
  gap: var(--s-1);
}
.view-toggle button {
  display: grid;
  place-items: center;
  border: 1px solid transparent;
  background: transparent;
  color: var(--muted);
  border-radius: var(--r-sm);
  padding: 0.3rem 0.45rem;
  cursor: pointer;
}
.view-toggle button:hover {
  color: var(--accent-text);
}
.view-toggle button[aria-pressed="true"] {
  color: var(--accent-text);
  background: var(--accent-soft);
}

/* list view (owner order 2026-08-26): cards become calm rows */
html[data-libview="list"] .work-grid {
  display: block;
}
html[data-libview="list"] .work-card {
  display: flex;
  flex-direction: row;
  align-items: baseline;
  gap: var(--s-3);
  border: none;
  border-bottom: 1px solid var(--hair);
  border-radius: 0;
  padding: 0.45rem 0.15rem;
  background: transparent;
}
html[data-libview="list"] .work-card:hover {
  border-color: var(--hair);
  box-shadow: none;
  background: var(--panel);
}
html[data-libview="list"] .work-card-title {
  flex-grow: 1;
}
html[data-libview="list"] .work-card-foot {
  flex-wrap: nowrap;
  flex-shrink: 0;
  gap: var(--s-3);
}

/* stage one of the library: the authors */
.author-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: var(--s-3);
  margin-top: 1rem;
}
.author-card {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  background: var(--panel);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: 1rem 1.1rem;
  color: var(--ink);
  transition:
    border-color var(--motion-fast),
    box-shadow var(--motion-fast);
}
.author-card:hover {
  border-color: var(--accent);
  box-shadow: var(--e-1);
  color: var(--ink);
}

/* The authors are the library's first stage, and the home page opens on it.
 * Without these the toggle changed nothing visible on the page it lives on
 * — which is exactly how it was reported: "the list view does not work". */
html[data-libview="list"] .author-grid {
  display: block;
}
html[data-libview="list"] .author-card {
  flex-direction: row;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  border: none;
  border-block-end: 1px solid var(--hair);
  border-radius: 0;
  padding: var(--s-2) var(--s-1);
  background: transparent;
}
html[data-libview="list"] .author-card:hover {
  background: var(--panel);
}
.author-name {
  font-family: var(--font-serif);
  font-size: var(--t-xl);
}
.author-count {
  color: var(--muted);
  font-size: var(--t-sm);
}
.shelf-back {
  font-weight: 500;
}
.shelf-nav .current {
  color: var(--accent-text);
  border-color: var(--accent);
}

/* Operator dashboard (/admin). Deliberately plain: figures large enough to
   read at a glance, verdicts first, everything on the portal's own tokens so
   there is no second design to keep in sync. */
.admin {
  max-inline-size: 62rem;
  margin-inline: auto;
  padding: 2rem 1.25rem 5rem;
  font-family: var(--font-ui);
}
.admin h1 {
  font-family: var(--font-serif);
  margin-block: 0 0.4rem;
}
.admin-section {
  margin-block-start: 2.5rem;
  padding-block-start: 1.4rem;
  border-block-start: 1px solid var(--hair);
}
.admin-section h2 {
  font-size: var(--t-xl);
  margin-block: 0 1rem;
}
.admin-section h3 {
  font-size: var(--t-md);
  font-weight: 600;
  color: var(--muted);
  margin-block: 1.6rem 0.6rem;
}
.admin-figures {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-6);
}
.admin-figure {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}
.admin-figure-value {
  font-size: var(--d-lg);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.admin-figure-label {
  font-size: var(--t-sm);
  color: var(--muted);
}
.admin-figure-note {
  font-size: var(--t-xs);
  color: var(--muted);
  opacity: 0.75;
}
.admin-verdicts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}
.admin-verdict {
  display: flex;
  gap: var(--s-3);
  align-items: baseline;
  font-size: var(--t-lg);
}
.admin-detail {
  display: block;
  color: var(--muted);
  font-size: var(--t-md);
  margin-block-start: 0.2rem;
}
.admin-badge {
  flex: none;
  font-size: var(--t-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border: 1px solid currentColor;
  border-radius: var(--r-pill);
  padding: 0.1rem 0.5rem;
}
.admin-ok .admin-badge {
  color: var(--muted);
}
.admin-attention .admin-badge {
  color: var(--accent-text);
}
.admin-problem .admin-badge {
  color: var(--danger);
}
.admin-list {
  margin: 0;
  padding-inline-start: 1.1rem;
  font-size: var(--t-md);
  line-height: 1.7;
}
.admin-count {
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
.admin-scroll {
  overflow-x: auto;
}
.admin-table {
  border-collapse: collapse;
  inline-size: 100%;
  font-size: var(--t-sm);
}
.admin-table th,
.admin-table td {
  text-align: start;
  padding: 0.45rem 0.9rem 0.45rem 0;
  border-block-end: 1px solid var(--hair);
  vertical-align: top;
  white-space: nowrap;
}
.admin-table td:last-child {
  white-space: normal;
  min-inline-size: 22rem;
}
.admin-table th {
  color: var(--muted);
  font-weight: 500;
}

/* --- privacy notice and consent (release.legal part 1) -------------------- */

/* A legal text is read, not scanned: the reading measure and the serif face
 * are the same ones the writings get, minus the reader chrome. */
.legal {
  max-inline-size: 42rem;
  padding-block: 3.5rem 5rem;
  gap: 0;
  display: block;
  font-family: var(--font-ui);
}
.legal h1 {
  font-family: var(--font-serif);
  font-size: var(--d-lg);
  font-weight: 500;
  margin: 0 0 1.75rem;
}
.legal h2 {
  font-family: var(--font-serif);
  font-size: var(--t-xl);
  font-weight: 500;
  margin: 2.25rem 0 0.6rem;
}
.legal p {
  margin: 0 0 0.9rem;
  line-height: 1.65;
}
.legal ul {
  margin: 0 0 0.9rem;
  padding-inline-start: 1.2rem;
  line-height: 1.65;
}
.legal li {
  margin-block-end: 0.5rem;
}

/* An unfilled blank must look unfinished. Rendering it as ordinary prose
 * would let a placeholder be read as the controller's actual name. */
.legal-blank {
  background: var(--accent-soft);
  color: var(--accent-text);
  border-radius: var(--r-xs);
  padding: 0.05em 0.35em;
  box-decoration-break: clone;
}
.legal-blank .muted {
  display: inline;
  font-size: 0.85em;
}
.legal-foot {
  margin-block-start: 2.5rem;
  padding-block-start: 1.25rem;
  border-block-start: 1px solid var(--hair);
}

.landing-foot {
  position: relative;
  text-align: center;
  padding: 0 1.5rem 3rem;
  font-size: var(--t-md);
  color: var(--muted);
}

.consent {
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  background: var(--panel);
  padding: 1.25rem;
  display: grid;
  gap: var(--s-3);
}
.consent h2 {
  font-family: var(--font-serif);
  font-size: var(--t-xl);
  font-weight: 500;
  margin: 0;
}
.consent p {
  margin: 0;
}
.consent-agree {
  display: flex;
  align-items: start;
  gap: var(--s-3);
  font-size: var(--t-lg);
  line-height: 1.5;
  cursor: pointer;
}
.consent-agree input {
  margin-block-start: 0.25rem;
  inline-size: 1.05rem;
  block-size: 1.05rem;
  accent-color: var(--accent);
  flex: none;
}
.consent-decline {
  font-size: var(--t-md);
  color: var(--muted);
}
.consent-decline summary {
  cursor: pointer;
}
.consent-decline > *:not(summary) {
  margin-block-start: 0.75rem;
}

/* --- the ways in (reading.auth) ------------------------------------------- */

.login {
  gap: var(--s-4);
}
.provider-list {
  display: grid;
  gap: var(--s-2);
}
.button-provider {
  inline-size: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  padding: 12px 14px;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--ink);
  font: inherit;
  font-size: var(--t-lg);
  cursor: pointer;
}
.button-provider:hover {
  border-color: var(--muted);
}
.provider-mark {
  inline-size: 1.15rem;
  block-size: 1.15rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-circle);
  border: 1px solid var(--hair);
  font-size: var(--t-sm);
  font-weight: 600;
  flex: none;
}

/* A labelled divider, drawn with borders rather than a pseudo-element grid so
   it survives the plain-HTML delivery path too. */
.rule {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  color: var(--muted);
  font-size: var(--t-md);
  margin: 0;
}
.rule::before,
.rule::after {
  content: "";
  flex: 1;
  border-block-start: 1px solid var(--hair);
}

.login-foot {
  margin-block-start: 0.5rem;
  padding-block-start: 1rem;
  border-block-start: 1px solid var(--hair);
  font-size: var(--t-md);
}

/* --- the foot of a signed-in page (owner order 2026-08-27) --------------- */

.site-foot {
  max-inline-size: 72rem;
  margin: var(--s-8) auto 0;
  padding: var(--s-5) var(--s-5) var(--s-6);
  border-block-start: 1px solid var(--hair);
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  color: var(--muted);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
}
/* The version sits first and reads as a label rather than as prose. */
.site-foot-version {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  color: var(--muted);
}
.site-foot-note {
  flex: 1;
  margin: 0;
  min-inline-size: 14rem;
  max-inline-size: 38rem;
}
.site-foot-links {
  display: flex;
  gap: var(--s-4);
  margin: 0;
}

/* --- what a page looks like while its data is coming -------------------- */
/* The shapes and the reasoning are in `app/skeleton.tsx`; what is here is
 * only the grey and its movement. The placeholders themselves are the
 * portal's own components, so nothing below sets a width or a radius that
 * could disagree with the thing it stands in for.
 *
 * The movement is a slow sweep rather than a pulse: at these contrasts a
 * change in opacity is nearly invisible, which is how the first version
 * managed to look broken rather than busy. It stops entirely for anyone who
 * asked for less motion. */

.skeleton {
  display: block;
  border-radius: var(--r-sm);
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--hair) 70%, var(--panel)) 25%,
    color-mix(in srgb, var(--hair) 30%, var(--panel)) 37%,
    color-mix(in srgb, var(--hair) 70%, var(--panel)) 63%
  );
  background-size: 400% 100%;
  animation: skeleton-sweep 1.6s ease-in-out infinite;
}
@keyframes skeleton-sweep {
  from {
    background-position: 100% 50%;
  }
  to {
    background-position: 0 50%;
  }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton {
    animation: none;
  }
}

.skeleton-line {
  block-size: 0.8em;
  margin-block: 0.3em;
}
/* Sized like the heading it sits inside, so the row head keeps its height. */
.skeleton-heading {
  inline-size: 9rem;
  block-size: 1em;
}
/* The three parts of the bar that are not the brand. */
.skeleton-field {
  flex: 1;
  max-inline-size: 26rem;
  block-size: var(--control);
  border-radius: var(--r-md);
}
.skeleton-avatar {
  inline-size: 2rem;
  block-size: 2rem;
  border-radius: var(--r-circle);
}
.skeleton-tab {
  inline-size: 9rem;
  block-size: 1.6rem;
  border-radius: var(--r-md);
}

/* --- compilations, in two panes (owner order 2026-08-27) ---------------- */
/* Left is where things are, right is what is there. The sidebar collapses
 * above the grid on a narrow screen rather than becoming a drawer: a drawer
 * needs a control to open it, and the tree is short enough to sit in the
 * flow. */

.comp-page {
  display: grid;
  grid-template-columns: 15rem minmax(0, 1fr);
  gap: var(--s-6);
  align-items: start;
  max-inline-size: 72rem;
  margin-inline: auto;
  padding: var(--s-6) var(--s-5) var(--s-8);
}
.comp-sidebar {
  position: sticky;
  inset-block-start: var(--s-8);
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  font-family: var(--font-ui);
  font-size: var(--t-sm);
}
.comp-main {
  min-inline-size: 0;
}
.comp-main h1 {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: var(--d-lg);
  margin: 0 0 var(--s-2);
}

/* The open folder's name is the page's heading and its rename control at
 * once, so a name is changed where it is being read. */
.folder-rename {
  display: flex;
  gap: var(--s-2);
  align-items: center;
  margin-block-end: var(--s-2);
}
.folder-rename input {
  font-family: var(--font-serif);
  font-size: var(--d-md);
  border-color: transparent;
  background: transparent;
  padding-inline: var(--s-2);
}
.folder-rename input:hover,
.folder-rename input:focus {
  background: var(--panel);
  border-color: var(--hair);
}
.folder-rename button {
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  padding: var(--s-1) var(--s-3);
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  color: var(--muted);
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--motion-fast);
}
.folder-rename:hover button,
.folder-rename:focus-within button {
  opacity: 1;
}

.folder-tree {
  list-style: none;
  margin: var(--s-2) 0 0;
  padding: 0;
}
/* Each level steps in by one spacing unit. Three levels is the cap, so the
 * deepest row is still three units from the edge — a tree that indents
 * further than it nests is a tree you scroll sideways. */
.folder-tree .folder-tree {
  margin-block-start: 0;
  padding-inline-start: var(--s-3);
}
.folder-row {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-1) var(--s-2);
  border-radius: var(--r-md);
  color: var(--muted);
  transition:
    background var(--motion-fast),
    color var(--motion-fast);
}
.folder-row > a {
  flex: 1;
  min-inline-size: 0;
  color: inherit;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.folder-row:hover {
  background: var(--panel);
  color: var(--ink);
}
.folder-row.current {
  background: var(--accent-soft);
  color: var(--accent-text);
}
.folder-count {
  flex-shrink: 0;
  font-size: var(--t-xs);
  color: var(--muted);
}
/* Quiet until the row is hovered, like the tab close it mirrors. */
.folder-delete button {
  display: block;
  border: none;
  background: none;
  padding: 0 var(--s-1);
  font-family: inherit;
  color: var(--muted);
  opacity: 0;
  cursor: pointer;
  transition:
    opacity var(--motion-fast),
    color var(--motion-fast);
}
.folder-row:hover .folder-delete button,
.folder-delete button:focus-visible {
  opacity: 1;
}
.folder-delete button:hover {
  color: var(--danger);
}
.folder-new {
  display: flex;
  gap: var(--s-2);
  margin-block-start: var(--s-4);
}
.folder-new input {
  min-inline-size: 0;
  flex: 1;
  font-size: var(--t-sm);
}
.folder-new button {
  flex-shrink: 0;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  padding-inline: var(--s-2);
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  color: var(--muted);
  cursor: pointer;
}
.folder-new button:hover {
  border-color: var(--accent);
  color: var(--accent-text);
}

/* The card and the control that files it are one block, so the select never
 * sits inside the link. */
.comp-card-shell {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}
.comp-file {
  display: flex;
  gap: var(--s-2);
  opacity: 0;
  transition: opacity var(--motion-fast);
}
.comp-card-shell:hover .comp-file,
.comp-file:focus-within {
  opacity: 1;
}
.comp-file select {
  min-inline-size: 0;
  flex: 1;
  font-size: var(--t-xs);
}
.comp-file button {
  flex-shrink: 0;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  padding-inline: var(--s-2);
  font-family: var(--font-ui);
  font-size: var(--t-xs);
  color: var(--muted);
  cursor: pointer;
}

@media (max-width: 52rem) {
  .comp-page {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-5);
  }
  .comp-sidebar {
    position: static;
  }
  /* Touch has no hover, so the filing control is simply always there. */
  .comp-file,
  .folder-delete button {
    opacity: 1;
  }
}

/* --- the legal documents, opened in place (owner order 2026-08-28) ------- */
/* An app people move around in should not send them away to read a notice.
 * Both documents are in the page already; this is only how they look when
 * one is open. The pages at /privacy and /impressum stay exactly as they
 * were — a shared link and a crawler both need them. */

.legal-dialog {
  inline-size: min(46rem, 92vw);
  max-block-size: 84vh;
  margin: 8vh auto auto;
  padding: 0;
  border: 1px solid var(--hair);
  border-radius: var(--r-xl);
  background: var(--panel);
  color: var(--ink);
  box-shadow: var(--e-3);
  overflow: hidden;
}
.legal-dialog::backdrop {
  background: color-mix(in srgb, var(--ink) 45%, transparent);
}
.legal-dialog-body {
  max-block-size: 84vh;
  overflow-y: auto;
  padding: var(--s-6) var(--s-6) var(--s-7);
  margin: 0;
}
.legal-dialog-close {
  position: sticky;
  inset-block-start: 0;
  display: flex;
  justify-content: flex-end;
  padding: var(--s-2) var(--s-2) 0;
  background: var(--panel);
  z-index: 1;
}
.legal-dialog-close button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 2rem;
  block-size: 2rem;
  border: none;
  border-radius: var(--r-circle);
  background: transparent;
  font-family: inherit;
  font-size: var(--t-lg);
  color: var(--muted);
  cursor: pointer;
  transition:
    background var(--motion-fast),
    color var(--motion-fast);
}
.legal-dialog-close button:hover {
  background: var(--bg);
  color: var(--ink);
}

/* --- a compilation, with its neighbourhood beside it -------------------- */
/* The third pane (owner order 2026-08-27, built 2026-08-28). Folders, then
 * the lists, then the one being read. The compilation keeps its own URL and
 * these are chrome around it, which is why the middle column is a narrow
 * list here and a grid of cards on the index: browsing and switching are
 * different acts and want different widths. */

.comp-page-three {
  grid-template-columns: 13rem 15rem minmax(0, 1fr);
  max-inline-size: 92rem;
  gap: var(--s-5);
}
/* The reading column keeps its measure but stops centring itself inside the
 * pane — a column that drifts away from the list it belongs to reads as two
 * unrelated pages. */
.comp-page-three .comp-main {
  max-inline-size: calc(var(--measure) + 8rem);
  margin-inline: 0;
  padding: 0;
}
.comp-back {
  margin: 0 0 var(--s-5);
}

.comp-list {
  position: sticky;
  inset-block-start: var(--s-8);
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  max-block-size: 78vh;
  overflow-y: auto;
  /* The list is a column of its own; the hairline says so without a box. */
  padding-inline-end: var(--s-3);
  border-inline-end: 1px solid var(--hair);
}
.comp-list-row {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-1);
  border-radius: var(--r-md);
  color: var(--ink);
  text-decoration: none;
  transition: background var(--motion-fast);
}
.comp-list-row:hover {
  background: var(--panel);
}
.comp-list-row.current {
  background: var(--accent-soft);
}
.comp-list-row .comp-cover {
  inline-size: 2rem;
  block-size: 2rem;
  border-radius: var(--r-sm);
  font-size: var(--t-lg);
}
.comp-list-text {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-2);
  flex: 1;
  min-inline-size: 0;
}
.comp-list-title {
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.comp-list-meta {
  flex-shrink: 0;
  font-size: var(--t-xs);
  color: var(--muted);
}

/* Below three columns the list folds away: at this width it would be a
 * sliver, and the way back is already in the sidebar and the back link. */
@media (max-width: 68rem) {
  .comp-page-three {
    grid-template-columns: 13rem minmax(0, 1fr);
  }
  .comp-list {
    display: none;
  }
}
@media (max-width: 52rem) {
  .comp-page-three {
    grid-template-columns: minmax(0, 1fr);
  }
}
