/* Gospel Bookmarks - base stylesheet.
   "Illuminated" visual design pass (phase 3): a warm, manuscript-inspired
   palette - burgundy and antique gold on parchment - built on the token set
   phase 2 left in place. Every colour and font below is a token; component
   rules read from the tokens rather than hard-coding a shade, so light/dark
   and any future theme stay in sync automatically. */

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/inter-variable.260c81a4759b.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/inter-variable.260c81a4759b.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/inter-variable.260c81a4759b.woff2") format("woff2");
}
/* Literata: the reading face for long text - talks, articles, quotes, notes,
   scripture. A book serif designed for screens; variable weight in one file. */
@font-face {
  font-family: "Literata";
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url("../fonts/literata-variable.cbfd016a5c91.woff2") format("woff2");
}
@font-face {
  font-family: "Literata";
  font-style: italic;
  font-weight: 200 900;
  font-display: swap;
  src: url("../fonts/literata-variable-italic.9e96203853e3.woff2") format("woff2");
}
@font-face {
  font-family: "Playfair Display";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/playfair-700.9401d0214a93.woff2") format("woff2");
}
@font-face {
  font-family: "Playfair Display";
  font-style: italic;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/playfair-600italic.7ac3358f7c5a.woff2") format("woff2");
}

:root {
  --ground: #faf6ee;
  --surface: #ffffff;
  --surface-alt: #f5eee0;
  --ink: #2b2420;
  --ink-2: #6e6259;
  --ink-3: #9a8d80;
  --rule: #e8dec9;
  --accent: #7a2331;
  --accent-2: #a6404b;
  --accent-tint: #f4e7bf;
  --accent-ink: #ffffff;
  --danger: #b23a34;
  --ok: #3f7d58;
  --radius: 8px;
  --shadow: 0 1px 2px rgba(43, 22, 16, .05), 0 4px 14px rgba(43, 22, 16, .07);
  --shadow-hover: 0 10px 26px rgba(43, 22, 16, .14);

  --font-head: "Playfair Display", Georgia, "Times New Roman", serif;
  --font-body: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-read: "Literata", Georgia, "Times New Roman", serif;
  --font-mono: ui-monospace, "Cascadia Mono", Consolas, monospace;

  /* Reading text: one size and rhythm everywhere long text appears. */
  --read-size: 1.1875rem;
  --read-leading: 1.75;

  /* Breakpoints (for reference - custom properties cannot be used inside
     @media): 40rem phone -> tablet, 64rem tablet -> desktop, 90rem wide. */

  /* Highlight colours (plan §09) - must stay in sync with
     highlights.models.HighlightColor. */
  --hl-yellow: #fdf1a0;
  --hl-green: #b9e6b0;
  --hl-blue: #b8dcf5;
  --hl-pink: #f7c6dd;
  --hl-orange: #fad2a6;
  --hl-ink: var(--ink);
}

/* The member's own choice (accounts.User.theme, set as data-theme on <html>)
   beats the device: "light" skips this block, "dark" is repeated just below
   for devices that prefer light. Keep the two dark lists in step. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ground: #1a1013;
    --surface: #241318;
    --surface-alt: #2c1920;
    --ink: #f1e8dd;
    --ink-2: #c7b9ac;
    --ink-3: #8f8177;
    --rule: #3a2530;
    --accent: #d9b863;
    /* Lifted from the light theme's #a6404b: on the dark ground that shade
       lands at 4.16:1, under the 4.5:1 AA floor for body-size link text. */
    --accent-2: #d67c8c;
    --accent-tint: #3b2e15;
    --accent-ink: #241318;
    --danger: #e0847c;
    --ok: #79c199;
    --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 4px 14px rgba(0, 0, 0, .28);
    --shadow-hover: 0 10px 26px rgba(0, 0, 0, .4);

    --hl-yellow: #6b5e12;
    --hl-green: #285c2c;
    --hl-blue: #234a63;
    --hl-pink: #6b2b49;
    --hl-orange: #6b3d12;
  }
}

:root[data-theme="dark"] {
  --ground: #1a1013;
  --surface: #241318;
  --surface-alt: #2c1920;
  --ink: #f1e8dd;
  --ink-2: #c7b9ac;
  --ink-3: #8f8177;
  --rule: #3a2530;
  --accent: #d9b863;
  --accent-2: #d67c8c;
  --accent-tint: #3b2e15;
  --accent-ink: #241318;
  --danger: #e0847c;
  --ok: #79c199;
  --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 4px 14px rgba(0, 0, 0, .28);
  --shadow-hover: 0 10px 26px rgba(0, 0, 0, .4);
  --hl-yellow: #6b5e12;
  --hl-green: #285c2c;
  --hl-blue: #234a63;
  --hl-pink: #6b2b49;
  --hl-orange: #6b3d12;
}

* { box-sizing: border-box; }
/* The hidden attribute always wins. The browser's own [hidden] rule is
   overridden by any class that sets display (.button, .card ...), so a
   script hiding a button with el.hidden = true left it on screen - and
   clickable, with nothing behind it. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font: 400 16px/1.6 var(--font-body);
  -webkit-font-smoothing: antialiased;
  /* A column whose main grows, so the footer sits at the bottom of the
     screen on a short page instead of floating halfway up it. */
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100svh;
}
/* In a flex column, main's auto side margins would shrink it to its content;
   a full width (capped by max-width and the .layout--* widths) keeps it put. */
body > main { flex: 1 0 auto; width: 100%; }

h1, h2, h3 { font-family: var(--font-head); font-weight: 700; letter-spacing: -.01em; text-wrap: balance; }

a { color: var(--accent-2); text-decoration-color: color-mix(in srgb, var(--accent-2) 45%, transparent); }
a:hover { color: var(--accent); }
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--accent-2);
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  left: -9999px;
}
.skip-link:focus {
  left: 1rem;
  top: 1rem;
  z-index: 10;
  background: var(--surface);
  padding: .5rem .75rem;
  border-radius: var(--radius);
}

/* --- Header ---------------------------------------------------------------- */

.site-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
  padding: .9rem 1.5rem;
  background: var(--surface);
  border-bottom: 1px solid var(--rule);
  box-shadow: var(--shadow);
  position: relative;
  z-index: 5;
}

.brand {
  font-family: var(--font-head);
  font-size: 1.2rem;
  font-weight: 700;
  text-decoration: none;
  color: var(--ink);
  display: inline-flex;
  align-items: center;
  gap: .55rem;
}
.brand::before {
  content: "";
  width: .6rem;
  height: .6rem;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  flex-shrink: 0;
}

.site-account { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; margin-left: auto; }

/* --- Side menu ------------------------------------------------------------- */
/* Off-canvas drawer by default; a permanent left column from 64rem up. */

.nav-toggle-input { position: absolute; opacity: 0; pointer-events: none; }
.nav-toggle {
  order: -1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.4rem;
  height: 2.4rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  color: var(--ink-2);
  cursor: pointer;
}
.nav-toggle:hover { background: var(--accent-tint); }
/* Three lines: the middle one is the element, the outer two are its shadows. */
.nav-toggle__bars,
.nav-toggle__bars::before,
.nav-toggle__bars::after {
  display: block;
  width: 1.2rem;
  height: 2px;
  background: currentColor;
  border-radius: 1px;
}
.nav-toggle__bars { position: relative; }
.nav-toggle__bars::before,
.nav-toggle__bars::after { content: ""; position: absolute; left: 0; }
.nav-toggle__bars::before { top: -6px; }
.nav-toggle__bars::after { top: 6px; }
.nav-toggle-input:focus-visible + .nav-toggle { outline: 2px solid var(--accent-2); outline-offset: 2px; }
.nav-backdrop { display: none; }

.site-sidebar {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  width: 16rem;
  max-width: 85vw;
  overflow-y: auto;
  padding: 1rem 1rem 2rem;
  background: var(--surface);
  border-right: 1px solid var(--rule);
  box-shadow: var(--shadow);
  transform: translateX(-100%);
  transition: transform .2s ease;
  z-index: 20;
}
.nav-toggle-input:checked ~ .site-sidebar { transform: none; }
.nav-toggle-input:checked ~ .nav-backdrop {
  display: block;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .35);
  z-index: 15;
}

.site-sidebar .brand { margin: 0 0 1rem .5rem; }
.side-section { margin-bottom: 1.1rem; }
.side-heading {
  margin: 0 0 .3rem .5rem;
  font: 700 .72rem/1.4 var(--font-body);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.site-sidebar a:not(.brand) {
  display: block;
  padding: .35rem .5rem;
  border-radius: var(--radius);
  color: var(--ink-2);
  text-decoration: none;
  font-size: .93rem;
  font-weight: 600;
  transition: color .15s ease, background-color .15s ease;
}
.site-sidebar a:not(.brand):hover { color: var(--ink); background: var(--accent-tint); }

@media print {
  .site-sidebar, .nav-toggle { display: none; }
}

.site-search { margin: 0; }
.site-search input {
  padding: .4rem .7rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--ground);
  color: var(--ink);
  font: inherit;
  width: 11rem;
  transition: border-color .15s ease, box-shadow .15s ease, width .2s ease;
}
.site-search input:focus { width: 14rem; border-color: var(--accent-2); }
/* The live dropdown under the header box (static/js/sitesearch.js). */
.site-search { position: relative; }
.site-search__panel {
  position: absolute; z-index: 40; top: calc(100% + .35rem); right: 0;
  width: min(28rem, calc(100vw - 2rem));
}
.site-search__panel[hidden] { display: none; }
.site-search__list { position: static; margin: 0; max-height: min(70vh, 32rem); }
.site-search__group {
  padding: .5rem .8rem .25rem;
  font-size: .72rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-3); background: var(--ground);
  border-top: 1px solid var(--rule);
}
.site-search__group:first-child { border-top: 0; }
.site-search__hit a { display: flex; flex-direction: column; gap: .1rem; min-width: 0; color: inherit; text-decoration: none; }
.site-search__title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.site-search__where { font-size: .78rem; color: var(--ink-3); }
.site-search__all { font-weight: 600; color: var(--accent); }
.site-search__empty { padding: .6rem .8rem; font-size: .88rem; color: var(--ink-2); }
@media (max-width: 40rem) {
  /* Phone: the box takes a row of its own, full width, and the results open
     the width of the screen beneath it. */
  .site-search { flex: 1 1 100%; order: 10; }
  .site-search input, .site-search input:focus { width: 100%; }
  .site-search__panel { left: 0; right: 0; width: auto; }
}
.whoami { color: var(--ink-3); font-size: .88rem; }
.inline-form { display: inline; margin: 0; }

/* --- Avatar and account menu ------------------------------------------------ */

.avatar {
  --size: 2.25rem;
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--size); height: var(--size); border-radius: 50%;
  background: var(--accent-tint); color: var(--accent);
  font-weight: 600; font-size: calc(var(--size) * .42); line-height: 1;
  object-fit: cover; overflow: hidden; flex: none;
}
.avatar--large { --size: 6rem; }
.avatar--small { --size: 1.5rem; }

.account-menu { position: relative; }
.account-menu > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: .5rem;
  min-height: 2.75rem; /* touch target */
}
.account-menu > summary::-webkit-details-marker { display: none; }
.account-menu__panel {
  position: absolute; right: 0; top: 100%; z-index: 30; min-width: 12rem;
  background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: .5rem; display: grid; gap: .25rem;
}
.account-menu__panel a, .account-menu__panel button {
  display: block; padding: .6rem .75rem; min-height: 2.75rem; text-align: left;
  border-radius: var(--radius); text-decoration: none; color: var(--ink);
  font: inherit; background: none; border: none; cursor: pointer; width: 100%;
}
.account-menu__panel a:hover, .account-menu__panel button:hover { background: var(--surface-alt); }
.account-menu__who { padding: .4rem .75rem; color: var(--ink-3); font-size: .85rem; overflow-wrap: anywhere; }

.profile-picture { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }

.linklike {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-weight: 600;
  color: var(--accent-2);
  cursor: pointer;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--accent-2) 45%, transparent);
}
.linklike:hover { color: var(--accent); }

/* --- Layout ---------------------------------------------------------------- */

/* Page widths, chosen per template with {% block main_class %}: the default
   (dashboards, settings, simple lists); --wide for card grids; --reading for
   anything long-form, which spans about 80% of a desktop screen and keeps a
   Connections column beside the text; --narrow for forms. Below 64rem the
   wide layouts go full width; below 40rem the gutter tightens to 1rem. */
main, .layout { max-width: 62rem; margin: 0 auto; padding: 1.5rem; }
.layout--wide { max-width: 110rem; width: 94%; }
.layout--reading { max-width: 110rem; width: 80%; }
.layout--narrow { max-width: 40rem; }
@media (max-width: 64rem) {
  .layout--wide, .layout--reading { width: 100%; }
}
@media (max-width: 40rem) {
  main, .layout { padding: 1rem; }
}
.detail { max-width: none; min-width: 0; }
.prose { max-width: 42rem; }
.detail .prose { max-width: none; }

h1 { font-size: 1.9rem; line-height: 1.2; margin: 0 0 .5rem; }
h2 { font-size: 1.3rem; margin: 1.75rem 0 .6rem; }

.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: 1.1rem;
  margin-bottom: .25rem;
  border-bottom: 1px solid var(--rule);
}
.page-head__actions { display: inline-flex; flex-wrap: wrap; gap: .5rem; }

.muted { color: var(--ink-3); font-size: .9rem; }
.empty { color: var(--ink-2); padding: 1.5rem 0; }

/* --- Messages -------------------------------------------------------------- */

.messages { list-style: none; margin: 0; padding: .75rem 1.5rem; }
/* Each background is declared twice: a flat token first, then the tinted
   color-mix. Browsers without color-mix drop the second declaration and keep
   the first, so the message still reads as a raised panel. */
.message {
  padding: .65rem 1rem;
  border-radius: var(--radius);
  border-left: 3px solid var(--accent-2);
  background: var(--surface);
  background: color-mix(in srgb, var(--accent-2) 8%, var(--surface));
  margin-bottom: .4rem;
}
.message--success {
  border-left-color: var(--ok);
  background: var(--surface);
  background: color-mix(in srgb, var(--ok) 10%, var(--surface));
}
.message--error {
  border-left-color: var(--danger);
  background: var(--surface);
  background: color-mix(in srgb, var(--danger) 10%, var(--surface));
}

/* --- Cards ----------------------------------------------------------------- */

.card-list { list-style: none; margin: 1rem 0; padding: 0; display: grid; gap: .75rem; }

.card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1.1rem 1.25rem;
  box-shadow: var(--shadow);
  transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}
.card-list .card:hover {
  box-shadow: var(--shadow-hover);
  border-color: color-mix(in srgb, var(--accent-2) 25%, var(--rule));
  transform: translateY(-1px);
}
.card h2, .card h3 { margin: 0 0 .35rem; font-size: 1.08rem; font-family: var(--font-body); font-weight: 700; }
.card h2 a, .card h3 a { color: var(--ink); text-decoration: none; }
.card h2 a:hover, .card h3 a:hover { color: var(--accent-2); }
.card h2 .swatch { vertical-align: middle; margin-right: .4rem; }
.card p { margin: .25rem 0; color: var(--ink-2); }

/* Quotes list: a grid of cards that gains columns as the screen widens. Each
   card shows the first seven lines of its quote; the full text is on the
   detail page. */
.card-list--quotes { grid-template-columns: 1fr; gap: 1rem; }
@media (min-width: 40rem) { .card-list--quotes { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 64rem) { .card-list--quotes { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 90rem) { .card-list--quotes { grid-template-columns: repeat(4, 1fr); } }
/* Portrait on desktop: taller than wide, the body takes the spare height and
   clamps. Below 64rem the card is as tall as its text needs - a forced aspect
   ratio on a phone-width card is a tall box of mostly nothing. */
.quote-card { display: flex; flex-direction: column; min-width: 0; }
@media (min-width: 64rem) { .quote-card { aspect-ratio: 3 / 4; } }
.quote-card h2 { font-size: .95rem; }
.quote-card__body {
  margin: .25rem 0;
  padding: 0 0 0 .75rem;
  border-left: 3px solid var(--accent-2);
  color: var(--ink-2);
  white-space: pre-line;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 7;
  line-clamp: 7;
  overflow: hidden;
  font-family: var(--font-read);
  font-style: italic;
  line-height: 1.6;
}
@media (min-width: 64rem) { .quote-card__body { -webkit-line-clamp: 9; line-clamp: 9; } }
.quote-card__body a { color: inherit; text-decoration: none; }
.quote-card__body a:hover { color: var(--accent-2); }
.quote-card .topic-list { margin: .35rem 0 0; }
.quote-card__by { margin: .25rem 0; font-style: italic; }
.quote-card .item-meta { margin-top: auto; padding-top: .5rem; }

/* Talks list: three cards across on wide screens (fewer when narrow). Each
   card shows the speaker's image if there is one, and the first 12 lines of
   the talk; the full text is on the detail page. */
.card-list--talks { grid-template-columns: 1fr; gap: 1rem; }
@media (min-width: 40rem) { .card-list--talks { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 64rem) { .card-list--talks { grid-template-columns: repeat(3, 1fr); } }
.talk-card { display: flex; flex-direction: column; min-width: 0; }
.talk-card__head { display: flex; gap: .75rem; align-items: center; }
.talk-card__image { width: 3.5rem; height: 3.5rem; border-radius: 50%; object-fit: cover; flex: none; }
.talk-card__by { font-style: italic; }
.talk-card__body {
  white-space: pre-line;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 6;
  line-clamp: 6;
  overflow: hidden;
}
.talk-card .topic-list { margin: .35rem 0 0; }
.talk-card .item-meta { margin-top: auto; padding-top: .5rem; }

.item-meta { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; margin: .5rem 0; }

.badge {
  font-size: .7rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  font-weight: 600;
  padding: .18rem .5rem;
  border-radius: 3px;
  background: var(--surface-alt);
  border: 1px solid var(--rule);
  color: var(--ink-2);
}
.badge--public { border-color: var(--ok); color: var(--ok); }
.badge--unlisted { border-color: var(--accent); color: var(--accent); }
/* A topic's own: used by this viewer somewhere (topics/services.py my_topics). */
.badge--mine { border-color: var(--accent-2); color: var(--accent-2); }
.combobox__badge { margin-left: .35rem; vertical-align: middle; }

/* --- The personal layer ------------------------------------------------------ */
/* A withdrawn item, shown from the snapshot taken when somebody first built on
   it. Muted rather than hidden: their notes are still theirs, and a row that
   silently disappeared would be worse than one that explains itself. */
.card--tombstone { opacity: .75; border-style: dashed; }
.card--tombstone h2 { color: var(--ink-3); }

/* Your own tagging, kept visually distinct from the owner's topics above it -
   the two are different things and the difference matters. */
.my-topics { margin: .6rem 0; display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
.my-topics .topic { display: inline-flex; gap: .3rem; align-items: center; }
.my-topics .combobox-form { display: flex; flex: 1 1 18rem; gap: .5rem; align-items: flex-start; }
.my-topics .combobox-form .combobox { flex: 1; }
.my-topics .combobox-field { flex: 1; position: relative; }

/* The box sits outside any .field wrapper, so it needs the form-input look
   spelled out here: same border, radius and focus ring as the other inputs. */
.combobox-form input[type="text"] {
  width: 100%;
  min-width: 12rem;
  padding: .45rem .8rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: .92rem;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.combobox-form input[type="text"]::placeholder { color: var(--ink-3); }
.combobox-form input[type="text"]:focus {
  outline: none;
  border-color: var(--accent-2);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-2) 18%, transparent);
}

/* --- Live-search box (static/js/combobox.js) --------------------------------- */
/* One control for every topic and author box on the site: the item form, the
   item page, the "Add to my topics" dialog, the highlight menu and the topic
   filter on list pages. The list drops under the input, one name per row with
   a rule between rows; a "+ Add" row closes it when nothing matches. */
.combobox { display: flex; flex-direction: column; gap: .35rem; min-width: 0; }
.combobox__box { position: relative; }
.combobox input[type="text"] { width: 100%; min-width: 0; }
.combobox__list {
  position: absolute; z-index: 30; left: 0; right: 0; top: 100%;
  margin: .2rem 0 0; padding: 0; list-style: none;
  max-height: 16rem; overflow-y: auto; overscroll-behavior: contain;
  background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius);
  box-shadow: var(--shadow-hover);
}
.combobox__list[hidden], .combobox__hint[hidden], .combobox__chips[hidden] { display: none; }
.combobox__option {
  display: flex; align-items: center;
  min-height: 2.5rem; padding: .45rem .8rem;
  font-size: .92rem; line-height: 1.3; color: var(--ink);
  cursor: pointer;
}
.combobox__option + .combobox__option { border-top: 1px solid var(--rule); }
.combobox__option:hover, .combobox__option--active { background: var(--accent-tint); }
.combobox__option--add { color: var(--accent); font-weight: 600; }
.combobox__option--add::before {
  content: "+";
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.3rem; height: 1.3rem; margin-right: .5rem; flex-shrink: 0;
  border-radius: 50%; background: var(--accent); color: var(--surface);
  font-weight: 700; line-height: 1;
}
.combobox__hint { margin: 0; font-size: .85rem; }
.combobox__hint .linklike { font-weight: 600; color: var(--accent); }
@media (max-width: 40rem) {
  /* Thumb-sized rows on a phone. */
  .combobox__option { min-height: 2.9rem; }
}

/* Chosen topics in a multi box. */
.combobox__chips { display: flex; flex-wrap: wrap; gap: .3rem; margin: 0; padding: 0; list-style: none; }
.combobox__chip {
  display: inline-flex; align-items: center; gap: .25rem;
  padding: .2rem .25rem .2rem .65rem;
  border-radius: 999px; background: var(--accent-tint); color: var(--ink);
  font-size: .85rem;
}
.combobox__chip-remove {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.4rem; height: 1.4rem; padding: 0;
  border: 0; border-radius: 50%; background: transparent;
  color: var(--ink-2); font-size: 1rem; line-height: 1; cursor: pointer;
}
.combobox__chip-remove:hover { background: var(--rule); color: var(--ink); }
.button--add[hidden] { display: none; }
.button--add { font-weight: 700; line-height: 1; min-width: 2.4rem; }

/* --- Fill from a link -------------------------------------------------------- */
/* Sits at the top of an add form. Deliberately quiet: it is a shortcut, not the
   main event, and what it fills in still has to be read before saving. */
.urlfetch { border: 1px dashed var(--rule); border-radius: var(--radius); padding: .8rem .9rem; }
.urlfetch__row { display: flex; gap: .5rem; align-items: center; }
.urlfetch__row input { flex: 1 1 auto; }
.urlfetch__status { color: var(--accent-2); }
/* What the fetch filled in, so it can be spotted and checked rather than
   trusted. Fades on focus - once someone has looked at it, it is theirs. */
.field--autofilled { background: var(--accent-tint); }
.field--autofilled:focus { background: var(--surface); }

/* --- Source and verification ------------------------------------------------ */
/* Two marks, never one. "Source given" is self-declared and says only that the
   box was filled in; the green tick is earned by an automatic check and its
   title attribute names what was actually checked. Conflating them would make
   the tick mean "somebody typed something", which is worse than no badge. */
.source { margin: .6rem 0; color: var(--ink-2); font-size: .93rem; }
.source-label {
  font-size: .74rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--ink-3); margin-right: .4rem;
}
.mark {
  display: inline-block; margin-left: .5rem; padding: .05rem .45rem;
  border: 1px solid var(--rule); border-radius: 999px;
  font-size: .74rem; font-weight: 600; white-space: nowrap;
}
.mark--verified { border-color: var(--ok); color: var(--ok); }
.mark--cited { color: var(--ink-3); }
.mark-note { color: var(--accent-2); }

/* Moderation states. Report status and account status share the badge shape so
   a queue row and an account row read the same way at a glance. */
.badge--open { border-color: var(--accent-2); color: var(--accent-2); }
.badge--upheld { border-color: var(--danger); color: var(--danger); }
.badge--dismissed { border-color: var(--ink-3); color: var(--ink-3); }
.badge--pending { border-color: var(--accent-2); color: var(--accent-2); }
.badge--active { border-color: var(--ok); color: var(--ok); }
.badge--suspended { border-color: var(--danger); color: var(--danger); }

.topic-list { list-style: none; display: flex; flex-wrap: wrap; gap: .35rem; margin: .5rem 0; padding: 0; }
.topic {
  font-size: .8rem;
  padding: .12rem .55rem;
  border-radius: 999px;
  background: var(--surface-alt);
  border: 1px solid var(--rule);
  color: var(--ink-2);
  text-decoration: none;
  transition: border-color .15s ease, color .15s ease;
}
.topic:hover { border-color: var(--accent-2); color: var(--accent-2); }

/* --- Detail ---------------------------------------------------------------- */

.byline { color: var(--ink-2); margin: 0 0 .5rem; }
.bookmark-url { word-break: break-all; }

.quote-body {
  margin: 1.25rem 0;
  padding: 1.25rem 1.5rem;
  background: linear-gradient(160deg, var(--surface), var(--surface-alt));
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  box-shadow: var(--shadow);
  font-family: var(--font-read);
  font-style: italic;
  font-weight: 400;
  font-size: var(--read-size);
  line-height: var(--read-leading);
  color: var(--ink);
}
.quote-body footer {
  color: var(--ink-2);
  font-family: var(--font-body);
  font-style: normal;
  font-weight: 600;
  font-size: .85rem;
  letter-spacing: .01em;
  margin-top: .75rem;
}
.talk-body { white-space: normal; }
.detail .prose {
  font-family: var(--font-read);
  font-size: var(--read-size);
  line-height: var(--read-leading);
}
.detail .prose p { margin: 0 0 1em; }
@media (min-width: 90rem) {
  .detail .prose, .quote-body { font-size: 1.25rem; }
}

/* --- Timeline: shared pieces ------------------------------------------------ */
/* The layout itself (strip and stage) is under "Timeline: a full-screen viewer"
   further down; these are the pieces the event page shares. */

.event-date {
  display: block;
  color: var(--accent);
  font-size: .76rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  margin: 0 0 .35rem;
}
.event-location { color: var(--ink-3); font-size: .85rem; margin: 0; font-style: italic; }
.event-quote {
  margin: .6rem 0;
  padding: .7rem 1rem;
  background: var(--surface-alt);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-family: var(--font-head);
  font-style: italic;
  font-size: .96rem;
  color: var(--ink-2);
}

/* --- Dialogs ------------------------------------------------------------------ */
body:has(dialog[open]) { overflow: hidden; }
/* The × close button every dialog shares (action, note and link dialogs). */
.event-modal-close {
  appearance: none;
  flex-shrink: 0;
  border: none;
  background: none;
  padding: .15rem;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--ink-3);
  cursor: pointer;
}
.event-modal-close:hover { color: var(--accent); }

/* --- Stats ----------------------------------------------------------------- */

.stat-row {
  list-style: none;
  margin: 1rem 0 2rem;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: .75rem;
}
.stat a {
  display: block;
  padding: 1.1rem 1rem;
  background: linear-gradient(160deg, var(--surface), var(--surface-alt));
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  text-decoration: none;
  color: inherit;
  box-shadow: var(--shadow);
  transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}
.stat a:hover {
  box-shadow: var(--shadow-hover);
  border-color: color-mix(in srgb, var(--accent-2) 30%, var(--rule));
  transform: translateY(-2px);
}
.stat-n { display: block; font-family: var(--font-head); font-size: 2.1rem; font-weight: 700; line-height: 1.1; color: var(--accent); }
.stat-l { display: block; color: var(--ink-3); font-size: .82rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; margin-top: .3rem; }

/* --- Forms ----------------------------------------------------------------- */

.stacked-form { max-width: 38rem; }
/* The article form: the page widens, and the form takes most of it. */
@media (min-width: 64rem) {
  .stacked-form--wide { max-width: none; width: 85%; }
}
.stacked-form--wide .ql-container { font-size: 1rem; min-height: 22rem; background: var(--surface); }
.stacked-form--wide .ql-editor { min-height: 22rem; font-family: var(--font-read); font-size: 1.05rem; line-height: 1.7; }
/* What you see is what is published: the same block spacing as the page. */
.stacked-form--wide .ql-editor :is(p, h2, h3, h4, blockquote) { margin: 0 0 1em; }
.stacked-form--wide .ql-editor :is(h2, h3, h4) { font-family: var(--font-head); line-height: 1.3; }
.stacked-form--wide .ql-toolbar.ql-snow {
  position: sticky; top: 0; z-index: 2;
  background: var(--surface-alt); border-radius: var(--radius) var(--radius) 0 0;
}
.stacked-form--wide .ql-container.ql-snow { border-radius: 0 0 var(--radius) var(--radius); }
/* Quill's own greys, swapped for the theme tokens so dark mode works. */
.ql-toolbar.ql-snow, .ql-container.ql-snow { border-color: var(--rule); }
.ql-snow .ql-stroke { stroke: var(--ink-2); }
.ql-snow .ql-fill { fill: var(--ink-2); }
.ql-snow .ql-picker { color: var(--ink-2); }
.ql-snow .ql-picker-options { background: var(--surface); border-color: var(--rule) !important; box-shadow: var(--shadow); }
.ql-snow.ql-toolbar :is(button, .ql-picker-label, .ql-picker-item):is(:hover, :focus, .ql-active) { color: var(--accent); }
.ql-snow.ql-toolbar :is(button:hover, button:focus, button.ql-active, .ql-picker-label:hover, .ql-picker-label.ql-active) .ql-stroke { stroke: var(--accent); }
.ql-snow.ql-toolbar :is(button:hover, button:focus, button.ql-active, .ql-picker-label:hover, .ql-picker-label.ql-active) .ql-fill { fill: var(--accent); }
.ql-editor.ql-blank::before { color: var(--ink-3); }
.ql-snow .ql-tooltip { background: var(--surface); color: var(--ink); border-color: var(--rule); box-shadow: var(--shadow); }
.ql-snow .ql-tooltip input[type="text"] { background: var(--surface); color: var(--ink); border-color: var(--rule); }
.ql-snow .ql-picker.ql-size { width: 6.5em; }
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before { content: "Normal"; }
.ql-snow .ql-picker.ql-size [data-value="085"]::before { content: "Small"; }
.ql-snow .ql-picker.ql-size [data-value="125"]::before { content: "Large"; }
.ql-snow .ql-picker.ql-size [data-value="150"]::before { content: "Larger"; }
.ql-snow .ql-picker.ql-size [data-value="200"]::before { content: "Huge"; }
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="085"]::before { font-size: .85em; }
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="125"]::before { font-size: 1.25em; }
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="150"]::before { font-size: 1.5em; }
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="200"]::before { font-size: 2em; }
/* Labels for any size a paste brought in that the picker does not offer. */
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="075"]::before { content: "Smaller"; }
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="115"]::before { content: "Larger"; }
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="175"]::before { content: "Huge"; }
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="250"]::before { content: "Giant"; }
.ql-snow .ql-picker.ql-spaceafter { width: 7.5em; }
.ql-snow .ql-picker.ql-spaceafter .ql-picker-label::before,
.ql-snow .ql-picker.ql-spaceafter .ql-picker-item::before { content: "Spacing"; }
.ql-snow .ql-picker.ql-spaceafter .ql-picker-item:not([data-value])::before { content: "Normal"; }
.ql-snow .ql-picker.ql-spaceafter [data-value="0"]::before { content: "None"; }
.ql-snow .ql-picker.ql-spaceafter [data-value="05"]::before { content: "Tight"; }
.ql-snow .ql-picker.ql-spaceafter [data-value="15"]::before { content: "Roomy"; }
.ql-snow .ql-picker.ql-spaceafter [data-value="2"]::before { content: "Spacious"; }
.field { margin-bottom: 1rem; }
.field label { display: block; font-weight: 600; margin-bottom: .3rem; font-size: .92rem; }

.field input[type="text"],
.field input[type="url"],
.field input[type="email"],
.field input[type="date"],
.field input[type="number"],
.field textarea,
.field select {
  width: 100%;
  padding: .55rem .7rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.field input:focus, .field textarea:focus, .field select:focus {
  border-color: var(--accent-2);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-2) 18%, transparent);
}

.field--error input, .field--error textarea, .field--error select { border-color: var(--danger); }
.field ul.errorlist { color: var(--danger); font-size: .85rem; margin: .25rem 0 0; padding-left: 1rem; }
.help { color: var(--ink-3); font-size: .85rem; margin: .25rem 0 0; }

/* --- Buttons --------------------------------------------------------------- */

.actions { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1.25rem; }
.actions--small { margin-top: .5rem; font-size: .88rem; }

.button {
  display: inline-block;
  padding: .5rem 1rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  text-decoration: none;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  transition: all .15s ease;
}
.button:hover { border-color: var(--accent-2); color: var(--accent-2); transform: translateY(-1px); }
.button--primary {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  border-color: var(--accent);
  color: var(--accent-ink);
  box-shadow: var(--shadow);
}
.button--primary:hover { color: var(--accent-ink); filter: brightness(1.08); box-shadow: var(--shadow-hover); }
.button--danger { border-color: var(--danger); color: var(--danger); }
.button--danger:hover { background: var(--danger); color: #fff; }
/* Sits inline in the header, where the standard button height is too tall. */
.button--compact { padding: .35rem .8rem; font-size: .88rem; }

/* --- Landing page (signed-out home) ---------------------------------------- */
/* The one page with a marketing job to do. It still uses the same tokens and
   card components as the app, so the visitor recognises the place once they
   sign in - the hero is the only element that does not appear elsewhere. */

.hero {
  margin: -1.5rem -1.5rem 0;
  padding: 4rem 1.5rem 3.5rem;
  text-align: center;
  /* Plain gradient first; the color-mix wash on top is an enhancement that
     older browsers drop without losing the panel itself. */
  background: linear-gradient(180deg, var(--surface-alt), var(--ground));
  background:
    radial-gradient(ellipse at 15% 0%, color-mix(in srgb, var(--accent) 16%, transparent), transparent 60%),
    radial-gradient(ellipse at 85% 10%, color-mix(in srgb, var(--accent-2) 14%, transparent), transparent 60%),
    linear-gradient(180deg, color-mix(in srgb, var(--accent) 9%, var(--surface-alt)), var(--ground));
  border-bottom: 1px solid color-mix(in srgb, var(--accent-2) 22%, var(--rule));
}

.hero-eyebrow {
  margin: 0 0 1rem;
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--accent);
}

.hero-title {
  max-width: 20ch;
  margin: 0 auto .9rem;
  font-size: clamp(2rem, 5vw, 3rem);
  line-height: 1.1;
}

.hero-lede {
  max-width: 46ch;
  margin: 0 auto 1.75rem;
  font-size: 1.08rem;
  color: var(--ink-2);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  justify-content: center;
  margin: 0;
}

.hero-note { margin: 1.25rem 0 0; font-size: .85rem; color: var(--ink-3); }

/* Section headings on this page carry a short gold rule, which is the one
   ornament the design uses to mark a top-level break. */
.section-heading {
  position: relative;
  padding-top: 1.1rem;
  margin-bottom: .35rem;
}
.section-heading::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 3rem;
  height: 3px;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
}

.features { margin-top: 2.75rem; }

.feature-grid {
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 1rem;
}
.feature {
  background: var(--surface);
  background: linear-gradient(150deg,
    color-mix(in srgb, var(--accent) 10%, var(--surface)),
    color-mix(in srgb, var(--accent-2) 4%, var(--surface)));
  border: 1px solid color-mix(in srgb, var(--accent-2) 20%, var(--rule));
  border-radius: var(--radius);
  padding: 1.25rem 1.35rem;
  box-shadow: var(--shadow);
}
.feature h3 {
  margin: 0 0 .4rem;
  font-size: 1.05rem;
  font-family: var(--font-body);
  font-weight: 700;
  color: var(--accent);
}
.feature p { margin: 0; color: var(--ink-2); font-size: .93rem; }

.landing-public, .landing-topics { margin-top: 3rem; }

/* The featured item ("Talk of the week") - chosen in the admin, the first
   real content under the hero. Stacked on a phone; the image moves beside
   the text once there is room. */
.landing-featured { margin-top: 2rem; }
.featured-card {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1.5rem 1.25rem;
  background: var(--surface);
  border: 1px solid color-mix(in srgb, var(--accent-2) 30%, var(--rule));
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.featured-card__image { width: 5.5rem; height: 5.5rem; border-radius: 50%; object-fit: cover; flex: none; }
.featured-card__main { min-width: 0; }
.featured-card__eyebrow {
  margin: 0 0 .5rem;
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--accent);
}
.featured-card__title { margin: 0 0 .3rem; font-size: clamp(1.35rem, 4vw, 1.85rem); line-height: 1.2; }
.featured-card__title a { color: var(--ink); text-decoration: none; }
.featured-card__title a:hover { color: var(--accent-2); }
.featured-card__by { margin: 0 0 .75rem; font-style: italic; color: var(--ink-2); }
.featured-card__excerpt { margin: 0 0 .75rem; color: var(--ink-2); max-width: 65ch; }
.featured-card__quote {
  margin: 0 0 .5rem;
  padding: 0 0 0 1rem;
  border-left: 3px solid var(--accent-2);
  font-family: var(--font-read);
  font-style: italic;
  font-size: 1.15rem;
  line-height: 1.6;
  max-width: 65ch;
}
.featured-card__quote a { color: var(--ink); text-decoration: none; }
.featured-card__quote a:hover { color: var(--accent-2); }
.featured-card__note { margin: 0 0 .75rem; font-size: .92rem; color: var(--ink-3); }
.featured-card__actions { margin: .5rem 0 0; }
@media (min-width: 40rem) {
  .featured-card { flex-direction: row; align-items: flex-start; gap: 1.5rem; padding: 2rem; }
  .featured-card__image { width: 7rem; height: 7rem; }
}

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem 1rem;
}
.section-more { font-size: .9rem; font-weight: 600; white-space: nowrap; }


.topic-list--large { gap: .5rem; margin-top: 1.25rem; }
.topic-list--large .topic { font-size: .9rem; padding: .3rem .85rem; }

.landing-cta {
  margin-top: 3.5rem;
  padding: 2.5rem 1.5rem;
  text-align: center;
  background: linear-gradient(160deg, var(--surface), var(--surface-alt));
  background:
    radial-gradient(ellipse at 50% 0%, color-mix(in srgb, var(--accent-2) 16%, transparent), transparent 75%),
    linear-gradient(135deg,
      color-mix(in srgb, var(--accent) 14%, var(--surface)),
      color-mix(in srgb, var(--accent-2) 8%, var(--surface-alt)));
  border: 1px solid color-mix(in srgb, var(--accent-2) 25%, var(--rule));
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.landing-cta h2 { margin-top: 0; }
.landing-cta p { color: var(--ink-2); }

/* --- Pagination & footer --------------------------------------------------- */

.pagination { display: flex; gap: 1rem; align-items: center; margin: 1.5rem 0; }

.site-footer {
  position: relative;
  margin-top: 2rem;
  padding: 2.25rem 1.5rem 1.75rem;
  background: var(--surface);
  border-top: 1px solid var(--rule);
  color: var(--ink-3);
  font-size: .9rem;
  text-align: center;
}
.site-footer::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--accent-2), var(--accent), var(--accent-2));
}
.footer-brand {
  font-family: var(--font-head);
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 .35rem;
}
.footer-verse {
  max-width: 34rem;
  margin: .5rem auto 0;
  font-family: var(--font-head);
  font-style: italic;
  color: var(--ink-2);
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* --- Favourites & collections ---------------------------------------------- */

.filter-row { display: flex; flex-wrap: wrap; gap: .4rem; margin: 1rem 0; }

.chip {
  display: inline-block;
  padding: .25rem .8rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-2);
  text-decoration: none;
  font-size: .88rem;
  font-weight: 600;
  transition: all .15s ease;
}
.chip:hover { border-color: var(--accent-2); color: var(--accent-2); }
.chip--on {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  border-color: var(--accent);
  color: var(--accent-ink);
}
.chip--on:hover { color: var(--accent-ink); filter: brightness(1.08); }

.card .inline-form { display: inline-flex; gap: .4rem; align-items: center; margin-right: .75rem; }
.card .inline-form select { padding: .3rem; border: 1px solid var(--rule); border-radius: var(--radius);
  background: var(--ground); color: var(--ink); font: inherit; }

/* Visible to screen readers only. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* --- Topics ---------------------------------------------------------------- */

/* --- Filter bar ------------------------------------------------------------ */
/* The one search-and-filter strip at the top of every section (templates/
   _filter_bar.html, and the pages with filters of their own). Phone first: the
   search box is a full-width row, the filters a two-column grid beneath it;
   from 40rem they flow into one wrapping row. static/js/livefilter.js updates
   the results as you type, so the submit button is only the no-script path. */
.filter-bar {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .6rem;
  align-items: end;
  margin: 0 0 1rem;
  padding: .75rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
}
.filter-bar__search, .filter-bar__wide { grid-column: 1 / -1; }
.filter-bar__field { display: flex; flex-direction: column; gap: .2rem; min-width: 0; }
.filter-bar__field > label, .filter-bar__label {
  font-size: .72rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-3);
}
.filter-bar input[type="text"],
.filter-bar input[type="search"],
.filter-bar select {
  width: 100%;
  min-width: 0;
  min-height: 2.6rem;
  padding: .5rem .75rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background-color: var(--ground);
  color: var(--ink);
  font: inherit;
  font-size: .95rem;
  transition: border-color .15s ease, box-shadow .15s ease;
}
/* [type] matches the specificity of the rule above, which would otherwise
   reset this padding and sit the icon on top of the placeholder. */
.filter-bar__search input[type="search"] {
  padding-left: 2.3rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%23938579' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='7' cy='7' r='5'/%3E%3Cpath d='m11 11 3.5 3.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: .8rem center;
}
.filter-bar input::placeholder { color: var(--ink-3); }
.filter-bar input:focus, .filter-bar select:focus {
  outline: none;
  border-color: var(--accent-2);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-2) 18%, transparent);
}
.filter-bar__check { display: flex; align-items: center; gap: .4rem; min-height: 2.6rem; font-size: .92rem; }
.filter-bar__actions { display: flex; gap: .75rem; align-items: center; grid-column: 1 / -1; min-height: 2.6rem; }
.filter-bar__actions:empty { display: none; }
.filter-bar__clear { font-size: .88rem; }
.filter-bar__status { margin: -.4rem 0 .9rem; font-size: .88rem; color: var(--ink-2); }
/* Results that are being replaced fade a little, so the update is noticed. */
[data-live-results] { transition: opacity .15s ease; }
[data-live-results][aria-busy="true"] { opacity: .55; }
@media (min-width: 40rem) {
  .filter-bar { display: flex; flex-wrap: wrap; align-items: flex-end; }
  .filter-bar__search { flex: 1 1 18rem; }
  .filter-bar__field { flex: 0 1 11rem; }
  .filter-bar__field--wide { flex: 1 1 14rem; }
  .filter-bar__actions { flex: 0 0 auto; grid-column: auto; }
}
/* Sticks under the top of the screen on long lists, so it is always to hand. */
@media (min-width: 40rem) {
  .filter-bar--sticky { position: sticky; top: .5rem; z-index: 4; box-shadow: var(--shadow); }
}
/* With script running the results follow the boxes; the button is noise. */
.js-live .filter-bar [data-live-submit] { display: none; }

.topic-grid {
  list-style: none;
  margin: 1rem 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: .6rem;
}
.topic-card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: .8rem 1rem;
  display: flex;
  flex-direction: column;
  gap: .2rem;
  box-shadow: var(--shadow);
  transition: box-shadow .18s ease, border-color .18s ease, transform .18s ease;
}
.topic-card:hover {
  box-shadow: var(--shadow-hover);
  border-color: color-mix(in srgb, var(--accent-2) 25%, var(--rule));
  transform: translateY(-1px);
}
.topic-name { font-weight: 700; text-decoration: none; color: var(--ink); }
.topic-name:hover { color: var(--accent-2); }

/* --- Scriptures ------------------------------------------------------------ */

.volume { margin-bottom: 2.25rem; }
.volume h2 {
  padding-bottom: .5rem;
  border-bottom: 1px solid var(--rule);
}
.book-list {
  list-style: none;
  margin: .75rem 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: .3rem .5rem;
}
.book-list a {
  display: block;
  padding: .4rem .6rem;
  border-radius: var(--radius);
  color: var(--ink-2);
  text-decoration: none;
  transition: background .15s ease, color .15s ease;
}
.book-list a:hover { background: var(--surface-alt); color: var(--accent-2); }

.breadcrumbs { margin-bottom: 1rem; font-size: .9rem; color: var(--ink-3); }
.breadcrumbs ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: .25rem; }
.breadcrumbs li + li::before { content: "\203A"; margin-right: .25rem; }
.breadcrumbs a { color: var(--accent-2); text-decoration: none; }
.breadcrumbs a:hover { text-decoration: underline; }

.card-grid {
  list-style: none;
  margin: 1.25rem 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: .9rem;
}
.scripture-card {
  display: flex;
  flex-direction: column;
  gap: .25rem;
  height: 100%;
  padding: 1.1rem 1.25rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  color: var(--ink);
  text-decoration: none;
  transition: box-shadow .15s ease, border-color .15s ease, transform .15s ease;
}
.scripture-card:hover {
  box-shadow: var(--shadow-hover);
  border-color: color-mix(in srgb, var(--accent-2) 25%, var(--rule));
  transform: translateY(-1px);
}
.scripture-card-title { font-size: 1.2rem; font-weight: 700; }
.scripture-card-count { font-size: .85rem; color: var(--ink-3); }
.card-grid--compact .scripture-card { padding: .8rem 1rem; }
.card-grid--compact .scripture-card-title { font-size: 1.05rem; }

.chapter-grid {
  list-style: none;
  margin: 1.25rem 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(3.5rem, 1fr));
  gap: .5rem;
}
.chapter-grid a {
  display: block;
  padding: .7rem 0;
  text-align: center;
  font-weight: 600;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  color: var(--ink);
  text-decoration: none;
}
.chapter-grid a:hover { background: var(--surface-alt); color: var(--accent-2); }

@media (min-width: 40rem) {
  .card-grid { grid-template-columns: repeat(2, 1fr); }
  .card-grid--compact { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 62rem) {
  .card-grid { grid-template-columns: repeat(3, 1fr); }
  .card-grid--compact { grid-template-columns: repeat(4, 1fr); }
}

.verse-list { list-style: none; margin: 1rem 0; padding: 0; max-width: 44rem; }
.verse-list--chapter { max-width: none; }
.verse { padding: .7rem 0; border-bottom: 1px solid var(--rule-soft, var(--rule)); }
.verse p {
  margin: .2rem 0;
  font-family: var(--font-read);
  font-size: 1.125rem;
  line-height: var(--read-leading);
}
.verse-ref { font-weight: 700; font-size: .9rem; text-decoration: none; color: var(--accent-2); font-family: var(--font-body); }
.verse-ref:hover { color: var(--accent); }
.verse-number { color: var(--ink-3); font-size: .8rem; font-weight: 600; font-family: var(--font-body); }
.verse-list--chapter .verse { display: grid; grid-template-columns: 2rem 1fr; gap: .5rem; scroll-margin-top: 1rem; }
/* The verses a scripture link pointed at (?verses=3-4) - scriptures/linkify.py. */
.verse--cited {
  background: color-mix(in srgb, var(--hl-yellow) 55%, transparent);
  box-shadow: inset 3px 0 0 var(--accent);
  padding-left: .5rem; padding-right: .5rem;
  border-radius: 0 var(--radius) var(--radius) 0;
}
/* The "[" scripture finder beneath a text box - static/js/scripture-insert.js.
   In the page flow rather than floating, so the text being written stays in view. */
.scripture-insert {
  display: flex; flex-direction: column; gap: .4rem;
  margin: .4rem 0 .8rem; padding: .7rem .8rem;
  border: 1px solid var(--rule); border-radius: var(--radius); background: var(--surface-alt);
}
.scripture-insert[hidden] { display: none; }
.scripture-insert__label { font-size: .85rem; font-weight: 600; }
.scripture-insert input[type="text"] { width: 100%; min-width: 0; }
.scripture-insert .combobox__list { position: static; }
.scripture-insert__preview { margin: 0; font-size: .9rem; }
.scripture-insert__actions { display: flex; gap: .5rem; }
.ql-snow .ql-toolbar button.ql-scripture, .ql-toolbar.ql-snow button.ql-scripture {
  width: auto; padding: 3px 6px; font-weight: 700; color: var(--ink-2);
}
/* The chapter a citation link opens - static/js/scripture-modal.js.
   Phone: a near-full-screen sheet. Wider: a large centred reading panel. */
.scripture-modal {
  width: 100vw; max-width: 100vw; height: 92dvh; max-height: 92dvh;
  margin: auto auto 0; padding: 0; border: none;
  border-radius: var(--radius) var(--radius) 0 0;
  background: var(--surface); color: var(--ink);
  box-shadow: var(--shadow-hover);
}
.scripture-modal[open] { display: flex; flex-direction: column; }
.scripture-modal::backdrop { background: rgba(43, 22, 16, .55); }
@media (prefers-color-scheme: dark) {
  .scripture-modal::backdrop { background: rgba(0, 0, 0, .65); }
}
.scripture-modal__head {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem;
  padding: .9rem 1rem .6rem; border-bottom: 1px solid var(--rule);
}
.scripture-modal__head .muted { margin: 0; }
.scripture-modal__title { margin: 0; font-size: 1.25rem; }
.scripture-modal__sub { margin: .1rem 0 0; font-size: .85rem; }
.scripture-modal__head .event-modal-close { font-size: 1.8rem; padding: .1rem .35rem; }
.scripture-modal__body { flex: 1; overflow-y: auto; overscroll-behavior: contain; padding: 0 1rem; }
.scripture-modal__body .verse-list { margin: .25rem 0 1rem; }
.scripture-modal__foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
  padding: .6rem 1rem calc(.6rem + env(safe-area-inset-bottom)); border-top: 1px solid var(--rule);
}
.scripture-modal__full { margin-left: auto; font-size: .9rem; }
@media (min-width: 40rem) {
  .scripture-modal {
    width: min(92vw, 52rem); height: 85vh; max-height: 85vh;
    margin: auto; border-radius: var(--radius);
  }
  .scripture-modal__head, .scripture-modal__foot { padding-left: 1.5rem; padding-right: 1.5rem; }
  .scripture-modal__body { padding: 0 1.5rem; }
}
/* A citation in written text, linked to the reader. */
a.scripture-ref { text-decoration-style: dotted; text-underline-offset: .18em; }
a.scripture-ref:hover { text-decoration-style: solid; }

@media (max-width: 40rem) {
  .quote-body { padding: 1rem; }
  .detail .prose, .verse p, .quote-body { font-size: 1.0625rem; }
}

.report-link { font-size: .88rem; color: var(--ink-3); align-self: center; margin-left: .5rem; }

/* --- allauth pages (login, signup, password reset, MFA, sessions) ---------- */
/* allauth's element templates (allauth/elements/*.html) emit bare, unclassed
   form / p / label / input / button tags - there is no .field wrapper to hang
   the usual form rules off, so this styles the tags directly, scoped to
   .auth-page so it cannot leak onto forms elsewhere in the site. */

.auth-page {
  max-width: 26rem;
  margin: 2rem auto;
  padding: 2rem 2.25rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.auth-page h1 { margin-bottom: 1rem; }
.auth-page p { margin: .6rem 0; }
.auth-page a { color: var(--accent-2); }
.auth-page a:hover { color: var(--accent); }

.auth-page form { display: flex; flex-direction: column; gap: 1rem; margin: 1.25rem 0; }
.auth-page form p { margin: 0; display: flex; flex-direction: column; gap: .3rem; }

.auth-page label { font-weight: 600; font-size: .92rem; }

.auth-page input:not([type="checkbox"]):not([type="radio"]),
.auth-page textarea,
.auth-page select {
  width: 100%;
  padding: .5rem .6rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
}

.auth-page input[type="checkbox"],
.auth-page input[type="radio"] { margin-right: .4rem; }

/* Field errors: allauth prints {{ attrs.errors }} as raw markup immediately
   before the <p> that wraps the field. */
.auth-page form ul { color: var(--danger); font-size: .85rem; margin: 0; padding-left: 1.1rem; }

/* Buttons and button-styled links share one look; allauth renders a submit
   as <button> and a same-purpose action (e.g. "Resend code") as <a>. */
.auth-page button,
.auth-page form a[href] {
  display: inline-block;
  padding: .55rem 1.1rem;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: var(--accent-ink);
  font: inherit;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  align-self: flex-start;
  transition: filter .15s ease, box-shadow .15s ease;
}
.auth-page button:hover,
.auth-page form a[href]:hover {
  filter: brightness(1.08);
  box-shadow: var(--shadow-hover);
}

/* "Forgot your password?" - a quiet link under the Sign In button, not a
   second button (templates/account/login.html). */
.auth-page .auth-forgot { margin: -.25rem 0 0; font-size: .92rem; }

.auth-page hr { border: none; border-top: 1px solid var(--rule); margin: 1.5rem 0; }

/* --- Highlighting (plan §09) ------------------------------------------------ */
/* static/js/highlights.js measures character offsets against this element's
   plain text content, so nothing here may add or remove characters - only
   `white-space: pre-wrap` stands in for the `linebreaks` filter used
   elsewhere, reproducing line breaks visually without restructuring the DOM. */

.highlightable { white-space: pre-wrap; }
/* highlights.js does the selecting itself - mouse drag or double-click,
   long-press on touch, then the handles - so the browser never makes a
   selection of its own and never shows its toolbar, callout or Edge's
   selection "mini menu" over ours. */
.highlightable--own-select {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  cursor: text;
}
/* Set for a single synchronous measurement (highlights.js caretAtPoint):
   some engines will not place a caret in user-select:none text, and the
   handles and menu must not be what the hit-test lands on - otherwise a drag
   only registers once the pointer escapes the handle, and jumps by words. */
.hl-measuring .highlightable { -webkit-user-select: text !important; user-select: text !important; }
.hl-measuring .highlight-handle,
.hl-measuring .highlight-menu,
.hl-measuring .highlight-note-marker { pointer-events: none !important; }
/* The selection being composed, before it is saved - painted with the CSS
   Custom Highlight API, so it adds no elements and cannot move any offsets. */
::highlight(hl-pending) { background-color: var(--accent-tint); color: inherit; }
/* Article bodies are sanitised HTML whose text content (newlines between
   blocks included) is what highlights anchor to; the block elements supply
   the visual breaks, so ordinary wrapping applies. */
.highlightable--rich { white-space: normal; }
.highlightable--rich p { margin: 0 0 1em; }
/* A scripture chapter as one block (highlights/_block.html): verses keep the
   reading layout they have everywhere else. */
.highlightable--rich .verse p { margin: .2rem 0; }
/* Each block owns its menu, handles and note markers - see highlights.js. */
.highlight-block { position: relative; }
.highlight-menu__error {
  margin: 0 0 .5rem;
  color: var(--danger);
  font-size: .875rem;
}
.highlightable--rich blockquote { margin: 0 0 1em; padding-left: 1em; border-left: 3px solid var(--border, #ccc); }
.highlightable--rich ul, .highlightable--rich ol { margin: 0 0 1em; padding-left: 1.5rem; }
.highlightable--rich h2,
.highlightable--rich h3,
.highlightable--rich h4 { font-family: var(--font-head); line-height: 1.3; margin: 1.4em 0 .5em; }
.highlightable--rich h2 { font-size: 1.5em; }
.highlightable--rich h3 { font-size: 1.25em; }
.highlightable--rich h4 { font-size: 1.08em; }
.highlightable--rich > :first-child { margin-top: 0; }

/* --- Rich formatting vocabulary ---------------------------------------------
   Kept by study/richtext.py (RICH_CLASSES) and produced by the editor and the
   document importers. Classes, never inline style: the CSP ignores style="".
   Sizes are relative, so a document's normal text is the reading size. */
:is(.highlightable--rich, .ql-editor) .fs-075 { font-size: .75em; }
:is(.highlightable--rich, .ql-editor) .fs-085 { font-size: .85em; }
:is(.highlightable--rich, .ql-editor) .fs-115 { font-size: 1.15em; }
:is(.highlightable--rich, .ql-editor) .fs-125 { font-size: 1.25em; }
:is(.highlightable--rich, .ql-editor) .fs-150 { font-size: 1.5em; line-height: 1.35; }
:is(.highlightable--rich, .ql-editor) .fs-175 { font-size: 1.75em; line-height: 1.3; }
:is(.highlightable--rich, .ql-editor) .fs-200 { font-size: 2em; line-height: 1.25; }
:is(.highlightable--rich, .ql-editor) .fs-250 { font-size: 2.5em; line-height: 1.2; }
:is(.highlightable--rich, .ql-editor) .sa-0 { margin-bottom: 0; }
:is(.highlightable--rich, .ql-editor) .sa-05 { margin-bottom: .5em; }
:is(.highlightable--rich, .ql-editor) .sa-15 { margin-bottom: 1.5em; }
:is(.highlightable--rich, .ql-editor) .sa-2 { margin-bottom: 2em; }
:is(.highlightable--rich, .ql-editor) .sb-05 { margin-top: .5em; }
:is(.highlightable--rich, .ql-editor) .sb-1 { margin-top: 1em; }
:is(.highlightable--rich, .ql-editor) .sb-15 { margin-top: 1.5em; }
:is(.highlightable--rich, .ql-editor) .sb-2 { margin-top: 2em; }
:is(.highlightable--rich, .ql-editor) .lh-150 { line-height: 2.1; }
:is(.highlightable--rich, .ql-editor) .lh-200 { line-height: 2.6; }
:is(.highlightable--rich, .ql-editor) .ti-1 { text-indent: 1.5em; }
.highlightable--rich .ql-align-center { text-align: center; }
.highlightable--rich .ql-align-right { text-align: right; }
.highlightable--rich .ql-align-justify { text-align: justify; }
.highlightable--rich .ql-indent-1 { padding-left: 2em; }
.highlightable--rich .ql-indent-2 { padding-left: 4em; }
.highlightable--rich .ql-indent-3 { padding-left: 6em; }
.highlightable--rich .ql-indent-4 { padding-left: 8em; }
.highlightable--rich .ql-indent-5 { padding-left: 10em; }
.highlightable--rich .ql-indent-6 { padding-left: 12em; }
.highlightable--rich .ql-indent-7 { padding-left: 14em; }
.highlightable--rich .ql-indent-8 { padding-left: 16em; }
@media (max-width: 40rem) {
  /* Deep indents would leave a word per line on a phone. */
  .highlightable--rich [class*="ql-indent-"] { padding-left: 1.25em; }
  .highlightable--rich .fs-200, .highlightable--rich .fs-250 { font-size: 1.6em; }
}

.highlight-mark {
  border-radius: 2px;
  padding: 0 .1em;
  cursor: pointer;
  color: var(--hl-ink);
}
.highlight-mark--yellow { background: var(--hl-yellow); }
.highlight-mark--green { background: var(--hl-green); }
.highlight-mark--blue { background: var(--hl-blue); }
.highlight-mark--pink { background: var(--hl-pink); }
.highlight-mark--orange { background: var(--hl-orange); }

/* Shown only while a highlight's menu is open, one at each end of its span -
   drag either to grow or shrink the highlight. `position: fixed` and
   `touch-action: none` for the same reason as .highlight-menu: JS places
   these in viewport coordinates and needs the browser not to turn a drag
   into a page scroll. */
.highlight-handle {
  position: fixed;
  z-index: 41;
  width: 1rem;
  height: 1rem;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  border: 2px solid var(--surface);
  background: var(--accent);
  box-shadow: var(--shadow);
  cursor: ew-resize;
  touch-action: none;
}
/* A bigger invisible grab area round the dot, so a fingertip can find it. */
.highlight-handle::before {
  content: "";
  position: absolute;
  inset: -.9rem;
}
@media (pointer: coarse) {
  .highlight-handle { width: 1.35rem; height: 1.35rem; }
}
.highlight-handle[hidden] { display: none; }

/* The one popup for both creating a highlight and editing one. Mobile-first:
   the base layout is a bottom sheet across the full width of a phone, which
   cannot run off any edge; from 40rem up static/js/highlights.js floats it
   beside the selection instead and clamps it to the visible viewport. Either
   way it scrolls inside itself, with Save pinned at the bottom, so the
   actions can never end up off-screen. */
.highlight-menu {
  position: fixed;
  z-index: 40;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: 70dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: .6rem;
  padding: .9rem 1rem 0;
  border: 1px solid var(--rule);
  border-bottom: none;
  border-radius: var(--radius) var(--radius) 0 0;
  background: var(--surface);
  box-shadow: var(--shadow-hover);
  transition: background-color .2s, border-color .2s, box-shadow .2s;
}
@media (min-width: 40rem) {
  .highlight-menu {
    right: auto;
    bottom: auto;
    width: 18rem;
    max-height: calc(100dvh - 1rem);
    padding: .75rem .75rem 0;
    border-bottom: 1px solid var(--rule);
    border-radius: var(--radius);
  }
}
/* Author rules otherwise beat the UA [hidden] rule on equal specificity -
   this is what actually keeps the menu hidden until it is opened. */
.highlight-menu[hidden] { display: none; }

/* Peek: the menu stays open but fades almost away and lets touches through,
   so the text and the handles beneath can be seen and dragged. Only the peek
   button stays solid and tappable, to bring the menu back. The children fade
   rather than the menu itself, since a child cannot undo a parent's opacity. */
.highlight-menu > *,
.highlight-menu__actions > * { transition: opacity .2s; }
.highlight-menu--peek {
  pointer-events: none;
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  overflow: hidden;
}
.highlight-menu--peek > :not(.highlight-menu__actions),
.highlight-menu--peek .highlight-menu__actions > :not(.highlight-menu__peek) { opacity: .12; }
.highlight-menu--peek .highlight-menu__actions { background: transparent; border-top-color: transparent; }
.highlight-menu--peek .highlight-menu__peek { pointer-events: auto; }

.highlight-menu__title {
  margin: 0;
  font-family: var(--font-head);
  font-size: 1rem;
  color: var(--ink);
}

.highlight-menu__section { display: flex; flex-direction: column; gap: .3rem; }

.highlight-menu__label { font-size: .8rem; color: var(--ink-2); }

.highlight-menu__swatches { display: flex; flex-wrap: wrap; gap: .4rem; }

.highlight-menu__note {
  width: 100%;
  padding: .4rem .5rem;
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) - 2px);
  background: var(--ground);
  color: var(--ink);
  font-family: inherit;
  font-size: .9rem;
  line-height: 1.4;
  resize: vertical;
}

/* Gospel topics in the highlight menu: the shared combobox, sized to the menu. */
.highlight-menu .combobox input[type="text"] {
  padding: .45rem .6rem;
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) - 2px);
  background: var(--ground);
  color: var(--ink);
  font: inherit;
  font-size: .9rem;
}
.highlight-menu .combobox input[type="text"]::placeholder { color: var(--ink-3); }
.highlight-menu .combobox input[type="text"]:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.highlight-menu .combobox__list { max-height: 11rem; }
/* iOS zooms the whole page into any field under 16px when it is focused,
   which would throw the menu around - so touch screens get exactly 16px. */
@media (pointer: coarse) {
  .highlight-menu__note,
  .highlight-menu .combobox input[type="text"] { font-size: 16px; }
}

/* The margin symbol beside a highlight that carries a note. */
.highlight-note-marker {
  position: absolute;
  z-index: 1;
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: 50%;
  background: var(--surface);
  color: var(--accent);
  font-size: .9rem;
  line-height: 1;
  cursor: pointer;
  box-shadow: var(--shadow);
}
.highlight-note-marker:hover { background: var(--accent-tint); }
@media (max-width: 40rem) {
  .highlight-note-marker { width: 1.25rem; height: 1.25rem; font-size: .75rem; }
}
/* Keep the dot small in the margin but give a fingertip something to hit. */
.highlight-note-marker::before { content: ""; position: absolute; inset: -.45rem; }

/* Pinned to the bottom of the (scrolling) menu, so Save is always in reach;
   one row, with the peek button pushed to the right-hand end. */
.highlight-menu__actions {
  position: sticky;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: .5rem;
  margin: 0 -1rem;
  padding: .6rem 1rem calc(.6rem + env(safe-area-inset-bottom));
  border-top: 1px solid var(--rule);
  background: var(--surface);
}
@media (min-width: 40rem) {
  .highlight-menu__actions { margin: 0 -.75rem; padding: .6rem .75rem; }
}
.highlight-menu__peek {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  margin-left: auto;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: 50%;
  background: var(--surface);
  color: var(--ink-2);
  box-shadow: var(--shadow);
  cursor: pointer;
}
.highlight-menu__peek:hover { color: var(--accent); }
.highlight-menu__peek:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.highlight-menu__peek[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--surface);
}

/* The note a ✎ margin symbol opens: just the note text and an X. The page
   stays visible behind it - the backdrop is clear, not dimmed (it is still
   there to catch the click that closes the dialog) - and a border and shadow
   set the popup apart instead. */
.note-dialog {
  width: min(92vw, 26rem);
  max-height: 70dvh;
  margin: auto;
  padding: .9rem 2.4rem .9rem 1rem;
  overflow-y: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-hover);
}
.note-dialog::backdrop { background: transparent; }
.note-dialog__close { position: absolute; top: .45rem; right: .5rem; font-size: 1.25rem; }
.note-dialog__text { margin: 0; font-size: .9rem; line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; }

.highlight-swatch {
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  border: 1px solid var(--rule);
  padding: 0;
  cursor: pointer;
}
.highlight-swatch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.highlight-swatch[aria-pressed="true"] {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.highlight-swatch--yellow { background: var(--hl-yellow); }
.highlight-swatch--green { background: var(--hl-green); }
.highlight-swatch--blue { background: var(--hl-blue); }
.highlight-swatch--pink { background: var(--hl-pink); }
.highlight-swatch--orange { background: var(--hl-orange); }

.highlight-orphan-notice { font-size: .85rem; color: var(--ink-3); margin-top: .5rem; }


/* --- Content links ---------------------------------------------------------- */
/* The panel under an item's detail page, and the picker dialog that fills it.
   Private to the viewer, so it is styled as part of their own workspace rather
   than as part of the item: set apart from the article above it, quieter than
   the content, and never shown to anyone who is not signed in. */

.links-panel {
  margin: 1.5rem 0 0;
  padding: 1rem 1.1rem 1.1rem;
  border: 1px dashed var(--rule);
  border-radius: var(--radius);
  background: var(--surface-alt);
}
.links-panel__title { margin: 0; font-size: 1rem; font-family: var(--font-head); }
.links-panel .empty { padding: .5rem 0; font-size: .9rem; }

.link-list { list-style: none; margin: .75rem 0; padding: 0; display: grid; gap: .5rem; }

.link-row {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  align-items: baseline;
  padding: .5rem .65rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
}
/* Matches .card--tombstone: an end that has been withdrawn is dimmed and
   dashed, not removed - the note about the connection is still the viewer's. */
.link-row--tombstone { opacity: .75; border-style: dashed; }

.link-row__kind {
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--ink-3);
}
.link-row__target { font-weight: 700; color: var(--ink); text-decoration: none; }
a.link-row__target:hover { color: var(--accent-2); }
.link-row__note { flex-basis: 100%; margin: .2rem 0 0; font-size: .9rem; color: var(--ink-2); }
.link-row__pair { display: flex; flex-wrap: wrap; gap: .5rem; align-items: baseline; margin: 0; }

.link-picker {
  width: min(92vw, 32rem);
  margin: auto;
  padding: 0;
  border: none;
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-hover);
}
.link-picker::backdrop { background: rgba(43, 22, 16, .55); }
@media (prefers-color-scheme: dark) {
  .link-picker::backdrop { background: rgba(0, 0, 0, .65); }
}
.link-picker__inner {
  display: flex;
  flex-direction: column;
  gap: .45rem;
  padding: 1.35rem 1.4rem 1.25rem;
  max-height: 85vh;
  overflow-y: auto;
}
.link-picker__title { margin: 0 0 .3rem; font-family: var(--font-head); font-size: 1.05rem; }
.link-picker__results {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 14rem;
  overflow-y: auto;
}
.link-picker__result {
  display: block;
  width: 100%;
  text-align: left;
  padding: .45rem .55rem;
  border: none;
  border-bottom: 1px solid var(--rule);
  background: none;
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}
.link-picker__result:hover { background: var(--accent-tint); }
.link-picker__result:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.link-picker__empty { padding: .45rem .55rem; color: var(--ink-3); font-size: .9rem; }
.link-picker__chosen { margin: .2rem 0; font-size: .9rem; color: var(--accent-2); }
.link-picker__actions { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .4rem; }



/* --- Notes ------------------------------------------------------------------ */
/* The panel under an item, and the /notes/ page. Styled like the links panel:
   part of the viewer's own workspace rather than part of the item, because that
   is exactly what it is - nobody else can see any of it. */

.notes-panel {
  margin: 1.5rem 0 0;
  padding: 1rem 1.1rem 1.1rem;
  border: 1px dashed var(--rule);
  border-radius: var(--radius);
  background: var(--surface-alt);
}
.notes-panel__title { margin: 0; font-size: 1rem; font-family: var(--font-head); }

.note-list { list-style: none; margin: .75rem 0; padding: 0; display: grid; gap: .6rem; }
.note-row {
  padding: .6rem .7rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
}
.note-row__kind { margin: 0 0 .3rem; font-size: .78rem; text-transform: uppercase;
  letter-spacing: .04em; color: var(--ink-3); }

/* The passage a note was written about, tinted with the highlight's own colour
   so the note and the mark in the text are recognisably the same thing. */
.note-excerpt {
  margin: 0 0 .4rem;
  padding: .4rem .65rem;
  border-left: 3px solid var(--rule);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-family: var(--font-head);
  font-style: italic;
  font-size: .93rem;
  color: var(--ink-2);
  background: var(--surface-alt);
}
.note-excerpt--yellow { border-left-color: var(--hl-yellow); }
.note-excerpt--green { border-left-color: var(--hl-green); }
.note-excerpt--blue { border-left-color: var(--hl-blue); }
.note-excerpt--pink { border-left-color: var(--hl-pink); }
.note-excerpt--orange { border-left-color: var(--hl-orange); }

.note-body { margin: .2rem 0; color: var(--ink); white-space: pre-wrap; }
.note-card .note-body { color: var(--ink); }

/* Editing a favourite's note, inline on the favourites list. */
.note-form { display: flex; gap: .5rem; align-items: flex-start; margin-top: .5rem; }
.note-form textarea {
  flex: 1 1 auto;
  padding: .4rem .5rem;
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) - 2px);
  background: var(--ground);
  color: var(--ink);
  font: inherit;
  resize: vertical;
}

/* --- Search results -------------------------------------------------------- */
/* The snippet under a hit, shown to signed-in viewers only. ts_headline picks
   the fragments; study/views.py escapes the text and wraps each match in
   <mark>, so the styling here is the only place the highlight colour is set. */
.result-snippet { margin: .25rem 0; color: var(--ink-2); }
.result-snippet mark {
  background: var(--hl-yellow);
  color: var(--ink);
  padding: 0 .1em;
  border-radius: 2px;
}

/* The verified-only checkbox and the scope radios share the filtered search
   form's row. The radios are visually a chip group but submit with the rest
   of the form, so a scope choice keeps every other filter. */
.check-inline { display: inline-flex; align-items: center; gap: .35rem; font-size: .88rem; color: var(--ink-2); }
.scope-chips { display: inline-flex; flex-wrap: wrap; gap: .4rem; }
.scope-chips .chip { cursor: pointer; }
.scope-chips .chip:focus-within {
  outline: 2px solid var(--accent-2);
  outline-offset: 2px;
}

/* --- Import Center --------------------------------------------------------- */
/* The hub (study/import_hub.html) and the wizard (study/import_form.html,
   static/js/importer.js). Mobile first: one column, then the guide moves
   beside the wizard on a wide screen. */

.form-tip {
  margin: .5rem 0 1.25rem; padding: .65rem .9rem;
  border-radius: var(--radius); background: var(--accent-tint); color: var(--ink); font-size: .92rem;
}
.crumbs { margin: 0 0 .5rem; font-size: .9rem; }
.crumbs a { color: var(--ink-2); text-decoration: none; }
.crumbs a:hover { color: var(--accent-2); }

.import-lede { color: var(--ink-2); max-width: 40rem; margin: 1rem 0 1.5rem; }
.import-group { margin: 0 0 2.25rem; }
.import-group__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem 1rem; margin-bottom: .75rem; }
.import-group__head h2 { margin: 0; font-size: 1.3rem; }
.import-group__head p { margin: 0; }

.import-cards {
  list-style: none; margin: 0 0 .75rem; padding: 0;
  display: grid; gap: .75rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
}
.import-card {
  display: flex; flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}
.import-card:hover, .import-card:focus-within {
  box-shadow: var(--shadow-hover);
  border-color: color-mix(in srgb, var(--accent-2) 35%, var(--rule));
  transform: translateY(-2px);
}
.import-card__link {
  display: flex; align-items: flex-start; gap: .85rem;
  padding: 1rem 1.1rem .6rem; flex: 1;
  color: inherit; text-decoration: none; border-radius: var(--radius) var(--radius) 0 0;
}
.import-card__link:focus-visible { outline: 2px solid var(--accent-2); outline-offset: -3px; }
.import-card__icon {
  flex: none; display: grid; place-items: center;
  width: 2.75rem; height: 2.75rem; border-radius: 50%;
  background: var(--accent-tint); color: var(--accent);
}
.import-card__text { display: grid; gap: .2rem; min-width: 0; flex: 1; }
.import-card__title { font-size: 1.02rem; }
.import-card__blurb { color: var(--ink-2); font-size: .9rem; }
.import-card__go { color: var(--ink-3); font-size: 1.2rem; transition: transform .18s ease, color .18s ease; }
.import-card:hover .import-card__go { color: var(--accent-2); transform: translateX(3px); }
.import-card__examples {
  margin: 0; padding: .55rem 1.1rem .7rem 4.7rem;
  font-size: .82rem; color: var(--ink-3);
}

/* The four steps. */
.stepper {
  list-style: none; margin: 1.25rem 0 1.25rem; padding: 0;
  display: flex; gap: .25rem; max-width: 40rem;
}
.stepper__step {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: .3rem;
  position: relative; color: var(--ink-3); font-size: .8rem; font-weight: 600; text-align: center;
}
/* The line joining each dot to the one before it. */
.stepper__step + .stepper__step::before {
  content: ""; position: absolute; top: .85rem; height: 2px;
  left: calc(-50% + 1.15rem); right: calc(50% + 1.15rem);
  background: var(--rule); transition: background .25s ease;
}
.stepper__dot {
  position: relative; z-index: 1;
  display: grid; place-items: center; width: 1.8rem; height: 1.8rem; border-radius: 50%;
  border: 2px solid var(--rule); background: var(--surface); font-size: .82rem;
  transition: background .25s ease, border-color .25s ease, color .25s ease;
}
.stepper__step.is-current { color: var(--ink); }
.stepper__step.is-current .stepper__dot { border-color: var(--accent); color: var(--accent); box-shadow: 0 0 0 4px var(--accent-tint); }
.stepper__step.is-done { color: var(--ink-2); }
.stepper__step.is-done .stepper__dot { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.stepper__step.is-done + .stepper__step::before,
.stepper__step.is-done + .stepper__step.is-done::before { background: var(--accent); }
@media (max-width: 30rem) {
  .stepper__name { font-size: .72rem; }
}

.importer-layout { display: grid; gap: 1.25rem; align-items: start; }
@media (min-width: 64rem) {
  .importer-layout { grid-template-columns: minmax(0, 1.6fr) minmax(18rem, 1fr); }
  .importer-guide { position: sticky; top: 1rem; }
}
/* Past the upload step the column guide has done its job; the check, the
   pictures and the result get the full width. importer.js sets this. */
.importer-layout.importer-layout--focused { grid-template-columns: minmax(0, 1fr); }
.importer-layout--focused .importer-guide { display: none; }
.importer-main { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; min-width: 0; }
.importer-main > [hidden] { display: none; }
.importer.card, .importer-panel.card { padding: 1.25rem; }
.importer .field { margin-bottom: 1rem; }
.importer__actions { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem 1rem; margin: 1rem 0 0; }
.importer-panel:focus { outline: none; }
.importer-panel__title { margin: 0 0 .35rem; font-size: 1.3rem; }
.importer-panel__title::before { content: "\2713"; color: var(--ok); margin-right: .5rem; }
.importer-panel--bad .importer-panel__title::before { content: "!"; color: var(--danger); font-weight: 800; }
.importer-panel__summary { color: var(--ink-2); margin: 0 0 1rem; }
.importer-panel h3 { font-size: .95rem; margin: 1.25rem 0 .25rem; }
.importer-warning {
  padding: .6rem .8rem; border-radius: var(--radius);
  background: var(--accent-tint); color: var(--ink); font-size: .9rem;
}
.importer-suggest { display: flex; flex-wrap: wrap; gap: .5rem; margin: 0; }
.importer-suggest[hidden] { display: none; }
.importer-notes {
  margin: 0 0 1rem; padding: .6rem .8rem .6rem 1.9rem; border-radius: var(--radius);
  background: var(--accent-tint); font-size: .9rem; display: grid; gap: .25rem;
}
.importer-notes[hidden], .importer-offer[hidden], .importer-confirm[hidden] { display: none; }
.importer-offer {
  margin: 0 0 1rem; padding: 1rem; border: 2px solid var(--accent); border-radius: var(--radius);
}
.importer-offer h3 { margin-top: 0; }
.importer-offer .field { margin: .75rem 0 0; }
.importer-offer input[type="text"] { width: 100%; }
.importer-confirm {
  display: flex; gap: .6rem; align-items: flex-start; margin: 1rem 0 0;
  padding: .75rem .8rem; border-radius: var(--radius); background: var(--accent-tint);
  font-weight: 600; cursor: pointer;
}
.importer-confirm input { margin-top: .2rem; flex: none; width: 1.25rem; height: 1.25rem; }
.recent-imports { display: grid; gap: .5rem; padding: 0; margin: 0; list-style: none; }
.recent-imports__row {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .5rem 1rem;
  padding: .75rem 1rem;
}
.recent-imports__row form { margin: 0; }
.importer-guide { display: grid; gap: 1rem; }
.importer-guide .card { padding: 1.1rem 1.2rem; }
.importer-guide h2 { font-size: 1.05rem; margin: 0 0 .5rem; font-family: var(--font-body); }
.importer-guide h3 { font-size: .9rem; margin: 1rem 0 .4rem; }
.download-row { display: flex; flex-wrap: wrap; gap: .5rem; margin: .75rem 0 0; }
.import-guide summary { cursor: pointer; list-style: none; display: flex; justify-content: space-between; align-items: center; }
.import-guide summary::-webkit-details-marker { display: none; }
.import-guide summary::after { content: "\25BE"; color: var(--ink-3); transition: transform .2s ease; }
.import-guide:not([open]) summary::after { transform: rotate(-90deg); }
.import-guide summary h2 { margin: 0; }
.column-list { margin: .75rem 0; display: grid; gap: .1rem; }
.column-list__row { padding: .45rem 0; border-bottom: 1px solid var(--rule); }
.column-list__row:last-child { border-bottom: 0; }
.column-list dt { font-weight: 600; }
.column-list dt code { font-family: var(--font-mono); font-size: .86rem; color: var(--accent); }
.column-list dd { margin: .15rem 0 0; color: var(--ink-2); font-size: .86rem; }
.kept-list, .lost-list, .tip-list { margin: 0; padding: 0; list-style: none; display: grid; gap: .35rem; font-size: .92rem; }
.kept-list li, .lost-list li { padding-left: 1.5rem; position: relative; }
.kept-list li::before { content: "\2713"; position: absolute; left: 0; color: var(--ok); font-weight: 700; }
.lost-list li { color: var(--ink-2); }
.lost-list li::before { content: "\2013"; position: absolute; left: .2rem; color: var(--ink-3); }

/* The file picker - templates/_dropzone.html, static/js/dropzone.js. The
   real input is stretched invisibly over the zone, so it works unscripted. */
.dropzone {
  position: relative;
  display: grid; place-items: center; gap: .4rem;
  min-height: 11rem; padding: 1.5rem 1rem;
  border: 2px dashed color-mix(in srgb, var(--accent) 35%, var(--rule));
  border-radius: calc(var(--radius) * 1.5);
  background: color-mix(in srgb, var(--accent-tint) 35%, var(--surface));
  text-align: center;
  transition: border-color .18s ease, background .18s ease, transform .18s ease;
}
.dropzone__input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.dropzone:hover, .dropzone--over {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent-tint) 70%, var(--surface));
}
.dropzone--over { transform: scale(1.01); }
.dropzone:has(.dropzone__input:focus-visible) { outline: 3px solid var(--accent-2); outline-offset: 3px; }
.dropzone__empty, .dropzone__chosen { display: grid; justify-items: center; gap: .35rem; pointer-events: none; }
.dropzone__empty[hidden], .dropzone__chosen[hidden] { display: none; }
.dropzone__icon { color: var(--accent); }
.dropzone__title { font-size: 1.05rem; }
.dropzone__title strong { color: var(--accent); }
.dropzone__name { font-weight: 700; word-break: break-all; }
.dropzone__size { color: var(--ink-3); font-size: .85rem; }
.dropzone__change { color: var(--accent-2); font-size: .85rem; text-decoration: underline; }
.dropzone__hint { margin: 0; color: var(--ink-3); font-size: .85rem; pointer-events: none; }
.dropzone--chosen { border-style: solid; }

/* A labelled progress bar - templates/_progress.html. */
.progress { display: grid; gap: .5rem; }
.progress__head { display: flex; justify-content: space-between; gap: 1rem; font-weight: 600; }
.progress__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.progress__pct { font-variant-numeric: tabular-nums; color: var(--accent); }
.progress__track {
  position: relative; height: .8rem; overflow: hidden;
  border-radius: 999px; background: var(--surface-alt);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .08);
}
.progress__bar {
  height: 100%; width: 0; border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transition: width .35s ease;
}
.progress__track--indeterminate .progress__bar {
  width: 40%;
  animation: progress-slide 1.3s ease-in-out infinite;
}
@keyframes progress-slide {
  from { transform: translateX(-100%); }
  to { transform: translateX(250%); }
}
@media (prefers-reduced-motion: reduce) {
  .progress__bar { transition: none; }
  .progress__track--indeterminate .progress__bar { animation: none; width: 100%; opacity: .45; }
  .dropzone, .import-card, .stepper__dot { transition: none; }
}
.progress__detail { margin: 0; color: var(--ink-2); font-size: .9rem; min-height: 1.3em; }

.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; border: 1px solid var(--rule); border-radius: var(--radius); }
.table-scroll .import-errors { margin: 0; }
.sample-table { border-collapse: collapse; width: 100%; font-size: .85rem; }
.sample-table th, .sample-table td {
  padding: .45rem .6rem; text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--rule); max-width: 16rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sample-table th { background: var(--surface-alt); font-family: var(--font-mono); font-weight: 600; }
.sample-table th.is-unknown { color: var(--ink-3); text-decoration: line-through; }
.sample-table tr:last-child td { border-bottom: 0; }

.importer-done { text-align: center; }
.importer-done h2 { margin: .5rem 0 0; }
.importer-done .stat-row { max-width: 30rem; margin: 1.25rem auto .5rem; }
.importer-done .stat {
  padding: .9rem; border: 1px solid var(--rule); border-radius: var(--radius);
  background: linear-gradient(160deg, var(--surface), var(--surface-alt));
}
.importer-done .importer__actions { justify-content: center; }
.importer-done__tick { color: var(--ok); }
.importer-done__tick path { stroke-dasharray: 40; stroke-dashoffset: 0; animation: tick-draw .5s .15s ease-out backwards; }
@keyframes tick-draw { from { stroke-dashoffset: 40; } }
@media (prefers-reduced-motion: reduce) { .importer-done__tick path { animation: none; } }

.import-columns { margin-top: 2rem; }
.pill-list { list-style: none; display: flex; flex-wrap: wrap; gap: .4rem; margin: .6rem 0; padding: 0; }
.pill {
  padding: .2rem .6rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--surface-alt);
  font-size: .82rem;
  font-family: var(--font-mono);
  color: var(--ink-2);
}

.form-error {
  padding: .7rem .9rem;
  border-left: 3px solid var(--danger);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  color: var(--ink);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.form-success {
  padding: .7rem .9rem;
  border-left: 3px solid var(--ok);
  background: color-mix(in srgb, var(--ok) 12%, transparent);
  color: var(--ink);
  border-radius: 0 var(--radius) var(--radius) 0;
}

.import-errors { width: 100%; border-collapse: collapse; margin: 1rem 0; }
.import-errors th,
.import-errors td { text-align: left; padding: .5rem .6rem; border-bottom: 1px solid var(--rule); vertical-align: top; }
.import-errors td ul { margin: 0; padding-left: 1rem; }

/* --- Honeypot ------------------------------------------------------------- */
/* The footer's trap link. display:none keeps it out of layout and out of the
   accessibility tree; aria-hidden and tabindex=-1 on the element itself are
   belt and braces. A link-harvesting bot reads the href from the HTML source
   and never sees any of this - see config/middleware.py. */
.trap { display: none !important; }

/* --- Content protection (plan L) ---------------------------------------------- */
/* Applied to the body text whenever the viewer is not its owner, signed in or
   not. A light deterrent - user-select and print only. It must not touch selection for the
   owner or for the highlight menu, which manage their own. */
.protected {
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
@media print {
  .protected { visibility: hidden; }
}

/* --- Permission matrix ----------------------------------------------------- */
/* Roles across, permissions down. Scrolls sideways inside its own box on a
   phone rather than pushing the whole page wider. */

.matrix-wrap { overflow-x: auto; margin: 1rem 0; }
.matrix {
  border-collapse: collapse;
  min-width: 100%;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
.matrix th, .matrix td {
  padding: .55rem .75rem;
  border-bottom: 1px solid var(--rule);
  text-align: center;
}
.matrix thead th {
  background: var(--surface-alt);
  font-size: .82rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--ink-3);
}
.matrix tbody th { text-align: left; font-weight: 600; }
.matrix tbody tr:last-child th, .matrix tbody tr:last-child td { border-bottom: 0; }
.matrix-cell { display: inline-flex; padding: .25rem; cursor: pointer; }
.matrix-cell input { width: 1.1rem; height: 1.1rem; accent-color: var(--accent); }

/* An account closed for good - quieter than suspended, which may yet be undone. */
.badge--removed { border-color: var(--ink-3); color: var(--ink-3); }

/* --- Theology Explorer ---------------------------------------------------- */
/* One semantic link fills each catalogue card. This keeps the full card easy
   to activate by mouse, touch, keyboard, and assistive technology without
   nesting interactive controls. */
.card--link { padding: 0; }
.card-link { display: block; height: 100%; padding: 1.1rem 1.25rem; color: inherit; text-decoration: none; }
.card-link:hover h2, .card-link:focus-visible h2 { color: var(--accent-2); }
.card-link:focus-visible { outline: 2px solid var(--accent-2); outline-offset: -3px; border-radius: var(--radius); }

/* A card remains one large detail link; its separate checkbox is deliberately
   outside that link so the two controls remain valid and keyboard accessible. */
.card--selectable { position: relative; }
.card--selectable .card-link { padding-left: 3.75rem; }
.compare-check { position: absolute; z-index: 1; top: 1rem; left: 1rem; display: grid; place-items: center; width: 1.7rem; height: 1.7rem; cursor: pointer; }
.compare-check input { width: 1.2rem; height: 1.2rem; margin: 0; accent-color: var(--accent); cursor: inherit; }
.compare-check input:disabled { cursor: not-allowed; opacity: .45; }

/* The selection tray stays visible while catalogue filters replace the result
   list. It deliberately contains the full names selected on earlier pages. */
.theology-compare-tray { position: fixed; z-index: 5; bottom: .75rem; left: 50%; display: flex; width: min(calc(100% - 1.5rem), 72rem); align-items: center; justify-content: space-between; gap: 1rem; margin: 0; padding: .8rem 1rem; transform: translateX(-50%); border: 1px solid var(--accent-2); border-radius: var(--radius); background: var(--surface); box-shadow: 0 8px 24px color-mix(in srgb, var(--ink) 16%, transparent); }
.theology-compare-tray[hidden] { display: none; }
.theology-compare-items { display: flex; flex-wrap: wrap; gap: .35rem .65rem; margin: .35rem 0 0; padding: 0; list-style: none; font-size: .88rem; }
.theology-compare-items li { display: inline-flex; align-items: center; gap: .25rem; }
.theology-compare-remove { border: 0; padding: .05rem; color: var(--accent-2); background: transparent; font: inherit; font-size: .78rem; text-decoration: underline; cursor: pointer; }
.theology-compare-remove:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 2px; }
.theology-compare-actions { display: flex; flex: 0 0 auto; gap: .5rem; align-items: center; }

.comparison-scroll { overflow-x: auto; margin: 1.25rem 0; border: 1px solid var(--rule); border-radius: var(--radius); background: var(--surface); }
.comparison-table { width: 100%; min-width: 60rem; border-collapse: collapse; }
.comparison-table th, .comparison-table td { padding: .8rem 1rem; border-bottom: 1px solid var(--rule); vertical-align: top; text-align: left; }
.comparison-table th { width: 11rem; background: var(--surface-alt); font-size: .82rem; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-2); }
.comparison-table td { min-width: 13rem; white-space: pre-line; }
.comparison-table tbody tr:last-child th, .comparison-table tbody tr:last-child td { border-bottom: 0; }

@media (max-width: 40rem) {
  .theology-compare-tray { align-items: stretch; flex-direction: column; }
  .theology-compare-actions { justify-content: flex-end; }
}

/* The searched word inside a scripture search hit (scriptures/templatetags/highlight.py). */
.verse mark {
  background: var(--hl-yellow);
  color: var(--ink);
  padding: 0 .1em;
  border-radius: 2px;
}

/* Section headings on the global search page: one per part of the site. */
.search-section { margin: 1.5rem 0 .5rem; font-size: 1.15rem; }
.card h3 { margin: 0 0 .25rem; font-size: 1.05rem; }


/* ===========================================================================
   Site-wide layout pass: one structure for every item, card and page.
   =========================================================================== */

/* --- Page head ------------------------------------------------------------- */
/* Eyebrow, title, actions on the right; wraps under the title on a phone. */
.page-head__main { min-width: 0; }
.page-head__main h1 { margin: 0; }
.page-head__eyebrow,
.detail-head__eyebrow,
.card__eyebrow {
  display: flex;
  align-items: center;
  gap: .4rem;
  margin: 0 0 .3rem;
  font-size: .74rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
}
.page-lede { margin: 1rem 0; color: var(--ink-2); }
.breadcrumb { margin: 0 0 .9rem; font-size: .9rem; }
.breadcrumb a { text-decoration: none; color: var(--ink-3); font-weight: 600; }
.breadcrumb a:hover { color: var(--accent-2); }

/* --- The ⋮ item menu ------------------------------------------------------- */
/* <details>/<summary>: opens with no script; static/js/menus.js adds
   one-at-a-time, outside-click and Escape. Sits top right of whatever holds
   it - a card, a detail header, a timeline's stage. */
.item-menu { position: relative; z-index: 3; flex: none; }
.card > .item-menu {
  position: absolute;
  top: .45rem;
  right: .45rem;
}
.item-menu__toggle {
  list-style: none;
  display: inline-grid;
  place-items: center;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 50%;
  color: var(--ink-3);
  font-size: 1.35rem;
  line-height: 1;
  cursor: pointer;
  user-select: none;
  transition: background-color .15s ease, color .15s ease;
}
.item-menu__toggle::-webkit-details-marker { display: none; }
.item-menu__toggle::marker { content: ""; }
.item-menu__toggle:hover,
.item-menu[open] > .item-menu__toggle { background: var(--accent-tint); color: var(--accent); }
/* A card with its menu open rises above its neighbours, so the panel is
   drawn over the next card in the grid rather than underneath it. */
.card:has(> .item-menu[open]) { z-index: 20; }
.item-menu__toggle:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 2px; }
.item-menu__panel {
  position: absolute;
  top: calc(100% + .25rem);
  right: 0;
  min-width: 14rem;
  padding: .35rem;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-hover);
}
.item-menu--right .item-menu__panel { right: auto; left: 0; }
.item-menu--up .item-menu__panel { top: auto; bottom: calc(100% + .25rem); }
.item-menu__form { margin: 0; display: contents; }
.item-menu__item {
  display: block;
  width: 100%;
  padding: .5rem .7rem;
  border: 0;
  border-radius: calc(var(--radius) - 2px);
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: .92rem;
  font-weight: 500;
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}
.item-menu__item[hidden] { display: none; }
.item-menu__item:hover,
.item-menu__item:focus-visible { background: var(--accent-tint); color: var(--ink); outline: none; }
.item-menu__item--danger { color: var(--danger); }
.item-menu__item--danger:hover { background: color-mix(in srgb, var(--danger) 12%, var(--surface)); color: var(--danger); }
.item-menu__rule { border: 0; border-top: 1px solid var(--rule); margin: .3rem .2rem; }

/* --- Clickable cards --------------------------------------------------------- */
/* The title link stretches over the whole card, so anywhere on it opens the
   item; topic pills, forms and the ⋮ menu sit above that layer and keep
   working on their own. */
.card--clickable { position: relative; padding-right: 3rem; }
.card__link { color: inherit; text-decoration: none; }
.card__link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: var(--radius);
}
.card__link:focus-visible { outline: none; }
.card__link:focus-visible::after { outline: 2px solid var(--accent-2); outline-offset: -2px; }
.card--clickable .topic-list,
.card--clickable .card__control,
.card--clickable form,
.card--clickable a:not(.card__link) { position: relative; z-index: 2; }
.card--clickable:hover h2 .card__link { color: var(--accent-2); }
.card.has-open-menu { z-index: 10; }
.card__eyebrow { color: var(--ink-3); }
.card__url { font-size: .85rem; color: var(--ink-3); word-break: break-all; }

/* The mixed-item card (study/_result_card.html): type, title, who gave it, a
   short preview, and the date pinned to the bottom so a row of cards lines up
   whatever the length of each title. Long titles - an imported quote is often
   titled with its first sentence - clamp rather than stretch the row. */
.result-card { display: flex; flex-direction: column; min-width: 0; }
.result-card__title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
  line-height: 1.35;
}
.card .result-card__by { margin: 0 0 .35rem; font-size: .92rem; font-style: italic; color: var(--accent); }
.card .result-card__excerpt {
  font-size: .92rem;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}
.result-card .topic-list { margin: .4rem 0 0; }
.result-card .item-meta { margin: auto 0 0; padding-top: .6rem; font-size: .85rem; }

/* A general card grid: one column on a phone, two on a tablet, three on a
   desktop, four on a wide screen. */
.card-grid { grid-template-columns: 1fr; gap: 1rem; }
@media (min-width: 40rem) { .card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 64rem) { .card-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 90rem) { .card-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.card-grid > .card { display: flex; flex-direction: column; min-width: 0; }
.card-grid > .card .item-meta { margin-top: auto; padding-top: .5rem; }

/* --- Detail pages ------------------------------------------------------------ */
.detail-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: 1rem;
  margin-bottom: 1.5rem;
  border-bottom: 1px solid var(--rule);
}
.detail-head__text { min-width: 0; }
.detail-head h1 { font-size: clamp(1.6rem, 3vw, 2.3rem); margin: 0 0 .35rem; }
.detail-head .item-meta { margin: .4rem 0 0; }
.detail-head .item-menu__toggle { border: 1px solid var(--rule); background: var(--surface); }

/* Text beside Connections from 64rem up; stacked below that. */
.detail-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2rem; }
@media (min-width: 64rem) {
  .detail-layout { grid-template-columns: minmax(0, 1fr) 19rem; gap: 3rem; }
}
@media (min-width: 90rem) {
  .detail-layout { grid-template-columns: minmax(0, 1fr) 22rem; }
}
.detail-body > :first-child { margin-top: 0; }
.detail-image {
  display: block;
  max-width: min(100%, 36rem);
  height: auto;
  margin: 0 0 1.5rem;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.detail-description { color: var(--ink-2); border-top: 1px solid var(--rule); padding-top: 1rem; margin-top: 1.5rem; }
.quote-body--feature { margin-top: 0; font-size: clamp(1.2rem, 1.6vw, 1.45rem); padding: 1.75rem 2rem; }
@media (max-width: 40rem) { .quote-body--feature { padding: 1.1rem 1.2rem; } }

/* --- Connections ------------------------------------------------------------- */
.connections { display: flex; flex-direction: column; gap: 1.25rem; min-width: 0; }
@media (min-width: 64rem) {
  .connections { position: sticky; top: 1rem; align-self: start; max-height: calc(100vh - 2rem); overflow-y: auto; padding-right: .25rem; }
}
.connections__group { margin: 0; }
.connections__title {
  margin: 0 0 .5rem;
  font-family: var(--font-body);
  font-size: .76rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.connections__empty { margin: 0; font-size: .9rem; color: var(--ink-3); }
.connections__list { list-style: none; margin: 0; padding: 0; display: grid; gap: .45rem; font-size: .93rem; }
.connections__list li { display: flex; flex-wrap: wrap; gap: .25rem .45rem; align-items: baseline; }
.connections__list a { font-weight: 600; text-decoration: none; }
.connections__list a:hover { text-decoration: underline; }
.connections .topic-list { margin: 0 0 .5rem; }
.connections__personal {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  padding: 1rem;
  border: 1px dashed var(--rule);
  border-radius: var(--radius);
  background: var(--surface-alt);
}
.connections__private-label { margin: 0; font-size: .8rem; font-weight: 600; color: var(--ink-3); }
.connections__signin { margin: 0; font-size: .92rem; color: var(--ink-2); }
.connections .my-topics { display: block; margin: 0; }
.connections .my-topics .combobox-form { display: flex; gap: .4rem; }
.connections .my-topics .combobox-form input[type="text"] { min-width: 0; }
/* Notes and links are panels of their own elsewhere; inside Connections they
   are just two more groups. */
.connections .notes-panel,
.connections .links-panel { margin: 0; padding: 0; border: 0; background: none; }
.connections .notes-panel__title,
.connections .links-panel__title {
  margin: 0 0 .5rem;
  font-family: var(--font-body);
  font-size: .76rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.connections .notes-panel > .help:first-of-type,
.connections .links-panel > .help:first-of-type { display: none; }
.connections .note-body { font-family: var(--font-read); font-size: .95rem; }

/* --- Shared action dialogs (static/js/item-actions.js) ----------------------- */
.action-dialog {
  width: min(92vw, 30rem);
  margin: auto;
  padding: 0;
  border: none;
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-hover);
}
.action-dialog::backdrop { background: rgba(43, 22, 16, .55); }
@media (prefers-color-scheme: dark) {
  .action-dialog::backdrop { background: rgba(0, 0, 0, .65); }
}
.action-dialog__inner { display: flex; flex-direction: column; gap: .6rem; padding: 1.35rem 1.4rem 1.25rem; max-height: 85vh; overflow-y: auto; }
.action-dialog__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; }
.action-dialog__title { margin: 0; font-size: 1.15rem; }
.action-dialog__subject { margin: .2rem 0 0; color: var(--ink-2); font-size: .92rem; }
.action-dialog__label { font-weight: 600; font-size: .9rem; margin-top: .4rem; }
.action-dialog__input {
  width: 100%;
  padding: .5rem .7rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
}
.action-dialog__actions { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .4rem; }
.action-dialog .combobox-field { position: relative; display: block; }

.check-list { list-style: none; margin: .25rem 0; padding: 0; display: grid; gap: .3rem; max-height: 16rem; overflow-y: auto; }
.check-list__row {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .45rem .6rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
}
.check-list__row:hover { border-color: var(--accent-2); }
.check-list__row input { width: 1.05rem; height: 1.05rem; accent-color: var(--accent); }
.check-list__row .badge { margin-left: auto; }

/* --- Timeline: a full-screen viewer --------------------------------------------- */
/* One layout at every width, phone first. The page fills the screen and never
   scrolls: header and toolbar at the top, the strip fixed along the bottom,
   and between them the stage - a sideways carousel, one slide per event, each
   slide scrolling inside itself, so a long event never moves anything else.
   The strip holds small event cards standing on an axis, each on a stem down
   to its jewel; each list item paints its own stretch of the axis, so the line
   runs the full scroll width. static/js/timeline.js keeps the two in step. The
   owner's insertion points are plain rings on the axis that grow a "+" on
   hover or focus. */
body.page--timeline {
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  /* clip, not hidden: nothing - not even the jump to an #event anchor - can
     scroll the frame itself. */
  overflow: clip;
}
body.page--timeline > :not(main) { flex: none; }
@media print {
  body.page--timeline { height: auto; display: block; overflow: visible; }
}
.layout--timeline {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 110rem;
  padding: 0 .75rem;
  overflow: clip;
}
@media (min-width: 40rem) {
  .layout--timeline { padding: 0 1.25rem; }
}

/* The one bar across the top. The title takes what is left and ellipses. */
.timeline-bar {
  flex: none;
  display: flex;
  align-items: center;
  gap: .45rem;
  min-height: 3rem;
  padding: .35rem 0;
  border-bottom: 1px solid var(--rule);
  margin: 0 0 .5rem;
}
.timeline-bar__back {
  flex: none;
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  text-decoration: none;
  font-weight: 700;
  color: var(--ink-3);
}
.timeline-bar__back:hover { color: var(--accent-2); background: var(--surface-alt); }
.timeline-bar__title {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: 1.05rem;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.timeline-bar__count { flex: none; font-size: .8rem; display: none; }
.timeline-bar__wide { display: none; }
.timeline-bar > .button, .timeline-bar > details { flex: none; }
@media (min-width: 40rem) {
  .timeline-bar__title { font-size: 1.25rem; }
  .timeline-bar__count { display: inline; }
}
@media (min-width: 48rem) {
  .timeline-bar__wide { display: inline-flex; }
}
/* Swiping covers it on a phone; the strip's arrow buttons appear from 40rem up. */
.timeline-toolbar__scroll { display: none; gap: .3rem; flex: none; }
@media (min-width: 40rem) {
  .timeline-toolbar__scroll { display: inline-flex; }
}
.timeline-toolbar__scroll[hidden] { display: none; }

/* "About": the meta line, description and source, in a drop-down panel. */
.timeline-about { position: relative; }
.timeline-about > summary { list-style: none; font-style: italic; font-family: var(--font-head); min-width: 2rem; justify-content: center; }
.timeline-about > summary::-webkit-details-marker { display: none; }
.timeline-about__body {
  position: absolute;
  right: 0;
  top: calc(100% + .4rem);
  z-index: 30;
  width: min(30rem, calc(100vw - 1.5rem));
  max-height: 60vh;
  overflow-y: auto;
  padding: .75rem 1rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-hover);
}
.timeline-about .item-meta { margin-top: 0; }
.timeline-intro { margin: 0 0 .5rem; }

.timeline-wrap { flex: 1; min-height: 0; display: flex; flex-direction: column; margin: 0; }

/* The stage: a carousel filling whatever height is left. */
.timeline-viewer { position: relative; flex: 1; min-height: 0; display: flex; }
.timeline-stage {
  position: relative;
  flex: 1;
  min-width: 0;
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.timeline-stage::-webkit-scrollbar { display: none; }
.timeline-stage__event {
  flex: 0 0 100%;
  min-width: 0;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  scroll-snap-align: center;
  scroll-snap-stop: always;
  /* The card fills the slide from the bar down to the strip, however short
     the event; a longer one grows past it and the slide scrolls. */
  display: flex;
  flex-direction: column;
  padding: .5rem .25rem .75rem;
}
.timeline-stage__card {
  position: relative;
  flex: 1 0 auto;
  width: 100%;
  max-width: 48rem;
  margin: 0 auto;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.timeline-stage__card::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 1;
  height: 3px;
  border-radius: var(--radius) var(--radius) 0 0;
  background: linear-gradient(90deg, var(--accent-2), var(--accent), var(--accent-2));
}
.timeline-stage__image {
  display: block;
  width: 100%;
  max-height: 35vh;
  object-fit: cover;
  border-radius: var(--radius) var(--radius) 0 0;
}
.timeline-stage__body { padding: 1.15rem 1rem 1rem; }
.timeline-stage__head { display: flex; align-items: flex-start; justify-content: space-between; gap: .75rem; }
.timeline-stage__head h2 { margin: 0 0 .3rem; font-size: 1.3rem; }
.timeline-stage__body > .prose { margin-top: .8rem; }
@media (min-width: 40rem) {
  .timeline-stage__body { padding: 1.5rem 1.5rem 1.25rem; }
}

/* ‹ › step buttons: over the card's edges on a phone, beside it when wide. */
.timeline-step {
  position: absolute;
  top: 50%;
  z-index: 4;
  width: 2.5rem;
  height: 2.5rem;
  display: grid;
  place-items: center;
  padding: 0 0 .2rem;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  box-shadow: var(--shadow);
  color: var(--ink);
  font-size: 1.7rem;
  line-height: 1;
  cursor: pointer;
  transform: translateY(-50%);
  transition: opacity .15s ease, border-color .15s ease;
}
.timeline-step[hidden] { display: none; }
.timeline-step:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.timeline-step:disabled { opacity: 0; pointer-events: none; }
.timeline-step--prev { left: -.35rem; }
.timeline-step--next { right: -.35rem; }
@media (min-width: 64rem) {
  .timeline-step--prev { left: calc(50% - 24rem - 3.5rem); }
  .timeline-step--next { right: calc(50% - 24rem - 3.5rem); }
}

/* The strip: a fixed band along the bottom. */
.timeline {
  position: relative;
  flex: none;
  display: flex;
  align-items: flex-end;
  height: 11rem;
  list-style: none;
  margin: 0 -.75rem;
  padding: .6rem .75rem 0;
  border-top: 1px solid var(--rule);
  background: var(--ground);
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scroll-padding: 0 1rem;
  scrollbar-width: thin;
}
@media (min-width: 40rem) {
  .timeline { margin: 0 -1.25rem; padding: .6rem 1.25rem 0; scroll-padding: 0 1.25rem; }
}
.timeline:focus-visible { outline: 2px solid var(--accent-2); outline-offset: -2px; }
.timeline-event,
.timeline-gap {
  position: relative;
  background: linear-gradient(90deg, var(--rule), var(--rule)) no-repeat;
  background-size: 100% 2px;
  background-position: 0 calc(100% - 2rem);
}
.timeline-event {
  flex: 0 0 min(62vw, 14rem);
  padding: 0 .35rem 3.6rem;
  scroll-snap-align: center;
}
@media (min-width: 40rem) {
  .timeline-event { flex-basis: clamp(14rem, 18vw, 18rem); scroll-snap-align: start; }
}
/* The jewel on the axis... */
.timeline-event::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 2rem;
  width: .75rem;
  height: .75rem;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, var(--accent-2), var(--accent));
  box-shadow: 0 0 0 3px var(--ground), 0 1px 3px rgba(43, 22, 16, .25);
  transform: translate(-50%, 50%);
  transition: transform .18s ease;
}
/* ...and the stem from the card down to it. */
.timeline-event::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 2.45rem;
  width: 2px;
  height: 1.15rem;
  background: color-mix(in srgb, var(--accent-2) 45%, var(--rule));
  transform: translateX(-50%);
}
.timeline-event:has(.is-selected)::before { transform: translate(-50%, 50%) scale(1.5); }
.timeline-event:has(.is-selected)::after { background: var(--accent); }
.timeline-event__axis {
  position: absolute;
  left: 0;
  right: 0;
  bottom: .15rem;
  margin: 0;
  text-align: center;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .06em;
  color: var(--ink-3);
}

/* A strip card: a fixed-size box, small type, clickable as a whole. */
.timeline-card {
  position: relative;
  display: block;
  height: 6.6rem;
  overflow: hidden;
  cursor: pointer;
  background: linear-gradient(160deg, var(--surface), var(--surface-alt));
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: .55rem .7rem;
  box-shadow: var(--shadow);
  transition: box-shadow .18s ease, border-color .18s ease;
}
.timeline-card.card--clickable { padding-right: .7rem; }
.timeline-card:hover {
  box-shadow: var(--shadow-hover);
  border-color: color-mix(in srgb, var(--accent-2) 30%, var(--rule));
}
.timeline-card.is-selected {
  border-color: var(--accent);
  background: linear-gradient(160deg, var(--accent-tint), var(--surface));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent), var(--shadow);
}
.timeline-card .card__link::after { border-radius: var(--radius); }
.timeline-card .event-date { margin: 0 0 .15rem; font-size: .7rem; }
.timeline-card h3 {
  margin: 0;
  font-size: .82rem;
  line-height: 1.25;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
.timeline-card__excerpt {
  margin: .25rem 0 0;
  font-size: .72rem;
  line-height: 1.35;
  color: var(--ink-3);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
.timeline-card-thumb {
  float: left;
  width: 2.75rem;
  height: 2.75rem;
  object-fit: cover;
  border-radius: calc(var(--radius) - 2px);
  margin: 0 .5rem .2rem 0;
}

/* Insertion points between events (owner only). */
.timeline-gap { flex: 0 0 2rem; align-self: stretch; }
.timeline-node {
  position: absolute;
  left: 50%;
  bottom: 2rem;
  transform: translate(-50%, 50%);
  border-radius: 50%;
}
.timeline-node--add {
  width: 1.6rem;
  height: 1.6rem;
  background: var(--ground);
  border: 2px solid var(--rule);
  transition: transform .15s ease, border-color .15s ease, background .15s ease;
}
.timeline-node--add::before,
.timeline-node--add::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  background: var(--accent);
  opacity: 0;
  border-radius: 1px;
  transition: opacity .15s ease;
}
.timeline-node--add::before { width: 55%; height: 2px; transform: translate(-50%, -50%); }
.timeline-node--add::after { width: 2px; height: 55%; transform: translate(-50%, -50%); }
.timeline-node--add:hover,
.timeline-node--add:focus-visible {
  transform: translate(-50%, 50%) scale(1.3);
  border-color: var(--accent);
  background: var(--accent-tint);
}
.timeline-node--add:hover::before, .timeline-node--add:hover::after,
.timeline-node--add:focus-visible::before, .timeline-node--add:focus-visible::after {
  opacity: 1;
}

/* On its side (a phone or tablet in landscape) the stage is wide and short:
   an event with a picture sits beside it rather than under it. */
@media (orientation: landscape) and (min-width: 40rem) {
  .timeline-stage__card { max-width: 62rem; }
  .timeline-stage__card:has(> .timeline-stage__image) {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    align-items: start;
  }
  .timeline-stage__card > .timeline-stage__image {
    position: sticky;
    top: 0;
    height: auto;
    max-height: 60vh;
    border-radius: var(--radius) 0 0 var(--radius);
  }
  .timeline-step--prev { left: max(-.35rem, calc(50% - 31rem - 3.5rem)); }
  .timeline-step--next { right: max(-.35rem, calc(50% - 31rem - 3.5rem)); }
}
/* A short screen - a phone on its side - gives the stage every line it can:
   a slimmer strip, cards with date and title only. */
@media (max-height: 34rem) {
  .timeline-bar { min-height: 2.6rem; padding: .2rem 0; margin-bottom: .35rem; }
  .timeline-stage__body { padding: .9rem 1rem .75rem; }
  .timeline-stage__head h2 { font-size: 1.15rem; }
  .timeline { height: 7.7rem; padding-top: .4rem; }
  .timeline-event { padding-bottom: 2.9rem; }
  .timeline-event,
  .timeline-gap { background-position: 0 calc(100% - 1.55rem); }
  .timeline-event::before,
  .timeline-node { bottom: 1.55rem; }
  .timeline-event::after { bottom: 1.95rem; height: .95rem; }
  .timeline-event__axis { bottom: .05rem; font-size: .65rem; }
  .timeline-card { height: 4.4rem; padding: .45rem .6rem; }
  .timeline-card__excerpt { display: none; }
  .timeline-card-thumb { width: 2.2rem; height: 2.2rem; }
}

/* --- Timelines list: tiles with a miniature timeline -------------------------- */
/* The real page in small: a little box per event on a stem down to its jewel
   on the axis. Six on a phone, up to twelve from 40rem up. */
.timeline-tile h2 { font-family: var(--font-head); font-size: 1.2rem; }
.timeline-tile__mini {
  position: relative;
  display: flex;
  justify-content: space-between;
  gap: .3rem;
  margin: .5rem 0 .75rem;
}
.timeline-tile__mini::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: .25rem;
  height: 2px;
  background: linear-gradient(90deg, var(--accent-2), var(--rule));
  transform: translateY(50%);
}
.timeline-tile__event {
  position: relative;
  flex: 1 1 0;
  max-width: 2.6rem;
  height: 1.6rem;
  margin-bottom: 1.1rem;
  background: linear-gradient(160deg, var(--surface), var(--surface-alt));
  border: 1px solid var(--rule);
  border-radius: 3px;
  box-shadow: 0 1px 2px rgba(43, 22, 16, .12);
}
.timeline-tile__event::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 100%;
  width: 2px;
  height: .85rem;
  background: color-mix(in srgb, var(--accent-2) 45%, var(--rule));
  transform: translateX(-50%);
}
.timeline-tile__event::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -.85rem;
  width: .5rem;
  height: .5rem;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, var(--accent-2), var(--accent));
  box-shadow: 0 0 0 2px var(--surface);
  transform: translate(-50%, 50%);
}
.timeline-tile__event:nth-child(n+7) { display: none; }
@media (min-width: 40rem) {
  .timeline-tile__event:nth-child(n+7) { display: block; }
}

/* --- Notes page -------------------------------------------------------------- */
/* The note is the page: large reading type first, then - quieter - the passage
   it was written about, then everything it connects to. */
.note-stream { list-style: none; margin: 1.25rem 0; padding: 0; display: grid; gap: 1.1rem; max-width: 52rem; }
.note-card { position: relative; padding: 1.4rem 3.25rem 1.2rem 1.5rem; }
.note-card__text {
  margin: 0 0 .9rem;
  font-family: var(--font-read);
  font-size: var(--read-size);
  line-height: var(--read-leading);
  color: var(--ink);
  white-space: pre-wrap;
}
.note-card .note-excerpt { font-size: .88rem; margin: 0 0 .9rem; }
.note-card__source { margin: 0 0 .5rem; font-size: .92rem; color: var(--ink-2); }
.note-card__source a { font-weight: 700; }
.note-card__links { display: flex; flex-wrap: wrap; gap: .35rem .5rem; align-items: center; margin: .35rem 0 0; font-size: .85rem; }
.note-card__label { font-size: .72rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3); }
/* Hidden until the menu's "Edit note" links to it - :target, no script. */
.note-edit { display: none; flex-direction: column; gap: .5rem; margin: 0 0 1rem; position: relative; z-index: 2; }
.note-edit:target { display: flex; }
.note-card:has(.note-edit:target) .note-card__text { display: none; }
.note-edit textarea {
  width: 100%;
  min-height: 8rem;
  padding: .6rem .7rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-read);
  font-size: 1rem;
  line-height: 1.6;
  resize: vertical;
}

@media print {
  .item-menu, .connections__personal, .timeline-toolbar { display: none; }
}

/* ===========================================================================
   Dashboard (templates/study/dashboard.html). Phone first: one column, a
   side rail from 64rem. Tokens only, so light and dark both follow.
   =========================================================================== */

.dash-icon { flex: none; vertical-align: -.2em; }

/* --- Hero: greeting and "pick up where you left off" ------------------------ */
.dash-hero {
  position: relative;
  overflow: hidden;
  display: grid;
  gap: 1.25rem;
  padding: 1.5rem 1.25rem;
  margin-bottom: 1.25rem;
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) * 2);
  background:
    radial-gradient(120% 140% at 100% 0%, color-mix(in srgb, var(--accent-tint) 85%, transparent), transparent 60%),
    linear-gradient(160deg, var(--surface), var(--surface-alt));
  box-shadow: var(--shadow);
}
.dash-hero::after {
  /* A soft accent bar along the top edge. */
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 4px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
}
.dash-hero h1 { font-size: clamp(1.7rem, 5vw, 2.5rem); margin: 0; }
.dash-hero__lede {
  display: flex;
  align-items: center;
  gap: .4rem;
  margin: .4rem 0 0;
  color: var(--ink-2);
}
.dash-hero__lede .dash-icon { color: var(--accent); }
.dash-hero__actions { display: flex; flex-wrap: wrap; gap: .5rem; align-self: end; }

.dash-continue { display: grid; gap: .75rem; }
.dash-continue__card {
  display: flex;
  align-items: center;
  gap: .9rem;
  min-width: 0;
  padding: .9rem 1rem;
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) * 1.5);
  background: var(--surface);
  color: inherit;
  text-decoration: none;
  box-shadow: var(--shadow);
  transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}
.dash-continue__card:hover {
  color: inherit;
  border-color: color-mix(in srgb, var(--accent-2) 40%, var(--rule));
  box-shadow: var(--shadow-hover);
  transform: translateY(-2px);
}
.dash-continue__card--primary {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  border-color: transparent;
  color: var(--accent-ink);
}
.dash-continue__card--primary:hover { color: var(--accent-ink); }
.dash-continue__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  background: var(--accent-tint);
  color: var(--accent);
}
.dash-continue__card--primary .dash-continue__icon {
  background: color-mix(in srgb, var(--accent-ink) 18%, transparent);
  color: var(--accent-ink);
}
.dash-continue__icon .dash-icon { width: 1.4rem; height: 1.4rem; }
.dash-continue__body { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.dash-continue__eyebrow {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  opacity: .8;
}
.dash-continue__title {
  font-family: var(--font-head);
  font-size: 1.2rem;
  font-weight: 700;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-continue__when { font-size: .8rem; opacity: .75; }
.dash-continue__go { flex: none; opacity: .7; transition: transform .18s ease; }
.dash-continue__card:hover .dash-continue__go { transform: translateX(3px); opacity: 1; }

@media (min-width: 40rem) {
  .dash-hero { padding: 2rem; }
  .dash-continue { grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); }
}
@media (min-width: 64rem) {
  .dash-hero { grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); align-items: center; }
}

/* --- Stat tiles ----------------------------------------------------------- */
.dash-stats {
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .6rem;
}
@media (min-width: 40rem) { .dash-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .75rem; } }
@media (min-width: 64rem) { .dash-stats { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (min-width: 90rem) { .dash-stats { grid-template-columns: repeat(9, minmax(0, 1fr)); } }
.dash-stat a {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: "icon n" "label label" "hint hint";
  align-items: center;
  column-gap: .6rem;
  height: 100%;
  padding: .85rem .9rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  color: inherit;
  text-decoration: none;
  box-shadow: var(--shadow);
  transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}
.dash-stat a:hover {
  color: inherit;
  border-color: color-mix(in srgb, var(--accent-2) 35%, var(--rule));
  box-shadow: var(--shadow-hover);
  transform: translateY(-2px);
}
.dash-stat__icon {
  grid-area: icon;
  display: grid;
  place-items: center;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 50%;
  background: var(--accent-tint);
  color: var(--accent);
}
.dash-stat__icon .dash-icon { width: 1.1rem; height: 1.1rem; }
.dash-stat__icon--highlight { background: var(--hl-yellow); color: var(--hl-ink); }
.dash-stat__icon--note { background: var(--hl-blue); color: var(--hl-ink); }
.dash-stat__icon--favorite { background: var(--hl-pink); color: var(--hl-ink); }
.dash-stat__icon--collection { background: var(--hl-green); color: var(--hl-ink); }
.dash-stat__n {
  grid-area: n;
  justify-self: end;
  font-family: var(--font-head);
  font-size: 1.8rem;
  font-weight: 700;
  line-height: 1;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.dash-stat__l {
  grid-area: label;
  margin-top: .55rem;
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.dash-stat__hint { grid-area: hint; font-size: .78rem; color: var(--accent-2); }
.dash-stat--zero .dash-stat__n { color: var(--ink-3); }
.dash-stat--zero a { background: transparent; box-shadow: none; border-style: dashed; }

/* --- Two-column body ------------------------------------------------------ */
.dash-grid { display: grid; gap: 1.25rem; }
.dash-main, .dash-rail { display: grid; gap: 1.25rem; align-content: start; min-width: 0; }
@media (min-width: 64rem) {
  .dash-grid { grid-template-columns: minmax(0, 1fr) 20rem; align-items: start; }
}
@media (min-width: 90rem) { .dash-grid { grid-template-columns: minmax(0, 1fr) 22rem; } }

.dash-panel {
  min-width: 0;
  padding: 1.1rem 1.1rem 1.25rem;
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) * 1.5);
  background: var(--surface);
  box-shadow: var(--shadow);
}
.dash-panel--flush { background: transparent; border: 0; box-shadow: none; padding: 0; }
.dash-panel__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: .25rem 1rem;
  margin-bottom: .75rem;
}
.dash-panel__title {
  display: flex;
  align-items: center;
  gap: .45rem;
  margin: 0 0 .75rem;
  font-size: 1.15rem;
}
.dash-panel__head .dash-panel__title { margin: 0; }
.dash-panel__title .dash-icon { color: var(--accent); }
.dash-panel__aside { margin: 0; font-size: .88rem; font-weight: 600; text-decoration: none; }
.dash-link-button {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-weight: 600;
  color: var(--ink-3);
  cursor: pointer;
}
.dash-link-button:hover { color: var(--danger); text-decoration: underline; }
.dash-empty { margin: 0; color: var(--ink-2); font-size: .95rem; }
.dash-count {
  display: inline-block;
  min-width: 1.5rem;
  padding: 0 .4rem;
  border-radius: 999px;
  background: var(--surface-alt);
  color: var(--ink-2);
  font-size: .75rem;
  font-weight: 700;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* --- Welcome steps -------------------------------------------------------- */
.dash-welcome { margin-bottom: 1.25rem; }
.dash-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 1rem; }
@media (min-width: 40rem) { .dash-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.dash-steps li { display: flex; gap: .75rem; align-items: flex-start; }
.dash-steps p { margin: .2rem 0 .35rem; }
.dash-steps__n {
  display: grid;
  place-items: center;
  flex: none;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 700;
}

/* --- Recently viewed ------------------------------------------------------ */
/* A swipeable strip on a phone; a two-column list once there is room. */
.dash-recent {
  list-style: none;
  margin: 0 -1.1rem;
  padding: 0 1.1rem .25rem;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(14rem, 78%);
  gap: .6rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: 1.1rem;
  overscroll-behavior-x: contain;
}
.dash-recent li { scroll-snap-align: start; min-width: 0; }
@media (min-width: 40rem) {
  .dash-recent {
    margin: 0;
    padding: 0;
    grid-auto-flow: row;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    overflow: visible;
  }
}
.dash-recent__row {
  display: flex;
  align-items: center;
  gap: .7rem;
  height: 100%;
  padding: .6rem .7rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface-alt);
  color: inherit;
  text-decoration: none;
  transition: border-color .15s ease, background .15s ease;
}
.dash-recent__row:hover {
  color: inherit;
  background: var(--surface);
  border-color: color-mix(in srgb, var(--accent-2) 40%, var(--rule));
}
.dash-recent__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--accent);
}
.dash-recent__icon--scripture { background: var(--accent); color: var(--accent-ink); }
.dash-recent__icon--theology { background: var(--hl-blue); color: var(--hl-ink); }
.dash-recent__icon--topic { background: var(--hl-green); color: var(--hl-ink); }
.dash-recent__text { display: flex; flex-direction: column; min-width: 0; }
.dash-recent__title {
  font-weight: 600;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-recent__meta { font-size: .8rem; color: var(--ink-3); }

/* --- Highlights and notes ------------------------------------------------- */
.dash-hl-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .8rem; }
@media (min-width: 64rem) { .dash-hl-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.dash-hl {
  --hl: var(--hl-yellow);
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: .85rem 1rem;
  border-left: 4px solid var(--hl);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: color-mix(in srgb, var(--hl) 22%, var(--surface));
}
.dash-hl--green { --hl: var(--hl-green); }
.dash-hl--blue { --hl: var(--hl-blue); }
.dash-hl--pink { --hl: var(--hl-pink); }
.dash-hl--orange { --hl: var(--hl-orange); }
.dash-hl__text {
  margin: 0;
  font-family: var(--font-read);
  font-size: 1.02rem;
  line-height: 1.55;
  color: var(--ink);
}
.dash-hl__text::before { content: "\201C"; }
.dash-hl__text::after { content: "\201D"; }
.dash-hl__note {
  margin: .5rem 0 0;
  padding-left: .6rem;
  border-left: 2px solid var(--rule);
  font-style: italic;
  font-size: .92rem;
  color: var(--ink-2);
}
.dash-hl__source { margin: auto 0 0; padding-top: .55rem; font-size: .85rem; }
.dash-hl__source a { font-weight: 600; text-decoration: none; }

/* Recently added: the shared cards, two-up inside the main column. */
.dash-cards { margin: 0; }
@media (min-width: 64rem) { .dash-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 90rem) { .dash-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* --- Activity heatmap ----------------------------------------------------- */
.heatmap {
  display: grid;
  grid-template-rows: repeat(7, auto);
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 3px;
  max-width: 22rem;
}
.heat {
  display: inline-block;
  aspect-ratio: 1;
  border-radius: 3px;
  background: var(--surface-alt);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--rule) 60%, transparent);
}
.heat--1 { background: color-mix(in srgb, var(--accent) 25%, var(--surface-alt)); }
.heat--2 { background: color-mix(in srgb, var(--accent) 50%, var(--surface-alt)); }
.heat--3 { background: color-mix(in srgb, var(--accent) 75%, var(--surface-alt)); }
.heat--4 { background: var(--accent); }
.heat--future { visibility: hidden; }
.heatmap__caption { margin: .7rem 0 .2rem; font-size: .88rem; color: var(--ink-2); }
.heatmap__caption strong { color: var(--accent); }
.heatmap__legend {
  display: flex;
  align-items: center;
  gap: 3px;
  margin: 0;
  font-size: .72rem;
  color: var(--ink-3);
}
.heatmap__legend .heat { width: .7rem; }

/* --- Rail lists ----------------------------------------------------------- */
.dash-quick {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr));
  gap: .45rem;
}
.dash-quick__link {
  display: flex;
  align-items: center;
  gap: .45rem;
  min-height: 2.75rem;
  padding: .45rem .65rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  color: var(--ink);
  font-size: .9rem;
  font-weight: 600;
  text-decoration: none;
  transition: background .15s ease, border-color .15s ease;
}
.dash-quick__link .dash-icon { color: var(--accent); }
.dash-quick__link:hover {
  color: var(--ink);
  background: var(--accent-tint);
  border-color: color-mix(in srgb, var(--accent) 35%, var(--rule));
}

.dash-collections { list-style: none; margin: 0; padding: 0; display: grid; gap: .15rem; }
.dash-collections a {
  display: flex;
  align-items: center;
  gap: .6rem;
  min-height: 2.5rem;
  padding: .3rem .5rem;
  margin: 0 -.5rem;
  border-radius: var(--radius);
  color: var(--ink);
  text-decoration: none;
}
.dash-collections a:hover { background: var(--surface-alt); color: var(--ink); }
.dash-collections__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.dash-topics { margin: 0; }
.dash-topics .topic { display: inline-flex; align-items: center; gap: .35rem; }

@media (prefers-reduced-motion: reduce) {
  .dash-continue__card, .dash-stat a, .dash-continue__go { transition: none; }
  .dash-continue__card:hover, .dash-stat a:hover { transform: none; }
}

/* --- Bookmarks: a grid of pictures ----------------------------------------- */
/* templates/study/bookmark_list.html. The picture fills the top of the card,
   the name sits under it, and the whole card opens the site (card__link's
   stretched ::after). Small cards - a bookmark is recognised by its picture,
   so a page of them is a wall to scan: three across on a phone, widening to
   eight. About half the size of the first version. */
.bookmark-grid {
  list-style: none;
  margin: 1.25rem 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: .5rem;
}
@media (min-width: 40rem) { .bookmark-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (min-width: 62rem) { .bookmark-grid { grid-template-columns: repeat(8, minmax(0, 1fr)); } }

/* No overflow: hidden here - it would clip the ⋮ menu's panel. The picture
   rounds its own top corners instead. */
.bookmark-card.card--clickable { padding: 0; display: flex; flex-direction: column; }
.bookmark-card:hover {
  box-shadow: var(--shadow-hover);
  border-color: color-mix(in srgb, var(--accent-2) 25%, var(--rule));
}
@media (hover: hover) { .bookmark-card:hover { transform: translateY(-1px); } }
.bookmark-card__media {
  aspect-ratio: 16 / 10;
  background: var(--surface-alt);
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: calc(var(--radius) - 1px) calc(var(--radius) - 1px) 0 0;
}
.bookmark-card__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.bookmark-card__placeholder {
  font-family: var(--font-head);
  font-size: 1.4rem;
  color: var(--accent-2);
  opacity: .55;
}
.bookmark-card__text { padding: .35rem .4rem .45rem; min-width: 0; }
.card .bookmark-card__title {
  margin: 0;
  font-size: .78rem;
  line-height: 1.25;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  overflow-wrap: anywhere;
}
.bookmark-card__host {
  margin: .15rem 0 0;
  font-size: .68rem;
  color: var(--ink-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* The ⋮ sits on the picture, so it needs its own backing to be seen. */
.bookmark-card > .item-menu { top: .2rem; right: .2rem; }
.bookmark-card .item-menu__toggle {
  width: 1.9rem;
  height: 1.9rem;
  font-size: 1.15rem;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  box-shadow: var(--shadow);
}

/* --- The image picker ------------------------------------------------------ */
/* static/js/imagepicker.js - the bookmark form and the import wizard. A strip
   that scrolls sideways on a phone; each choice is a radio with a picture
   for its label, big enough to tap. */
.image-picker { margin-top: .6rem; }
.image-picker__status { margin: .5rem 0 0; }
.image-picker__strip {
  display: flex;
  gap: .5rem;
  overflow-x: auto;
  padding: .35rem .1rem .5rem;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}
.image-picker__choice {
  position: relative;
  flex: none;
  width: 8.5rem;
  aspect-ratio: 16 / 10;
  border: 2px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface-alt);
  cursor: pointer;
  scroll-snap-align: start;
  display: grid;
  place-items: center;
}
.image-picker__choice img { width: 100%; height: 100%; object-fit: cover; display: block; }
.image-picker__choice--none { width: 6.5rem; font-size: .85rem; color: var(--ink-2); text-align: center; padding: .25rem; }
.image-picker__radio { position: absolute; opacity: 0; pointer-events: none; }
.image-picker__choice:has(.image-picker__radio:checked) {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-tint);
}
.image-picker__choice:has(.image-picker__radio:checked)::after {
  content: "\2713";
  position: absolute;
  top: .3rem;
  right: .3rem;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: .85rem;
  font-weight: 700;
}
.image-picker__choice:has(.image-picker__radio:focus-visible) { outline: 2px solid var(--accent-2); outline-offset: 2px; }

/* The import wizard's pictures step: one row per link. */
.importer-pictures__title { margin: 0 0 .35rem; font-size: 1.3rem; }
.picture-rows { list-style: none; margin: 1rem 0; padding: 0; display: grid; gap: .25rem; }
.picture-row { padding: .75rem 0; border-top: 1px solid var(--rule); min-width: 0; }
.picture-row__head { display: grid; gap: .1rem; min-width: 0; }
.picture-row__title { overflow-wrap: anywhere; }
.picture-row__url {
  font-size: .8rem;
  color: var(--ink-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.picture-row__status { margin: .3rem 0 0; }
