.non-printable {
  display: none !important;
}

.print-mode-enabled .non-printable {
  display: none !important;
}

html,
body {
  font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serifsans-serif, sans-serif;
  background: #f6f8f9;
  padding: 0;
  margin: 0;
}

@page {
  @top-left {
    content: element(topLeftMarginBoxRunning);
  }

  @top-center {
    content: element(topCenterMarginBoxRunning);
  }

  @top-right {
    content: element(topRightMarginBoxRunning);
  }

  @bottom-left {
    content: element(bottomLeftMarginBoxRunning);
  }

  @bottom-center {
    content: element(bottomCenterMarginBoxRunning);
  }

  @bottom-right {
    content: element(bottomRightMarginBoxRunning);
  }
}

.topLeftMarginBox {
  position: running(topLeftMarginBoxRunning);
}

.topCenterMarginBox {
  position: running(topCenterMarginBoxRunning);
}

.topRightMarginBox {
  position: running(topRightMarginBoxRunning);
}

.bottomLeftMarginBox {
  position: running(bottomLeftMarginBoxRunning);
}

.bottomCenterMarginBox {
  position: running(bottomCenterMarginBoxRunning);
}

.bottomRightMarginBox {
  position: running(bottomRightMarginBoxRunning);
}

.no-break {
  break-inside: avoid;
}

.page-number-total:before {
  content: counter(pages);
}

.page-number-current:before {
  content: counter(page);
}

/*
 * Widens a full-width group from the page's content box out to the paper edge, so its
 * background color reaches the sheet edges instead of stopping at the text column.
 *
 * position/left/width rather than negative margins: the group keeps its original in-flow
 * box, which is what paged.js measures when looking for break tokens.
 *
 * These literal 1cm values are only the unpaged fallback — they apply to the hidden source
 * wrapper paged.js reads innerHTML from, and to any non-paged render of the same markup.
 * Inside a sheet the rule below overrides them with the page's real margins.
 *
 * Do not "simplify" this to var(--pagedjs-margin-left, 1cm) here: paged.js's base sheet
 * declares --pagedjs-margin-*: 1in on :root, so outside a .pagedjs_page the var resolves to
 * that rather than to the fallback, and the group would bleed 2.54cm instead of 1cm.
 */
.full-bleed {
  position: relative;
  left: -1cm;
  width: calc(100% + 2cm);
  padding: 0cm 1cm 0.5cm 1cm;
  box-sizing: border-box;
}

/*
 * .pagedjs_area is the center cell of the .pagedjs_pagebox grid, inset by the real @page
 * margins — which report-style.ts writes from the dashboard's configured pageLayout and
 * defaults to 20mm, not 10mm. The fixed 1cm shift above therefore only reaches the paper edge
 * on a 10mm-margin report; on a default one it stops 10mm short on each side, leaving a
 * page-colored strip down both edges and two matching strips at the bottom corners of the
 * bleed band below.
 *
 * The Polisher writes --pagedjs-margin-* onto .pagedjs_page itself (not :root) from our @page
 * rule, so inside a sheet these always describe this page's actual inset. left/right on the
 * band below resolve against this already-bled padding box, so it follows automatically.
 *
 * This also degrades correctly — a page margin of `0` reaches these calc()s as a unitless
 * zero, making them invalid at computed-value time, which lands on `left: auto` / `width:
 * auto`, i.e. exactly the un-bled box a zero margin should produce.
 *
 * @page *padding* is deliberately not compensated. It insets .pagedjs_area from the margin
 * box, but the Polisher emits an unset one as a unitless `0`, so adding it in would
 * invalidate the whole declaration on every report that leaves paddings alone. A report that
 * sets a page padding keeps a band of that width at each edge.
 */
.pagedjs_area .full-bleed {
  left: calc(-1 * var(--pagedjs-margin-left));
  width: calc(100% + var(--pagedjs-margin-left) + var(--pagedjs-margin-right));
  padding-left: var(--pagedjs-margin-left);
  padding-right: var(--pagedjs-margin-right);
}

/*
 * Extends a full-bleed group's background from its own bottom edge all the way to the
 * sheet edge, covering every gap below it: unused content-area height, the @page
 * padding-bottom, and the @page margin-bottom.
 *
 * Absolutely positioned on purpose: paged.js finds break tokens by measuring in-flow
 * node rects, so growing the group itself (padding-bottom + negative margin-bottom)
 * can make it "not fit" and push it onto the next page. Out-of-flow content cannot
 * affect fragmentation.
 *
 * The height is deliberately over-generous rather than computed. The distance from the
 * group's bottom edge to the sheet edge is not expressible in CSS — it depends on where
 * paged.js happened to break the page — but it can never exceed one page, so a full page
 * height always reaches the edge and .pagedjs_sheet clips the remainder. Deriving it from
 * padding-bottom + margin-bottom instead only covers the page margins, which collapses to
 * nothing on a report whose margins are 0.
 *
 * left/right resolve against the already-bled padding box, so the band automatically
 * matches the horizontal bleed width.
 *
 * z-index: -1 keeps the band below in-flow page content, so footer margin-box content
 * ($currentPage etc.) and any components further down the page paint on top of it. It relies
 * on .pagedjs_page being a stacking context — see the rule below. Note that paint order alone
 * is not legibility: on a .dark band the footer also needs recoloring, see the rule below.
 *
 * content needs !important. paged.js's base sheet resets
 *   .pagedjs_pages > .pagedjs_page > .pagedjs_sheet > .pagedjs_pagebox > .pagedjs_area
 *     > div [data-split-to]:not([data-footnote-call])::after { content: unset }
 * and its Splits handler stamps data-split-to on the fragment left behind on the page where
 * a break happened. A group is only break-inside: avoid per component, so any multi-component
 * group can fragment — and that fragment, the one whose bottom edge sits at the page break
 * and most needs the band, would silently lose it while the continuation page kept it.
 * Specificity cannot win: that selector is 7 class-level components and ties any chain we can
 * mirror, then wins the element-count tiebreak on its `div`. !important is also how paged.js
 * overrides this family itself (.pagedjs_clear-after::after { content: none !important }).
 */
.full-bleed.bleed-bottom::after {
  content: "" !important;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  height: var(--pagedjs-pagebox-height, 100%);
  background-color: inherit;
  z-index: -1;
}

/*
 * Keeps the footer readable once a dark band is painted behind it.
 *
 * .pagedjs_margin-bottom is an in-flow grid item at grid-row: footer, a sibling of
 * .pagedjs_area inside .pagedjs_pagebox, and the band above is deliberately unclipped, so it
 * always travels underneath the footer. z-index: -1 only guarantees paint order — the footer's
 * glyphs land on top of the band, but its content is author HTML with no color of its own
 * (DashboardReportWrapper's margin-box divs) and inherits the default black, and
 * injectDynamicStyles() adds border-top: 1px solid gray. On a .dark group that is black on
 * black: the page number and timestamp disappear.
 *
 * Only .dark needs this. .light paints a white band that the default dark text already reads
 * on, and .transparent leaves the page's own bgColor showing.
 *
 * Keyed on the whole page, not on the last group, because the band is a full page-height
 * rectangle extending downward — any dark bleed-bottom group on the page reaches the footer,
 * not just a trailing one. The one case this over-matches is a dark bleed group followed on the
 * same page by a light one, whose later band paints over the dark one.
 *
 * :has() is Chrome 105+; report generation and preview both run in current Chrome.
 */
.pagedjs_pagebox:has(.pagedjs_area .bleed-bottom.dark) .pagedjs_margin-bottom {
  color: white;
  border-top-color: rgba(255, 255, 255, 0.4);
}

/*
 * Both declarations exist for the bleed band above.
 *
 * isolation: makes each sheet its own stacking context. Without it the band's negative
 * z-index resolves against some ancestor further up, which puts it at step 2 of the paint
 * order while the opaque .pagedjs_page background (injected per report from
 * pageLayout.bgColor) paints at step 3 — covering the band completely.
 *
 * overflow: rounds the band off at the page's corners. Clipping to the sheet box is NOT the
 * reason — .pagedjs_sheet is .pagedjs_page's only child, is sized from the same
 * --pagedjs-width/height, and already carries overflow: hidden in paged.js's base sheet, so
 * the band could never reach the inter-page gutter or the following sheet on its own. What the
 * sheet cannot do is honor the border-radius: 5px that DashboardReportViewPaged's
 * injectDynamicStyles() puts on .pagedjs_page (alongside the opaque bgColor background). A
 * radius clips that element's own background but not a descendant's, so without a clip here
 * the band's square bottom corners poke past the rounded page corner.
 *
 * This cannot clip the horizontal bleed, at any page margin: `.pagedjs_area .full-bleed` derives
 * its offsets from the same --pagedjs-margin-* vars that inset .pagedjs_area, so the bled box
 * lands exactly on the sheet box rather than past it. The literal 1cm in the base `.full-bleed`
 * rule only governs markup outside .pagedjs_area — the hidden source wrapper — which is not a
 * descendant of .pagedjs_page at all.
 */
.pagedjs_page {
  isolation: isolate;
  overflow: hidden;
}

/*
 * Paint-only variant of the bleed above, for a group whose own box must not move: it
 * leaves the container exactly where it is and lays a band of its background color
 * across the full paper width behind it.
 *
 * Report grid groups need this. react-grid-layout measures their container and bakes
 * pixel widths into every item, and it does so in the pre-pagination DOM which has no
 * @page geometry — so that container carries a concrete inline width (PAGE_WIDTHS) and a
 * CSS-sized box like `.full-bleed` either loses to it or, if the inline width is removed,
 * lets the grid measure the whole app layout and render one item per row.
 *
 * Anchored by width, not by a right inset: the container's inline width is PAGE_WIDTHS,
 * which is not the page's content width, so insetting each side by its margin overshoots
 * the right paper edge. `left` + `width` instead put the band on the paper itself, and
 * keep one custom property per declaration so a unitless `0` margin can only invalidate
 * the offset it appears in.
 *
 * Not in the flow and behind its siblings by paint order (it precedes the positioned grid
 * items in the DOM), so it can neither affect paged.js fragmentation nor cover content.
 * It does have to escape the container's `overflow: hidden` — see GridLayout.scss.
 */
.full-bleed-background {
  position: relative;
}

.full-bleed-background::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(-1 * var(--pagedjs-margin-left, 1cm));
  width: var(--pagedjs-width, 210mm);
  background-color: inherit;
}

.report-grid-container.full-bleed-background {
  overflow: visible;
}

.dark {
  background-color: black;
}

.light {
  background-color: white;
}

.transparent {
  background-color: transparent;
}

@media screen {
  .pagedjs_pages {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
  }

  .pagedjs_page {
    border: 1px solid #d6d9dc;
    border-radius: 5px;
    margin: 1.5rem;
  }

  .grid-3 {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    column-gap: 1rem;
  }
}

@media print {
  #root {
    display: none;
  }

  #preview {
    display: block;
  }

  * {
    print-color-adjust: exact;
  }
}
