/* trove — dark console
   ------------------------------------------------------------------
   Near-black ground, raised panels, one accent colour per meaning, and
   numbers given real weight. Type is Plus Jakarta Sans: geometric,
   slightly warm, and deliberately not a system stack.
*/

:root {
  /* ground and surfaces */
  --bg:        #16171b;
  --panel:     #292c31;
  --panel-2:   #31353b;
  --line:      #3a3f46;
  --line-soft: #32363c;

  /* type */
  --ink:   #ffffff;
  --ink-2: #b9bfc8;
  --ink-3: #7d848f;

  /* one colour per meaning */
  --violet: #8f44f2;
  --pink:   #f6459c;
  --red:    #f91302;
  --green:  #19c46f;
  --blue:   #0082f5;

  --violet-dim: rgba(143, 68, 242, .14);
  --pink-dim:   rgba(246, 69, 156, .14);
  --red-dim:    rgba(249, 19, 2, .13);
  --green-dim:  rgba(25, 196, 111, .13);
  --blue-dim:   rgba(0, 130, 245, .14);

  --radius:    16px;
  --radius-sm: 10px;
  --sidebar:   248px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: "Plus Jakarta Sans", "Segoe UI", system-ui, sans-serif;
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--blue); text-decoration: none; }
a:hover { text-decoration: underline; }

h1 { font-size: 26px; font-weight: 800; letter-spacing: -.02em; margin: 0 0 6px; }
h2 {
  font-size: 12px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .09em; color: var(--ink-3); margin: 0 0 14px;
}

.muted { color: var(--ink-2); }
.small { font-size: 13px; }
.strong { font-weight: 600; }
.hint { color: var(--ink-3); font-size: 12.5px; margin: 8px 0 0; font-weight: 400; }
.crumb { color: var(--ink-3); font-size: 12.5px; margin: 0 0 4px; }
.crumb a { color: var(--ink-2); }

/* --- shell ---------------------------------------------------------- */

.shell { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar); flex: 0 0 var(--sidebar);
  background: var(--panel); border-right: 1px solid var(--line-soft);
  padding: 20px 14px; display: flex; flex-direction: column; gap: 3px;
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
}

.brand {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 10px 18px; color: var(--ink);
}
.brand:hover { text-decoration: none; }
.brand-mark {
  width: 30px; height: 30px; border-radius: 9px; flex: 0 0 30px;
  background: linear-gradient(135deg, var(--violet), var(--pink));
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 15px; color: #fff;
}
.brand-name { font-weight: 800; font-size: 16px; letter-spacing: -.01em; }

.nav-label {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .1em; color: var(--ink-3); padding: 16px 12px 6px;
}
.nav-item {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 12px; border-radius: var(--radius-sm);
  color: var(--ink-2); font-weight: 500; font-size: 13.5px;
}
.nav-item:hover { background: var(--panel-2); color: var(--ink); text-decoration: none; }
.nav-item.on { background: var(--bg); color: var(--ink); font-weight: 700; }
.nav-item svg { flex: 0 0 17px; opacity: .8; }
.nav-item.on svg { opacity: 1; color: var(--violet); }
.nav-count {
  margin-left: auto; font-size: 11.5px; font-weight: 700;
  color: var(--ink-3); font-variant-numeric: tabular-nums;
}

.sidebar-foot { margin-top: auto; padding-top: 18px; }
.conn {
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 11px 12px; font-size: 12px; color: var(--ink-2);
}
.conn-dot {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  margin-right: 7px; vertical-align: middle;
}
.conn-ok .conn-dot { background: var(--green); box-shadow: 0 0 0 3px var(--green-dim); }
.conn-warn .conn-dot { background: var(--red); box-shadow: 0 0 0 3px var(--red-dim); }

main { flex: 1; min-width: 0; padding: 22px 30px 70px; max-width: 1320px; }

.topbar { display: flex; align-items: center; gap: 14px; margin-bottom: 20px; flex-wrap: wrap; }
.topbar .spacer, .filters .spacer { flex: 1; }
.filters a.btn-quiet {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 15px; border-radius: 999px;
}

/* --- cards ---------------------------------------------------------- */

.card {
  background: var(--panel); border: 1px solid var(--line-soft);
  /* Both ends. With only a bottom margin a card sat flush against anything
     that was not itself a card - a list of results, a paragraph, a row of
     buttons - because nothing else was holding the gap. Adjacent margins
     collapse, so two cards in a row still show 18px between them. */
  border-radius: var(--radius); padding: 20px 22px; margin: 18px 0;
}
details.card > summary { cursor: pointer; color: var(--ink-3); font-size: 12.5px; }
details.card[open] > summary { margin-bottom: 14px; }

.card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; margin-bottom: 14px; flex-wrap: wrap;
}
.card-head h2, .card-head h1 { margin: 0; }
.card-head.bare { margin: 0 0 14px; }
.card-head form { margin: 0; }

/* --- stat tiles ------------------------------------------------------ */

.stats { display: flex; flex-wrap: wrap; gap: 12px; margin: 0 0 18px; }
.stat {
  background: var(--panel); border: 1px solid var(--line-soft);
  border-radius: var(--radius); padding: 15px 18px; min-width: 132px;
}
.stat .n {
  display: block; font-size: 26px; font-weight: 800; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; line-height: 1.15;
}
.stat .l { display: block; font-size: 11.5px; color: var(--ink-3); margin-top: 2px; }
.stat-link { color: inherit; display: block; }
.stat-link:hover { border-color: var(--line); text-decoration: none; }
.stat-new { border-color: rgba(25,196,111,.4); }
.stat-new .n { color: var(--green); }
.stat-gone { border-color: rgba(249,19,2,.35); }
.stat-gone .n { color: var(--red); }

/* --- dashboard ------------------------------------------------------- */

/* Every source, in a row, including the ones sitting on nothing. A source
   you cannot see from the dashboard is a source that gets forgotten. */
.strip {
  display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 18px;
}
.strip-item {
  display: flex; align-items: center; gap: 8px;
  background: var(--panel); border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm); padding: 9px 13px; color: var(--ink-2);
  font-size: 13px;
}
.strip-item:hover { border-color: var(--line); color: var(--ink); text-decoration: none; }
.strip-item svg { opacity: .7; }
.strip-name { font-weight: 600; }
.strip-n { font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ink); }
.strip-doing { font-size: 11px; color: var(--green); }
.strip-item.empty { opacity: .55; }
.strip-item.empty .strip-n { color: var(--ink-3); }

/* Two columns rather than four: these cards hold lists, not numbers. The
   min() is what lets a column shrink below its own minimum on a narrow
   window - without it the track stays 420px wide and the page scrolls
   sideways by however much it overshoots. */
.grid.two { grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr)); }

.queue { list-style: none; margin: 4px 0 0; padding: 0; }
.queue li {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding: 10px 0; border-top: 1px solid var(--line-soft);
}
.queue li:first-child { border-top: 0; }
/* The source label is the point of this list: it is what says the queue
   covers everything rather than one tab's worth. */
.queue-src {
  display: inline-flex; align-items: center; gap: 5px;
  flex: 0 0 auto; width: 108px;
  font-size: 11px; text-transform: uppercase; letter-spacing: .05em;
  font-weight: 700; color: var(--ink-3);
}
.queue-src:hover { color: var(--ink-2); text-decoration: none; }
.queue-title { flex: 1 1 200px; min-width: 0; font-weight: 600; }
.queue-sub {
  flex: 0 1 auto; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
  color: var(--ink-3); font-size: 11.5px;
}

.movers { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 4px; }
/* A grid item's minimum is its content by default, and the content here is a
   nowrap URL. Without this the column is sized to the longest path on the
   site and the card pushes the page sideways. */
.movers > div { min-width: 0; }
.movers-head {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  font-weight: 700; margin: 0 0 6px;
}
.movelist { list-style: none; margin: 0; padding: 0; }
.movelist li {
  display: flex; align-items: baseline; gap: 8px; padding: 6px 0;
  border-top: 1px solid var(--line-soft);
}
.movelist li:first-child { border-top: 0; }
.movelist a {
  flex: 1 1 auto; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; font-size: 13px;
}
/* After above, before below: side by side the pair runs off the end of a
   narrow column and the figure that matters is the one that gets cut. */
.movers-n {
  flex: 0 0 auto; text-align: right; line-height: 1.25;
  font-variant-numeric: tabular-nums; font-weight: 700; font-size: 13px;
}
.movers-n em {
  display: block; font-style: normal; font-weight: 400;
  color: var(--ink-3); font-size: 11px;
}
.movelist li { align-items: center; }

.dashfoot { margin-top: 18px; }
/* A figure that held steady. Saying nothing at all reads as no data. */
.level { color: var(--ink-3); }

@media (max-width: 720px) {
  .movers { grid-template-columns: 1fr; }
  .queue-src { width: auto; }
}

/* --- dashboard tiles ------------------------------------------------- */

.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(285px, 1fr)); gap: 18px; }

.tile {
  background: var(--panel); border: 1px solid var(--line-soft);
  border-radius: var(--radius); padding: 20px 22px;
  display: flex; flex-direction: column; gap: 10px;
  color: inherit; position: relative; overflow: hidden;
}
.tile:hover { border-color: var(--line); text-decoration: none; }
.tile::after {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: var(--accent, var(--violet));
}
.tile-head { display: flex; align-items: center; gap: 11px; }
.tile-icon {
  width: 34px; height: 34px; border-radius: var(--radius-sm); flex: 0 0 34px;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent-dim, var(--violet-dim)); color: var(--accent, var(--violet));
}
.tile-name { font-weight: 700; font-size: 15px; }
.tile-big {
  font-size: 30px; font-weight: 800; letter-spacing: -.025em;
  font-variant-numeric: tabular-nums; line-height: 1.1;
}
.tile-sub { font-size: 12.5px; color: var(--ink-3); }
.tile-foot {
  margin-top: auto; padding-top: 6px; font-size: 12.5px;
  color: var(--ink-2); font-weight: 700;
}
.tile:hover .tile-foot { color: var(--accent, var(--violet)); }

.a-violet { --accent: var(--violet); --accent-dim: var(--violet-dim); }
.a-pink   { --accent: var(--pink);   --accent-dim: var(--pink-dim); }
.a-green  { --accent: var(--green);  --accent-dim: var(--green-dim); }
.a-blue   { --accent: var(--blue);   --accent-dim: var(--blue-dim); }
.a-red    { --accent: var(--red);    --accent-dim: var(--red-dim); }

.split { display: flex; gap: 22px; flex-wrap: wrap; }
.split > div { flex: 1; min-width: 118px; }
.split .k { font-size: 11.5px; color: var(--ink-3); }
.split .v { font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; }
.up { color: var(--green); }
.down { color: var(--red); }

/* --- controls -------------------------------------------------------- */

input, select, textarea, button {
  font: inherit; font-family: inherit;
  border-radius: var(--radius-sm); border: 1px solid var(--line);
  background: var(--bg); color: var(--ink); padding: 8px 11px;
}
input::placeholder, textarea::placeholder { color: var(--ink-3); }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--violet); box-shadow: 0 0 0 3px var(--violet-dim);
}
select { cursor: pointer; }
textarea { resize: vertical; width: 100%; }

button, .btn {
  background: var(--violet); border-color: var(--violet); color: #fff;
  font-weight: 600; cursor: pointer; padding: 9px 17px;
  display: inline-flex; align-items: center; gap: 7px;
}
/* A link styled as a button never got the box: border and radius come from
   the input reset above, which only names real controls. So every <a
   class="btn"> in the tool has been rendering as bare text with padding.
   Width and style only - the colour is whatever the variant sets. */
.btn { border-style: solid; border-width: 1px; border-radius: var(--radius-sm); }
button:hover, .btn:hover { filter: brightness(1.12); text-decoration: none; }
button:disabled { opacity: .5; cursor: default; filter: none; }

.btn-quiet, .btn-quiet-solid {
  background: transparent; color: var(--ink-2); border-color: var(--line);
}
.btn-quiet:hover, .btn-quiet-solid:hover {
  background: var(--panel-2); color: var(--ink); filter: none;
}
button.danger { background: transparent; color: var(--red); border-color: var(--line); }
button.danger:hover { background: var(--red); color: #fff; border-color: var(--red); }
.btn-run { background: var(--violet); border-color: var(--violet); }
.btn-link { align-self: center; font-size: 13px; color: var(--ink-2); }

/* The browser's own `hidden` rule is display:none at the lowest weight, so
   any class here that sets a display beats it and the element stays on
   screen. That is how the bio's Save and Cancel were sitting there before
   anybody asked to edit anything. One rule, once, for every use of it. */
[hidden] { display: none !important; }

form.row { display: flex; gap: 9px; flex-wrap: wrap; align-items: center; }
form.row .grow, .row .grow { flex: 1; min-width: 230px; }
.row { display: flex; gap: 9px; flex-wrap: wrap; align-items: center; }
.filters { margin-bottom: 14px; }
form.stack { display: flex; flex-direction: column; gap: 12px; width: min(560px, 100%); }
form.stack label {
  display: flex; flex-direction: column; gap: 5px; font-size: 12.5px; color: var(--ink-3);
}
form.stack button { align-self: flex-start; }
form.stack .hint { display: inline; margin-left: 6px; }
form.stack.tight { margin-top: 14px; }

/* --- tables ---------------------------------------------------------- */

.table-wrap { overflow-x: auto; }
.table-wrap table.list { min-width: 660px; }
table.list { width: 100%; border-collapse: collapse; }
table.list th {
  text-align: left; font-size: 10.5px; text-transform: uppercase;
  letter-spacing: .09em; color: var(--ink-3); font-weight: 700;
  padding: 8px 9px; border-bottom: 1px solid var(--line);
}
table.list td {
  padding: 7px 9px; border-bottom: 1px solid var(--line-soft); vertical-align: middle;
}
table.list tbody tr:hover { background: rgba(255,255,255,.022); }
table.list .num { text-align: right; font-variant-numeric: tabular-nums; }

.pages { table-layout: fixed; }
.pages th:nth-child(1) { width: 30%; }
.pages th:nth-child(2) { width: 13%; }
.pages th:nth-child(3), .pages th:nth-child(4), .pages th:nth-child(5) { width: 78px; }
.pages th:nth-child(7) { width: 116px; }
.pages select, .pages input, .pages textarea { width: 100%; padding: 5px 7px; }
.pages td form { margin: 0; }

a.sort { color: var(--ink-3); white-space: nowrap; display: inline-block; }
a.sort::after { content: " \25BE"; font-size: 9px; margin-left: 3px; visibility: hidden; }
a.sort:hover { color: var(--ink); text-decoration: none; }
a.sort.on { color: var(--violet); font-weight: 800; }
a.sort.on::after { visibility: visible; }

.urlcell { display: flex; align-items: center; white-space: nowrap; }
.urlcell > .trend, .urlcell > .visit, .urlcell > .tag,
.urlcell > .anchorbtn { flex: 0 0 auto; }
.urlcell a { color: var(--ink); }
.urlcell a:hover { color: var(--blue); }

.urlbtn {
  background: none; border: none; padding: 0; margin: 0;
  color: var(--ink); text-align: left; cursor: pointer;
  flex: 0 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.urlbtn:hover { color: var(--blue); text-decoration: underline; filter: none; }
.urlbtn.open { font-weight: 700; color: var(--violet); }
.urlbtn.open::before { content: "\25BE "; font-size: 10px; }
.visit { color: var(--ink-3); font-size: 13px; margin-left: 6px; }
.visit:hover { color: var(--blue); }

/* --- tags, pills, states --------------------------------------------- */

.tag {
  font-size: 10px; text-transform: uppercase; letter-spacing: .06em;
  font-weight: 700; background: var(--panel-2); color: var(--ink-3);
  padding: 2px 6px; border-radius: 5px; margin-left: 6px;
}
.tag-new { background: var(--green-dim); color: var(--green); }
.tag-bad { background: var(--red-dim); color: #ff8577; }
.tag-money { background: var(--green-dim); color: var(--green); }
.tag-boost { background: var(--pink-dim); color: var(--pink); }
/* A subject the client has hearted on the authority map. Same pink as
   the heart itself, because it is the same fact. */
.tag-target { background: var(--pink-dim); color: var(--pink); }

.pill { padding: 2px 9px; border-radius: 20px; font-size: 12px; font-weight: 600; }
.pill-warn { background: var(--pink-dim); color: var(--pink); }

.routepill, .statepill, .keyitem {
  font-size: 11px; font-weight: 600; padding: 2px 9px;
  border-radius: 20px; border: 1px solid transparent; white-space: nowrap;
  display: inline-block;
}
.route-blog      { background: var(--violet-dim); border-color: rgba(143,68,242,.5); color: #c79bff; }
.route-faq       { background: var(--blue-dim);   border-color: rgba(0,130,245,.5);  color: #74bcff; }
.route-tool      { background: var(--green-dim);  border-color: rgba(25,196,111,.5); color: #5ddba0; }
.route-landing   { background: var(--pink-dim);   border-color: rgba(246,69,156,.5); color: #ff8dc2; }
.route-low_value { background: var(--panel-2);    border-color: var(--line);         color: var(--ink-3); }
.route-bin       { background: var(--red-dim);    border-color: rgba(249,19,2,.4);   color: #ff8577; }

.drop-rank       { background: var(--blue-dim);   border-color: rgba(0,130,245,.4);  color: #74bcff; }
.drop-slug       { background: var(--pink-dim);   border-color: rgba(246,69,156,.4); color: #ff8dc2; }
.drop-other_page { background: var(--violet-dim); border-color: rgba(143,68,242,.4); color: #c79bff; }
.drop-settled    { background: var(--panel-2);    border-color: var(--line);         color: var(--ink-3); }

.state-earned       { background: var(--green-dim);  border-color: rgba(25,196,111,.5); color: #5ddba0; }
.state-untapped     { background: var(--pink-dim);   border-color: rgba(246,69,156,.5); color: #ff8dc2; }
.state-weak         { background: var(--panel-2);    border-color: var(--line);         color: var(--ink-3); }
.state-aspirational { background: var(--violet-dim); border-color: rgba(143,68,242,.5); color: #c79bff; }

.pilebtn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 14px; border: 1px solid var(--line); border-radius: 20px;
  background: var(--panel); color: var(--ink-2); font-size: 13px; font-weight: 600;
}
.pilebtn:hover { border-color: var(--ink-3); color: var(--ink); text-decoration: none; filter: none; }
.pilebtn.on { background: var(--violet); border-color: var(--violet); color: #fff; }
.pilecount { font-size: 11.5px; opacity: .8; font-variant-numeric: tabular-nums; }
.perpage { color: var(--ink-3); font-size: 12.5px; margin-left: auto; }
.perpage a, .perpage strong { margin-left: 9px; color: var(--ink-2); }
.perpage strong { color: var(--violet); font-weight: 700; }

/* --- flashes and banners --------------------------------------------- */

.flashes { margin: 0 0 16px; }
.flash {
  padding: 11px 15px; border-radius: var(--radius-sm);
  /* Top margin as well as bottom. A message that appears under a button was
     landing flush against it, and against whatever card came next. It turns
     up beneath something on nearly every page, so the gap belongs on the
     message rather than being remembered at each place one can appear. */
  margin: 10px 0 9px; font-size: 13.5px; border: 1px solid transparent;
}
/* Inside the page-top stack the first one needs no lead-in: the container
   already holds it off the content above. */
.flashes > .flash:first-child { margin-top: 0; }
.flash-ok { background: var(--green-dim); border-color: rgba(25,196,111,.35); color: #7fe0b0; }
.flash-error { background: var(--red-dim); border-color: rgba(249,19,2,.35); color: #ff9c91; }

.banner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; padding: 13px 17px;
  border-radius: var(--radius-sm); margin: 0 0 16px; font-size: 13.5px;
  border: 1px solid transparent;
}
.banner-warn { background: var(--red-dim); border-color: rgba(249,19,2,.35); color: #ff9c91; }
.banner-soft { background: var(--pink-dim); border-color: rgba(246,69,156,.3); color: #ffa8cd; }
.banner .btn { padding: 7px 13px; font-size: 13px; }
.banner-warn .btn { background: var(--red); border-color: var(--red); }
.btn-quiet { background: transparent; border-color: currentColor; color: inherit; }

.flash.working::after, p.nq.working::after {
  content: ""; display: inline-block; width: 6px; height: 6px;
  margin-left: 8px; border-radius: 50%; background: currentColor;
  animation: pulse 1s ease-in-out infinite; vertical-align: middle;
}
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .25; } }

/* --- the expander under a page row ----------------------------------- */

.panelrow > td { background: var(--bg); padding: 14px 16px 16px 30px; }
.tabs { display: flex; gap: 5px; margin-bottom: 13px; }
.tab {
  background: transparent; border: 1px solid transparent; border-radius: 20px;
  padding: 5px 14px; font-size: 12.5px; font-weight: 600; color: var(--ink-3);
}
.tab:hover { color: var(--ink); filter: none; }
.tab.on { background: var(--panel); border-color: var(--line); color: var(--ink); }

.qwrap { max-height: 340px; overflow-y: auto; }
p.nq { margin: 0 0 9px; font-size: 12.5px; color: var(--ink-3); }
table.qtable { width: 100%; border-collapse: collapse; font-size: 12.5px; }
table.qtable th {
  text-align: left; font-size: 10px; text-transform: uppercase;
  letter-spacing: .07em; color: var(--ink-3); font-weight: 700;
  padding: 5px 9px; border-bottom: 1px solid var(--line);
  position: sticky; top: 0; background: var(--bg);
}
table.qtable td { padding: 4px 9px; border-bottom: 1px solid var(--line-soft); }
table.qtable td.num, table.qtable th.num {
  text-align: right; font-variant-numeric: tabular-nums; width: 64px;
}
table.qtable tbody tr:hover { background: rgba(255,255,255,.03); }

.colourkey { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 11px; }
.qtable tr.t0 td:first-child { box-shadow: inset 3px 0 0 var(--violet); }
.qtable tr.t1 td:first-child { box-shadow: inset 3px 0 0 var(--blue); }
.qtable tr.t2 td:first-child { box-shadow: inset 3px 0 0 var(--green); }
.qtable tr.t3 td:first-child { box-shadow: inset 3px 0 0 var(--pink); }
.qtable tr.t4 td:first-child { box-shadow: inset 3px 0 0 #e0a51f; }
.qtable tr.t5 td:first-child { box-shadow: inset 3px 0 0 #14b5c4; }
.keyitem.t0 { background: var(--violet-dim); border-color: var(--violet); color: #c79bff; }
.keyitem.t1 { background: var(--blue-dim);   border-color: var(--blue);   color: #74bcff; }
.keyitem.t2 { background: var(--green-dim);  border-color: var(--green);  color: #5ddba0; }
.keyitem.t3 { background: var(--pink-dim);   border-color: var(--pink);   color: #ff8dc2; }
.keyitem.t4 { background: rgba(224,165,31,.14); border-color: #e0a51f; color: #ffd06b; }
.keyitem.t5 { background: rgba(20,181,196,.14); border-color: #14b5c4; color: #63dbe6; }
.qtable tr.beaten td { background: var(--red-dim); color: var(--ink-3); }
.qtable tr.beaten td:first-child {
  box-shadow: inset 3px 0 0 var(--red);
  text-decoration: line-through; text-decoration-color: rgba(249,19,2,.5);
}
.keyitem.beaten { background: var(--red-dim); border-color: var(--red); color: #ff8577; }
.qtable .tiny { display: block; font-size: 10.5px; color: #ff8577; text-decoration: none; }

/* --- marks ------------------------------------------------------------ */

th.marks { text-align: right; }
td.marks { text-align: right; white-space: nowrap; }
.mark {
  width: 28px; height: 28px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 8px;
  color: var(--ink-3); font-size: 14px; line-height: 1; cursor: pointer;
}
.mark + .mark { margin-left: 5px; }
.mark:hover { border-color: var(--ink-3); color: var(--ink); filter: none; }
.mark-heart.on { background: var(--pink); border-color: var(--pink); color: #fff; }
.mark-heart:hover { color: var(--pink); border-color: var(--pink); }
.mark-cross.on { background: var(--red); border-color: var(--red); color: #fff; }
.mark-cross:hover { color: var(--red); border-color: var(--red); }
.mark-cross.on:hover { color: #fff; }
.mark-research:hover { color: var(--blue); border-color: var(--blue); }
.mark-research.done { color: var(--blue); border-color: rgba(0,130,245,.5); background: var(--blue-dim); }
.mark-research.busy svg { animation: pulse 1s ease-in-out infinite; }
.mark-research svg { display: block; }

tr.status-important { background: rgba(246,69,156,.05); }
tr.status-important .urlbtn { font-weight: 700; }
tr.status-remove .urlbtn, tr.status-remove .urlcell a { color: var(--ink-3); text-decoration: line-through; }
.row-gone .urlcell a, .row-gone .urlbtn { color: var(--ink-3); text-decoration: line-through; }

/* --- trend symbols ----------------------------------------------------- */

.trend {
  display: inline-block; width: 13px; margin-right: 6px; font-size: 10px;
  line-height: 1; text-align: center; vertical-align: middle; position: relative;
}
.trend-exploding { color: var(--green); font-size: 13px; font-weight: 800; }
.trend-up { color: var(--green); }
.trend-down { color: var(--red); }
.trend-steady { color: var(--ink-3); }
.trend-new { color: var(--pink); font-size: 11px; }
.trend-none { color: transparent; }
.trend[data-tip]::after {
  content: attr(data-tip); position: absolute;
  left: 100%; top: 50%; transform: translateY(-50%); margin-left: 5px;
  background: var(--ink); color: var(--bg); padding: 2px 8px; border-radius: 5px;
  font-size: 12px; font-weight: 700; white-space: nowrap;
  opacity: 0; pointer-events: none; z-index: 5;
}
.trend[data-tip]:hover::after { opacity: 1; }

/* --- notes ------------------------------------------------------------- */

textarea.notes {
  width: 100%; height: 30px; padding: 5px 7px; resize: none; overflow: hidden;
  line-height: 1.4; white-space: nowrap; text-overflow: ellipsis;
  transition: height .15s ease; font-size: 13px;
}
textarea.notes:focus {
  height: 190px; overflow: auto; white-space: pre-wrap;
  position: relative; z-index: 2;
  box-shadow: 0 10px 28px rgba(0,0,0,.55), 0 0 0 3px var(--violet-dim);
}

/* --- anchor themes ----------------------------------------------------- */

.themes { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.theme {
  position: relative;   /* the remove cross sits in the corner */
  background: var(--panel); border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm); padding: 13px 15px;
}
.theme .cardx { top: 7px; right: 7px; }

/* Adding one of your own, under the list. */
.addanchor { display: flex; gap: 8px; margin: 0 0 12px; }
.addanchor .anchor-input { flex: 1 1 auto; }

/* The way back into a page's anchors: an anchor glyph beside the visit
   arrow, in the same weight. A row can carry a dozen of these down a
   column, and "3 anchors" a dozen times is a wall of words. */
.anchorbtn {
  cursor: pointer; background: none; border: 0; padding: 0;
  font-size: 12px; line-height: 1;
  /* White rather than the muted grey the visit arrow uses. The arrow is a
     shape you can read at any weight; the anchor is a small drawing and
     disappears at --ink-3. */
  color: var(--ink);
}
.anchorbtn:hover { color: var(--pink); }

/* The heart while the anchor run is happening behind it. Reuses the pulse
   defined further up rather than redefining it - two @keyframes with one
   name and the later wins, which would have quietly changed the other user. */
.mark.busy { animation: pulse 1.1s ease-in-out infinite; }
.theme.decision-accepted { border-color: rgba(25,196,111,.45); background: rgba(25,196,111,.05); }
.theme.decision-dismissed { opacity: .45; }
.theme-head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px; flex-wrap: wrap; margin-bottom: 9px;
}
.theme-name { font-weight: 700; font-size: 14px; }
.theme-stats { color: var(--ink-3); font-size: 11.5px; font-variant-numeric: tabular-nums; }
.anchor-line { display: flex; align-items: center; gap: 9px; }
.anchor-line .lbl, .alts .lbl {
  font-size: 10px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--ink-3); font-weight: 700; flex: 0 0 auto;
}
.anchor-input { flex: 1 1 auto; min-width: 0; font-size: 14px; font-weight: 600; }
.alts { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 9px; }
.alt {
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 20px;
  padding: 3px 11px; font-size: 12px; color: var(--ink-2); font-weight: 500;
}
.alt:hover { background: var(--violet-dim); border-color: var(--violet); color: #c79bff; filter: none; }
.why { margin: 9px 0 0; font-size: 12.5px; color: var(--ink-2); }
.mismatch {
  margin: 0 0 9px; padding: 8px 11px; border-radius: 8px; font-size: 12.5px;
  background: var(--pink-dim); border: 1px solid rgba(246,69,156,.35); color: #ffa8cd;
}
details.terms { margin-top: 9px; font-size: 12px; }
details.terms summary { cursor: pointer; color: var(--ink-3); }
details.terms ul { margin: 6px 0 0; padding-left: 20px; color: var(--ink-3); }
.theme-actions { display: flex; gap: 6px; margin-top: 11px; }
.pillbtn {
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 8px;
  padding: 5px 13px; font-size: 12.5px; color: var(--ink-2); font-weight: 600;
}
.pillbtn:hover { border-color: var(--ink-3); color: var(--ink); filter: none; text-decoration: none; }
.pillbtn.target {
  background: transparent; border-color: rgba(143, 68, 242, .55); color: #c79bff;
}
.pillbtn.target:hover { border-color: var(--violet); color: #fff; background: var(--violet-dim); }
.pillbtn.target.on { background: var(--violet); border-color: var(--violet); color: #fff; }
.pillbtn.target.on:hover { filter: brightness(1.12); color: #fff; }

.topicname {
  background: none; border: 0; padding: 0; font: inherit; color: var(--ink);
  cursor: pointer; text-align: left; border-bottom: 1px dashed var(--line);
}
.topicname:hover { color: var(--violet); border-bottom-color: var(--violet); }
.topicdetail > td { background: var(--bg); padding: 16px 18px !important; }
.renameform { display: flex; align-items: center; gap: 9px; margin: 0 0 14px; }
.renameform label {
  font-size: 10px; text-transform: uppercase; letter-spacing: .09em; color: var(--ink-3);
}
.renameform input { max-width: 340px; }
.list.inner { margin: 0; font-size: 12.5px; }
.list.inner th { font-size: 9.5px; }
.list.inner td { padding: 7px 10px; }

.dropcell { width: 26px; padding-right: 0 !important; }
.dropcell form { margin: 0; }
.dropbtn {
  background: none; border: 0; color: var(--ink-3); font-size: 17px; line-height: 1;
  padding: 2px 5px; border-radius: 6px; cursor: pointer; font-family: inherit;
}
.dropbtn:hover { color: var(--red); background: var(--red-dim); }

.hiddenrow { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; margin-top: 14px; }
.hiddenrow form { margin: 0; }
.hiddenlabel {
  font-size: 10px; text-transform: uppercase; letter-spacing: .09em;
  color: var(--ink-3); margin-right: 4px;
}

.pillbtn.accept.on { background: var(--green); border-color: var(--green); color: #06150d; }
.pillbtn.dismiss.on { background: var(--red); border-color: var(--red); color: #fff; }
.pillbtn.done.on { background: var(--blue); border-color: var(--blue); color: #fff; }
.opp.moved { opacity: .55; }
.moved-note { margin: 10px 0 0; font-size: 12px; color: var(--ink-3); }

/* --- opportunities and briefs ------------------------------------------ */

/* Two across, so a screenful is eight opportunities rather than three. */
.opplist { display: grid; grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)); gap: 14px; }
.opp[data-brief] { cursor: pointer; }
.opp[data-brief]:hover { border-color: var(--line); background: var(--panel-2); }

.opp {
  background: var(--panel); border: 1px solid var(--line-soft);
  border-radius: var(--radius); padding: 16px 18px;
}
.opplist .opp { margin-bottom: 0; }
.opp.decision-actioned { border-color: rgba(25,196,111,.45); background: rgba(25,196,111,.05); }
.opp.decision-completed { border-color: rgba(0,130,245,.45); background: rgba(0,130,245,.05); }
.opp.decision-removed { opacity: .5; }
/* An idea you added yourself. It sits at the top of the list and wears the
   brand violet, because a hundred angles can come out of one afternoon on
   Reddit and this is the one somebody actually stopped and wrote down. */
.opp.mine {
  border-color: rgba(143, 68, 242, .5);
  background: linear-gradient(135deg, rgba(143,68,242,.12), var(--panel) 55%);
}
.opp.mine .radar-source { color: #c79bff; }
.opp-head { display: flex; align-items: baseline; gap: 11px; flex-wrap: wrap; }
.opp-score {
  font-size: 24px; font-weight: 800; color: var(--violet);
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
/* The title wraps its own text rather than taking a flex line of its own.
   A zero basis is what does it: with `flex-wrap: wrap`, an item whose
   content is wider than the room left moves to the next line *before*
   shrinking is considered, so a two-line headline pushed itself below the
   score and left the number sitting alone on the line above.

   A basis of 60% is small enough that it never triggers that break and large
   enough that the title still gets most of the row: at a zero basis the
   pills beside it took their content width first and squeezed the headline
   into a column four lines deep. */
.opp-term { font-size: 15px; font-weight: 700; flex: 1 1 60%; min-width: 0; }
.opp-parts { margin: 7px 0 0; font-size: 12px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.signpost {
  margin: 11px 0 0; padding: 10px 13px; border-radius: var(--radius-sm);
  font-size: 12.5px; background: var(--blue-dim);
  border: 1px solid rgba(0,130,245,.3); color: #9ad0ff;
}
.signpost a { color: #bfe1ff; }
.brief-line { margin: 0 0 9px; font-size: 13.5px; }
.termlist { margin: 8px 0 0; padding-left: 20px; font-size: 13px; color: var(--ink-2); }
.termlist li { padding: 2px 0; }
.linklist { margin: 11px 0 0; padding-left: 22px; }
.linklist li { padding: 10px 0; border-bottom: 1px solid var(--line-soft); }
.linklist li:last-child { border-bottom: none; }
.link-head { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.link-head a { font-weight: 700; color: var(--ink); }
.anchor-out { margin: 6px 0 0; font-size: 13.5px; color: var(--ink-2); }
.linklist .why { margin: 3px 0 0; }

/* --- content gaps ------------------------------------------------------ */

.funnel { display: flex; flex-wrap: wrap; gap: 9px; }
.step {
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  padding: 12px 16px; min-width: 122px; background: var(--bg);
}
.step .n { display: block; font-size: 21px; font-weight: 800; font-variant-numeric: tabular-nums; }
.step .l { display: block; font-size: 11px; color: var(--ink-3); }
.step.drop { background: var(--red-dim); border-color: rgba(249,19,2,.25); }
.step.drop .n { color: #ff8577; }
.step.keep { background: var(--green-dim); border-color: rgba(25,196,111,.35); }
.step.keep .n { color: var(--green); }

.gaps { table-layout: fixed; }
.gaps th:nth-child(1) { width: 34%; }
.gaps td.term { white-space: normal; word-break: break-word; }
.gaps td.reason { white-space: normal; font-size: 12px; color: var(--ink-3); }
.yes { color: var(--green); font-weight: 700; }
.no { color: var(--ink-3); }

/* --- topical authority map --------------------------------------------- */

/* --- the authority map --------------------------------------------------- */

.mapswitch { display: flex; gap: 4px; padding: 3px; background: var(--bg);
  border: 1px solid var(--line-soft); border-radius: 999px; }
.mapswitch button {
  background: none; border: 0; color: var(--ink-3); font-size: 12px; font-weight: 600;
  padding: 6px 15px; border-radius: 999px; cursor: pointer; font-family: inherit;
}
.mapswitch button:hover { color: var(--ink-2); }
.mapswitch button.on { background: var(--violet); color: #fff; }

.rebuildrow { display: flex; justify-content: flex-end; margin-top: 14px; }
.rebuildrow button.danger {
  background: var(--red); border-color: var(--red); color: #fff;
}
.rebuildrow button.danger:hover { filter: brightness(1.12); background: var(--red); }

.linkgroup { margin: 18px 0 0; }
.linkgroup-head {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--ink-2); margin: 0 0 8px;
}
.linkgroup-head span {
  text-transform: none; letter-spacing: 0; font-weight: 400;
  color: var(--ink-3); margin-left: 8px;
}

.daterange {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12px; color: var(--ink-3);
}
.daterange input { font-family: inherit; }
.mapswitch a {
  color: var(--ink-3); font-size: 12px; font-weight: 600;
  padding: 6px 15px; border-radius: 999px; text-decoration: none;
}
.mapswitch a:hover { color: var(--ink-2); text-decoration: none; }
.mapswitch a.on { background: var(--violet); color: #fff; }
/* The chart sits in a well cut deeper than the page, which is what gives the
   lines their contrast - a chart drawn on the same grey as everything around
   it has to shout to be seen. Lines carry their own colour inline. */
.chartcard { padding: 0; background: transparent; border: 0; }
.chart {
  background: #101116;
  border: 1px solid #24262d;
  border-radius: var(--radius);
  padding: 18px 20px 12px;
}
.chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.chart .c-line {
  fill: none; stroke-width: 1.9; stroke-linejoin: round; stroke-linecap: round;
}
.chart .c-area { stroke: none; opacity: .13; }
.chart .c-grid { stroke: #272930; stroke-width: 1; }
.chart .c-axis { font-size: 10.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.chart .c-date { fill: #767c88; font-weight: 500; }
.chart .c-ghost {
  fill: none; stroke-width: 1.6; stroke-dasharray: 5 4;
  opacity: .55; stroke-linejoin: round;
}
.chart-key {
  display: flex; gap: 18px; margin: 0 0 -6px; padding: 0 2px;
  font-size: 11.5px; color: var(--ink-3);
}
.chart-key i { width: 18px; height: 0; display: inline-block; margin-right: 7px;
  vertical-align: middle; }
.chart-key .k-solid { border-top: 2px solid var(--ink-2); }
.chart-key .k-dash { border-top: 2px dashed var(--ink-3); }
.chart .c-name {
  font-size: 10.5px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
}

/* The figures above the chart are its switches, so they have to look
   switchable - and look off when they are off. Their borders take the same
   colour as the line each one draws. */
.metricstats .stat {
  cursor: pointer; text-align: left; font-family: inherit;
  border: 1px solid var(--line-soft); background: var(--panel);
  transition: border-color .12s, opacity .12s;
}
.metricstats .stat:hover { border-color: var(--line); }
.metricstats .stat:not(.on) { opacity: .5; }
.metricstats .stat.on.metric-clicks { border-color: #b47cff; }
.metricstats .stat.on.metric-impressions { border-color: #4db2ff; }
.metricstats .stat.on.metric-ctr { border-color: #3ee096; }
.metricstats .stat.on.metric-position { border-color: #ff7ab8; }
.metricstats .stat.on .n { color: var(--ink); }

.dlnote {
  font-size: 11.5px; color: var(--ink-3); margin-left: 10px;
  white-space: nowrap; align-self: center;
}

.radar-source { color: var(--ink-2); font-weight: 700; }

.switchlabel {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 12.5px; color: var(--ink-2);
}
/* A label and the control it names belong together; the next pair does not.
   Without this the whole row reads as one run of words and boxes. */
.settingsrow { gap: 20px; margin-top: 18px; }
.settingsrow .switchlabel { gap: 10px; }
.settingsrow button[type=submit] { margin-left: 4px; }
.switchlabel input[type=checkbox] { width: 15px; height: 15px; accent-color: var(--violet); }

.findrow {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 22px; margin-bottom: 20px;
}
.findlabel { font-size: 13px; font-weight: 700; margin: 0 0 4px; color: var(--ink); }
.findrow .hint { margin-top: 0; margin-bottom: 11px; }
.lookup { border-top: 1px solid var(--line-soft); padding-top: 18px; }
#lookupout { margin-top: 12px; }

.mapnote { margin: 2px 0 12px; font-size: 12.5px; color: var(--ink-3); }
.mapcount { color: var(--ink-2); font-weight: 600; margin-left: 7px; }
.mapstage { margin: 0; }
.m-cell.off { cursor: default; }
.m-cell.off:hover rect { filter: brightness(1.9); }
.mapstage svg { display: block; width: 100%; height: auto; overflow: visible; }
.m-cell { cursor: default; }
.m-cell:hover rect, .m-cell:hover path { filter: brightness(1.35); }
.m-area { font-size: 11px; font-weight: 700; fill: var(--ink-2);
  text-transform: uppercase; letter-spacing: .06em; }
.m-name { font-size: 10.5px; font-weight: 600; }
.m-sub  { font-size: 9.5px; opacity: .82; }
.m-ring { font-size: 10px; font-weight: 700; text-anchor: middle; }
.m-spoke { font-size: 10px; fill: var(--ink-3); }
.m-hub { font-size: 22px; font-weight: 800; fill: var(--ink); text-anchor: middle;
  font-variant-numeric: tabular-nums; }
.m-hubsub { font-size: 10px; fill: var(--ink-3); text-anchor: middle;
  text-transform: uppercase; letter-spacing: .09em; }

.mapchips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 13px; }
.mapchip {
  display: flex; align-items: center; gap: 8px; padding: 7px 12px;
  background: var(--bg); border: 1px solid var(--line-soft);
  border-radius: 999px; font-size: 12px; color: var(--ink-3);
}
.mapchip i { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.mapchip b { color: var(--ink); font-weight: 600; }
.mapchip em { font-style: normal; color: var(--ink-3); opacity: .65; }
.mapempty { font-size: 12.5px; color: var(--ink-3); margin: 13px 0 0; }
.maptip { min-height: 17px; margin: 10px 0 0; font-size: 12.5px; color: var(--ink-2); }
.mapkey { display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  margin-top: 6px; font-size: 11.5px; color: var(--ink-3); }
.mk-ramp { width: 132px; height: 9px; border-radius: 999px;
  background: linear-gradient(90deg, #22252a, #4c2e60, #8138ab, #a760f0); }
.mk-note { margin-left: 6px; }
.mk-target { display: flex; align-items: center; gap: 6px; margin-left: 4px; }
.mk-ring {
  width: 11px; height: 11px; border-radius: 50%;
  border: 1.6px solid var(--pink); display: inline-block;
}

.topics td.num { font-variant-numeric: tabular-nums; }
.topics td form { margin: 0; }

/* --- pager, reports ----------------------------------------------------- */

.pager {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 12px 0 2px; font-size: 12.5px;
}
.pager a { color: var(--ink-2); font-weight: 600; }
.pager .off { color: var(--ink-3); opacity: .45; }
.pager .where { color: var(--ink-3); }

.report { margin-top: 14px; font-size: 12.5px; }
.report summary { cursor: pointer; color: var(--ink-3); }
.report pre {
  background: var(--bg); border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  padding: 13px; overflow-x: auto; max-height: 320px; font-size: 11.5px;
  white-space: pre-wrap; word-break: break-all; color: var(--ink-2);
}

.sitemaps th:nth-child(2) { width: 80px; }
.sitemaps th:nth-child(3) { width: 170px; }
.sitemaps th:nth-child(4) { width: 46px; }

@keyframes saveflash { from { background: var(--green-dim); } to { background: transparent; } }
@keyframes failflash { from { background: var(--red-dim); } to { background: transparent; } }
.saved { animation: saveflash .9s ease-out; }
.failed { animation: failflash .9s ease-out; }

@media (max-width: 900px) {
  .shell { flex-direction: column; }
  .sidebar {
    width: 100%; flex: none; height: auto; position: static;
    flex-direction: row; flex-wrap: wrap; align-items: center;
    border-right: none; border-bottom: 1px solid var(--line-soft);
  }
  .brand { padding: 0 12px 0 4px; }
  .nav-label, .sidebar-foot { display: none; }
  main { padding: 18px 16px 60px; }
}


/* --- conversations --------------------------------------------------------
   An angle carries two things an opportunity does not: the words somebody
   actually used, and a marker for something that has not reached search data
   yet. Both earn their own treatment. */
.convquote {
  margin: 8px 0 0;
  padding: 8px 14px;
  border-left: 2px solid var(--violet);
  color: var(--ink-2);
  font-style: italic;
}
.emerging {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--violet);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  font-style: normal;
}
#convtext { width: 100%; font-family: inherit; font-size: 14px; line-height: 1.5; }

/* An angle's headline is a link now, but it should not look like one until
   you go near it - the card is a decision surface, not a list of links. */
.opplink { color: inherit; text-decoration: none; }
.opplink:hover { color: var(--violet); text-decoration: underline; }

/* The brief is markdown held as text. Shown as written rather than parsed:
   it is handed to a writer as a file, and what is on screen should be what
   is in the file. */
.briefbody {
  margin-top: 14px;
  padding: 18px 20px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg);
  white-space: pre-wrap;
  font-size: 13.5px;
  line-height: 1.66;
  color: var(--ink-2);
  max-height: 620px;
  overflow-y: auto;
}

/* A suggestion is an instruction to go and do something, so the action sits
   at the front of the row rather than hiding at the end of it. */
.idea {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 10px 0;
  border-bottom: 1px solid var(--line-soft);
}
.idea:last-child { border-bottom: none; }
.idea p { margin: 2px 0 0; }
.idea-term { font-weight: 600; }
.idea-where {
  margin-left: 8px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--ink-3, var(--ink-2));
}

/* Severity is the point of this report, so it is the one thing coloured.
   Three bands rather than a gradient - the number is already on the badge,
   and the colour only has to say "look here first". */
.opp-score.sev-high { background: var(--red-dim, rgba(224,90,90,.18)); color: #e0625d; }
.opp-score.sev-mid  { background: var(--violet-dim); color: var(--violet); }
.opp-score.sev-low  { background: var(--line-soft); color: var(--ink-2); }
.grid.tight td { padding: 5px 10px; font-size: 13px; }
.grid.tight td.n {
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
  width: 54px;
}
.claims {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--violet);
}
/* The page that should own the term. Marked rather than reordered - moving it
   to the top would hide the very thing worth seeing, which is that it is
   sitting below something else. */
.winrow td { background: var(--violet-dim); }
.winrow td:first-child { border-left: 2px solid var(--violet); }
/* The quick bin. Sits in the corner and stays quiet until you go near it -
   it is an escape hatch, not one of the three real decisions below. */
.opp { position: relative; }
.cardx {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 26px;
  height: 26px;
  padding: 0;
  line-height: 1;
  font-size: 17px;
  border-radius: 8px;
  background: none;
  border: 1px solid transparent;
  color: var(--ink-3, var(--ink-2));
  opacity: .5;
}
.cardx:hover {
  opacity: 1;
  filter: none;
  background: var(--red-dim, rgba(224,90,90,.14));
  border-color: var(--red, #e0625d);
  color: var(--red, #e0625d);
}

/* The decision filters sit beside the three kinds and should read as a
   second, quieter axis rather than competing with them. */
.pilebtn.small { font-size: 12.5px; padding: 4px 11px; }

/* Splits the sidebar into the two things it actually contains: work to pick
   up, and the reference pages you go to when you already know what you want. */
.nav-rule {
  height: 1px;
  margin: 10px 12px;
  background: var(--line-soft);
}

/* The overview is a preview, so its cards sit closer together than they do on
   a source page where each one is the thing you are working on. */
.opplist.tight { gap: 10px; }
.opplist.tight .opp { padding: 12px 16px; }
.summary { margin-bottom: 18px; }

/* The websites table runs straight into the first card with nothing between
   them, so the card reads as part of the table rather than a separate thing. */
.table-wrap + .card { margin-top: 26px; }

/* The setup checklist. Shown only while something is still missing, so a
   working website never carries scaffolding it has finished with. */
.card.setup { border-color: var(--violet-dim); }
.steps { list-style: none; margin: 0; padding: 0; counter-reset: step; }
.steps li {
  position: relative;
  padding: 7px 0 7px 30px;
  counter-increment: step;
  border-bottom: 1px solid var(--line-soft);
}
.steps li:last-child { border-bottom: none; }
.steps li::before {
  content: counter(step);
  position: absolute; left: 0; top: 8px;
  width: 19px; height: 19px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 11px; font-variant-numeric: tabular-nums;
  background: var(--line-soft); color: var(--ink-2);
}
.steps li.done::before { content: "¹3"; background: var(--violet); color: #fff; }
.steps li span { color: var(--ink-2); margin-left: 8px; font-size: 13px; }

/* The target heart on a treemap block. Faint until you go near it - an empty
   heart on every block would otherwise compete with the block's own label. */
.m-heart { cursor: pointer; opacity: .45; transition: opacity .12s ease; }
.m-heart:hover { opacity: 1; }
.m-heart.on { opacity: 1; }

/* --- the dashboard -----------------------------------------------------
   Deliberately a different world from the rest of trove. Every other page
   is a dense working list read by somebody who knows what a canonical is;
   this one is read by whoever opens the tool, so it gets bigger type, more
   air, lighter panels and colour doing some of the talking. Scoped under
   .dash so none of it leaks into the pages that need to stay dense. */

.dash { --dpanel: #22252b; --dpanel-2: #2b2f37; }
.dash h1 { font-size: 30px; letter-spacing: -.02em; }
.dhead { margin: 0 0 26px; }

.dsection {
  font-size: 11px; text-transform: uppercase; letter-spacing: .14em;
  font-weight: 800; color: var(--ink-3);
  margin: 34px 0 12px; padding-bottom: 8px;
  border-bottom: 1px solid var(--line-soft);
}

.dgrid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
.dgrid.three { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
.dgrid.four { grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr)); }
.dgrid > * { min-width: 0; }

.dcard {
  position: relative; min-width: 0;
  background: var(--dpanel); border: 1px solid var(--line-soft);
  border-radius: 16px; padding: 22px 24px 24px;
}
.dcard h3 {
  margin: 0 0 8px; font-size: 15px; font-weight: 700; letter-spacing: -.01em;
  /* Room for the cull badge in the corner. Without it a long heading runs
     underneath the number and both become unreadable. */
  padding-right: 62px;
}
.dhero { margin-bottom: 16px; }
.dbanner { background: linear-gradient(140deg, #2c2140, var(--dpanel) 62%); }
.dwin { border-color: rgba(25,196,111,.3); }
.dquiet { background: none; }

/* The sentence a skimmer reads instead of the chart. */
.dverdict { font-size: 15px; line-height: 1.55; margin: 0 0 16px; color: var(--ink-2); }
.dverdict strong { color: var(--ink); font-weight: 700; }
.dverdict.big { font-size: 19px; line-height: 1.45; }
.dsay { font-size: 13px; line-height: 1.55; color: var(--ink-2); margin: 0 0 14px; }
.dmuted { color: var(--ink-3); font-size: 12px; line-height: 1.5; }
.dcard p.dmuted { margin: 10px 0 0; }

.dbig {
  margin: 0; font-size: 40px; font-weight: 800; letter-spacing: -.03em;
  line-height: 1.05; font-variant-numeric: tabular-nums;
}
.dslash { color: var(--ink-3); font-weight: 400; }
.dlabel { margin: 6px 0 0; font-size: 12.5px; color: var(--ink-3); }
.dpulse .dspark { margin-top: 12px; display: block; }

.dchart { display: block; margin: 0 -6px; overflow: visible; }
.dgrid-line, .dchart .dgrid { stroke: rgba(255,255,255,.07); stroke-width: 1; }
.dchart .dchart-x { fill: #8b929e; font-size: 12px; font-weight: 600; }

/* Two quantities as one shape. Quicker to read than the pair of numbers. */
.dbar { display: flex; gap: 3px; height: 8px; margin-top: 14px; }
.dbar span { border-radius: 4px; }
.dbar-up { background: var(--green); }
.dbar-down { background: var(--red); }
.dbar-rest { background: var(--panel-2); }

/* One card across the width, not four tiles each holding a nought. Three
   stages sharing a card read as one idea; the same three numbers in three
   boxes read as three things that have gone wrong. */
.dpipecard { margin-bottom: 16px; }
.dstages {
  display: flex; align-items: stretch; gap: 14px; flex-wrap: wrap;
  margin: 18px 0 22px;
}
.dstage {
  flex: 1 1 180px; min-width: 0;
  display: flex; flex-direction: column; gap: 3px;
  background: var(--dpanel-2); border-radius: 12px; padding: 16px 18px;
}
.dstage-n {
  font-size: 34px; font-weight: 800; line-height: 1; letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}
.dstage-name { font-size: 13px; font-weight: 700; }
.dstage-say { font-size: 11.5px; color: var(--ink-3); }
.dstage.done { background: rgba(25,196,111,.1); }
.dstage.done .dstage-n, .dstage-done { color: var(--green); }
.dstage-arrow { align-self: center; color: var(--ink-3); font-size: 18px; }

/* Where each stage's work came from. Quiet: the three numbers above are the
   card, this is the detail somebody asks for second. */
.dsources { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.dsources th {
  text-align: right; font-size: 10.5px; text-transform: uppercase;
  letter-spacing: .06em; color: var(--ink-3); font-weight: 700;
  padding: 0 0 8px; border-bottom: 1px solid var(--line-soft);
}
.dsources th:first-child { text-align: left; }
.dsources td { padding: 8px 0; border-top: 1px solid var(--line-soft); }
.dsources tbody tr:first-child td { border-top: 0; }
.dsources td.num { text-align: right; font-variant-numeric: tabular-nums; width: 88px; }

@media (max-width: 560px) {
  .dstage-arrow { display: none; }
  .dstage { flex: 1 1 100%; }
}

.dlist, .dsplit, .dbars { list-style: none; margin: 0; padding: 0; }
/* One row, one line. These lists are scanned, and a URL that wraps onto a
   second line breaks the scan far worse than the same URL cut short with an
   ellipsis. Nothing here is long except the URL, and the URL is the thing
   that can afford to be trimmed. */
.dlist li, .dsplit li {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: nowrap;
  padding: 8px 0; border-top: 1px solid var(--line-soft); font-size: 13px;
}
.dlist li:first-child, .dsplit li:first-child { border-top: 0; }
/* The thing being named is what stretches - not whatever happens to come
   first, which on the movers list is a one-character arrow. The :not() is
   doing real work: `span:first-child` is the more specific selector of the
   two, so excluding the arrow there is the only way to stop it growing and
   shoving every URL into the middle of its row. */
.dlist li > a:first-of-type,
.dlist li > span:first-child:not(.dtick) { flex: 1 1 auto; min-width: 0; }
.dlist li > .dtick { flex: 0 0 auto; }
.dlist li > .dtick ~ a { flex: 1 1 auto; min-width: 0; }
/* A name that grows is a name that has to be able to be cut. */
.dlist li > span:first-child:not(.dtick) {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* The figures on the right keep their width and stay whole. Only the URL
   gives ground, because a trimmed URL is still recognisable and "8 visito"
   is not. */
.dlist li > span { white-space: nowrap; }
.dlist li > span:last-child { flex: 0 0 auto; }

/* The teaser cards are the exception. Their first line is a sentence and
   their second is where it came from, so those genuinely are two lines. */
.dlist.raised li { flex-wrap: wrap; }
.dlist li > a { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dsplit li { justify-content: space-between; color: var(--ink-3); font-size: 12px; }
.dsplit em { font-style: normal; }

.dbars li { display: flex; align-items: center; gap: 10px; padding: 7px 0; font-size: 13px; }
/* The name gets the room and the bar gets what is left. It was the other
   way round, and a 90px bar says everything a 300px one does - while
   "greater manchester locations" cut to "greater manchester ..." does not. */
.dbars-name {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dbars-track {
  flex: 0 0 90px; height: 7px; background: var(--panel-2); border-radius: 4px;
}
.dbars-fill {
  display: block; height: 100%; border-radius: 4px;
  background: linear-gradient(90deg, var(--violet), #a760f0);
}
.dbars-fill.pink { background: linear-gradient(90deg, #b4348e, var(--pink)); }
.dbars-n { flex: 0 0 auto; font-variant-numeric: tabular-nums; font-weight: 700; font-size: 12px; }

.dmore {
  display: inline-block; align-self: flex-start;
  margin-top: 12px; font-size: 12.5px; font-weight: 600;
}
/* A link in a tinted section takes that section's colour. */
.tinted .dmore { color: rgb(var(--tint)); }
.dfoot { margin-top: 34px; }

@media (max-width: 640px) {
  .dcard { padding: 18px 18px 20px; }
  .dbig { font-size: 32px; }
}

/* --- the colour language ----------------------------------------------

   Two rules, and they hold everywhere in trove rather than only on the
   dashboard:

     * Anything that IS a source - Offshoots, Voices, Headlines, Contenders,
       Clashes - wears that source's colour. The sidebar icon, the card top,
       the dot on the pipeline row, the rule across the top of its own page.
       Five words, five colours, so "the amber one" becomes a way of saying
       Headlines without anybody being told.

     * Anything that is an observation rather than a source - what moved,
       which subjects you own, where you are winning - gets a soft tint
       instead. It gives those cards life without pretending they belong to
       a source they do not.

   The hues are declared on :root rather than on the dashboard, because the
   sidebar needs them on every page in the tool. */

:root {
  --t-offshoots:  #8f44f2;
  --t-voices:     #4db2ff;
  --t-headlines:  #f5a524;
  --t-contenders: #19c46f;
  --t-clashes:    #f6459c;
  /* Handoffs: teal, the one hue left that is not already a source. */
  --t-handoffs:   #17c0c7;
}
.tone-offshoots  { --tone: var(--t-offshoots); }
.tone-voices     { --tone: var(--t-voices); }
.tone-headlines  { --tone: var(--t-headlines); }
.tone-contenders { --tone: var(--t-contenders); }
.tone-clashes    { --tone: var(--t-clashes); }
.tone-handoffs   { --tone: var(--t-handoffs); }

/* The sidebar. Coloured whether or not the page is open, because the colour
   is what the word means, not a highlight for where you happen to be. */
.nav-item[class*="tone-"] svg { color: var(--tone); opacity: .95; }
.nav-item[class*="tone-"].on svg { color: var(--tone); }

/* A source's own page, topped with its colour. */
main[class*="tone-"] { position: relative; }
main[class*="tone-"]::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: var(--tone);
}

/* --- source cards: the signature ---------------------------------------- */
.dsig { overflow: hidden; padding-top: 24px; }
.dsig-bar {
  position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: var(--tone);
}
.dsig:hover { border-color: color-mix(in srgb, var(--tone) 55%, transparent); }
.dsig-head {
  display: flex; align-items: center; gap: 9px;
  margin: 0 0 8px; padding-right: 62px;
}
.dsig-dot {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 8px; flex: 0 0 auto;
  color: var(--tone); background: color-mix(in srgb, var(--tone) 16%, transparent);
}
.dsig-n {
  font-size: 11px; font-weight: 800; color: var(--tone);
  background: color-mix(in srgb, var(--tone) 14%, transparent);
  padding: 2px 8px; border-radius: 20px;
}
.dsig-head a { color: var(--ink); }
.dsig-head a:hover { text-decoration: none; }

/* The whole card is the link. The anchor covers it from behind, and the rows
   inside sit above so they still reach their own briefs. */
.dstretch::after { content: ""; position: absolute; inset: 0; z-index: 0; }
.dlist.raised { position: relative; z-index: 1; }
/* The link sits on the floor of the card, not under the last row of
   content. The cards in a row are the same height, so four links at the same
   height read as one control repeated; four at four different heights read
   as four cards that did not quite line up. */
.dsig, .dfoot-link { display: flex; flex-direction: column; }
.dsig .dmore, .dfoot-link .dmore { margin-top: auto; padding-top: 14px; }
.dsig .dmore {
  position: relative; z-index: 1; color: var(--tone); pointer-events: none;
}

/* --- insight cards: the tint --------------------------------------------

   One hue per section rather than one for all of them. Three stretches of
   the same violet read as one long section that will not end; a different
   wash on each says plainly where one ends and the next begins.

   Held as an r,g,b triple so a single value drives both the wash and the
   border at different strengths. */
.tinted      { --tint: 143, 68, 242; }
.tint-blue   { --tint: 77, 178, 255; }
.tint-green  { --tint: 25, 196, 111; }
.tint-amber  { --tint: 245, 165, 36; }
.tint-pink   { --tint: 246, 69, 156; }

.tinted .dcard {
  background: linear-gradient(150deg, rgba(var(--tint), .13), var(--dpanel) 62%);
  border-color: rgba(var(--tint), .2);
}
/* The rule under the section heading picks up the same colour, so the label
   and the cards below it are visibly one block. */
.dsection[class*="tint-"] { border-bottom-color: rgba(var(--tint), .45); }
.dgap { height: 18px; }
.dsection { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }

/* --- the pipeline, graded left to right ------------------------------- */
.dcard-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 14px; flex-wrap: wrap; margin-bottom: 4px;
}
.dcard-head h3 { padding-right: 0; margin-bottom: 0; }
.dhead-right { display: inline-flex; align-items: center; gap: 10px; }
.dbtn {
  display: inline-block; font-size: 12px; font-weight: 700;
  padding: 7px 13px; border-radius: 20px;
  background: var(--violet); color: #fff;
}
.dbtn:hover { background: #a760f0; text-decoration: none; color: #fff; }

.dstage.waiting { background: var(--dpanel-2); }
.dstage.waiting .dstage-n { color: var(--ink-2); }
/* Amber in the middle: started, not finished. The colour carries the story
   left to right before the numbers are read. */
.dstage.going { background: rgba(245,165,36,.13); }
.dstage.going .dstage-n { color: #f5a524; }
.dstage.done { background: rgba(25,196,111,.13); }

/* Source rows go to their tab. */
.dsrc td:first-child { display: flex; align-items: center; gap: 9px; }
.dsrc-dot {
  width: 8px; height: 8px; border-radius: 3px; flex: 0 0 auto;
  background: var(--tone, var(--ink-3));
}
.dsrc a { color: var(--ink); font-weight: 600; }
.dsrc:hover a { color: var(--tone, var(--blue)); text-decoration: none; }
.dsrc:hover td { background: rgba(255,255,255,.03); }

/* --- settings: connection, bio, danger --------------------------------- */

.connline { font-size: 14px; margin: 0; }

/* The bio's two halves, told apart by a line rather than by a warning.
   Everything above is Claude's and gets rewritten; everything below the rule
   is the user's and survives. */
.biokeep {
  border-top: 2px solid var(--line);
  padding-top: 16px; margin-top: 4px;
}
.bioform { margin-top: 16px; }
.bioform label { display: block; }

/* A delete that looks like one. It was red text on a transparent button,
   which reads as a link and sits a mis-click away from Save. */
.dangerrow { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--line-soft); }
button.danger-solid {
  background: var(--red); border-color: var(--red); color: #fff; font-weight: 700;
}
button.danger-solid:hover { background: #ff3b28; border-color: #ff3b28; color: #fff; }

/* --- settings: numbered sections, the bio block ------------------------ */

/* A number on each section, so "section 3" means something in a message. */
.snum {
  display: inline-block; min-width: 20px; margin-right: 10px;
  font-size: 11px; font-weight: 800; text-align: center;
  color: var(--violet); background: rgba(143,68,242,.14);
  padding: 2px 7px; border-radius: 20px; vertical-align: middle;
}

/* One block, the width of the card. It was five boxes with their own
   scrollbars, which assumed every business has tidy services and areas. */
.biobox { margin-top: 14px; }
.bioread, .bioedit {
  width: 100%; font-size: 14px; line-height: 1.65;
  white-space: pre-wrap; word-break: break-word;
}
.bioread { color: var(--ink-2); }
.bioedit {
  min-height: 220px; padding: 14px 16px; resize: vertical; overflow: hidden;
  background: var(--bg); border: 1px solid var(--violet);
}
.biosave { margin-top: 12px; }

/* Section 4's own row: the box to add a publication, then the offer to have
   trove pick some. The button sits under the box because adding one by hand
   is the thing on the card and the seed is the fallback. */
.seedrow { margin-top: 14px; }
/* Any row of controls sitting under a card's prose. */
.cardrow { margin-top: 18px; }
/* And room under the line that introduces them. Settings was a stack of
   sentences and fields with the same eight pixels between every one of
   them, so nothing grouped with anything. */
.card > p.hint { margin-bottom: 14px; }
.card > p.muted { margin-bottom: 14px; }

/* Section 4's watched list. The cells were touching, which read as one run
   of words rather than a name, a label and two buttons. */
.grid td { padding: 9px 14px 9px 0; vertical-align: middle; }
.grid td:last-child { padding-right: 0; }
.watchname strong { display: block; }
.watchname .muted { display: block; margin-top: 1px; }

/* How a publication is followed, in one word. Amber for a feed read
   directly - the Headlines colour, because that is the whole feature working
   as intended - and blue for one followed through a search. Both are on the
   palette; the grey it used to wear made a working source look switched off. */
.viapill {
  display: inline-block; min-width: 58px; text-align: center;
  font-size: 11px; font-weight: 700; letter-spacing: .03em;
  padding: 3px 10px; border-radius: 20px;
  background: rgba(245,165,36,.16); color: var(--t-headlines);
}
.viapill.via-search { background: rgba(77,178,255,.16); color: var(--t-voices); }

/* --- settings pass 3: a bio that does not own the page ----------------- */

/* Three lines at rest. The bio is the longest thing on Settings and it sits
   at the top, so open by default it pushes every other setting off screen. */
.bioread.clamped {
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
.biomore {
  background: none; border: 0; padding: 6px 0 0;
  color: var(--blue); font-size: 12.5px; font-weight: 600; cursor: pointer;
}
.biomore:hover { text-decoration: underline; }

/* A card for something the tool manages itself: one line, no room taken. */
.card.thin { padding-top: 18px; padding-bottom: 18px; }
.card.thin .hint { margin-bottom: 0; }
.card.thin .grid { margin-top: 14px; }

/* The second line of a wait: the clock, in smaller type under the step. */
.waitfor {
  display: block; margin-top: 3px; font-size: 12px; opacity: .75;
  font-weight: 500;
}

/* --- Opportunities: every card wears its source ------------------------

   The five sources each have a colour in the sidebar and on their own page,
   and this was the one page where they all looked alike. The colour goes on
   the cards rather than on the section, because the cards are what the eye
   actually travels down: a run of green reads as Contenders before the
   heading above it has been read at all.

   Chosen over a rule along the top, a spine down the left and a wash across
   the panel, all of which put the colour where you stop looking after the
   first second. */

.opsource .card-head h2 svg { color: var(--tone); }
.opsource .opp {
  border-left: 3px solid color-mix(in srgb, var(--tone) 65%, transparent);
}
.opsource .opp-score { color: var(--tone); }

/* An idea somebody added keeps its own violet edge, which would otherwise be
   overwritten by the source colour of the block it is sitting in. */
.opsource .opp.mine { border-left-color: var(--violet); }

/* --- handoffs: the pages a card is offering ---------------------------
   A list inside a card, so it stays clearly subordinate to the page that is
   giving. The wording sits on its own line because it is the thing being
   copied, and hunting for it mid-sentence is the sort of small friction that
   stops somebody doing the job. */
.handoff-list { list-style: none; margin: 8px 0 0; padding: 0; }
/* Two rows, never three. The address is cut with an ellipsis rather than
   allowed to wrap, because one long address wrapping pushed the link wording
   down a line on some cards and not others, and no two cards then read the
   same way. */
.handoff-list li { padding: 8px 0; border-top: 1px solid var(--line-soft); }
.handoff-top {
  display: flex; align-items: baseline; gap: 12px; justify-content: space-between;
}
.handoff-top > a {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.nowrap { white-space: nowrap; flex: 0 0 auto; }
.handoff-anchor {
  display: block; margin-top: 2px; font-weight: 600;
  color: color-mix(in srgb, var(--t-handoffs) 78%, var(--ink));
}
.handoff-list.roomy li { padding: 12px 0; }
.handoff-list.roomy .handoff-top > a { white-space: normal; overflow: visible; }

/* What the page is earning. It is the reason the card exists, so it is not
   grey like the rest of the line above it. */
.handoff-metric { color: var(--ink); font-weight: 600; }
.handoff-trend {
  margin-left: 8px; font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; padding: 2px 8px; border-radius: 20px;
}
.handoff-trend.t-up, .handoff-trend.t-exploding {
  color: #3ee096; background: rgba(62, 224, 150, .14);
}
.handoff-trend.t-steady {
  color: var(--ink-2); background: var(--line-soft);
}
.handoff-trend.t-new {
  color: #c79bff; background: rgba(143, 68, 242, .16);
}

/* --- a finished brief -------------------------------------------------
   Blue, not green. Green already means "actioned" throughout trove and blue
   already means "completed" - the Complete button turns blue, and a completed
   card is blue-edged in every list. Green here would be the one place those
   two swapped over. */
.donebanner {
  display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap;
  padding: 12px 16px; margin: 0 0 18px; border-radius: var(--radius-sm);
  background: rgba(0, 130, 245, .09);
  border: 1px solid rgba(0, 130, 245, .35);
  color: var(--ink-2); font-size: 13.5px; line-height: 1.5;
}
.donesay { flex: 1 1 320px; min-width: 0; }
/* The undo sits at the end of the banner rather than among the page's own
   buttons: somebody looking for it is looking at the thing that told them it
   was finished. */
.doneundo { flex: 0 0 auto; }
.donebadge {
  display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto;
  font-size: 11px; font-weight: 800; letter-spacing: .07em;
  text-transform: uppercase; color: #6fc2ff;
}

/* --- signing in -------------------------------------------------------
   Its own page, with no sidebar: the sidebar is one website's pages, and
   nobody signed out has a website yet. */
.gatepage { display: flex; align-items: center; justify-content: center;
  min-height: 100vh; padding: 24px; }
.gatebox { width: 100%; max-width: 380px; }
.gatebox h1 { margin: 0 0 6px; font-size: 26px; }
.gatebox .stack { margin-top: 18px; }
.gatebox label { display: block; margin-bottom: 12px; font-size: 13px;
  color: var(--ink-2); }
.gatebox input { width: 100%; margin-top: 5px; }
.gatebox button[type="submit"] { width: 100%; }
.gatemark {
  width: 34px; height: 34px; border-radius: 10px; margin-bottom: 14px;
  background: var(--violet); color: #fff; font-weight: 800;
  display: flex; align-items: center; justify-content: center;
}

/* Who is signed in, at the foot of the sidebar next to the connection. */
.whoami {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 10px;
}
.whoami-name {
  font-size: 12.5px; color: var(--ink-2); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}

/* People. The website tick list is the whole point of the page, so it is
   given room rather than squeezed into a row. */
.sitepick { border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  padding: 12px 14px; margin: 0 0 12px; }
.sitepick legend { font-size: 11px; text-transform: uppercase;
  letter-spacing: .06em; color: var(--ink-3); padding: 0 6px; }
.pickone { display: inline-flex; align-items: center; gap: 7px;
  margin: 4px 16px 4px 0; font-size: 13.5px; }
.peoplerow { flex-wrap: wrap; gap: 10px 18px; align-items: center; }
.personoff { opacity: .55; }
.kind-admin { color: var(--violet); background: var(--violet-dim); }

/* --- the finished log -------------------------------------------------
   Three columns and no decoration: date, which list it came from, what it
   was called. Somebody reads down this to answer "what has been done since
   we last spoke", and anything more than that gets in the way of reading. */
.donelist td { vertical-align: baseline; padding: 9px 12px; }
.doneday {
  color: var(--ink-3); font-variant-numeric: tabular-nums;
  font-size: 12.5px; width: 1%;
}
.donetitle a { color: var(--ink); }
.donekind {
  display: inline-block; font-size: 10.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em;
  padding: 2px 9px; border-radius: 20px; white-space: nowrap;
}
/* Each list keeps the colour it wears everywhere else, so the kind is read
   before the word is. */
.kind-offshoot  { color: var(--t-offshoots);  background: color-mix(in srgb, var(--t-offshoots) 15%, transparent); }
.kind-voice     { color: var(--t-voices);     background: color-mix(in srgb, var(--t-voices) 15%, transparent); }
.kind-headline  { color: var(--t-headlines);  background: color-mix(in srgb, var(--t-headlines) 15%, transparent); }
.kind-contender { color: var(--t-contenders); background: color-mix(in srgb, var(--t-contenders) 15%, transparent); }
.kind-clash     { color: var(--t-clashes);    background: color-mix(in srgb, var(--t-clashes) 15%, transparent); }
.kind-handoff   { color: var(--t-handoffs);   background: color-mix(in srgb, var(--t-handoffs) 15%, transparent); }

/* Why a page is offered ahead of a closer match. Without it the order looks
   arbitrary, and an order nobody can account for is one people stop trusting. */
.lifted {
  display: inline-block; margin-right: 6px; font-weight: 700; font-size: 11.5px;
}
.lifted.hearted { color: var(--t-clashes); }
.lifted.earns   { color: var(--t-contenders); }

/* --- notes on a brief ---------------------------------------------------
   The one part of a brief a person writes. Deliberately plain: it is a
   sentence or two, not a document, and anything more elaborate would suggest
   otherwise. The empty state is a prompt rather than a blank box, because a
   blank box on a page full of headings reads as something that failed to
   load. */
.noteread { white-space: pre-wrap; line-height: 1.55; }
.noteread.empty { color: var(--ink-3); font-style: italic; }
.noteedit {
  width: 100%; min-height: 96px; resize: vertical; line-height: 1.55;
}
.notesave { margin-top: 10px; }

/* --- the two ways in ---------------------------------------------------
   A thread somebody else had, and an idea you had reading it. Side by side
   because they feed one list: the second exists because reading the first
   gives you ideas, and there was nowhere to put one. Equal columns, and they
   stack rather than squeeze once there is no room for two. */
.pastepair {
  display: grid; grid-template-columns: 1fr 1fr; gap: 14px;
  align-items: start;
}
.pastepair > .card { margin: 0; }
.dgrid > .card, .opplist > .card { margin: 0; }
@media (max-width: 860px) {
  .pastepair { grid-template-columns: 1fr; }
}

/* --- Voices: a suggestion you can act on ------------------------------- */
/* Text on the left, the two things you can do with it on the right. The
   platform is no longer printed here: it lives on the end of the query the
   Search now button runs, which is where it does some work. */
.idea { align-items: center; }
.idea-body { flex: 1 1 auto; min-width: 0; }
.idea-acts { flex: 0 0 auto; display: flex; gap: 6px; }
.idea-term { font-size: 14px; }
.idea-body p { margin: 3px 0 0; }
/* A suggestion that has been acted on, on its way out of the list. */
.idea.used { opacity: .4; }
/* "Search" is a caption over the two places, not a word on every row. It was
   printed five times down the list to say one thing about the pair beneath
   it, so it sits above them and only on the first row - after that the
   buttons say it themselves. */
.idea-acts { align-items: center; }
.idea-searchbox { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.idea-pills { display: flex; gap: 6px; }
.idea-label {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .07em;
  font-weight: 700; color: var(--ink-3); line-height: 1;
}
.idea:not(:first-child) .idea-label { display: none; }

/* Three buttons that looked the same were three buttons you had to read. A
   colour each and the row is legible at a glance: amber and pink for the two
   places, and the dismiss stays grey because it is not a destination. */
.pillbtn.idea-search.reddit {
  background: transparent; border-color: rgba(245, 165, 36, .5); color: #f0b45a;
}
.pillbtn.idea-search.reddit:hover {
  border-color: var(--t-headlines); color: #ffd08a;
  background: rgba(245, 165, 36, .12);
}
.pillbtn.idea-search.quora {
  background: transparent; border-color: rgba(246, 69, 156, .5); color: #f77ab6;
}
.pillbtn.idea-search.quora:hover {
  border-color: var(--t-clashes); color: #ff9ecb;
  background: rgba(246, 69, 156, .12);
}
.idea .cardx { position: static; width: 24px; height: 24px; font-size: 15px; }
/* Five controls is a wide cluster. Given no room the row used to hold them
   all and squeeze the phrase into a single-word column, so below a sensible
   width the buttons drop underneath instead. */
.idea { flex-wrap: wrap; }
.idea-body { flex: 1 1 240px; }

/* --- connected Google accounts ---------------------------------------- */
/* A list, not a table. The buttons were stacking and touching because a form
   is a block element sitting beside an inline link in a cell that laid out
   nothing - so the row lays itself out instead. */

.acctlist { list-style: none; margin: 16px 0 0; padding: 0; }
.acct {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 14px 0; border-top: 1px solid var(--line-soft);
}
.acct:first-child { border-top: 0; padding-top: 4px; }

/* Green or red, not the amber Headlines wears. Whether a connection works is
   the first thing to know and the last thing to have to read. */
.acct-dot {
  flex: 0 0 auto; width: 9px; height: 9px; border-radius: 50%;
}
.acct-dot.ok { background: var(--green); box-shadow: 0 0 0 3px rgba(25,196,111,.16); }
.acct-dot.bad { background: var(--red); box-shadow: 0 0 0 3px rgba(249,19,2,.16); }

.acct-who { flex: 1 1 260px; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.acct-who strong { font-size: 14px; }
.acct-count { flex: 0 0 auto; font-size: 12.5px; color: var(--ink-3); }
.acct-acts { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }
.acct-acts form { margin: 0; }
