/* sytwm — mobile-first responsive CSS. No build step. */

:root {
  --bg: #ffffff;
  --fg: #1c1c20;
  --muted: #6c7079;
  --accent: #2a5dff;
  --accent-soft: #eaf0ff;
  --accent-fg: #ffffff;
  --border: #e2e4ea;
  --pill-public-bg: #e7f5e9;
  --pill-public-fg: #235a2a;
  --pill-private-bg: #efeff3;
  --pill-private-fg: #44464c;
  --pill-hidden-bg: #fde7e7;
  --pill-hidden-fg: #7a1f1f;
  --error-bg: #fde7e7;
  --error-fg: #7a1f1f;
}

/* Issue #7 — role themes. Each role gets a subtle accent shift; every
 * component that reads --accent / --accent-soft re-tints automatically.
 * Job 020: body.manage is now its OWN class (no longer `admin manage`),
 * so source-order between body.admin and body.manage no longer matters.
 */
body.public { --accent: #2a5dff; --accent-soft: #eaf0ff; }
body.admin  { --accent: #5b3dd9; --accent-soft: #ede9fb; }
/* Manage was #0f9b6e — failed WCAG AA on white (3.47:1) per Issue #9
 * axe sweep. #0d6e4e is darker, still visibly the same teal hue, and
 * passes ≥5:1 on white and on --accent-soft (#e6f7ef). */
body.manage { --accent: #0d6e4e; --accent-soft: #e6f7ef; }

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--fg);
  font: 16px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

a { color: var(--accent); }
a:visited { color: var(--accent); }

.topbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border);
  gap: 0.5rem;
}

.brand {
  font-weight: 600;
  text-decoration: none;
  color: var(--fg);
}

.primary-nav {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
}

.primary-nav a { text-decoration: none; }

.content {
  max-width: 920px;
  margin: 0 auto;
  padding: 1.5rem 1rem 3rem;
}

.footer {
  border-top: 1px solid var(--border);
  padding: 1rem;
  text-align: center;
  color: var(--muted);
}

h1 { font-size: 1.75rem; line-height: 1.2; margin-top: 0; }
h2 { font-size: 1.25rem; margin-top: 2rem; }

.lead { font-size: 1.05rem; color: var(--muted); }
.muted { color: var(--muted); }
.error {
  background: var(--error-bg);
  color: var(--error-fg);
  padding: 0.75rem;
  border-radius: 0.4rem;
}

.cta {
  display: inline-block;
  background: var(--accent);
  color: var(--accent-fg);
  padding: 0.6rem 1.1rem;
  border-radius: 0.4rem;
  text-decoration: none;
  border: none;
  cursor: pointer;
  font: inherit;
  font-weight: 600;
}
.cta:visited { color: var(--accent-fg); }
.cta.primary { background: #155a1f; }
button.link {
  background: none; border: none; color: var(--accent); cursor: pointer; padding: 0;
  text-decoration: underline; font: inherit;
}

.hero { text-align: center; padding-top: 2rem; }
.hero .cta { font-size: 1.05rem; margin: 1rem 0; }

/* Splash page — issue #1: per-word color treatment for
 * "shareyourthoughtswith.me". Smooth gradient between "your" and "thoughts". */
.splash { text-align: center; padding: 2.5rem 0 1rem; max-width: 760px; margin: 0 auto; }
.splash-logo {
  display: block;
  width: clamp(120px, 30vw, 200px);
  height: auto;
  margin: 0 auto 1.25rem;
}
.wordmark {
  margin: 0 0 1.25rem;
  font-weight: 800;
  /* Issue #4: cap at 4rem (was 5rem) so the wordmark fits the 920px content
   * container at every desktop width. Line-height 1.18 (was 1.05) gives
   * descenders in "your" + "thoughts" room to render — the
   * background-clip:text gradient paints inside the line box, so tight
   * line-height clipped the descenders. */
  font-size: clamp(2.2rem, 8vw, 4rem);
  letter-spacing: -0.02em;
  line-height: 1.18;
  padding-bottom: 0.05em;
  text-transform: lowercase;
  font-family: ui-rounded, "SF Pro Rounded", "Nunito", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
.wm { display: inline-block; }
.wm-navy { color: #070B45; }
.wm-pink { color: #F7359D; }
.wm-gradient {
  background-image: linear-gradient(90deg, #1498F5 0%, #1498F5 28%, #6C3BFF 56%, #8A4DFF 100%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.splash-lead {
  font-size: 1.15rem;
  color: var(--muted);
  margin: 0 auto 1.5rem;
  max-width: 36rem;
}
.splash-cta {
  font-size: 1.1rem;
  padding: 0.85rem 1.5rem;
  border-radius: 0.5rem;
}
.splash-secondary { margin-top: 1.5rem; }

/* Issue #5 — landing overview + manager CTA sections. */
.splash-overview,
.splash-manager-cta {
  max-width: 640px;
  margin: 2.5rem auto 0;
  padding: 1.5rem;
  border: 1px solid var(--border);
  border-radius: 0.6rem;
  background: #fafbff;
}
.splash-overview h2,
.splash-manager-cta h2 {
  margin-top: 0;
  font-size: 1.2rem;
}
.splash-overview p,
.splash-manager-cta p {
  margin: 0.5rem 0;
  line-height: 1.5;
}
.splash-manager-cta { text-align: center; }
.splash-manager-cta .cta { margin-top: 0.75rem; }
/* Issue #9 — the secondary CTA used to render `--accent` text on a
 * `--accent-tinted` parent (`#fafbff` on .splash-manager-cta). At
 * --accent=#2a5dff that's ~4.85:1 contrast — passes WCAG AA on a
 * calculator but reads as faint because text + border share the
 * same hue family as the surface. Move text to --fg so contrast is
 * text-vs-background (>15:1); keep --accent on the border + the
 * hover state as the brand mark. */
.cta-secondary {
  background: #ffffff;
  color: var(--fg);
  border: 2px solid var(--accent);
}
.cta-secondary:visited { color: var(--fg); }
.cta-secondary:hover { background: var(--accent-soft); }

.post-shell { max-width: 540px; margin: 0 auto; }

/* Issue #2 — Open Graph link card on the public post page (rendered when
 * post definition.link is set; admin populates it via the post editor). */
.post-link-card {
  display: flex;
  gap: 0.75rem;
  align-items: stretch;
  padding: 0.75rem;
  margin: 0 0 1.25rem;
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  text-decoration: none;
  color: inherit;
  background: #fafbff;
}
.post-link-card:hover { border-color: var(--accent); }
.post-link-image {
  width: 96px;
  height: 96px;
  object-fit: cover;
  border-radius: 0.35rem;
  flex-shrink: 0;
}
.post-link-body { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; }
.post-link-title { font-size: 1rem; line-height: 1.25; }
.post-link-description {
  margin: 0;
  font-size: 0.9rem;
  color: var(--muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Admin editor preview card mirrors the public one. */
.admin-link-card {
  display: flex;
  gap: 0.75rem;
  padding: 0.75rem;
  margin-top: 0.75rem;
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  background: #fafbff;
}
.admin-link-card img { width: 96px; height: 96px; object-fit: cover; border-radius: 0.35rem; }
.admin-link-card .body { flex: 1; min-width: 0; }
.admin-link-card .actions { margin-top: 0.5rem; }
.post-step fieldset { border: none; padding: 0; margin: 0; }
.post-step legend { font-weight: 600; font-size: 1.1rem; margin-bottom: 0.5rem; }
.post-step .help { color: var(--muted); margin: 0 0 0.75rem; }
.post-step input[type=text], .post-step textarea, .post-step select {
  width: 100%;
  padding: 0.6rem;
  border: 1px solid var(--border);
  border-radius: 0.4rem;
  font: inherit;
}
.post-step textarea { resize: vertical; min-height: 6rem; }
.post-step label.choice {
  display: block;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 0.4rem;
  margin: 0.4rem 0;
  cursor: pointer;
}
.post-step .actions { margin-top: 1rem; display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; }
/* Honeypot: visually offscreen for sighted users, marked aria-hidden so
 * assistive tech ignores it. Applies anywhere the class is used —
 * scoping to `.post-step` (the original step container) caused the
 * label to render on /manage/signup, which has no .post-step ancestor. */
.hp { position: absolute; left: -9999px; height: 0; overflow: hidden; }
.post-step .rating { display: flex; gap: 0.4rem; border: none; padding: 0; }

.comments .comment {
  border-bottom: 1px solid var(--border);
  padding: 1rem 0;
  list-style: none;
}
.comment-list { padding: 0; }
.comment .body { white-space: pre-wrap; }
.comment .meta { color: var(--muted); font-size: 0.9rem; }

.pill {
  display: inline-block;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  font-size: 0.85rem;
}
.pill.public { background: var(--pill-public-bg); color: var(--pill-public-fg); }
.pill.private { background: var(--pill-private-bg); color: var(--pill-private-fg); }
.pill.hidden { background: var(--pill-hidden-bg); color: var(--pill-hidden-fg); }

body.admin .content,
body.manage .content {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  max-width: 1200px;
}
.admin-nav {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 1rem;
  border: 1px solid var(--border);
  border-radius: 0.4rem;
}
.admin-nav a { text-decoration: none; }
.admin-nav form { margin-top: 1rem; }

.admin-main h1 { margin-top: 0; }
.entries, .answers, .funnels, .counts, .keys, .posts {
  width: 100%; border-collapse: collapse; font-size: 0.95rem;
}
.entries th, .answers th, .funnels th, .counts th, .keys th, .posts th,
.entries td, .answers td, .funnels td, .counts td, .keys td, .posts td {
  text-align: left; padding: 0.5rem 0.6rem; border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.entries pre, .answers pre { white-space: pre-wrap; word-break: break-word; max-width: 36rem; }
.new-key pre.secret {
  padding: 0.75rem; background: #f5f5f8; border: 1px solid var(--border);
  border-radius: 0.4rem; overflow-x: auto;
}
.new-key-form, .new-post {
  display: grid; gap: 0.75rem; max-width: 540px; margin-bottom: 1.5rem;
}
.new-key-form label, .new-post label { display: grid; gap: 0.25rem; }
.new-key-form input, .new-post input, .new-key-form select {
  padding: 0.5rem; border: 1px solid var(--border); border-radius: 0.4rem; font: inherit;
}

.filter-bar {
  display: flex; gap: 1rem; margin: 1rem 0;
}
.filter-bar label { display: flex; gap: 0.4rem; align-items: center; }

.publish-form { margin-top: 1.5rem; padding-top: 1rem; border-top: 1px solid var(--border); }

/* Issue #12 — form-based post builder (replaces JSON textarea). Each step
 * is a card; htmx swaps the whole list on every mutation so branching
 * dropdowns refresh with the current step IDs. */
.post-meta-form {
  display: grid; gap: 0.5rem; max-width: 540px;
  padding: 0.75rem; background: #fafbff; border: 1px solid var(--border);
  border-radius: 0.5rem; margin-bottom: 1.25rem;
}
.post-meta-form label { display: grid; gap: 0.25rem; }
.post-meta-form input {
  padding: 0.5rem; border: 1px solid var(--border); border-radius: 0.4rem; font: inherit;
}

.builder-step-list {
  list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.75rem;
}
.builder-step-card {
  border: 1px solid var(--border); border-radius: 0.5rem; padding: 0.75rem 1rem;
  background: #ffffff;
}
.builder-step-card-header {
  display: flex; align-items: center; gap: 0.6rem;
  padding-bottom: 0.5rem; margin-bottom: 0.6rem;
  border-bottom: 1px solid var(--border);
}
.builder-step-id { font-family: monospace; }
.builder-step-position { font-size: 0.85rem; }
.builder-step-controls { margin-left: auto; display: flex; gap: 0.4rem; align-items: center; }
.builder-step-delete { color: var(--danger, #b00020); }
.builder-step-form { display: grid; gap: 0.5rem; }
.builder-step-form .field { display: grid; gap: 0.2rem; }
.builder-step-form .field-checkbox { display: flex; gap: 0.4rem; align-items: center; }
.builder-step-form input[type=text], .builder-step-form select {
  padding: 0.45rem; border: 1px solid var(--border); border-radius: 0.4rem; font: inherit;
}
.builder-options, .builder-branches {
  border: 1px solid var(--border); border-radius: 0.4rem; padding: 0.5rem 0.75rem;
}
.builder-options legend, .builder-branches legend {
  padding: 0 0.4rem; font-size: 0.85rem; color: var(--muted);
}
.builder-option-row { display: flex; gap: 0.4rem; margin-bottom: 0.4rem; }
.builder-option-row input { flex: 1; }
.builder-add-step-form { margin-top: 0.75rem; }
.builder-empty {
  padding: 1rem; text-align: center;
  border: 1px dashed var(--border); border-radius: 0.5rem;
}

.delete-post-form { margin-top: 2rem; padding-top: 1rem; border-top: 1px solid var(--border); }
.cta-danger { background: #b00020; color: #fff; border-color: #b00020; }
.cta-danger:hover { background: #8e0019; }
.small { font-size: 0.85rem; }

.docs-nav, .docs-body {
  margin-bottom: 1.5rem;
}
.docs-nav ul { list-style: none; padding: 0; }
.docs-nav li { padding: 0.25rem 0; }
.docs-nav li.current a { font-weight: 700; }

@media (min-width: 760px) {
  body.admin .content,
  body.manage .content {
    grid-template-columns: 220px 1fr;
  }
  body.docs .content {
    display: grid;
    grid-template-columns: 240px 1fr;
    gap: 2rem;
  }
}

@media (min-width: 1024px) {
  .content { padding: 2rem 1.5rem 4rem; }
  h1 { font-size: 2rem; }
}

/* Issue #7 — "fully styled" polish for the authenticated surfaces.
 * All rules read --accent / --accent-soft so they re-tint per role. */
body.admin .admin-nav,
body.manage .admin-nav {
  background: var(--accent-soft);
  border-color: var(--accent);
}
body.admin .admin-nav a,
body.manage .admin-nav a {
  color: var(--accent);
  font-weight: 600;
}
body.admin .admin-main h2,
body.manage .admin-main h2 {
  padding-bottom: 0.3rem;
  border-bottom: 2px solid var(--accent-soft);
}
body.admin .entries th,
body.admin .answers th,
body.admin .funnels th,
body.admin .counts th,
body.admin .keys th,
body.admin .posts th,
body.manage .entries th,
body.manage .answers th,
body.manage .funnels th,
body.manage .counts th,
body.manage .keys th,
body.manage .posts th {
  background: var(--accent-soft);
  color: var(--accent);
}
body.admin input:focus,
body.admin select:focus,
body.admin textarea:focus,
body.manage input:focus,
body.manage select:focus,
body.manage textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: var(--accent);
}

/* Issue #7 follow-up — login pages carry the `admin` body class for the
 * role chip + accent, but they have no sidebar (no .admin-nav). Without
 * this opt-out, body.admin .content's 220px+1fr grid squeezes the login
 * section into the narrow first column. body.login wins by source order
 * (equal specificity to body.admin .content; declared later). Also
 * pulls .admin-login forms out of bare-default browser styling. */
body.login .content {
  display: block;
  max-width: 480px;
}
.admin-login {
  padding: 2rem 0;
}
.admin-login h1 {
  text-align: center;
  margin: 0 0 0.5rem;
}
.admin-login p.muted {
  text-align: center;
  margin: 0 0 1.5rem;
}
.admin-login form {
  display: grid;
  gap: 1rem;
}
.admin-login form label {
  display: grid;
  gap: 0.35rem;
  font-weight: 600;
}
.admin-login form input {
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 0.4rem;
  font: inherit;
}
.admin-login form button[type=submit] {
  margin-top: 0.25rem;
  font-size: 1rem;
}

/* Issue #16 — modernized management surfaces. Additive over the
 * existing role-themed CSS: new tokens, status badges, refreshed table
 * density, refreshed form input padding/focus, wizard layout. No
 * existing rules removed. */

/* Visually hide content from sighted users while keeping it in the a11y
 * tree. The earlier `clip: rect(0,0,0,0)` variant left the element at its
 * static position, which on table-th cells at narrow viewports leaks
 * past the viewport edge and extends `<html>`.scrollWidth — caught at
 * 360px by Job 020 E2E. `left: -9999px` definitively off-screens it.
 * Screen readers still see + read the content. */
.visually-hidden {
  position: absolute;
  left: -9999px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Slightly looser tables on the management surfaces; the public/
 * comments tables stay unchanged. */
body.admin .posts th,
body.manage .posts th,
body.admin .posts td,
body.manage .posts td {
  padding: 0.65rem 0.75rem;
  vertical-align: middle;
}
body.admin .posts td.num,
body.manage .posts td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
body.admin .posts td.row-actions,
body.manage .posts td.row-actions {
  white-space: nowrap;
}
body.admin .posts tbody tr:hover,
body.manage .posts tbody tr:hover {
  background: var(--accent-soft);
}
body.admin .posts .post-url,
body.manage .posts .post-url {
  font-size: 0.85rem;
  margin-top: 0.15rem;
}
body.admin .posts .post-url code,
body.manage .posts .post-url code {
  background: transparent;
  padding: 0;
}

/* Status badge. Pill-shaped, neutral palette, distinct per state. The
 * data-status attribute is the load-bearing hook (tests assert on it);
 * the visible text mirrors it. */
.status-badge {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 600;
  line-height: 1.4;
  border: 1px solid transparent;
  background: var(--pill-private-bg);
  color: var(--pill-private-fg);
}
.status-badge[data-status="draft"] {
  background: #fff7e0;
  color: #6a4e00;
  border-color: #f0d68c;
}
.status-badge[data-status="published"],
.status-badge[data-status="published-pending"] {
  background: var(--pill-public-bg);
  color: var(--pill-public-fg);
  border-color: #b6d8b9;
}
.status-badge[data-status="disabled"] {
  background: var(--pill-hidden-bg);
  color: var(--pill-hidden-fg);
  border-color: #e9b6b6;
}
.status-note {
  font-size: 0.8rem;
  margin-left: 0.35rem;
}

/* Create CTA below the posts table. */
.create-cta {
  margin: 1.5rem 0 0;
}
.create-section {
  margin-top: 2rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--border);
}
.create-section h2 {
  margin-top: 0;
}

/* Wizard layout for /manage/posts/new. Full-page; two steps; form
 * inputs use a slightly larger touch target and clearer focus ring. */
.wizard {
  max-width: 560px;
  margin: 0 auto;
}
.wizard h1 {
  margin: 0.25rem 0 0.5rem;
}
.wizard-step-tag {
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: 0.75rem;
  font-weight: 600;
  margin: 0;
}
.wizard-form {
  display: grid;
  gap: 1.25rem;
  margin-top: 1.5rem;
}
.wizard-form label {
  display: grid;
  gap: 0.4rem;
}
.wizard-form .field-label {
  font-weight: 600;
}
.wizard-form .field-help {
  font-size: 0.85rem;
}
.wizard-form input[type=text],
.wizard-form input:not([type]) {
  padding: 0.65rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  font: inherit;
}
.wizard-form input:focus {
  outline: 3px solid var(--accent-soft);
  outline-offset: 0;
  border-color: var(--accent);
}
.wizard-actions {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  flex-wrap: wrap;
  margin-top: 1.25rem;
}
.wizard-back-form,
.wizard-confirm-form {
  margin: 0;
}
.wizard-review {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.5rem 1rem;
  margin: 1.5rem 0;
  padding: 1rem;
  background: var(--accent-soft);
  border: 1px solid var(--border);
  border-radius: 0.5rem;
}
.wizard-review dt {
  font-weight: 600;
  color: var(--muted);
}
.wizard-review dd {
  margin: 0;
  word-break: break-word;
}

@media (max-width: 480px) {
  .wizard-review {
    grid-template-columns: 1fr;
    gap: 0.15rem 0;
  }
  .wizard-review dt {
    margin-top: 0.5rem;
  }
}

/* Issue #16 follow-up — Job 020 admin/manage shell redesign.
 * Sidebar + topbar + stats cards + posts toolbar + per-row avatar. */

/* Authenticated topbar replaces the public top-nav on body.admin / body.manage.
 * The breadcrumb is left, the user-menu details element is right. */
body.admin .topbar,
body.manage .topbar {
  padding: 0.5rem 1rem;
  background: var(--accent-soft);
  border-bottom-color: var(--accent);
}
.app-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.5rem 1rem;
  border-bottom: 1px solid var(--border);
  background: #ffffff;
}
.app-breadcrumb ol {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: 0;
  padding: 0;
  font-size: 0.95rem;
  color: var(--muted);
}
.app-breadcrumb li::after {
  content: "›";
  margin-left: 0.35rem;
  color: var(--border);
}
.app-breadcrumb li:last-child::after { content: ""; }
.app-breadcrumb li[aria-current="page"] {
  color: var(--fg);
  font-weight: 600;
}
.app-breadcrumb a {
  color: var(--muted);
  text-decoration: none;
}
.app-breadcrumb a:hover { color: var(--accent); }

.app-user-menu {
  position: relative;
}
.app-user-menu > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.9rem;
  user-select: none;
}
.app-user-menu > summary::-webkit-details-marker { display: none; }
.app-user-menu[open] > summary { border-color: var(--accent); }
.app-user-email { font-weight: 500; }
.app-user-caret { color: var(--muted); font-size: 0.8rem; }
.app-user-menu-panel {
  position: absolute;
  right: 0;
  margin-top: 0.5rem;
  min-width: 12rem;
  padding: 0.4rem;
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  z-index: 20;
}
.app-user-menu-panel a,
.app-user-menu-panel button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.4rem 0.6rem;
  border-radius: 0.35rem;
  background: transparent;
  border: none;
  font: inherit;
  color: var(--fg);
  text-decoration: none;
  cursor: pointer;
}
.app-user-menu-panel a:hover,
.app-user-menu-panel button:hover {
  background: var(--accent-soft);
  color: var(--accent);
}

/* Shell grid: sidebar + main. Reuses the body.admin / body.manage
 * grid-template-columns set above. */
.app-shell {
  display: contents;
}
.app-sidebar {
  padding: 1rem;
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  background: var(--accent-soft);
  display: flex;
  flex-direction: column;
  gap: 1rem;
  position: sticky;
  top: 1rem;
  align-self: start;
}
.app-sidebar-brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  text-decoration: none;
  color: var(--fg);
  font-weight: 700;
  font-size: 1.05rem;
}
.app-sidebar-mark { border-radius: 0.4rem; }
.app-sidebar-wordmark { line-height: 1.1; }
.app-sidebar-nav ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.app-sidebar-nav a {
  display: block;
  padding: 0.55rem 0.7rem;
  border-radius: 0.4rem;
  color: var(--accent);
  text-decoration: none;
  font-weight: 600;
}
.app-sidebar-nav a:hover { background: rgba(255, 255, 255, 0.6); }
.app-sidebar-nav a[aria-current="page"] {
  background: var(--accent);
  color: var(--accent-fg);
}
.app-sidebar-footer {
  margin-top: auto;
  padding-top: 0.75rem;
  border-top: 1px solid rgba(0, 0, 0, 0.08);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.app-sidebar-signout button {
  color: var(--accent);
  font-weight: 600;
}
.app-sidebar-user {
  font-size: 0.85rem;
  margin: 0;
}

/* The new shell replaces the old .admin-nav rules. Keep .admin-nav for
 * backward-compat on any inherited surface, but the layout templates now
 * render .app-sidebar. */

/* Page header. */
.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.page-header h1 { margin: 0; }
.page-header-subtitle { margin: 0.25rem 0 0; }
.page-header-actions { display: flex; gap: 0.5rem; align-items: center; }

/* Stats row. Mobile: stacked. Desktop: 4 across. */
.stats-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.75rem;
  margin-bottom: 1.25rem;
}
@media (min-width: 640px) { .stats-row { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .stats-row { grid-template-columns: repeat(4, 1fr); } }
.stat-card {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  column-gap: 0.65rem;
  row-gap: 0.1rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--border);
  border-radius: 0.65rem;
  background: #ffffff;
}
.stat-card-icon {
  grid-row: span 2;
  align-self: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 0.5rem;
  background: var(--accent-soft);
  font-size: 1.1rem;
}
.stat-card-value {
  font-size: 1.4rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.stat-card-label {
  color: var(--muted);
  font-size: 0.85rem;
}

/* Posts toolbar (search + status + sort + apply). */
.posts-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  margin: 0 0 1rem;
  padding: 0.75rem;
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: 0.5rem;
}
.posts-toolbar input[type=search] {
  flex: 1 1 14rem;
  padding: 0.45rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 0.4rem;
  font: inherit;
}
.posts-toolbar-field select {
  padding: 0.45rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 0.4rem;
  font: inherit;
  background: #ffffff;
}
.posts-toolbar .cta {
  padding: 0.45rem 0.9rem;
}

/* Per-row avatar in the posts table. Deterministic 4-color palette. */
.post-cell {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.post-cell-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.post-cell-title {
  font-weight: 600;
}
.post-avatar {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 0.5rem;
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 700;
  font-size: 1rem;
}
.post-avatar[data-color="a"] { background: #e0ecff; color: #1e3a8a; }
.post-avatar[data-color="b"] { background: #fde7f3; color: #831843; }
.post-avatar[data-color="c"] { background: #e6f7ef; color: #065f46; }
.post-avatar[data-color="d"] { background: #fff5e0; color: #92400e; }

/* Empty state */
.empty-state {
  padding: 1.5rem;
  border: 1px dashed var(--border);
  border-radius: 0.6rem;
  text-align: center;
}

/* Hide the unauthenticated topbar's public-nav on authenticated bodies.
 * The authenticated topbar (overridden via the `topbar` block) carries
 * the breadcrumb + user menu instead. */
body.admin .topbar .brand,
body.admin .topbar .primary-nav,
body.manage .topbar .brand,
body.manage .topbar .primary-nav { display: none; }
body.login .topbar .brand,
body.login .topbar .primary-nav { display: initial; }

/* The login page already opts out of the shell grid via body.login. */

/* Responsive: at narrow widths the sidebar stacks above the main. */
@media (max-width: 759px) {
  .app-sidebar {
    position: static;
  }
  .app-sidebar-nav ul {
    flex-direction: row;
    overflow-x: auto;
    gap: 0.4rem;
  }
  .app-sidebar-footer {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
  .post-cell { gap: 0.5rem; }
  .post-avatar { width: 30px; height: 30px; font-size: 0.9rem; }
  /* Job 021 — at narrow viewports keep the page itself within the
   * viewport. Long slug URLs in <code> can otherwise force the
   * page-level scrollWidth past clientWidth (E2E spec for 360px caught
   * scrollWidth=515 before this fix landed). Two pieces together:
   *   - posts table becomes its own horizontal-scroll container,
   *     not the page;
   *   - <code> text breaks across characters so it doesn't enforce a
   *     wider min-width on the row.
   */
  body.admin .app-main,
  body.manage .app-main,
  body.admin .app-sidebar,
  body.manage .app-sidebar { min-width: 0; }
  .table-wrap {
    overflow-x: auto;
    max-width: 100%;
    -webkit-overflow-scrolling: touch;
  }
  .post-url code { word-break: break-all; }
  .posts-toolbar input[type=search] {
    flex: 1 1 100%;
    min-width: 0;
  }
  .stat-card { min-width: 0; }
  .app-user-email {
    max-width: 8rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}
