/* report.css --------------------------------------------------------------
   Presentation layer for the standing test report, live in-page case:
   loaded via <link> alongside /assets/styles.css (whose custom
   properties this file reuses), used by tests/test-report.html now and
   by /upload/'s success state once step 4 wires the report in.

   The standalone downloadable report (docs/assets/report/template.js)
   cannot link this file, since it must carry no external assets, so it
   inlines an identical copy of these rules as a JS string instead. This
   project has no build step to share the two: keep them in sync by
   hand when either changes. */

/* One or several files' reports together. Each buildReportSection()
   output styles itself the same way regardless of how many files are
   on the page (see .report-heading-main/.report-heading-section
   below); what differs between one file and several is only this
   wrapper and, for several, the per-file heading and divider around
   each .report. */
.multi-report {
  max-width: 1080px;
  margin: 0 auto;
}

.report-file-section {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
}

.report-file-section:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

/* The pooled section (buildPooledReportSection() in template.js) sits
   above every file-specific .report-file-section, shown only when more
   than one file was analysed. It gets the same bottom divider a file
   section gets on top, so the boundary between "every file combined"
   and "one file's own detail" stays visible; the first file section's
   own top divider (.report-file-section above) then reads as the
   continuation of that same boundary, not a second one. */
.report-pooled-section {
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--color-border);
}

/* Date and clock time from the file, not its name: see
   describeFileHeading() in template.js. Sized like the page's own h2
   (.state-block headings), one level above .report-heading-main below,
   so the visual hierarchy across a multi-file report reads: which
   file, then that file's own overview, then that file's own
   subsections. */
.report-file-section-heading {
  font-family: var(--font-serif);
  font-weight: 600;
  line-height: 1.25;
  font-size: var(--fs-5);
  margin: 0 0 var(--space-1);
}

.report-file-section-subtitle {
  font-size: 13px;
  color: var(--color-accent);
  margin: 0 0 var(--space-2);
}

/* Names which files could not be read or analysed, without singling
   any one out as a mistake: descriptive, not a judgement, matching the
   rest of the report's tone. */
.report-failure-note {
  background: var(--color-accent-soft);
  border: 1px solid var(--color-border);
  border-radius: 3px;
  padding: var(--space-2) var(--space-3);
  margin: 0 0 var(--space-4);
  font-size: var(--fs-1);
}

.report-failure-note p {
  margin: 0 0 var(--space-1);
}

.report-failure-note ul {
  margin: 0;
  padding-left: 1.2em;
}

.report-failure-note li {
  margin-bottom: 4px;
}

.report-failure-note li:last-child {
  margin-bottom: 0;
}

.report {
  max-width: 1080px;
  margin: var(--space-4) auto 0;
}

/* /upload/'s own wrapper around the report (#report-container in
   docs/upload/index.html, nowhere else): breaks the report out of
   .page-main's 720px cap (docs/assets/styles.css) without touching
   that class, since four other pages share it and must stay at their
   current width. margin-left: 50% together with transform:
   translateX(-50%) recentres the box on the viewport itself rather
   than on .page-main's own, narrower centre; this works regardless of
   .page-main's width as long as .page-main stays centred symmetrically
   in the body, which it does (margin: 0 auto, equal padding on both
   sides). The width keeps the same side gutter as the rest of the
   page (2 * var(--space-3), matching .page-main's own left/right
   padding) all the way down to a narrow phone, capped at the same
   1080px .report/.multi-report themselves are capped at above, so
   this rule alone cannot cause the page to scroll sideways. Nothing
   else selects #report-container: the downloaded standalone document
   (STANDALONE_REPORT_CSS in template.js) and tests/test-report.html
   both lay the report out directly, with no such wrapper, so neither
   is affected by this rule. */
#report-container {
  width: calc(100vw - 2 * var(--space-3));
  max-width: 1080px;
  margin-left: 50%;
  transform: translateX(-50%);
}

/* Visual size lives on these two classes, never on the tag name
   itself: a single uploaded file's report uses h2 for "Översikt" and
   h3 for every subsection below, exactly as before multiple files were
   possible, while a file nested inside a multi-file report (see
   buildMultiReportSection() in template.js) uses h3 and h4 instead, so
   the outline still goes in order under that file's own h2, with no
   gap forward. Either way "Översikt" reads at the same size (this
   project's old h2 size) and every subsection at the same, smaller
   size (the old h3 size), because both are set by class, not tag. */
.report .report-heading-main { font-size: var(--fs-4); }
.report .report-heading-section { font-size: var(--fs-3); margin-top: var(--space-4); }

/* Every section heading reads the same size and weight, whether it is
   a plain sibling (the two measures sections below) or, as here,
   nested inside a <figcaption>/<caption> so it also serves as that
   figure's or table's accessible name. The nested case keeps its own
   margin-top at 0: the figure/table's own spacing (.report-figure,
   .report-table) already sets the gap above it, and relying on that
   instead of a second, collapsing margin from the heading itself
   keeps the gap's size in one place. */
.report-figure figcaption .report-heading-section,
.report-table caption .report-heading-section {
  margin-top: 0;
}

.report-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-1) var(--space-3);
  margin: var(--space-2) 0 var(--space-4);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: 3px;
  background: var(--color-accent-soft);
}

.report-meta dt {
  font-family: var(--font-sans);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-accent);
}

.report-meta dd {
  margin: 0;
}

.report-figure {
  margin: var(--space-4) 0;
}

.report-figure figcaption {
  margin-bottom: var(--space-1);
}

.report-figure-legend {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  margin: 0 0 var(--space-1);
  padding: 0;
  font-size: 14px;
  color: var(--color-text);
}

.report-figure-legend li {
  display: flex;
  align-items: center;
  gap: 6px;
}

.report-figure-legend-swatch {
  width: 10px;
  height: 10px;
  flex: 0 0 auto;
}

.report-figure-legend-swatch.is-dot { border-radius: 50%; }
.report-figure-legend-swatch.is-rest { background: #3B6EA5; }
.report-figure-legend-swatch.is-stand { background: #C1522B; }

/* Steady state figure legend swatches: plain colour blocks standing in
   for a line style or a shaded band, the same simplification the rest of
   this legend already makes (a swatch is always a flat colour, never an
   attempt to draw a miniature line or rectangle). */
.report-figure-legend-swatch.is-steady-smooth { background: #5A5A54; }
.report-figure-legend-swatch.is-steady-band { background: #5B8A3A; }
.report-figure-legend-swatch.is-steady-band.is-partial { background: #C9A227; }
.report-figure-legend-swatch.is-steady-exp { background: #2B2B28; }

/* The overview table's "Datum" column, and its card layout's title
   (buildPooledOverviewTable() in template.js): colour swatch and date
   side by side, the one remaining place that links a pooled figure's
   colour back to a file now that the timeseries figure carries no
   legend of its own. font-weight is reset here because in the table
   this sits in a <th> (a row header, for the same reason every other
   row label in this report is one): its date should not read as
   emphasised the way the table's actual column headings do. On the
   card title, .stats-card-title's own font-weight wins back over this
   reset, since there it is the card's heading, not a row header. */
.report-file-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: normal;
}

/* Fixed report figure size, min-width matching figures.js's FIG_W: on a
   narrow phone the figure never scales its own text below its designed
   size, the wrapper scrolls horizontally instead. Every value the chart
   shows is also in the ordinary table right below it, so nothing in the
   report depends on being able to read small SVG text on a phone. */
.report-figure-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--color-border);
  border-radius: 3px;
  background: #FFFFFF;
}

.report-figure-scroll:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
}

.report-chart {
  display: block;
  width: 100%;
  min-width: 480px;
  height: auto;
}

.report-chart .report-chart-grid {
  stroke: var(--color-border);
  stroke-width: 1;
}

.report-chart .report-chart-tick,
.report-chart .report-chart-axis-title,
.report-chart .report-chart-phase-label,
.report-chart .report-chart-third-label,
.report-chart .report-chart-n-label {
  font-family: var(--font-sans);
  fill: #5A5A54;
}

.report-chart .report-chart-tick { font-size: 12px; }
.report-chart .report-chart-axis-title { font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase; }
.report-chart .report-chart-phase-label { font-size: 13px; font-weight: 600; }
.report-chart .report-chart-third-label { font-size: 11px; }
.report-chart .report-chart-n-label { font-size: 10px; }

.report-chart .report-chart-marker-label {
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 600;
  fill: var(--color-text);
}

.report-chart .report-chart-marker-line {
  stroke: #333333;
  stroke-width: 2;
}

/* The boundaries between each phase's three thirds: thin, dashed, muted,
   drawn under the transition marker so that line stays the one the eye
   lands on first. Discreet on purpose, see figures.js. */
.report-chart .report-chart-third-line {
  stroke: #999999;
  stroke-width: 1;
  stroke-dasharray: 3 3;
  stroke-opacity: 0.6;
}

/* Phase colours copied by hand from docs/r/core-plots.R's
   PHASE_COLOURS; that file is the reference, never run in the browser,
   so this cannot read the values from it directly. The box outline,
   whisker and median greys, and the boxplot's stratification by third,
   have no R equivalent to copy: core-plots.R draws a two box violin
   plot, this report draws six plain boxes instead. */
.report-chart .report-chart-point.is-rest { fill: #3B6EA5; fill-opacity: 0.75; }
.report-chart .report-chart-point.is-stand { fill: #C1522B; fill-opacity: 0.75; }
.report-chart .report-chart-box.is-rest { fill: #3B6EA5; }
.report-chart .report-chart-box.is-stand { fill: #C1522B; }
.report-chart .report-chart-box { fill-opacity: 0.85; stroke: #404040; stroke-width: 1.5; }
.report-chart .report-chart-whisker { stroke: #404040; stroke-width: 1.5; }
.report-chart .report-chart-median { stroke: #404040; stroke-width: 2; }

/* Sampling interval histogram: two bars per slot, side by side, so
   their heights are easy to compare directly. */
.report-chart .report-chart-hist-bar.is-rest { fill: #3B6EA5; }
.report-chart .report-chart-hist-bar.is-stand { fill: #C1522B; }

/* Pooled timeseries figure: one line per file, coloured by the `stroke`
   attribute set per element in figures.js (up to ten distinct colours,
   not just the two phase colours above), this class only carries what
   every file's line shares. */
.report-chart .report-chart-pooled-line {
  fill: none;
  stroke-width: 1.5;
  stroke-opacity: 0.85;
}

/* Steady state, drawn onto the time series figure above: a shaded band
   per period, drawn before the points and lines above so it reads as
   background, not as covering them. is-confirmed is an actual steady
   state period; is-partial (standing only) met the window criteria but
   did not hold to the phase's own end, so it gets a visually distinct,
   more tentative shade rather than the same treatment as a confirmed one. */
.report-chart .report-chart-steady-band {
  stroke: none;
}
.report-chart .report-chart-steady-band.is-confirmed { fill: #5B8A3A; fill-opacity: 0.18; }
.report-chart .report-chart-steady-band.is-partial { fill: #C9A227; fill-opacity: 0.16; }

/* The smoothed series the detector itself runs on: bolder than the raw
   points, in the same phase colours, so it reads as "the signal", not a
   third, unrelated colour language on top of the report's existing one. */
.report-chart .report-chart-steady-smooth {
  fill: none;
  stroke-width: 2;
}
.report-chart .report-chart-steady-smooth.is-rest { stroke: #3B6EA5; }
.report-chart .report-chart-steady-smooth.is-stand { stroke: #C1522B; }

/* The fitted exponential curve: dashed so it is never mistaken for the
   smoothed series itself, dark and neutral since it is not tied to
   either phase colour (both phases can show one at once). */
.report-chart .report-chart-steady-exp {
  fill: none;
  stroke: #2B2B28;
  stroke-width: 1.5;
  stroke-dasharray: 6 3;
}

.report-table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.report-table-scroll:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
}

.report-table {
  width: 100%;
  min-width: 420px;
  border-collapse: collapse;
  margin: var(--space-2) 0 var(--space-3);
  font-size: var(--fs-1);
}

.report-table caption {
  text-align: left;
  margin-bottom: var(--space-1);
}

.report-table th,
.report-table td {
  text-align: left;
  padding: 6px var(--space-1);
  border-bottom: 1px solid var(--color-border);
}

.report-table tbody tr:last-child td {
  border-bottom: none;
}

/* Two representations of the same rows, toggled by viewport width, not
   the same <table> restyled: a several column table with a range in
   most cells does not fit a typical phone even at its narrowest, and
   scrolling it sideways would still mean reading one row at a time.
   Below 640px (matching the breakpoint the rest of the site already
   uses) the stacked cards show; at or above it, the ordinary table
   does, and .report-table-scroll stays as a width safety net on top of
   that. Print always gets the table, see print.css. */
.stats-block .stats-cards {
  display: block;
}

.stats-block .report-table-scroll {
  display: none;
}

@media (min-width: 640px) {
  .stats-block .stats-cards {
    display: none;
  }

  .stats-block .report-table-scroll {
    display: block;
  }
}

.stats-card {
  border: 1px solid var(--color-border);
  border-radius: 3px;
  padding: var(--space-2);
  margin-bottom: var(--space-2);
}

.stats-card:last-child {
  margin-bottom: 0;
}

.stats-card-title {
  font-weight: 600;
  margin: 0 0 var(--space-1);
}

.stats-card-metrics {
  margin: 0;
}

.stats-card-metrics > div {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-2);
  padding: 3px 0;
  border-bottom: 1px solid var(--color-border);
}

.stats-card-metrics > div:last-child {
  border-bottom: none;
}

.stats-card-metrics dt {
  margin: 0;
  font-size: 13px;
  color: var(--color-accent);
}

.stats-card-metrics dd {
  margin: 0;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
