/*
 * FieldCMS base.css — shared markdown component styles.
 *
 * Loaded by every theme's base.html BEFORE site.css so themes
 * can override with their own colours/spacing. Defines structure
 * only; colours use CSS custom properties that themes set in :root.
 *
 * Conventions:
 *   --border        border colour
 *   --bg-raised     slightly elevated surface (code blocks, table headers)
 *   --fg            primary text colour
 *   --fg-muted      secondary / label text
 *
 * Any theme that sets these variables gets correct component styling
 * for free. Add new shared components here — never in site.css.
 */

/* ── Markdown body scope ────────────────────────────────────────────── */
/* Applied to .post-body and .page-body by convention in all themes.    */

.post-body, .page-body {
  line-height: 1.65;
}

/* ── Tables ─────────────────────────────────────────────────────────── */

.post-body table,
.page-body table {
  border-collapse: collapse;
  width: 100%;
  max-width: 100%;
  margin: 24px 0;
  font-size: 0.92em;
  overflow-x: auto;
  display: table;
}

.post-body th,
.page-body th {
  background: var(--bg-raised, #f4f4f5);
  color: var(--fg-muted, #6b7280);
  font-weight: 600;
  font-size: 0.8em;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-align: left;
  padding: 8px 12px;
  border: 1px solid var(--border, #e5e7eb);
  white-space: nowrap;
}

.post-body td,
.page-body td {
  padding: 8px 12px;
  border: 1px solid var(--border, #e5e7eb);
  vertical-align: top;
  color: var(--fg, #1a1d24);
}

.post-body tr:nth-child(even) td,
.page-body tr:nth-child(even) td {
  background: rgba(128, 128, 128, 0.04);
}

/* ── Images ─────────────────────────────────────────────────────────── */

.post-body img,
.page-body img {
  max-width: 100%;
  width: 100%;
  height: auto;
  border-radius: 4px;
  display: block;
  margin: 20px 0;
  object-fit: cover;
}

/* Body images — float alternating left/right with text wrapping, plus
   overlay captions to match the hero style. Two markup patterns are
   supported in parallel:
     * <figure class="fb-figure"><img/><figcaption>...</figcaption></figure>
       — emitted by the drafter post-processor for newer content
     * <p><img/><br/><em>caption</em></p>
       — the raw markdown render for older content (![alt](url)\n_caption_)
   Both get the same float behaviour + overlay caption. The <br> that
   the markdown renderer inserts between img and em is collapsed.
   A small JS snippet in the theme picks a random starting side and
   tags each figure with .float-left or .float-right synchronously; the
   wide-image detection toggles .wide on images whose natural aspect
   ratio exceeds 2.2:1 so banner-wide images sit full-width. */

/* Shared figure base */
.page-body .fb-figure,
.post-body .fb-figure,
.page-body > p:has(> img),
.post-body > p:has(> img) {
  position: relative;
  max-width: 46%;
  margin: 6px 0 16px;
  text-align: left;
}
.page-body .fb-figure img,
.post-body .fb-figure img,
.page-body > p:has(> img) > img,
.post-body > p:has(> img) > img {
  width: 100%;
  height: 100%;
  display: block;
  margin: 0;
  border-radius: 4px;
  object-fit: cover;
  object-position: center;
}
/* Constrain the floated container itself — aspect-ratio on the wrapper
   (not the <img>) so the image always crops to landscape regardless of
   its intrinsic shape. Portrait photos lose their tall framing but
   don't dominate whole sections, which would force h2 headings into
   the narrow text column or push them past multiple paragraphs. */
.page-body .fb-figure,
.post-body .fb-figure,
.page-body > p:has(> img),
.post-body > p:has(> img) {
  aspect-ratio: 5 / 3;
  overflow: hidden;
}
.page-body > p:has(> img) > br,
.post-body > p:has(> img) > br { display: none; }

/* Float sides. `clear: both` on every floated image so two images close
   together never stack side-by-side — the second one always starts
   below the first, giving text room to wrap cleanly around each one
   in turn. */
.page-body .fb-figure.float-right,
.post-body .fb-figure.float-right,
.page-body > p:has(> img).float-right,
.post-body > p:has(> img).float-right {
  float: right;
  margin-left: 1.5rem;
  margin-right: 0;
  clear: both;
}
.page-body .fb-figure.float-left,
.post-body .fb-figure.float-left,
.page-body > p:has(> img).float-left,
.post-body > p:has(> img).float-left {
  float: left;
  margin-right: 1.5rem;
  margin-left: 0;
  clear: both;
}

/* Very-wide images (aspect ratio > 2.2:1) go full width, no float */
.page-body .fb-figure.wide,
.post-body .fb-figure.wide,
.page-body > p:has(> img).wide,
.post-body > p:has(> img).wide {
  float: none;
  max-width: 100%;
  margin: 1.5rem auto;
}

/* Overlay caption — bottom-right pill on the image */
.page-body .fb-figure figcaption,
.post-body .fb-figure figcaption,
.page-body > p:has(> img) > em,
.post-body > p:has(> img) > em {
  position: absolute;
  bottom: 8px;
  right: 12px;
  margin: 0;
  padding: 2px 8px;
  background: rgba(0, 0, 0, 0.55);
  color: rgba(255, 255, 255, 0.85);
  font-size: 0.7rem;
  line-height: 1.3;
  border-radius: 3px;
  font-style: italic;
  text-align: left;
}

/* Clear trailing floats so the article footer doesn't slide up into
   a floated image's empty column. */
.page-body::after,
.post-body::after {
  content: "";
  display: block;
  clear: both;
}

/* Clear floats before the Sources section so the source list never
   wraps around a trailing body image. Two forms to cover:
     * Post template: <section class="post-sources"> lives outside .post-body
     * Page body: drafter emits "## Sources" as the final h2 in body_html,
       so `:last-of-type` targets it without clearing earlier section headings.
   Intermediate h2s stay clear-free so body text wraps floats normally. */
.page-body > h2:last-of-type,
.post-body > h2:last-of-type { clear: both; }
.post-sources,
.post-footer,
.page-sources { clear: both; }

/* Mobile: floats are cramped — let images stack full-width instead. */
@media (max-width: 720px) {
  .page-body .fb-figure,
  .post-body .fb-figure,
  .page-body > p:has(> img),
  .post-body > p:has(> img) {
    float: none !important;
    max-width: 100% !important;
    margin: 1rem auto !important;
  }
}

/* ── Blockquote ──────────────────────────────────────────────────────── */

.post-body blockquote,
.page-body blockquote {
  border-left: 3px solid var(--border, #e5e7eb);
  margin: 0 0 1em;
  padding: 4px 18px;
  color: var(--fg-muted, #6b7280);
}

/* ── Fieldbook Agents image figures (drafter output) ──────────────────
 * <figure class="fb-figure"> wraps each ![alt](url) + ``_caption_`` pair
 * the unified-drafter / report-drafter emit, so the caption sits flush
 * against the image and renders smaller than body text. Without this
 * rule the markdown renderer emits two separate <p> elements and the
 * caption floats with full body line-height, looking unrelated to the
 * image above.
 * ──────────────────────────────────────────────────────────────────── */
.fb-figure {
  margin: 1.5rem auto;
  max-width: 100%;
  text-align: center;
}
.fb-figure img {
  display: block;
  width: 100%;
  height: auto;
  margin: 0 auto;
  border-radius: 4px;
}
.fb-figure figcaption {
  margin-top: 0.4rem;
  font-size: 0.78rem;
  line-height: 1.35;
  color: var(--fg-muted, #6b7280);
  font-style: italic;
  text-align: center;
}

/* ── Fieldbook Agents diagrams (svg-architect output) ──────────────────
 * <figure class="fb-diagram"> wraps one inline animated SVG per page,
 * inserted by the diagram_builder step in the agent pipeline.
 *
 * Reveal behaviour: the entire figure is held at opacity 0 and faded in
 * once the reader has scrolled roughly 150-200px past its top edge. The
 * gating lives on the figure (an HTML block element) rather than on the
 * SVG children because Chromium's ``animation-timeline: view()`` is
 * unreliable on elements nested inside an <svg> — the inner stagger
 * animations often fall back to the document timeline and complete on
 * page load, so by the time the reader scrolls into view the diagram is
 * already fully drawn. Gating the figure guarantees the "dark until
 * visible" behaviour regardless of whether the inner animations honour
 * the scroll timeline.
 *
 * Browsers without animation-timeline: view() (Safari as of 2025) skip
 * the gate and show the diagram normally — graceful degradation via
 * @supports.
 * ──────────────────────────────────────────────────────────────────── */
.fb-diagram {
  margin: 36px auto;
  max-width: 100%;
  overflow: visible;
}
.fb-diagram svg {
  display: block;
  width: 100%;
  height: auto;
}
@supports (animation-timeline: view()) {
  .fb-diagram {
    opacity: 0;
    animation: fb-diagram-reveal 1ms linear forwards;
    animation-timeline: view();
    /* Range anchors:
     *   entry 0%   = bottom of figure touches bottom of viewport
     *   entry 100% = top of figure touches bottom of viewport (fully entered)
     *   contain 0% = same as entry 100%, contain 100% = fully visible elapsed
     *
     * Stay invisible from entry 0% → entry 70% (~280px of scroll for a
     * 400px-tall diagram) so the figure is genuinely dark until the
     * reader has pulled it well into view. Fade in over entry 70% →
     * contain 40% (~440px more), so the reveal spans hundreds of
     * pixels and cannot finish before the figure is reached. The
     * animation-duration (1ms) is irrelevant — animation-timeline
     * overrides it with the scroll range length. */
    animation-range: entry 70% contain 40%;
  }
  /* Inner scroll-triggered animations kept for browsers that DO honour
   * view() on SVG children. Longer window so the stagger feels unhurried
   * and finishes well after the reader has stopped scrolling. */
  .fb-diagram [class] {
    animation-timeline: view();
    animation-range: entry 70% contain 80%;
  }
}
@keyframes fb-diagram-reveal {
  to { opacity: 1; }
}

/* ── Full-bleed site hero ─────────────────────────────────────────────
 * Public renderer lifts the first <figure class="fb-figure"> off the
 * top of body_html into a separate `hero_html` context var. Themes
 * render it in a {% block hero %} slot ABOVE the main article so the
 * hero spans full viewport width, flush against the nav below. Tall /
 * portrait source images crop to a wide banner via object-fit: cover.
 * ──────────────────────────────────────────────────────────────────── */
.site-hero {
  width: 100%;
  margin: 0;
}
.site-hero .fb-figure {
  margin: 0;
  max-width: 100%;
  text-align: left;
}
.site-hero .fb-figure img {
  width: 100%;
  height: auto;
  max-height: 520px;
  aspect-ratio: 3 / 1;
  object-fit: cover;
  object-position: center;
  border-radius: 0;
  display: block;
}
.site-hero .fb-figure figcaption {
  position: absolute;
  bottom: 8px;
  right: 12px;
  margin: 0;
  padding: 2px 8px;
  background: rgba(0, 0, 0, 0.55);
  color: rgba(255, 255, 255, 0.85);
  font-size: 0.7rem;
  line-height: 1.3;
  border-radius: 3px;
}
.site-hero .fb-figure {
  position: relative;
}

/* ── SVG diagram headings inherit page fg ─────────────────────────────
 * The svg-architect post-processor rewrites `.diag-title` fills to
 * `currentColor`, but older diagrams bake `fill: #0f172a` or similar.
 * Force the page foreground so titles read on dark themes too.
 * ──────────────────────────────────────────────────────────────────── */
.site-main svg .diag-title,
.site-main svg .diagram-title,
.site-main svg .fig-title { fill: currentColor; }

/* ── Sticky site nav + mobile hamburger ──────────────────────────────
 * Opt-in: theme markup must include a hamburger `<button class="nav-toggle">`
 * inside `.site-nav`, and JS to toggle a `.nav-open` class on the nav.
 * Desktop hides the toggle; narrow viewports hide `.nav-links` until
 * the nav is opened. Themes that don't want sticky behavior can
 * override `.site-nav { position: static; }` in their own stylesheet.
 * ──────────────────────────────────────────────────────────────────── */
.site-nav {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--bg, #fff);
}
.site-nav .nav-toggle {
  display: none;
  width: 36px;
  height: 36px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--border, #e5e7eb);
  border-radius: 4px;
  color: var(--fg, inherit);
  cursor: pointer;
  margin-left: auto;
  font-size: 18px;
  line-height: 1;
  align-items: center;
  justify-content: center;
}
.site-nav .nav-toggle:focus-visible {
  outline: 2px solid var(--accent, #3b82f6);
  outline-offset: 2px;
}

@media (max-width: 720px) {
  .site-nav .nav-toggle { display: inline-flex; }
  .site-nav .nav-links {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--bg, #fff);
    border-bottom: 1px solid var(--border, #e5e7eb);
    padding: 4px 0;
    margin: 0;
  }
  .site-nav.nav-open .nav-links { display: flex; }
  .site-nav .nav-links > li,
  .site-nav .nav-links .nav-item { width: 100%; }
  .site-nav .nav-links a {
    display: block;
    padding: 10px 20px;
  }
  /* Submenus stack inline on mobile — no hover dropdown. */
  .site-nav .submenu {
    position: static;
    display: block;
    border: none;
    box-shadow: none;
    background: transparent;
    padding: 0 0 4px 16px;
    min-width: 0;
  }
}
