/*
 * feedback-portal styles (fp-hki).
 *
 * Extracted verbatim from the inline <style> block in
 * web/templates/layout.gohtml so the page can drop 'unsafe-inline'
 * from CSP style-src-elem.
 *
 * The --brand CSS custom property is set per-request via a single
 * inline style attribute on <body> (sourced from the project's brand
 * color, sanitised by render.brandColor). All other rules are static.
 */

:root {
  --brand: #4f46e5; /* fallback; <body style="--brand: ..."> overrides */
  --bg: #fafafa;
  --surface: #ffffff;
  --text: #18181b;
  --text-muted: #71717a;
  --border: #e4e4e7;
  --border-strong: #d4d4d8;
  --radius: 8px;
  --shadow-sm: 0 1px 2px rgba(0,0,0,.04);
  --shadow: 0 1px 3px rgba(0,0,0,.06), 0 1px 2px rgba(0,0,0,.04);
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* Sticky footer: flex column so the .page wrapper grows to fill any
   remaining viewport height on short pages, pinning .site-footer at
   the bottom rather than letting it float halfway up. */
html { min-height: 100%; }
body {
  min-height: 100vh;
  display: flex; flex-direction: column;
  font-family: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, sans-serif;
  font-size: 14px; line-height: 1.5; color: var(--text); background: var(--bg);
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
a:hover { color: var(--brand); }

/* ---- Header ---- */
.site-header {
  position: sticky; top: 0; z-index: 10;
  background: var(--surface); border-bottom: 1px solid var(--border);
  padding: 0 1.5rem;
}
.site-header-inner {
  max-width: 1100px; margin: 0 auto;
  display: flex; align-items: center; justify-content: space-between;
  height: 56px; gap: 1rem;
}
.brand-mark {
  font-weight: 700; font-size: 15px; letter-spacing: -.01em;
  color: var(--text); display: flex; align-items: center; gap: .5rem;
}
.brand-mark .dot {
  width: 10px; height: 10px; border-radius: 50%; background: var(--brand);
}
.brand-mark .logo {
  width: 24px; height: 24px; border-radius: 6px; object-fit: cover;
  flex: 0 0 auto;
}
.nav { display: flex; gap: 1.25rem; align-items: center; }
.nav a { font-size: 13px; color: var(--text-muted); font-weight: 500; }
.nav a.active, .nav a:hover { color: var(--text); }

/* ---- Header search (fp-689 / fp-82g) ----
   Lives inside .nav so it shares the nav's flex line. The form
   itself is display: contents so it doesn't add its own box —
   the input becomes a direct flex sibling of the nav links. */
.nav-search { display: contents; }
.nav-search input[type="search"] {
  width: 200px; max-width: 28vw;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--border); border-radius: 6px;
  padding: .35rem .6rem; font-size: 13px; line-height: 1.2;
  outline-offset: 2px;
}
.nav-search input[type="search"]:focus {
  border-color: var(--brand);
}

/* ---- Topnav Submit CTA (fp-e9tw) ----
   Pinned to the sticky topbar so the submit affordance is reachable
   on mobile. The board sidebar's .cta-feedback pill stays for desktop
   visual weight; on iPhone-sized viewports it lands ~6000px down the
   page (sidebar reorders below main at the 720px breakpoint), so this
   topnav button is the actual mobile entry point. */
.nav-submit { white-space: nowrap; }
.nav-signin-link { font-size: 13px; }

/* Compact the nav on small viewports so the Submit button stays
   visible alongside Feedback/Roadmap. We drop the search input
   (search is still reachable from the dedicated /search page via
   nav links and post titles) and the secondary Sign-in text link
   (anonymous users still get to the modal via the Submit button or
   the inline "Sign in to post" CTA above the post feed). */
@media (max-width: 640px) {
  .nav { gap: .75rem; }
  .nav-search { display: none; }
  .site-header { padding: 0 1rem; }
  .nav-signin-link { display: none; }
}

/* ---- Search results page (fp-689) ---- */
.search-head { margin-bottom: 1.25rem; }
.search-form {
  display: flex; gap: .5rem; align-items: center;
}
.search-form input[type="search"] {
  flex: 1;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: 6px;
  padding: .55rem .8rem; font-size: 14px;
}
.search-form input[type="search"]:focus { border-color: var(--brand); }
.search-summary {
  color: var(--text-muted); font-size: 13px;
  margin: 0 0 1rem 0;
}
.search-summary strong { color: var(--text); }
.search-notice {
  background: var(--surface); color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 6px;
  padding: .75rem 1rem; margin: 0 0 1.25rem 0; font-size: 13px;
}

.btn {
  background: var(--brand); color: #fff;
  padding: .5rem .9rem; border-radius: var(--radius);
  font-size: 13px; font-weight: 500; border: 0; cursor: pointer;
  display: inline-flex; align-items: center; gap: .35rem;
  transition: opacity .12s;
}
a.btn, a.btn:link, a.btn:visited, a.btn:active { color: #fff; }
.btn:hover, a.btn:hover { opacity: .9; color: #fff; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn-ghost {
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border-strong);
}
.btn-ghost:hover { background: var(--bg); color: var(--text); }
/* fp-9ntd: the link-state rules above (`a.btn:link`, specificity 0,2,1)
   outrank the plain `.btn-ghost` class (0,1,0), so every ghost button
   rendered as an <a> — post "Edit", edit-post "Cancel", "Load more" —
   inherited the solid button's white text and vanished against the
   white surface. Restate the ghost colour at matching specificity. */
a.btn-ghost, a.btn-ghost:link, a.btn-ghost:visited, a.btn-ghost:active { color: var(--text); }
a.btn-ghost:hover { background: var(--bg); color: var(--text); }

/* ---- OAuth provider buttons ---- */
.oauth-row {
  display: flex; flex-direction: column; gap: .5rem;
  margin: 0 0 1rem;
}
.oauth-btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: .625rem;
  height: 40px; padding: 0 1rem;
  border-radius: 8px; border: 1px solid transparent;
  font-size: 14px; font-weight: 500;
  text-decoration: none;
  transition: background 120ms, border-color 120ms;
}
.oauth-btn .oauth-logo {
  flex: 0 0 auto;
}
/* Apple: black pill, white text + glyph. HIG-required wording.
   Hover lightens slightly per Apple's spec. */
.oauth-apple, a.oauth-apple, a.oauth-apple:link, a.oauth-apple:visited {
  background: #000; color: #fff; border-color: #000;
}
.oauth-apple:hover { background: #1a1a1a; color: #fff; }
/* Google: white pill, dark text, neutral border. Google's brand
   guidelines forbid the G logo on a colored background. */
.oauth-google, a.oauth-google, a.oauth-google:link, a.oauth-google:visited {
  background: #fff; color: #1f1f1f;
  border-color: #dadce0;
}
.oauth-google:hover { background: #f8f9fa; color: #1f1f1f; }
/* Visible focus for keyboard navigation — Apple/Google buttons
   are anchors so the browser default focus ring would be
   inconsistent with the rest of the form. */
.oauth-btn:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
.oauth-divider {
  display: flex; align-items: center; gap: .75rem;
  margin: 0 0 1rem;
  color: var(--text-muted); font-size: 12px;
}
.oauth-divider::before,
.oauth-divider::after {
  content: ""; flex: 1; height: 1px; background: var(--border);
}

/* ---- Layout: content + right sidebar (UserJot pattern) ---- */
.page {
  flex: 1;
  width: 100%;
  max-width: 1100px; margin: 0 auto; padding: 1.5rem;
  display: grid; grid-template-columns: 1fr 280px; gap: 2.5rem;
}
/* Single column when the page didn't override the sidebar block.
   The aside still renders empty but :empty + display:none drops it
   so the grid track has nothing to size against — combined with
   :has() the page becomes a true single column. */
.page:has(> .sidebar:empty) { grid-template-columns: 1fr; gap: 0; }
.sidebar:empty { display: none; }
@media (max-width: 720px) {
  .page { grid-template-columns: 1fr; padding: 1rem; }
  .sidebar { order: 2; }
}
.sidebar { font-size: 14px; }
.sidebar h3 {
  font-size: 13px; font-weight: 600; margin: 0 0 .5rem; color: var(--text);
}

/* Right-rail "Give Feedback" CTA — bold pill, brand background. */
.cta-feedback {
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  background: var(--brand); color: #fff;
  padding: .55rem 1rem; border-radius: var(--radius);
  font-weight: 500; font-size: 13px; width: 100%;
  margin-bottom: .6rem;
  transition: opacity .12s;
}
.cta-feedback:link, .cta-feedback:visited { color: #fff; }
.cta-feedback:hover { opacity: .9; color: #fff; }
.cta-feedback svg { width: 16px; height: 16px; flex: 0 0 auto; }

/* Boxed cards for sidebar meta sections (Status / Posted, Reactions). */
.side-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 1rem 1.1rem;
  margin-bottom: 1rem; font-size: 14px;
}
/* fp-9ntd: gap + a non-shrinking label. Without them a long value
   ("Private - only you and the <project> team") squeezed the label
   below its content width and the two texts overlapped. */
.side-card .row {
  display: flex; align-items: center; justify-content: space-between;
  gap: .75rem; padding: .35rem 0;
}
.side-card .label { color: var(--text-muted); flex: 0 0 auto; }
.side-card .value { color: var(--text); font-weight: 500; min-width: 0; text-align: right; }

/* Right-rail Actions block — minimal icon links (just Copy link
   today; Share button removed in fp-h1e for being unreliable). */
.actions-block { margin-top: 1.5rem; }
.actions-block ul { list-style: none; padding: 0; margin: 0; }
.actions-block li { margin: 0; }
.actions-block button {
  display: flex; align-items: center; gap: .65rem;
  padding: .45rem 0; font-size: 13px; font-weight: 500;
  color: var(--text-muted); background: transparent;
  border: 0; cursor: pointer; width: 100%; text-align: left;
}
.actions-block button:hover { color: var(--text); }
.actions-block button:disabled { color: var(--brand); cursor: default; }
.actions-block svg { width: 14px; height: 14px; flex: 0 0 auto; }

/* Top-of-content status filter bar (UserJot pills). */
.status-filters {
  display: flex; align-items: center; gap: 1.5rem;
  padding: 0 0 .85rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 1.5rem;
  font-size: 14px; flex-wrap: wrap;
}
.status-filter {
  display: inline-flex; align-items: center; gap: .45rem;
  color: var(--text-muted); font-weight: 500;
  padding: 0; text-decoration: none;
}
.status-filter:hover { color: var(--text); }
/* fp-2pct: the selected chip needs a clear signal — color alone (muted ->
   text) was indistinguishable from :hover. Bold the label and fill the ring
   with its status color (the .ring.solid treatment) so the active filter
   reads as selected. The ring's currentColor is the .ring-<status> hue, so
   the fill picks up the right color automatically; the neutral "All" ring
   fills gray. Sort chips have no ring, so they just go bold when active. */
.status-filter.active { color: var(--text); font-weight: 600; }
.status-filter.active .ring { background: currentColor; }
.status-filter .ring {
  width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid currentColor; flex: 0 0 auto;
}
.status-filter .ring.solid { background: currentColor; }
.status-filter.sort { color: var(--text); }
/* fp-4nsg: the two sort chips (Newest / Top) are one cohesive group
   floated to the right behind a single divider. The old rule put
   margin-left:auto AND border-left on EACH .sort chip, so on a flex line
   the two auto margins split the free space evenly — Newest drifted to
   mid-row, Top to the far right — and each chip drew its own divider.
   The ~732px main column always wraps this bar, so that split was the
   default appearance, not an edge case. Wrapping the chips moves the
   margin + divider onto the group: one auto margin pushes the pair right
   as a unit, one divider, and the pair wraps together. */
.board-sort {
  display: inline-flex; align-items: center; gap: 1.5rem;
  margin-left: auto;
  padding-left: 1.5rem; border-left: 1px solid var(--border);
}

/* Status pill (outlined, colored ring) — used on cards + detail. */
.status-pill {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .25rem .75rem; border-radius: 999px;
  border: 1px solid var(--border-strong);
  font-size: 12px; font-weight: 500; color: var(--text);
  background: var(--surface);
}
.status-pill .ring {
  width: 12px; height: 12px; border-radius: 50%;
  border: 2px solid currentColor; flex: 0 0 auto;
}
/* Color hooks for status rings — keyed to the enum values rendered
   by render/funcs.go (statusPill, statusBadge) and the board filter
   pills in templates. Adding a new status: extend the enum, add a
   row here, and the templates/Go side picks it up automatically. */
/* fp-qhm: palette matches UserJot's roadmap so users moving from
   UserJot see the same status colors. Open kept as sky to disambiguate
   from the new blue Planned (UserJot color). Completed and Shipped both
   green but completed is a lighter shade (done vs released). */
.ring-open { color: #0ea5e9; }        /* sky — pre-roadmap submission */
.ring-pending { color: #f59e0b; }     /* amber — UserJot Pending */
.ring-review { color: #f97316; }      /* orange — UserJot Reviewing */
.ring-planned { color: #3b82f6; }     /* blue — UserJot Planned */
.ring-in-progress { color: #8b5cf6; } /* purple — UserJot In Progress */
.ring-completed { color: #22c55e; }   /* green — done, not released */
.ring-shipped { color: #10b981; }     /* emerald — released */
.ring-closed { color: #64748b; }      /* slate — UserJot Closed */
.ring-verifying { color: #9ca3af; }   /* gray — pending_email (internal) */
.ring-moderating { color: #9ca3af; }  /* gray — pending_moderation (internal) */
.ring-rejected { color: #ef4444; }    /* red — explicit reject */
.ring-neutral { color: #9ca3af; }

/* Status badge (filled pill) — colored background, white text. The
   color hook stays parallel to .ring-* so the two renderers (badge
   and pill) share their palette. */
.badge { color: white; }
.badge-open { background: #0ea5e9; }
.badge-pending { background: #f59e0b; }
.badge-review { background: #f97316; }
.badge-planned { background: #3b82f6; }
.badge-in-progress { background: #8b5cf6; }
.badge-completed { background: #22c55e; }
.badge-shipped { background: #10b981; }
.badge-closed { background: #64748b; }
.badge-verifying { background: #9ca3af; }
.badge-moderating { background: #9ca3af; }
.badge-rejected { background: #ef4444; }
.badge-neutral { background: #9ca3af; }

/* ---- Content cards ---- */
.content > h1 {
  font-size: 22px; font-weight: 600; letter-spacing: -.01em;
  margin: 0 0 .25rem;
}
.content > p.lead {
  color: var(--text-muted); margin: 0 0 1.5rem;
}
.card-list {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); overflow: hidden;
}
.card-list > article { border-top: 1px solid var(--border); padding: 0; }
.card-list > article:first-child { border-top: 0; }

/* Compact variant for the post-detail comment list — padded so the
   nested .comment rows don't run flush against the card border. */
.card-list-padded { padding: 0 1.25rem; }

/* fp-9ntd: #comment-list is rendered unconditionally so HTMX has a
   stable append target, so the empty case must not paint a 2px
   border sandwich above the comment form. (A #comment-list:first-child
   margin used to sit here for the first appended comment; fp-sig1 made
   the "N comments" heading unconditional too, so #comment-list is never
   the first child any more and the heading's own margin does the job.) */
.card-list:empty { display: none; }

/* ---- Post card (board feed) ---- */
article.post {
  display: grid; grid-template-columns: 60px 1fr; gap: .9rem;
  padding: 1rem 1.25rem;
  transition: background .12s;
}
article.post:hover { background: rgba(0,0,0,.015); }
article.post .vote-col {
  display: flex; flex-direction: column; align-items: center;
}
article.post h2 {
  margin: 0 0 .15rem; font-size: 14px; font-weight: 600;
  letter-spacing: -.005em;
}
article.post h2 a:hover { color: var(--brand); }
article.post .excerpt {
  color: var(--text-muted); margin: 0 0 .5rem;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
article.post .meta {
  display: flex; gap: .65rem; align-items: center;
  color: var(--text-muted); font-size: 12px;
}
article.post .meta .sep { color: var(--border-strong); }

/* Vertical feed of post.card articles on the board page — replaces
   the inline grid that the htmx target carried. */
.post-feed {
  display: flex; flex-direction: column; gap: 1rem;
}

/* ---- Post detail (UserJot-style: borderless, body-first) ---- */
article.post-detail { padding: 0; background: transparent; border: 0; }
.post-detail-head {
  display: flex; align-items: center; gap: .75rem;
  margin-bottom: 1.5rem;
}
.post-detail-head .author-name { font-weight: 600; font-size: 14px; }
.post-detail-head .author-time {
  color: var(--text-muted); font-size: 13px;
}
.post-detail-body {
  font-size: 22px; line-height: 1.45; letter-spacing: -.005em;
  color: var(--text); margin: 0 0 1.5rem;
  white-space: pre-wrap; word-wrap: break-word;
}
/* The post body paragraph (under the h1) shows as smaller muted text
   so the title carries the primary weight. */
.post-detail-body.body-text {
  font-size: 16px; color: var(--text-muted);
}
.post-detail-meta {
  display: flex; align-items: center; gap: 1rem;
  padding-bottom: 1.25rem; margin-bottom: 1.5rem;
  border-bottom: 1px solid var(--border);
}
.post-detail-meta .vote-heart { margin-left: 0; }

/* ---- Attachments (fp-lp0) ----
   Grid of image thumbnails / file links rendered under the post body.
   Images link to the full-resolution source in a new tab. */
.post-attachments {
  list-style: none; padding: 0; margin: 0 0 1.5rem;
  display: grid; gap: .75rem;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
}
.post-attachment-image img {
  width: 100%; height: auto; max-height: 320px; object-fit: cover;
  border-radius: 8px; border: 1px solid var(--border); display: block;
  background: var(--surface);
}
.post-attachment-image a { display: block; line-height: 0; }
.post-attachment-file {
  padding: .5rem .75rem; border: 1px solid var(--border);
  border-radius: 8px; font-size: 14px; background: var(--surface);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.post-attachment-file a { color: var(--text); text-decoration: none; }
.post-attachment-file a:hover { text-decoration: underline; }

/* ---- Post card thumbnails (fp-sfj) ----
   Single-image strip on the board card. We show at most one image
   to keep cards visually consistent with the existing layout; the
   detail page renders the full gallery. The strip sits between the
   title block and the card foot so it doesn't interfere with the
   card-wide hyperlink. */
.post-card-thumbs {
  display: flex; gap: .375rem; margin: .25rem 0 .75rem;
}
.post-card-thumbs img {
  width: 96px; height: 64px; object-fit: cover;
  border-radius: 6px; border: 1px solid var(--border);
  background: var(--surface);
}
.post-card-thumbs .more {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 32px; padding: 0 .5rem; height: 64px;
  border: 1px solid var(--border); border-radius: 6px;
  background: var(--surface); color: var(--text-muted);
  font-size: 12px; font-weight: 600;
}

/* ---- Upload zone (fp-sfj / fp-iroa polish) ----
   File picker on the new-post form. The dashed box doubles as a
   drag-and-drop target; .upload-trigger is the visible "Add images"
   button (the native file input is sr-only) and the hint text sits
   next to it. The thumbnail strip grows below as files attach. */
.upload-zone {
  margin: .75rem 0 1rem;
  padding: .85rem 1rem;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface);
  transition: border-color .15s, background .15s;
  display: flex; flex-wrap: wrap; align-items: center;
  gap: .5rem .85rem;
}
.upload-zone.upload-busy { opacity: .65; pointer-events: none; }
.upload-zone.upload-dragover {
  border-color: var(--brand);
  border-style: solid;
  background: color-mix(in srgb, var(--brand) 6%, var(--surface));
}

.upload-trigger {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .4rem .75rem;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  font-size: 13px; font-weight: 500; cursor: pointer;
  transition: background .12s, border-color .12s, color .12s;
}
.upload-trigger:hover { background: var(--bg); border-color: var(--text-muted); }
.upload-trigger-icon { flex: 0 0 auto; color: var(--text-muted); }
.upload-trigger:hover .upload-trigger-icon { color: var(--text); }
/* Keyboard focus ring lands on the hidden input — mirror it on the
   visible label so tab-users see where they are. */
.upload-input:focus-visible + .upload-trigger-icon {
  outline: 2px solid var(--brand);
  outline-offset: 3px; border-radius: 2px;
}
.upload-trigger:focus-within {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 25%, transparent);
}

.upload-hint {
  color: var(--text-muted); font-size: 12px;
}

/* visually-hidden: removes from layout but keeps in the accessibility
   tree and focus order. Used to hide the native <input type="file">
   while delegating clicks/keyboard to the wrapping label. */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

.upload-attached {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: .5rem;
  flex-basis: 100%;
}
.upload-attached:empty { display: none; }
.upload-thumb {
  position: relative;
  width: 96px; height: 96px;
  border-radius: 6px; overflow: hidden;
  border: 1px solid var(--border); background: var(--surface);
}
.upload-thumb img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.upload-thumb-remove {
  position: absolute; top: 4px; right: 4px;
  width: 22px; height: 22px; padding: 0;
  border: 0; border-radius: 50%;
  background: rgba(0,0,0,.65); color: #fff;
  font-size: 18px; line-height: 1;
  cursor: pointer;
}
.upload-thumb-remove:hover { background: rgba(0,0,0,.85); }
.upload-file-icon {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 60px;
  font-size: 12px; font-weight: 600; color: var(--text-muted);
  text-transform: lowercase; word-break: break-all;
}
.upload-file-name {
  display: block; padding: 0 6px;
  font-size: 10px; color: var(--text-muted);
  text-align: center; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.upload-status {
  margin: 0; font-size: 12px; color: var(--text-muted);
  min-height: 1em; flex-basis: 100%;
}
.upload-status:empty { display: none; }
.upload-status-error { color: #b91c1c; }

/* ---- Reactions card (fp-96s) ---- */
.reactions-card {
  display: flex; align-items: center; gap: .75rem;
  padding: .75rem 1rem; margin-bottom: 1.5rem;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 8px;
}
.reactor-strip {
  list-style: none; padding: 0; margin: 0;
  display: flex; align-items: center;
}
.reactor-strip .reactor {
  margin-left: -6px;
}
.reactor-strip .reactor:first-child { margin-left: 0; }
.reactor-strip .avatar {
  width: 28px; height: 28px;
  border: 2px solid var(--surface);
  background: var(--bg);
  object-fit: cover;
}
.reactions-summary {
  margin: 0; color: var(--text-muted); font-size: 13px;
}
.reactions-summary strong { color: var(--text); font-weight: 600; }

/* ---- Vote button ---- */
.vote-btn {
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border-strong); border-radius: 6px;
  padding: .3rem .35rem; min-width: 44px;
  cursor: pointer; font-size: 11px; font-weight: 600;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  transition: border-color .1s, background .1s, color .1s;
}
.vote-btn:hover { border-color: var(--brand); color: var(--brand); }
.vote-btn.voted {
  border-color: var(--brand); background: color-mix(in srgb, var(--brand) 8%, transparent);
  color: var(--brand);
}
.vote-btn .arrow { font-size: 13px; line-height: 1; }
.vote-btn .vote-count { font-size: 12px; line-height: 1; }

/* ---- Status badges (softer / pastel) ---- */
.badge {
  display: inline-block; padding: .15rem .55rem;
  border-radius: 999px; font-size: 11px; font-weight: 500;
  color: white;
}

/* ---- Forms ---- */
form label {
  display: block; margin: 1rem 0 .35rem;
  font-size: 13px; font-weight: 500;
}
form input[type=text], form input[type=email], form textarea {
  width: 100%; padding: .55rem .75rem;
  border: 1px solid var(--border-strong); border-radius: 6px;
  font: inherit; background: var(--surface); color: var(--text);
}
form input:focus, form textarea:focus {
  outline: 2px solid color-mix(in srgb, var(--brand) 40%, transparent);
  outline-offset: 0; border-color: var(--brand);
}
form textarea { min-height: 7rem; resize: vertical; }
form .form-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 1.5rem;
}

/* ---- Comment form / sign-in CTA (fp-c316) ----
   Set the comment section off from the issue with a divider + breathing
   room so "Join the discussion" doesn't read as part of the post. The
   signed-out CTA is a <div class="form-card">, not a <form>, so the
   `form .form-card` rule above never matched it — it rendered borderless
   and flush. Give it the same card treatment here so both states read as
   a distinct block.

   fp-c316b: scope strictly to #comment-form. The board's "Have feedback?"
   hero uses the SAME `form-card signin-cta` classes, so an unscoped
   `.signin-cta` rule boxed + inset that hero too — making its content
   read as narrower than the flush full-width status-filter row right
   below it. Keeping the styling under #comment-form leaves the board
   hero flush and column-wide, aligned with the filters. */
#comment-form { margin-top: 2rem; padding-top: 1.75rem; border-top: 1px solid var(--border); }
#comment-form .signin-cta {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 1.5rem;
}
#comment-form .signin-cta .form-card-title { margin-top: 0; }

/* ---- Comments ---- */
.comments h3 { font-size: 13px; font-weight: 600; margin: 1.5rem 0 .5rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .05em; }
/* fp-sig1: the heading is always in the DOM so comment_count.partial
   has an out-of-band target; it carries no text until there is
   something to count. */
#comment-count-heading:empty { display: none; }
article.comment {
  padding: .8rem 0; border-top: 1px solid var(--border);
}
article.comment:first-of-type { border-top: 0; }
article.comment p { margin: 0 0 .25rem; word-wrap: break-word; }
article.comment footer { margin-top: .7rem; color: var(--text-muted); font-size: 12px; }

/* ---- Linked posts (fp-442t) ----
   The global `a { color: inherit; text-decoration: none }` reset strips
   link affordance, so the relation links need an explicit accent colour +
   hover underline to read as clickable. Heading matches the .comments
   sub-section treatment (small uppercase muted) so "Linked" groups as a
   peer of "Activity" / "N COMMENTS" rather than a page-level heading. */
.linked-posts h3 { font-size: 13px; font-weight: 600; margin: 1.5rem 0 .5rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .05em; }
.linked-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .4rem; }
.linked-entry { font-size: 14px; }
.linked-rel { color: var(--text-muted); margin-right: .4rem; }
.linked-list a { color: var(--brand); font-weight: 500; }
.linked-list a:hover { text-decoration: underline; }

/* fp-uwu6: rendered-markdown bodies (post + comment). goldmark emits
   real block elements and maps single newlines to <br>, so white-space
   is normal here — the old pre-wrap would double every break. Styles
   are scoped to .markdown-body so nothing else shifts. */
.markdown-body { white-space: normal; word-wrap: break-word; }
.markdown-body > :first-child { margin-top: 0; }
.markdown-body > :last-child { margin-bottom: 0; }
.markdown-body p { margin: 0 0 .6em; white-space: normal; }
.markdown-body ul, .markdown-body ol { margin: .4em 0; padding-left: 1.5em; }
.markdown-body ul { list-style: disc; }
.markdown-body ol { list-style: decimal; }
.markdown-body li { margin: .15em 0; }
.markdown-body a { color: var(--brand, #4f46e5); text-decoration: underline; }
.markdown-body code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .9em;
  background: rgba(127, 127, 127, .14); padding: .1em .35em; border-radius: 4px;
}
.markdown-body pre {
  margin: .5em 0; padding: .6em .8em; overflow-x: auto;
  background: rgba(127, 127, 127, .14); border-radius: 6px;
}
.markdown-body pre code { background: none; padding: 0; font-size: .85em; }
.markdown-body blockquote {
  margin: .5em 0; padding: .1em .9em; color: var(--text-muted);
  border-left: 3px solid var(--border);
}
.markdown-body hr { border: 0; border-top: 1px solid var(--border); margin: .8em 0; }

/* ---- Roadmap (3-column board UserJot-style) ---- */
.roadmap-board {
  display: grid; gap: 2rem;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (max-width: 880px) {
  .roadmap-board { grid-template-columns: 1fr; gap: 1.5rem; }
}
.roadmap-col-v2 { min-width: 0; }
.roadmap-col-title {
  font-size: 20px; font-weight: 600; margin: 0;
  display: flex; align-items: baseline; gap: .55rem;
}
.roadmap-col-title .count {
  color: var(--text-muted); font-weight: 500; font-size: 14px;
}
.roadmap-col-sub {
  color: var(--text-muted); margin: .25rem 0 1.25rem;
  font-size: 14px;
}
.roadmap-cards { display: flex; flex-direction: column; gap: 1rem; }
.roadmap-col-v2 .empty { color: var(--text-muted); font-size: 13px; }

/* ---- Post card (board feed + roadmap columns) ---- */
article.post-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 12px; padding: 1.25rem 1.4rem;
  box-shadow: var(--shadow-sm);
  transition: border-color .12s, box-shadow .12s;
}
article.post-card:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow);
}
.post-card-head {
  display: flex; align-items: center; gap: .55rem;
  margin-bottom: .5rem;
  font-size: 13px;
}
.post-card-head .post-card-author {
  color: var(--text); font-weight: 600;
}
.post-num {
  margin-left: auto;
  color: var(--text-muted);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  font-weight: 500;
}
/* Submit form: native <select> tweaked to match the inputs. */
form select {
  width: 100%; padding: .55rem .75rem;
  border: 1px solid var(--border-strong); border-radius: 6px;
  font: inherit; background: var(--surface); color: var(--text);
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill='%236b7280' d='M3 4l3 4 3-4z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .75rem center;
  background-size: 12px;
  padding-right: 2rem;
}
form select:focus {
  outline: 2px solid color-mix(in srgb, var(--brand) 40%, transparent);
  outline-offset: 0; border-color: var(--brand);
}
.post-card-link { display: block; color: inherit; }
.post-card-link:hover { color: inherit; }
article.post-card h3 {
  margin: 0 0 .35rem; font-size: 16px; font-weight: 600;
  line-height: 1.35; letter-spacing: -.005em;
}
article.post-card p {
  margin: 0; color: var(--text-muted); font-size: 14px;
  line-height: 1.55;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
.post-card-foot {
  display: flex; align-items: center; gap: .85rem;
  margin-top: 1rem;
}
.avatar {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--bg); color: var(--text-muted);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 600; flex-shrink: 0;
  border: 1px solid var(--border);
}
.post-card-author {
  color: var(--text-muted); font-size: 13px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vote-heart {
  margin-left: auto;
  background: transparent; border: 0; cursor: pointer;
  display: inline-flex; align-items: center; gap: .35rem;
  color: var(--text-muted); font-size: 13px; font-weight: 500;
  padding: .25rem .5rem; border-radius: 6px;
  transition: color .12s, background .12s;
}
.vote-heart:hover { color: var(--brand); background: var(--bg); }
.vote-heart.voted { color: var(--brand); }
.vote-heart.voted svg { fill: var(--brand); }
.comment-count {
  display: inline-flex; align-items: center; gap: .35rem;
  color: var(--text-muted); font-size: 13px; font-weight: 500;
}
.comment-count svg { width: 14px; height: 14px; }

/* ---- Errors / notices ---- */
.error {
  color: #991b1b; background: #fef2f2; border: 1px solid #fecaca;
  padding: .65rem .9rem; border-radius: 6px; margin: 1rem 0; font-size: 13px;
}
.notice {
  color: #075985; background: #f0f9ff; border: 1px solid #bae6fd;
  padding: .65rem .9rem; border-radius: 6px; margin: 1rem 0; font-size: 13px;
}
.empty-state {
  text-align: center; padding: 3rem 1rem; color: var(--text-muted); font-size: 14px;
}

/* ---- Footer (legal links, centered, getbookshelves.app style) ---- */
.site-footer {
  border-top: 1px solid var(--border);
  margin-top: 3rem; padding: 1.5rem 1.5rem 2rem; background: var(--surface);
  text-align: center;
}
.site-footer-inner {
  max-width: 720px; margin: 0 auto;
  font-size: 12px; color: var(--text-muted); line-height: 1.7;
}
.site-footer a { color: var(--text-muted); }
.site-footer a:hover { color: var(--text); }
.site-footer .links {
  display: inline-flex; flex-wrap: wrap; justify-content: center;
  gap: .15rem .85rem; margin-bottom: .5rem;
}
.site-footer .links .sep { color: var(--border-strong); }
.site-footer .copyright { color: var(--text-muted); }

/* ---- Utility classes (replaces inline style="..." attributes) ----
   Added when removing inline styles from templates. Each class
   corresponds to a previously-inline declaration so the visual
   result is unchanged. */

/* Spacing utilities. */
.mt-1   { margin-top: 1rem; }
.mt-125 { margin-top: 1.25rem; }
.mt-15  { margin-top: 1.5rem; }
.mt-075 { margin-top: .75rem; }
.my-1   { margin: 1rem 0; }
.text-center { text-align: center; }

/* Muted helper line used in sidebars and form hints. */
.sidebar-hint {
  color: var(--text-muted); font-size: 13px; line-height: 1.5;
}
/* "(optional)" hint next to a form label. */
.label-optional {
  color: var(--text-muted); font-weight: 400;
}

/* ---- Signed-in nav affordance (fp-76m) ---- */
/* Right-side "<name> · sign out" pair next to the Submit button.
   Avatar is a small round image; referrerpolicy=no-referrer on the
   <img> avoids leaking the page URL to Google when the user came
   via OAuth. */
.signed-in-as {
  display: inline-flex; align-items: center; gap: .375rem;
  color: var(--text); font-weight: 500;
}
.signed-in-as .avatar {
  border-radius: 50%;
  vertical-align: middle;
}
/* fp-bqan: sign-out is a POST form now, but the nav still wants
   a plain-text link look. Reset button defaults + style the form
   wrapper to drop the inline-block height that submit buttons get
   by default. */
.nav-signout-form {
  display: inline-flex;
  align-items: center;
  margin: 0;
  padding: 0;
}
.nav-signout {
  display: inline-flex;
  align-items: center;
  color: var(--text-muted) !important;
  background: none;
  border: 1px solid var(--border, #d0d7de);
  border-radius: 6px;
  padding: .25rem .625rem;
  font: inherit;
  font-size: 13px;
  line-height: 1.2;
  cursor: pointer;
  text-decoration: none;
}
.nav-signout:hover {
  color: var(--text) !important;
  background: var(--bg);
}

/* ---- Account pulldown (fp-869w) ----
   Native <details>/<summary> disclosure. The panel is absolutely
   positioned under the summary, so it doesn't push the nav layout
   when open. .account-menu-item resets <button> defaults so a form-
   wrapped sign-out looks identical to a plain <a> sibling. */
.account-menu { position: relative; display: inline-block; }
.account-menu > summary {
  list-style: none;
  cursor: pointer;
  user-select: none;
}
.account-menu > summary::-webkit-details-marker { display: none; }
.account-menu-caret {
  transition: transform .12s ease;
  color: var(--text-muted);
}
.account-menu[open] .account-menu-caret { transform: rotate(180deg); }
.account-menu-panel {
  position: absolute;
  top: calc(100% + .375rem);
  right: 0;
  min-width: 160px;
  background: var(--surface, #fff);
  border: 1px solid var(--border, #d0d7de);
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0,0,0,.08);
  padding: .25rem;
  z-index: 50;
}
.account-menu-form { margin: 0; padding: 0; }
.account-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: .4rem .625rem;
  font: inherit;
  font-size: 13px;
  line-height: 1.3;
  color: var(--text);
  background: none;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
  text-decoration: none;
}
.account-menu-item:hover { background: var(--bg); }

/* ---- /account page (fp-jru) ---- */
.account-section { margin: 1.5rem 0 2rem; }
.account-section h2 {
  font-size: 14px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted); font-weight: 600; margin: 0 0 .75rem;
}
.linked-list, .sessions-list { list-style: none; padding: 0; margin: 0; }
.linked-row, .session-row {
  display: flex; align-items: center; gap: .75rem;
  padding: .75rem 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: .5rem;
  font-size: 13px;
}
.linked-provider { font-weight: 600; min-width: 70px; }
.linked-email { color: var(--text-muted); }
.linked-time, .session-last-seen {
  color: var(--text-muted); margin-left: auto; font-size: 12px;
}
.session-meta {
  display: flex; flex-direction: column; gap: .125rem; flex: 1; min-width: 0;
}
.session-ua {
  font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.session-badge {
  display: inline-block;
  font-size: 11px; padding: 1px 6px; border-radius: 4px;
  background: var(--brand); color: #fff;
  width: fit-content;
}
.session-current { border-color: var(--brand); }
.session-revoke-form { margin: 0; }

/* ---- /sign-in page (fp-2rm) ---- */
.signin-cancel {
  margin-top: 1.5rem;
  font-size: 13px;
}
.signin-cancel a {
  color: var(--text-muted);
}
.signin-cancel a:hover {
  color: var(--text);
}

/* ---- Cookie consent banner + preferences modal (fp-5vy, fp-ivm9) ---- */
/* fp-ivm9: the bottom strip uses .fp-prefs-strip* (not .cookie-banner*) so
   Brave Shields' EasyList cosmetic filter doesn't hide it. Modal classes
   below keep the cookie-* prefix — the modal IDs aren't on the filter. */
.fp-prefs-strip {
  position: fixed; bottom: 0; left: 0; right: 0;
  background: rgba(255, 255, 255, 0.97);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  border-top: 1px solid var(--border);
  padding: 16px; z-index: 1000;
  box-shadow: 0 -4px 6px -1px rgba(0,0,0,.08);
}
.fp-prefs-strip-content {
  max-width: 1100px; margin: 0 auto;
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px;
}
.fp-prefs-strip-text p {
  margin: 0; font-size: 13px; color: var(--text); line-height: 1.5;
}
.cookie-link {
  color: var(--brand); text-decoration: underline; font-weight: 500;
}
.fp-prefs-strip-actions { display: flex; gap: 12px; flex-shrink: 0; }
.cookie-btn {
  padding: 8px 16px; border-radius: 6px;
  font-size: 13px; font-weight: 500; cursor: pointer;
  border: 1px solid; transition: all .15s ease;
  white-space: nowrap; line-height: 1.3;
}
.cookie-btn-primary {
  background: var(--brand); color: #fff; border-color: var(--brand);
}
.cookie-btn-primary:hover { filter: brightness(0.92); }
.cookie-btn-secondary {
  background: transparent; color: var(--text-muted); border-color: var(--border-strong);
}
.cookie-btn-secondary:hover { background: var(--bg); color: var(--text); }

.cookie-modal {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 2000;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.cookie-modal-content {
  background: var(--surface); border-radius: 12px;
  max-width: 500px; width: 100%; max-height: 80vh; overflow-y: auto;
  box-shadow: 0 20px 25px -5px rgba(0,0,0,.18);
}
.cookie-modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 20px 24px 12px; border-bottom: 1px solid var(--border);
}
.cookie-modal-header h3 {
  margin: 0; font-size: 16px; font-weight: 600; color: var(--text);
}
.cookie-modal-close {
  background: none; border: none; font-size: 22px; color: var(--text-muted);
  cursor: pointer; padding: 4px 8px; line-height: 1; border-radius: 4px;
}
.cookie-modal-close:hover { background: var(--bg); color: var(--text); }
.cookie-modal-body { padding: 20px 24px; }
.cookie-category { margin-bottom: 20px; }
.cookie-category:last-child { margin-bottom: 0; }
.cookie-category-header { display: flex; align-items: flex-start; gap: 16px; }
.cookie-category h4 {
  margin: 0 0 4px 0; font-size: 14px; font-weight: 600; color: var(--text);
}
.cookie-category p {
  margin: 0; font-size: 13px; color: var(--text-muted); line-height: 1.5;
}
.cookie-toggle {
  position: relative; display: inline-block;
  width: 40px; height: 22px; flex-shrink: 0; margin-top: 2px;
}
.cookie-toggle input { opacity: 0; width: 0; height: 0; }
.cookie-slider {
  position: absolute; cursor: pointer; inset: 0;
  background-color: var(--border-strong);
  transition: .2s; border-radius: 22px;
}
.cookie-slider:before {
  position: absolute; content: "";
  height: 16px; width: 16px; left: 3px; bottom: 3px;
  background-color: #fff; transition: .2s; border-radius: 50%;
}
input:checked + .cookie-slider { background-color: var(--brand); }
input:checked + .cookie-slider:before { transform: translateX(18px); }
input:disabled + .cookie-slider { opacity: 0.6; cursor: not-allowed; }
.cookie-modal-footer {
  padding: 12px 24px 20px; border-top: 1px solid var(--border);
}
.cookie-modal-footer .cookie-btn {
  width: 100%; display: flex; justify-content: center;
}

@media (max-width: 640px) {
  .fp-prefs-strip-content { flex-direction: column; align-items: stretch; gap: 12px; }
  .fp-prefs-strip-actions { justify-content: stretch; }
  .cookie-btn { flex: 1; text-align: center; }
  .cookie-modal { padding: 12px; }
  .cookie-category-header { gap: 12px; }
}

/* ---- Sign-in modal (fp-eqbg) ---- */
.signin-modal {
  width: min(420px, calc(100vw - 2rem));
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.75rem 1.5rem 1.5rem;
  background: var(--surface);
  color: var(--text);
  box-shadow: 0 10px 40px rgba(0,0,0,.18);
}
.signin-modal::backdrop {
  background: rgba(15, 15, 20, .45);
}
.signin-modal h2 {
  margin: 0 0 .25rem;
  font-size: 18px;
  font-weight: 600;
}
.signin-modal-hint {
  margin: 0 0 1rem;
  color: var(--text-muted);
  font-size: 13px;
}
.signin-modal-dismiss {
  margin: 0;
  position: absolute;
  top: .5rem;
  right: .5rem;
}
.signin-modal-close {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--text-muted);
  font-size: 22px;
  line-height: 1;
  padding: .25rem .5rem;
  cursor: pointer;
  border-radius: 4px;
}
.signin-modal-close:hover { color: var(--text); background: var(--bg); }
.signin-modal-form { margin: 0; }
.signin-modal-form label {
  display: block;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-muted);
  margin-bottom: .25rem;
}
.signin-modal-form input[type="email"] {
  width: 100%;
  padding: .5rem .65rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 14px;
  background: var(--surface);
  color: var(--text);
}

/* fp-7ma4: submit-kind chooser (public post vs private support ticket) */
.kind-choice { border: 0; padding: 0; margin: 0 0 1rem; display: grid; gap: .5rem; }
.kind-option { display: flex; gap: .6rem; align-items: flex-start; padding: .65rem .8rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); cursor: pointer; }
.kind-option:has(input:checked) { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand); }
.kind-option input { margin: .2rem 0 0; flex: 0 0 auto; }
.kind-option-body { display: flex; flex-wrap: wrap; gap: .3rem .5rem; align-items: center; }
.kind-option-body small { flex-basis: 100%; color: var(--text-muted); }
.kind-visibility { font-size: .7rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; padding: .1rem .45rem; border-radius: 999px; }
.kind-public { background: #dcfce7; color: #166534; }
.kind-private { background: #fef3c7; color: #92400e; }
.cta-support { margin-top: 0; }
.cta-hint { font-size: 12px; line-height: 1.45; color: var(--text-muted); margin: .15rem 0 1rem; }

/* fp-7exr: own-content edit / delete */
.edited { color: var(--text-muted); font-size: 12px; margin: .35rem 0 0; }
.own-post-actions { display: flex; gap: .5rem; align-items: center; margin: .75rem 0 0; }
.inline { display: inline; }
.linklike { background: none; border: 0; padding: 0; color: var(--brand); cursor: pointer; font: inherit; }
.linklike:hover { text-decoration: underline; }
.comment-editing textarea { width: 100%; min-height: 5rem; }
.edit-note { font-size: 12px; color: var(--text-muted); margin: .75rem 0 0; }
.comment-deleted .comment-deleted-note { margin: 0; color: var(--text-muted); font-size: 13px; font-style: italic; }
.comment-attachments { list-style: none; padding: 0; margin: .5rem 0 0; display: flex; flex-wrap: wrap; gap: .5rem; }
.comment-attachments img { max-width: 240px; max-height: 180px; border-radius: var(--radius); border: 1px solid var(--border); display: block; }
