/* ============================================================
   reviews.css — Published reviews list (SF-2134)

   Its own file rather than another block on the end of staff.css: this is one
   self-contained page, three lanes were editing staff.css the week it was
   written, and a page that owns its stylesheet can be read in one screen.

   Doctrine: doctrine/design/ — 05 shape and border (no perimeter borders, the
   selection ring, the radius ladder), 06 spacing, 11 surface rules (staff
   portal: moderate-high density, working tool). Every colour is a token; no
   value in this file is a new colour, radius or spacing step.
   ============================================================ */

.rv-page {
    max-width: var(--max-width);
    margin: 0 auto;
    padding: 0 0 48px;

    /* Container queries, not media queries: this page sits inside the SPA's
       content column, and what it has to respond to is the width of THAT
       column, not the window. A future sidebar would narrow the page without
       moving a single breakpoint. */
    container-type: inline-size;
    container-name: rv;

    /* SF-2139 pass 1: the portal now defines --selection-ring in both theme
       blocks of staff.css, so the page-scoped binding that used to sit here
       is gone and nothing on the page changed — which is what its own note
       said would happen. */
}

/* ----- Header ------------------------------------------------ */
.rv-header {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px 16px;
    margin-bottom: 16px;
}
.rv-header .section-heading { margin-bottom: 0; }

.rv-scope {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    font-size: var(--thx-fs-small);
    color: var(--fg-dim);
}
.rv-scope-count { color: var(--fg); font-weight: var(--thx-fw-medium); }
.rv-scope-sep {
    width: 3px; height: 3px;
    border-radius: var(--thx-radius-circle);
    background: currentColor;
    opacity: 0.5;
}
/* The honest label. Said plainly, in ordinary ink, not dressed as a warning —
   it is a fact about the archive, not a fault. */
.rv-scope-honest { font-style: italic; cursor: help; }

/* ----- Filters ----------------------------------------------- */
.rv-filters {
    display: flex;
    flex-wrap: wrap;
    gap: var(--thx-space-2);
    margin-bottom: var(--thx-space-5);
}

/* Inputs carry NO perimeter border (doctrine 05, the 2026-07-03 ruling): they
   are told apart from the page by their own tone, and by the focus ring when
   you are in one. */
.rv-input {
    /* SF-2139 pass 4: 9 is not a rung of the doctrine 06 ladder; 8 and 12 are,
       and they are what .form-input and .btn already use. */
    padding: var(--thx-space-2) var(--thx-space-3);
    background: var(--bg-input);
    border: none;
    border-radius: var(--thx-radius-button);
    color: var(--fg);
    font-family: var(--font-body);
    font-size: var(--thx-fs-body);
    transition: box-shadow 0.15s, background 0.15s;
}
/* Doctrine 10: a control never loses its focus outline outright. The bare
   `outline: none` this rule carried removed it for the keyboard too; the ring
   below is what replaces it, and the outline only goes for a MOUSE focus,
   which is the one case it was ever meant for. Same correction pass 2 made to
   .nmmq-time. */
.rv-input:focus:not(:focus-visible) { outline: none; }
.rv-input:focus-visible { box-shadow: 0 0 0 2px var(--accent); }
.rv-input::placeholder { color: var(--fg-dim); }

.rv-search-wrap { position: relative; flex: 1 1 260px; min-width: 200px; }
/* 32 is the rung that clears the 12px-inset, 13px-wide search glyph. */
input.rv-search { width: 100%; padding-left: var(--thx-space-6); }
.rv-search-icon {
    position: absolute;
    left: 12px; top: 50%;
    transform: translateY(-50%);
    color: var(--fg-dim);
    font-size: 14px;
    pointer-events: none;
}
/* The native clear affordance on a search input; nothing else added. */
.rv-search::-webkit-search-cancel-button { cursor: pointer; }

.rv-select { flex: 0 1 auto; cursor: pointer; }

.rv-group-toggle {
    display: inline-flex;
    background: var(--bg-input);
    border-radius: var(--thx-radius-button);
    padding: var(--thx-space-1);
    gap: var(--thx-space-1);
}
.rv-toggle-btn {
    border: none;
    background: transparent;
    color: var(--fg-dim);
    font-family: var(--font-body);
    font-size: var(--thx-fs-small);
    /* 8/12 off the ladder, and the segment clears doctrine 10's 32px floor
       with it — 7/14 drew a 28px target. */
    padding: var(--thx-space-2) var(--thx-space-3);
    min-height: 32px;
    border-radius: var(--thx-radius-card-sm);
    cursor: pointer;
}
.rv-toggle-btn:hover { color: var(--fg); }
/* Active = its FILL, per doctrine 05: the fill says which one you are on. No
   ring — the ring is reserved for a selected row. */
.rv-toggle-btn.active { background: var(--bg-card); color: var(--fg-bright); font-weight: var(--thx-fw-medium); }

/* ----- Cards (counts, cross-check) --------------------------- */
.rv-card {
    background: var(--bg-card);
    border-radius: var(--thx-radius-modal);
    margin-bottom: var(--thx-space-5);
    overflow: hidden;
}
.rv-card-head {
    display: flex;
    align-items: center;
    gap: var(--thx-space-3);
    width: 100%;
    padding: var(--thx-space-4);
    background: transparent;
    border: none;
    color: var(--fg-heading);
    font-family: var(--font-body);
    font-size: var(--thx-fs-small);
    font-weight: var(--thx-fw-semibold);
    text-align: left;
    cursor: pointer;
}
.rv-card-head:hover { background: var(--bg-card-hover); }
.rv-card-title { flex: 1 1 auto; }
.rv-chev { font-size: 14px; color: var(--fg-dim); }
.rv-card-body { padding: 0 var(--thx-space-4) var(--thx-space-4); }

.rv-count-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    padding: var(--thx-space-1) var(--thx-space-2);
    border-radius: var(--thx-radius-pill);
    background: var(--bg-input);
    color: var(--fg-dim);
    font-size: var(--thx-fs-meta);
    font-weight: var(--thx-fw-medium);
}

/* ----- Counts table ------------------------------------------ */
/* A table inside a card has no rule lines between its rows (doctrine 05 /
   11): the header is told from the body by weight and tone, and the rows by
   the alternating ground below. */
.rv-table-scroll { overflow-x: auto; }
.rv-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--thx-fs-small);
}
.rv-table th, .rv-table td {
    border: none;
    padding: var(--thx-space-2) var(--thx-space-3);
    text-align: left;
    vertical-align: top;
}
/* Doctrine 03: a column header is a label, not a badge, so it does not shout.
   Tone and weight tell it from the body — which is what the rest of this
   table already relies on. SF-2139 pass 4. */
.rv-table thead th {
    color: var(--fg-dim);
    font-weight: var(--thx-fw-medium);
    font-size: var(--thx-fs-small);
    white-space: nowrap;
}
.rv-table tbody tr:nth-child(odd) { background: var(--bg-body); }
.rv-table tbody tr:first-child td:first-child,
.rv-table tbody tr:first-child th:first-child { border-top-left-radius: var(--thx-radius-tag); }
.rv-table tbody th {
    font-weight: var(--thx-fw-medium);
    color: var(--fg-bright);
    white-space: nowrap;
}
.rv-num { text-align: right; font-variant-numeric: tabular-nums; }
.rv-zero { color: var(--fg-dim); opacity: 0.45; }
.rv-total { font-weight: var(--thx-fw-semibold); color: var(--fg-bright); }
.rv-last { min-width: 220px; }
.rv-last-date { display: block; color: var(--fg); }
.rv-last-title {
    display: block;
    color: var(--fg-dim);
    max-width: 380px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ----- Groups + rows ----------------------------------------- */
.rv-result-line {
    font-size: var(--thx-fs-small);
    color: var(--fg-dim);
    margin-bottom: var(--thx-space-3);
}

.rv-group { margin-bottom: var(--thx-space-4); }
.rv-group-head {
    display: flex;
    align-items: center;
    gap: var(--thx-space-3);
    width: 100%;
    padding: var(--thx-space-3) var(--thx-space-4);
    background: transparent;
    border: none;
    color: var(--fg-heading);
    font-family: var(--font-body);
    font-size: var(--thx-fs-small);
    text-align: left;
    cursor: pointer;
    border-radius: var(--thx-radius-card-sm);
}
.rv-group-head:hover { background: var(--bg-card); }
.rv-group-name { font-weight: var(--thx-fw-semibold); }
.rv-group-last { margin-left: auto; color: var(--fg-dim); font-size: var(--thx-fs-small); }

.rv-rows { display: flex; flex-direction: column; gap: 4px; }

.rv-row {
    position: relative;                 /* the ring hangs off this */
    display: grid;
    grid-template-columns: 96px 1fr 150px auto;
    align-items: center;
    /* SF-2139 pass 1 — the doctrine 06 ladder; 10 and 14 are not rungs. */
    gap: var(--thx-space-4);
    padding: var(--thx-space-3) var(--thx-space-4);
    background: var(--bg-card);
    border-radius: var(--thx-radius-card);
    cursor: pointer;
}
.rv-row:hover { background: var(--bg-card-hover); }
.rv-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The ring is written ONCE, in staff.css — search "THE SELECTION RING"
   there. .rv-row is named in it. SF-2139 pass 1. */

/* Inside a group the writer's name is already on the group head. */
.rv-row--grouped { grid-template-columns: 96px 1fr auto; }
.rv-row--grouped .rv-writer { display: none; }

.rv-date {
    font-size: var(--thx-fs-small);
    color: var(--fg-dim);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.rv-main { min-width: 0; }
.rv-title {
    display: block;
    color: var(--fg-bright);
    font-size: var(--thx-fs-small);
    font-weight: var(--thx-fw-medium);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.rv-tags { display: flex; flex-wrap: wrap; gap: var(--thx-space-1); margin-top: var(--thx-space-1); }
.rv-tag {
    padding: var(--thx-space-1) var(--thx-space-2);
    border-radius: var(--thx-radius-pill);
    background: var(--bg-input);
    color: var(--fg-dim);
    font-size: 13px;
    white-space: nowrap;
}
.rv-row .rv-writer {
    font-size: var(--thx-fs-small);
    color: var(--fg);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.rv-actions { display: flex; align-items: center; gap: 12px; }
.rv-link, .rv-project {
    display: inline-flex;
    align-items: center;
    gap: var(--thx-space-1);
    font-size: var(--thx-fs-small);
    color: var(--accent);
    text-decoration: none;
    white-space: nowrap;
}
.rv-link:hover, .rv-project:hover { color: var(--accent-hover); text-decoration: underline; }

/* ----- Cross-check: quiet on purpose ------------------------- */
/* Not red, not a warning pill. One row today, and it is a housekeeping list an
   editor can clear in a minute — dressing it as an alarm would be the same
   fault as a status stripe (doctrine 05). */
.rv-cross-card { background: var(--bg-input); }
.rv-cross-note {
    margin: 0 0 12px;
    font-size: var(--thx-fs-small);
    color: var(--fg-dim);
    line-height: var(--thx-lh-body);
}
.rv-row--quiet { background: var(--bg-body); cursor: default; }
.rv-row--quiet:hover { background: var(--bg-body); }

/* ----- States ------------------------------------------------ */
.rv-loading, .rv-empty {
    padding: var(--thx-space-6) var(--thx-space-4);
    text-align: center;
    color: var(--fg-dim);
    font-size: var(--thx-fs-small);
    background: var(--bg-card);
    border-radius: var(--thx-radius-modal);
}

/* ----- Narrow container -------------------------------------- */
@container rv (max-width: 820px) {
    .rv-row {
        grid-template-columns: 1fr auto;
        grid-template-areas:
            "title  actions"
            "date   writer";
        gap: var(--thx-space-2) var(--thx-space-3);
    }
    .rv-main    { grid-area: title; }
    .rv-actions { grid-area: actions; align-self: start; }
    .rv-date    { grid-area: date; }
    .rv-row .rv-writer {
        grid-area: writer;
        justify-self: end;
    }
    .rv-title { white-space: normal; }
    .rv-last { min-width: 0; }
    .rv-last-title { max-width: 200px; }
}

@container rv (max-width: 520px) {
    .rv-filters { flex-direction: column; align-items: stretch; }
    /* In a column the flex basis is a HEIGHT, so the search wrapper's
       `flex: 1 1 260px` would make it 260px tall and strand its icon in the
       middle of the gap. Hand it back its content height. */
    .rv-search-wrap { flex: 0 0 auto; }
    .rv-select, .rv-group-toggle { width: 100%; }
    .rv-group-toggle { justify-content: stretch; }
    .rv-toggle-btn { flex: 1 1 0; }
}
