/* ── ff-post-flow.css ─────────────────────────────────────────────────────
   Newsletter/announcement post layout: title spans full width; body is
   2 columns of flowing text with inline photos. On mobile, collapses to
   1 column.

   Photo sizing/alignment is computed in ff-blog.js at render time (not
   stored in JSON). Rules:
     - First photo in a post → .flow-photo-full (column-span: all, hero)
     - Inline photos → .flow-photo-medium alternating right/left
   See plan_ff_post_flow_layout.md → "Surface discipline".
   ───────────────────────────────────────────────────────────────────── */

.flow-post {
  max-width: 900px;
  margin: 0 auto;
  padding: 16px;
}

.flow-post-title {
  /* Use the tenant's display font when ff-theme.js sets one; otherwise
     fall back to Amatic SC so the page still has personality on raw
     dev installs. Same pattern applies to body + drop-cap below. */
  font-family: var(--fnf-font-display, 'Amatic SC', cursive, sans-serif);
  color: var(--fnf-color-heading, inherit);
  font-size: 3rem;
  text-align: center;
  margin: 24px 0 8px;
  line-height: 1.1;
}

/* Free-form date shown under the title (display_date column). Hidden
   when the post has no display date set — keeps the spacing clean
   instead of leaving an empty line under the title. */
.flow-post-date {
  font-family: var(--fnf-font-accent, inherit);
  color: var(--fnf-color-text-muted, #888);
  font-size: 0.95rem;
  text-align: center;
  margin: 0 0 24px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.flow-post-date:empty {
  display: none;
}

.flow-post-body {
  column-count: 2;
  column-gap: 32px;
  column-rule: 1px solid #eee;
  font-family: var(--fnf-font-body, inherit);
  color: var(--fnf-color-text, inherit);
  font-size: 1rem;
  line-height: 1.7;
}

.flow-post-body p {
  margin: 0 0 1em;
  text-align: justify;
  hyphens: auto;
}

/* Drop cap on the first paragraph's first real letter. We deliberately
   skip empty / br-only paragraphs so the "Start typing…" placeholder's
   S doesn't get yanked out as a floated drop cap (which, inside a
   multi-column container, can also land in the wrong column). */
.flow-post-body p:first-child:not(:empty):not(:has(> br:only-child))::first-letter {
  font-family: var(--fnf-font-display, 'Amatic SC', cursive, sans-serif);
  font-size: 3.5em;
  float: left;
  line-height: 0.85;
  margin: 0.05em 0.08em 0 0;
  color: var(--fnf-color-accent, var(--fnf-color-primary, #444));
}

/* H2s break the column flow — act as a section divider that spans both. */
.flow-post-body h2 {
  font-family: var(--fnf-font-heading, 'Amatic SC', cursive, sans-serif);
  color: var(--fnf-color-heading, inherit);
  font-size: 2rem;
  margin: 1.5em 0 0.5em;
  column-span: all;
  text-align: center;
  break-after: avoid;
}

.flow-post-body ul,
.flow-post-body ol {
  margin: 0 0 1em;
  padding-left: 1.5em;
}

.flow-post-body li {
  margin-bottom: 0.3em;
}

/* ── Inline photo figures ───────────────────────────────────────────── */

.flow-post-body figure.flow-photo {
  position: relative;     /* anchor for the per-photo controls bar */
  margin: 0 0 1em;
  padding: 0;
  /* Lock the image and its caption together. Without this, CSS multi-
     column flow can split the figure: image at the bottom of column N,
     figcaption orphaned at the top of column N+1 (looks like a stray
     italic paragraph far from any photo). The legacy property name is
     kept for older browsers. */
  break-inside: avoid;
  page-break-inside: avoid;
}

.flow-post-body figure.flow-photo img {
  width: 100%;
  display: block;
  border-radius: 6px;
  /* Empty-collection placeholder: ff-photomanager swaps the 1×1
     transparent gif for a real image once one's uploaded. Until then,
     give the image area a visible box so the figure isn't "just a
     floating caption" — and so the photomanager's hover overlay has
     something to land on. */
  min-height: 120px;
  background: #f8fafc;
}

.flow-post-body figure.flow-photo figcaption {
  font-size: 0.85rem;
  color: #666;
  text-align: center;
  margin-top: 0.4em;
  font-style: italic;
  line-height: 1.3;
}

/* Full-width hero: breaks out of column flow. Used for the first photo
   in a post. */
.flow-post-body figure.flow-photo-full {
  column-span: all;
  margin: 1em 0 1.5em;
}

.flow-post-body figure.flow-photo-full img {
  max-height: 480px;
  object-fit: cover;
}

/* Medium inline photo — half-column, text wraps around. */
.flow-post-body figure.flow-photo-medium {
  width: 60%;
  margin-bottom: 0.75em;
}

.flow-post-body figure.flow-photo-medium-right {
  float: right;
  margin-left: 16px;
  margin-right: 0;
  shape-outside: margin-box;
}

.flow-post-body figure.flow-photo-medium-left {
  float: left;
  margin-right: 16px;
  margin-left: 0;
  shape-outside: margin-box;
}

/* Centered within column — block, no text wrap. Text continues above
   and below the photo within the same column. */
.flow-post-body figure.flow-photo-medium-center {
  display: block;
  float: none;
  margin-left: auto;
  margin-right: auto;
  width: 80%;
}

/* ── Mobile: 1 column, photos full-width ────────────────────────────── */

@media (max-width: 768px) {
  .flow-post-body {
    column-count: 1;
    column-rule: none;
  }
  .flow-post-body figure.flow-photo-medium,
  .flow-post-body figure.flow-photo-medium-right,
  .flow-post-body figure.flow-photo-medium-left {
    float: none;
    width: 100%;
    margin: 1em 0;
  }
  .flow-post-title {
    font-size: 2.25rem;
  }
}

/* ── Empty state (no body content yet) ──────────────────────────────── */

.flow-post-body-empty {
  column-count: 1;
  text-align: center;
  color: #999;
  padding: 40px 0;
  font-style: italic;
}

/* ── Edit mode affordances (slice B) ─────────────────────────────────── */

.flow-post-body[contenteditable="true"] {
  outline: 2px dashed transparent;
  outline-offset: 6px;
  border-radius: 4px;
  transition: outline-color 0.2s ease;
  min-height: 200px;
}

.flow-post-body[contenteditable="true"]:focus-within {
  outline-color: #c7d2fe;
}

/* Empty-paragraph placeholder hint — shows when a P has no text or
   only a single trailing <br>. Pointer-events:none so it doesn't
   intercept the click that places the caret. Generic "Start typing…"
   — the flow template isn't newsletter-only; people also use it for
   announcements, story posts, anything flow-shaped. */
/* The placeholder is taken OUT of the inline flow (absolute, not inline).
   As an inline ::before it occupied real space on the line, so the caret was
   pushed to sit AFTER "Start typing…" — which reads as though whatever you
   type will be appended to the hint rather than replacing it. Absolute
   positioning puts the caret at the left edge where it belongs, exactly like
   a form field's placeholder. Needs position:relative on the paragraph to
   anchor against. */
.flow-post-body[contenteditable="true"] p:empty,
.flow-post-body[contenteditable="true"] p:has(> br:only-child) {
  position: relative;
}
.flow-post-body[contenteditable="true"] p:empty::before,
.flow-post-body[contenteditable="true"] p:has(> br:only-child)::before {
  content: 'Start typing…';
  position: absolute;
  left: 0;
  top: 0;
  color: #c9cdd3;
  pointer-events: none;
  font-style: italic;
  user-select: none;
}

/* Subtle border on photo figures so the author sees where they live —
   especially useful before the photo's collection has been populated. */
.flow-post-body[contenteditable="true"] figure.flow-photo {
  outline: 1px dashed #cbd5e1;
  outline-offset: 4px;
  border-radius: 4px;
}

/* Empty figcaption gets a hint too — same out-of-flow treatment, or the
   caret sits after "Caption…" instead of in front of it. */
.flow-post-body[contenteditable="true"] figure.flow-photo figcaption:empty {
  position: relative;
}
.flow-post-body[contenteditable="true"] figure.flow-photo figcaption:empty::before {
  content: 'Caption…';
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  color: #c9cdd3;
  pointer-events: none;
  font-style: italic;
  user-select: none;
}

/* ── Per-photo control bar (slice B — placement + delete) ────────────── */

/* Positioned INSIDE the figure (top-right corner) rather than floating
   above it. Outside-positioning had a flicker bug: the small gap between
   the figure's top edge and the bar's bottom edge broke the :hover chain
   when the cursor traversed it, so the bar disappeared before you could
   click anything. Overlaying the photo keeps the bar in the figure's
   hover region the whole time. z-index sits above photomanager's
   replace/reposition overlay (z-index:10). */
.ff-flow-photo-controls {
  position: absolute;
  top: 8px;
  right: 8px;
  display: none;
  gap: 2px;
  background: rgba(255, 255, 255, 0.95);
  border: 1px solid #c7d2fe;
  border-radius: 6px;
  padding: 2px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.18);
  z-index: 30;
  backdrop-filter: blur(2px);
}

/* Show controls when hovering the figure or when any focus lives inside
   it (covers the figcaption-editing case). */
.flow-post-body[contenteditable="true"] figure.flow-photo:hover .ff-flow-photo-controls,
.flow-post-body[contenteditable="true"] figure.flow-photo:focus-within .ff-flow-photo-controls {
  display: inline-flex;
}

.ff-flow-photo-controls button {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  padding: 5px 8px;
  color: #475569;
  border-radius: 4px;
}

.ff-flow-photo-controls button:hover {
  background: #f1f5f9;
  color: #1e293b;
}

.ff-flow-photo-controls button.active {
  background: #c7d2fe;
  color: #1e293b;
}

.ff-flow-photo-controls button.delete:hover {
  background: #fee2e2;
  color: #dc2626;
}

/* ── Between-blocks inserter ─────────────────────────────────────────────
   Hover the gap between two blocks → a thin line with a ⊕. Clicking it
   opens a small Text / Heading / List / Photo menu and inserts exactly
   there. Replaces the insert buttons that used to sit in the top strip:
   a toolbar far from the cursor can't answer "insert WHERE", which is how
   photos ended up on top of the text.

   Both elements live in <body>, outside the editable flow body, so the
   serializer can never mistake them for content. */

.ff-flow-ins {
  position: absolute;
  height: 2px;
  background: #2563eb;
  border-radius: 2px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease;
  z-index: 900;
}
.ff-flow-ins.is-visible { opacity: 1; pointer-events: auto; }

.ff-flow-ins__plus {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 26px;
  height: 26px;
  padding: 0;
  border: 1px solid #2563eb;
  border-radius: 50%;
  background: #fff;
  color: #2563eb;
  font-size: 13px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
}
.ff-flow-ins__plus:hover { background: #2563eb; color: #fff; }

.ff-flow-ins__menu {
  position: absolute;
  display: none;
  min-width: 150px;
  padding: 4px;
  background: #fff;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.16);
  z-index: 901;
}
.ff-flow-ins__menu.is-open { display: block; }

.ff-flow-ins__item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 7px 10px;
  border: none;
  border-radius: 5px;
  background: transparent;
  color: #1f2937;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}
.ff-flow-ins__item:hover { background: #eff6ff; color: #2563eb; }
.ff-flow-ins__item i { font-size: 15px; opacity: 0.75; }

/* Drag handle — appears in the left margin of the hovered block. Drag it to
   move that block; the insert line doubles as the drop indicator. Lives in
   <body>, outside the editable area, like the inserter. */

.ff-flow-handle {
  position: absolute;
  width: 22px;
  height: 24px;
  padding: 0;
  border: 1px solid #e2e8f0;
  border-radius: 5px;
  background: #fff;
  color: #94a3b8;
  font-size: 14px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: grab;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease;
  z-index: 899;
}
.ff-flow-handle.is-visible { opacity: 1; pointer-events: auto; }
.ff-flow-handle:hover { color: #2563eb; border-color: #2563eb; }
.ff-flow-handle:active { cursor: grabbing; }

/* The block being dragged: dimmed and outlined so it's obvious what's moving.
   Text selection is killed page-wide for the duration, or the drag paints a
   selection across the article instead of moving anything. */
.flow-post-body .ff-flow-dragging {
  opacity: 0.45;
  outline: 2px dashed #2563eb;
  outline-offset: 3px;
}
body.ff-flow-drag-active,
body.ff-flow-drag-active * {
  cursor: grabbing !important;
  user-select: none !important;
}

/* (?) help affordance on the post strip's controls. Convention: a labelled
   on/off switch explains itself, anything else gets one of these. */
.ff-flow-help {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  margin-left: 4px;
  border: 1px solid #94a3b8;
  border-radius: 50%;
  color: #64748b;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  cursor: help;
  user-select: none;
}
.ff-flow-help:hover,
.ff-flow-help:focus { border-color: #2563eb; color: #2563eb; outline: none; }

/* Blocks should LOOK like blocks while editing. A faint tint on the block
   under the pointer (paired with the ⠿ handle appearing in its margin) makes
   the boundaries visible, so it's obvious what a drag will move and what a
   delete will affect. View mode is untouched. */
.flow-post-body[contenteditable="true"] > *.ff-flow-hover {
  background: rgba(37, 99, 235, 0.04);
  box-shadow: 0 0 0 1px rgba(37, 99, 235, 0.12);
  border-radius: 3px;
}

/* Delete-this-block button, under the drag handle in the left margin. Every
   block gets one — photos used to be the only thing with a visible way to
   remove it. */
.ff-flow-del {
  position: absolute;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 1px solid #e2e8f0;
  border-radius: 5px;
  background: #fff;
  color: #94a3b8;
  font-size: 11px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease;
  z-index: 899;
}
.ff-flow-del.is-visible { opacity: 1; pointer-events: auto; }
.ff-flow-del:hover { color: #dc2626; border-color: #dc2626; }

/* ── Version history panel ───────────────────────────────────────────────
   Every save keeps the version it replaced (migration 094). This editor
   rewrites the whole body on each autosave, so without a way back a single
   bad save is permanent — which is exactly what lost work on 2026-08-22. */

.ff-flow-hist {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 3000;
  padding: 20px;
}
.ff-flow-hist__panel {
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.3);
  width: 100%;
  max-width: 560px;
  max-height: 80vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.ff-flow-hist__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid #e2e8f0;
  font-size: 16px;
}
.ff-flow-hist__close {
  border: none; background: none; font-size: 24px; line-height: 1;
  color: #64748b; cursor: pointer; padding: 0 4px;
}
.ff-flow-hist__close:hover { color: #0f172a; }
.ff-flow-hist__note {
  margin: 0; padding: 10px 18px; font-size: 13px; color: #64748b;
  background: #f8fafc; border-bottom: 1px solid #e2e8f0;
}
.ff-flow-hist__body { overflow-y: auto; padding: 8px 0; }
.ff-flow-hist__empty { padding: 24px 18px; color: #64748b; font-size: 14px; text-align: center; }

.ff-flow-hist__row {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas: "meta btn" "preview btn";
  gap: 2px 12px;
  align-items: center;
  padding: 10px 18px;
  border-bottom: 1px solid #f1f5f9;
}
.ff-flow-hist__row:last-child { border-bottom: none; }
.ff-flow-hist__meta {
  grid-area: meta; display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
}
.ff-flow-hist__when  { font-weight: 600; font-size: 14px; color: #0f172a; }
.ff-flow-hist__count { font-size: 12px; color: #64748b; }
.ff-flow-hist__who   { font-size: 12px; color: #94a3b8; }
.ff-flow-hist__preview {
  grid-area: preview; font-size: 13px; color: #64748b; line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ff-flow-hist__restore {
  grid-area: btn;
  border: 1px solid #c7d2fe; border-radius: 6px; background: #fff;
  color: #2563eb; font-size: 13px; padding: 5px 12px; cursor: pointer; white-space: nowrap;
}
.ff-flow-hist__restore:hover:not(:disabled) { background: #eff6ff; }
.ff-flow-hist__restore:disabled { opacity: 0.6; cursor: default; }
