/* Project activity — the bell and its flyout (D163).
 *
 * SHARED BY THE VIEWER AND THE DASHBOARD, which is why it is its own file
 * rather than a block in style.css or dashboard.css: one feature, one set of
 * rules, and no chance of the two pages drifting into two different feeds.
 * severity.css is here for the same reason (D145).
 *
 * THE FLYOUT IS AN OVERLAY; THE DASHBOARD'S DOCK IS NOT (D164). Nothing here
 * touches --pane-right or --panel-rail, so opening the flyout moves neither the
 * compass ring (D148) nor the tool panels, and the viewer underneath is exactly
 * where it was. The dock's own geometry -- how wide it is, where it sits in the
 * page, what it collapses to -- lives in dashboard.css, because that is page
 * layout rather than feed presentation. What both surfaces share is everything
 * below .activity-head: one feature, one set of rules.
 *
 * CALM IS A REQUIREMENT, not a preference: this sits over a measurement UI
 * during review work. No animation but a short fade, no colour that competes
 * with the severity ramp, and the one accent is the unseen badge.
 */

/* The slot is the positioning context for the flyout, so the flyout hangs from
 * the bell rather than from whatever ancestor happens to be positioned. */
#activity-slot {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.activity-bell {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.06);
  color: inherit;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
}

.activity-bell:hover { background: rgba(255, 255, 255, 0.12); }
.activity-bell:focus-visible { outline: 2px solid #6ea8fe; outline-offset: 2px; }
.activity-bell.has-unseen { border-color: rgba(110, 168, 254, 0.6); }

.activity-badge {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: #2f6fd0;
  color: #fff;
  font-size: 10px;
  font-weight: 600;
  line-height: 16px;
  text-align: center;
}

/* The base both shells supply, and every internal rule below inherits.
 *
 * It used to live on .activity-flyout alone, which meant a second surface
 * rendering the same cards would have drawn them in the browser's default
 * 16px black-on-white -- correct structure, correct copy, and unreadable. */
.activity-surface {
  color: #e6e8ec;
  font-size: 12px;
}

.activity-flyout {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 60;
  width: 360px;
  max-width: calc(100vw - 24px);
  max-height: min(70vh, 640px);
  overflow-y: auto;
  padding: 12px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 10px;
  background: #16181d;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
  color: #e6e8ec;
  font-size: 12px;
  animation: activity-fade 120ms ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .activity-flyout { animation: none; }
}

@keyframes activity-fade {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}

/* In the viewer the toolbar IS the bottom edge of the window, so the flyout
 * opens upward — the same direction .toolmenu opens for the tool groups. A
 * downward flyout there would be entirely off screen. */
#toolbar .activity-flyout {
  top: auto;
  bottom: calc(100% + 8px);
}

.activity-head {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 8px;
  align-items: baseline;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.activity-title { margin: 0; font-size: 13px; font-weight: 600; }

.activity-mark,
.activity-retry,
.activity-more,
.activity-expand {
  border: 0;
  background: none;
  color: #8ab4f8;
  cursor: pointer;
  font: inherit;
  padding: 0;
}

.activity-mark:hover,
.activity-retry:hover,
.activity-more:hover,
.activity-expand:hover { text-decoration: underline; }

/* The state line. Each tone is a DIFFERENT ANSWER, never a shade of the same
 * one: "no recent activity" is a fact about the project, "unavailable" is a
 * fact about this browser's ability to ask, and they must not look alike. */
.activity-state {
  grid-column: 1 / -1;
  margin: 2px 0 0;
  color: #9aa0a6;
  font-size: 11px;
}

.activity-state::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 6px;
  border-radius: 50%;
  background: #6b7280;
  vertical-align: middle;
}

.activity-state[data-tone="ok"]::before { background: #43a047; }
.activity-state[data-tone="empty"]::before { background: #6b7280; }
.activity-state[data-tone="delayed"]::before,
.activity-state[data-tone="retrying"]::before,
.activity-state[data-tone="partial"]::before,
.activity-state[data-tone="unavailable"]::before { background: #e0a030; }

.activity-state[data-tone="unavailable"],
.activity-state[data-tone="partial"] { color: #e0a030; }

.activity-list { display: flex; flex-direction: column; }

.activity-card {
  padding: 10px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}

.activity-card:last-child { border-bottom: 0; }

/* NEW AND SEEN, SPLIT AT THE BOOKMARK (D167).
 *
 * New work carries the one accent this panel has -- the badge's blue -- as a
 * rule down its left edge and a faint wash, so it reads as "this is what you
 * came for" without a second colour. Work you have already looked at stays
 * readable and steps back; it is dimmed, not greyed out, because it is still
 * the record. */
.activity-card.fresh {
  margin: 4px 0;
  padding: 8px 8px 8px 10px;
  border-bottom: 0;
  border-left: 2px solid #2f6fd0;
  border-radius: 4px;
  background: rgba(47, 111, 208, 0.10);
}

.activity-card.earlier { opacity: 0.72; }

/* Your own work is quieter still. You know what you did. */
.activity-card.earlier.mine { opacity: 0.5; }

.activity-divider {
  margin: 10px 0 2px;
  color: #9aa0a6;
  font-size: 10px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
}

.activity-divider:first-child { margin-top: 2px; }
.activity-divider.fresh { color: #8fb6f0; }

.activity-divider.earlier {
  display: flex;
  align-items: center;
  gap: 8px;
}

.activity-divider.earlier::after {
  content: "";
  flex: 1;
  height: 1px;
  background: rgba(255, 255, 255, 0.10);
}

.activity-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.activity-who { font-weight: 600; font-size: 12px; }

.activity-live {
  flex: none;
  padding: 1px 6px;
  border-radius: 10px;
  background: rgba(67, 160, 71, 0.16);
  color: #7fd18a;
  font-size: 10px;
}

.activity-context,
.activity-when,
.activity-counts {
  color: #9aa0a6;
  font-size: 11px;
  margin-top: 1px;
}

.activity-entries { margin-top: 6px; }

.activity-entry {
  padding: 3px 4px;
  border-radius: 4px;
}

.activity-entry.clickable { cursor: pointer; }
.activity-entry.clickable:hover { background: rgba(255, 255, 255, 0.06); }
.activity-entry.clickable:focus-visible { outline: 2px solid #6ea8fe; outline-offset: -2px; }

.activity-entry-main {
  display: flex;
  gap: 6px;
  align-items: baseline;
}

.activity-tag {
  flex: none;
  color: #9aa0a6;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
}

.activity-entry-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.activity-entry-detail {
  margin-left: 4px;
  color: #9aa0a6;
  font-size: 11px;
}

.activity-entry-detail.withdrawn { color: #e0a030; }

.activity-members { margin-left: 10px; border-left: 1px solid rgba(255, 255, 255, 0.1); padding-left: 6px; }

/* ONE PALETTE, BECAUSE BOTH PAGES ARE DARK.
 *
 * This file first carried a light-theme block for the dashboard, on the
 * assumption that a landing page is white. It is not: dashboard.css paints
 * near-black, and the result was a glaring white card floating over it. Nothing
 * in the text assertions could see that — the copy was correct, the structure
 * was correct, and it looked broken. It took the screenshot.
 *
 * WHAT THE DASHBOARD NEEDS NOW IS FOR THE FLYOUT TO GET OUT OF THE DOCK'S WAY.
 *
 * The bell sits in #topbar, about 102px from the right edge, and the flyout is
 * 360px wide and right-aligned to it -- so it spanned roughly 102px to 462px
 * from the right, while the dock occupies 0 to 460px. It covered almost all of
 * a wide dock and landed exactly on its header: two copies of the same record,
 * stacked.
 *
 * It cannot be fixed with a selector, because #activity-slot is inside #topbar
 * and the dock is in #page after it -- there is no combinator from one to the
 * other. And a fixed offset would be wrong, because #admin-link is hidden until
 * the caller is the operator, which moves the slot. So it is positioned against
 * the same two custom properties the dock itself is driven by, and follows a
 * drag for free. */
body.dashboard .activity-flyout {
  position: fixed;
  top: calc(var(--topbar-h, 57px) + 10px);
  right: calc(var(--dock-w, 0px) + 12px);
}

/* The viewer's prompt that the list is behind. It sits in the observations
 * panel header, NOT over the model: it is about the list, and a banner over
 * the twin would cover the thing being inspected. */
#obs-behind {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 4px 0;
  padding: 4px 6px;
  border-radius: 4px;
  background: rgba(110, 168, 254, 0.12);
  color: #cfe0ff;
  font-size: 11px;
}

#obs-behind button {
  border: 0;
  background: none;
  color: #8ab4f8;
  cursor: pointer;
  font: inherit;
  padding: 0;
  text-decoration: underline;
}
