/* Rules of engagement — scoped under .page-roe.
   Colour tokens (--surface, --line, --good/--warn/--bad…) inherit from .shell on the layout, so both
   themes come for free; nothing here hard-codes a colour.

   Three tabs, in the signed document's own order: the response matrix, the asset register, and the
   escalation ladder. The first is deliberately the same matrix as the document — one row per response
   action, one column per answer, and the answer that applies is the marked cell — which is the whole
   reason the grid rules below are worth their length: a reader with the PDF open should recognise it.

   Every track is proportional with a zero floor (§26): .content .panel is overflow: hidden, so a
   pixel minimum on five columns would push the last one past the edge rather than scroll it. Below
   900px the row folds instead, and the cells take their own labels, because a five-column matrix is
   unreadable on a narrow screen and the column headings would be off-screen anyway. */

.page-roe { display: flex; flex-direction: column; gap: 34px; }

/* ── Empty / loading states (same shapes as the other page kits) ── */
.page-roe .empty { padding: 40px 24px; text-align: center; color: var(--muted); }
.page-roe .empty-title { font-size: 14.5px; font-weight: 600; color: var(--text); margin: 0 0 6px; }
.page-roe .empty-detail { font-size: 13px; color: var(--faint); margin: 0; }

/* Skeleton shimmer for the <Skeleton> component. A scoped port of the admin-kit rules, which are
   scoped to .admin-kit — a wrapper this page is not inside. The @keyframes it animates is global. */
.page-roe .shimmer {
    position: relative;
    overflow: hidden;
    background: var(--surface-2);
    border-radius: 0;
}
.page-roe .shimmer::after {
    content: "";
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgba(120, 160, 220, .13), transparent);
    animation: shimmer-slide 1.3s ease-in-out infinite;
}
.page-roe .sk-line { display: block; height: 13px; }
.page-roe .sk-rows { display: flex; flex-direction: column; gap: 14px; padding: 20px 16px; }

@media (prefers-reduced-motion: reduce) {
    .page-roe .shimmer::after { animation: none; }
}

/* ── Standing of the agreement, beside the heading ─────────────────
   It was a full-width band of its own with the four totals in it, and on a matrix nobody has answered
   yet that is a lot of chrome around one date, so it lives in .head-actions now. State beside a
   heading, which is what may sit there (§14); the band counts below carry the totals. */

.page-roe .roe-agreed { display: inline-flex; align-items: baseline; gap: 7px; white-space: nowrap; }

.page-roe .roe-agreed-label {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--faint);
}

.page-roe .roe-agreed .is-unset { color: var(--faint); }

/* "An answer has moved since this was signed" — the one thing a reader of an agreed document needs
   told without asking, so it is a flag rather than a line of prose further down. */
.page-roe .roe-flag {
    padding: 2px 8px;
    border: 1px solid var(--warn);
    color: var(--warn);
    font-size: 11.5px;
    font-weight: 600;
    white-space: nowrap;
}

.page-roe .roe-band-count { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* ── The matrix ────────────────────────────────────────────────────
   One grid template, declared once, shared by the header row and every action row so the columns line
   up without a table. */

.page-roe .roe-grid { --roe-cols: minmax(0, 2.6fr) repeat(4, minmax(0, 1fr)); }

.page-roe .roe-row {
    display: grid;
    grid-template-columns: var(--roe-cols);
    align-items: stretch;
    border-top: 1px solid var(--line-soft);
}

.page-roe .roe-row:first-child { border-top: 0; }

.page-roe .roe-row.is-pending { opacity: .55; }

.page-roe .roe-head {
    background: var(--surface-2);
    border-bottom: 1px solid var(--line);
}

.page-roe .roe-head .roe-name {
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--muted);
    justify-content: center;
}

.page-roe .roe-head-cell {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    padding: 10px 12px;
    min-width: 0;
    text-align: center;
    border-left: 1px solid var(--line-soft);
}

.page-roe .roe-head-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.page-roe .roe-head-cell.is-never .roe-head-label { color: var(--bad); }
.page-roe .roe-head-cell.is-approval .roe-head-label { color: var(--warn); }
.page-roe .roe-head-cell.is-preapproved .roe-head-label { color: var(--good); }
/* Not applicable is the one answer that is not a decision about our authority, so its heading stays
   quiet rather than taking a fourth colour. */
.page-roe .roe-head-cell.is-na .roe-head-label { color: var(--muted); }

/* Sub-heading inside a band (Live Response today). A sibling of the rows rather than a cell in one:
   each row is its own grid, so this sits between two of them and labels the ones under it. */
.page-roe .roe-subhead {
    padding: 9px 14px 7px;
    border-top: 1px solid var(--line-soft);
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--accent);
    background: var(--line-soft);
}

/* ── The action, and what it does ── */

.page-roe .roe-name {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    /* min-width: 0 on the grid item, then clamp inside it: without both, the longest action name sets
       the column's width and the four answer columns are squeezed off the panel (§26). */
    min-width: 0;
    padding: 11px 14px;
}

/* The name and the unanswered mark share one line, so a row is the same height whether it is answered
   or not. Stacked, the mark added a line to every unanswered row and answering one shrank the row and
   every cell in it, which read as the boxes resizing under the press. min-width: 0 so the name is what
   gives way when the column is tight, never the mark (§26). */
.page-roe .roe-action-line { display: flex; align-items: center; gap: 8px; min-width: 0; }

.page-roe .roe-action {
    min-width: 0;
    font-size: 13.5px;
    font-weight: 600;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Two lines, then clipped, with the whole sentence on the title: a description is a sentence, so it
   wraps rather than sitting on one clamped line (§30). */
.page-roe .roe-desc {
    font-size: 12px;
    line-height: 1.4;
    color: var(--muted);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* An action nobody has answered. Said out loud rather than left as four empty cells, because "we have
   not agreed this" and "this does not apply" must not read the same (§30). It sits on the name's line
   and its line box is kept under the name's, so its arrival and departure cost the row no height. */
.page-roe .roe-unset {
    flex: none;
    padding: 0 7px;
    border: 1px dashed var(--line);
    font-size: 11px;
    line-height: 16px;
    color: var(--faint);
    white-space: nowrap;
}

/* ── The answer cells ── */

.page-roe .roe-cell {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-width: 0;
    padding: 11px 10px;
    border: 0;
    border-left: 1px solid var(--line-soft);
    background: none;
    color: var(--muted);
    font: inherit;
    text-align: center;
    transition: background .15s ease;
}

/* Only a writer's cells are controls. A read-only role gets the same grid rendered as spans, so there
   is nothing to press rather than a grid of dead buttons (§32). */
.page-roe button.roe-cell { cursor: pointer; }
.page-roe button.roe-cell:hover:not(:disabled) { background: var(--line-soft); }
.page-roe button.roe-cell:disabled { cursor: default; }

/* The mark. An empty square where a press would land, filled in the column's own colour when that is
   the agreed answer: the interactive form of the X in the spreadsheet's column. */
.page-roe .roe-cell::before {
    content: "";
    flex: none;
    width: 13px;
    height: 13px;
    border: 1px solid var(--line);
    background: none;
}

.page-roe .roe-cell.is-chosen { background: var(--surface-2); }

.page-roe .roe-cell.is-chosen::before {
    background: var(--roe-tone, var(--accent));
    border-color: var(--roe-tone, var(--accent));
}

.page-roe .roe-cell.is-never { --roe-tone: var(--bad); }
.page-roe .roe-cell.is-approval { --roe-tone: var(--warn); }
.page-roe .roe-cell.is-preapproved { --roe-tone: var(--good); }
.page-roe .roe-cell.is-na { --roe-tone: var(--faint); }

.page-roe .roe-cell.is-chosen .roe-cell-label { color: var(--text); }

/* Hidden while the column headings are on screen — the mark's position is what names it there. The
   folded layout below turns them on, where each cell has to name itself. */
.page-roe .roe-cell-label {
    display: none;
    font-size: 12px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── Folded layout ─────────────────────────────────────────────────
   A five-column matrix does not survive a narrow screen, and its headings would be scrolled off it.
   The row becomes the action over two columns of self-labelling cells. */

@media (max-width: 900px) {
    .page-roe .roe-head { display: none; }

    .page-roe .roe-row {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        padding-bottom: 8px;
    }

    .page-roe .roe-name { grid-column: 1 / -1; padding-bottom: 4px; }

    .page-roe .roe-cell {
        justify-content: flex-start;
        border-left: 0;
        border: 1px solid var(--line-soft);
        margin: 3px 0 0 14px;
        padding: 7px 10px;
    }

    /* The right-hand cell of each pair keeps the same gutter as the left one. */
    .page-roe .roe-cell:nth-child(odd) { margin-right: 14px; }

    .page-roe .roe-cell-label { display: block; }
}

/* ════════════════════════════════════════════════════════════════
   Tabs — the three parts of the document. The same control as the
   Help and Vulnerabilities pages, in this page's kit.
   ════════════════════════════════════════════════════════════════ */

.page-roe .roe-tabs {
    display: flex;
    gap: 2px;
    flex-wrap: wrap;
    border-bottom: 1px solid var(--line);
}

.page-roe .roe-tabs button {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 15px;
    border: none;
    border-bottom: 2px solid transparent;
    background: transparent;
    color: var(--muted);
    font: 600 13px var(--font-body);
    cursor: pointer;
    transition: color .15s ease, border-color .15s ease;
}

.page-roe .roe-tabs button:hover { color: var(--text); }
.page-roe .roe-tabs button.is-active { color: var(--text); border-bottom-color: var(--accent); }

/* How many staged changes are waiting on a tab the reader is not looking at. The Save bar counts the
   whole page, so without this its number could be about something off screen. */
.page-roe .roe-tab-dirty {
    min-width: 17px;
    padding: 0 5px;
    border: 1px solid var(--accent-line);
    background: var(--accent-soft);
    color: var(--accent-2);
    font-size: 11px;
    font-weight: 700;
    line-height: 15px;
    text-align: center;
}

/* A row the reader has changed but not saved. The edge is the only mark, because the cell itself
   already shows the new answer: this says "not written down yet", not "different from the others". */
.page-roe .roe-row.is-edited,
.page-roe .roe-arow.is-edited { box-shadow: inset 3px 0 0 var(--accent); }

/* ════════════════════════════════════════════════════════════════
   The Save bar. Both grids stage their edits, so this is the only
   thing that writes them, and it counts the whole page rather than
   the tab in front of the reader.
   ════════════════════════════════════════════════════════════════ */

.page-roe .roe-savebar {
    position: sticky;
    bottom: 0;
    z-index: 90;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 18px;
    flex-wrap: wrap;
    padding: 13px 18px;
    border: 1px solid var(--accent-line);
    background: var(--surface-2);
    box-shadow: 0 -10px 30px -18px rgba(0, 0, 0, .8);
}

.page-roe .roe-savebar-text { font-size: 13px; font-weight: 600; color: var(--text); }
.page-roe .roe-savebar-actions { display: flex; align-items: center; gap: 10px; }

/* ════════════════════════════════════════════════════════════════
   The asset register. Four tracks, all proportional with a zero
   floor (§26); the two the reader edits are selects rather than
   free text, because the point of recording a category is that an
   analyst can act on it.
   ════════════════════════════════════════════════════════════════ */

.page-roe .roe-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;
}

/* The Environment page's filter row, and the lift that keeps its open menu above the clipping
   panel (§26/§27). */
.page-roe .section.menus-open { position: relative; z-index: 50; }
.page-roe .inc-filterbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 12px 0 14px; }

.page-roe .roe-assets { --roe-acols: minmax(0, 2.2fr) minmax(0, 1.4fr) minmax(0, 1.2fr) minmax(0, 1.1fr); }

.page-roe .roe-arow {
    display: grid;
    grid-template-columns: var(--roe-acols);
    align-items: center;
    border-top: 1px solid var(--line-soft);
}

.page-roe .roe-arow:first-child { border-top: 0; }

.page-roe .roe-acell-head {
    padding: 10px 12px;
    min-width: 0;
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.page-roe .roe-acell { padding: 8px 12px; min-width: 0; }

.page-roe .roe-os {
    display: block;
    font-size: 12.5px;
    color: var(--muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* A device Defender no longer reports. Its classification is kept, so the row says why it is still
   here rather than disappearing (§30). */
.page-roe .roe-gone { color: var(--warn); }

.page-roe .roe-select {
    width: 100%;
    min-width: 0;
    padding: 6px 8px;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    color: var(--text);
    font: 500 12.5px var(--font-body);
    cursor: pointer;
}

.page-roe .roe-select:focus { outline: none; border-color: var(--accent-line); }

/* Criticality carries the colour ranking severity does everywhere else, in the select and in the
   read-only rendering of it, so the register can be scanned for the machines that matter. */
.page-roe .roe-select.is-critical,
.page-roe .roe-avalue.is-critical { color: var(--bad); font-weight: 600; }
.page-roe .roe-select.is-high,
.page-roe .roe-avalue.is-high { color: var(--warn); font-weight: 600; }

.page-roe .roe-avalue {
    display: block;
    min-width: 0;
    font-size: 12.5px;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.page-roe .roe-avalue.is-unset { color: var(--faint); }

/* ════════════════════════════════════════════════════════════════
   The escalation ladder. Numbered, because the order is the point:
   an unordered list of people to ring at 2am is not a path.
   ════════════════════════════════════════════════════════════════ */

.page-roe .roe-rung {
    display: grid;
    grid-template-columns: 34px minmax(0, 1.4fr) minmax(0, 1.6fr) auto;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    border-top: 1px solid var(--line-soft);
}

.page-roe .roe-rung:first-child { border-top: 0; }

.page-roe .roe-rung-no {
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--accent-line);
    color: var(--accent-2);
    font-family: var(--font-display);
    font-size: 12.5px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.page-roe .roe-rung-who { display: flex; flex-direction: column; gap: 1px; min-width: 0; }

.page-roe .roe-rung-name {
    font-size: 13.5px;
    font-weight: 600;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.page-roe .roe-rung-title {
    font-size: 12px;
    color: var(--muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.page-roe .roe-rung-reach { display: flex; flex-direction: column; gap: 1px; min-width: 0; }

/* The number leads: at 2am it is the one that gets used, and the address is the follow-up. */
.page-roe .roe-rung-link {
    font-size: 13px;
    color: var(--text);
    text-decoration: none;
    font-variant-numeric: tabular-nums;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.page-roe .roe-rung-link.is-quiet { font-size: 12px; color: var(--muted); }
.page-roe .roe-rung-link:hover { color: var(--accent-2); text-decoration: underline; }

.page-roe .roe-rung-actions { display: flex; align-items: center; gap: 4px; }

.page-roe .roe-icon {
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid transparent;
    background: transparent;
    color: var(--muted);
    cursor: pointer;
    transition: color .15s ease, border-color .15s ease;
}

.page-roe .roe-icon svg { width: 15px; height: 15px; }
.page-roe .roe-icon:hover:not(:disabled) { color: var(--text); border-color: var(--line); }
.page-roe .roe-icon.is-danger:hover:not(:disabled) { color: var(--bad); border-color: var(--bad); }
.page-roe .roe-icon:disabled { opacity: .35; cursor: default; }

.page-roe .roe-head-right { margin-left: auto; }

/* ════════════════════════════════════════════════════════════════
   Buttons and the dialog. Scoped ports: .btn-ghost is global on
   .content, but the primary and danger variants and the whole modal
   shell are scoped to .admin-kit, a wrapper this page is not inside
   — without these the dialog would sit in the DOM invisible, which
   is §24's bug exactly.
   ════════════════════════════════════════════════════════════════ */

.page-roe .btn-primary,
.page-roe .btn-danger {
    padding: 9px 16px;
    border: 1px solid var(--accent-line);
    border-radius: var(--radius-sm);
    background: var(--accent-soft);
    color: var(--accent-2);
    font: 600 13px var(--font-body);
    cursor: pointer;
    transition: border-color .18s ease, background .18s ease;
}

.page-roe .btn-danger { border-color: var(--bad); background: transparent; color: var(--bad); }
.page-roe .btn-primary:hover:not(:disabled) { background: var(--surface-2); border-color: var(--accent); }
.page-roe .btn-danger:hover:not(:disabled) { background: var(--surface-2); }
.page-roe .btn-primary:disabled,
.page-roe .btn-danger:disabled,
.page-roe .btn-ghost:disabled { opacity: .5; cursor: not-allowed; }

.page-roe .modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: rgba(7, 9, 10, .66);
    backdrop-filter: blur(3px);
    animation: modal-fade .18s ease both;
}

.page-roe .modal {
    display: block;
    position: relative;
    inset: auto;
    width: 100%;
    max-width: 480px;
    max-height: calc(100vh - 64px);
    overflow-y: auto;
    overflow-x: hidden;
    padding: 22px 24px 24px;
    border: 1px solid var(--line);
    background: var(--surface);
    box-shadow: 0 24px 60px rgba(0, 0, 0, .5);
    animation: modal-rise .22s cubic-bezier(.22, .9, .3, 1) both;
}

.page-roe .modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; margin-bottom: 18px; }
.page-roe .modal-title { margin: 0; font-family: var(--font-display); font-size: 18px; font-weight: 600; color: var(--text); }
.page-roe .modal-eyebrow { margin: 0 0 3px; font-size: 11.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--accent); }

.page-roe .modal-close {
    flex: none;
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--line);
    background: transparent;
    color: var(--muted);
    font-size: 15px;
    cursor: pointer;
    transition: border-color .15s, color .15s;
}

.page-roe .modal-close:hover { border-color: var(--bad); color: var(--bad); }

.page-roe .modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }

.page-roe .roe-modal-error {
    margin-top: 4px;
    padding: 9px 12px;
    border: 1px solid var(--bad);
    color: var(--bad);
    font-size: 12.5px;
}

.page-roe .roe-confirm { margin: 0; font-size: 13px; color: var(--muted); }

/* The change request just raised: named and linked until dismissed, where a toast was gone before it
   was read. The page's column gap already spaces it from the header and the tabs. */
.page-roe .roe-raised {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 14px 12px 16px;
    border: 1px solid var(--accent-line);
    border-radius: var(--radius);
    background: var(--surface-2);
}

.page-roe .roe-raised p {
    flex: 1;
    min-width: 0;
    margin: 0;
    font-size: 13px;
    line-height: 1.5;
    color: var(--text);
}

.page-roe .roe-raised p a { color: var(--accent-2); font-weight: 600; }

.page-roe .roe-raised .btn-ghost { flex: none; text-decoration: none; }

.page-roe .roe-raised-close {
    flex: none;
    border: 0;
    background: none;
    padding: 4px;
    color: var(--muted);
    cursor: pointer;
}

.page-roe .roe-raised-close:hover { color: var(--text); }

@media (max-width: 640px) {
    .page-roe .roe-raised { flex-wrap: wrap; }
    .page-roe .roe-raised p { flex-basis: 100%; }
}

/* The change request's detail box. .fld-input is the shared field style and is written for one-line
   inputs, so the textarea takes back the things a box needs: room to grow downward only, and the body
   font rather than the browser's monospace default. */
.page-roe .roe-textarea { resize: vertical; min-height: 96px; line-height: 1.5; font-family: var(--font-body); }

@media (max-width: 900px) {
    /* The register folds the way the matrix does: the device keeps the full width and its two answers
       sit under it, where the column headings are no longer on screen to name them. */
    .page-roe .roe-arow { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); padding-bottom: 8px; }
    .page-roe .roe-arow.roe-head { display: none; }
    .page-roe .roe-arow .roe-name { grid-column: 1 / -1; }
    .page-roe .roe-os { grid-column: 1 / -1; padding-top: 0; }

    .page-roe .roe-rung { grid-template-columns: 26px minmax(0, 1fr); row-gap: 6px; }
    .page-roe .roe-rung-reach { grid-column: 2; }
    .page-roe .roe-rung-actions { grid-column: 2; }
}
