/* Dockd Web — design tokens ported from project/web/tokens.js.
   Switch themes by setting data-theme on <html>. */

:root {
  --font-display: "Inter Tight", "Inter", -apple-system, system-ui, sans-serif;
  --font-ui: "Inter", -apple-system, system-ui, sans-serif;
  --font-reader: "Inter", -apple-system, system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, monospace;
  --nav-w: 240px;
}

/* Editorial Warm */
[data-theme="warm"] {
  --bg: #f4f0e8;
  --surface: #ffffff;
  --surface-2: #ece7dc;
  --surface-3: #e4ddcc;
  --ink: #1a1712;
  --ink-2: #3d3630;
  --ink-3: #756b5f;
  --ink-4: #a89d8e;
  --line: rgba(26, 23, 18, 0.08);
  --line-2: rgba(26, 23, 18, 0.14);
  --line-3: rgba(26, 23, 18, 0.22);
  --accent: #c2410c;
  --accent-soft: #fde9cf;
  --accent-ink: #7a2706;
  --good: #526d3f;
  --warn: #a16207;
  --highlight: #fde68a;
  --hatch: rgba(26, 23, 18, 0.08);
  --card-shadow: 0 1px 2px rgba(26, 23, 18, .04), 0 8px 24px rgba(26, 23, 18, .06);
  --sidebar-shadow: inset -1px 0 0 rgba(26, 23, 18, 0.06);
}

/* Bold Contrast */
[data-theme="bold"] {
  --bg: #0d0c0a;
  --surface: #191714;
  --surface-2: #24211d;
  --surface-3: #2f2b26;
  --ink: #f6f1e6;
  --ink-2: #c8bfae;
  --ink-3: #857c6c;
  --ink-4: #5c554a;
  --line: rgba(246, 241, 230, 0.09);
  --line-2: rgba(246, 241, 230, 0.16);
  --line-3: rgba(246, 241, 230, 0.24);
  --accent: #f59e0b;
  --accent-soft: rgba(245, 158, 11, 0.18);
  --accent-ink: #fbbf24;
  --good: #86efac;
  --warn: #fbbf24;
  --highlight: rgba(245, 158, 11, 0.25);
  --hatch: rgba(246, 241, 230, 0.06);
  --card-shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 12px 32px rgba(0, 0, 0, .5);
  --sidebar-shadow: inset -1px 0 0 rgba(246, 241, 230, 0.08);
}

/* Mono Cool — included for completeness */
[data-theme="cool"] {
  --bg: #eeeff1;
  --surface: #ffffff;
  --surface-2: #e4e6ea;
  --surface-3: #d8dbe1;
  --ink: #0e1013;
  --ink-2: #2a2e35;
  --ink-3: #6b7280;
  --ink-4: #9ca3af;
  --line: rgba(14, 16, 19, 0.08);
  --line-2: rgba(14, 16, 19, 0.14);
  --line-3: rgba(14, 16, 19, 0.22);
  --accent: #4338ca;
  --accent-soft: #e0e7ff;
  --accent-ink: #1e1b4b;
  --good: #15803d;
  --warn: #b45309;
  --highlight: #fef3c7;
  --hatch: rgba(14, 16, 19, 0.07);
  --card-shadow: 0 1px 2px rgba(14, 16, 19, .04), 0 8px 24px rgba(14, 16, 19, .06);
  --sidebar-shadow: inset -1px 0 0 rgba(14, 16, 19, 0.06);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a { color: inherit; text-decoration: none; }

kbd, .dw-kbd {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.5px;
  color: var(--ink-4);
  padding: 2px 5px;
  border: 0.5px solid var(--line-2);
  border-radius: 3px;
  background: transparent;
}
.dw-kbd--ghost { border: none; padding: 0; }

/* Inline shortcut hints — used in the reader toolbar footer.
   Keys and labels share the same font size so nothing reads as
   "smaller than the rest"; keys are differentiated by color and a
   tighter mono weight rather than a chip outline (which felt heavy
   at this size). */
.dw-keyhint {
  display: inline-flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.2;
  color: var(--ink-4);
  user-select: none;
}
.dw-keyhint kbd {
  font: inherit;
  color: var(--ink-2);
  background: transparent;
  border: 0;
  padding: 0;
  letter-spacing: 0;
}
.dw-keyhint__label { color: var(--ink-4); }
.dw-keyhint__sep   { color: var(--ink-4); margin: 0 -3px; }
.dw-keyhint__dot   { color: var(--line-2); }

/* ---------- Shell ---------- */

.dw-shell {
  display: flex;
  min-height: 100vh;
  background: var(--bg);
  color: var(--ink);
}

.dw-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.dw-content {
  flex: 1;
  display: flex;
  min-height: 0;
}

/* ---------- Public shell ----------
   Stripped layout used by anonymous viewers on public profile and
   public list pages. No sidebar, no capture bar — a slim top bar
   with brand-back-to-landing and a sign-up CTA, then content. */

.dw-public-shell {
  --public-rail: max(20px, 4vw);
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  background: var(--bg);
  color: var(--ink);
}

.dw-public-top {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 14px var(--public-rail);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  -webkit-backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 0.5px solid var(--line);
}

.dw-public-top__brand {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 500;
}
.dw-public-top__icon {
  width: 22px;
  height: 22px;
  align-self: center;
  display: block;
  flex-shrink: 0;
}
.dw-public-top__mark {
  font-size: 22px;
  letter-spacing: -0.01em;
}
.dw-public-top__dot {
  color: var(--accent);
  font-size: 22px;
  line-height: 1;
}
.dw-public-top__tag {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-3);
}

.dw-public-top__actions {
  display: flex;
  align-items: center;
  gap: 18px;
}
.dw-public-top__about {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.6px;
  text-transform: lowercase;
  color: var(--ink-3);
  transition: color .15s ease;
}
.dw-public-top__about:hover { color: var(--ink); }

.dw-public-top__cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  padding: 9px 14px;
}

.dw-public-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}
/* The inner .dw-page handles its own padding and (for lists) max-width;
   we just need the container to fill the remaining vertical space below
   the top bar. */

@media (max-width: 720px) {
  .dw-public-top__tag,
  .dw-public-top__dot,
  .dw-public-top__about { display: none; }
  .dw-public-top__cta { padding: 8px 12px; font-size: 12px; }
}

/* ---------- Nav rail ---------- */

.dw-nav {
  width: var(--nav-w);
  flex-shrink: 0;
  background: var(--bg);
  box-shadow: var(--sidebar-shadow);
  padding: 14px 12px 18px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  /* Pin the rail to the viewport so it doesn't scroll with the page.
     Explicit height + align-self stops the flex parent from stretching
     it to document height (which would push the user strip far below
     the fold). overflow-y: auto handles the rare case where the rail's
     own content (long "My lists") exceeds viewport height. */
  position: sticky;
  top: 0;
  height: 100vh;
  align-self: flex-start;
  overflow-y: auto;
}

.dw-wordmark {
  padding: 4px 10px 0;
  display: flex;
  align-items: center;
  gap: 6px;
}
.dw-wordmark__icon {
  width: 24px;
  height: 24px;
  display: block;
  flex-shrink: 0;
}
.dw-wordmark__name {
  font-family: var(--font-display);
  font-size: 26px;
  color: var(--ink);
  line-height: 1;
}
.dw-wordmark__tag {
  font-family: var(--font-mono);
  font-size: 8px;
  color: var(--ink-4);
  letter-spacing: 1.5px;
  text-transform: uppercase;
}

.dw-search {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border-radius: 6px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  font-size: 12px;
  color: var(--ink-3);
}
.dw-search:focus-within { border-color: var(--ink-3); color: var(--ink); }
.dw-search__input {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--ink);
  outline: none;
}
.dw-search__input::placeholder { color: var(--ink-3); }
.dw-search__input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }

.dw-nav__items { display: flex; flex-direction: column; gap: 1px; }
.dw-nav__item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  border-radius: 6px;
  color: var(--ink-2);
  font-size: 13px;
  cursor: pointer;
}
.dw-nav__item span:first-of-type:not(.dw-kbd) { flex: 1; }
.dw-nav__item.is-active {
  background: var(--surface);
  color: var(--ink);
  font-weight: 500;
  box-shadow: inset 0 0 0 0.5px var(--line-2);
}

.dw-nav__section { display: flex; flex-direction: column; gap: 1px; }
.dw-nav__heading {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-4);
  padding: 0 10px 6px;
}

.dw-list {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 10px;
  border-radius: 6px;
  color: var(--ink-2);
  font-size: 13px;
  cursor: pointer;
}
.dw-list__dot {
  width: 6px; height: 6px;
  border-radius: 2px;
  background: var(--accent);
  opacity: 0.7;
}
.dw-list__name { flex: 1; }
.dw-list__count {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-4);
}
.dw-list--add { color: var(--ink-3); font-size: 12px; }

.dw-spacer { flex: 1; }

.dw-profile {
  padding: 10px;
  border-radius: 8px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  display: flex;
  align-items: center;
  gap: 10px;
}
.dw-avatar {
  width: 28px; height: 28px;
  border-radius: 14px;
  background: var(--accent-soft);
  color: var(--accent-ink);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-size: 14px;
}
.dw-profile__meta { flex: 1; min-width: 0; }
.dw-profile__name { font-size: 12px; font-weight: 500; }
.dw-profile__streak {
  font-size: 10px;
  color: var(--ink-3);
  display: flex;
  align-items: center;
  gap: 4px;
}
.dw-profile__streak .dw-icon { color: var(--accent); }

.dw-logout { margin: 0; }
.dw-logout button {
  appearance: none;
  border: none;
  background: transparent;
  padding: 0;
  color: var(--ink-3);
  cursor: pointer;
  display: flex;
  align-items: center;
}
.dw-logout button:hover { color: var(--ink); }

/* ---------- Nav collapse ---------- */

.dw-nav__toggle {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--ink-4);
  width: 28px;
  height: 28px;
  border-radius: 6px;
  padding: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: auto;
  flex-shrink: 0;
  transition: background 120ms ease, color 120ms ease;
}
.dw-nav__toggle:hover { background: var(--surface); color: var(--ink); }
.dw-nav__toggle .dw-icon { width: 14px; height: 14px; transform: rotate(180deg); }
.dw-nav.is-collapsed .dw-nav__toggle .dw-icon { transform: rotate(0deg); }

.dw-nav.is-collapsed { width: 64px; padding: 14px 8px 18px; }
.dw-nav.is-collapsed .dw-wordmark { justify-content: center; padding: 4px 0 0; }
.dw-nav.is-collapsed .dw-nav__toggle { margin-left: 0; }

.dw-capture__brand {
  display: none;
  font-family: var(--font-display);
  font-size: 20px;
  color: var(--ink);
  line-height: 1;
  padding-right: 4px;
}
.dw-nav.is-collapsed ~ .dw-main .dw-capture__brand { display: inline-block; }
.dw-nav.is-collapsed .dw-wordmark__icon,
.dw-nav.is-collapsed .dw-wordmark__name,
.dw-nav.is-collapsed .dw-wordmark__tag,
.dw-nav.is-collapsed .dw-search > span,
.dw-nav.is-collapsed .dw-search .dw-kbd,
.dw-nav.is-collapsed .dw-search__input,
.dw-nav.is-collapsed .dw-nav__item > span,
.dw-nav.is-collapsed .dw-nav__heading,
.dw-nav.is-collapsed .dw-list > span,
.dw-nav.is-collapsed .dw-profile__meta,
.dw-nav.is-collapsed .dw-logout {
  display: none;
}
.dw-nav.is-collapsed .dw-search,
.dw-nav.is-collapsed .dw-nav__item,
.dw-nav.is-collapsed .dw-list,
.dw-nav.is-collapsed .dw-profile {
  justify-content: center;
  padding: 7px 0;
}
/* Hide the lists / teams sections wholesale when the rail is collapsed.
   Each section's heading already hides via the .dw-nav__heading rule
   above, and per-item labels collapse via .dw-list > span — but the
   list rows themselves and the "+ New list/team" button kept showing
   as icon-only entries with no useful affordance. Drop the entire
   .dw-nav__section so the collapsed rail is the four top-level pages
   plus the user strip, and that's it. */
.dw-nav.is-collapsed .dw-nav__section { display: none; }

/* ---------- Capture bar ---------- */

.dw-capture {
  height: 52px;
  border-bottom: 0.5px solid var(--line);
  padding: 0 18px;
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--bg);
  flex-shrink: 0;
}
.dw-capture > .dw-icon { color: var(--ink-3); }
.dw-capture__field {
  flex: 1;
  max-width: 560px;
  padding: 7px 12px;
  background: var(--surface);
  border-radius: 8px;
  border: 0.5px solid var(--line-2);
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--ink-3);
}
.dw-capture__field .dw-icon { color: var(--ink-3); }
.dw-capture__placeholder { flex: 1; }
.dw-capture__input {
  flex: 1;
  border: none;
  background: transparent;
  outline: none;
  color: var(--ink);
  font: inherit;
  padding: 0;
}
.dw-capture__input::placeholder { color: var(--ink-3); }
.dw-capture__signal {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-3);
}
.dw-capture__signal .dw-icon { color: var(--accent); }
.dw-muted { color: var(--ink-4); }

/* Document upload affordances. The paperclip sits inside the URL field,
   left of the ⌘V kbd; the drop overlay covers the entire capture bar
   while a file is being dragged into the page. */
.dw-capture__attach {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 2px 4px;
  margin: -2px 0;
  border: none;
  background: transparent;
  color: var(--ink-3);
  cursor: pointer;
  border-radius: 4px;
}
.dw-capture__attach:hover { color: var(--ink); background: var(--surface-2, rgba(0,0,0,0.04)); }
.dw-capture__attach:focus-visible { outline: 1.5px solid var(--accent); outline-offset: 1px; }
.dw-capture__doc-form { display: none; }
.dw-capture { position: relative; }
.dw-capture__drop {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: var(--bg);
  border: 1.5px dashed var(--accent);
  color: var(--ink);
  font-size: 12px;
  font-family: var(--font-mono);
  letter-spacing: 0.02em;
  pointer-events: none;
  z-index: 5;
}
.dw-capture__drop .dw-icon { color: var(--accent); }
.dw-capture.is-drop-active .dw-capture__drop { display: flex; }

/* ---------- Home page ---------- */

.dw-home {
  padding: 36px 48px 48px;
  display: flex;
  flex-direction: column;
  gap: 28px;
  width: 100%;
  min-width: 0;
}
.dw-home__head { display: flex; flex-direction: column; gap: 14px; }

.dw-meta {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-3);
  letter-spacing: 1.4px;
  text-transform: uppercase;
}
.dw-meta--soft { color: var(--ink-4); }

.dw-display {
  font-family: var(--font-display);
  color: var(--ink);
  letter-spacing: -0.005em;
  margin: 0;
  font-weight: 400;
}
.dw-display--xl { font-size: 42px; line-height: 1.1; max-width: 760px; letter-spacing: -0.01em; }
.dw-display--lg { font-size: 30px; line-height: 1.15; }
.dw-display--sm { font-size: 16px; line-height: 1.25; margin-bottom: 5px; }
.dw-display--muted { color: var(--ink-3); }

.dw-stats {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 12px;
  color: var(--ink-3);
}
.dw-stat { display: flex; align-items: center; gap: 5px; }
.dw-stat .dw-icon { color: var(--accent); }
.dw-stats__div { width: 1px; height: 12px; background: var(--line-2); }

.dw-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 24px;
  flex: 1;
  min-height: 0;
}

/* Hero card */
.dw-hero {
  background: var(--surface);
  border-radius: 10px;
  border: 0.5px solid var(--line);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: var(--card-shadow);
}
.dw-hero__art {
  height: 220px;
  background: linear-gradient(160deg, var(--surface-2) 0%, var(--surface-3) 100%);
  position: relative;
}
.dw-hero__art::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(45deg, var(--hatch) 0, var(--hatch) 1px, transparent 1px, transparent 8px);
}
.dw-hero__body {
  padding: 20px 22px 22px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
}
.dw-row { display: flex; align-items: center; gap: 8px; }
.dw-row--meta { gap: 8px; }
.dw-row--between { justify-content: space-between; margin-bottom: 5px; }

.dw-lede {
  font-family: var(--font-reader);
  font-size: 14px;
  color: var(--ink-2);
  line-height: 1.55;
  font-style: italic;
  margin: 0;
}
.dw-hero__why {
  margin-top: auto;
  padding-top: 8px;
  border-top: 0.5px solid var(--line);
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-3);
  letter-spacing: 0.4px;
}
.dw-hero__why .dw-icon { color: var(--accent); }

/* Pill */
.dw-pill {
  font-size: 10px;
  letter-spacing: 0.3px;
  padding: 2px 7px;
  border-radius: 100px;
  font-family: var(--font-ui);
  font-weight: 500;
  background: var(--surface-2);
  color: var(--ink-2);
}
.dw-pill--accent { background: var(--accent-soft); color: var(--accent-ink); }

/* Stack */
.dw-stack {
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow: hidden;
}
.dw-label {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-3);
}
.dw-card {
  padding: 12px 14px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
  display: block;
  transition: border-color .15s ease, transform .15s ease;
}
.dw-card:hover { border-color: var(--line-2); }
.dw-card__why {
  font-family: var(--font-ui);
  font-size: 11px;
  color: var(--ink-3);
  display: flex;
  align-items: center;
  gap: 5px;
}
.dw-card__why .dw-icon { color: var(--accent); }

/* ---------- Icons ---------- */

.dw-icon { display: block; flex-shrink: 0; width: 18px; height: 18px; }
.dw-icon--sm { width: 14px; height: 14px; }
.dw-icon--xs { width: 10px; height: 10px; }

/* ---------- Responsive (basic) ---------- */

@media (max-width: 1024px) {
  .dw-grid { grid-template-columns: 1fr; }
  .dw-home { padding: 24px; }
}
@media (max-width: 720px) {
  .dw-capture__signal { display: none; }
}

/* ---------- Login page ---------- */

.dw-login {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: var(--bg);
}

.dw-login__left {
  padding: 60px 80px;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
/* Oversized signal-mark watermark behind the left-pane content. The
 * SVG is the same transparent mark used for the favicon and brand
 * placements; sized way past the pane so only the central waveform
 * sweep is visible, with the node and tails fading off both edges. */
.dw-login__left::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url("/static/img/dockd-icon.svg");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 140% auto;
  opacity: 0.10;
  z-index: -1;
  pointer-events: none;
}

.dw-login__brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-size: 32px;
  color: var(--ink);
  line-height: 1;
}
.dw-login__brand-icon {
  width: 36px;
  height: 36px;
  display: block;
  flex-shrink: 0;
}

.dw-login__center {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 24px;
  max-width: 360px;
}

.dw-display--xxl {
  font-family: var(--font-display);
  font-size: 44px;
  color: var(--ink);
  line-height: 1.05;
  letter-spacing: -0.01em;
  margin: 10px 0 0;
  font-weight: 400;
}

.dw-actions { display: flex; flex-direction: column; gap: 10px; }

.dw-btn {
  appearance: none;
  border: none;
  border-radius: 8px;
  padding: 12px 16px;
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  text-align: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  transition: filter .15s ease, transform .05s ease;
}
.dw-btn:hover { filter: brightness(1.05); }
.dw-btn:active { transform: translateY(0.5px); }

.dw-btn--accent {
  background: var(--accent);
  color: #fff;
}
.dw-btn--ghost {
  background: transparent;
  color: var(--ink-2);
  border: 0.5px solid var(--line-2);
}
.dw-btn--google {
  background: var(--surface);
  color: var(--ink);
  border: 0.5px solid var(--line-2);
}
.dw-btn--apple {
  background: var(--ink);
  color: var(--bg);
}

.dw-or {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 6px 0;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-4);
  letter-spacing: 1px;
}
.dw-or::before, .dw-or::after {
  content: '';
  flex: 1;
  height: 0.5px;
  background: var(--line-2);
}

.dw-form { display: flex; flex-direction: column; gap: 10px; }
.dw-form__row { display: flex; gap: 10px; }
.dw-form__row .dw-btn { flex: 1; }

.dw-input {
  padding: 12px 14px;
  background: var(--surface);
  border: 0.5px solid var(--line-2);
  border-radius: 8px;
  font-family: var(--font-ui);
  font-size: 14px;
  color: var(--ink);
  outline: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.dw-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.dw-banner {
  padding: 10px 12px;
  border-radius: 6px;
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-size: 13px;
  border: 0.5px solid var(--line-2);
}

.dw-fineprint {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-3);
  letter-spacing: 0.4px;
  margin: 0;
}

/* Right pane — paywall preview */

.dw-login__right {
  background: var(--surface-2);
  padding: 60px 80px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 24px;
  border-left: 0.5px solid var(--line);
  position: relative;
  overflow: hidden;
}
.dw-login__pro {
  position: absolute;
  top: 40px;
  right: 40px;
}
.dw-login__pitch { max-width: 420px; display: flex; flex-direction: column; gap: 18px; }
.dw-login__pitch .dw-display--xl { margin: 0; }

.dw-features {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.dw-features li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 13px;
  color: var(--ink-2);
}
.dw-features .dw-icon { color: var(--accent); }

.dw-price {
  margin-top: 10px;
  padding: 14px 16px;
  background: var(--surface);
  border: 0.5px solid var(--line-2);
  border-radius: 8px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.dw-price > div:first-child { flex: 1; }
.dw-price__amount {
  font-family: var(--font-display);
  font-size: 20px;
  color: var(--ink);
}
.dw-price__amount span {
  font-family: var(--font-ui);
  font-size: 12px;
  color: var(--ink-3);
}
.dw-pill--solid {
  background: var(--accent);
  color: #fff;
  padding: 7px 12px;
  font-size: 12px;
}

@media (max-width: 900px) {
  .dw-login { grid-template-columns: 1fr; }
  .dw-login__right { display: none; }
  .dw-login__left { padding: 40px 24px; }
}

/* ---------- Generic page chrome ---------- */

.dw-page {
  width: 100%;
  min-width: 0;
  padding: 32px 48px 40px;
  display: flex;
  flex-direction: column;
  gap: 22px;
  overflow: auto;
}
.dw-page__head {
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-shrink: 0;
}
.dw-display--page {
  font-family: var(--font-display);
  font-size: 40px;
  letter-spacing: -0.01em;
  margin: 0;
  font-weight: 400;
  color: var(--ink);
}
.dw-display--md { font-size: 22px; line-height: 1.15; margin: 0; font-weight: 400; }
.dw-display--xs { font-size: 17px; line-height: 1.2; margin: 0; font-weight: 400; }
.dw-mono {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-3);
}

.dw-btn-soft {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px 10px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 6px;
  font-size: 12px;
  color: var(--ink-2);
  cursor: pointer;
}

.dw-pill--outline {
  background: transparent;
  color: var(--ink-3);
  border: 0.5px solid var(--line-2);
}

/* ---------- Library ---------- */

.dw-filters {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
}
.dw-chip {
  padding: 5px 10px;
  border-radius: 4px;
  border: 0.5px solid var(--line-2);
  color: var(--ink-2);
  cursor: pointer;
}
.dw-chip.is-active {
  background: var(--ink);
  color: var(--bg);
  border-color: transparent;
  font-weight: 500;
}
.dw-chip--sm {
  padding: 2px 7px;
  font-family: var(--font-mono);
  font-size: 10px;
}
.dw-filters__hint {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--ink-3);
}

.dw-table {
  background: var(--surface);
  border-radius: 10px;
  border: 0.5px solid var(--line);
  /* overflow: visible so per-row hover popovers can spill outside the
     table; the head + last-row corner-radii below keep the visual edge
     rounded without relying on overflow:hidden. */
  overflow: visible;
}
.dw-table__head { border-radius: 10px 10px 0 0; }
.dw-table__row:last-child { border-radius: 0 0 10px 10px; }
.dw-table__head,
.dw-table__row {
  display: grid;
  /* Columns: Title, Source, Tag, Added, Signal, Time, Notes, Actions.
     Last column hosts: favorite star (always visible) + add-to-list
     picker + archive (hover-revealed). Three icons + gap need ~96px.
     Signal sits between Added and Time so the two date-shaped columns
     stay adjacent and read as a pair. */
  grid-template-columns: minmax(0, 1fr) 140px 130px 70px 80px 70px 60px 96px;
  align-items: center;
  gap: 12px;
  padding: 12px 18px;
}
.dw-table__head {
  background: var(--surface-2);
  border-bottom: 0.5px solid var(--line);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 1.3px;
  text-transform: uppercase;
  color: var(--ink-3);
  padding: 11px 18px;
}
.dw-table__row {
  border-bottom: 0.5px solid var(--line);
  font-size: 13px;
  color: var(--ink);
  position: relative; /* contain the absolutely-positioned insights popover */
}
.dw-table__row:last-child { border-bottom: none; }
.dw-table__row:hover { background: var(--surface-2); }
.dw-table__row.is-pending { color: var(--ink-3); }
.dw-table__row.is-failed { color: var(--ink-4); }

.dw-table__title-cell {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  color: inherit;
}
.dw-table__title {
  font-family: var(--font-display);
  font-size: 15px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  transition: color .15s ease;
}
/* Match the discover row hover: title shifts to accent when the user
   hovers the title cell (the whole row's clickable area). */
.dw-table__title-cell:hover .dw-table__title { color: var(--accent); }

.dw-table__hl {
  display: flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-4);
}
.dw-table__hl.has-hl { color: var(--accent); }
.dw-table__hl.has-hl .dw-icon { color: var(--accent); }

/* Signal column: dimmed em-dash by default, accent color when the save
   has appeared on a recent signal so the column visually flags "this
   one was picked" at a glance. Matches the Added column's mono font so
   the two date columns read as a pair. */
.dw-table__signal { color: var(--ink-4); }
.dw-table__signal.has-signal { color: var(--accent); }

/* Inline tag editor (one per row) */
.dw-table__tag-cell { min-width: 0; }
.dw-inline-form { margin: 0; display: inline-flex; min-width: 0; }
.dw-tag-input {
  width: 100%;
  min-width: 0;
  padding: 3px 8px;
  background: transparent;
  border: 0.5px solid transparent;
  border-radius: 100px;
  font: 500 10px/1.4 var(--font-ui);
  letter-spacing: 0.3px;
  color: var(--ink-2);
  outline: none;
}
.dw-tag-input:hover { border-color: var(--line-2); }
.dw-tag-input:focus {
  background: var(--surface);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
  color: var(--ink);
}
.dw-tag-input::placeholder { color: var(--ink-4); }

/* Row-action cell: favorite star (always visible) + a sub-container
   for hover-revealed actions (add-to-list, archive). The hover group
   has its own opacity so the favorite isn't dimmed with it — a child
   can't be more visible than its parent, so the favorite has to live
   outside that group's opacity scope. */
.dw-row-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
}
.dw-row-actions__hover {
  display: flex;
  align-items: center;
  gap: 4px;
}
/* All three icon buttons share the same chrome — favorite star,
   add-to-list summary, archive button. Single rule covers <button>
   AND <summary> (the rowmenu disclosure trigger) so they read as one
   visual family. */
.dw-row-actions button,
.dw-row-actions .dw-rowmenu summary {
  appearance: none;
  border: none;
  background: transparent;
  padding: 4px;
  border-radius: 4px;
  color: var(--ink-3);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  list-style: none;
}
.dw-row-actions button:hover,
.dw-row-actions .dw-rowmenu summary:hover {
  background: var(--surface-3);
  color: var(--ink);
}

/* Favorite is-on overrides: same hover chrome, accent-tinted star. */
.dw-row-fav.is-on button { color: var(--accent); }
.dw-row-fav.is-on button .dw-icon { fill: var(--accent); }
.dw-row-fav.is-on button:hover { color: var(--accent); }

/* Status pills used in the title cell */
.dw-pill--soft {
  background: var(--surface-2);
  color: var(--ink-3);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}
.dw-pill--warn {
  background: rgba(251, 191, 36, 0.15);
  color: var(--warn);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}

/* Tag chip strip below the status filters */
.dw-filters--tags { flex-wrap: wrap; }

/* Empty state */
.dw-empty {
  margin-top: 24px;
  padding: 48px 24px;
  text-align: center;
  background: var(--surface);
  border: 0.5px dashed var(--line-2);
  border-radius: 10px;
  color: var(--ink-3);
}
.dw-empty__hint {
  margin: 8px 0 0;
  font-size: 13px;
  color: var(--ink-3);
}

/* ---------- Discover ---------- */

.dw-tabs { display: inline-flex; gap: 4px; }
.dw-tab {
  padding: 5px 10px;
  border-radius: 4px;
  font-size: 12px;
  color: var(--ink-3);
}
.dw-tab.is-active {
  background: var(--ink);
  color: var(--bg);
  font-weight: 500;
}

.dw-grid-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  align-content: start;
}
.dw-grid-4 {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}
@media (max-width: 1100px) {
  .dw-grid-3 { grid-template-columns: repeat(2, 1fr); }
  .dw-grid-4 { grid-template-columns: repeat(2, 1fr); }
}

.dw-list-card {
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: var(--card-shadow);
  transition: border-color .15s ease;
}
.dw-list-card:hover { border-color: var(--line-2); }
.dw-list-card__art {
  position: relative;
  height: 110px;
  background: linear-gradient(135deg, var(--accent-soft) 0%, var(--surface-2) 100%);
}
.dw-list-card__art::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(45deg, var(--hatch) 0, var(--hatch) 1px, transparent 1px, transparent 8px);
}
.dw-list-card__art[data-seed="1"] { background: linear-gradient(160deg, var(--surface-2) 0%, var(--surface-3) 100%); }
.dw-list-card__art[data-seed="2"] { background: linear-gradient(180deg, var(--surface-3) 0%, var(--accent-soft) 100%); }
.dw-list-card__art[data-seed="3"] { background: linear-gradient(200deg, var(--surface) 0%, var(--surface-2) 100%); }
.dw-list-card__tag {
  position: absolute;
  bottom: 8px; left: 10px;
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--ink-3);
  letter-spacing: 1.2px;
  text-transform: uppercase;
  z-index: 1;
}
.dw-list-card__body {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
}
.dw-list-card__blurb {
  font-size: 12px;
  color: var(--ink-2);
  line-height: 1.5;
  font-style: italic;
  margin: 0;
}
.dw-list-card__foot {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-top: 10px;
  border-top: 0.5px solid var(--line);
}

.dw-avatar--xs { width: 22px; height: 22px; border-radius: 11px; font-size: 12px; }
.dw-avatar--xl { width: 84px; height: 84px; border-radius: 42px; font-size: 40px; flex-shrink: 0; }

/* ---------- Reader ---------- */

/* When the reader's 3-pane layout is on the page, lock the shell to
   the viewport so panes scroll independently rather than the body
   scrolling. Scoped via :has() so other pages keep their normal
   document-flow scroll. */
.dw-shell:has(.dw-reader__layout) {
  height: 100vh;
  min-height: 0;
  overflow: hidden;
}

/* The reader's 3-pane container. Sits inside #dw-content (provided by
   the standard shell template) so the chrome nav's htmx-boost can swap
   it cleanly when navigating away. Flex row: list pane (fixed width),
   main article (flex), insights rail. min-height:0 lets children scroll
   internally without pushing the layout. */
.dw-reader__layout {
  /* Pane widths live as custom properties so the drag handles can
     mutate them without touching the rules below. JS persists the
     dragged values to localStorage and reapplies on load. */
  --reader-list-w: 340px;
  --reader-rail-w: 320px;
  flex: 1;
  display: flex;
  min-height: 0;
  min-width: 0;
}
.dw-shell.is-reader-list-collapsed .dw-reader__list { display: none; }
.dw-shell.is-reader-rail-collapsed .dw-reader__rail { display: none; }
.dw-shell.is-reader-list-collapsed .dw-reader__resizer[data-resize="list"] { display: none; }
.dw-shell.is-reader-rail-collapsed .dw-reader__resizer[data-resize="rail"] { display: none; }
/* Vertical drag handles between panes. 4px wide so the resting state
   reads as a thin divider; hover/active widen the visual to make the
   target feel generous without making the layout look heavy. */
.dw-reader__resizer {
  flex: 0 0 4px;
  cursor: col-resize;
  background: transparent;
  user-select: none;
  border-left: 0.5px solid var(--line);
  border-right: 0.5px solid var(--line);
  margin: 0 -0.5px;
}
.dw-reader__resizer:hover,
.dw-reader__resizer.is-dragging {
  background: var(--accent);
  opacity: 0.4;
}
.dw-reader__resizer:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
/* While dragging, lock the cursor across the whole layout so the
   pointer doesn't flicker if it briefly leaves the 4px hit zone. */
.dw-reader__layout.is-resizing { cursor: col-resize; }
.dw-reader__layout.is-resizing * { user-select: none; }
.dw-reader__list {
  width: var(--reader-list-w);
  flex-shrink: 0;
  background: var(--surface);
  border-right: 0.5px solid var(--line);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.dw-reader__list-head {
  padding: 14px 16px 10px;
  border-bottom: 0.5px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex-shrink: 0;
}
.dw-reader__list-title {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.dw-reader__list-tools {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: var(--ink-3);
}
.dw-reader__list-body {
  overflow-y: auto;
  flex: 1;
}
.dw-save {
  display: block;
  padding: 12px 16px;
  border-bottom: 0.5px solid var(--line);
  border-left: 2px solid transparent;
  cursor: pointer;
}
.dw-save:hover { background: var(--surface-2); }
.dw-save.is-active { background: var(--surface-2); border-left-color: var(--accent); }
.dw-save.is-read { opacity: 0.5; }
.dw-save__row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 5px;
}
.dw-save__src {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--ink-4);
  letter-spacing: 0.8px;
  text-transform: uppercase;
}
.dw-save__title {
  font-family: var(--font-display);
  font-size: 15px;
  color: var(--ink);
  line-height: 1.3;
  margin-bottom: 6px;
}

.dw-reader__main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--bg);
}
.dw-reader__article {
  flex: 1;
  overflow-y: auto;
  padding: 42px 64px 60px;
  /* Reader-scoped tokens driven by the type/display menu. Inline
     style on the element overrides these on a per-user basis; the
     defaults below are the fallback when the menu hasn't been opened
     yet (or the user hasn't picked anything yet on this device). */
  --reader-font-size: 17px;
  --reader-line-height: 1.6;
  --reader-width: 720px;
  --reader-font-stack: var(--font-display);
}
.dw-article {
  max-width: var(--reader-width);
  margin: 0 auto;
}

/* The article body's font / size / leading bind to the reader-scoped
   tokens directly in the main .dw-article__body rule further down in
   this file (~line 1657) — duplicating them here would not actually
   raise specificity, the later rule wins anyway. */

/* Font-family pickers. The menu writes data-font="serif|sans|mono"
   onto the article element; the stacks below are deliberate:
     • serif — a system book stack ("Iowan Old Style" on macOS / iOS,
       "Charter" on macOS, Cambria on Windows, Georgia anywhere) so
       Serif actually renders as a serif. No web-font load — the app
       only ships Inter / Inter Tight / JetBrains Mono.
     • sans  — Inter, which the page already loads.
     • mono  — JetBrains Mono, same. */
.dw-reader__article[data-font="serif"] {
  --reader-font-stack:
    "Iowan Old Style", "Apple Garamond", Baskerville,
    Charter, "Bitstream Charter", "Sitka Text",
    Cambria, Georgia, "Times New Roman", Times, serif;
}
.dw-reader__article[data-font="sans"]  { --reader-font-stack: var(--font-ui); }
.dw-reader__article[data-font="mono"]  { --reader-font-stack: var(--font-mono); font-feature-settings: "ss01" 1; }

/* Per-reader theme override. data-theme on the article re-binds the
   surface / ink / accent tokens for the article column only, leaving
   the surrounding shell (nav rail, capture bar, right rail) in the
   global theme. "auto" = inherit the global theme; "light/dark/sepia"
   force a specific palette. */
.dw-reader__article[data-theme="light"] {
  --bg: #fbfaf6;
  --surface: #ffffff;
  --surface-2: #f3efe6;
  --surface-3: #e8e1d2;
  --ink: #1a1712;
  --ink-2: #3d3630;
  --ink-3: #756b5f;
  --ink-4: #a89d8e;
  --line: rgba(26, 23, 18, 0.08);
  --line-2: rgba(26, 23, 18, 0.14);
  --line-3: rgba(26, 23, 18, 0.22);
  --highlight: #fde68a;
  background: var(--bg);
  color: var(--ink);
}
.dw-reader__article[data-theme="dark"] {
  --bg: #14110e;
  --surface: #1d1a16;
  --surface-2: #28241f;
  --surface-3: #322d27;
  --ink: #f4ecdf;
  --ink-2: #cbc1ae;
  --ink-3: #8a8170;
  --ink-4: #5b5448;
  --line: rgba(244, 236, 223, 0.09);
  --line-2: rgba(244, 236, 223, 0.16);
  --line-3: rgba(244, 236, 223, 0.24);
  --highlight: rgba(245, 158, 11, 0.28);
  background: var(--bg);
  color: var(--ink);
}
.dw-reader__article[data-theme="sepia"] {
  --bg: #f1e7d0;
  --surface: #f8f0db;
  --surface-2: #eadfc4;
  --surface-3: #e0d4b3;
  --ink: #2d2516;
  --ink-2: #4d4127;
  --ink-3: #7a6a48;
  --ink-4: #a59574;
  --line: rgba(45, 37, 22, 0.10);
  --line-2: rgba(45, 37, 22, 0.16);
  --line-3: rgba(45, 37, 22, 0.24);
  --highlight: #f3d27a;
  background: var(--bg);
  color: var(--ink);
}

/* Bionic / Fast Reading. bread.js wraps the leading letters of each
   long-enough word in <span class="bread">; the CSS here is what
   makes the bolding actually visible. display:contents keeps the
   span out of the layout flow so highlights and link styling still
   anchor against the real text nodes. */
.dw-article__body span.bread {
  display: contents;
  font-weight: 700;
}

/* --- Type / display menu --------------------------------------- */

.dw-toolform__type { margin-left: 0; }
.dw-rowmenu__panel.dw-type-menu {
  /* The default rowmenu panel is narrow + right-aligned + capped at
     320px tall with overflow scrolling. The type menu has enough
     rows that the cap forced the Fast Reading toggle into a scroll
     region, which read as broken; widen and let the panel grow as
     tall as its content. Selector is doubled up so it beats the
     base .dw-rowmenu__panel rule defined later in the file. */
  min-width: 300px;
  max-width: 340px;
  max-height: none;
  overflow: visible;
  padding: 8px;
  gap: 4px;
}
.dw-type-menu .dw-rowmenu__heading { padding: 8px 4px 2px; }
.dw-type-menu__row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 0;
}
.dw-type-menu__seg { width: 100%; }
.dw-type-menu__chip {
  flex: 1;
  appearance: none;
  border: 0.5px solid var(--line-2);
  background: var(--surface);
  color: var(--ink-2);
  padding: 7px 6px;
  border-radius: 6px;
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  text-align: center;
}
.dw-type-menu__chip:hover { background: var(--surface-2); color: var(--ink); }
.dw-type-menu__chip.is-on {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-ink);
}
.dw-type-menu__chip--font--serif {
  font-family:
    "Iowan Old Style", "Apple Garamond", Baskerville,
    Charter, "Bitstream Charter", "Sitka Text",
    Cambria, Georgia, "Times New Roman", Times, serif;
}
.dw-type-menu__chip--font--sans  { font-family: var(--font-ui); }
.dw-type-menu__chip--font--mono  { font-family: var(--font-mono); }

.dw-type-menu__steps { justify-content: space-between; padding: 0 2px; }
.dw-type-menu__step {
  appearance: none;
  border: 0.5px solid var(--line-2);
  background: var(--surface);
  color: var(--ink-2);
  width: 28px;
  height: 28px;
  border-radius: 6px;
  font: inherit;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
}
.dw-type-menu__step:hover { background: var(--surface-2); color: var(--ink); }
.dw-type-menu__readout {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-3);
  min-width: 70px;
  text-align: center;
}

.dw-type-menu__sep {
  height: 0.5px;
  background: var(--line);
  margin: 6px 2px;
}

.dw-type-menu__toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 4px;
  cursor: pointer;
}
.dw-type-menu__toggle-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.dw-type-menu__toggle-title { color: var(--ink); font-size: 13px; }
.dw-type-menu__toggle-hint {
  color: var(--ink-3);
  font-size: 11px;
  line-height: 1.35;
}
/* iOS-style switch. The native <input> is visually hidden but stays
   in the layout so click + keyboard focus work; the visible track +
   thumb spans next to it react to :checked / :focus-visible. */
.dw-switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  width: 36px;
  height: 22px;
  flex-shrink: 0;
}
.dw-switch__input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
  z-index: 1;
}
.dw-switch__track {
  position: absolute;
  inset: 0;
  background: var(--surface-3);
  border: 0.5px solid var(--line-2);
  border-radius: 999px;
  transition: background 140ms ease;
}
.dw-switch__thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 999px;
  background: var(--surface);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
  transition: transform 140ms ease, background 140ms ease;
}
.dw-switch__input:checked ~ .dw-switch__track { background: var(--accent); border-color: var(--accent); }
.dw-switch__input:checked ~ .dw-switch__track .dw-switch__thumb { transform: translateX(14px); background: #fff; }
.dw-switch__input:focus-visible ~ .dw-switch__track {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.dw-article__meta {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 22px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-3);
  letter-spacing: 0.8px;
  text-transform: uppercase;
}
.dw-article__title {
  font-family: var(--font-display);
  font-size: 54px;
  line-height: 1.08;
  color: var(--ink);
  margin: 0 0 16px;
  font-weight: 400;
  letter-spacing: -0.01em;
}
.dw-article__lede {
  font-family: var(--font-reader);
  font-size: 18px;
  line-height: 1.45;
  color: var(--ink-3);
  margin-bottom: 32px;
  font-style: italic;
}
.dw-article__body {
  font-family: var(--reader-font-stack);
  font-size: var(--reader-font-size);
  line-height: var(--reader-line-height);
  color: var(--ink);
  letter-spacing: 0.005em;
}
.dw-article__body p { margin: 0 0 1em; font-size: inherit; line-height: inherit; }
.dw-article__body li,
.dw-article__body blockquote { font-size: inherit; line-height: inherit; }
.dw-article__body p.is-soft { color: var(--ink-2); }
.dw-article__body mark { background: var(--highlight); color: inherit; padding: 0 1px; }
.dw-article__body h1,
.dw-article__body h2,
.dw-article__body h3,
.dw-article__body h4 {
  font-family: var(--font-display);
  color: var(--ink);
  letter-spacing: -0.005em;
  margin: 1.6em 0 0.5em;
  font-weight: 400;
  line-height: 1.2;
}
.dw-article__body h2 { font-size: 1.55em; }
.dw-article__body h3 { font-size: 1.25em; }
.dw-article__body h4 { font-size: 1.05em; }
.dw-article__body a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 0.5px;
}
.dw-article__body a:hover { text-decoration-thickness: 1px; }
.dw-article__body blockquote {
  margin: 1em 0;
  padding: 0.4em 1em;
  border-left: 2px solid var(--line-3);
  color: var(--ink-2);
  font-style: italic;
}
.dw-article__body ul,
.dw-article__body ol { margin: 0 0 1em 1.5em; padding: 0; }
.dw-article__body li { margin: 0.25em 0; }
.dw-article__body img,
.dw-article__body figure { max-width: 100%; height: auto; margin: 1em 0; border-radius: 4px; }
.dw-article__body .dw-embed { margin: 1.25em 0; }
.dw-article__body .dw-embed--video {
  position: relative;
  aspect-ratio: 16 / 9;
  background: #000;
  border-radius: 6px;
  overflow: hidden;
}
.dw-article__body .dw-embed--video iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
.dw-article__body .dw-embed--disabled {
  background: var(--surface-2);
  border: 0.5px solid var(--line);
  border-radius: 6px;
  padding: 16px;
  text-align: center;
}
.dw-article__body .dw-embed--disabled img {
  max-width: 100%;
  margin: 0 auto;
  border-radius: 4px;
}
.dw-article__body .dw-embed__notice {
  margin: 10px 0 0;
  font-size: 13px;
  color: var(--ink-2);
}
.dw-article__body figure { text-align: center; }
.dw-article__body figcaption {
  font-size: 13px;
  color: var(--ink-3);
  font-style: italic;
  margin-top: 6px;
}

/* Document viewer. Documents render their original bytes in a viewer
   instead of the readability prose body — PDFs go through the browser's
   built-in PDF view inside an <iframe>; EPUB/DOCX fall back to a
   download card since browsers can't render those inline. The article
   wrapper widens (640px is too narrow for a PDF page) and the article
   pane's padding shrinks so the viewer fills as much vertical space as
   the reader main pane will give it. */
.dw-reader__article:has(.dw-article--document) { padding: 24px 24px 24px; }
.dw-article--document { max-width: none; }
.dw-article--document .dw-article__title {
  font-size: 24px;
  margin: 0 0 14px;
  line-height: 1.2;
}
.dw-doc-viewer {
  margin-top: 12px;
  border-radius: 6px;
  border: 0.5px solid var(--line-2);
  background: var(--surface);
  overflow: hidden;
  height: calc(100vh - 220px);
  min-height: 420px;
}
.dw-doc-viewer__frame {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  background: var(--surface);
}
.dw-doc-fallback {
  margin: 24px auto;
  max-width: 480px;
  padding: 36px 28px;
  border: 0.5px dashed var(--line-2);
  border-radius: 8px;
  background: var(--surface);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 14px;
}
.dw-doc-fallback__icon { color: var(--ink-3); }
.dw-doc-fallback__title {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink);
  word-break: break-all;
}
.dw-doc-fallback__hint {
  margin: 0;
  font-size: 13px;
  color: var(--ink-3);
  line-height: 1.5;
}

.dw-article__body pre {
  background: var(--surface-2);
  border: 0.5px solid var(--line);
  border-radius: 6px;
  padding: 14px 16px;
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.55;
  margin: 1em 0;
}
.dw-article__body code {
  font-family: var(--font-mono);
  font-size: 0.88em;
  background: var(--surface-2);
  padding: 1px 5px;
  border-radius: 3px;
}
.dw-article__body pre code { background: transparent; padding: 0; }
.dw-article__body hr {
  border: none;
  border-top: 0.5px solid var(--line-2);
  margin: 2em 0;
}

.dw-empty--page {
  margin: 80px auto;
  max-width: 480px;
}
.dw-empty--inline {
  margin: 0;
  padding: 32px;
  background: var(--surface-2);
}
.dw-empty__hint--inline { margin-top: 4px; font-size: 12px; }
.dw-link {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 0.5px;
}
.dw-link--meta {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink-3);
}
.dw-link--meta:hover { color: var(--ink); }
/* Amber text-button next to "View source" — buttons inside form posts
   for the mark-read toggle, styled to match dw-link--meta but in
   accent so the article-completion action reads as primary. */
button.dw-link--meta {
  appearance: none;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
}
.dw-link--meta-accent {
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}
.dw-link--meta-accent:hover { color: var(--accent-ink); }
.dw-link--meta-accent:focus-visible {
  outline: 1.5px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}
.dw-article__note {
  margin: 20px 0;
  padding: 12px 14px;
  border-left: 2px solid var(--accent);
  background: var(--accent-soft);
  border-radius: 0 6px 6px 0;
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--accent-ink);
  line-height: 1.45;
  display: flex;
  gap: 10px;
}
.dw-article__note .dw-icon { color: var(--accent-ink); }

.dw-reader__toolbar {
  position: relative;
  height: 48px;
  border-top: 0.5px solid var(--line);
  display: flex;
  align-items: center;
  padding: 0 22px;
  gap: 14px;
  background: var(--bg);
  color: var(--ink-3);
  font-size: 12px;
  flex-shrink: 0;
}

/* Thin reading-progress bar along the top edge of the reader footer.
   Sits flush over the toolbar's top border so it reads as a unit. The
   width of the inner <span> is driven by the scroll listener (and the
   server-rendered saved % on first paint). */
.dw-reader__progress {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: transparent;
  pointer-events: none;
  overflow: hidden;
  z-index: 1;
}
.dw-reader__progress span {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--accent);
  transition: width 120ms ease-out;
}
.dw-toolbtn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  cursor: pointer;
  appearance: none;
  border: none;
  background: transparent;
  padding: 4px 6px;
  border-radius: 4px;
  color: inherit;
  font: inherit;
}
.dw-toolbtn:hover { background: var(--surface-2); color: var(--ink); }
.dw-toolbtn.is-stub { opacity: 0.55; cursor: default; }
.dw-toolbtn.is-stub:hover { background: transparent; color: var(--ink-3); }
.dw-toolbtn .dw-kbd {
  padding: 1px 4px;
  background: var(--surface-2);
  border-radius: 3px;
  border: none;
}
.dw-toolform { margin: 0; display: inline-flex; }

.dw-reader__rail {
  width: var(--reader-rail-w);
  flex-shrink: 0;
  background: var(--surface);
  border-left: 0.5px solid var(--line);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.dw-reader__tabs {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 16px;
  border-bottom: 0.5px solid var(--line);
  font-size: 12px;
  flex-shrink: 0;
}
/* Tabs render as buttons now (interactive + keyboard-focusable). The
   reset below strips the user-agent button chrome so they read like
   the original spans, with hover/focus picking up the existing
   underline + ink. */
.dw-reader__tab {
  appearance: none;
  background: transparent;
  border: none;
  border-bottom: 1.5px solid transparent;
  padding: 12px 2px;
  color: var(--ink-3);
  font: inherit;
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease;
}
.dw-reader__tab:hover { color: var(--ink-2); }
.dw-reader__tab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}
.dw-reader__tab.is-active {
  color: var(--ink);
  border-bottom-color: var(--accent);
  font-weight: 500;
}
.dw-reader__tab.is-stub,
.dw-reader__tab[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}
.dw-reader__tab.is-stub:hover,
.dw-reader__tab[disabled]:hover { color: var(--ink-3); }
.dw-reader__rail-body {
  flex: 1;
  overflow-y: auto;
  padding: 18px 16px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.dw-reader__rail-title {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
}
.dw-reader__rail-title .dw-icon { color: var(--accent); }
.dw-reader__tldr {
  font-family: var(--font-reader);
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-2);
}
.dw-reader__tldr mark { background: var(--highlight); color: inherit; padding: 0 2px; }
/* "Why read this" — single sentence, weighted slightly heavier than the
   TL;DR so the eye lands here first when triaging the rail. */
.dw-reader__gain {
  font-family: var(--font-reader);
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink);
  font-style: italic;
}
/* LLM-suggested tag chip strip. Spacing only — colour comes from
   .dw-pill--soft. */
.dw-reader__tags { display: flex; flex-wrap: wrap; gap: 4px; }

/* ---------- Reader: highlights / notes ---------- */

/* Floating selection bar — same surface/border/shadow language as the
   rowmenu panel and the modal so it reads as part of the site rather
   than a stock browser tooltip. The reader JS moves this element to
   <body> on init so its position: absolute is unambiguously relative
   to the document; coords are page-relative. */
.dw-annot-bar {
  position: absolute;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 4px;
  background: var(--surface);
  border: 0.5px solid var(--line-2);
  border-radius: 8px;
  box-shadow: var(--card-shadow);
  z-index: 50;
}
/* The display: inline-flex above wins against the UA's
   [hidden] { display: none } at equal specificity, so the [hidden]
   attribute alone wouldn't hide the bar. Force display:none here. */
.dw-annot-bar[hidden] { display: none; }
.dw-annot-bar__btn {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--ink-2);
  font: 500 11px/1 var(--font-ui);
  padding: 6px 10px;
  border-radius: 4px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.dw-annot-bar__btn:hover { background: var(--surface-2); color: var(--ink); }
.dw-annot-bar__btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* Inline <mark> the JS wraps around re-anchored highlights. Uses the
   theme's --highlight token so each theme styles it appropriately. */
.dw-mark {
  background: var(--highlight);
  color: inherit;
  padding: 0 2px;
  border-radius: 2px;
}

/* Right-rail annotations list. Each item shows the quote (when present)
   and any attached note, with a small delete affordance on hover. */
.dw-annots {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.dw-annot {
  position: relative;
  padding: 10px 32px 10px 10px;
  background: var(--surface-2);
  border-radius: 6px;
  border-left: 2px solid var(--accent);
}
.dw-annot--note { border-left-color: var(--ink-3); }
.dw-annot__quote {
  margin: 0 0 6px;
  font-family: var(--font-reader);
  font-size: 12px;
  font-style: italic;
  color: var(--ink);
  line-height: 1.5;
}
.dw-annot__quote::before { content: "\201C"; margin-right: 1px; }
.dw-annot__quote::after { content: "\201D"; margin-left: 1px; }
.dw-annot__body {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 11px;
  color: var(--ink-2);
  line-height: 1.5;
}
.dw-annot__delete {
  position: absolute;
  top: 4px;
  right: 4px;
  /* Always visible — the X is the user's only way to remove an
     annotation, no point hiding it behind hover. */
}
.dw-annot__delete button {
  appearance: none;
  border: none;
  background: transparent;
  padding: 4px;
  border-radius: 4px;
  color: var(--ink-3);
  cursor: pointer;
}
.dw-annot__delete button:hover { color: var(--ink); background: var(--surface-3); }

/* Standalone-note input below the highlights list. */
.dw-annot__add {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 12px;
}
.dw-annot__textarea {
  font: 12px/1.5 var(--font-ui);
  color: var(--ink);
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 6px;
  padding: 8px 10px;
  outline: none;
  resize: vertical;
  min-height: 56px;
}
.dw-annot__textarea:focus { border-color: var(--line-2); }
.dw-annot__add button { align-self: flex-start; }

/* Public list page: curator's annotations under each item. Reuses the
   .dw-annot styles from the reader rail, just with a wider max-width
   so they breathe in the article-list context. */
.dw-list-public__annots {
  margin-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: 60ch;
}
.dw-list-public__annots .dw-annot { padding: 8px 10px; }

/* ---------- Themed modal ---------- */

/* Generic modal pattern: full-viewport flex container with a
   semi-opaque backdrop + centred dialog. The [hidden] attribute on
   the root toggles the whole thing. dialog itself has its own
   surface + border so it reads as a contained card on top of the
   dimmed page. */
.dw-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.dw-modal[hidden] { display: none; }
.dw-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  cursor: pointer;
}
.dw-modal__dialog {
  position: relative;
  width: 100%;
  max-width: 540px;
  background: var(--surface);
  border: 0.5px solid var(--line-2);
  border-radius: 12px;
  padding: 18px 20px 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  box-shadow: var(--card-shadow);
  animation: dw-modal-in 120ms ease-out;
}
@keyframes dw-modal-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.dw-modal__head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.dw-modal__close {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--ink-3);
  cursor: pointer;
  padding: 4px;
  border-radius: 4px;
  margin-left: auto;
}
.dw-modal__close:hover { color: var(--ink); background: var(--surface-2); }
.dw-modal__quote {
  margin: 0;
  padding: 8px 12px;
  background: var(--surface-2);
  border-left: 2px solid var(--accent);
  border-radius: 4px;
  font-family: var(--font-reader);
  font-size: 13px;
  font-style: italic;
  color: var(--ink-2);
  line-height: 1.5;
  max-height: 6em;
  overflow-y: auto;
}
.dw-modal__quote[hidden] { display: none; }
.dw-modal__quote::before { content: "\201C"; margin-right: 1px; }
.dw-modal__quote::after { content: "\201D"; margin-left: 1px; }
.dw-modal__textarea {
  width: 100%;
  font: 13px/1.55 var(--font-ui);
  color: var(--ink);
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 6px;
  padding: 10px 12px;
  outline: none;
  resize: vertical;
  min-height: 100px;
}
.dw-modal__textarea:focus {
  border-color: var(--line-2);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.dw-modal__actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Iframe preview modal — reuses the dw-modal flex container but
   stretches the dialog to a near-fullscreen surface so the embedded
   page has real estate. The dialog itself is a column flexbox; the
   header is fixed-height and the viewport flexes to fill the rest.
   The viewport is position:relative so the loading + error overlays
   can stack on top of the iframe without affecting layout. */
.dw-iframe-modal { padding: 24px; }
.dw-iframe-modal__dialog {
  max-width: 1100px;
  width: 100%;
  height: 100%;
  max-height: calc(100vh - 48px);
  padding: 0;
  gap: 0;
  overflow: hidden;
}
.dw-iframe-modal__head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px 10px 16px;
  border-bottom: 0.5px solid var(--line);
  background: var(--surface-2);
  flex-shrink: 0;
}
.dw-iframe-modal__heading {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}
.dw-iframe-modal__title {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--ink-3);
}
.dw-iframe-modal__src {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dw-iframe-modal__viewport {
  position: relative;
  flex: 1;
  min-height: 0;
  background: var(--surface);
  overflow: hidden;
}
.dw-iframe-modal__frame {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  background: #fff;
}
.dw-iframe-modal__loading,
.dw-iframe-modal__error {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  background: var(--surface);
  color: var(--ink-3);
  font-size: 13px;
  padding: 24px;
  text-align: center;
}
.dw-iframe-modal__loading[hidden],
.dw-iframe-modal__error[hidden] { display: none; }
.dw-iframe-modal__error .dw-display { color: var(--ink); }
.dw-iframe-modal__spinner {
  width: 22px;
  height: 22px;
  border: 2px solid var(--line);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: dw-iframe-spin 700ms linear infinite;
}
@keyframes dw-iframe-spin { to { transform: rotate(360deg); } }

.dw-keypoints {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.dw-keypoints li {
  display: flex;
  gap: 10px;
  font-size: 12px;
  color: var(--ink-2);
  line-height: 1.45;
}
.dw-keypoints__num {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-4);
  min-width: 12px;
}

.dw-highlights {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.dw-highlights__item {
  padding: 8px 10px;
  background: var(--highlight);
  border-radius: 4px;
  font-family: var(--font-reader);
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink);
}

.dw-related {
  display: flex;
  flex-direction: column;
  gap: 7px;
  margin-top: 10px;
}
.dw-related__item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 10px;
  border: 0.5px solid var(--line);
  border-radius: 6px;
  font-size: 12px;
  color: var(--ink-2);
}
.dw-related__item:hover { border-color: var(--line-2); }

.dw-publish-cta {
  padding: 12px;
  border-radius: 8px;
  background: var(--accent-soft);
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  color: var(--accent-ink);
}
.dw-publish-cta__title { font-size: 12px; font-weight: 500; }
.dw-publish-cta__hint {
  font-family: var(--font-mono);
  font-size: 9px;
  opacity: 0.7;
  letter-spacing: 0.4px;
}

/* ---------- Publish composer ---------- */

.dw-publish {
  display: grid;
  grid-template-columns: 1fr 340px;
  padding: 0;
  gap: 0;
}
.dw-publish__editor {
  padding: 32px 48px 40px;
  display: flex;
  flex-direction: column;
  gap: 22px;
  border-right: 0.5px solid var(--line);
  overflow-y: auto;
}
.dw-publish__title {
  font-family: var(--font-display);
  font-size: 44px;
  color: var(--ink);
  border: none;
  outline: none;
  background: transparent;
  padding: 0;
  letter-spacing: -0.01em;
}
.dw-publish__sub {
  font-family: var(--font-reader);
  font-size: 17px;
  color: var(--ink-2);
  border: none;
  outline: none;
  background: transparent;
  padding: 0;
  resize: none;
  line-height: 1.5;
  font-style: italic;
  min-height: 52px;
}
.dw-publish__tags {
  display: flex;
  align-items: center;
  gap: 10px;
}
.dw-publish__items {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.dw-publish__item {
  padding: 14px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 8px;
  display: flex;
  gap: 12px;
}
.dw-publish__num {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-4);
  width: 22px;
  padding-top: 3px;
}
.dw-publish__item-body { flex: 1; }
.dw-publish__item-body .dw-meta { margin: 6px 0; }
.dw-publish__note {
  font-family: var(--font-reader);
  font-size: 13px;
  color: var(--ink-2);
  line-height: 1.5;
  font-style: italic;
}
.dw-publish__note--empty { color: var(--ink-4); font-style: normal; }
.dw-publish__add {
  padding: 14px;
  border: 0.5px dashed var(--line-2);
  border-radius: 8px;
  font-size: 12px;
  color: var(--ink-3);
  display: flex;
  align-items: center;
  gap: 8px;
}

.dw-publish__rail {
  background: var(--surface);
  padding: 32px 22px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  overflow-y: auto;
}
.dw-publish__visibility {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.dw-radio {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 6px;
  font-size: 12px;
  color: var(--ink-2);
  cursor: pointer;
}
.dw-radio.is-on {
  background: var(--accent-soft);
  color: var(--accent-ink);
}
.dw-radio__dot {
  width: 14px;
  height: 14px;
  border-radius: 7px;
  border: 1.5px solid var(--line-3);
  flex-shrink: 0;
  position: relative;
}
.dw-radio.is-on .dw-radio__dot { border-color: var(--accent); }
.dw-radio.is-on .dw-radio__dot::after {
  content: '';
  position: absolute;
  inset: 2px;
  background: var(--accent);
  border-radius: 50%;
}
.dw-publish__url {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-3);
  padding: 8px 10px;
  background: var(--surface-2);
  border-radius: 4px;
}
.dw-publish__cover {
  position: relative;
  height: 120px;
  border-radius: 6px;
  background: linear-gradient(180deg, var(--surface-3) 0%, var(--accent-soft) 100%);
  overflow: hidden;
}
.dw-publish__cover::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(45deg, var(--hatch) 0, var(--hatch) 1px, transparent 1px, transparent 8px);
}
.dw-publish__cover .dw-meta {
  position: absolute;
  bottom: 8px;
  left: 10px;
}

/* ---------- Feeds ---------- */

.dw-connector {
  padding: 14px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 8px;
  display: flex;
  gap: 10px;
  align-items: center;
}
.dw-connector__icon {
  width: 32px;
  height: 32px;
  border-radius: 6px;
  background: var(--surface-2);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--ink-2);
}
.dw-connector__name { font-size: 13px; color: var(--ink); font-weight: 500; }
.dw-connector__status {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--good);
}

.dw-sources {
  background: var(--surface);
  border-radius: 10px;
  border: 0.5px solid var(--line);
  overflow: hidden;
}
.dw-source-row {
  display: grid;
  grid-template-columns: 28px 1fr 120px 140px 60px;
  align-items: center;
  padding: 14px 18px;
  border-bottom: 0.5px solid var(--line);
  font-size: 13px;
}
.dw-source-row:last-child { border-bottom: none; }
.dw-source-row.is-off { opacity: 0.5; }
.dw-source-row__icon { color: var(--ink-2); }
.dw-source-row__name { color: var(--ink); }

/* The richer label-based .dw-toggle (used on the settings page) is
   defined further down in the file. The original small-switch variant
   has been removed — no template references it anymore. */

/* ---------- Profile ---------- */

.dw-profile-page { gap: 28px; }

.dw-profile-head {
  display: flex;
  align-items: flex-start;
  gap: 20px;
}
.dw-profile-head__meta { flex: 1; }
.dw-profile-head__bio {
  font-size: 13px;
  color: var(--ink-2);
  margin: 8px 0 0;
  max-width: 520px;
  font-style: italic;
}
.dw-profile-stats {
  display: flex;
  gap: 20px;
  align-items: flex-start;
}
.dw-profile-stat { text-align: right; }
.dw-profile-stat__value {
  font-family: var(--font-display);
  font-size: 28px;
  color: var(--ink);
  line-height: 1;
}
.dw-profile-stat__label {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--ink-3);
  letter-spacing: 1px;
  text-transform: uppercase;
  margin-top: 4px;
}
.dw-profile-stat__sub {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--accent);
  letter-spacing: 0.5px;
  margin-top: 2px;
}

/* ---------- Achievements row (profile gamification) ----------

   Earned-first chip strip with a visible "next" target underneath. We
   don't render locked badges in the row — surfacing every locked tier
   would make the strip feel sparse for new users. The single .dw-next-badge
   block instead shows the closest goal as a progress bar. */
.dw-achievements {
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 12px;
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.dw-achievements__head {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.dw-achievements__row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.dw-badge {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px 8px 10px;
  border-radius: 10px;
  background: var(--surface-2);
  border: 0.5px solid var(--line);
  min-width: 0;
}
.dw-badge.is-earned {
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
  border-color: color-mix(in srgb, var(--accent) 30%, var(--line));
}
.dw-badge__icon {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-3);
  flex-shrink: 0;
}
.dw-badge.is-earned .dw-badge__icon {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--surface);
}
.dw-badge__icon .dw-icon { width: 14px; height: 14px; }
.dw-badge__meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.dw-badge__title {
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.1;
}
.dw-badge__desc {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--ink-3);
  letter-spacing: 0.4px;
}

/* Next-up callout sits below the earned strip and pushes the user to
   the closest reachable goal. Visually subtler than the earned chips —
   it's a guidepost, not a celebration. */
.dw-next-badge {
  display: flex;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 10px;
  background: var(--surface-2);
  border: 0.5px dashed color-mix(in srgb, var(--accent) 50%, var(--line));
}
.dw-next-badge__icon {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
  flex-shrink: 0;
}
.dw-next-badge__icon .dw-icon { width: 16px; height: 16px; }
.dw-next-badge__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.dw-next-badge__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.dw-next-badge__title {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
}
.dw-next-badge__count { font-size: 10px; color: var(--ink-3); }
.dw-next-badge__bar {
  height: 4px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  overflow: hidden;
}
.dw-next-badge__fill {
  height: 100%;
  background: var(--accent);
  border-radius: 2px;
  transition: width 240ms ease;
}
.dw-next-badge__desc {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--ink-3);
  letter-spacing: 0.4px;
}

/* ---------- Reading rhythm (heatmap section) ---------- */
.dw-rhythm {
  position: relative;
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 12px;
  padding: 20px 22px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.dw-rhythm__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.dw-rhythm__sub { color: var(--ink-3); margin-top: 4px; font-size: 11px; }
.dw-rhythm__streak { text-align: right; }
.dw-rhythm__streak-figure {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  color: var(--accent);
}
.dw-rhythm__streak-figure .dw-icon {
  width: 16px;
  height: 16px;
  align-self: center;
  position: relative;
  top: 1px;
}
.dw-rhythm__streak-num {
  font-family: var(--font-display);
  font-size: 32px;
  color: var(--ink);
  line-height: 1;
  letter-spacing: -0.01em;
}
.dw-rhythm__streak-unit {
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--ink-3);
}
.dw-rhythm__streak-sub {
  font-size: 10px;
  color: var(--ink-3);
  margin-top: 4px;
}

/* The heatmap itself sits inside .dw-streak alongside the day-of-week
   labels. Two-column flex: left rail is the labels (collapses below the
   grid on narrow screens), right is the cell grid. */
.dw-streak {
  display: flex;
  align-items: stretch;
  gap: 10px;
}
.dw-streak__rows {
  display: grid;
  grid-template-rows: repeat(7, 1fr);
  font-size: 9px;
  color: var(--ink-3);
  letter-spacing: 0.5px;
}
.dw-streak__row-label { line-height: 1; align-self: center; }
.dw-streak__head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 12px;
}
/* GitHub-contribution-style heatmap: each column is a week (oldest left,
   today's week right), each row a weekday (Sun..Sat top→bottom). The
   server emits cells in column-first order, so `grid-auto-flow: column`
   lays them out without extra markup. Keep in sync with
   profile.StreakWindowWeeks (Go) — bumping the window only requires
   changing that constant + this `repeat()` count. */
.dw-streak__grid {
  display: grid;
  grid-template-columns: repeat(30, 1fr);
  grid-template-rows: repeat(7, 1fr);
  grid-auto-flow: column;
  gap: 3px;
  flex: 1;
}
.dw-streak__day {
  aspect-ratio: 1;
  border-radius: 3px;
  border: 0.5px solid var(--line);
  background: var(--surface-2);
  display: block;
  transition: transform 120ms ease, box-shadow 120ms ease;
}
.dw-streak__day[data-level="1"] { background: color-mix(in oklab, var(--accent) 22%, var(--surface-2)); }
.dw-streak__day[data-level="2"] { background: color-mix(in oklab, var(--accent) 42%, var(--surface-2)); }
.dw-streak__day[data-level="3"] { background: color-mix(in oklab, var(--accent) 65%, var(--surface-2)); }
.dw-streak__day[data-level="4"] { background: var(--accent); }
.dw-streak__grid .dw-streak__day:hover {
  transform: scale(1.18);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent);
  z-index: 1;
}
/* Future-dated cells (the trailing days in the current week, after today)
   render as a dotted placeholder so the calendar shape stays rectangular
   without implying "no reads on a day that hasn't happened yet". */
.dw-streak__day.is-future {
  background: transparent;
  border-style: dashed;
  opacity: 0.5;
}

.dw-streak__legend {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 10px;
  color: var(--ink-3);
  margin-left: 38px; /* aligns the swatches with the grid, after row labels */
}
.dw-streak__legend .dw-streak__day {
  width: 11px;
  height: 11px;
  flex: 0 0 11px;
  border-radius: 2px;
  aspect-ratio: auto;
}

/* Tooltip: positioned absolutely against the .dw-rhythm host. Shown by
   the inline JS when a cell is hovered/focused; hidden otherwise. */
.dw-tooltip {
  position: absolute;
  pointer-events: none;
  background: var(--ink);
  color: var(--surface);
  border-radius: 6px;
  padding: 8px 10px;
  font-family: var(--font-ui);
  font-size: 11px;
  line-height: 1.3;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
  min-width: 110px;
  z-index: 5;
}
.dw-tooltip[hidden] { display: none; }
.dw-tooltip__date {
  font-weight: 600;
  letter-spacing: 0.1px;
}
.dw-tooltip__body {
  font-family: var(--font-mono);
  font-size: 10px;
  color: color-mix(in srgb, var(--surface) 70%, transparent);
  margin-top: 2px;
}
/* Pointer triangle below the tooltip */
.dw-tooltip::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -4px;
  width: 8px;
  height: 8px;
  background: var(--ink);
  transform: translateX(-50%) rotate(45deg);
  border-radius: 1px;
}

/* ---------- Insights cards (Reading life) ---------- */
.dw-insights {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.dw-insights__head {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.dw-insights__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
.dw-insight {
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 12px;
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  position: relative;
}
.dw-insight__icon {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 10px;
}
.dw-insight__icon .dw-icon { width: 14px; height: 14px; }
.dw-insight__value {
  font-family: var(--font-display);
  font-size: 26px;
  color: var(--ink);
  line-height: 1.05;
  letter-spacing: -0.01em;
  /* prevent very long top-source values from breaking the grid */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dw-insight__label {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--ink-3);
  letter-spacing: 1px;
  text-transform: uppercase;
  margin-top: 4px;
}
.dw-insight__sub {
  font-family: var(--font-ui);
  font-size: 11px;
  color: var(--ink-3);
  margin-top: 2px;
}

.dw-profile-lists { display: flex; flex-direction: column; gap: 12px; }

@media (max-width: 900px) {
  .dw-insights__grid { grid-template-columns: repeat(2, 1fr); }
  .dw-rhythm__head { flex-direction: column; align-items: flex-start; }
  .dw-rhythm__streak { text-align: left; }
}
@media (max-width: 600px) {
  .dw-streak__rows { display: none; }
  .dw-streak__legend { margin-left: 0; }
}

@media (max-width: 1024px) {
  .dw-publish { grid-template-columns: 1fr; }
  .dw-publish__rail { border-top: 0.5px solid var(--line); }
  .dw-reader__rail { display: none; }
}
@media (max-width: 720px) {
  .dw-reader__list { display: none; }
}

/* ---------- Feeds — page additions for verticals catalog + manual add ---------- */

/* Notice / error banners on /feeds. Reuses .dw-banner base; modifiers
   recolor for success vs. warning. The base .dw-banner uses accent colors,
   so dw-banner--ok overrides to the "good" token. */
.dw-banner--ok {
  background: color-mix(in srgb, var(--good) 18%, transparent);
  color: var(--good);
}
.dw-banner--warn {
  background: color-mix(in srgb, var(--warn) 18%, transparent);
  color: var(--warn);
}

/* Manual-add section: a single URL input + button, with a hint underneath. */
.dw-feeds__add {
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 10px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.dw-feeds__add-form {
  display: flex;
  align-items: center;
  gap: 10px;
}
.dw-feeds__add-form .dw-icon { color: var(--ink-3); flex-shrink: 0; }
.dw-feeds__add-input {
  flex: 1;
  border: 0;
  background: transparent;
  font-family: var(--font-ui);
  font-size: 14px;
  color: var(--ink);
  outline: none;
  padding: 6px 0;
  min-width: 0;
}
.dw-feeds__add-input::placeholder { color: var(--ink-4); }
.dw-feeds__hint { margin: 0; }

/* Vertical card highlight when the user is subscribed. */
.dw-connector.is-on {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent-soft);
}
.dw-connector.is-on .dw-connector__icon {
  background: var(--accent-soft);
  color: var(--accent-ink);
}
.dw-connector__body { flex: 1; min-width: 0; }
.dw-connector__blurb {
  margin-top: 4px;
  font-size: 11px;
  color: var(--ink-3);
  line-height: 1.4;
}

/* Stack title + site URL inside the subscription row's name cell. */
.dw-source-row__name {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  overflow: hidden;
}
.dw-source-row__name a {
  color: var(--ink-3);
  text-decoration: none;
  font-size: 11px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dw-source-row__name a:hover { color: var(--accent); }

/* The subscription row's last column is a remove button, not a toggle —
   match dw-row-actions visual treatment. */
.dw-source-row .dw-row-actions { opacity: 0.6; justify-self: end; }
.dw-source-row:hover .dw-row-actions { opacity: 1; }

/* ---------- Preset cards (Common sources) ---------- */

/* Top-level section headings on the feeds page (Verticals, Your feeds,
   Common sources) sit a notch above the sub-group labels nested under
   Common sources, so their visual hierarchy reads. */
.dw-feeds > .dw-label { font-size: 12px; letter-spacing: 1.6px; }

.dw-preset-group { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }

/* Full-width stack — one preset per row, spanning the content column. */
.dw-preset-list { display: flex; flex-direction: column; gap: 8px; }
.dw-preset-group__name {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-left: 2px;
}

/* Both fixed and parameterized cards share the base look. Parameterized
   cards are <details>; fixed cards are <form>. Same visual treatment. */
.dw-preset {
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 8px;
  padding: 12px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--ink);
  min-width: 0;
}
.dw-preset__icon {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: var(--surface-2);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--ink-2);
}
.dw-preset__label {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Fixed presets: form with one button at the end, no chevron. */
.dw-preset--fixed { /* nothing extra; default flex row */ }
.dw-preset--fixed button {
  flex-shrink: 0;
  padding: 4px 8px;
  min-width: 0;
}

/* Parameterized: <details>/<summary>. Summary is the row; expanded form
   appears below. Pad the form area; reset details default cursor. */
.dw-preset--param { padding: 0; flex-direction: column; align-items: stretch; gap: 0; }
.dw-preset--param > summary {
  padding: 12px;
  display: flex;
  align-items: center;
  gap: 10px;
  list-style: none;
  cursor: pointer;
  user-select: none;
}
.dw-preset--param > summary::-webkit-details-marker { display: none; }
.dw-preset--param > summary .dw-icon:last-child {
  color: var(--ink-3);
  transition: transform .15s ease;
  flex-shrink: 0;
}
.dw-preset--param[open] > summary .dw-icon:last-child { transform: rotate(180deg); }
.dw-preset--param[open] > summary { border-bottom: 0.5px solid var(--line); }

.dw-preset__form {
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.dw-preset__hint {
  margin: 0;
  font-size: 11px;
  color: var(--ink-3);
  line-height: 1.4;
}
.dw-preset__field { display: flex; flex-direction: column; gap: 4px; }
.dw-preset__field-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.4px;
  color: var(--ink-3);
  text-transform: uppercase;
}
.dw-preset__field-input {
  border: 0.5px solid var(--line-2);
  border-radius: 6px;
  padding: 8px 10px;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 13px;
  outline: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.dw-preset__field-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.dw-preset__field-input:invalid:not(:placeholder-shown) {
  border-color: var(--warn);
}
.dw-preset__form button { align-self: flex-start; }

/* ---------- Discover (feed-item firehose) ---------- */

/* The flat single-row firehose styles (.dw-discover__list, .dw-discover-row*)
   and the centered pager rule were retired when the page moved to the
   richer .dw-feedrow card-row design. .dw-discover__more is now defined
   under "Discover: hero + firehose polish" with a space-between layout;
   .dw-discover__empty (just below) is still used by the new template. */

.dw-discover__empty {
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 10px;
  padding: 32px 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-start;
}
.dw-discover__empty .dw-meta { line-height: 1.5; max-width: 60ch; }
.dw-discover__empty a { color: var(--accent); }

/* ---------- Lists ---------- */

/* Sidebar headings rendered as a link to /lists keep the underline-free
   inheritance the rest of the rail uses. */
.dw-nav__heading--link { color: var(--ink-4); cursor: pointer; }
.dw-nav__heading--link:hover { color: var(--ink-3); }

.dw-page__head--list { align-items: center; gap: 12px; }
.dw-back { font-family: var(--font-mono); font-size: 11px; color: var(--ink-3); }
.dw-back:hover { color: var(--ink); }

.dw-page.dw-lists,
.dw-page.dw-list-edit,
.dw-page.dw-list-public,
.dw-page.dw-user-public { padding: 32px 48px 40px; display: flex; flex-direction: column; gap: 20px; }
.dw-lists__grid { gap: 18px; }

/* List cards on /lists and /@user pages. The cover area sits flush with the
   card edges; the body picks up where the existing .dw-list-card rules
   leave off so we don't restate them here. */
.dw-list-card { color: inherit; }
.dw-list-card__cover {
  position: relative;
  height: 132px;
  overflow: hidden;
  background: var(--surface-2);
}
.dw-list-card__cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.dw-list-card__cover-fallback {
  width: 100%;
  height: 100%;
  background-image:
    repeating-linear-gradient(45deg, var(--hatch) 0, var(--hatch) 1px, transparent 1px, transparent 9px),
    linear-gradient(135deg, var(--surface-2) 0%, var(--surface-3) 100%);
}
.dw-list-card__title {
  font-family: var(--font-display);
  font-size: 22px;
  line-height: 1.15;
  letter-spacing: -0.005em;
  color: var(--ink);
}
.dw-list-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-left: auto;
}

/* Form pages — /lists/new and /lists/{id}. Two-column layout for the
   editor; single column for the create form. */
.dw-list-edit__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 28px;
  align-items: start;
}
@media (max-width: 1100px) {
  .dw-list-edit__layout { grid-template-columns: 1fr; }
}
.dw-list-edit__main { display: flex; flex-direction: column; gap: 18px; }
.dw-list-edit__rail {
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 10px;
  padding: 18px;
  position: sticky;
  top: 18px;
}
.dw-list-edit__cover {
  background: var(--surface-2);
  border-radius: 8px;
  overflow: hidden;
  aspect-ratio: 16 / 10;
}
.dw-list-edit__cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dw-list-edit__cover-empty {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  background-image:
    repeating-linear-gradient(45deg, var(--hatch) 0, var(--hatch) 1px, transparent 1px, transparent 9px),
    var(--surface-2);
}
.dw-list-edit__url {
  font-size: 11px;
  color: var(--ink-3);
  background: var(--surface-2);
  padding: 8px 10px;
  border-radius: 4px;
  word-break: break-all;
}

.dw-cover-form {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.dw-cover-form input[type="file"] {
  font-size: 11px;
  color: var(--ink-3);
  flex: 1 1 160px;
  min-width: 0;
}
/* The browser's native "Choose file" button is the only part of the file
   input we can style cross-browser (::file-selector-button is supported
   in all current evergreens). Match the dw-btn-soft palette so the
   trigger sits next to Upload without looking like a system widget. */
.dw-cover-form input[type="file"]::file-selector-button {
  appearance: none;
  -webkit-appearance: none;
  border: 0.5px solid var(--line-2);
  background: var(--surface);
  color: var(--ink-2);
  font-family: var(--font-ui);
  font-size: 12px;
  padding: 6px 10px;
  border-radius: 4px;
  cursor: pointer;
  margin-right: 8px;
  transition: border-color .15s ease, color .15s ease;
}
.dw-cover-form input[type="file"]::file-selector-button:hover {
  border-color: var(--line-3);
  color: var(--ink);
}

.dw-list-form { display: flex; flex-direction: column; gap: 14px; }
.dw-list-form__title {
  font-family: var(--font-display);
  font-size: 32px;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--ink);
  background: transparent;
  border: none;
  outline: none;
  padding: 4px 0;
  border-bottom: 0.5px solid var(--line);
}
.dw-list-form__title:focus { border-bottom-color: var(--line-3); }
.dw-list-form__desc,
.dw-list-form__tags,
.dw-list-form__slug {
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--ink);
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 6px;
  padding: 8px 10px;
  outline: none;
  resize: vertical;
}
.dw-list-form__desc:focus,
.dw-list-form__tags:focus,
.dw-list-form__slug:focus { border-color: var(--line-2); }
.dw-list-form__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.dw-list-form__actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  align-items: center;
  margin-top: 6px;
}

.dw-field { display: flex; flex-direction: column; gap: 6px; border: none; padding: 0; margin: 0; }
.dw-field--inline { gap: 4px; }
.dw-field .dw-label { padding-left: 2px; }

.dw-visibility { display: flex; flex-direction: column; gap: 6px; }
.dw-visibility .dw-radio {
  align-items: flex-start;
  padding: 10px;
  border: 0.5px solid var(--line);
  position: relative; /* contain the absolutely-positioned native input */
}
/* Hide the native input but keep it focusable; the label wraps it so
   clicks anywhere on the row toggle the underlying radio. */
.dw-visibility .dw-radio input[type="radio"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.dw-radio__body { display: flex; flex-direction: column; gap: 2px; }
.dw-radio__title { font-size: 13px; color: var(--ink-2); font-weight: 500; }
.dw-radio.is-on .dw-radio__title { color: var(--accent-ink); }
.dw-radio__desc { font-size: 11px; color: var(--ink-3); }
.dw-radio.is-on .dw-radio__desc { color: var(--accent-ink); opacity: 0.85; }

/* Live visual state — follows the actual <input> checked state so the
   selection updates without JS. The .is-on class is still rendered
   server-side as a fallback for browsers without :has() support. */
.dw-radio:has(input:checked) {
  background: var(--accent-soft);
  color: var(--accent-ink);
  border-color: color-mix(in srgb, var(--accent) 30%, var(--line-2));
}
.dw-radio:has(input:checked) .dw-radio__dot { border-color: var(--accent); }
.dw-radio:has(input:checked) .dw-radio__dot::after {
  content: '';
  position: absolute;
  inset: 2px;
  background: var(--accent);
  border-radius: 50%;
}
.dw-radio:has(input:checked) .dw-radio__title { color: var(--accent-ink); }
.dw-radio:has(input:checked) .dw-radio__desc { color: var(--accent-ink); opacity: 0.85; }
.dw-radio:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* List items inside the editor. Numbered rows that mirror the public
   list rendering so the owner sees what the public will see. */
.dw-list-items { display: flex; flex-direction: column; gap: 8px; }
.dw-list-item {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 12px 14px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 8px;
}
.dw-list-item__num {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-4);
  width: 22px;
  flex-shrink: 0;
  padding-top: 2px;
}
.dw-list-item__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.dw-list-item__title {
  font-family: var(--font-display);
  font-size: 17px;
  color: var(--ink);
  line-height: 1.25;
}
.dw-list-item__title:hover { color: var(--accent); }
.dw-list-item__note { font-size: 12px; color: var(--ink-2); font-style: italic; line-height: 1.5; }
/* The remove (X) button on each item — small and muted, brightens on
   hover. Matches dw-row-actions' palette so the editor and library
   tables share visual treatment. */
.dw-list-item .dw-inline-form button {
  appearance: none;
  border: none;
  background: transparent;
  padding: 4px;
  border-radius: 4px;
  color: var(--ink-3);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.dw-list-item .dw-inline-form button:hover {
  background: var(--surface-2);
  color: var(--ink);
}

/* Library picker on the editor page — a compact list of every save the
   user has, with one-click add. is-in dims rows already in the list. */
.dw-list-picker { display: flex; flex-direction: column; gap: 4px; max-height: 360px; overflow-y: auto; }
.dw-list-picker__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 12px;
  align-items: center;
  padding: 8px 10px;
  border-radius: 6px;
}
.dw-list-picker__row:hover { background: var(--surface-2); }
.dw-list-picker__row.is-in { opacity: 0.55; }
.dw-list-picker__title { font-size: 13px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dw-list-picker__src { font-size: 10px; color: var(--ink-3); white-space: nowrap; }

/* Public list page — /@user/slug. Two-row header (cover + meta), then a
   numbered ordered list. */
.dw-list-public { max-width: 880px; margin: 0 auto; }
.dw-list-public__head {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 24px;
  align-items: end;
}
@media (max-width: 720px) {
  .dw-list-public__head { grid-template-columns: 1fr; }
}
.dw-list-public__cover {
  aspect-ratio: 4 / 3;
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface-2);
  border: 0.5px solid var(--line);
}
.dw-list-public__cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dw-list-public__cover-fallback {
  width: 100%; height: 100%;
  background-image:
    repeating-linear-gradient(45deg, var(--hatch) 0, var(--hatch) 1px, transparent 1px, transparent 9px),
    linear-gradient(135deg, var(--surface-2) 0%, var(--surface-3) 100%);
}
.dw-list-public__meta { display: flex; flex-direction: column; gap: 10px; }
.dw-display--list { font-size: 38px; line-height: 1.1; letter-spacing: -0.01em; margin: 0; }
.dw-list-public__blurb {
  font-size: 16px;
  color: var(--ink-2);
  line-height: 1.5;
  font-style: italic;
  margin: 0;
  max-width: 56ch;
}
.dw-list-public__byline { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-3); }
.dw-list-public__byline strong { color: var(--ink); font-weight: 500; }
.dw-list-public__tags { display: flex; flex-wrap: wrap; gap: 4px; }
.dw-list-public__owner-actions { display: flex; gap: 8px; }
.dw-list-public__items {
  list-style: none;
  margin: 24px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.dw-list-public__item {
  display: flex;
  gap: 14px;
  padding: 16px 0;
  border-top: 0.5px solid var(--line);
}
.dw-list-public__num {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-4);
  width: 28px;
  flex-shrink: 0;
  padding-top: 4px;
}
.dw-list-public__item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.dw-list-public__title {
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--ink);
  line-height: 1.2;
  letter-spacing: -0.005em;
}
.dw-list-public__title:hover { color: var(--accent); }
.dw-list-public__note { font-size: 13px; color: var(--ink-2); font-style: italic; line-height: 1.55; margin: 4px 0 0; max-width: 60ch; }
.dw-list-public__excerpt { font-size: 12px; color: var(--ink-3); line-height: 1.55; margin: 4px 0 0; max-width: 60ch; }

/* User profile (public) — /@username. Header + grid of public list cards. */
.dw-user-public__head { display: flex; align-items: center; gap: 14px; }
.dw-user-public__meta { display: flex; flex-direction: column; gap: 2px; }
.dw-avatar--sm { width: 22px; height: 22px; border-radius: 11px; font-size: 11px; }
.dw-avatar--lg { width: 56px; height: 56px; border-radius: 28px; font-size: 24px; flex-shrink: 0; }

/* Library row's "Add to list" picker. <details> + <summary> for the
   no-JS disclosure; the panel positions absolutely below the trigger so
   the row's grid stays unaffected. */
.dw-rowmenu { position: relative; display: inline-flex; }
.dw-rowmenu summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 4px;
  border-radius: 4px;
  color: var(--ink-3);
}
.dw-rowmenu summary::-webkit-details-marker { display: none; }
.dw-rowmenu summary:hover { color: var(--ink); background: var(--surface-2); }
.dw-rowmenu[open] summary { color: var(--ink); background: var(--surface-2); }
.dw-rowmenu__panel {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  min-width: 200px;
  max-height: 320px;
  overflow-y: auto;
  background: var(--surface);
  border: 0.5px solid var(--line-2);
  border-radius: 8px;
  padding: 6px;
  box-shadow: var(--card-shadow);
  z-index: 10;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.dw-rowmenu__heading {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-4);
  padding: 6px 8px 4px;
}
.dw-rowmenu__row { margin: 0; }
.dw-rowmenu__row button,
.dw-rowmenu__row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 8px;
  border: none;
  background: transparent;
  color: var(--ink-2);
  font-family: var(--font-ui);
  font-size: 12px;
  text-align: left;
  border-radius: 4px;
  cursor: pointer;
  width: 100%;
}
.dw-rowmenu__row button:hover,
.dw-rowmenu__row:hover { background: var(--surface-2); color: var(--ink); }
.dw-rowmenu__row--new { color: var(--ink-3); border-top: 0.5px solid var(--line); padding-top: 8px; margin-top: 4px; }

/* Team share row: team name on the left, R/A buttons on the right.
   The row itself isn't a button so the hover-bg from .dw-rowmenu__row
   doesn't fire for the whole strip — that would muddy the kind buttons'
   own hover states. */
.dw-rowmenu__team-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 4px;
  align-items: center;
  padding: 4px 8px;
  cursor: default;
}
.dw-rowmenu__team-row:hover { background: transparent; color: var(--ink-2); }
.dw-rowmenu__team-name {
  font-size: 12px;
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dw-rowmenu__kind {
  appearance: none;
  border: 0.5px solid var(--line-2);
  background: transparent;
  color: var(--ink-3);
  font: 500 10px/1 var(--font-mono);
  letter-spacing: 0.4px;
  width: 22px;
  height: 22px;
  border-radius: 4px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.dw-rowmenu__kind--soft:hover {
  background: var(--surface-2);
  color: var(--ink);
  border-color: var(--line-3);
}
.dw-rowmenu__kind--warn:hover {
  background: rgba(251, 191, 36, 0.15);
  color: var(--warn);
  border-color: color-mix(in srgb, var(--warn) 35%, var(--line-2));
}

/* Reader toolbar share dropdown opens upward so the panel doesn't
   collide with the article body sitting below the toolbar. The
   surrounding details element keeps left:0 so the panel anchors to the
   button rather than the right edge of the toolbar. */
.dw-toolform__share { position: relative; display: inline-flex; }
.dw-toolform__share summary { list-style: none; cursor: pointer; }
.dw-toolform__share summary::-webkit-details-marker { display: none; }
.dw-rowmenu__panel--up {
  top: auto;
  bottom: calc(100% + 4px);
  left: 0;
  right: auto;
}

/* Buttons — danger and ghost variants the danger zone uses. */
.dw-btn {
  appearance: none;
  border: 0.5px solid var(--line-2);
  background: var(--surface);
  color: var(--ink);
  padding: 9px 14px;
  border-radius: 6px;
  font-family: var(--font-ui);
  font-size: 13px;
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.dw-btn:hover { border-color: var(--line-3); }
.dw-btn--ghost { background: transparent; }
.dw-btn--warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 30%, var(--line-2)); }
.dw-btn--warn:hover { background: color-mix(in srgb, var(--warn) 10%, transparent); }

/* ---------- Profile head extras + Settings ---------- */

.dw-profile-head__actions { display: flex; gap: 8px; align-items: flex-start; }
.dw-profile-head__bio--empty { font-style: normal; }
.dw-profile-head__bio--empty a { color: var(--accent); }

/* Settings is a full-width page like /lists or /library. The form
   itself is bounded so it stays readable on wide screens — the page
   wrapper handles its own padding to match the rest of the app. */
.dw-page.dw-settings { padding: 32px 48px 40px; display: flex; flex-direction: column; gap: 20px; }
.dw-settings__form {
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 10px;
  padding: 22px;
  max-width: 720px;
}
.dw-settings__readonly {
  font-size: 13px;
  color: var(--ink-2);
  background: var(--surface-2);
  padding: 8px 10px;
  border-radius: 4px;
}

/* Label-based toggle used on the settings page. Layout: 36px track
   column + flexible body. The hidden checkbox is stretched to fill the
   label so clicks anywhere on the row toggle it; :has(input:checked)
   tracks the live state so the visual updates without JS. */
.dw-toggle {
  display: grid;
  grid-template-columns: 36px 1fr;
  gap: 12px;
  align-items: flex-start;
  padding: 10px;
  border: 0.5px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
  position: relative; /* contain the absolutely-positioned checkbox */
}
.dw-toggle input[type="checkbox"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.dw-toggle__track {
  width: 30px;
  height: 17px;
  background: var(--line-3);
  border-radius: 10px;
  position: relative;
  flex-shrink: 0;
  margin-top: 2px;
  transition: background .15s ease;
}
.dw-toggle__thumb {
  position: absolute;
  top: 1.5px;
  left: 2px;
  width: 14px;
  height: 14px;
  background: #fff;
  border-radius: 7px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
  transition: left .15s ease;
}
.dw-toggle:has(input:checked) .dw-toggle__track { background: var(--accent); }
.dw-toggle:has(input:checked) .dw-toggle__thumb { left: 14px; }
.dw-toggle__body { display: flex; flex-direction: column; gap: 4px; }
.dw-toggle__title { font-size: 13px; font-weight: 500; color: var(--ink); }
.dw-toggle__desc { font-size: 12px; color: var(--ink-3); line-height: 1.5; }

/* ---------- Discover sections + list-card extras ---------- */

.dw-discover { gap: 24px; }
.dw-discover__section { display: flex; flex-direction: column; gap: 12px; }
.dw-discover__more-row { display: flex; justify-content: center; gap: 10px; padding: 4px 0 4px; }
.dw-section-head { display: flex; align-items: baseline; gap: 10px; }
.dw-section-head .dw-meta a { color: var(--ink-2); }
.dw-section-head .dw-meta a:hover { color: var(--ink); }

/* Card variant used in the Discover hero — adds a byline row + actions
   under the body. The cover and title are anchors so the whole card is
   navigable; the subscribe button stops propagation by being its own
   form element. */
.dw-list-card--with-actions { color: inherit; text-decoration: none; }
.dw-list-card__title {
  font-family: var(--font-display);
  font-size: 22px;
  line-height: 1.15;
  letter-spacing: -0.005em;
  color: var(--ink);
  text-decoration: none;
}
.dw-list-card__title:hover { color: var(--accent); }
.dw-list-card__byline {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  color: var(--ink-3);
}
.dw-list-card__byline a { color: var(--ink-2); }
.dw-list-card__byline a:hover { color: var(--ink); }

/* The subscribe button toggles to a "Subscribed ✓" pill via the on
   modifier — slightly emphasised so the user can see they've followed. */
.dw-btn-soft--on {
  background: var(--accent-soft);
  color: var(--accent-ink);
  border-color: color-mix(in srgb, var(--accent) 35%, var(--line-2));
}
.dw-btn-soft--on:hover {
  border-color: color-mix(in srgb, var(--accent) 50%, var(--line-3));
}

/* Public list page: show the subscribe button + count next to the byline.
   The subscribed-list rows on /feeds reuse .dw-source-row so they get
   styling for free; we just need to handle the bookmark icon color. */
.dw-source-row .dw-source-row__icon { color: var(--ink-3); }

/* ---------- Settings sections ---------- */

.dw-settings__form { gap: 22px; }
.dw-settings__section { display: flex; flex-direction: column; gap: 14px; }
.dw-settings__section + .dw-settings__section {
  padding-top: 22px;
  border-top: 0.5px solid var(--line);
}
/* Section heading inside the form — slightly bigger than the inline
   .dw-label so the form reads as grouped sections, not a flat list. */
.dw-settings__section > .dw-label:first-child {
  font-size: 11px;
  letter-spacing: 1.6px;
  color: var(--ink-2);
  margin-bottom: 2px;
}

/* Username field gets a leading "@" prefix that isn't part of the input
   value — purely visual so the user sees what their handle reads as. */
.dw-settings__username {
  display: flex;
  align-items: stretch;
  border: 0.5px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
  overflow: hidden;
}
.dw-settings__username:focus-within { border-color: var(--line-2); }
.dw-settings__username-prefix {
  display: inline-flex;
  align-items: center;
  padding: 0 10px;
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink-3);
  background: var(--surface-2);
  border-right: 0.5px solid var(--line);
}
.dw-settings__username-input {
  flex: 1;
  border: none;
  border-radius: 0;
  background: transparent;
}
.dw-settings__username-input:focus { border: none; }

/* The "URLs will change" line under the username field — muted but
   visually distinct from the regular helper text so users notice it. */
.dw-settings__warn {
  color: var(--warn);
  border-left: 2px solid color-mix(in srgb, var(--warn) 50%, transparent);
  padding-left: 8px;
  margin-top: 2px;
}

/* ---------- Library: insights popover ---------- */

/* dw-pill--xs is a smaller chip variant kept around as a utility (the
   popover's tag chips don't need it, but it's handy elsewhere). */
.dw-pill--xs {
  font-size: 9px;
  padding: 1px 6px;
  letter-spacing: 0.4px;
}

/* The sparkle wrapper is the popover's anchor: position: relative so
   the absolute-positioned panel sits at a known offset from this
   element. Keeping the icon + popover together as siblings means
   wherever the icon lands (depends on title length), the popover
   follows. */
.dw-table__insight {
  position: relative;
  display: inline-flex;
  align-items: center;
  color: var(--ink-4);
  flex-shrink: 0;
  transition: color .15s ease;
}
.dw-table__row:hover .dw-table__insight { color: var(--accent); }

/* Hover popover. Position is set by JS on mousemove so the panel
   follows the cursor inside the row — feels predictable rather than
   "appearing in a fixed place that varies with title length." We use
   position: fixed so the JS-supplied coords are viewport-relative;
   the CSS provides only initial state (hidden) and visual styling. */
.dw-row-popover {
  position: fixed;
  top: 0;
  left: 0;
  width: 320px;
  max-width: calc(100vw - 80px);
  z-index: 30;

  background: var(--surface);
  border: 0.5px solid var(--line-2);
  border-radius: 10px;
  padding: 12px 14px;
  box-shadow: var(--card-shadow);

  display: flex;
  flex-direction: column;
  gap: 10px;

  /* Override inherited inline color/text-decoration from the parent
     <a class="dw-table__title-cell"> link — without these the popover's
     text would render as a link-coloured underlined block. */
  color: var(--ink);
  text-decoration: none;
  font-weight: normal;
  white-space: normal;

  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-4px);
  transition: opacity .12s ease, visibility .12s ease, transform .12s ease;
}
.dw-table__row.has-insights .dw-table__title-cell:hover .dw-row-popover,
.dw-table__row.has-insights .dw-table__title-cell:focus-within .dw-row-popover {
  visibility: visible;
  opacity: 1;
  transform: translateY(0);
  /* Small delay on appearance so the panel doesn't flash when the
     mouse is just passing through the title — no delay on disappearance,
     the panel should feel snappy to dismiss. */
  transition-delay: 0.25s, 0.25s, 0.25s;
}
.dw-row-popover__section {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.dw-row-popover__gain {
  font-family: var(--font-reader);
  font-size: 12px;
  line-height: 1.45;
  color: var(--ink);
  font-style: italic;
}
.dw-row-popover__summary {
  font-family: var(--font-reader);
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--ink-2);
}
.dw-row-popover__tags { display: flex; flex-wrap: wrap; gap: 4px; }

/* ---------- Library: toolbar (search + sort) + favicon + pager ---------- */

.dw-library__toolbar {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

/* Search field. Full-width on the left, compact icon-prefixed input.
   Submits via GET so the URL stays shareable; hidden inputs in the
   form preserve the active filter/tag/sort. */
.dw-library__search {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 280px;
  max-width: 480px;
  padding: 7px 10px;
  border-radius: 6px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  color: var(--ink-3);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.dw-library__search:focus-within {
  border-color: var(--line-2);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.dw-library__search-input {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  font: 12px/1.4 var(--font-ui);
  color: var(--ink);
}
.dw-library__search-input::placeholder { color: var(--ink-4); }

/* Sort chip strip. Sits to the right of search, label + chips inline.
   Reuses dw-chip / dw-chip--sm so the visual matches the filter row. */
.dw-library__sorts {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.dw-library__sorts .dw-label { margin-right: 4px; }

/* Favicon next to the title. Same grayscale-on-row-hover treatment as
   the discover row icon, just smaller (14px) so it fits the denser
   library row height. */
.dw-table__favicon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  border-radius: 2px;
  filter: grayscale(0) opacity(1);
  transition: filter .15s ease;
}
.dw-table__row:hover .dw-table__favicon { filter: grayscale(1) opacity(0.7); }

/* Pagination footer. Centered row of Prev / position / Next.
   Disabled buttons are styled inert so the user knows they can't go
   further without us hiding them entirely (avoids layout shift). */
.dw-library__pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 16px 0 4px;
}
.dw-library__pager-pos { color: var(--ink-3); font-size: 11px; }
.dw-btn-soft.is-disabled {
  opacity: 0.4;
  pointer-events: none;
  cursor: default;
}

/* ---------- Reader: Ask chat ---------- */

.dw-ask {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* The display: flex above ties with the UA's [hidden] { display: none }
   on specificity but wins the cascade order, so [hidden] alone wouldn't
   hide the chat panel. Force display:none here so the tab switcher
   actually hides it on Insight / Highlights tabs. */
.dw-ask[hidden] { display: none; }

/* Messages list scrolls within itself so older turns stay accessible
   without pushing the input out of view when the conversation grows. */
.dw-ask__messages {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 480px;
  overflow-y: auto;
  padding: 4px 2px;
}

/* Message bubble. User on the right with the accent tint; assistant on
   the left on a soft surface. pre-wrap preserves newlines from the
   model without us injecting HTML. */
.dw-ask__msg {
  max-width: 92%;
  padding: 8px 10px;
  border-radius: 8px;
  font-size: 12px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-wrap: break-word;
}
.dw-ask__msg--user {
  align-self: flex-end;
  background: var(--accent-soft);
  color: var(--accent-ink);
  border: 0.5px solid color-mix(in srgb, var(--accent) 25%, var(--line-2));
}
.dw-ask__msg--assistant {
  align-self: flex-start;
  background: var(--surface-2);
  color: var(--ink);
  border: 0.5px solid var(--line);
}
.dw-ask__msg--pending { color: var(--ink-3); font-style: italic; }
.dw-ask__msg--error {
  border-color: color-mix(in srgb, var(--warn) 30%, var(--line-2));
  color: var(--warn);
}

.dw-ask__form {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.dw-ask__input {
  font: 12px/1.55 var(--font-ui);
  color: var(--ink);
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 6px;
  padding: 8px 10px;
  outline: none;
  resize: vertical;
  min-height: 56px;
}
.dw-ask__input:focus {
  border-color: var(--line-2);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.dw-ask__actions { display: flex; align-items: center; gap: 6px; }
.dw-ask__hint { font-size: 10px; }
.dw-ask__send { padding: 6px 14px; font-size: 12px; }
.dw-ask__send[disabled] { opacity: 0.5; cursor: not-allowed; }

/* ---------- Teams ---------- */

/* Index + detail share the page padding pattern with /lists. The detail
   page is a 2-column layout (feed + sidebar with members and settings);
   the index reuses .dw-grid-3 cards. */
.dw-page.dw-teams,
.dw-page.dw-team { padding: 32px 48px 40px; display: flex; flex-direction: column; gap: 20px; }
.dw-teams__grid { gap: 18px; }

.dw-team__blurb {
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-2);
  margin: 0;
  max-width: 760px;
}

/* Post-a-pick form sits above the feed, full-width. The URL row is the
   primary affordance; the optional note slips in below as a secondary
   field so the form reads as one block rather than four scattered inputs. */
.dw-team__post {
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 10px;
  padding: 14px;
  box-shadow: var(--card-shadow);
}
.dw-team__post-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 8px;
  align-items: stretch;
}
.dw-team__post-url { font-size: 13px; }
.dw-team__post-note { font-size: 13px; }

/* Native select styled to match .dw-input. Drops the OS chrome and adds
   a chev via background-image so it visually clusters with the URL
   input + post button. */
.dw-team__post-kind {
  appearance: none;
  -webkit-appearance: none;
  padding: 10px 32px 10px 12px;
  background: var(--surface);
  border: 0.5px solid var(--line-2);
  border-radius: 8px;
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--ink);
  cursor: pointer;
  outline: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-3) 50%),
                    linear-gradient(135deg, var(--ink-3) 50%, transparent 50%);
  background-position: calc(100% - 16px) 50%, calc(100% - 11px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.dw-team__post-kind:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* 2-column layout: feed on the left, sticky rail on the right with the
   members roster and settings. Mirrors .dw-list-edit__layout. */
.dw-team__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 28px;
  align-items: start;
}
@media (max-width: 1100px) {
  .dw-team__layout { grid-template-columns: 1fr; }
}

.dw-team__feed { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.dw-team__picks { display: flex; flex-direction: column; gap: 12px; }

/* One pick = one card. Same surface + border + shadow as .dw-list-card so
   feed + library + lists feel like the same product. */
.dw-team__pick {
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 10px;
  padding: 14px 16px;
  box-shadow: var(--card-shadow);
  transition: border-color .15s ease;
}
.dw-team__pick:hover { border-color: var(--line-2); }

.dw-team__pick-head {
  display: flex;
  align-items: center;
  gap: 10px;
}
.dw-team__pick-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.dw-team__pick-by {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--ink);
}
.dw-team__pick-by strong { font-weight: 500; }

/* Card-within-a-card: the article preview area. Surface-2 background sets
   it apart from the pick chrome and matches the muted cell style we use
   for the URL preview in the list editor. */
.dw-team__pick-card {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  background: var(--surface-2);
  border: 0.5px solid var(--line);
  border-radius: 8px;
  color: inherit;
  transition: border-color .15s ease, background .15s ease;
}
.dw-team__pick-card:hover {
  border-color: var(--line-2);
  background: var(--surface-3);
}
.dw-team__pick-card .dw-table__favicon { margin-top: 3px; flex-shrink: 0; }
.dw-team__pick-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.dw-team__pick-title {
  font-family: var(--font-display);
  font-size: 15px;
  line-height: 1.25;
  color: var(--ink);
  word-break: break-word;
}
.dw-team__pick-card:hover .dw-team__pick-title { color: var(--accent); }
.dw-team__pick-host { font-size: 11px; }
.dw-team__pick-excerpt {
  font-size: 12px;
  color: var(--ink-3);
  line-height: 1.5;
  margin-top: 2px;
  /* Two-line clamp keeps cards even-height when excerpts vary. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.dw-team__pick-note {
  font-size: 13px;
  color: var(--ink-2);
  line-height: 1.55;
  font-style: italic;
  margin: 0;
  padding-left: 10px;
  border-left: 2px solid var(--line-2);
}

.dw-team__pick-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  padding-top: 4px;
}
.dw-team__pick-actions .dw-btn-soft { gap: 6px; }
.dw-team__pick-actions .dw-btn-soft .dw-icon { color: var(--ink-3); }
.dw-team__pick-actions .dw-btn-soft:hover { border-color: var(--line-2); }

/* Delete-pick button hides at rest and surfaces on row hover so it
   doesn't shout from every card. Same hover-reveal pattern as the
   library row's archive icon. */
.dw-team__pick-del {
  margin-left: auto;
  opacity: 0;
  transition: opacity .15s ease;
}
.dw-team__pick:hover .dw-team__pick-del,
.dw-team__pick-del:focus-within { opacity: 1; }
.dw-team__pick-del button {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--ink-4);
  cursor: pointer;
  padding: 4px;
  border-radius: 4px;
  display: inline-flex;
}
.dw-team__pick-del button:hover { color: var(--warn); background: var(--surface-2); }

/* Right rail: members + settings. Sticky behaviour mirrors the list
   editor's rail. Two stacked cards rather than one big block so the
   visual rhythm matches the rest of the rail surface in the app. */
.dw-team__side {
  display: flex;
  flex-direction: column;
  gap: 16px;
  position: sticky;
  top: 18px;
}
.dw-team__members,
.dw-team__settings {
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 10px;
  padding: 16px;
}
.dw-team__side-h {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 4px;
  font-weight: 500;
}

.dw-team__roster {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.dw-team__roster-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  border-radius: 8px;
  transition: background .15s ease;
}
.dw-team__roster-row:hover { background: var(--surface-2); }
.dw-team__roster-meta {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  flex: 1;
}
.dw-team__roster-name {
  font-size: 13px;
  color: var(--ink);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dw-team__roster-name:hover { color: var(--accent); }
.dw-team__roster-row form button {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--ink-4);
  cursor: pointer;
  padding: 4px;
  border-radius: 4px;
  display: inline-flex;
  opacity: 0;
  transition: opacity .15s ease, color .15s ease, background .15s ease;
}
.dw-team__roster-row:hover form button,
.dw-team__roster-row form button:focus { opacity: 1; }
.dw-team__roster-row form button:hover { color: var(--warn); background: var(--surface); }

.dw-team__invite {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 10px;
  border-top: 0.5px solid var(--line);
}
.dw-team__invite-row {
  display: flex;
  align-items: stretch;
  gap: 6px;
}
.dw-team__invite-input { flex: 1; min-width: 0; font-size: 13px; padding: 8px 10px; }
.dw-team__invite-row .dw-btn-soft { padding: 0 10px; }

.dw-team__settings-form .dw-input {
  font-size: 13px;
  padding: 8px 10px;
}
.dw-team__delete {
  margin-top: 10px;
  padding-top: 12px;
  border-top: 0.5px solid var(--line);
}
.dw-team__delete-btn {
  width: 100%;
  font-size: 12px;
  padding: 8px 12px;
  color: var(--ink-3);
}
.dw-team__delete-btn:hover { color: var(--warn); border-color: var(--line-3); }

/* Source provenance badge on the library row title cell. Matches the
   muted-mono pill family already used for "Fetching…" / "Failed". */
.dw-pill--src {
  text-transform: none;
  letter-spacing: 0.2px;
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 500;
  color: var(--ink-3);
}
.dw-pill--src a { color: var(--ink-2); border-bottom: 0.5px solid var(--line-2); }
.dw-pill--src a:hover { color: var(--accent); border-bottom-color: var(--accent); }

/* ---------- Add-to-list modal (reader right-rail CTA) ----------

   Native <dialog> handles centering + backdrop on its own; we just
   skin the surface and the inner sections. The .dw-modal class is
   reserved for the older wrapper-div annotation modal — see
   .dw-modal { position: fixed; inset: 0 } above — so this dialog
   stands alone with its own root class. */
/* Skin only — the surface itself stays display:none until the dialog is
   opened. Setting display: flex unconditionally would override the
   user-agent rule and leave the modal sitting in the page flow after a
   form-POST round-trip (the redirected page has no JS state, so the
   dialog isn't reopened). The [open] guard scopes the flex layout so
   the closed dialog truly disappears. */
.dw-list-modal {
  border: 0.5px solid var(--line-2);
  border-radius: 14px;
  background: var(--surface);
  color: var(--ink);
  padding: 0;
  width: min(92vw, 520px);
  max-height: min(80vh, 640px);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.22);
  overflow: hidden;
}
.dw-list-modal[open] {
  display: flex;
  flex-direction: column;
}
.dw-list-modal::backdrop {
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(2px);
}
.dw-list-modal__head {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 18px 20px 12px;
  border-bottom: 0.5px solid var(--line);
}
.dw-list-modal__heading { flex: 1; min-width: 0; }
.dw-list-modal__article {
  margin-top: 4px;
  color: var(--ink-3);
  font-size: 11px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dw-list-modal__close {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--ink-3);
  cursor: pointer;
  padding: 4px;
  border-radius: 6px;
  line-height: 0;
}
.dw-list-modal__close:hover { color: var(--ink); background: var(--surface-2); }

.dw-list-modal__body {
  padding: 12px 14px;
  overflow-y: auto;
  flex: 1;
}
.dw-list-modal__rows {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.dw-list-modal__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-radius: 8px;
  border: 0.5px solid transparent;
  transition: background 80ms ease, border-color 80ms ease;
}
.dw-list-modal__row:hover {
  background: var(--surface-2);
  border-color: var(--line);
}
.dw-list-modal__row.is-in { opacity: 0.7; }
.dw-list-modal__row.is-in:hover { background: transparent; border-color: transparent; }
.dw-list-modal__meta { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.dw-list-modal__name {
  font-family: var(--font-ui);
  font-size: 14px;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dw-list-modal__sub {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  color: var(--ink-3);
}

.dw-list-modal__foot {
  padding: 12px 16px 14px;
  border-top: 0.5px solid var(--line);
  display: flex;
  justify-content: flex-end;
}

/* Right-rail CTA was originally an <a>; now it's a <button>. Keep the
   left-aligned visual by neutralising default button styles. */
button.dw-publish-cta {
  appearance: none;
  background: transparent;
  font: inherit;
  text-align: left;
  width: 100%;
  cursor: pointer;
  color: inherit;
}
button.dw-publish-cta:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ---------- Signal page (the daily AI digest) ---------- */

/* History strip — small horizontal date chips above the signal bar so the
   reader can scroll back to past days. Active chip gets the accent fill;
   empty days (no signal generated) render dimmed. */
.dw-signal__history {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.dw-signal__chip {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--ink-3);
  padding: 6px 10px;
  border-radius: 100px;
  border: 0.5px solid var(--line);
  background: var(--surface);
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.dw-signal__chip:hover { border-color: var(--line-2); color: var(--ink); }
.dw-signal__chip.is-active {
  background: var(--accent-soft);
  color: var(--accent-ink);
  border-color: transparent;
}
.dw-signal__chip.is-empty { opacity: 0.55; }

/* Signal bar — the editorial header strip ("3 reads ranked..." + regen
   button). Mirrors the design's accent-soft fill. */
.dw-signal__bar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 18px;
  border-radius: 10px;
  background: var(--accent-soft);
  color: var(--accent-ink);
}
.dw-signal__bar-icon { display: flex; }
.dw-signal__bar-icon .dw-icon { color: var(--accent-ink); }
.dw-signal__bar-text { flex: 1; min-width: 0; }
.dw-signal__bar-title {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
}
.dw-signal__bar-sub {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.4px;
  opacity: 0.75;
  margin-top: 2px;
}
.dw-signal__regen { margin: 0; }
.dw-signal__regen .dw-btn,
.dw-signal__regen-cta .dw-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--surface);
  color: var(--ink);
}
.dw-signal__regen .dw-btn .dw-icon,
.dw-signal__regen-cta .dw-btn .dw-icon { color: var(--accent); }

/* Source badges — tiny pills before each pick title naming the source
   ("From your library" / "From your feeds" / "From your teams"). */
.dw-source-badge {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--ink-3);
  padding: 2px 7px;
  border-radius: 100px;
  background: var(--surface-2);
}

/* Hero title is a link; remove default underline and inherit colour. */
.dw-hero__title-link { color: inherit; text-decoration: none; display: block; }
.dw-hero__title-link:hover .dw-display { color: var(--accent); }

/* Picks in the right rail — numbered prefix + body, mirrors the design's
   "Also ranked high" stack. */
.dw-signal__pick {
  display: flex;
  gap: 14px;
  align-items: flex-start;
}
.dw-signal__pick-rank {
  font-family: var(--font-display);
  font-size: 28px;
  line-height: 1;
  color: var(--ink-3);
  width: 32px;
  flex-shrink: 0;
  letter-spacing: -0.04em;
}
.dw-signal__pick-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.dw-signal__pick:hover .dw-display { color: var(--accent); }

/* Read state — picks the viewer has already finished. Rendered as a
   small "Read" pill in the meta strip plus a dimmed card so finished
   items recede without disappearing. Hover lifts opacity to make the
   destination still feel clickable. */
.dw-signal__pick-tags { display: inline-flex; align-items: center; gap: 6px; }
.dw-pill--read {
  background: var(--surface-2);
  color: var(--ink-3);
  text-transform: uppercase;
  letter-spacing: 1.2px;
  font-family: var(--font-mono);
  font-size: 9px;
}
.dw-hero.is-read,
.dw-signal__pick.is-read { opacity: 0.6; }
.dw-hero.is-read:hover,
.dw-signal__pick.is-read:hover { opacity: 0.85; }

/* Editorial commentary — small pull-quote feel under the hero, sparkle
   accent, italicised body to set it apart from pick whys. */
.dw-signal__commentary {
  padding: 14px 16px;
  border-radius: 10px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.dw-signal__commentary-mark {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 1.4px;
  color: var(--ink-3);
  text-transform: uppercase;
}
.dw-signal__commentary-mark .dw-icon { color: var(--accent); }
.dw-signal__commentary p {
  margin: 0;
  font-family: var(--font-reader);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink-2);
  font-style: italic;
}

/* Empty / pending / failed / disabled state — same shell, different copy. */
.dw-signal__empty {
  padding: 48px 32px;
  border-radius: 10px;
  background: var(--surface);
  border: 0.5px dashed var(--line-2);
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-start;
}
.dw-signal__empty-icon {
  width: 36px;
  height: 36px;
  border-radius: 100px;
  background: var(--accent-soft);
  display: flex;
  align-items: center;
  justify-content: center;
}
.dw-signal__empty-icon .dw-icon { color: var(--accent-ink); }
.dw-signal__empty .dw-lede { max-width: 580px; }
.dw-signal__regen-cta { margin-top: 8px; }
.dw-signal__regen-cta .dw-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.dw-signal__regen-cta .dw-btn .dw-icon { color: var(--accent); }


/* ---------- Signal page — new-user onboarding tour ----------
   Rendered in place of the empty/pending/failed states when the
   viewer has no saves, feed subs, or team memberships. Reuses
   dw-card / dw-pill / dw-btn for visual consistency with the rest
   of the page; only the layout grid and the small "tour mark" disc
   are tour-specific. */

.dw-signal__tour {
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.dw-signal__tour-bar {
  background: var(--accent-soft);
  border-color: var(--accent-line, var(--line-2));
}

.dw-signal__tour-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px;
}

.dw-signal__tour-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 22px;
}

.dw-signal__tour-card .dw-row--meta { margin-top: 4px; flex-wrap: wrap; }

.dw-signal__tour-card--lead {
  grid-column: 1 / -1;
  background: var(--surface);
  border: 0.5px solid var(--line-2);
  gap: 12px;
}

.dw-signal__tour-mark {
  width: 36px;
  height: 36px;
  border-radius: 100px;
  background: var(--accent-soft);
  display: flex;
  align-items: center;
  justify-content: center;
}
.dw-signal__tour-mark .dw-icon { color: var(--accent-ink); }

.dw-signal__tour-foot {
  margin-top: 6px;
  padding: 22px;
  border-radius: 10px;
  border: 0.5px dashed var(--line-2);
  background: var(--surface);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
}
.dw-signal__tour-foot-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }

@media (max-width: 820px) {
  .dw-signal__tour-grid { grid-template-columns: 1fr; }
}


/* ---------- Margins (marginalia explorer) ---------- */

.dw-margins { gap: 26px; }

/* Header — display title on the left, counter strip on the right.
   The strip wraps onto its own line on narrow viewports rather than
   shrinking each counter past readability. */
.dw-margins__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 32px;
  align-items: end;
}
.dw-margins__head-text { display: flex; flex-direction: column; gap: 8px; }
.dw-margins__head-text .dw-meta {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--ink-3);
}
.dw-margins__lede {
  margin: 0;
  font-family: var(--font-reader);
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ink-3);
  max-width: 540px;
}
.dw-margins__counters {
  display: flex;
  gap: 0;
  align-items: stretch;
  border: 0.5px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  overflow: hidden;
}
.dw-counter {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 14px 18px;
  min-width: 88px;
  border-right: 0.5px solid var(--line);
}
.dw-counter:last-child { border-right: none; }
.dw-counter__num {
  font-family: var(--font-display);
  font-size: 26px;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--ink);
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
}
.dw-counter--ghost .dw-counter__num { color: var(--ink-2); }
.dw-counter--accent {
  background: var(--accent-soft);
}
.dw-counter--accent .dw-counter__num {
  color: var(--accent-ink);
  align-items: center;
}
.dw-counter--accent .dw-icon { color: var(--accent); }
.dw-counter__label {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* Section heading — the small label above the spotlight rail. */
.dw-margins__section-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}
.dw-margins__section-head .dw-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-2);
}
.dw-margins__section-head .dw-icon { color: var(--accent); }

/* Spotlight grid — four cards across on wide; collapses to two then one. */
.dw-margins__spot { display: flex; flex-direction: column; }
.dw-margins__spot-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
}
@media (max-width: 1100px) {
  .dw-margins__spot-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .dw-margins__spot-grid { grid-template-columns: 1fr; }
}

/* Toolbar — search box left, type chips right. Mirrors the library
   toolbar but kept its own classes so we can tune spacing without
   pulling library tokens around. */
.dw-margins__toolbar {
  display: flex;
  gap: 14px;
  align-items: center;
  flex-wrap: wrap;
}
.dw-margins__search {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  flex: 1;
  min-width: 240px;
  max-width: 460px;
}
.dw-margins__search .dw-icon { color: var(--ink-3); flex-shrink: 0; }
.dw-margins__search-input {
  border: none;
  outline: none;
  background: transparent;
  color: inherit;
  font: inherit;
  flex: 1;
  min-width: 0;
}
.dw-margins__types { gap: 6px; flex-wrap: wrap; }
.dw-margins__sources { flex-wrap: wrap; }

/* Inline counter inside chips — small dimmed number after the label.
   "Highlights · 42" without an em-dash sigil to keep chip width tight. */
.dw-chip__count {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.6px;
  color: var(--ink-3);
  margin-left: 6px;
  padding-left: 6px;
  border-left: 0.5px solid var(--line-2);
}
.dw-chip.is-active .dw-chip__count {
  color: var(--bg);
  border-left-color: rgba(255,255,255,.25);
}

/* Wall — CSS columns gives us a no-JS masonry. Cards are display:block
   inside columns so they pack tightly without leaving holes. break-inside
   keeps a single card from splitting across columns. */
.dw-margins__wall {
  column-count: 3;
  column-gap: 18px;
}
@media (max-width: 1100px) { .dw-margins__wall { column-count: 2; } }
@media (max-width: 640px)  { .dw-margins__wall { column-count: 1; } }

.dw-margins__wall .dw-margcard {
  break-inside: avoid;
  margin: 0 0 18px;
  display: block;
}

/* Margin card — the unit on both the spotlight rail and the wall. The
   card has three regions stacked: kind tag, body (quote and/or note),
   foot (source + age). */
.dw-margcard {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px 18px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 12px;
  color: var(--ink);
  text-decoration: none;
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
  overflow: hidden;
}
.dw-margcard:hover {
  border-color: var(--line-2);
  transform: translateY(-1px);
  box-shadow: var(--card-shadow);
}

/* Spotlight cards are taller and use a slightly heavier display
   treatment — they're the "look at this!" feature row. */
.dw-margcard--spot {
  min-height: 200px;
  background: var(--surface);
  padding: 18px 20px;
}

/* Highlight cards — a soft yellow stripe spanning the left edge,
   evoking the marker stripe on a paper page. The color is the theme's
   --highlight token so it harmonises in light, dark, and cool modes. */
.dw-margcard--highlight::before,
.dw-margcard--highlight-note::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 4px;
  background: var(--highlight);
}

/* Notes — a folded-corner detail in the upper right. Pure decoration
   via a clip-path triangle rather than a background-image SVG, so it
   scales with theme colour automatically. */
.dw-margcard--note::after {
  content: "";
  position: absolute;
  right: 0;
  top: 0;
  width: 18px;
  height: 18px;
  background: var(--surface-2);
  clip-path: polygon(100% 0, 0 0, 100% 100%);
  border-bottom-left-radius: 4px;
}

/* Kind tag — tiny mono label at the top of every card. Pairs an icon
   with an uppercase string ("HIGHLIGHT", "NOTE", "HIGHLIGHT + NOTE"). */
.dw-margcard__kind {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-3);
}
.dw-margcard--highlight .dw-margcard__kind .dw-icon,
.dw-margcard--highlight-note .dw-margcard__kind .dw-icon {
  color: var(--accent);
}
.dw-margcard--note .dw-margcard__kind .dw-icon {
  color: var(--ink-2);
}

/* Quote text — display font, slightly larger so the underlined passage
   reads like a pull-quote rather than body copy. We cap displayed
   height for very long highlights with line-clamp; the full text is
   one click away (the card opens the article). */
.dw-margcard__quote {
  margin: 0;
  font-family: var(--font-reader);
  font-size: 15px;
  line-height: 1.45;
  color: var(--ink);
  position: relative;
  padding-left: 14px;
  display: -webkit-box;
  -webkit-line-clamp: 7;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.dw-margcard__quote::before {
  content: "\201C"; /* left double quote */
  position: absolute;
  left: -2px;
  top: -8px;
  font-family: var(--font-display);
  font-size: 28px;
  line-height: 1;
  color: var(--ink-4);
}
.dw-margcard--spot .dw-margcard__quote {
  font-size: 16.5px;
  -webkit-line-clamp: 6;
}

/* Note text — slightly smaller than the quote, with a vertical rule
   on the left to read as a marginal annotation. */
.dw-margcard__note {
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-2);
  position: relative;
  padding-left: 14px;
  display: -webkit-box;
  -webkit-line-clamp: 6;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.dw-margcard__note-rule {
  position: absolute;
  left: 0;
  top: 4px;
  bottom: 4px;
  width: 2px;
  background: var(--line-2);
  border-radius: 2px;
}

/* Note-only cards (no quote): bump the body up so the card doesn't
   feel bottom-heavy under the kind tag alone. */
.dw-margcard--note .dw-margcard__note {
  font-size: 14px;
  color: var(--ink);
  -webkit-line-clamp: 9;
}

/* Foot — source + relative time. Always at the bottom; flex-grows
   above push it down so cards in a row align their feet. */
.dw-margcard__foot {
  margin-top: auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding-top: 8px;
  border-top: 0.5px dashed var(--line-2);
  font-size: 11px;
  color: var(--ink-3);
}
.dw-margcard__src {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow: hidden;
}
.dw-margcard__favicon { flex-shrink: 0; opacity: 0.85; }
.dw-margcard__title {
  font-family: var(--font-display);
  font-size: 12.5px;
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 220px;
}
.dw-margcard__source {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Wall card hit area — the whole card is one big anchor so click
   anywhere lands on the article. */
.dw-margcard__hit {
  display: flex;
  flex-direction: column;
  gap: 10px;
  color: inherit;
  text-decoration: none;
}

/* Pager — newer / older buttons under the wall. */
.dw-pager {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  padding-top: 10px;
}
.dw-pager__pos { color: var(--ink-3); }
.dw-btn-soft.is-disabled { opacity: .45; pointer-events: none; }

/* Empty state — large pull-quote glyph as the visual anchor. */
.dw-margins__empty {
  padding: 56px 32px;
  border-radius: 14px;
  background: var(--surface);
  border: 0.5px dashed var(--line-2);
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: flex-start;
  text-align: left;
  position: relative;
  overflow: hidden;
}
.dw-margins__empty-art {
  font-family: var(--font-display);
  color: var(--accent-soft);
  position: absolute;
  right: 32px;
  top: -24px;
  pointer-events: none;
}
.dw-margins__empty-quote {
  font-size: 220px;
  line-height: 1;
  color: var(--accent-soft);
}
.dw-margins__empty .dw-lede { max-width: 560px; }

/* Tighten the page padding on narrow widths so the wall's 1-column
   stack uses the screen efficiently. */
@media (max-width: 640px) {
  .dw-page.dw-margins { padding: 22px 18px 32px; }
  .dw-margins__head { grid-template-columns: 1fr; }
  .dw-margins__counters { flex-wrap: wrap; }
}

/* ---------- Library: hero + page polish ---------- */

/* Page-level rhythm: more vertical air than the default page layout
   gives us, so the hero and toolbar don't crowd the table. */
.dw-page.dw-library { gap: 24px; }

/* Hero — display title + lede on the left, counter strip + actions on
   the right. Same skeleton as the margins hero so the two centerpieces
   share a visual signature. Shrinks gracefully: side rail wraps below
   the text on narrower viewports. */
.dw-library__hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 32px;
  align-items: end;
}
.dw-library__hero-text { display: flex; flex-direction: column; gap: 8px; }
.dw-library__hero-text .dw-meta {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--ink-3);
}
.dw-library__lede {
  margin: 0;
  font-family: var(--font-reader);
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ink-3);
  max-width: 540px;
}
.dw-library__hero-side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
}
.dw-library__counters {
  display: flex;
  align-items: stretch;
  border: 0.5px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  overflow: hidden;
}
/* dw-counter is shared with the margins page; the rules there cover
   number/label typography and the accent variant. We don't redefine. */
.dw-library__newlist { align-self: flex-end; }

/* Toolbar — give the search field a subtle inner shadow and tighten
   the sort row so it feels like one band rather than two zones. */
.dw-library__toolbar { gap: 14px; }
.dw-library__sorts .dw-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* Filter row — bigger chip target, tucked just below the toolbar. The
   filter chip strip is the most-clicked part of the page, so it earns
   slightly more presence than the small tag chips below it. */
.dw-library__filters { gap: 8px; flex-wrap: wrap; }
.dw-library__filters .dw-chip {
  padding: 7px 12px;
  font-size: 12.5px;
  border-radius: 100px;
  background: var(--surface);
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.dw-library__filters .dw-chip:hover {
  border-color: var(--line-3);
  color: var(--ink);
}
.dw-library__filters .dw-chip.is-active {
  background: var(--ink);
  color: var(--bg);
}

/* Tag chips below the filters — leave the existing dw-chip--sm rules
   alone but soften their edge to pill so the strip reads as a related
   secondary band, not a duplicate of the filter row. */
.dw-library .dw-filters--tags .dw-chip--sm {
  border-radius: 100px;
  padding: 3px 9px;
}
.dw-library .dw-filters--tags .dw-chip--sm.is-active {
  background: var(--accent-soft);
  color: var(--accent-ink);
  border-color: transparent;
}

/* Table — lift it onto the surface with a soft shadow and trim the
   border so the card feels deliberate rather than ruled. The head
   keeps its surface-2 wash but loses the harsh bottom-border line in
   favor of a softer divider. */
.dw-library .dw-table {
  border-radius: 14px;
  border: 0.5px solid var(--line);
  box-shadow: var(--card-shadow);
  background: var(--surface);
  position: relative;
  overflow: visible;
}
/* A 1px accent rail at the top edge of the table — a tiny editorial
   flourish that anchors the eye to the start of the data, mirroring
   the highlight stripe the margin cards use. */
.dw-library .dw-table::before {
  content: "";
  position: absolute;
  left: 14px;
  right: 14px;
  top: -1px;
  height: 2px;
  background: linear-gradient(90deg,
    transparent 0%,
    var(--accent) 12%,
    var(--accent) 88%,
    transparent 100%);
  opacity: 0.55;
  border-radius: 2px;
  pointer-events: none;
}

.dw-library .dw-table__head {
  border-radius: 14px 14px 0 0;
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border-bottom: 0.5px solid var(--line);
  letter-spacing: 1.6px;
  font-size: 9.5px;
  padding: 12px 18px;
}

/* Row polish — slightly softer hover, tighter borders, and the title
   font picks up a touch more weight when the row is hovered. */
.dw-library .dw-table__row {
  transition: background .12s ease;
}
.dw-library .dw-table__row:hover {
  background: color-mix(in srgb, var(--surface-2) 70%, var(--surface));
}
.dw-library .dw-table__row:last-child {
  border-radius: 0 0 14px 14px;
}
.dw-library .dw-table__title {
  letter-spacing: -0.005em;
}

/* Source mono cell — slightly lighter so the title carries the weight. */
.dw-library .dw-table__row .dw-mono {
  color: var(--ink-3);
}

/* Pager — center it under the table with a touch more breathing room. */
.dw-library__pager {
  padding: 18px 0 4px;
}

/* Empty state — bigger, more inviting, with a soft accent washed background.
   This replaces the legacy .dw-empty look on this page; other pages keep
   theirs (we scope by .dw-library). */
.dw-library__empty {
  margin-top: 8px;
  padding: 56px 36px;
  border-radius: 16px;
  background: var(--surface);
  border: 0.5px dashed var(--line-2);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  position: relative;
  overflow: hidden;
}
.dw-library__empty::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 100% 0%, var(--accent-soft) 0%, transparent 55%);
  opacity: .6;
  pointer-events: none;
}
.dw-library__empty-art {
  width: 44px;
  height: 44px;
  border-radius: 100px;
  background: var(--accent-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent-ink);
  position: relative;
}
.dw-library__empty-art .dw-icon { color: var(--accent-ink); }
.dw-library__empty .dw-display--lg {
  font-family: var(--font-display);
  font-size: 28px;
  line-height: 1.15;
  margin: 0;
  font-weight: 400;
  position: relative;
}
.dw-library__empty .dw-lede {
  margin: 0;
  max-width: 520px;
  font-family: var(--font-reader);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-3);
  position: relative;
}
.dw-library__empty-link {
  color: var(--accent-ink);
  text-decoration: underline;
  text-decoration-thickness: 0.5px;
  text-underline-offset: 2px;
}

/* Narrower viewports: the side rail stacks under the title text, the
   counter strip wraps so the row doesn't push horizontal scroll. */
@media (max-width: 1100px) {
  .dw-library__hero { grid-template-columns: 1fr; }
  .dw-library__hero-side { align-items: flex-start; }
  .dw-library__newlist { align-self: flex-start; }
}
@media (max-width: 720px) {
  .dw-library__counters { flex-wrap: wrap; }
  .dw-library__counters .dw-counter { flex: 1 1 33%; min-width: 96px; }
}

/* ---------- Discover: hero + firehose polish ---------- */

.dw-page.dw-discover { gap: 26px; }

/* Hero — same skeleton as the library/margins heroes for visual rhyme.
   The accent counter (FreshCount) sits leftmost so the eye lands on
   the energetic "new in 24h" number first. */
.dw-discover__hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 32px;
  align-items: end;
}
.dw-discover__hero-text { display: flex; flex-direction: column; gap: 8px; }
.dw-discover__hero-text .dw-meta {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--ink-3);
}
.dw-discover__lede {
  margin: 0;
  font-family: var(--font-reader);
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ink-3);
  max-width: 540px;
}
.dw-discover__hero-side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
}
.dw-discover__counters {
  display: flex;
  align-items: stretch;
  border: 0.5px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  overflow: hidden;
}
/* dw-counter / dw-counter--accent / dw-counter--ghost are defined once
   under the margins section; we reuse them here verbatim. */

@media (max-width: 1100px) {
  .dw-discover__hero { grid-template-columns: 1fr; }
  .dw-discover__hero-side { align-items: flex-start; }
}
@media (max-width: 720px) {
  .dw-discover__counters { flex-wrap: wrap; }
  .dw-discover__counters .dw-counter { flex: 1 1 40%; min-width: 110px; }
}

/* Section heads — richer variant with a small icon medallion on the
   left and an optional action on the right. The plain
   `.dw-section-head` (label + meta side by side) still works for any
   non-discover page that uses it. */
.dw-section-head--rich {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 4px;
  border-bottom: 0.5px dashed var(--line);
}
.dw-section-head--rich > div {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}
.dw-section-head__icon {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border-radius: 100px;
  background: var(--accent-soft);
  display: flex;
  align-items: center;
  justify-content: center;
}
.dw-section-head__icon .dw-icon { color: var(--accent-ink); }
.dw-section-head--rich .dw-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-2);
}
.dw-section-head--rich .dw-meta {
  font-size: 11px;
  color: var(--ink-3);
}
.dw-section-head__action { flex-shrink: 0; }

/* Vertical filter chip strip — pill-shaped chips with a subtle hover
   lift. The "All" chip uses the same chip class so the active
   treatment is consistent with the per-vertical chips. */
.dw-discover__verticals {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.dw-discover__verticals .dw-chip {
  padding: 6px 12px;
  font-size: 12px;
  border-radius: 100px;
  background: var(--surface);
  border: 0.5px solid var(--line-2);
  transition: background .15s ease, border-color .15s ease, color .15s ease, transform .12s ease;
}
.dw-discover__verticals .dw-chip:hover {
  border-color: var(--line-3);
  color: var(--ink);
  transform: translateY(-1px);
}
.dw-discover__verticals .dw-chip.is-active {
  background: var(--ink);
  color: var(--bg);
  border-color: transparent;
}

/* Firehose list — replace the old flat-row look with richer card-rows.
   Each row gets: a left-edge "rail" (accent on FRESH items), a top
   meta line with feed title + host + relative time + badges, the
   article title (display font, bigger), an optional summary preview,
   and an inline save form on the right. */
.dw-discover__feed {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 4px;
}

.dw-feedrow {
  position: relative;
  display: grid;
  grid-template-columns: 4px minmax(0, 1fr) auto;
  grid-template-rows: auto auto;
  column-gap: 14px;
  row-gap: 6px;
  padding: 14px 16px 14px 0;
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 12px;
  overflow: hidden;
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease, background .15s ease;
}
.dw-feedrow:hover {
  border-color: var(--line-2);
  transform: translateY(-1px);
  box-shadow: var(--card-shadow);
}

/* Left rail — a flat surface-2 strip that flips to the accent color
   when the row is fresh, anchoring the row's left edge with intent. */
.dw-feedrow__rail {
  grid-column: 1;
  grid-row: 1 / -1;
  background: var(--surface-2);
  align-self: stretch;
}
.dw-feedrow.is-fresh .dw-feedrow__rail {
  background: linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent) 50%, var(--surface-2)));
}

.dw-feedrow__main {
  grid-column: 2;
  grid-row: 2;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.dw-feedrow__top {
  grid-column: 2 / 4;
  grid-row: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-3);
  flex-wrap: wrap;
}
.dw-feedrow__favicon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  border-radius: 3px;
  filter: grayscale(0) opacity(1);
  transition: filter .15s ease;
}
.dw-feedrow:hover .dw-feedrow__favicon { filter: grayscale(0.4) opacity(0.85); }
.dw-feedrow__feed {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.4px;
  color: var(--ink-2);
  padding: 2px 8px;
  border-radius: 100px;
  background: var(--surface-2);
  white-space: nowrap;
}
.dw-feedrow__host { color: var(--ink-3); font-size: 10.5px; }
.dw-feedrow__author { color: var(--ink-3); font-size: 10.5px; }
.dw-feedrow__when {
  font-size: 10px;
  color: var(--ink-3);
  margin-left: auto;
  white-space: nowrap;
}

.dw-feedrow__title {
  font-family: var(--font-display);
  font-size: 17px;
  line-height: 1.3;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  letter-spacing: -0.005em;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  transition: color .15s ease;
}
.dw-feedrow__title:hover { color: var(--accent); }

.dw-feedrow__summary {
  margin: 0;
  font-family: var(--font-reader);
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink-3);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* FRESH badge — high-energy accent pill that sits in the meta line.
   Distinguishes within-the-day items at a glance and creates the
   "something new is here" feeling that keeps people scrolling. */
.dw-pill--fresh {
  background: var(--accent);
  color: var(--bg);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 1.4px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 100px;
  text-transform: uppercase;
}

/* Save form — the inline tag input expands when focused so users can
   type without feeling cramped, and the save button is a deliberate
   pill rather than an icon-only square. The whole control sits on
   the right of the row and aligns to the bottom (so the action
   always lands at the row's natural baseline). */
.dw-feedrow__save {
  grid-column: 3;
  grid-row: 2;
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  align-self: center;
  flex-shrink: 0;
}
.dw-feedrow__tag-input {
  width: 110px;
  padding: 7px 10px;
  border: 0.5px solid var(--line-2);
  border-radius: 100px;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 12px;
  outline: none;
  transition: border-color .15s ease, box-shadow .15s ease, width .18s ease;
}
.dw-feedrow__tag-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
  width: 160px;
}
.dw-feedrow__save-btn {
  appearance: none;
  border: 0.5px solid var(--line-2);
  border-radius: 100px;
  background: var(--surface);
  color: var(--ink-2);
  padding: 7px 14px 7px 10px;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  transition: background .12s ease, color .12s ease, border-color .12s ease, transform .12s ease;
}
.dw-feedrow__save-btn:hover {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
  transform: translateY(-1px);
}
.dw-feedrow__save-btn:hover .dw-icon { color: var(--bg); }
.dw-feedrow__save-btn:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.dw-feedrow__save-btn:active { transform: translateY(0); }

/* Narrower viewports: stack the save form below the body so the title
   keeps its full readable width. */
@media (max-width: 820px) {
  .dw-feedrow {
    grid-template-columns: 4px minmax(0, 1fr);
    grid-template-rows: auto auto auto;
  }
  .dw-feedrow__top { grid-column: 2; grid-row: 1; }
  .dw-feedrow__main { grid-column: 2; grid-row: 2; }
  .dw-feedrow__save {
    grid-column: 2;
    grid-row: 3;
    margin-top: 4px;
  }
  .dw-feedrow__when { margin-left: 0; }
}

/* "Load older / Newer" pager — equal-spaced row, disabled state inert. */
.dw-discover__more {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 16px 0 4px;
}

/* Empty firehose — a touch of accent texture and a circular icon
   medallion to soften the "nothing's here" feel. */
.dw-discover__empty {
  background: var(--surface);
  border: 0.5px dashed var(--line-2);
  border-radius: 14px;
  padding: 40px 32px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-start;
  position: relative;
  overflow: hidden;
}
.dw-discover__empty::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 0% 100%, var(--accent-soft) 0%, transparent 50%);
  opacity: .55;
  pointer-events: none;
}
.dw-discover__empty-icon {
  width: 40px;
  height: 40px;
  border-radius: 100px;
  background: var(--accent-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}
.dw-discover__empty-icon .dw-icon { color: var(--accent-ink); }
.dw-discover__empty .dw-meta { line-height: 1.5; max-width: 60ch; position: relative; }
.dw-discover__empty .dw-display--md { position: relative; }
.dw-discover__empty .dw-btn-soft { position: relative; }

/* ==========================================================================
   Welcome modal — post-login onboarding overlay. Renders once per fresh
   login (cleared by the auth middleware on first protected page hit).
   The dismiss form posts to /api/v1/welcome/dismiss; HTMX swaps the
   whole .dw-welcome out via outerHTML so no JS is needed for close.
   ========================================================================== */

.dw-welcome {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  animation: dw-welcome-in .18s ease-out;
}
@keyframes dw-welcome-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.dw-welcome__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(2px);
}

.dw-welcome__panel {
  position: relative;
  width: min(640px, 100%);
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  background: var(--surface);
  border: 0.5px solid var(--line-2);
  border-radius: 14px;
  box-shadow: var(--card-shadow);
  padding: 32px 36px 28px;
  animation: dw-welcome-rise .22s ease-out;
}
@keyframes dw-welcome-rise {
  from { transform: translateY(8px); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}

.dw-welcome__close {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0.5px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--ink-3);
  cursor: pointer;
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.dw-welcome__close:hover {
  background: var(--surface-2);
  color: var(--ink);
  border-color: var(--line-2);
}

.dw-welcome__header { margin-bottom: 18px; }

.dw-welcome__eyebrow {
  margin: 0 0 6px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--accent);
}

.dw-welcome__title {
  margin: 0 0 8px;
  font-family: var(--font-display);
  font-size: 22px;
  line-height: 1.25;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.01em;
}

.dw-welcome__lede {
  margin: 0;
  color: var(--ink-2);
  font-size: 14px;
  line-height: 1.5;
  max-width: 56ch;
}

.dw-welcome__steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.dw-welcome__step {
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: 14px;
  padding: 14px 16px;
  background: var(--surface-2);
  border: 0.5px solid var(--line);
  border-radius: 10px;
}

.dw-welcome__step-num {
  width: 24px;
  height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  margin-top: 2px;
}

.dw-welcome__step-body { min-width: 0; }

.dw-welcome__step-title {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.005em;
}

.dw-welcome__step-body p {
  margin: 0;
  color: var(--ink-2);
  font-size: 13px;
  line-height: 1.5;
}

.dw-welcome__cta-row {
  margin-top: 8px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
}

.dw-welcome__chip {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--surface);
  border: 0.5px solid var(--line-2);
  color: var(--ink);
  font-size: 12px;
  font-weight: 500;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.dw-welcome__chip:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-ink);
}

.dw-welcome__note {
  font-size: 12px;
  color: var(--ink-3);
}
.dw-welcome__note a { color: var(--accent-ink); border-bottom: 0.5px dashed var(--line-2); }
.dw-welcome__note a:hover { border-bottom-color: var(--accent); }

.dw-welcome__step-body code {
  font-family: var(--font-mono);
  font-size: 12px;
  padding: 1px 5px;
  background: var(--surface);
  border: 0.5px solid var(--line);
  border-radius: 4px;
  color: var(--ink);
}

.dw-welcome__footer {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 0.5px solid var(--line);
}

.dw-welcome__dismiss {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.dw-welcome__check {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--ink-2);
  cursor: pointer;
  user-select: none;
}
.dw-welcome__check input[type="checkbox"] {
  width: 14px;
  height: 14px;
  accent-color: var(--accent);
  cursor: pointer;
}

.dw-welcome__primary {
  padding: 10px 18px;
  background: var(--accent);
  color: #fff;
  border: 0;
  border-radius: 8px;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: filter .15s ease, transform .05s ease;
}
.dw-welcome__primary:hover { filter: brightness(1.05); }
.dw-welcome__primary:active { transform: translateY(0.5px); }

@media (max-width: 520px) {
  .dw-welcome { padding: 12px; }
  .dw-welcome__panel { padding: 24px 20px 20px; }
  .dw-welcome__title { font-size: 19px; }
  .dw-welcome__step { padding: 12px; }
}

