/* audit/style.css — page-specific styling. Header chrome and buttons
 * come from /app.css; only audit-table layout lives here. */

html {
  scroll-behavior: smooth;
}

main {
  max-width: 1200px;
  margin: 0 auto;
  padding: 16px 18px 64px;
}

main h2 {
  font-family: "Playfair Display", serif;
  font-size: 22px;
  font-weight: 600;
  margin: 0 0 12px;
}

.section-help {
  font-size: 13px;
  color: var(--text);
  opacity: 0.72;
  margin: 0 0 14px;
  line-height: 1.45;
}

.empty-state {
  text-align: center;
  padding: 3rem 1rem;
  color: var(--text);
  opacity: 0.72;
  font-size: 14px;
}

/* ── Sticky zone ──
 *
 * Wraps the filters card + results header. Stays at the top of the
 * viewport as audit rows scroll past. Opaque background so rows
 * scrolling underneath don't show through. On phones (≤700px) the
 * zone drops position:sticky entirely — see the @media block at the
 * bottom of this file.
 */
.audit-sticky-zone {
  position: sticky;
  /* Stick at the zone's natural render position so it appears frozen
     from the moment scrolling starts (no 16px "approach" travel).
     The 16px matches main's padding-top below; if you change that,
     change this too. The header-offset accounts for body padding
     pushing main down past the fixed page header. */
  top: calc(var(--header-offset) + 16px);
  z-index: 10;
  /* Opaque background — the page's hill graphics live behind the
     content; without this, scrolling rows would visually bleed
     through the supposedly-frozen region. */
  background: var(--bg, #fff);
  /* Subtle shadow so the boundary between frozen and scrolling
     regions is legible. The zone otherwise visually merges with
     the table card below it. */
  box-shadow: 0 4px 12px -8px rgba(0, 0, 0, 0.18);
}

/* `.card` is locally-defined per page across this codebase (hub.css,
 * compliance/style.css). app.css does NOT ship a global `.card` rule,
 * so without this block the audit page's filter and table cards
 * render with no padding / border / surface. Mirror the compliance
 * page's definition since that's the closest sibling — paginated
 * data UI on the same scenic background. */
.card {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 18px 20px;
}

/* ── Filters: <details>/summary wrapping ──
 *
 * The filter card body lives inside a <details> element so it can be
 * collapsed for a quick-glance view on phones (default-closed on
 * narrow viewports via JS). The <summary> contains the h2 title;
 * these rules make the disclosure widget look like the previous
 * static h2 + give it a visible affordance.
 */

.audit-filters-summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  /* h2 inside summary has its own margin; collapse it onto summary
     so the title sits where it did before the wrap. */
}

.audit-filters-summary::-webkit-details-marker {
  display: none;
}

.audit-filters-summary h2 {
  margin: 0;
}

/* Disclosure triangle, drawn with a CSS shape so it inherits color
   and rotates smoothly. Points right when closed, down when open. */
.audit-filters-summary::after {
  content: "";
  display: inline-block;
  width: 0;
  height: 0;
  border-left: 6px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  opacity: 0.5;
  transition: transform 120ms ease;
  margin-left: 2px;
}

.audit-filters-details[open] > .audit-filters-summary::after {
  transform: rotate(90deg);
}

/* ── Filters form ── */

.audit-filters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  align-items: end;
}

.audit-filters label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  font-weight: 500;
}

.audit-filters input,
.audit-filters select {
  padding: 6px 8px;
  font-size: 14px;
  border: 1px solid var(--border, #ccc);
  border-radius: 4px;
  background: var(--bg, #fff);
  color: var(--text);
}

.audit-filter-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  /* Push the action buttons to span the full row when the grid
     wraps — keeps them aligned with the filter labels above. */
  grid-column: 1 / -1;
  margin-top: 4px;
}

/* Force Since onto a new grid row so Since + Until share row 2,
   leaving the 5 text/dropdown filters on row 1. `grid-column: 1`
   pins Since to column 1, which forces a new row when row 1 is
   already filled. Until then takes column 2 of the same row. */
.audit-filter-row-break {
  grid-column: 1;
}

/* ── Results header (lives inside the sticky zone) ── */

.audit-results-header {
  margin-bottom: 0;
}

/* Top strip: "Results" title + row count, side-by-side. */
.audit-results-title {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 8px;
}

/* Header table inside the sticky zone — only renders the column-
   header row. Shares fixed column widths with the data table below
   (.audit-table) so headers line up over data cells. The table-layout
   declaration + matching colgroups in CSS are how alignment stays
   stable as content varies. */
.audit-headers-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  table-layout: fixed;
}

.audit-headers-table th {
  font-weight: 600;
  background: var(--surface-alt, #f6f6f6);
  padding: 8px 10px;
  text-align: left;
  border-bottom: 1px solid var(--border, #e5e5e5);
}

/* Shared column-width contract between the headers table (above,
   inside the sticky zone) and the data table (below, inside the
   scrolling card). Both tables use `table-layout: fixed`; these
   percentages are the only thing keeping their columns aligned.
 *
 * Why two tables: the headers live in the sticky filter card so they
 * stay frozen with it on desktop, while the data table scrolls
 * normally below. A single table with a sticky thead can't work here
 * because `.table-wrap` carries `overflow: hidden` from app.css,
 * which becomes a sticky containing block and pins thead to the
 * wrap's top instead of the viewport.
 *
 * If you need to retune a column's width, EDIT BOTH SELECTORS in the
 * pair below — they have to stay in sync or the headers will drift
 * out of alignment with the data cells. */
.audit-headers-table th:nth-child(1),
.audit-table td:nth-child(1) { width: 18%; }
.audit-headers-table th:nth-child(2),
.audit-table td:nth-child(2) { width: 12%; }
.audit-headers-table th:nth-child(3),
.audit-table td:nth-child(3) { width: 22%; }
.audit-headers-table th:nth-child(4),
.audit-table td:nth-child(4) { width: 48%; }

.audit-count {
  font-size: 13px;
  opacity: 0.65;
}

/* `card-header-only` is a card variant for elements that visually
 * belong to a card but only render the header strip. Used by the
 * "Results" header that lives inside the sticky zone while the
 * actual table card sits below the zone (.card-no-top). Together
 * they look like one card whose body scrolls. */
.card-header-only {
  background: var(--surface, #fff);
  border: 1px solid var(--border, #e5e5e5);
  border-bottom: none;
  border-radius: 8px 8px 0 0;
  padding: 14px 18px 10px;
  margin-top: 12px;
}

.card-header-only h2 {
  margin: 0;
}

/* `card-no-top` is the matching modifier for the table card. Drops
 * top padding/border so it visually continues the card-header-only
 * above it rather than rendering a separate card outline. */
.card-no-top {
  border-top-left-radius: 0;
  border-top-right-radius: 0;
  border-top: none;
  padding-top: 0;
}

/* ── Table ── */

.audit-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  /* table-layout: fixed lets the explicit column widths above
     (shared with .audit-headers-table) actually take effect.
     Without it, columns auto-size by content and won't align with
     the header table in the sticky zone. */
  table-layout: fixed;
}

.audit-table th,
.audit-table td {
  padding: 8px 10px;
  border-bottom: 1px solid var(--border, #e5e5e5);
  text-align: left;
  vertical-align: top;
}

/* Override app.css's `.table-wrap { overflow: hidden }` for the audit
   page. `.table-wrap` carries its own border + box-shadow + bg from
   app.css, which would double up on top of the .card styling on
   #results-section. Strip those so it's a plain positioning wrapper. */
#results-section .table-wrap {
  overflow: visible;
  border: none;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
}

.audit-when {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  opacity: 0.85;
}

.audit-action {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 12px;
  white-space: nowrap;
}

.audit-system {
  font-style: italic;
  opacity: 0.65;
}

.audit-empty,
.audit-empty-cell {
  opacity: 0.5;
  font-style: italic;
}

.audit-error {
  color: var(--danger, #b00020);
  font-weight: 500;
}

/* ── Click-to-expand rows ──
 *
 * The whole row is the affordance for opening the detail panel.
 * Cursor + hover signal interactivity. `tabindex="0"` (set in JS)
 * makes the row focusable; `:focus-visible` shows a subtle outline
 * so keyboard users can see where they are.
 */

.audit-row {
  cursor: pointer;
  transition: background-color 120ms ease;
}

.audit-row:hover {
  background: var(--surface-alt, #f6f6f6);
}

.audit-row:focus-visible {
  outline: 2px solid var(--accent, #4a90e2);
  outline-offset: -2px;
}

.audit-row-expanded,
.audit-row-expanded:hover {
  background: var(--surface-alt, #eef3f8);
}

/* ── Expanded detail panel ──
 *
 * Full-width row beneath the clicked audit row. Two-column grid:
 * a definition list of the typed columns on the left, the metadata
 * JSON pre-block on the right. Padding is intentionally generous
 * so the panel feels like a discrete forensic view, not a row
 * variant.
 */

.audit-detail-row > td {
  background: var(--surface, #fafafa);
  padding: 16px 18px;
  border-bottom: 2px solid var(--border, #e5e5e5);
}

.audit-detail-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 24px;
  align-items: start;
}

@media (max-width: 800px) {
  /* Single-column on narrow screens. Mobile-friendly enough to be
     readable without committing to a full mobile redesign. */
  .audit-detail-grid {
    grid-template-columns: 1fr;
  }
}

.audit-detail-fields {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 6px 14px;
  margin: 0;
  font-size: 13px;
}

.audit-detail-fields dt {
  font-weight: 600;
  opacity: 0.75;
  white-space: nowrap;
}

.audit-detail-fields dd {
  margin: 0;
  word-break: break-word;
  font-variant-numeric: tabular-nums;
}

.audit-detail-metadata h4 {
  margin: 0 0 6px;
  font-size: 13px;
  font-weight: 600;
  opacity: 0.75;
}

.audit-detail-metadata pre {
  margin: 0;
  padding: 10px 12px;
  background: var(--bg, #fff);
  border: 1px solid var(--border, #e5e5e5);
  border-radius: 4px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 12px;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 360px;
  overflow: auto;
}

/* Diff table for the horse-update `changes` shape. See audit.md
 * "PII vs privilege metadata convention". Three columns: field name,
 * before value, after value. Inherits the metadata block's surface
 * styling but lays out as a table instead of a JSON blob. */
.audit-changes-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  background: var(--bg, #fff);
  border: 1px solid var(--border, #e5e5e5);
  border-radius: 4px;
  overflow: hidden;
}

.audit-changes-table thead th {
  font-weight: 600;
  background: var(--surface-alt, #f6f6f6);
  text-align: left;
  padding: 6px 10px;
  border-bottom: 1px solid var(--border, #e5e5e5);
  font-size: 12px;
  opacity: 0.75;
}

/* Column-width contract: Field column collapses to its content
 * (width:1% + nowrap is the well-known shrink-to-content trick for
 * tables), Before and After split the remaining width evenly. Long
 * notes are the common case and benefit from every inch of horizontal
 * room. */
.audit-changes-table thead th:first-child,
.audit-changes-table tbody th {
  width: 1%;
  white-space: nowrap;
}

.audit-changes-table thead th:nth-child(2),
.audit-changes-table thead th:nth-child(3) {
  width: 50%;
}

.audit-changes-table tbody th {
  font-weight: 600;
  text-align: left;
  padding: 6px 10px;
  vertical-align: top;
  background: var(--surface-alt, #f6f6f6);
  border-right: 1px solid var(--border, #e5e5e5);
}

.audit-changes-table tbody td {
  padding: 6px 10px;
  vertical-align: top;
  word-break: break-word;
  font-variant-numeric: tabular-nums;
}

.audit-changes-table tbody tr + tr th,
.audit-changes-table tbody tr + tr td {
  border-top: 1px solid var(--border, #e5e5e5);
}

/* When the changes table is followed by an "extras" JSON block (a
 * metadata blob that includes both `changes` and additional keys),
 * add a little breathing room between them. */
.audit-changes-table + .audit-metadata-json {
  margin-top: 10px;
}

/* ── Pagination ── */

.audit-pagination {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: center;
  margin-top: 16px;
  font-size: 13px;
}

.audit-pagination button:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* ── Mobile layout (≤ 700px) ──
 *
 * Two problems disappear at this width:
 *
 * 1. The sticky filters block dominates a phone viewport, leaving
 *    no room to glance at results. We drop sticky on the zone and
 *    tighten the surrounding chrome (main padding, card padding).
 *    The <details> wrapping the filter form is also collapsed by
 *    default at this width via JS so first paint shows results.
 *
 * 2. The 4-column desktop table (When / Who / Action / Detail)
 *    wastes horizontal space on phones and overflows text between
 *    columns. We collapse columns 1–3 into a stacked "event" column
 *    and leave Detail as the second column:
 *
 *      WHEN     |
 *      WHO      |  DETAIL
 *      ACTION   |
 *
 *    The sticky column-header table is hidden — rows are
 *    self-labelling at this width.
 *
 * Block lives at the end of the file (after every other selector)
 * because several rules below override desktop selectors of equal
 * specificity (`.audit-detail-row > td`, `.audit-row > td`) — source
 * order is the tie-breaker, so the mobile rules must come last.
 *
 * Row-layout implementation: convert the entire table to block
 * layout. Mixing `display:grid` on one <tr> while the sibling detail
 * <tr> stays `display:table-row` triggers anonymous-table-wrapper
 * behavior that lays out inconsistently across browsers, so it's
 * safer to make the whole table/tbody/tr stack non-table. The data
 * row's 4 <td>s are placed via CSS grid; the expanded detail row's
 * single <td colspan="4"> becomes a full-width block (colspan is
 * ignored once display is no longer table-cell, which is fine — it
 * was a 4-of-4 span anyway).
 */
@media (max-width: 700px) {
  /* === Outer chrome: drop sticky, tighten padding === */
  main {
    padding: 12px 10px 48px;
  }

  .audit-sticky-zone {
    position: static;
    box-shadow: none;
  }

  .card {
    padding: 12px 14px;
  }

  .card-header-only {
    padding: 10px 14px 8px;
  }

  /* === Row layout: stack when/who/action vertically === */

  /* Hide the sticky column-header row. The data rows are
     self-labelling — when/who/action stack on the left, the entity
     label sits on the right. */
  .audit-headers-table {
    display: none;
  }

  /* Drop table layout for the outer table so child grid layout
     doesn't have to fight the table layout algorithm. Direct-child
     selectors (`>`) prevent these rules from cascading into the
     nested .audit-changes-table inside expanded detail rows — that
     diff table needs to keep its native table layout. */
  .audit-table,
  .audit-table > tbody,
  .audit-table > tbody > tr,
  .audit-table > tbody > tr > td {
    display: block;
    width: auto;
  }

  /* The detail row is toggled via the `hidden` attribute (see app.js
     renderRowPair). `[hidden]`'s UA `display:none` has lower
     specificity than the `display:block` rule above, so without this
     all detail rows render expanded by default. Restore hide-on-
     `[hidden]` with matching specificity. */
  .audit-table > tbody > tr[hidden] {
    display: none;
  }

  /* Override the desktop width contract — table-layout:fixed is no
     longer in effect, but the explicit nth-child width:%% rules
     above would still constrain the now-block cells. Reset. */
  .audit-table > tbody > tr > td:nth-child(1),
  .audit-table > tbody > tr > td:nth-child(2),
  .audit-table > tbody > tr > td:nth-child(3),
  .audit-table > tbody > tr > td:nth-child(4) {
    width: auto;
  }

  /* Data row: 2-column grid. Col 1 stacks when/who/action; col 2
     holds the entity label, vertically centered against the stack.
     gap on the row supplies all spacing between cells (their own
     padding is zeroed below).
   *
   * Selector is `.audit-table > tbody > tr.audit-row` (not just
   * `.audit-row`) to outrank the `.audit-table > tbody > tr {
   * display: block }` rule above — without the extra qualifiers,
   * specificity ties go to source order and the broad block rule
   * wins, leaving the tr non-grid and the children stacking in
   * source order (when/who/action/detail rather than the intended
   * stack-plus-sidebar layout). */
  .audit-table > tbody > tr.audit-row {
    display: grid;
    grid-template-columns: minmax(0, 42%) minmax(0, 1fr);
    gap: 2px 12px;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border, #e5e5e5);
  }

  .audit-row .audit-when {
    grid-column: 1;
    grid-row: 1;
  }
  .audit-row .audit-who {
    grid-column: 1;
    grid-row: 2;
  }
  .audit-row .audit-action {
    grid-column: 1;
    grid-row: 3;
    /* Allow long action strings to wrap rather than overflow into
       the detail column. */
    white-space: normal;
    word-break: break-word;
  }
  .audit-row .audit-detail {
    grid-column: 2;
    grid-row: 1 / span 3;
    align-self: center;
    word-break: break-word;
  }

  /* Zero the per-cell padding/border so the grid container owns
     spacing. */
  .audit-row > td {
    padding: 0;
    border: none;
  }

  /* Expanded detail row: full-width block beneath the data row.
     The inner two-column grid already collapses to one column at
     ≤800px (see .audit-detail-grid media query above), so nothing
     more to do there — just tighten the outer gutters. */
  .audit-detail-row {
    border-bottom: 2px solid var(--border, #e5e5e5);
  }
  .audit-detail-row > td {
    padding: 12px 12px;
    border-bottom: none;
  }
}
