/* Shared presentation for sanitized documents and TinyMCE's editable body. */
:root {
  /* A4 sheet width (210mm at 96dpi), in rem so it tracks the root font size. */
  --rich-text-measure: 49.6rem;
  /* Clearance between the A4 text column and its margin rules. */
  --rich-text-gutter: 1.5rem;
  --rich-text-mobile-editor-gutter: 0.75rem;
  /* Virtual sheet geometry. The inline box mirrors the guardrails frame exactly — sheet
     edge where the rules are, side margin equal to the gutter — so switching width modes
     never reflows the text column. Block values stay px (A4 at 96dpi): a sheet is a
     physical height and the measured page-break math works in the same unit. */
  --rich-text-page-width: calc(var(--rich-text-measure) + var(--rich-text-gutter) * 2);
  --rich-text-page-height: 1123px;
  --rich-text-page-gap: 24px;
  --rich-text-page-margin-inline: var(--rich-text-gutter);
  --rich-text-page-margin-block: 64px;
  --rich-text-page-content-height: calc(
    var(--rich-text-page-height) - var(--rich-text-page-margin-block) -
      var(--rich-text-page-margin-block)
  );
  /* Written by useDocumentPageLayout so the last sheet ends complete. */
  --rich-text-page-fill: 0px;
}

.rich-text-content {
  box-sizing: border-box;
  color: var(--foreground);
  /* Pages mode is on unless a host narrows it off; useDocumentPageLayout reads the
     same flag, so the CSS fallback and the measured breaks can never disagree. */
  --rich-text-pages-active: 1;
  font-family: 'Jost', sans-serif;
  font-size: 1rem;
  line-height: 1.625;
  overflow-wrap: anywhere;
  /* Containing block for the margin rules, and the offsetParent the page-break
     measurements are taken against. */
  position: relative;
  /* Layout-affecting zoom: caret and hit-testing coordinates stay native inside
     contenteditable, and authored image sizes scale with the text. */
  zoom: var(--rich-text-zoom, 1);
}

/*
 * Margin rules framing the A4 text column. Hosts opt in through
 * `--rich-text-rails-display` once their surface is wide enough — the viewer with a
 * container query, the editor iframe with its own viewport width. Living inside the
 * zoomed element means `min(100%, …)` clamps them to the surface at any zoom, with no
 * scale math: 100% is already the available width in the element's own coordinates.
 */
/* TinyMCE reserves ::before for its placeholder. Keep the rails on ::after. */
[data-doc-width='page'] .rich-text-content::after {
  border-inline: 1px solid var(--border);
  box-sizing: border-box;
  content: '';
  display: var(--rich-text-rails-display, none);
  inline-size: min(100%, calc(var(--rich-text-measure) + var(--rich-text-gutter) * 2));
  inset-block: 0;
  inset-inline: 0;
  margin-inline: auto;
  /* Ends fade instead of butting into the surface padding; capped for short documents. */
  mask-image: linear-gradient(
    to bottom,
    transparent,
    #000 min(3rem, 12%),
    #000 calc(100% - min(3rem, 12%)),
    transparent
  );
  pointer-events: none;
  position: absolute;
  z-index: -1;
}

/* The editor iframe has no container ancestor to query, so it gates on its own width. */
@media (min-width: 55rem) {
  html:has(> body.rich-text-content) > body {
    --rich-text-rails-display: block;
  }
}

.rich-text-content *,
.rich-text-content *::before,
.rich-text-content *::after {
  box-sizing: border-box;
}

/* Keep every top-level document block inside the shared reading measure. Table keeps its
   native display model; newly supported non-table content remains block-level by default. */
.rich-text-content > :not(br) {
  max-inline-size: var(--rich-text-measure);
  margin-inline: auto;
}

.rich-text-content > :not(br, table) {
  display: block;
}

/* Text containers fill the measure; media keeps its authored/intrinsic width. */
.rich-text-content > :not(br, img) {
  inline-size: 100%;
}

/* Float-based image alignment must contribute to its block's measured page height. */
.rich-text-content > :not(table):has(img) {
  display: flow-root;
}

/*
 * Width modes. The flag lives on the document element of whichever document owns the
 * content — the host page's <html> in the viewer, the iframe's <html> in the editor —
 * so one selector shape resolves in both. These outrank the `body.rich-text-content`
 * block TinyMCE injects via content_style, which is why pages mode can restyle the
 * editor body without reordering the injection.
 */

/* Full width: top-level content stops being capped, but keeps a readable edge gutter. */
[data-doc-width='full'] .rich-text-content {
  padding-inline: clamp(1rem, 3vw, 2rem) !important;
}

[data-doc-width='full'] .rich-text-content > :not(br) {
  max-inline-size: none;
}

/* Inherited padding keeps the placeholder aligned with the first text block in every width mode.
   The content-box measure leaves the editor's side gutters outside the text column. */
.rich-text-content.mce-content-body[data-mce-placeholder]:not(.mce-visualblocks)::before {
  box-sizing: content-box;
  color: var(--muted-foreground);
  inline-size: auto;
  inset-inline: 0;
  margin-inline: auto;
  max-inline-size: var(--rich-text-measure);
  padding-inline: inherit;
}

[data-doc-width='full']
  .rich-text-content.mce-content-body[data-mce-placeholder]:not(.mce-visualblocks)::before {
  max-inline-size: none;
}

/*
 * Virtual pages: the content element becomes the paper stack itself. The desk is
 * card-colored so it merges with a card host — two levels, not three — and the paper
 * sits a step lighter than it, which `--card` against `--background` is too close to do.
 */
[data-doc-width='pages'] .rich-text-content {
  background-color: transparent;
  background-image: repeating-linear-gradient(
    to bottom,
    var(--muted) 0,
    var(--muted) var(--rich-text-page-height),
    transparent var(--rich-text-page-height),
    transparent calc(var(--rich-text-page-height) + var(--rich-text-page-gap))
  );
  inline-size: var(--rich-text-page-width);
  margin-inline: auto;
  min-block-size: var(--rich-text-page-height);
  padding: var(--rich-text-page-margin-block) var(--rich-text-page-margin-inline);
  /* The measured fill completes the last sheet below the final page margin. */
  padding-block-end: calc(var(--rich-text-page-margin-block) + var(--rich-text-page-fill));
}

/* Code shares the paper tone, so on paper it steps down to the desk color instead. */
[data-doc-width='pages'] .rich-text-content :where(code, pre) {
  background: var(--card);
}

/*
 * In TinyMCE's iframe the body is the sheet, so its <html> is the desk and owns the
 * clearance above the first page. `:has()` keeps this off the host page, whose <html>
 * carries the same flag but is not a document surface.
 */
html[data-doc-width='pages']:has(> body.rich-text-content) {
  background-color: var(--card);
  padding-block: var(--rich-text-page-gap);
}

/* Phones always use the available reading width. The persisted desktop mode stays
   untouched, but page rails and virtual sheets never consume scarce mobile space. */
@media (width < 48rem) {
  [data-doc-width] .rich-text-content {
    --rich-text-pages-active: 0;
    padding-inline: 0 !important;
  }

  [data-doc-width] .rich-text-content > :not(br) {
    max-inline-size: none;
  }

  [data-doc-width] .rich-text-content > img {
    max-inline-size: 100%;
  }

  [data-doc-width='pages'] .rich-text-content {
    --rich-text-pages-active: 0;
    background-image: none;
    inline-size: auto;
    margin-inline: 0;
    min-block-size: 0;
    padding: 0 !important;
  }

  html[data-doc-width='pages']:has(> body.rich-text-content) {
    background-color: transparent;
    padding-block: 0;
  }

  [data-doc-width]
    .rich-text-content.mce-content-body[data-mce-placeholder]:not(.mce-visualblocks)::before {
    max-inline-size: none;
  }

  /* TinyMCE owns its iframe body, so restore a small editing gutter without
     changing the edge-to-edge read-only document surface. */
  html:has(> body.rich-text-content) > body.rich-text-content {
    padding-inline: var(--rich-text-mobile-editor-gutter) !important;
  }
}

.rich-text-content :where(h1, h2, h3, h4, h5, h6) {
  color: var(--foreground);
  letter-spacing: -0.025em;
  margin-block: 0.75em 0.25em;
}

.rich-text-content :where(h1, h2, h3, h4, h5, h6):first-child {
  margin-block-start: 0;
}

.rich-text-content h1 {
  font-size: 1.875rem;
  font-weight: 700;
  line-height: 2.25rem;
}

.rich-text-content h2 {
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 2rem;
}

.rich-text-content h3 {
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.75rem;
}

.rich-text-content h4 {
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.75rem;
  letter-spacing: normal;
}

.rich-text-content h5 {
  font-size: 1rem;
  font-weight: 500;
  line-height: 1.5rem;
  letter-spacing: normal;
}

.rich-text-content h6 {
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.25rem;
  letter-spacing: normal;
}

.rich-text-content p {
  color: var(--foreground);
  font-size: 1rem;
  line-height: 1.625;
  margin-block: 0 0.4em;
}

.rich-text-content p:last-child {
  margin-block-end: 0;
}

.rich-text-content a {
  color: var(--gold);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.rich-text-content :where(ul, ol) {
  margin-block: 0.4em;
  padding-inline-start: 1.5em;
}

.rich-text-content ul {
  list-style: disc;
}

.rich-text-content ol {
  list-style: decimal;
}

.rich-text-content li {
  margin-block-end: 0.2em;
}

/* Tables are persisted as semantic elements only: presentation comes entirely from this
   shared stylesheet so editor and viewer output stay identical in every width mode. */
.rich-text-content table {
  --rich-text-table-border: color-mix(in srgb, var(--border) 80%, var(--muted-foreground) 20%);
  border: 1px solid var(--rich-text-table-border) !important;
  border-collapse: collapse;
  border-spacing: 0;
  color: var(--foreground);
  inline-size: 100%;
  margin-block: 0.75em;
  max-inline-size: 100%;
  table-layout: fixed;
}

/* TinyMCE property dialogs may author width styles. Reading modes own the effective
   width so those styles can never escape the same measure used by every other block. */
[data-doc-width='page'] .rich-text-content table,
[data-doc-width='pages'] .rich-text-content table {
  inline-size: min(100%, var(--rich-text-measure)) !important;
  margin-inline: auto !important;
  max-inline-size: var(--rich-text-measure) !important;
}

[data-doc-width='full'] .rich-text-content table {
  inline-size: 100% !important;
  max-inline-size: none !important;
}

:root .rich-text-content :where(th, td) {
  border: 1px solid var(--rich-text-table-border) !important;
  color: var(--foreground);
  min-inline-size: 0;
  overflow-wrap: anywhere;
  padding: 0.5rem 0.625rem;
  text-align: start;
  vertical-align: top;
  word-break: normal;
}

/* TinyMCE-only table selection cues; these never enter serialized document HTML. */
.mce-content-body table[data-mce-selected] {
  outline: 2px solid color-mix(in srgb, var(--primary) 65%, transparent) !important;
}

.mce-content-body :is(td, th)[data-mce-selected]::after {
  background-color: color-mix(in srgb, var(--primary) 16%, transparent) !important;
  border-color: color-mix(in srgb, var(--primary) 55%, transparent) !important;
  mix-blend-mode: normal !important;
}

.rich-text-content.mce-content-body div.mce-resizehandle {
  background-color: var(--primary);
  border-color: var(--background);
}

.rich-text-content th {
  background: color-mix(in srgb, var(--muted) 82%, var(--card));
  font-weight: 600;
}

.rich-text-content tbody > tr:nth-child(even) > td {
  background: color-mix(in srgb, var(--muted) 35%, transparent);
}

.rich-text-content caption {
  border: 0 !important;
  color: var(--muted-foreground);
  font-size: 0.875rem;
  font-weight: 600;
  overflow-wrap: anywhere;
  padding-block: 0.25rem 0.4rem;
  text-align: start;
}

/* Virtual sheets have less room for wide matrices; compact cells preserve useful columns. */
[data-doc-width='pages'] .rich-text-content :where(th, td) {
  padding: 0.4rem 0.5rem;
}

/* Match compact table geometry to a narrow host (viewer) or iframe viewport (editor). */
@container (max-width: 40rem) {
  .rich-text-content table {
    font-size: 0.875rem;
  }

  :root .rich-text-content :where(th, td) {
    padding: 0.35rem 0.4rem;
  }
}

@media (max-width: 40rem) {
  .rich-text-content table {
    font-size: 0.875rem;
  }

  :root .rich-text-content :where(th, td) {
    padding: 0.35rem 0.4rem;
  }
}

:root .rich-text-content blockquote {
  border-inline-start: 3px solid var(--gold);
  color: var(--muted-foreground);
  margin: 0.6em auto;
  padding: 0.2em 0 0.2em 1em;
}

:root .rich-text-content blockquote p {
  color: inherit;
}

.rich-text-content code {
  border-radius: 0.25rem;
  background: var(--muted);
  font-size: 0.875em;
  padding: 0.1em 0.35em;
}

.rich-text-content pre {
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  background: var(--muted);
  margin-block: 0.6em;
  overflow-wrap: normal;
  overflow-x: auto;
  padding: 0.75em 1em;
}

.rich-text-content pre code {
  background: transparent;
  font-size: 0.875em;
  padding: 0;
}

.rich-text-content img {
  border-radius: 0.5rem;
  block-size: auto;
  margin-block: 0.6em;
  max-inline-size: 100%;
}

/* Leave room for the image's line box and margins so media can fit in one paper band. */
[data-doc-width='pages'] .rich-text-content img {
  max-block-size: calc(var(--rich-text-page-content-height) - 3rem);
  object-fit: contain;
}
