/* PRD 03 — News Feed Markdown + Inline Media styles. */

/* TYPE: every text size in this file is a step of the platform type scale (custom.css ":root"
   --type-caption 12 / --type-small 13 / --type-title 16 / --type-page 22 / --type-display 28;
   PAGE_COMPOSITION_STANDARDS §5A), and body-sized text inherits the tenant's body size.
   Until 2026-09-24 this file ran its own scale — 9, 10, 11, 11.5, 12.5, 13.5, 14, 14.5, 17px —
   so 44–67% of the Feed, My Posts and My Feeds read off the scale and 400+ characters per page sat
   under the 12px floor (/design-pass communications). Never add a px font-size here: pick a token.
   Icon glyph sizes are not type and stay in px. */

/* ---------- Category left-border accents (one per category + must-read) ---------- */
.news-feed-card--operational {
  border-left: 3px solid var(--bs-primary, #3b7ddd) !important;
}

.news-feed-card--company-news {
  border-left: 3px solid var(--bs-info, #0dcaf0) !important;
}

.news-feed-card--social {
  border-left: 3px solid var(--bs-success, #28a745) !important;
}

.news-feed-card--must-read {
  border-left: 3px solid var(--bs-danger, #dc3545) !important;
}

/* ---------- Card hover lift ---------- */
.card[data-feed-id] {
  transition: box-shadow 0.15s ease;
}

.card[data-feed-id]:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08) !important;
}

/* ---------- Rendered Markdown body ---------- */
.news-feed-rendered {
  line-height: 1.5;
  word-wrap: break-word;
}

.news-feed-rendered p:last-child {
  margin-bottom: 0;
}

.news-feed-rendered img {
  max-width: 100%;
  height: auto;
  border-radius: 4px;
}

/* A picture inserted from the editor toolbar (2026-09-22) sits in the text
   as its own block at the column's width — never mid-line with the prose. */
.news-feed-rendered img.nf-inline-image {
  display: block;
  margin: 0.75rem 0;
  border-radius: 0.5rem;
}

.news-feed-rendered pre {
  background: #f6f8fa;
  padding: 0.75rem;
  border-radius: 6px;
  overflow-x: auto;
  font-size: 0.875rem;
}

.news-feed-rendered code {
  background: #f6f8fa;
  padding: 0.1rem 0.3rem;
  border-radius: 3px;
  font-size: 0.875em;
}

.news-feed-rendered pre code {
  background: transparent;
  padding: 0;
}

.news-feed-rendered blockquote {
  border-left: 3px solid #d0d7de;
  padding-left: 0.75rem;
  color: #57606a;
  margin: 0.5rem 0;
}

/* A Markdown table is the one body element that can be genuinely wider than
   the card: `pre` above already scrolls, and everything else is inline text
   that the container's `word-wrap: break-word` can break. Untreated, a table
   laid out 1688px inside an 880px post card, took the card's own box 833px
   with it and gave the page 659px of horizontal scroll
   (ISS-20260903-353-B1C4BF). Same block-scroll formula GitHub uses for
   rendered Markdown, which is the typography this whole block already
   mirrors (#f6f8fa / #d0d7de).

   `anywhere` rather than `break-word` on the cells: `break-word` is ignored
   when honouring it would change an element's min-content width, which is
   exactly a table cell holding a long unbroken token — so only `anywhere`
   shrinks the table that contains it. The two rules compose: a long token
   wraps and the table fits, and a table that is wide because it has many
   columns scrolls inside the card instead of bursting it. */
.news-feed-rendered table {
  border-collapse: collapse;
  margin: 0.5rem 0;
  font-size: 0.875rem;
  display: block;
  width: max-content;
  max-width: 100%;
  overflow-x: auto;
}

.news-feed-rendered th,
.news-feed-rendered td {
  border: 1px solid #d0d7de;
  padding: 0.35rem 0.6rem;
}

/* Body cells only. `anywhere` drops a cell's min-content width to one
   character, so applying it to the header row too let the table squeeze a
   short heading and break it mid-word ("Colu/mn") whenever a sibling column
   wanted the space. Headers keep their natural minimum; a long token in a
   header instead falls through to the block scroll above. */
.news-feed-rendered td {
  overflow-wrap: anywhere;
}

.news-feed-rendered th {
  background: #f6f8fa;
}

/* Read-More clamp on collapsed body. */
.news-feed-body {
  position: relative;
}

.news-feed-body:not([open]) .news-feed-body__rendered {
  display: -webkit-box;
  -webkit-line-clamp: 5;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.news-feed-body[open] .news-feed-body__more {
  display: none;
}

.news-feed-body__more {
  display: inline-block;
  margin-top: 0.25rem;
}

.news-feed-body__summary::-webkit-details-marker {
  display: none;
}

/* ---------- Media grid ---------- */
.news-feed-media {
  margin-top: 0.75rem;
}

.news-feed-media-grid {
  display: grid;
  gap: 4px;
  border-radius: 6px;
  overflow: hidden;
}

.news-feed-media-grid--1 {
  grid-template-columns: 1fr;
}

.news-feed-media-grid--2 {
  grid-template-columns: 1fr 1fr;
}

.news-feed-media-grid--3 {
  grid-template-columns: 2fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.news-feed-media-grid--3 .news-feed-media-tile:first-child {
  grid-row: span 2;
}

.news-feed-media-tile {
  position: relative;
  background: #f0f0f0;
  cursor: pointer;
  overflow: hidden;
  aspect-ratio: 16 / 9;
}

.news-feed-media-tile img,
.news-feed-media-tile video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.news-feed-media-tile__badge {
  position: absolute;
  top: 6px;
  left: 6px;
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  padding: 1px 6px;
  border-radius: 3px;
  font-size: 0.7rem;
  font-weight: 600;
}

.news-feed-media-tile__overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  font-weight: 600;
}

.news-feed-media-tile__play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 3rem;
  pointer-events: none;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.6);
}

.news-feed-media-tile__status {
  position: absolute;
  inset: 0;
  background: #f6f8fa;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #57606a;
  font-size: 0.875rem;
  gap: 0.4rem;
}

.news-feed-media-tile__status--failed {
  color: #b42318;
  background: #fef3f2;
}

/* ---------- PRD 09 — Auto-subtitle CC badge & toggle ---------- */
.news-feed-cc-badge {
  bottom: 6px;
  right: 6px;
  padding: 2px 8px;
  background: rgba(0, 0, 0, 0.65);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  border-radius: 3px;
  pointer-events: none;
  z-index: 2;
}

.news-feed-cc-pending {
  opacity: 0.7;
}

.news-feed-cc-failed {
  opacity: 0.55;
  cursor: not-allowed;
}

.news-feed-cc-toggle {
  position: absolute;
  bottom: 16px;
  right: 16px;
  padding: 6px 12px;
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  cursor: pointer;
  z-index: 10;
}

.news-feed-cc-toggle.is-on {
  background: #fff;
  color: #000;
}

.news-feed-cc-toggle:focus-visible {
  outline: 2px solid #4b9eff;
  outline-offset: 2px;
}

/* ---------- File cards ---------- */
.news-feed-file-list {
  margin-top: 0.5rem;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.news-feed-file-card {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.75rem;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  background: #fafbfc;
  text-decoration: none;
  color: inherit;
}

.news-feed-file-card:hover {
  background: #f3f4f6;
}

.news-feed-file-card__icon {
  font-size: 1.4rem;
  color: #6b7280;
}

.news-feed-file-card__meta {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.news-feed-file-card__name {
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.news-feed-file-card__size {
  font-size: 0.75rem;
  color: #6b7280;
}

/* ---------- Link previews ---------- */
.news-feed-link-preview {
  display: flex;
  gap: 0.75rem;
  margin-top: 0.5rem;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  background: #fff;
}

.news-feed-link-preview:hover {
  background: #f9fafb;
}

.news-feed-link-preview__image {
  flex: 0 0 120px;
  background-size: cover;
  background-position: center;
}

.news-feed-link-preview__thumb {
  flex: 0 0 96px;
  width: 96px;
  height: 96px;
  object-fit: cover;
  border-radius: 4px;
}

.news-feed-link-preview__body {
  padding: 0.6rem 0.75rem;
  min-width: 0;
}

.news-feed-link-preview__host {
  font-size: 0.75rem;
  color: #6b7280;
  text-transform: uppercase;
}

.news-feed-link-preview__title {
  font-weight: 600;
  margin: 0.15rem 0;
}

.news-feed-link-preview__desc {
  font-size: 0.85rem;
  color: #4b5563;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ---------- Composer attach list ---------- */
.news-feed-attach-list {
  list-style: none;
  padding: 0;
  margin: 0.5rem 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.news-feed-attach-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.6rem;
  border: 1px solid #e5e7eb;
  border-radius: 4px;
  background: #fafbfc;
}

.news-feed-attach-item__name {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.news-feed-attach-item__status {
  font-size: 0.75rem;
  color: #6b7280;
}

.news-feed-attach-item__status--ready {
  color: #15803d;
}

.news-feed-attach-item__status--failed {
  color: #b42318;
}

/* ---------- Gallery overlay ---------- */
.news-feed-gallery-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.92);
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.news-feed-gallery-stage {
  max-width: 95vw;
  max-height: 90vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.news-feed-gallery-stage img,
.news-feed-gallery-stage video {
  max-width: 95vw;
  max-height: 90vh;
  object-fit: contain;
}

.news-feed-gallery-close,
.news-feed-gallery-prev,
.news-feed-gallery-next {
  position: absolute;
  background: transparent;
  border: none;
  color: #fff;
  font-size: 2rem;
  cursor: pointer;
  padding: 0.5rem 0.75rem;
}

.news-feed-gallery-close {
  top: 12px;
  right: 16px;
  font-size: 2.5rem;
  line-height: 1;
}

.news-feed-gallery-prev {
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 3rem;
}

.news-feed-gallery-next {
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 3rem;
}

.news-feed-gallery-close:hover,
.news-feed-gallery-prev:hover,
.news-feed-gallery-next:hover {
  color: #d1d5db;
}

/* ---------- PRD 04 Phase 15: Reaction bar ---------- */
.sf-reaction-bar {
  padding: 0.5rem 0;
}

.sf-reaction-bar.is-reacting {
  opacity: 0.7;
  pointer-events: none;
}

.sf-reaction-summary {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 2px 8px 2px 4px;
  border-radius: 999px;
  background: #f3f4f6;
  border: 1px solid #e5e7eb;
}

.sf-reaction-summary:hover {
  background: #e9ecef;
}

.sf-reaction-cluster {
  display: inline-flex;
  align-items: center;
}

.sf-reaction-cluster .sf-reaction-glyph:not(:first-child) {
  margin-left: -4px;
}

.sf-reaction-glyph {
  font-size: 1.15rem;
  line-height: 1;
  display: inline-block;
  background: #fff;
  border-radius: 50%;
  padding: 1px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.05);
}

.sf-reaction-react-btn {
  color: #57606a;
  transition: background 0.12s ease, color 0.12s ease;
  border-radius: 4px;
}

.sf-reaction-react-btn:hover {
  color: var(--bs-primary, #0d6efd);
  background: #f3f4f6;
  padding: 2px 6px;
  margin: -2px -6px;
}

.sf-reaction-react-btn.is-reacted {
  color: var(--bs-primary, #0d6efd);
  background: #eff6ff;
  border-radius: 4px;
  padding: 2px 6px;
  margin: -2px -6px;
}

.sf-reaction-react-btn.is-reacted:hover {
  background: #dbeafe;
}

.sf-reaction-react-btn.is-reacted .sf-reaction-label {
  color: var(--bs-primary, #0d6efd);
}

button.sf-reaction-comment-count {
  transition: background 0.12s ease;
  border-radius: 4px;
  cursor: pointer;
}

button.sf-reaction-comment-count:hover {
  background: #f3f4f6;
  padding: 2px 6px;
  margin: -2px -6px;
}

.sf-reaction-share {
  cursor: default;
}

span.sf-reaction-comment-count {
  cursor: default;
}

/* ---------- Reaction picker popover ---------- */
.sf-reaction-picker-popover {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 0;
  z-index: 1050;
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 999px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
  padding: 4px 6px;
  animation: sf-pop-in 120ms ease-out;
}

.sf-reaction-picker-popover.is-below {
  bottom: auto;
  top: calc(100% + 6px);
}

.sf-reaction-picker-row {
  display: flex;
  gap: 2px;
  align-items: center;
}

.sf-reaction-picker-chip {
  position: relative;
  background: transparent;
  border: none;
  border-radius: 50%;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.25rem;
  line-height: 1;
  transition: transform 100ms ease-out, background 100ms ease-out;
  cursor: pointer;
}

.sf-reaction-picker-chip:hover {
  transform: scale(1.25);
  background: #f3f4f6;
}

.sf-reaction-picker-chip.sf-tier-action {
  box-shadow: inset 0 0 0 2px #0d9488;
  /* teal border per PRD §7.1 */
}

.sf-reaction-picker-chip .sf-tier-badge {
  position: absolute;
  top: -2px;
  right: -2px;
  font-size: 0.65rem;
  color: #0d9488;
}

@keyframes sf-pop-in {
  from {
    opacity: 0;
    transform: translateY(4px) scale(0.96);
  }

  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* ---------- Admin palette editor (Settings → General → Reactions) ----------
   The chips rendered by apps/news_feed/shared/_reaction_palette_picker.
   Distinct from .sf-reaction-picker-chip above (the reader-facing popover):
   this one is a labelled pill whose whole job is to show which of the 14
   catalog keys are in the business's active palette. Element selectors so
   these win over Bootstrap's .btn / .btn-sm without !important. */
button.sf-reaction-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.35rem 0.75rem;
  border: 1px solid #e5e7eb;
  border-radius: 999px;
  background: #fff;
  color: #57606a;
  font-weight: 500;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}

button.sf-reaction-chip:hover {
  background: #f6f8fa;
  border-color: #d0d7de;
  color: #24292f;
}

/* Selected == the reaction is part of the active palette. */
button.sf-reaction-chip.is-selected {
  background: #eff6ff;
  border-color: var(--bs-primary, #0d6efd);
  color: var(--bs-primary, #0d6efd);
  font-weight: 600;
}

/* A shape cue as well as a colour one, so the on/off state survives
   greyscale printing and the common colour-vision deficiencies. */
button.sf-reaction-chip.is-selected::before {
  content: "\2713";
  font-weight: 600;
  line-height: 1;
}

/* Teal marks action-oriented keys everywhere else in the app
   (.sf-reaction-picker-chip.sf-tier-action) — keep that meaning here, where
   it matters most: an enabled action key is what feeds the Signals pipeline. */
button.sf-reaction-chip.sf-tier-action.is-selected {
  background: #f0fdfa;
  border-color: #0d9488;
  color: #0f766e;
}

/* Off keys read as muted rather than merely uncoloured. */
button.sf-reaction-chip:not(.is-selected) .sf-reaction-glyph {
  opacity: 0.45;
}

/* The shared .sf-reaction-glyph rule paints a white bubble + ring for the
   feed's overlapping reactor cluster; inside a flat editor chip that bubble
   fights the chip's own fill. */
button.sf-reaction-chip .sf-reaction-glyph {
  background: transparent;
  box-shadow: none;
  padding: 0;
}

/* Keyboard focus. AdminKit's `.btn:focus-visible` is (0,2,0) and so OUTRANKS the
   base chip rule (0,1,1) above; it resolves background/border/colour/box-shadow
   against --bs-btn-hover-* custom properties that a bare `.btn` (no colour
   variant — which is exactly what a chip is) never defines, so all four collapse
   to transparent/none, and it finishes with `outline: 0`. Result without these
   rules: tabbing onto an unselected chip makes it dissolve to bare text with no
   focus indicator anywhere in the 14-chip grid. Element+class selectors put us
   back above it. Same remedy as the poll option buttons further down. */
button.sf-reaction-chip:focus-visible {
  background: #fff;
  border-color: #d0d7de;
  color: #24292f;
  outline: 3px solid var(--bs-primary, #0d6efd);
  outline-offset: 2px;
  box-shadow: none;
}

button.sf-reaction-chip.is-selected:focus-visible {
  background: #eff6ff;
  border-color: var(--bs-primary, #0d6efd);
  color: var(--bs-primary, #0d6efd);
}

button.sf-reaction-chip.sf-tier-action.is-selected:focus-visible {
  background: #f0fdfa;
  border-color: #0d9488;
  color: #0f766e;
}

/* `.is-selected` is later in source than `:hover` and equally specific, so a
   selected chip had no hover feedback at all. Border only — the fill stays in
   its own colour family (blue vs teal). */
button.sf-reaction-chip.is-selected:hover {
  border-color: #0a58ca;
}

button.sf-reaction-chip.sf-tier-action.is-selected:hover {
  border-color: #0f766e;
}

/* Shared by the editor chips and the "Keys marked ⚡" line above them. The
   popover's own rule (which also positions it) keeps its higher specificity. */
.sf-tier-badge {
  color: #0d9488;
  font-size: 0.75rem;
}

/* ---------- Reactor sheet (bottom sheet on mobile / center card desktop) ---------- */
.sf-reactor-sheet-backdrop {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}

.sf-reactor-sheet {
  background: #fff;
  border-radius: 12px;
  width: 100%;
  max-width: 420px;
  max-height: 80vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.2);
  animation: sf-pop-in 140ms ease-out;
}

.sf-reactor-sheet__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid #e5e7eb;
}

.sf-reactor-sheet__close {
  font-size: 1.5rem;
  line-height: 1;
  padding: 0 0.5rem;
}

.sf-reactor-sheet__tabs {
  display: flex;
  gap: 0.25rem;
  overflow-x: auto;
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid #e5e7eb;
}

.sf-reactor-sheet__tab {
  background: transparent;
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 0.25rem 0.75rem;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  white-space: nowrap;
  cursor: pointer;
}

.sf-reactor-sheet__tab.is-active {
  background: #eff6ff;
  border-color: #bfdbfe;
  color: #1d4ed8;
}

.sf-reactor-sheet__body {
  overflow-y: auto;
}

.sf-reactor-sheet__list {
  padding: 0.5rem 0;
}

.sf-reactor-sheet__row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 1rem;
}

.sf-reactor-sheet__row:hover {
  background: #f9fafb;
}

/* The clickable avatar+name half of a reactor row — opens that person's
   profile card. Rendered as a bare <button> so it keeps the row's own flex
   metrics (the glyph stays pinned right) while carrying real button
   semantics for keyboard and screen-reader users. */
.sf-reactor-sheet__person {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex: 1;
  min-width: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.sf-reactor-sheet__avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  object-fit: cover;
  background: #f3f4f6;
}

.sf-reactor-sheet__name {
  flex: 1;
  min-width: 0;
  font-size: 0.9rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sf-reactor-sheet__glyph {
  font-size: 1.1rem;
}

/* Bottom sheet on small viewports */
@media (max-width: 576px) {
  .sf-reactor-sheet-backdrop {
    align-items: flex-end;
    padding: 0;
  }

  .sf-reactor-sheet {
    max-width: 100%;
    width: 100%;
    max-height: 75vh;
    border-radius: 16px 16px 0 0;
    animation: sf-slide-up 180ms ease-out;
  }

  @keyframes sf-slide-up {
    from {
      transform: translateY(100%);
    }

    to {
      transform: translateY(0);
    }
  }
}

/* ---------- Composer (New Post popup — design handoff 2026-06-05) ---------- */

/* Modal shell — centered, rounded, sticky header/footer.
   760px, not the 640px of the 2026-06-05 handoff: the footer has since grown a
   fourth control (Requested action, which used to hang outside .modal-content
   entirely), and at 640 the row ran out of room and broke "Save Draft" and
   "Requested action" onto two lines each. The editor and its toolbar get the
   rest of the width. */
.news-feed-composer-modal {
  max-width: 760px;
}

/* A footer control that wraps mid-label reads as broken. The autosave status is
   the only thing here that may shrink, so it is the only thing allowed to. */
.news-feed-composer-modal .modal-footer .btn { white-space: nowrap; }
.news-feed-composer-modal .news-feed-composer__draft-saved { min-width: 0; }

.news-feed-composer-modal .modal-content {
  border: none;
  border-radius: 12px;
  box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.3);
}

.news-feed-composer-modal .modal-header {
  position: sticky;
  top: 0;
  z-index: 2;
  background: #fff;
  border-bottom: 1px solid #eef0f3;
  padding: 18px 24px;
  border-top-left-radius: 12px;
  border-top-right-radius: 12px;
}

.news-feed-composer-modal .modal-header .modal-title {
  font-size: var(--type-title);
  font-weight: 600;
  color: #212529;
}

.news-feed-composer-modal .modal-header .text-muted {
  color: #8a929c !important;
  font-size: var(--type-small);
}

.news-feed-composer-modal .modal-body {
  padding: 20px 24px 24px;
}

.news-feed-composer-modal .modal-footer {
  position: sticky;
  bottom: 0;
  z-index: 2;
  background: #fafbfc;
  border-top: 1px solid #eef0f3;
  padding: 14px 24px;
  display: flex;
  align-items: center;
  gap: 8px;
  border-bottom-left-radius: 12px;
  border-bottom-right-radius: 12px;
}

/* Inline card variant — same density adjustments */
.news-feed-composer .form-label {
  font-size: var(--type-small);
  font-weight: 600;
  color: #64748b;
}

.news-feed-composer .form-text {
  font-size: var(--type-small);
  line-height: 18px;
}

.news-feed-composer .mb-3 {
  margin-bottom: 20px !important;
}

/* Focus ring consistency */
.news-feed-composer .form-control:focus,
.news-feed-composer .form-select:focus {
  border-color: var(--bs-primary, #3b82f6);
  box-shadow: 0 0 0 3px rgba(var(--bs-primary-rgb, 59, 130, 246), 0.18);
}

/* Draft banner — subtle single line (design handoff). No `.alert` class now,
   so this rule supplies the full border/background. */
.news-feed-composer__draft-banner {
  padding: 8px 12px !important;
  font-size: var(--type-small);
  border-radius: 8px;
  background-color: #f4f7fc !important;
  border: 1px solid #e3eaf4 !important;
}

/* Section labels — small uppercase headers used above each composer field group.
   Specificity must beat .news-feed-composer .form-label (0,2,0). */
.news-feed-composer .news-feed-composer__section-label,
.news-feed-composer__section-label {
  font-size: var(--type-caption);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #8a929c;
  margin-bottom: 10px;
}

/* Type tabs — underline style, blue active */
.news-feed-composer__type-tabs {
  border-bottom: 1px solid #eef0f3;
  padding-bottom: 0;
  margin-bottom: 20px !important;
  gap: 2px;
}

.news-feed-composer__type-tabs .nav-link {
  font-size: inherit;
  font-weight: 500;
  color: #6c757d;
  padding: 13px 14px;
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  margin-bottom: -1px;
  background: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

.news-feed-composer__type-tabs .nav-link:hover:not(.disabled):not(.active) {
  color: var(--bs-primary, #2e63b3);
  border-bottom-color: transparent;
}

.news-feed-composer__type-tabs .nav-link.active {
  color: var(--bs-primary, #2e63b3);
  font-weight: 600;
  border-bottom-color: var(--bs-primary, #2e63b3);
  background: none;
}

/* Editor header row — section label on the left, Edit/Preview pill on the right */
.news-feed-composer__editor-header {
  margin-bottom: 9px;
}

/* Edit / Preview — compact segmented pill control */
.news-feed-composer__edit-preview {
  display: inline-flex;
  border: 1px solid #dde1e7;
  border-radius: 6px;
  overflow: hidden;
  list-style: none;
  margin: 0;
  padding: 0;
}

.news-feed-composer__edit-preview .nav-link {
  font-size: var(--type-small);
  font-weight: 500;
  color: #6c757d;
  background: #fff;
  padding: 0.3rem 0.68rem;
  border: none;
  border-radius: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.news-feed-composer__edit-preview .nav-item + .nav-item .nav-link {
  border-left: 1px solid #dde1e7;
}

.news-feed-composer__edit-preview .nav-link.active {
  background: #eef3f9;
  color: var(--bs-primary, #2e63b3);
  font-weight: 600;
}

/* Toolbar — compact, sits inside the editor border (no own border) */
.news-feed-composer-toolbar {
  background: #f8f9fb !important;
  border: none !important;
  border-bottom: 1px solid #e6e9ee !important;
  border-radius: 8px 8px 0 0 !important;
  padding: 6px 8px !important;
  gap: 1px !important;
  flex-wrap: nowrap !important;
  overflow-x: auto;
}

.news-feed-composer-toolbar .btn {
  font-size: var(--type-caption);
  padding: 3px 6px;
  white-space: nowrap;
  color: #5a6572;
}

.news-feed-composer-toolbar .btn:hover {
  background: #e9edf2;
  color: var(--bs-primary, #2e63b3);
}

.news-feed-composer-toolbar__divider {
  display: inline-block;
  width: 1px;
  height: 18px;
  background: #dde1e7;
  margin: 0 5px;
  align-self: center;
  flex-shrink: 0;
}

/* Edit-pane uses flex column so we can reorder the AI strip below the
   editor box without restructuring the DOM (preserves Stimulus targets). */
.news-feed-composer__editor [data-news-feed--markdown-toolbar-target="editPane"] {
  display: flex;
  flex-direction: column;
}

/* AI strip placed last so it always renders below the editor + counter. */
.news-feed-composer__editor [data-news-feed--markdown-toolbar-target="editPane"] .news-feed-composer__ai-strip {
  order: 3;
  margin-top: 12px;
  margin-bottom: 0;
}

.news-feed-composer__editor [data-news-feed--markdown-toolbar-target="editPane"] .news-feed-enhance-diff {
  order: 4;
  margin-top: 8px;
  margin-bottom: 0;
}

.news-feed-composer__editor [data-news-feed--markdown-toolbar-target="editPane"] .news-feed-composer__editor-box {
  order: 1;
}

.news-feed-composer__editor [data-news-feed--markdown-toolbar-target="editPane"] .news-feed-composer__char-counter {
  order: 2;
}

/* Editor box — wraps toolbar + textarea in a single bordered container */
.news-feed-composer__editor-box {
  border: 1px solid #ced4da;
  border-radius: 8px;
  background: #fff;
}

/* Floating mic — 34x34 circle at bottom-right of the textarea (design handoff). */
.news-feed-composer__mic-slot {
  position: absolute;
  right: 10px;
  bottom: 10px;
  z-index: 2;
}

.news-feed-composer__mic-slot .btn,
.news-feed-composer__mic-slot button[data-news-feed--voice-recorder-target="triggerButton"] {
  width: 34px;
  height: 34px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid #ced4da;
  background: #fff;
  color: #6c757d;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.news-feed-composer__mic-slot .btn:hover,
.news-feed-composer__mic-slot button[data-news-feed--voice-recorder-target="triggerButton"]:hover {
  background: #eef3f9;
  color: var(--bs-primary, #2e63b3);
  border-color: var(--bs-primary, #2e63b3);
}

/* Char counter — text below the editor box, right-aligned */
.news-feed-composer__char-counter {
  text-align: right;
  font-size: var(--type-small);
  color: #adb5bd;
  margin-top: 6px;
}

.news-feed-composer__char-counter small {
  font-size: var(--type-small);
  color: #adb5bd;
}

/* Textarea — seamless join with toolbar, no border, full padding */
.news-feed-composer__editor textarea.form-control {
  border: none !important;
  border-radius: 0 !important;
  resize: vertical;
  min-height: 156px;
  padding: 13px 52px 13px 15px;
  font-size: inherit;
  line-height: 1.6;
}

.news-feed-composer__editor textarea.form-control:focus {
  box-shadow: none !important;
  border-color: transparent !important;
}

/* (Old char-overlay removed — counter now sits below the editor box.) */

/* Priority pills — soft, rounded, no dark wrapper */
.news-feed-composer__priority .btn-group {
  gap: 6px;
  border: none;
}

.news-feed-composer__priority .btn-check+.news-feed-composer__priority-pill {
  border: 1px solid #d1d5db;
  border-radius: 999px !important;
  padding: 4px 14px;
  height: 32px;
  font-size: var(--type-small);
  font-weight: 500;
  background: transparent;
  color: #475569;
  transition: all 0.15s ease;
}

.news-feed-composer__priority .btn-check+.news-feed-composer__priority-pill:hover {
  background: #f8fafc;
  border-color: #94a3b8;
}

.news-feed-composer__priority .btn-check:checked+.news-feed-composer__priority-pill {
  box-shadow: none;
}

.news-feed-composer__priority .btn-check[value="must_read"]:checked+.news-feed-composer__priority-pill {
  background: var(--bs-danger, #dc3545);
  border-color: var(--bs-danger, #dc3545);
  color: var(--bs-on-danger, #fff);
}

.news-feed-composer__priority .btn-check[value="must_read"]:checked+.news-feed-composer__priority-pill .text-danger,
.news-feed-composer__priority .btn-check[value="operational"]:checked+.news-feed-composer__priority-pill .text-primary,
.news-feed-composer__priority .btn-check[value="social"]:checked+.news-feed-composer__priority-pill .text-success {
  color: #fff !important;
}

.news-feed-composer__priority .btn-check[value="operational"]:checked+.news-feed-composer__priority-pill {
  background: var(--bs-primary, #2e63b3);
  border-color: var(--bs-primary, #2e63b3);
  color: var(--bs-on-primary, #fff);
}

.news-feed-composer__priority .btn-check[value="social"]:checked+.news-feed-composer__priority-pill {
  background: var(--bs-success, #1cbb8c);
  border-color: var(--bs-success, #1cbb8c);
  color: var(--bs-on-success, #fff);
}

.news-feed-composer__priority .btn-check:disabled+.news-feed-composer__priority-pill {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Bootstrap's `d-flex` defeats the HTML `hidden` attribute (display: flex
   wins over display: none from the user-agent style). Restore the
   expected hide-when-hidden behavior for composer rows.
   `d-block` (display: block !important) defeats it the same way, so the
   AI-enhance error banner is listed here too — its 5s auto-dismiss only sets
   `hidden`, leaving the red message on screen forever without this rule.
   The voice recorder's warning line is the same shape (`.d-block` + a JS
   `hidden` toggle in _showWarning), so it holds its margin-top gap open under
   the transcript on every recording. */
.news-feed-composer__media-count[hidden],
.news-feed-composer__expiry[hidden],
.news-feed-composer__draft-banner[hidden],
[data-news-feed--enhance-target="error"][hidden],
[data-news-feed--voice-recorder-target="warning"][hidden] {
  display: none !important;
}

/* Priority hint — icon + per-priority help text below the pills */
.news-feed-composer__priority-hint {
  font-size: var(--type-small);
  color: #6c757d;
  gap: 7px;
}

.news-feed-composer__priority-hint i {
  font-size: var(--type-caption);
  color: #adb5bd;
}

/* ---------- Audience chip multi-select (design handoff) ---------- */
.news-feed-audience-picker {
  position: relative;
}

.news-feed-audience-picker__control {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  min-height: 42px;
  border: 1px solid #ced4da;
  border-radius: 8px;
  padding: 6px 40px 6px 10px;
  background: #fff;
  cursor: pointer;
  position: relative;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.news-feed-audience-picker__control:focus,
.news-feed-audience-picker__control.is-open {
  outline: none;
  border-color: #86b7fe;
  box-shadow: 0 0 0 0.2rem rgba(var(--bs-primary-rgb, 13, 110, 253), 0.18);
}

.news-feed-audience-picker__chips {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
  flex: 1;
}

.news-feed-audience-picker__placeholder {
  color: #adb5bd;
  font-size: inherit;
  padding: 4px 0;
}

.news-feed-audience-picker__chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: #e7eefb;
  color: var(--bs-primary, #2e63b3);
  font-size: var(--type-small);
  font-weight: 500;
  padding: 4px 9px;
  border-radius: 6px;
}

.news-feed-audience-picker__chip i {
  font-size: var(--type-caption);
}

.news-feed-audience-picker__chip-remove {
  cursor: pointer;
  margin-left: 1px;
  opacity: 0.7;
  line-height: 1;
}

.news-feed-audience-picker__chip-remove:hover {
  opacity: 1;
}

.news-feed-audience-picker__caret {
  position: absolute;
  right: 13px;
  top: 50%;
  transform: translateY(-50%);
  color: #6c757d;
  font-size: var(--type-caption);
  pointer-events: none;
  transition: transform 0.15s;
}

.news-feed-audience-picker__control.is-open .news-feed-audience-picker__caret {
  transform: translateY(-50%) rotate(180deg);
}

.news-feed-audience-picker__menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background: #fff;
  border: 1px solid #e6e9ee;
  border-radius: 8px;
  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
  z-index: 20;
  padding: 6px;
  max-height: 280px;
  overflow-y: auto;
}

.news-feed-audience-picker__option {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  background: transparent;
  transition: background 0.1s;
}

.news-feed-audience-picker__option:hover {
  background: #f8f9fb;
}

.news-feed-audience-picker__option.is-selected {
  background: #f4f7fc;
}

.news-feed-audience-picker__check {
  width: 18px;
  height: 18px;
  border-radius: 4px;
  border: 1.5px solid #ced4da;
  background: #fff;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.news-feed-audience-picker__option.is-selected .news-feed-audience-picker__check {
  border-color: var(--bs-primary, #2e63b3);
  background: var(--bs-primary, #2e63b3);
}

.news-feed-audience-picker__option.is-selected .news-feed-audience-picker__check::after {
  content: "\f00c";
  font-family: "Font Awesome 6 Free";
  font-weight: 900;
  color: #fff;
  font-size: var(--type-caption);
}

.news-feed-audience-picker__icon {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: #eef3f9;
  color: var(--bs-primary, #2e63b3);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: 13px;
}

.news-feed-audience-picker__option-body {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.news-feed-audience-picker__option-label {
  font-size: inherit;
  font-weight: 500;
  color: #212529;
}

.news-feed-audience-picker__option-sub {
  font-size: var(--type-caption);
  color: #8a929c;
}

.news-feed-audience-picker__reach {
  font-size: var(--type-small);
  color: #6c757d;
}

.news-feed-audience-picker__reach i {
  font-size: var(--type-caption);
  color: #adb5bd;
}

.news-feed-audience-picker__reach strong {
  color: #495057;
  font-weight: 600;
  margin: 0 3px;
}

/* Schedule — toggle-style row matching the design */
.news-feed-composer__schedule summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  border: 1px solid #e6e9ee;
  border-radius: 8px;
  padding: 12px 14px;
  color: #212529;
  font-size: inherit;
  font-weight: 500;
  transition: border-color 0.15s ease;
}

.news-feed-composer__schedule summary::before {
  content: "\f017"; /* fa-clock */
  font-family: "Font Awesome 6 Free";
  font-weight: 900;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: #eef3f9;
  color: var(--bs-primary, #2e63b3);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: var(--type-small);
  margin-right: 11px;
}

.news-feed-composer__schedule summary > i.fa-clock,
.news-feed-composer__schedule summary > .fa-clock {
  /* Hide the legacy inline icon — the ::before pseudo replaces it */
  display: none;
}

.news-feed-composer__schedule-text {
  display: inline-flex;
  flex-direction: column;
  flex: 1;
}

.news-feed-composer__schedule-title {
  font-size: inherit;
  font-weight: 500;
  color: #212529;
}

.news-feed-composer__schedule-sub {
  font-size: var(--type-small);
  color: #8a929c;
  font-weight: 400;
}

/* Sub-line follows the toggle state — off copy by default, on copy when open */
.news-feed-composer__schedule [data-on] {
  display: none;
}

.news-feed-composer__schedule[open] [data-off] {
  display: none;
}

.news-feed-composer__schedule[open] [data-on] {
  display: inline;
}

.news-feed-composer__schedule summary::after {
  content: "";
  width: 44px;
  height: 24px;
  border-radius: 50rem;
  background-color: #ced4da;
  background-image: radial-gradient(circle 10px at 12px 12px, #fff 99%, transparent 100%);
  flex-shrink: 0;
  margin-left: auto;
  transition: background-color 0.15s ease, background-image 0.15s ease;
}

.news-feed-composer__schedule[open] summary::after {
  background-color: var(--bs-primary, #2e63b3);
  background-image: radial-gradient(circle 10px at 32px 12px, #fff 99%, transparent 100%);
}

.news-feed-composer__schedule summary:hover {
  border-color: #ced4da;
}

.news-feed-composer__schedule .mt-2 {
  margin-top: 10px !important;
  background: #f8f9fb;
  border: 1px solid #e6e9ee;
  border-radius: 8px;
  padding: 12px 14px;
}

/* Footer row — inside the form so Stimulus targets remain reachable */
.news-feed-composer__footer-row {
  gap: 8px;
  border-top: 1px solid #eef0f3;
  padding-top: 14px !important;
}

/* In the modal variant the footer-row bleeds to the body edges and gets
   the gray background + rounded bottom corners. */
.news-feed-composer-modal .modal-body .news-feed-composer__footer-row {
  background: #fafbfc;
  margin: 20px -24px -24px;
  padding: 14px 24px !important;
  border-bottom-left-radius: 12px;
  border-bottom-right-radius: 12px;
}

.news-feed-composer__draft-saved {
  font-size: var(--type-small);
  color: #adb5bd !important;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.news-feed-composer__footer-row .news-feed-composer__autosave-status {
  font-size: var(--type-caption);
  color: #9ca3af;
}
/* PRD 05 Unit 6 — reserve vertical space for poll result rows so the
   card doesn't reflow when the live-update handler swaps voting UI for
   results. --sf-poll-rows is set inline by _poll.html.erb to the option
   count; 44px matches the per-row height (label + 6px bar + margin). */
.news-feed-poll {
  min-height: calc(var(--sf-poll-rows, 4) * 44px);
}

/* PRD 05 Unit 11 — presentation mode (FR-05-13). The poll card is portaled
   into a <dialog> and scaled up for town-hall projection. Hidden on mobile
   since the use case is desktop/projected. */
.news-feed-poll-presentation {
  width: min(90vw, 1100px);
  max-width: 1100px;
  max-height: 90vh;
  padding: 3rem 3.5rem;
  border: 0;
  border-radius: 12px;
  overflow: auto;
  font-size: 1.5em;
}

.news-feed-poll-presentation::backdrop {
  background: rgba(0, 0, 0, 0.7);
}

.news-feed-poll-presentation__close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  font-size: 0.875rem;
}

.news-feed-poll-presentation .news-feed-poll .progress {
  height: 16px !important;
}

.news-feed-poll-presentation .news-feed-poll h3 {
  font-size: 1.75em;
  margin-bottom: 1.25rem;
}

.news-feed-poll-presentation .news-feed-poll-present-row {
  display: none;
}

@media (max-width: 767.98px) {
  .news-feed-poll-present { display: none; }
}

/* PRD 05 Unit 13 — visible keyboard focus ring for poll option buttons.
   Bootstrap's default :focus ring is dropped on .btn-outline-* when the
   button has .active, so we restore a 3:1-contrast ring via focus-visible
   only (keyboard users only, not mouse click). */
.news-feed-poll [data-news-feed--poll-vote-target="optionButton"]:focus-visible {
  outline: 3px solid var(--bs-primary, #0d6efd);
  outline-offset: 2px;
  box-shadow: none;
}

.news-feed-poll-presentation__close:focus-visible {
  outline: 3px solid var(--bs-primary, #0d6efd);
  outline-offset: 2px;
}

/* PRD 07 — AI Enhance diff highlight colors and toolbar layout. */
.news-feed-enhance__add {
  background: rgba(46, 160, 67, 0.18);
  text-decoration: none;
}
.news-feed-enhance__remove {
  background: rgba(207, 34, 46, 0.18);
  text-decoration: line-through;
}
.news-feed-enhance__diff-body {
  white-space: pre-wrap;
  word-break: break-word;
}
@media (max-width: 575.98px) {
  /* Tone pills scroll horizontally on narrow screens (PRD §7.2). */
  .news-feed-enhance-toolbar .btn-group {
    overflow-x: auto;
    flex-wrap: nowrap;
  }
}

/* PRD 08 Phase 7 — Read Aloud player. Hidden until a feed-card speaker
   button enqueues something; the controller toggles `is-active` to reveal. */
.news-feed-read-aloud-player {
  display: none;
  position: sticky;
  /* Clear the platform navbar. custom.css pins `.navbar` `position: fixed;
     top: 0; z-index: 1030 !important`, and `body.authenticated` compensates with
     `padding-top: 56px` — but sticky `top` is measured against the VIEWPORT, which
     that body padding does not shift. At `top: 0` the bar pinned inside the band
     the navbar occupies, and with both at z-index 1030 in the root stacking
     context the later element (this one) won: playback covered global search, the
     notification bell and the account menu. 56px is the same navbar height
     custom.css uses; 1020 keeps it under the navbar either way. */
  top: 56px;
  z-index: 1020;
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  padding: 8px 12px;
  margin-bottom: 1rem;
}

.news-feed-read-aloud-player.is-active {
  display: block;
}

/* PRD 11 §7.1 — topic chip strip. Muted background, 12sp / 0.75rem,
 * min 28px height for touch targets. */
.news-feed-topic-chips {
  padding-left: 0;
}

/* A topic name is authored (admin-created, or a #hashtag lifted out of a post
   body), so a chip can hold one long unbroken token. Untreated the chip is a
   single unshrinkable inline-flex box: measured 1431px inside the 1158px feed
   filter card, which burst the card and took 261px of the page with it
   (ISS-20260903-353-B1C4BF). max-width pins the chip to its container and
   `anywhere` is what actually lets the token break — `break-word` is ignored
   when honouring it would change the box's min-content width, which is exactly
   this case. min-width on the flex line keeps the text run shrinkable. */
/* Fill, size and radius follow the 2026-09-17 feed comp's `.nf-chip` so the
   chips on a post, on a comment and in the rail's Topics panel are one
   component rather than three near-misses. */
.news-feed-topic-chip {
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  min-width: 0;
  overflow-wrap: anywhere;
  min-height: 26px;
  padding: 0 10px;
  border-radius: 50rem;
  background-color: #f8f9fa;
  color: #6c757d;
  font-size: var(--type-small);
  font-weight: 500;
  line-height: 1.2;
  text-decoration: none;
  border: 1px solid transparent;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.news-feed-topic-chip:hover,
.news-feed-topic-chip:focus-visible {
  background-color: #f1f3f5;
  color: #495057;
  text-decoration: none;
  outline: none;
  border-color: #c5cfdb;
}

.news-feed-topic-chip:focus-visible {
  box-shadow: 0 0 0 2px rgba(var(--bs-primary-rgb, 13, 110, 253), 0.25);
}

.news-feed-topic-chip--overflow {
  background-color: transparent;
  color: #6c757d;
  cursor: default;
}

.news-feed-topic-chip--overflow:hover {
  background-color: transparent;
  color: #6c757d;
  border-color: transparent;
}

/* Layer-3 relevance (design-principle doc) — followed-topic star on chips.
   The star is the explainability affordance for the social-tier ordering
   boost: "you follow this, so it surfaced higher". */
.news-feed-topic-chip__followed-star {
  font-size: var(--type-caption);
  margin-left: 4px;
  color: #b8860b;
}

.news-feed-topic-chip--followed {
  border-color: #e6d9a8;
  background-color: #fdf8e7;
}

.news-feed-topic-chip--followed:hover,
.news-feed-topic-chip--followed:focus-visible {
  background-color: #f7efd2;
  border-color: #d9c98a;
}

/* App-contributed posts: the contributor topic chip is tinted — immutable, no
   edit affordance. The words "via Contests" are on the byline
   (apps/news_feed/shared/_delegated_byline), not on the chip. */
.news-feed-topic-chip--provenance {
  border-color: #d3dce6;
  background-color: #f4f7fa;
}

/* PRD 11 §7.1 — active-filter chip ribbon at the top of the feed. */
.news-feed-active-filter__chip {
  display: inline-flex;
  align-items: center;
  padding: 4px 12px;
  border-radius: 999px;
  background-color: #fff3cd;
  color: #664d03;
  font-size: 0.85rem;
  border: 1px solid #ffe69c;
}

.news-feed-active-filter__clear {
  color: #664d03;
  text-decoration: none;
  font-weight: 600;
  line-height: 1;
  padding: 0 2px;
}

.news-feed-active-filter__clear:hover,
.news-feed-active-filter__clear:focus-visible {
  color: #523c01;
  text-decoration: none;
  outline: none;
}

/* PRD 11 §5.2 — Composer "AI suggests …" chip strip. Sits below the
 * textarea, only visible when the suggestions endpoint returns slugs. */
.news-feed-topic-suggestions {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  background-color: #f4f7fb;
  border: 1px dashed #c5cfdb;
  border-radius: 8px;
  font-size: 0.8rem;
}

.news-feed-topic-suggestions__label {
  color: #495057;
  font-weight: 500;
  flex-shrink: 0;
}

.news-feed-topic-suggestions__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  flex: 1 1 auto;
}

.news-feed-topic-suggestion-chip {
  display: inline-flex;
  align-items: center;
  background-color: #fff;
  border: 1px solid #c5cfdb;
  border-radius: 14px;
  padding: 2px 4px 2px 10px;
  font-size: 0.75rem;
  line-height: 1.2;
}

.news-feed-topic-suggestion-chip__label {
  margin-right: 4px;
}

.news-feed-topic-suggestion-chip__close {
  background: transparent;
  border: 0;
  color: #6c757d;
  font-size: 0.95rem;
  line-height: 1;
  padding: 0 4px;
  cursor: pointer;
  border-radius: 50%;
}

.news-feed-topic-suggestion-chip__close:hover,
.news-feed-topic-suggestion-chip__close:focus-visible {
  background-color: #f1f3f5;
  color: #1f2d3d;
  outline: none;
}

.news-feed-topic-suggestions__action {
  flex-shrink: 0;
  padding: 0 6px;
  text-decoration: none;
  color: #6c757d;
  font-size: 0.95rem;
}

.news-feed-topic-suggestions__action:hover {
  color: #1f2d3d;
  text-decoration: none;
}

/* PRD 18 §7.2 — sticky Must-Read CTA on mobile; in-flow on desktop. */
@media (max-width: 767.98px) {
  .news-feed-must-read-cta-sticky {
    position: sticky;
    bottom: 0;
    z-index: 1020;
    background: rgba(255, 255, 255, 0.96);
    padding: 12px;
    border-top: 1px solid #dee2e6;
    margin-left: -1rem;
    margin-right: -1rem;
  }
  .news-feed-must-read-cta-sticky .btn {
    min-height: 48px;
  }
  /* Analytics drawer renders as a bottom sheet on mobile. */
  .offcanvas-bottom.news-feed-analytics-drawer {
    height: 80vh;
    border-top-left-radius: 16px;
    border-top-right-radius: 16px;
  }
}

/* ============================================================================
   Signals dashboard — interactive type pills + filter bar (PRD 10 §7.1)
   Colors mirror the design system signal taxonomy (colors_and_type.css).
   ========================================================================== */
.news-feed-signals__types {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

/* Base pill (shared by the "All types" link and each type label). */
.news-feed-signals__pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid transparent;
  border-radius: 50rem;
  padding: 0.4rem 0.95rem;
  font-size: var(--type-small);
  font-weight: 600;
  line-height: 1.4;
  cursor: pointer;
  color: #fff;
  opacity: 0.82;
  transition: opacity 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
  text-decoration: none;
  user-select: none;
}
.news-feed-signals__pill:hover {
  opacity: 1;
  color: #fff;
}
.news-feed-signals__pill.is-empty {
  opacity: 0.45;
}
.news-feed-signals__pill-count {
  font-weight: 600;
}
.news-feed-signals__pill-check {
  display: none;
  font-size: var(--type-caption);
}
.btn-check:checked + .news-feed-signals__pill {
  opacity: 1;
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.28);
}
.btn-check:checked + .news-feed-signals__pill .news-feed-signals__pill-check {
  display: inline-block;
}

/* "All types" pill — neutral, turns brand-blue when no type is selected. */
.news-feed-signals__pill--all {
  background: #fff;
  color: #495057;
  border-color: #ced4da;
  opacity: 1;
}
.news-feed-signals__pill--all:hover {
  background: #f6f8fb;
  color: #495057;
}
.news-feed-signals__pill--all.is-active {
  background: var(--bs-primary, #2e63b3);
  color: var(--bs-on-primary, #fff);
  border-color: var(--bs-primary, #2e63b3);
}

/* Per-type colors. */
.news-feed-signals__pill--question    { background: var(--bs-primary, #2e63b3); }
.news-feed-signals__pill--issue       { background: var(--bs-warning, #fcb92c); color: #5c4400; }
.news-feed-signals__pill--issue:hover { color: #5c4400; }
.news-feed-signals__pill--idea        { background: var(--bs-success, #198754); }
.news-feed-signals__pill--risk        { background: var(--bs-danger, #dc3545); }
.news-feed-signals__pill--decision    { background: var(--bs-info, #0dcaf0); color: #06414c; }
.news-feed-signals__pill--decision:hover { color: #06414c; }
.news-feed-signals__pill--action_item { background: #5a6572; }

/* Sentiment uses an outline treatment (matches the design's outline pill). */
.news-feed-signals__pill--sentiment {
  background: #fff;
  color: #495057;
  border-color: #ced4da;
  opacity: 1;
}
.news-feed-signals__pill--sentiment:hover { color: #495057; }
.btn-check:checked + .news-feed-signals__pill--sentiment {
  background: #eef3f9;
  box-shadow: 0 0 0 2px rgba(var(--bs-primary-rgb, 46, 99, 179), 0.25);
}

/* ============================================================================
   Tabbed feed — category tabs, topic-filter chips, verified-only toggle.
   ========================================================================== */
.news-feed-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  border-bottom: 1px solid #e6e9ee;
}
.news-feed-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 15px;
  margin-bottom: -1px;
  font-size: inherit;
  font-weight: 500;
  color: #6c757d;
  text-decoration: none;
  border-bottom: 2px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.news-feed-tab:hover { color: #495057; }
.news-feed-tab__icon { font-size: 13px; color: #adb5bd; }
.news-feed-tab.is-active {
  color: var(--nf-tab-color, var(--bs-primary, #2e63b3));
  font-weight: 600;
  border-bottom-color: var(--nf-tab-color, var(--bs-primary, #2e63b3));
}
.news-feed-tab.is-active .news-feed-tab__icon { color: var(--nf-tab-color, var(--bs-primary, #2e63b3)); }
.news-feed-tab__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 50rem;
  font-size: var(--type-caption);
  font-weight: 600;
  background: #e9ecef;
  color: #495057;
}
.news-feed-tab.is-active .news-feed-tab__count {
  background: var(--nf-tab-color, var(--bs-primary, #2e63b3));
  color: #fff;
}
.news-feed-tab__count.is-red { background: var(--bs-danger, #dc3545); color: var(--bs-on-danger, #fff); }

/* Topic filter chips (btn-check labels). */
.news-feed-topic-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: 1px solid #dfe3e8;
  background: #fff;
  color: #5a6572;
  border-radius: 50rem;
  padding: 0.3rem 0.8rem;
  font-size: var(--type-small);
  font-weight: 500;
  cursor: pointer;
  line-height: 1.4;
  transition: all 0.15s ease;
}
.news-feed-topic-chip:hover { border-color: #aac0e4; }
.news-feed-topic-chip__check { display: none; font-size: var(--type-caption); }
.btn-check:checked + .news-feed-topic-chip {
  background: var(--bs-primary, #2e63b3);
  border-color: var(--bs-primary, #2e63b3);
  color: var(--bs-on-primary, #fff);
}
.btn-check:checked + .news-feed-topic-chip .news-feed-topic-chip__check { display: inline-block; }

/* "Verified answers only" toggle pill. */
.news-feed-verified-toggle {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--bs-success, #198754);
  background: #fff;
  color: var(--bs-success, #198754);
  border-radius: 50rem;
  padding: 0.38rem 0.85rem;
  font-size: var(--type-small);
  font-weight: 500;
  cursor: pointer;
  line-height: 1.4;
  transition: all 0.15s ease;
}
.news-feed-verified-toggle:hover { background: #f0fdf4; }
.btn-check:checked + .news-feed-verified-toggle {
  background: var(--bs-success, #198754);
  color: var(--bs-on-success, #fff);
}

/* ============================================================================
   Home dashboard — summary metric cards + "Important & unread" list.
   ========================================================================== */
.news-feed-metric { transition: transform 0.15s ease, box-shadow 0.15s ease; }
.news-feed-metric:hover { transform: translateY(-2px); box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.1) !important; }
.news-feed-metric__label { font-size: var(--type-caption); letter-spacing: 0.04em; margin-bottom: 6px; }
.news-feed-metric__value { font-size: var(--type-display); font-weight: 600; line-height: 1; color: #212529; }
.news-feed-metric__icon {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  flex-shrink: 0;
}

.news-feed-dash-list .list-group-item { padding: 14px 16px; }
.news-feed-dash-list .list-group-item:hover { background: #f8fafd; }
.news-feed-dash-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: transparent;
  margin-top: 7px;
  flex-shrink: 0;
}
.news-feed-dash-dot.is-unread { background: var(--bs-primary, #3b7ddd); }
.news-feed-dash-headline {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-height: 1.4;
}
.min-width-0 { min-width: 0; }

/* ============================================================================
   SMEs — managed-topic expert rows.
   ========================================================================== */
.border-dashed { border-style: dashed !important; }
.news-feed-sme-remove { opacity: 0; transition: opacity 0.15s ease; }
.news-feed-sme-expert:hover .news-feed-sme-remove { opacity: 1; }
.news-feed-sme-remove:hover { color: #b02a37 !important; }
@media (hover: none) { .news-feed-sme-remove { opacity: 1; } }

/* ============================================================================
   Composer "New Post" — AI assist now lives in the toolbar as a single "AI"
   dropdown (replaced the old always-on light-blue AI strip).

   The menu uses Popper's fixed strategy (set via data-bs-config on the toggle)
   so it escapes the toolbar's overflow:auto and the scrollable modal-body that
   would otherwise clip it to a single row. The global
   `.dropdown-menu { position: absolute !important }` in
   fixes/dropdown_fixes.css would force it back inside those clips, so this
   higher-specificity rule opts this one menu out.
   ========================================================================== */
.news-feed-composer__ai-menu.dropdown-menu {
  position: fixed !important;
}

/* ============================================================================
   Feed page — approved web comp (2026-09-17).

   The feed's card anatomy, filter card, footer and right rail, as specified by
   the design handed over for this page. Tints and inks are Bootstrap 5.3's
   own subtle/emphasis tokens so a tenant's brand still drives them; the
   fallbacks after each `var()` are the exact values the comp measured on the
   default theme, so an older/overridden token can never blank a surface.

   Everything here is scoped to `nf-` classes rather than Bootstrap's `.card`
   family: `body.mgx-restyle` re-skins `.card`, `.card-header` and
   `.card-footer` app-wide (custom.css), and a feed card that opted into those
   selectors would be re-skinned back out of this design.
   ========================================================================== */

:root {
  --nf-line:      #dee2e6;   /* card + control border */
  /* #4076 (2026-09-27): the fills and the grey inks are the theme's own
     tokens (Bootstrap's secondary/tertiary grounds equal the comp's values in
     the light theme), so the feed follows the dark theme; the dark block at
     the end of this section re-points the rest. #6c757d read 4.44:1 on the
     chip fill and 4.21:1 on the count pill; the theme's secondary ink clears
     4.5:1 on both, in both themes. */
  --nf-divider:   var(--bs-secondary-bg, #f1f3f5);   /* inner hairline */
  --nf-surface:   var(--bs-tertiary-bg, #f8f9fa);   /* chip / placeholder fill */
  --nf-ink:       #000;
  --nf-body-ink:  #495057;
  --nf-muted:     var(--bs-secondary-color, #6c757d);
  --nf-faint:     var(--bs-secondary-color, #6c757d); /* was #adb5bd — 2.07:1 on white; meta text must clear AA (/design-pass communications 2026-09-24) */
  --nf-radius:    0.5rem;
  --nf-radius-sm: 0.2rem;
  --nf-shadow:    0 0.1rem 0.2rem rgba(0, 0, 0, 0.05);
}

/* ---------- Page shell ---------- */
.nf-feed-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  align-items: flex-start;
}
.nf-feed-main {
  flex: 1 1 560px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.nf-feed-rail {
  flex: 1 1 280px;
  max-width: 320px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
/* Sticky only where there is room to scroll past it; below the wrap point the
   rail is stacked under the feed and sticking it would pin it to the viewport
   for the rest of the page. */
@media (min-width: 992px) {
  .nf-feed-rail { position: sticky; top: 96px; }
}

.nf-page-title { font-size: var(--type-page); line-height: 1.2; color: var(--nf-ink); }
.nf-page-sub   { font-size: var(--type-small); color: var(--nf-muted); margin-top: 4px; }

/* ---------- Card ---------- */
.nf-card {
  background: var(--bs-card-bg, #fff);
  border: 1px solid var(--nf-line);
  border-radius: var(--nf-radius);
  box-shadow: var(--nf-shadow);
  transition: transform 0.15s, box-shadow 0.15s;
}
.nf-card--flush { overflow: hidden; }
.nf-card__body { padding: 18px 20px 16px; }
/* Any strip below the body: the acknowledgement callout, the footer. */
.nf-card__bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 16px;
  border-top: 1px solid var(--nf-divider);
}

/* ---------- Badge rail ---------- */
.nf-rail {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}
.nf-rail__spacer { flex: 1 1 0%; }

.nf-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--type-caption);
  font-weight: 600;
  letter-spacing: 0.4px;
  padding: 3px 10px;
  border-radius: 50rem;
  white-space: nowrap;
}
.nf-badge i { font-size: var(--type-caption); }
.nf-badge--danger  { background: var(--bs-danger-bg-subtle,  #fdecec); color: var(--bs-danger-text-emphasis,  #b02a37); }
.nf-badge--primary { background: var(--bs-primary-bg-subtle, #e7f0fc); color: var(--bs-primary-text-emphasis, #1c5ba8); }
.nf-badge--success { background: var(--bs-success-bg-subtle, #e8f8f2); color: var(--bs-success-text-emphasis, #12916c); }
.nf-badge--info    { background: var(--bs-info-bg-subtle,    #e2f4fb); color: var(--bs-info-text-emphasis,    #087990); }
/* Amber is stated as an alpha of its own ink rather than the Bootstrap subtle
   token: --bs-warning-bg-subtle is a yellow light enough that #997404 on it
   reads washed out, and this pill is the "Pinned"/"Expires" pair that has to
   stay legible beside the red one. */
.nf-badge--amber   { background: rgba(153, 116, 4, 0.12); color: var(--bs-on-subtle-warning, #997404); font-weight: 600; letter-spacing: normal; padding: 3px 9px; }
.nf-badge--type    { background: var(--nf-divider); color: var(--nf-muted); font-weight: 600; letter-spacing: 0.3px; text-transform: uppercase; padding: 3px 9px; gap: 0; }
.nf-badge--quiet   { background: var(--nf-surface); color: var(--nf-faint); font-weight: 600; letter-spacing: normal; padding: 3px 9px; gap: 0; }

.nf-expiry {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--type-caption);
  color: var(--bs-on-subtle-warning, #997404); /* #997404 read 4.32:1 on the card (#4076) */
  white-space: nowrap;
}
.nf-expiry i { font-size: var(--type-caption); }
.nf-unread-dot {
  width: 8px;
  height: 8px;
  border-radius: 50rem;
  background: var(--bs-primary, #3b7ddd);
  flex-shrink: 0;
}

/* ---------- Byline ---------- */
.nf-byline { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.nf-byline__name { font-size: inherit; font-weight: 600; color: var(--nf-ink); }
.nf-byline__meta { font-size: var(--type-caption); color: var(--nf-faint); margin-top: 1px; }
.nf-byline__menu {
  width: 32px;
  height: 32px;
  border-radius: var(--nf-radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--nf-faint);
  border: 0;
  background: transparent;
}
.nf-byline__menu:hover { background: var(--nf-surface); color: var(--nf-muted); }

/* ---------- Body ---------- */
.nf-title { font-size: var(--type-title); line-height: 1.35; color: var(--nf-ink); margin-bottom: 6px; }
.nf-body  { font-size: inherit; line-height: 1.65; color: var(--nf-body-ink); text-wrap: pretty; }
.nf-body p:last-child { margin-bottom: 0; }

/* ---------- Topic chips ---------- */
.nf-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }
.nf-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 26px;
  padding: 0 10px;
  border-radius: 50rem;
  background: var(--nf-surface);
  color: var(--nf-muted);
  font-size: var(--type-small);
  font-weight: 500;
  text-decoration: none;
  border: 0;
}
.nf-chip:hover { background: var(--nf-divider); color: var(--nf-body-ink); }
.nf-chip--on { background: var(--bs-primary-bg-subtle, #e7f0fc); color: var(--bs-primary-text-emphasis, #1c5ba8); }
/* No opacity (#4076): at .6 the count read 2.22:1 on the chip. Weight sets it apart. */
.nf-chip__count { font-size: var(--type-caption); font-weight: 600; }

/* ---------- Acknowledgement callout ---------- */
.nf-ack {
  background: rgba(252, 185, 44, 0.12);
  color: var(--bs-on-subtle-warning, #8a6100);
  gap: 11px;
  padding: 11px 16px;
}
.nf-ack i { font-size: var(--type-small); flex-shrink: 0; }
.nf-ack__text { flex: 1 1 0%; min-width: 0; font-size: var(--type-small); line-height: 1.45; }
.nf-ack__btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  flex-shrink: 0;
  min-height: 34px;
  padding: 0 16px;
  border: 0;
  border-radius: var(--nf-radius-sm);
  font-size: var(--type-small);
  font-weight: 600;
  background: var(--bs-warning, #fcb92c);
  color: #4a3500;
}
.nf-ack__btn:hover { filter: brightness(0.96); color: #4a3500; }
.nf-ack__btn i { font-size: var(--type-caption); }
/* Acknowledged: the SAME strip, turned green. The comp keeps the geometry and
   the leading glyph and swaps only the tint, the sentence and the button — so
   the card does not reflow when you answer it, and the answer lands where the
   question was. */
.nf-ack--ok { background: rgba(var(--bs-success-rgb, 28, 187, 140), 0.08); color: var(--bs-success-text-emphasis, #12916c); }
.nf-ack__btn--ok {
  background: var(--bs-success-bg-subtle, #e8f8f2);
  color: var(--bs-success-text-emphasis, #12916c);
  cursor: default;
}
.nf-ack__btn--ok:hover { filter: none; color: var(--bs-success-text-emphasis, #12916c); }
/* The neutral variants of the same strip: already acknowledged, window closed,
   not published yet. Same geometry so a card does not change height when its
   state changes. */
.nf-note { gap: 11px; padding: 11px 16px; font-size: var(--type-small); line-height: 1.45; }
.nf-note--ok    { background: var(--bs-success-bg-subtle, #e8f8f2); color: var(--bs-success-text-emphasis, #12916c); }
.nf-note--quiet { background: var(--nf-surface); color: var(--nf-muted); }
.nf-note--info  { background: var(--bs-primary-bg-subtle, #e7f0fc); color: var(--bs-primary-text-emphasis, #1c5ba8); }

/* ---------- Footer ---------- */
.nf-foot__react { display: flex; align-items: center; gap: 6px; }
.nf-quick {
  width: 30px;
  height: 30px;
  border-radius: 50rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: inherit;
  line-height: 1;
  border: 1px solid #e9ecef;
  background: var(--bs-card-bg, #fff);
  padding: 0;
  transition: transform 0.1s;
}
.nf-quick:hover { transform: scale(1.12); }
.nf-quick.is-mine { border-color: var(--bs-primary, #3b7ddd); background: var(--bs-primary-bg-subtle, #e7f0fc); }
.nf-foot__count { font-size: var(--type-small); color: var(--nf-muted); margin-left: 2px; border: 0; background: none; padding: 0; }
.nf-foot__sep { width: 1px; height: 18px; background: #e9ecef; flex-shrink: 0; }
.nf-foot__action {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--type-small);
  color: var(--nf-muted);
  padding: 4px 8px;
  border: 0;
  border-radius: var(--nf-radius-sm);
  background: none;
  text-decoration: none;
}
.nf-foot__action:hover { background: var(--nf-surface); color: var(--nf-body-ink); }
.nf-foot__action i { font-size: var(--type-small); }
.nf-foot__stats {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  font-size: var(--type-small);
  color: var(--nf-muted);
  flex-wrap: wrap;
}
.nf-foot__stats b { font-weight: 600; color: var(--nf-body-ink); }
.nf-foot__link {
  font-weight: 600;
  color: var(--bs-link-color, var(--bs-primary, #3b7ddd));
  border: 0;
  background: none;
  padding: 0;
  text-decoration: none;
}
.nf-foot__link[disabled] { color: var(--nf-faint); }

/* ---------- Filter card ---------- */
.nf-filter { padding: 6px 8px; }
.nf-filter__tabs { display: flex; flex-wrap: wrap; gap: 4px; }
.nf-tab2 {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  flex-shrink: 0;
  min-height: 36px;
  padding: 0 14px;
  border-radius: var(--nf-radius-sm);
  font-size: var(--type-small);
  font-weight: 500;
  color: var(--nf-muted);
  background: transparent;
  text-decoration: none;
  white-space: nowrap;
}
.nf-tab2:hover { background: var(--nf-surface); color: var(--nf-body-ink); }
.nf-tab2 i { font-size: var(--type-caption); }
.nf-tab2.is-active {
  font-weight: 600;
  color: var(--bs-primary-text-emphasis, #1c5ba8);
  background: var(--bs-primary-bg-subtle, #e7f0fc);
  box-shadow: inset 0 -2px 0 var(--bs-primary, #3b7ddd);
}
.nf-tab2__count {
  font-size: var(--type-caption);
  font-weight: 600;
  padding: 1px 7px;
  border-radius: 50rem;
  background: var(--nf-divider);
  color: var(--nf-muted);
}
.nf-tab2__count--danger { background: var(--bs-danger-bg-subtle, #fdecec); color: var(--bs-danger-text-emphasis, #b02a37); }

.nf-filter__sort {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 8px 6px 4px;
  border-top: 1px solid var(--nf-divider);
  margin-top: 6px;
}
.nf-filter__label { font-size: var(--type-caption); color: var(--nf-muted); }
/* The feed's ONE filter row: tabs (what needs you) left, Type and Sort right;
   wraps to two lines on a narrow screen instead of scrolling. */
.nf-filter__row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; }
.nf-filter__row .nf-filter__sort { border-top: 0; margin-top: 0; padding: 2px 4px; }
.nf-filter__select { font-size: var(--type-small); min-height: 32px; padding-top: 4px; padding-bottom: 4px; }
.nf-sortchip {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  padding: 0 11px;
  border-radius: 50rem;
  font-size: var(--type-small);
  font-weight: 500;
  color: var(--nf-muted);
  background: var(--nf-surface);
  text-decoration: none;
}
.nf-sortchip:hover { background: var(--nf-divider); color: var(--nf-body-ink); }
.nf-sortchip.is-active { color: var(--bs-primary-text-emphasis, #1c5ba8); background: var(--bs-primary-bg-subtle, #e7f0fc); }
.nf-toggle2 {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 30px;
  padding: 0 12px;
  border-radius: 50rem;
  font-size: var(--type-small);
  font-weight: 500;
  border: 1px solid var(--nf-line);
  background: var(--bs-card-bg, #fff);
  color: var(--nf-muted);
  cursor: pointer;
  margin-bottom: 0;
}
.nf-toggle2 i { font-size: var(--type-caption); }
.nf-toggle2:hover { background: var(--nf-surface); }
.btn-check:checked + .nf-toggle2 {
  border-color: var(--bs-primary, #3b7ddd);
  background: var(--bs-primary-bg-subtle, #e7f0fc);
  color: var(--bs-primary-text-emphasis, #1c5ba8);
}

/* ---------- Search box ---------- */
.nf-search { position: relative; flex-shrink: 0; }
.nf-search i {
  position: absolute;
  left: 11px;
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--type-caption);
  color: var(--nf-faint);
  pointer-events: none;
}
.nf-search input {
  width: 240px;
  max-width: 100%;
  box-sizing: border-box;
  height: 34px;
  padding: 0 12px 0 32px;
  border: 1px solid #ced4da;
  border-radius: var(--nf-radius-sm);
  background: var(--bs-card-bg, #fff);
  color: var(--nf-body-ink);
  font-size: var(--type-small);
}
/* Beside the header's Post button, the box stretches to the row the button
   sets, so the two read as one row of controls whatever the theme's sizes. */
.nf-header-actions { align-items: stretch; }
.nf-header-actions .nf-search input { height: 100%; font-size: inherit; }

/* ---------- Right-rail panels ---------- */
.nf-panel__head {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--nf-line);
}
.nf-panel__head i { font-size: var(--type-caption); }
.nf-panel__head--danger { background: rgba(var(--bs-danger-rgb, 220, 53, 69), 0.06); }
.nf-panel__title { flex: 1 1 0%; min-width: 0; font-size: var(--type-small); font-weight: 600; color: var(--nf-ink); }
.nf-panel__count {
  font-size: var(--type-caption);
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 50rem;
  background: var(--bs-danger-bg-subtle, #fdecec);
  color: var(--bs-danger-text-emphasis, #b02a37);
}
.nf-panel__row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 16px;
  border-top: 1px solid var(--nf-divider);
  text-decoration: none;
}
.nf-panel__row:first-of-type { border-top: 0; }
.nf-panel__row:hover { background: var(--nf-surface); }
.nf-panel__row-title { font-size: var(--type-small); line-height: 1.4; color: var(--nf-body-ink); text-wrap: pretty; }
.nf-panel__row-meta { font-size: var(--type-caption); color: var(--bs-on-subtle-warning, #997404); margin-top: 3px; }
.nf-panel__pad { padding: 14px 16px; }
.nf-panel__foot {
  display: block;
  padding: 10px 16px;
  border-top: 1px solid var(--nf-divider);
  font-size: var(--type-small);
  font-weight: 600;
  color: var(--bs-link-color, var(--bs-primary, #3b7ddd));
  text-decoration: none;
}
.nf-panel__foot:hover { background: var(--nf-surface); }
.nf-panel__empty { padding: 14px 16px; font-size: var(--type-small); color: var(--nf-muted); }
.nf-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); padding: 14px 16px; gap: 10px; }
.nf-stat { min-width: 0; }
.nf-stat__value { font-size: var(--type-display); line-height: 1.1; color: var(--nf-ink); }
.nf-stat__label { font-size: var(--type-caption); color: var(--nf-muted); margin-top: 3px; }

/* ---------- Documents ----------
   The comp's attachment card: a white tile with a type-coloured glyph, the
   filename, its size beneath, and the action on the right. Replaces a grey
   `bg-light` slab whose only affordance was a bare text link. Used by a post's
   file attachments AND by the policy a Must-Read asks you to accept, so a
   document looks like a document wherever the feed shows one. */
.nf-docs { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.nf-doc-label {
  font-size: var(--type-caption);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--nf-faint);
  margin-bottom: 7px;
}
.nf-doc {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 10px 13px;
  border: 1px solid var(--nf-line);
  border-radius: var(--nf-radius-sm);
  background: var(--bs-card-bg, #fff);
  text-decoration: none;
  transition: border-color 0.12s ease;
}
/* The whole tile is the link, so it must never take the app's global
   `a:hover { text-decoration: underline }` — a card is not a text link, and the
   underline lands on the filename and its meta line together. */
.nf-doc, .nf-doc:hover, .nf-doc:focus { text-decoration: none; }
.nf-doc:hover { border-color: var(--bs-primary, #3b7ddd); }
.nf-doc:hover .nf-doc__name { color: var(--bs-primary-text-emphasis, #1c5ba8); }
.nf-doc__icon { font-size: 20px; line-height: 1; flex-shrink: 0; }
.nf-doc__body { flex: 1 1 auto; min-width: 0; }
.nf-doc__name {
  font-size: var(--type-small);
  color: var(--nf-body-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nf-doc__meta { font-size: var(--type-caption); color: var(--nf-faint); margin-top: 1px; }
.nf-doc__action { flex-shrink: 0; margin-left: 6px; }

/* ---------- Poll ---------- */
.nf-poll { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.nf-poll__row {
  position: relative;
  border: 1px solid var(--nf-line);
  border-radius: var(--nf-radius-sm);
  overflow: hidden;
  background: var(--bs-card-bg, #fff);
  width: 100%;
  padding: 0;
  text-align: left;
}
.nf-poll__row:hover { border-color: var(--bs-primary, #3b7ddd); }
.nf-poll__fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  background: var(--bs-primary-bg-subtle, #e7f0fc);
}
.nf-poll__face {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
}
.nf-poll__label { flex: 1 1 0%; min-width: 0; font-size: var(--type-small); color: var(--nf-body-ink); }
.nf-poll__pct { font-size: var(--type-small); font-weight: 600; color: var(--bs-primary-text-emphasis, #1c5ba8); flex-shrink: 0; }
.nf-poll__meta { font-size: var(--type-caption); color: var(--nf-faint); margin-top: 10px; }

/* ============================================================================
   My Posts — approved web comp (2026-09-17).

   Reuses the feed comp's filter card wholesale (.nf-card / .nf-filter /
   .nf-tab2 / .nf-sortchip) — the two designs draw the same control — and adds
   only what a lifecycle row needs on top: the status/type pill rail, a meta
   line, and a fixed action column.
   ========================================================================== */

.mp-head { display: flex; align-items: flex-start; justify-content: space-between;
           gap: 20px; flex-wrap: wrap; margin-bottom: 20px; }
.mp-head__title { font-size: var(--type-page); line-height: 1.2; color: var(--nf-ink); font-weight: 600; }
.mp-head__sub { font-size: var(--type-small); color: var(--nf-muted); margin-top: 5px; max-width: 640px; text-wrap: pretty; }

.mp-list { display: flex; flex-direction: column; gap: 12px; }

.mp-row {
  background: var(--bs-card-bg, #fff);
  border: 1px solid var(--nf-line);
  border-radius: var(--nf-radius);
  box-shadow: var(--nf-shadow);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.mp-row:hover { transform: translateY(-2px); box-shadow: 0 10px 20px rgba(0, 0, 0, 0.10); }
.mp-row__body { display: flex; align-items: flex-start; gap: 16px; padding: 16px 18px; }
.mp-row__main { flex: 1; min-width: 0; }

/* Pill rail. These are square-ish (.2rem), NOT the feed card's round badges —
   a lifecycle state is a label on a row, not a tag on a post. */
.mp-pills { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 9px; }
.mp-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--type-caption);
  font-weight: 500;
  padding: 2px 9px;
  border-radius: var(--nf-radius-sm);
  border: 1px solid var(--nf-line);
  background: var(--nf-surface);
  color: var(--nf-body-ink);
  white-space: nowrap;
}
.mp-pill i { font-size: var(--type-caption); }
.mp-pill--status { font-weight: 600; }
.mp-pill--draft     { background: var(--nf-surface); color: var(--nf-muted); border-color: var(--nf-line); }
.mp-pill--scheduled { background: var(--bs-primary-bg-subtle, #e7f0fc); color: var(--bs-primary-text-emphasis, #1c5ba8); border-color: rgba(59, 125, 221, 0.25); }
.mp-pill--approval  { background: rgba(252, 185, 44, 0.16); color: var(--bs-on-subtle-warning, #8a6100); border-color: rgba(252, 185, 44, 0.35); }
.mp-pill--published { background: var(--bs-success, #1cbb8c); color: var(--bs-on-success, #fff); border-color: var(--bs-success, #1cbb8c); }
.mp-pill--must      { background: var(--bs-danger-bg-subtle, #fdecec); color: var(--bs-danger-text-emphasis, #b02a37); border-color: rgba(220, 53, 69, 0.25); }

.mp-row__title { font-size: var(--type-title); line-height: 1.4; color: var(--nf-ink); margin-bottom: 6px; text-wrap: pretty; }
.mp-row__excerpt { font-size: var(--type-small); line-height: 1.6; color: var(--nf-muted); margin-bottom: 9px; text-wrap: pretty; }
.mp-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 14px; font-size: var(--type-small); color: var(--nf-faint); }
.mp-meta span { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.mp-meta i { font-size: var(--type-caption); }

/* Acknowledgement progress. The fill colour is a reading of the number, not
   decoration: amber under 60%, brand blue on the way, green once everyone has
   answered. */
.mp-ack { max-width: 360px; margin-top: 12px; }
.mp-ack__row { display: flex; justify-content: space-between; font-size: var(--type-small); color: var(--nf-muted); margin-bottom: 5px; }
.mp-ack__value { font-weight: 600; color: var(--nf-body-ink); }
.mp-ack__track { height: 6px; border-radius: 50rem; background: #e9ecef; overflow: hidden; }
.mp-ack__fill { display: block; height: 100%; border-radius: 50rem; }

/* Action group: natural-width buttons side by side, right-anchored, never squeezed by a long
   headline (flex-shrink: 0 + nowrap is what keeps "Open" from wrapping under its icon). Was a
   152px column of full-width stacked buttons — a second row-action design beside every other
   list in the app (/design-pass communications 2026-09-24; CLAUDE.md: natural button width). */
.mp-actions { display: flex; flex-direction: row; flex-wrap: wrap; justify-content: flex-end; gap: 8px; align-items: flex-start; flex-shrink: 0; }
.mp-actions .btn,
.mp-actions form { width: auto; }
.mp-actions .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 32px;
  padding: 0 12px;
  border-radius: var(--nf-radius-sm);
  font-size: var(--type-small);
  font-weight: 500;
  white-space: nowrap;
}
@media (max-width: 575.98px) {
  .mp-row__body { flex-direction: column; }
  .mp-actions { width: 100%; flex-direction: row; flex-wrap: wrap; }
  .mp-actions .btn, .mp-actions form { width: auto; flex: 1 1 auto; }
}

/* ============================================================================
   Broadcast composer — approved web comp (2026-09-17).
   The page already had the two-column shape and the settings-row drawers; this
   is the state the comp adds around them: what the draft is, what is stopping
   it, and what it will cost a recipient.
   ========================================================================== */

.bc-state {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--type-caption);
  font-weight: 600;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: var(--nf-radius-sm);
  border: 1px solid var(--nf-line);
  background: var(--nf-surface);
  color: var(--nf-muted);
  white-space: nowrap;
}
.bc-state i { font-size: var(--type-caption); }
.bc-state--scheduled { background: var(--bs-primary-bg-subtle, #e7f0fc); color: var(--bs-primary-text-emphasis, #1c5ba8); border-color: rgba(59, 125, 221, 0.25); }
.bc-state--approval  { background: rgba(252, 185, 44, 0.16); color: var(--bs-on-subtle-warning, #8a6100); border-color: rgba(252, 185, 44, 0.35); }
.bc-state--published { background: var(--bs-success, #1cbb8c); color: var(--bs-on-success, #fff); border-color: var(--bs-success, #1cbb8c); }
.bc-saved { font-size: var(--type-small); color: var(--nf-faint); white-space: nowrap; }

/* The blocking banner: says why the primary action will refuse, in the one
   place the author is already looking. */
.bc-blocker {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 11px 16px;
  margin-bottom: 16px;
  border-radius: var(--nf-radius-sm);
  background: rgba(252, 185, 44, 0.12);
  color: var(--bs-on-subtle-warning, #8a6100);
  font-size: var(--type-small);
  line-height: 1.45;
}
.bc-blocker i { flex-shrink: 0; font-size: var(--type-small); }

/* Under the body: what you have written, and how it will read on a phone. */
.bc-body-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 6px;
  font-size: var(--type-small);
  color: var(--nf-faint);
}
.bc-body-foot__link { font-size: var(--type-small); border: 0; background: none; padding: 0; color: var(--bs-link-color, var(--bs-primary, #3b7ddd)); text-decoration: none; }
.bc-body-foot__link:hover { text-decoration: underline; }

.bc-sms-strip {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-top: 10px;
  padding: 11px 16px;
  border-radius: var(--nf-radius-sm);
  background: rgba(252, 185, 44, 0.12);
  color: var(--bs-on-subtle-warning, #8a6100);
  font-size: var(--type-small);
  line-height: 1.45;
}
.bc-sms-strip > i { flex-shrink: 0; font-size: var(--type-small); }
.bc-sms-strip__text { flex: 1 1 auto; min-width: 0; }
.bc-sms-strip__action {
  flex-shrink: 0;
  border: 0;
  background: none;
  padding: 0;
  font-size: var(--type-small);
  font-weight: 600;
  color: var(--bs-on-subtle-warning, #8a6100);
  text-decoration: underline;
  white-space: nowrap;
}

/* "Before it can go out" — the readiness checklist. */
.bc-check__title { font-size: var(--type-small); font-weight: 600; color: var(--nf-ink); margin-bottom: 10px; }
.bc-check__item {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: var(--type-small);
  color: var(--nf-faint);
  padding: 3px 0;
}
.bc-check__item i { font-size: var(--type-small); width: 14px; text-align: center; }
.bc-check__item.is-done { color: var(--nf-body-ink); }
.bc-check__item.is-done i { color: var(--bs-success, #1cbb8c); }

/* ── X2 (cross-app contrast, 2026-09-27): the feed, My Posts and the broadcast
   comp in the DARK theme (#4076). Their cards painted #fff under the dark
   theme's light link ink (2.11:1) with black titles; the grounds above are
   now var(--bs-card-bg) and the fills/greys are theme tokens, so this block
   re-points only the three inks and the hairlines the light theme keeps as
   the comp's literals. ── */
:root[data-theme="dark"] {
  --nf-line:     var(--bs-border-color, #43494f);
  --nf-ink:      var(--bs-heading-color, #e9ecef);
  --nf-body-ink: var(--bs-body-color, #ced4da);
}
:root[data-theme="dark"] .nf-quick,
:root[data-theme="dark"] .nf-search input { border-color: var(--nf-line); }
:root[data-theme="dark"] .nf-foot__sep,
:root[data-theme="dark"] .mp-ack__track { background: var(--nf-line); }
/* ── end X2 ── */
