/* ─────────────────────────────────────────────────────────────────────────
   RPT — Learning Reports landing page (#/reports)
   LearningReportsLandingPage.js's markup uses several `.rpt-*` classes whose
   actual rules live only in admin.css (.rpt-card-grid, .rpt-report-card,
   .rpt-card-badge-row, .rpt-card-title, .rpt-card-desc,
   .rpt-report-card--locked, .rpt-card-lock(-label), .rpt-view-btn,
   .rpt-upgrade-btn) — admin.css is never loaded by this tenant-portal SPA
   (confirmed via index.html's <link> list), so the report card grid
   rendered as unstyled, full-width, full-bleed stacked <div>s instead of a
   contained, padded card grid. This is the same class of gap GLPD-7 already
   found and fixed for GenericLpDashboardPage.js (see glpd-dashboard.css) —
   every rule below is scoped under `.rpt-landing-page`, the wrapper class
   this page's root element already carries, so the fix is self-contained
   and cannot collide with any other page's use of the same class names.
   Values are copied from admin.css's own rules (lines ~4352-4363), using
   the shared --adm-* custom properties already available here
   (tenant-shell.css defines both the dark default and the
   [data-theme="light"] override for every token referenced below).

   Two additional, narrower gaps found during the same audit (present
   platform-wide, not admin.css-only, but visible on this page):

   1. `.adm-filter-bar-group` (the label-over-control filter wrapper used by
      both the Cohort Retention and Stalled Joiners filter bars) has no CSS
      rule anywhere in this SPA's loaded stylesheets outside GLPD's own
      `.glpd-dashboard-page`-scoped copy — so on this page label and control
      rendered inline instead of stacked. Re-declared here scoped to
      `.rpt-landing-page`, including the exact same
      `.adm-filter-bar-group > .adm-input` ballooning-height neutralization
      GLPD-7 already documented (components.css's unscoped
      ".adm-filter-bar .adm-input { flex: 1 1 200px }" was written for the
      OLD flat, flex-ROW .adm-filter-bar layout; read against a flex-COLUMN
      .adm-filter-bar-group, flex-basis:200px is misread as a *height*
      basis). Confirmed this page's `<input class="adm-input">` elements
      (Cohort Retention's month filters) are nested exactly this way.

   2. `.adm-filter-bar .adm-filter-label` in components.css
      (~line 7651, unscoped, specificity 0-2-0) was written for an inline
      checkbox-label use case and overrides the intended small-caps
      "FROM"/"TO"-style label look (10px/700/uppercase/muted, defined
      unscoped in auditor.css) with a plain 13px/400/no-uppercase style —
      exactly the "section-label font size inconsistency" flagged for this
      page. Re-asserted here at higher specificity
      (`.rpt-landing-page .adm-filter-bar .adm-filter-label`, 0-3-0) so it
      wins regardless of stylesheet load order, rather than relying on
      GLPD's simpler equal-specificity/load-order tiebreak.

   2026-09-11 update: the identical `.adm-filter-bar-group` gap was found a
   third time on this page's own child page, LearningReportDetailPage.js
   (`.rpt-detail-page`) — fixed in frontend/assets/css/rpt-detail-page.css.
   Since fixed in three further instances too: AuditEngagementsPage.js
   (`.aem-page`, fixed in auditor.css), PoshDashboardPage.js
   (`.posh-page-wrap`, fixed in posh.css), and AdminCertificatesPage.js
   (`.acp-wrap`, fixed in learning-admin.css). All confirmed instances of
   this bug are now fixed.

   Architecture ref: requirement-manager (RPT-1A/1B/1C, MEAS-A2 trackers)
   ───────────────────────────────────────────────────────────────────────── */

/* ── Report card grid (admin.css-only, never loaded by this SPA) ─────────── */

.rpt-landing-page .rpt-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 20px;
    margin-block-start: 20px;
}

.rpt-landing-page .rpt-report-card {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.rpt-landing-page .rpt-card-badge-row {
    margin-block-end: 2px;
}

.rpt-landing-page .rpt-card-title {
    font-size: 17px;
    font-weight: 700;
    margin: 0;
    color: var(--adm-text-primary);
}

.rpt-landing-page .rpt-card-desc {
    font-size: 13px;
    color: var(--adm-text-secondary);
    margin: 0;
    flex: 1;
    line-height: 1.5;
}

.rpt-landing-page .rpt-report-card--locked {
    opacity: 0.65;
}

.rpt-landing-page .rpt-card-lock {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-block-start: auto;
    padding-block-start: 10px;
    flex-wrap: wrap;
}

.rpt-landing-page .rpt-card-lock-label {
    font-size: 12px;
    color: var(--adm-text-muted);
}

.rpt-landing-page .rpt-view-btn {
    margin-block-start: auto;
    align-self: flex-start;
}

.rpt-landing-page .rpt-upgrade-btn {
    font-size: 12px;
}

/* ── Filter bar group (missing everywhere outside GLPD's own scope) ──────── */

.rpt-landing-page .adm-filter-bar-group {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

/* Ballooning-height neutralization — see file header comment; identical
   fix to .glpd-dashboard-page's own carve-out in glpd-dashboard.css. */
.rpt-landing-page .adm-filter-bar-group > .adm-input {
    flex: none;
    width: 100%;
    box-sizing: border-box;
    min-width: 0;
}

/* Re-assert the intended small-caps filter-label look at higher specificity
   than components.css's unscoped ".adm-filter-bar .adm-filter-label" (which
   was written for an inline checkbox-label use case). */
.rpt-landing-page .adm-filter-bar .adm-filter-label {
    display: block;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--adm-text-muted);
}

/* MR-213: the Cohort Retention filter bar's <input type="month" class="adm-input">
   resolves to 43px effective height (1px short of the 44px touch-target
   minimum, Rule 1) — confirmed live at 375/414/768px. type="month" renders
   its native calendar-icon affordance with a slightly different intrinsic
   box height than type="date" (which already lands on exactly 44px via the
   shared, unscoped .adm-input rule) — pin it explicitly here rather than
   relying on font-driven intrinsic height. */
@media (max-width: 768px) {
    .rpt-landing-page .adm-filter-bar-group > .adm-input {
        min-height: 44px;
    }
}

/* ── Cohort Retention — dumbbell chart (2026-09-11 redesign) ─────────────────
   Replaces the old grouped-bar-chart markup (no gridlines, no visible value
   labels, colliding rotated x-axis labels, hardcoded rgba() empty-state
   colour that was invisible on the light theme). Painted by
   DumbbellChartRenderer (frontend/assets/js/components/charts/), which
   builds only structural DOM + geometry — every colour below comes from this
   stylesheet, sourced exclusively from the existing --adm-* tokens
   (tenant-shell.css) already used platform-wide. No new hex/rgba literals.

   Colour convention: single hue (--adm-purple), two shades —
     Day-90  (variant "a"): light tint  = color-mix(--adm-purple, --adm-bg-card)
     Day-180 (variant "b"): full saturation = --adm-purple
   Connector: mid-shade color-mix by default; swaps to the existing
   --adm-amber / --adm-red status tokens (already used by
   .adm-badge--warning / .adm-badge--deleted) when a cohort's day90→day180
   drop exceeds the 10pp materiality threshold — this reuses the platform's
   RAG status colours, it does not introduce a new categorical hue. The RAG
   tint is paired with an always-visible, non-colour-coded "-Npp" delta label
   (.rpt-db-delta) as a redundant cue: a manual contrast check against this
   page's card background (#FFFFFF, light theme) puts --adm-amber at ~2.15:1
   — below the 3:1 WCAG 1.4.11 non-text threshold for a thin connector line —
   so colour alone cannot be the only way this signal is conveyed.
   ───────────────────────────────────────────────────────────────────────── */

.rpt-landing-page .rpt-db-chart {
    position: relative;
    display: grid;
    grid-template-columns: minmax(150px, 220px) 1fr;
    column-gap: 14px;
    row-gap: 2px;
    align-items: center;
    padding-block: 6px 10px;
}

/* Shared gridline overlay — see DumbbellChartRenderer's render() comment for
   why this is drawn once (grid-row spanning) instead of once per row.
   MUST be position:absolute, not relative/static: its explicit grid-column/
   grid-row (set inline by the renderer) still define its containing block,
   so it paints in exactly the same place, but absolute positioning removes
   it from CSS Grid's auto-placement algorithm entirely. Left in-flow, this
   element's row-span (1 / span rows+1) reserves column 2 for every row
   before the axis ticks and per-cohort label/track cells are auto-placed,
   so the browser pushes ALL of them into column 1 only, one per row —
   collapsing the intended two-column (label | plot) layout into a single
   stacked column where axis ticks, labels, dots and value text overlap. */
.rpt-landing-page .rpt-db-gridlines {
    position: absolute;
    inset: 0;
    pointer-events: none;
}
.rpt-landing-page .rpt-db-gridline {
    position: absolute;
    inset-block: 0;
    inline-size: 1px;
    background: var(--adm-border);
}

/* ── Axis header row ─────────────────────────────────────────────────────── */
.rpt-landing-page .rpt-db-axis-label-cell {
    min-block-size: 1px;
}
.rpt-landing-page .rpt-db-axis-track {
    position: relative;
    block-size: 18px;
}
.rpt-landing-page .rpt-db-tick {
    position: absolute;
    inset-block-start: 0;
    font-size: 10px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--adm-text-muted);
    transform: translateX(-50%);
    white-space: nowrap;
}
/* Edge ticks anchor to their own edge instead of centring, so they never
   clip outside the chart's bounding box. Interior ticks' plain -50% centring
   above needs NO dir="rtl" override — centring a box on a point is direction-
   symmetric (shifting back by half its own width lands the centre on the
   anchor regardless of reading direction). The edge ticks ARE direction-
   dependent, because "grow inward, away from the edge" flips meaning
   between LTR and RTL: tick--start already grows inward for free (an
   RTL-direction box's own layout naturally extends from its start edge
   toward its end edge, i.e. away from the anchored edge, with no transform
   needed) — only tick--end needs an explicit RTL override, since -100%
   (a fixed physical-left shift) would push it further off the container's
   edge instead of pulling it back in once `inset-inline-start:100%` starts
   resolving against the container's mirrored axis. */
.rpt-landing-page .rpt-db-tick--start { transform: none; }
.rpt-landing-page .rpt-db-tick--end   { transform: translateX(-100%); }
[dir="rtl"] .rpt-landing-page .rpt-db-tick--end { transform: translateX(100%); }

/* ── Row label column ─────────────────────────────────────────────────────── */
.rpt-landing-page .rpt-db-row-label {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    min-block-size: 34px;
    padding-block: 4px;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
    color: var(--adm-text-secondary);
}
.rpt-landing-page .rpt-db-row-label.rpt-db-row--emphasis {
    min-block-size: 42px;
    font-weight: 700;
    color: var(--adm-text-primary);
    background: var(--adm-bg-elevated);
    border-radius: var(--adm-radius-sm, 6px);
    padding-inline-start: 8px;
    margin-inline-start: -8px;
}
.rpt-landing-page .rpt-db-suppressed-chip {
    font-size: 10px;
    padding-block: 1px;
    padding-inline: 6px;
}

/* ── Plot track column ────────────────────────────────────────────────────── */
.rpt-landing-page .rpt-db-track {
    position: relative;
    min-block-size: 34px;
    border-radius: var(--adm-radius-sm, 6px);
}
.rpt-landing-page .rpt-db-track.rpt-db-row--emphasis {
    min-block-size: 42px;
    background: var(--adm-bg-elevated);
    --db-dot-d: 13px;
}

/* ── Dots ─────────────────────────────────────────────────────────────────── */
.rpt-landing-page .rpt-db-dot {
    position: absolute;
    inset-block-start: 50%;
    inline-size: var(--db-dot-d, 10px);
    block-size: var(--db-dot-d, 10px);
    margin-inline-start: calc(var(--db-dot-d, 10px) / -2);
    transform: translateY(-50%);
    border-radius: 50%;
    box-sizing: border-box;
}
.rpt-landing-page .rpt-db-dot--origin {
    margin-inline-start: 0; /* flush to the axis start edge, not centred */
}
/* Day-90 (variant a) — light tint fill, full-saturation edge for definition. */
.rpt-landing-page .rpt-db-dot--a.rpt-db-dot--value {
    background: color-mix(in srgb, var(--adm-purple) 42%, var(--adm-bg-card));
    border: 1.5px solid var(--adm-purple);
}
/* Day-180 (variant b) — full saturation fill. */
.rpt-landing-page .rpt-db-dot--b.rpt-db-dot--value {
    background: var(--adm-purple);
    border: 1.5px solid var(--adm-purple);
}
/* Pending (not yet reached this day window) — hollow ring, same hue,
   regardless of which of the two points it is. */
.rpt-landing-page .rpt-db-dot--hollow {
    background: transparent;
    border: 1.5px solid var(--adm-purple);
}
.rpt-landing-page .rpt-db-track.rpt-db-row--emphasis .rpt-db-dot {
    border-width: 2px;
}

/* ── Inline value labels — always visible, never hover-only ─────────────── */
.rpt-landing-page .rpt-db-value {
    position: absolute;
    inset-block-start: 50%;
    transform: translateY(-50%);
    display: flex;
    align-items: baseline;
    gap: 3px;
    font-size: 11px;
    font-variant-numeric: tabular-nums;
    color: var(--adm-text-primary);
    white-space: nowrap;
    pointer-events: none;
}
.rpt-landing-page .rpt-db-value--after {
    margin-inline-start: calc(var(--db-dot-d, 10px) / 2 + 6px);
}
.rpt-landing-page .rpt-db-value--before {
    margin-inline-end: calc(var(--db-dot-d, 10px) / 2 + 6px);
}
.rpt-landing-page .rpt-db-value-exemplar {
    font-size: 10px;
    font-weight: 700;
    color: var(--adm-text-muted);
}
.rpt-landing-page .rpt-db-track.rpt-db-row--emphasis .rpt-db-value {
    font-size: 12px;
    font-weight: 700;
}

/* ── Connector line ───────────────────────────────────────────────────────── */
.rpt-landing-page .rpt-db-connector {
    position: absolute;
    inset-block-start: 50%;
    block-size: 2px;
    transform: translateY(-50%);
    border-radius: 2px;
}
.rpt-landing-page .rpt-db-connector--neutral {
    background: color-mix(in srgb, var(--adm-purple) 75%, var(--adm-bg-card));
}
.rpt-landing-page .rpt-db-connector--warning { background: var(--adm-amber); }
.rpt-landing-page .rpt-db-connector--danger  { background: var(--adm-red); }
.rpt-landing-page .rpt-db-track.rpt-db-row--emphasis .rpt-db-connector {
    block-size: 3px;
}
/* Centred on the connector's midpoint and lifted clear of the dot row so it
   never collides with either endpoint's own always-visible value label
   (both value labels start immediately after/before their own dot — the
   midpoint is the one point in the row guaranteed clear of both, given the
   10pp materiality floor keeps `from`/`to` meaningfully apart). */
.rpt-landing-page .rpt-db-delta {
    position: absolute;
    inset-block-start: 50%;
    /* Shift up by the label's own full height plus a small gap — keeps it
       inside this row's own block box (min-block-size 34px/42px) instead of
       an imprecise fixed percentage that could drift into the row above. */
    transform: translate(-50%, calc(-100% - 3px));
    font-size: 10px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--adm-text-secondary);
    white-space: nowrap;
    pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
    .rpt-landing-page .rpt-db-dot,
    .rpt-landing-page .rpt-db-connector {
        transition: none;
    }
}

@media (max-width: 640px) {
    .rpt-landing-page .rpt-db-chart {
        grid-template-columns: minmax(96px, 130px) 1fr;
        column-gap: 8px;
    }
    .rpt-landing-page .rpt-db-value-exemplar {
        display: none; /* position + colour convention still carries the
                           Day-90/Day-180 meaning; aria-label keeps it for AT */
    }
    .rpt-landing-page .rpt-db-value {
        font-size: 10px;
    }
}

/* ─────────────────────────────────────────────────────────────────────────
   Stalled Joiners pagination (#rpt-stalled-pagination, _renderStalledPagination
   in LearningReportsLandingPage.js) — restyled to match the platform-canonical
   "Team" pagination look, per explicit request. Deliberately does NOT
   re-declare `.rpt-pager` / `.rpt-pager-info` / `.rpt-pager-btn` — those base
   rules already live in rpt-detail-page.css and are always co-loaded with
   this stylesheet (both are unconditional <link>s in index.html, confirmed),
   so re-declaring them here would just be duplicate CSS with no functional
   benefit and a future drift risk. Only this page's own spacing tweak lives
   here, scoped to `.rpt-stalled-pager` (the extra class on the
   #rpt-stalled-pagination div) so it cannot affect the report-detail pages'
   own `.rpt-pager` usage. The "Per page" control for this table is a
   separate, pre-existing filter-bar select (#rpt-stalled-pagesize,
   `.adm-select-sm`) — not part of this pager strip. */
.rpt-stalled-pager {
    margin-block-start: 12px;
}
