/* Clerky - Custom Styles */

/* ===== Admin Multi-View: Board ===== */
.board-col {
    min-height: 300px;
}
.board-col-cards {
    background: #f9fafb;
}
.board-col-drag-over > .board-col-cards,
.board-col.board-col-drag-over .board-col-cards {
    background: #dff2c5;
    outline: 2px dashed #5a9326;
    outline-offset: -2px;
}
.board-card {
    transition: box-shadow 0.15s, opacity 0.15s;
    line-clamp: 2;
    -webkit-line-clamp: 2;
}
.board-card:hover {
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.board-card[draggable="true"]:active {
    box-shadow: 0 6px 20px rgba(0,0,0,0.15);
}
.line-clamp-2 {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
}

/* ===== Admin Multi-View: Table ===== */
#req-admin-table-view table tbody tr:last-child {
    border-bottom: none;
}


.nav-btn {
    color: #6b7280;
    font-size: 13px;
    display: flex;
    align-items: center;
}

.nav-btn:hover {
    background-color: #f3f4f6;
    color: #111827;
}

.nav-btn.active {
    background-color: #f1f5f9;
    color: #0f172a;
    font-weight: 600;
}

/* Active indicator dot — shown only on active nav items */
.nav-active-dot {
    display: none;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #3d6b1c;
    flex-shrink: 0;
    margin-left: 4px;
}
.nav-btn.active .nav-active-dot {
    display: none;
}

/* ── Settings left nav (#979) ───────────────────────────────── */
/* The entries reuse the sidebar's .nav-btn and its .nav-sub-group/.nav-sub-item tree;
 * only the two-column layout and the board rows are Settings' own. */
.settings-layout { display: grid; grid-template-columns: 14rem minmax(0, 1fr); gap: 1.5rem; align-items: start; }
/* The heading and the nav stick together (#1005): the heading tops the nav's column. */
.settings-side { position: sticky; top: 1rem; }
.settings-nav { display: flex; flex-direction: column; gap: 1px; }
/* The section's panel starts 36px from the top of the page: #main-content's 24px plus this. */
.settings-main { margin-top: 12px; }
.settings-nav-label { font-size: 10px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--gv-text-subtle); padding: 12px 10px 4px; }
.settings-nav-board { display: flex; align-items: center; border-radius: 0.5rem; transition: background-color 150ms; }
.settings-nav-board .nav-btn { flex: 1; min-width: 0; padding-left: 1.25rem; }
/* The board's highlight covers its whole row, chevron included, so it lines up with the
 * full-width page highlights under it rather than stopping short of the chevron. */
.settings-nav-board:hover { background-color: #f3f4f6; }
.settings-nav-board.is-current { background-color: #f1f5f9; }
.settings-nav-board .nav-btn, .settings-nav-board .nav-btn:hover, .settings-nav-board .nav-btn.active { background-color: transparent; }
.settings-nav-toggle { width: 26px; height: 26px; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; border: 0; background: none; border-radius: 6px; color: #9ca3af; font-size: 10px; cursor: pointer; }
.settings-nav-toggle:hover { background-color: rgba(15, 23, 42, .06); color: #111827; }
.settings-nav-toggle i { transition: transform 200ms var(--gv-ease, ease); }
.settings-nav-board.is-open .settings-nav-toggle i { transform: rotate(90deg); }
/* A board's pages slide open and shut: the row's height animates from 0 to its content. */
.settings-nav-pages { display: grid; grid-template-rows: 0fr; opacity: 0; transition: grid-template-rows 220ms var(--gv-ease, ease), opacity 180ms var(--gv-ease, ease); }
.settings-nav-pages.is-open { grid-template-rows: 1fr; opacity: 1; }
.settings-nav-pages > .nav-sub-group { min-height: 0; overflow: hidden; margin-top: 0; margin-bottom: 0; }
.settings-nav .nav-sub-group { margin-left: 38px; }
@media (prefers-reduced-motion: reduce) {
  .settings-nav-pages, .settings-nav-toggle i { transition: none; }
}
.settings-nav-add { color: var(--gv-brand-900) !important; font-weight: 600; padding-left: 1.25rem !important; }
/* Below this the member table needs the width more than the nav needs its column. */
@media (max-width: 1100px) {
  .settings-layout { grid-template-columns: 1fr; gap: 1rem; }
  .settings-side { position: static; }
  .settings-main { margin-top: 0; }
}
/* Settings → a board → Members (#981): one read-only line per person, opened to edit. */
.bm-list { border: 1px solid var(--gv-border); border-radius: var(--gv-radius-lg); background: var(--gv-surface); }
.bm-row { position: relative; display: flex; align-items: center; gap: 10px; padding: 9px 8px 9px 12px; cursor: pointer; transition: background-color 120ms var(--gv-ease, ease); }
.bm-row + .bm-row, .bm-row + .bm-edit, .bm-edit + .bm-row { border-top: 1px solid var(--gv-ink-100); }
.bm-row:first-child, .bm-edit:first-child { border-top-left-radius: var(--gv-radius-lg); border-top-right-radius: var(--gv-radius-lg); }
.bm-row:last-child, .bm-edit:last-child { border-bottom-left-radius: var(--gv-radius-lg); border-bottom-right-radius: var(--gv-radius-lg); }
.bm-row:hover { background: var(--gv-surface-sunk); }
/* Settings → Team uses the same lines (#1005), with an initials avatar beside the name. */
.team-avatar { width: 32px; height: 32px; flex-shrink: 0; border-radius: 9999px; display: inline-flex; align-items: center; justify-content: center; background: var(--gv-surface-sunk); color: var(--gv-text-muted); font-size: 11px; font-weight: 600; letter-spacing: .02em; }
.bm-row:focus-visible { outline: var(--gv-focus-width) solid var(--gv-focus-color); outline-offset: -2px; }
.bm-row-main { flex: 1; min-width: 0; }
.bm-row-line { display: flex; align-items: center; gap: 6px; min-width: 0; }
.bm-row-name { font-size: 13.5px; font-weight: 600; color: var(--gv-text); white-space: nowrap; }
.bm-row-name.is-empty { color: var(--gv-text-disabled); font-style: italic; font-weight: 500; }
.bm-row-sep { color: var(--gv-ink-300); }
.bm-row-title { font-size: 13px; color: var(--gv-text-subtle); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bm-row-sub { font-size: 11.5px; color: var(--gv-text-subtle); margin-top: 1px; }
.bm-row .bm-vp { position: relative; right: auto; top: auto; transform: none; font-size: 12px; display: inline-flex; }
/* The fingerprint shows its hint on hover, and pressing it opens the line with its recordings
   (#570): a pointer, not the help cursor (#1064) .bm-hint gives the "?" beside a field's label. */
.bm-row .bm-vp { cursor: pointer; align-items: center; border-radius: var(--gv-radius-sm); }
.bm-row .bm-vp:focus-visible { outline: var(--gv-focus-width) solid var(--gv-focus-color); outline-offset: 2px; }
/* Saved or Not yet beside it: Saved in the success text colour, which holds 4.5:1 on white. Not yet
   in the subtle grey since 2026-10-24 (Vinny), here and on Speakers: amber there is the edge on a
   voice nobody is on, and an untrained VoicePrint is optional work, not a thing wrong. An AI guess
   (Speakers) is a person still to confirm, so it keeps the warning text colour. */
.bm-vp-word { margin-left: 5px; font-size: 12px; font-weight: 500; color: var(--gv-success-fg); }
.bm-vp-word.is-off { color: var(--gv-text-subtle); }
.bm-vp-word.is-guess { color: var(--gv-warning-fg); }
.bm-edit { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; padding: 12px; background: var(--gv-surface-sunk); }
.bm-edit-full { grid-column: 1 / -1; }
@media (max-width: 640px) { .bm-edit { grid-template-columns: 1fr; } }
/* The open person (#570, option I): the line holds its own fields, so no pointer or hover wash,
   the sunk ground of the Group panel under it so the two read as one, and cells that let a
   field's focus ring show rather than clip it. */
.bm-row.bm-row--cols.is-editing { cursor: default; background: var(--gv-surface-sunk); padding-top: 6px; padding-bottom: 6px; }
.bm-row--cols.is-editing .bm-row-name, .bm-row--cols.is-editing .bm-row-title, .bm-row.is-editing .bm-row-min { overflow: visible; }
.bm-row.is-editing .gv-input { padding: var(--gv-space-1) var(--gv-space-2); }
/* Its VoicePrint cell, Saved or Not yet as a button that opens the recordings. */
.bm-vp-trigger { display: inline-flex; align-items: center; gap: var(--gv-space-1); padding: 3px var(--gv-space-2); font: inherit; font-size: 12px;
    border: 1px solid var(--gv-border-strong); border-radius: var(--gv-radius-md); background: var(--gv-surface); cursor: pointer; white-space: nowrap; }
.bm-vp-trigger:hover { background: var(--gv-surface-sunk); }
.bm-vp-trigger:focus-visible { outline: var(--gv-focus-width) solid var(--gv-focus-color); outline-offset: 1px; }
.bm-vp-trigger .bm-vp-word { margin-left: 0; }
.bm-vp-caret { font-size: 0.65em; color: var(--gv-text-subtle); }
/* The recordings menu: one grid for all the rows (each row display: contents), so the clips,
   dates and meetings stand as columns whatever the dates' lengths. */
.gv-picker.bm-vpm { width: 31rem; max-width: calc(100vw - 16px); padding-bottom: var(--gv-space-1); }
.bm-vpm-list { display: grid; grid-template-columns: auto auto minmax(0, 1fr) auto; align-items: center; gap: var(--gv-space-1) var(--gv-space-3);
    max-height: 16rem; overflow-y: auto; padding: var(--gv-space-1) var(--gv-space-3); font-size: var(--gv-text-sm); }
.bm-vpm-rec { display: contents; }
.bm-vpm-date { color: var(--gv-text); white-space: nowrap; font-variant-numeric: tabular-nums; }
.bm-vpm-mtg { display: block; justify-self: start; max-width: 100%; min-width: 0; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--gv-text); }
.bm-vpm-mtg.is-gone { color: var(--gv-text-disabled); }
/* Delete all VoicePrints, at the right under the rows' ×s it does all of at once. */
.bm-vpm-all { justify-content: flex-end; }
.bm-vpm-all .gv-picker__opt-text { flex: 0 1 auto; }
.bm-vpm-none { padding: var(--gv-space-3); font-size: var(--gv-text-sm); color: var(--gv-text-subtle); line-height: var(--gv-leading-snug); }
/* A recording's clip: a pill that says how long it is, and pressing any of it plays it, play or
   pause in front of the length. Where the clip wasn't kept, the length is plain grey text, no pill,
   so nothing about it says press. */
.bm-vpl-clip { display: inline-flex; align-items: center; gap: var(--gv-space-1); justify-self: start; white-space: nowrap;
    border: 1px solid var(--gv-border-strong); border-radius: var(--gv-radius-full); background: var(--gv-surface);
    padding: 2px var(--gv-space-2); font: inherit; font-size: var(--gv-text-xs); color: var(--gv-text); cursor: pointer; }
.bm-vpl-clip i { font-size: 0.75em; color: var(--gv-brand-600); }
.bm-vpl-play:hover { background: var(--gv-surface-sunk); }
.bm-vpl-play:focus-visible { outline: var(--gv-focus-width) solid var(--gv-focus-color); outline-offset: 1px; }
.bm-vpl-play.is-playing { border-color: var(--gv-brand-600); }
.bm-vpl-clip.is-none { border-color: transparent; background: transparent; color: var(--gv-text-subtle); cursor: default; }
.bm-vpl-len { font-variant-numeric: tabular-nums; }
@media (max-width: 640px) {
    .bm-row.is-editing .bm-row-min { display: flex; align-items: center; gap: var(--gv-space-2); white-space: nowrap; }
}
/* Remove sits on the line in plain sight, quiet until pointed at. */
/* Members' lines are columns under a heading row (#1064): name, title, how the minutes write
   them, voiceprint, then the ⋯. One grid for the headings and the lines, so they can't
   drift apart, and minmax(0, …) lets a long name shrink to an ellipsis rather than push the line
   past the card. Settings → Team has the same lines in its own columns (#1068, below); Archived
   keeps the one-line .bm-row. */
.bm-cols, .bm-row.bm-row--cols { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1.4fr) 5.5rem var(--gv-control-sm); align-items: center; gap: 0 10px; }
.bm-cols { padding: 6px 8px 6px 12px; border-bottom: 1px solid var(--gv-ink-100); border-top-left-radius: var(--gv-radius-lg); border-top-right-radius: var(--gv-radius-lg); background: var(--gv-surface-sunk); font-size: 11.5px; font-weight: 600; color: var(--gv-text-subtle); }
.bm-cols > span:nth-child(4), .bm-row-vp { justify-self: center; }
.bm-row--cols .bm-row-name, .bm-row--cols .bm-row-title, .bm-row-min { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A minutes name someone set reads as plainly as the name; the title-and-name the minutes fall
   back to is greyed, so it reads as the default it is. */
.bm-row-min { font-size: 13px; color: var(--gv-text); }
.bm-row-min.is-default { color: var(--gv-text-subtle); }
.bm-row-acts { display: flex; justify-content: flex-end; }
/* The ⋯ on every line a notch quieter, so the names lead, and at full strength on the line under
   the pointer or the keyboard. It stays in sight, since a tablet has no hover to reveal it.
   --gv-ink-500 is as light as an icon on white can go and keep 3:1. Remove is in it, last and in
   red, the way Delete board ends the board's ⋯; it used to be a bin on every line. */
.bm-row--cols .bm-row-acts .gv-btn { color: var(--gv-ink-500); }
.bm-row--cols:hover .bm-row-acts .gv-btn, .bm-row--cols:focus-within .bm-row-acts .gv-btn { color: var(--gv-text-subtle); }
/* A phone has no room for five columns: the headings go, and each line is the name with its
   voiceprint and ⋯, the title under it, and a minutes name only when one is set. */
@media (max-width: 640px) {
  .bm-cols { display: none; }
  .bm-row.bm-row--cols { grid-template-columns: minmax(0, 1fr) auto auto; grid-template-areas: "name vp acts" "title title title" "min min min"; }
  .bm-row--cols .bm-row-name { grid-area: name; }
  .bm-row--cols .bm-row-title { grid-area: title; }
  .bm-row--cols .bm-row-title:empty, .bm-row-min.is-default { display: none; }
  .bm-row-min { grid-area: min; font-size: 12px; }
  .bm-row-min::before { content: 'In the minutes: '; color: var(--gv-text-subtle); }
  .bm-row-vp { grid-area: vp; }
  .bm-row-acts { grid-area: acts; }
}
/* Members' own columns since #570 (option O, Vinny, 2026-10-25): name, title, minutes name, the
   group, a dropdown in the ⋯'s old place, the voiceprint, and the × that removes them. Scoped to
   Members, since Team shares .bm-row--cols with columns of its own. The group fills its column,
   chevron at the right as a select's is, and reads as text on a closed line and as a control on
   the open one, as the VoicePrint cell beside it does. */
[data-board-members] .bm-cols, [data-board-members] .bm-row.bm-row--cols { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 9.5rem) 5.5rem var(--gv-control-sm); }
[data-board-members] .bm-cols > span:nth-child(4) { justify-self: start; }
[data-board-members] .bm-cols > span:nth-child(5) { justify-self: center; }
.bm-row-grp { min-width: 0; }
.bm-grp-btn { display: flex; align-items: center; justify-content: space-between; gap: var(--gv-space-1); width: calc(100% + var(--gv-space-2)); padding: 3px var(--gv-space-2); margin-left: calc(-1 * var(--gv-space-2));
    font: inherit; font-size: 12px; color: var(--gv-text-subtle); background: transparent; border: 1px solid transparent; border-radius: var(--gv-radius-md); cursor: pointer; white-space: nowrap; }
.bm-grp-text { overflow: hidden; text-overflow: ellipsis; }
.bm-grp-btn i { font-size: 0.65em; }
.bm-grp-btn:hover, .bm-grp-btn[aria-expanded="true"] { background: var(--gv-surface); border-color: var(--gv-border-strong); color: var(--gv-text); }
.bm-grp-btn:focus-visible { outline: var(--gv-focus-width) solid var(--gv-focus-color); outline-offset: 1px; }
.bm-row.is-editing .bm-grp-btn { width: 100%; margin-left: 0; background: var(--gv-surface); border-color: var(--gv-border-strong); color: var(--gv-text); }
.bm-row-del { display: flex; justify-content: flex-end; }
/* The voiceprint is the last column now, so its hint opens leftward from the mark's right edge:
   centred, half of it ran past the card and made the page scroll sideways. */
.bm-row-vp .bm-hint::after { left: auto; right: 0; transform: none; }
@media (max-width: 640px) {
  /* A phone has no room for the group beside the name: on a closed line the tab already says it,
     and the open line gives it a row of its own, under the minutes name. */
  [data-board-members] .bm-row.bm-row--cols { grid-template-columns: minmax(0, 1fr) auto auto; grid-template-areas: "name vp del" "title title title" "min min min" "grp grp grp"; }
  [data-board-members] .bm-row:not(.is-editing) .bm-row-grp { display: none; }
  .bm-row-grp { grid-area: grp; }
  .bm-row-del { grid-area: del; }
  .bm-grp-btn, .bm-row.is-editing .bm-grp-btn { width: auto; justify-self: start; }
}
/* Settings → Team's lines are Members' columns too (#1068): the avatar and name, title, email, then
   board access with two or more boards, then Status (who hasn't set a password: Pending, No login
   or Login off, wide enough for the widest), then the ⋯. Department isn't a column: it's in the
   details. The list's classes pick the template, so the heading row and the lines can't drift
   apart, and it is all under #team-list, so Members' template isn't touched. It stops at 56rem, as
   Members does. */
#team-list { max-width: 56rem; }
#team-list .bm-cols, #team-list .bm-row--cols { grid-template-columns: var(--team-cols); }
#team-list .team-cols { --team-cols: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1.3fr) 5.5rem var(--gv-control-sm); }
#team-list .team-cols--boards { --team-cols: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1.3fr) minmax(0, .9fr) 5.5rem var(--gv-control-sm); }
/* Members centres its 4th heading over the voiceprints; Team's 4th is Board access, read from the left. */
#team-list .bm-cols > span:nth-child(4) { justify-self: start; }
.team-who { display: flex; align-items: center; gap: 10px; min-width: 0; }
.team-cell { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; color: var(--gv-text-subtle); }
.team-cell.is-empty { color: var(--gv-text-disabled); font-style: italic; }
/* The note over the list is there only when nobody's Status could be checked. */
.team-passwords-note:empty { display: none; }
.team-passwords-note { margin-bottom: 8px; font-size: 13px; color: var(--gv-warning-fg); }
/* On a phone the headings go (above), and each line is the avatar, name and ⋯, with what has a
   value stacked under the name, lined up with it past the avatar (32px and the 10px gap). Board
   access says what it is, as Members says "In the minutes:"; a Status badge says it itself, and
   someone with none has no line for it. */
@media (max-width: 640px) {
  #team-list .bm-row--cols { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "who acts" "title title" "email email" "boards boards" "status status"; }
  #team-list .team-who { grid-area: who; }
  #team-list .team-row-email { grid-area: email; }
  #team-list .team-row-boards { grid-area: boards; }
  #team-list .bm-row--cols > .bm-row-title, #team-list .bm-row--cols > .team-cell { padding-left: 42px; font-size: 12px; }
  #team-list .team-row-boards::before { content: 'Boards: '; }
  #team-list .team-row-status { grid-area: status; }
  #team-list .team-row-status:empty { display: none; }
  /* Three tabs and their counts in a 390px phone's width without an ellipsis: half the padding
     Members' tabs keep there, and half the space before a count. Narrower still, names give way. */
  #team-list .bm-tabs .gv-tabs__tab { padding-left: var(--gv-space-1); padding-right: var(--gv-space-1); }
  #team-list .bm-tabs .gv-tabs__count { margin-left: var(--gv-space-1); }
}
/* Admin Portal → Users (#1134): Team's lines for every user in every org, in columns of its own
   under #sa-users-list, so Team's aren't touched. The same columns on every tab: the name (no
   initials), email, first login, last login, # logins, org, then the ⋯. A super admin who can't sign
   in has their access badge across the two login columns (.sa-users-access). */
#sa-users-list .bm-cols, #sa-users-list .bm-row--cols { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1.5fr) 7rem 7rem 4.5rem minmax(0, 1.1fr) var(--gv-control-sm); }
#sa-users-list .sa-users-access { grid-column: span 2; }
/* Super Admins has no Org column. */
#sa-users-list .sa-users-list--sa .bm-cols, #sa-users-list .sa-users-list--sa .bm-row--cols { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1.5fr) 7rem 7rem 4.5rem var(--gv-control-sm); }
#sa-users-list .bm-cols > span:nth-child(4) { justify-self: start; }
#sa-users-list .sa-users-count { font-variant-numeric: tabular-nums; }
/* You and Super admin keep their size beside a name that gives way, and an access badge gives way
   in its two columns, its hint saying the rest. */
#sa-users-list .team-who .gv-badge { flex-shrink: 0; }
#sa-users-list .sa-users-access .gv-badge { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; vertical-align: middle; }
/* The filters in force (GV.filterPills), in a row of their own over the role tabs, there only while
   one is (#1134 has no search box for them to sit beside). */
.sa-users-chips { margin-bottom: 12px; }
.sa-users-chips:empty { display: none; }
.sa-users-meta { margin-bottom: 8px; font-size: 13px; color: var(--gv-text-subtle); }
.sa-users-meta .is-warn { color: var(--gv-warning-fg); }
.sa-users-note { padding: 4px 0; font-size: 13px; color: var(--gv-text-subtle); }
/* Every heading has a funnel (#1134), as Organizations' do (#811): out of sight until the pointer
   is over its heading or focus is in it, while its column is filtered, and while its menu is open
   (components.css has the rest). Its label sorts (#1234), and the sorted one takes a table's
   sorted colour: a table keys that off its <th>'s aria-sort, which these headings don't have. */
#sa-users-list .bm-cols > span { display: inline-flex; align-items: center; min-width: 0; white-space: nowrap; }
#sa-users-list .bm-cols .gv-table__sort.is-sorted { color: var(--gv-text); }
@media (hover: hover) {
  #sa-users-list .bm-cols > span:hover .gv-table__filter, #sa-users-list .bm-cols > span:focus-within .gv-table__filter { opacity: 1; }
}
/* An address and its copy button (#1234): the address gives way with an ellipsis and the button
   keeps its place after it. 2xs, as a heading's funnel, so it doesn't make the line taller. Out
   of sight until the pointer is over the line or focus is on or in it; a touch screen, which can't
   hover, always shows it. Its focus ring is drawn inside it, since the cell clips what overflows. */
#sa-users-list .sa-users-email:not(.is-empty) { display: flex; align-items: center; gap: var(--gv-space-1); }
#sa-users-list .sa-users-addr { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sa-users-copy {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: var(--gv-control-2xs); height: var(--gv-control-2xs); padding: 0; border: 0; border-radius: var(--gv-radius-sm);
  background: none; color: var(--gv-text-disabled); font-size: var(--gv-text-2xs); cursor: pointer;
}
.sa-users-copy:hover { color: var(--gv-text); background: var(--gv-surface-sunk); }
.sa-users-copy:focus-visible { outline: var(--gv-focus-width) solid var(--gv-focus-color); outline-offset: calc(-1 * var(--gv-focus-width)); }
@media (hover: hover) {
  #sa-users-list .sa-users-copy { opacity: 0; }
  #sa-users-list .bm-row:hover .sa-users-copy, #sa-users-list .bm-row:focus-within .sa-users-copy { opacity: 1; }
}
/* On a phone, as on Team: the headings go, each line is the avatar, name and ⋯, and what has a
   value stacks under the name, lined up with it. Of the logins, Last Login alone, saying what it
   is; the first and the count wait for a wider screen. */
@media (max-width: 640px) {
  #sa-users-list .bm-row--cols { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "who acts" "email email" "last last" "org org"; }
  #sa-users-list .team-who { grid-area: who; }
  #sa-users-list .sa-users-email { grid-area: email; }
  #sa-users-list .sa-users-last, #sa-users-list .sa-users-access { grid-area: last; }
  #sa-users-list .sa-users-org { grid-area: org; }
  #sa-users-list .bm-row--cols > .team-cell { font-size: 12px; }
  #sa-users-list .sa-users-org:empty, #sa-users-list .sa-users-first, #sa-users-list .sa-users-count { display: none; }
  #sa-users-list .sa-users-last::before { content: 'Last login '; }
  #sa-users-list .bm-tabs .gv-tabs__tab { padding-left: var(--gv-space-1); padding-right: var(--gv-space-1); }
  #sa-users-list .bm-tabs .gv-tabs__count { margin-left: var(--gv-space-1); }
}
/* Members' groups are tabs (#1064), the gv-tabs strip on one line however many groups a board
   makes: the standard three, then one tab whose menu holds the board's own and Add a group. On a
   phone the three take their short names. Past that, a tab's name gives way with an ellipsis
   rather than the strip wrapping or scrolling. Nothing clips the strip itself, which would cut
   off the focus ring drawn outside a tab. */
.bm-tabs { flex-wrap: nowrap; margin-bottom: 12px; }
/* Members stops at 56rem (#1064). On a wide window the bin and ⋯ sat a screen's width from the
   names they belong to; the General tab's card stops short for the same reason. */
[data-board-members] { max-width: 56rem; }
.bm-tabs .gv-tabs__tab { display: inline-flex; align-items: center; flex: 0 1 auto; min-width: 0; }
.bm-tabs .gv-tabs__count, .bm-tabs .gv-tabs__tab > i { flex-shrink: 0; }
.bm-tab-long, .bm-tab-short, .bm-tab-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.bm-tab-short { display: none; }
@media (max-width: 640px) {
  .bm-tabs .gv-tabs__tab { padding-left: var(--gv-space-2); padding-right: var(--gv-space-2); }
  .bm-tab-long { display: none; }
  .bm-tab-short { display: block; }
}
/* The board's own groups: named for the one showing, with a ▾ for its menu. */
.bm-tab-own { gap: 6px; }
.bm-tab-own .bm-tab-label { max-width: 14rem; }
.bm-tab-own > i { font-size: 10px; }
/* A board with no groups of its own has Add a group there instead, in the green of Add to …. */
.gv-tabs__tab.bm-tab-add { gap: 6px; color: var(--gv-brand-700); }
.gv-tabs__tab.bm-tab-add:hover { color: var(--gv-brand-900); }
.bm-tab-add i { font-size: 11px; }
/* The picked group under the tabs: its title, list, Add to … and Apply. A board's own group says
   by its name that it doesn't count in votes. */
.bm-panel { padding-bottom: 16px; }
.bm-panel > .bm-group-head { margin-bottom: 6px; }
.bm-group-note { font-size: 12.5px; font-weight: 400; color: var(--gv-text-subtle); white-space: nowrap; }
/* Archived, drawn as a group. (Settings → Team's role groups were these too, every one open, until
   they became tabs, #1068.) */
.bm-group { border-top: 1px solid var(--gv-ink-100); padding: 4px 0; }
.bm-group:first-child { border-top: 0; }
.bm-group-head { display: flex; align-items: center; gap: 8px; min-height: 40px; }
.bm-group-toggle { display: flex; align-items: baseline; gap: 6px; width: calc(100% + 16px); min-width: 0; border: 0; background: none; padding: 7px 8px; margin: 0 -8px; border-radius: var(--gv-radius-sm); text-align: left; cursor: pointer; font-size: 14px; font-weight: 600; color: var(--gv-text); }
.bm-group-toggle:hover { background: var(--gv-surface-sunk); }
.bm-group-toggle:focus-visible { outline: var(--gv-focus-width) solid var(--gv-focus-color); outline-offset: -2px; }
.bm-group-toggle > i { align-self: center; width: 10px; font-size: 10px; color: var(--gv-text-subtle); transition: transform 120ms var(--gv-ease, ease); }
.bm-group-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.bm-group-count { flex-shrink: 0; font-size: 12px; font-weight: 400; color: var(--gv-text-subtle); }
/* Archived, drawn like a group heading. */
.bm-archived { margin-top: 16px; }
.bm-archived > summary { list-style: none; }
.bm-archived > summary::-webkit-details-marker { display: none; }
.bm-archived[open] > summary > i { transform: rotate(90deg); }
.bm-archived[open] { padding-bottom: 16px; }
.bm-archived > .bm-list { margin-top: 6px; }
.bm-arch-row { display: flex; align-items: center; gap: 10px; padding: 9px 8px 9px 12px; }
.bm-arch-row + .bm-arch-row { border-top: 1px solid var(--gv-ink-100); }
/* Renaming a group: its name box, in the heading's type. */
.bm-group-rename { flex: 1; min-width: 0; font-size: 14px; font-weight: 600; }
/* Adding under a group (#1025): one quick line at the foot of the group's list, in the open
   person's grid and labels (.bm-edit, #1041), with its × in the top corner, clear of the fields. */
.bm-new { position: relative; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; padding: 12px; background: var(--gv-surface-sunk); }
.bm-new-x { position: absolute; top: 4px; right: 4px; }
/* A Name box offers the people the town already has as it is typed in (#974), here and in Add a
   group's form. The arrow Chrome draws on any box with a list made it look like a dropdown to pick
   from rather than a name to type, so it goes (#1064); the names still come up as you type. */
.bm-new input::-webkit-calendar-picker-indicator,
.bg-draft input::-webkit-calendar-picker-indicator { display: none !important; }
.bm-row + .bm-new, .bm-edit + .bm-new { border-top: 1px solid var(--gv-ink-100); }
.bm-new:first-child { border-top-left-radius: var(--gv-radius-lg); border-top-right-radius: var(--gv-radius-lg); }
.bm-new:last-child { border-bottom-left-radius: var(--gv-radius-lg); border-bottom-right-radius: var(--gv-radius-lg); }
@media (max-width: 640px) { .bm-new { grid-template-columns: 1fr; } }
/* "Add to <group>" under each group, and "Another person" in the group form. */
.bm-add-to { display: inline-flex; align-items: center; gap: 6px; margin-top: 6px; padding: 4px 6px; margin-left: -6px; border: 0; background: none; border-radius: var(--gv-radius-sm); font-size: 13px; font-weight: 600; color: var(--gv-brand-700); cursor: pointer; }
.bm-add-to:hover { background: var(--gv-brand-50); color: var(--gv-brand-900); }
.bm-add-to i { font-size: 11px; }
/* A group's own Apply (#1037): at the open group's foot while something in it waits. Always in
   the markup and only shown or hidden, so a press that ends an edit still lands on it. */
.bm-apply { display: none; align-items: center; gap: 8px; margin-top: 10px; padding: 6px 8px 6px 12px; border: 1px solid var(--gv-border); border-radius: var(--gv-radius-lg); background: var(--gv-surface-sunk); }
.bm-apply.is-dirty { display: flex; }
.bm-apply .settings-apply-state { color: var(--gv-warning-fg); font-weight: 600; }
/* Settings → Team (#1044): the open person applies from a .bm-apply at the foot of their details,
   as a Members group does at the foot of its list. */
.bm-edit > .bm-apply { margin-top: 2px; background: var(--gv-surface); }
.bm-group-title { display: flex; align-items: baseline; gap: 6px; min-width: 0; padding: 7px 0; font-size: 14px; font-weight: 600; color: var(--gv-text); }
.bm-edit .gv-check-row { font-size: 13px; color: var(--gv-text); }
/* Board access in a person's details is a dropdown (GV.checkMenu, #1068); under it, what a
   Contributor's boxes mean, or Select all boards. */
.team-boards-note { margin-top: 6px; font-size: 12px; color: var(--gv-text-subtle); }
.team-boards-all { margin-top: 6px; margin-left: -8px; }
.team-empty { font-size: 14px; color: var(--gv-text-muted); }
/* Add a group: the group's name and its people, kept on Save. */
.bg-draft { border: 1px solid var(--gv-border); border-radius: var(--gv-radius-lg); background: var(--gv-surface-sunk); padding: 14px; margin: 12px 0 1.25rem; }
/* The × column has the button's own width, so the headings row (#1041), which has no ×, lines up. */
.bg-d-line { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr) calc(var(--gv-control-sm) * 0.8); gap: 8px; align-items: center; }
.bg-d-cols .gv-label { margin-bottom: 0; }
.bg-d-err { min-height: 1.25rem; margin: 4px 0; font-size: 12px; color: var(--gv-danger-fg); }
@media (max-width: 640px) { .bg-d-cols { display: none; } .bg-d-line { grid-template-columns: minmax(0, 1fr) auto; } .bg-d-line > button { grid-row: 1; grid-column: 2; } .bg-d-line > input[data-bg-f="title"], .bg-d-line > input[data-bg-f="minutesName"] { grid-column: 1; } }
/* Settings → Agenda → Departments (#1039): each a box you click to rename, its × outside it. */
.dept-row { display: flex; align-items: center; gap: 6px; }
.dept-box { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; padding: 8px 12px; border: 1px solid var(--gv-border); border-radius: var(--gv-radius-lg); background: var(--gv-surface-sunk); text-align: left; cursor: pointer; font-size: 14px; font-weight: 500; color: var(--gv-text); }
.dept-box:hover { background: var(--gv-surface); }
.dept-box:focus-visible { outline: var(--gv-focus-width) solid var(--gv-focus-color); outline-offset: var(--gv-focus-offset); }
.dept-box-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dept-box i { font-size: 11px; color: var(--gv-text-subtle); }
.dept-rename { flex: 1; min-width: 0; }
.dept-remove { color: var(--gv-text-subtle); }
.dept-remove:hover, .dept-remove:focus-visible { color: var(--gv-danger-fg); background: var(--gv-danger-bg); }
.dept-none { padding: 4px 0; font-size: 13px; color: var(--gv-text-subtle); }
.dept-new { flex: 1; min-width: 0; }
/* The board's name: text you click to rename, not an open box (#981). */
.board-name-line { flex: 1; min-width: 0; display: inline-flex; align-items: center; gap: 10px; border: 0; background: none; padding: 8px 6px; border-radius: 8px; font-size: 1.125rem; font-weight: 600; color: var(--gv-text); text-align: left; cursor: pointer; }
.board-name-line i { font-size: 11px; color: var(--gv-ink-400); opacity: 0; transition: opacity 120ms; }
.board-name-line:hover { background: var(--gv-surface-sunk); }
.board-name-line:hover i, .board-name-line:focus-visible i { opacity: 1; }
/* A hint that opens upward, where the next row would otherwise cover it. */
.bm-hint.bm-hint--up::after { top: auto; bottom: calc(100% + 6px); z-index: 40; }
/* A hint with a picture in it (Number the lines): a real popover, since ::after holds only
   text. Opens upward, because it sits at the foot of the page above the Apply bar. */
.bm-hint.bm-hint--pop::after { content: none; }
.bm-hint-pop { position: absolute; z-index: 40; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%); width: 18rem; padding: 10px; background: var(--gv-text); color: var(--gv-text-invert); font-size: 12px; font-weight: 400; line-height: 1.4; text-align: left; border-radius: var(--gv-radius-sm); box-shadow: 0 4px 12px rgba(0,0,0,.15); opacity: 0; pointer-events: none; transition: opacity var(--gv-dur-fast); }
.bm-hint:hover .bm-hint-pop, .bm-hint:focus-visible .bm-hint-pop { opacity: 1; }
.bm-hint-pop__text { display: block; margin-bottom: 8px; }
.bm-ln-page { position: relative; overflow: hidden; display: block; background: var(--gv-surface); color: var(--gv-ink-700); border-radius: 3px; padding: 8px 10px 8px 0; font-family: Georgia, 'Times New Roman', serif; font-size: 10px; line-height: 1.6; }
.bm-ln-row { display: flex; min-height: 1.6em; }
.bm-ln-num { flex: 0 0 26px; padding-right: 8px; text-align: right; color: var(--gv-ink-400); font-family: var(--gv-font-sans, sans-serif); font-size: 9px; }
.bm-pv-pad { padding-left: 12px; }
.bm-pv-wm { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) rotate(-30deg); font-family: var(--gv-font-sans, sans-serif); font-size: 40px; font-weight: 700; letter-spacing: 4px; color: rgba(156,163,175,.6); pointer-events: none; }
.bm-pv-mo { display: block; text-align: right; font-family: var(--gv-font-sans, sans-serif); font-size: 9px; color: var(--gv-text-subtle); margin-top: 4px; }

/* Settings Apply bar (#983): pinned to the bottom of the section column. */
.settings-apply-bar { position: sticky; bottom: 0; z-index: 20; display: flex; align-items: center; gap: 8px; margin-top: 1.5rem;
  padding: 10px 14px calc(10px + env(safe-area-inset-bottom, 0px)); background: var(--gv-surface); border: 1px solid var(--gv-border);
  border-radius: var(--gv-radius-lg) var(--gv-radius-lg) 0 0; box-shadow: 0 -4px 16px rgba(12, 22, 18, .08); }
.settings-apply-state { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--gv-text-subtle); }
.settings-apply-bar.is-dirty .settings-apply-state { color: var(--gv-warning-fg, #b45309); font-weight: 600; }
.settings-apply-state i { font-size: 7px; }
.settings-apply-bar .gv-btn[disabled] { opacity: .45; cursor: not-allowed; }

/* A saved voiceprint, in the member's name field (#979). */
.bm-name-cell { position: relative; min-width: 0; }
.bm-name-cell input { padding-right: 2rem; }
.bm-name-cell .bm-vp { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); font-size: 13px; }

/* ── Meetings sub-items tree connector ──────────────────────── */
.nav-sub-group {
    margin-left: 22px;
    padding-left: 12px;
    border-left: 1px dashed #d1d5db;
    margin-top: 1px;
    margin-bottom: 2px;
}

.nav-sub-item {
    position: relative;
    display: flex;
    align-items: center;
    width: 100%;
    padding: 5px 8px;
    border-radius: 6px;
    font-size: 12px;
    color: #6b7280;
    transition: background-color 0.15s, color 0.15s;
    text-align: left;
    cursor: pointer;
    background: transparent;
    border: none;
}

.nav-sub-item::before {
    content: '';
    position: absolute;
    left: -12px;
    top: 50%;
    width: 8px;
    height: 1px;
    background: #e5e7eb;
}

.nav-sub-item:hover {
    background-color: #f3f4f6;
    color: #111827;
}

.nav-sub-item.active {
    background-color: #f0f7ed;
    color: var(--gv-brand-800);
    font-weight: 600;
}

/* Sub-item icons only render in the collapsed icon rail */
.nav-sub-icon {
    display: none;
}

/* The band across the top of the app (#1253) is sticky at the top of the window, and holds the
   session strip (#1246) while staff work inside an org and the trial bar while an org is on a
   trial. _appTopBandFit writes its height to --gv-session-h (0 when neither shows). Everything
   else that sticks to the window's top moves down by it, or it would slide under the band:
   the sidebar (which also gets that much shorter, or its bottom -- Contact support and the
   account row with Log out -- runs off the window), the meeting workspace's heading and Review
   Agenda's toolbar under it (.mw-sticky-toolbar), Settings' side nav and the agenda request
   form's header (.rf-header). The row under the band gets that much shorter too, or a short
   page scrolls by the band's height for nothing. Only the strip was counted until #1253, so a
   trial clerk's sidebar ran off the window by the trial bar's height. A stage measures what is
   above it (GV.stage's stageFit), so it needs nothing here. Ids, so these beat the h-screen /
   top-0 / min-h-screen utilities in the markup. */
#app-top-band {
    position: sticky;
    top: 0;
    z-index: var(--gv-z-sticky);
}
#app-columns { min-height: calc(100vh - var(--gv-session-h, 0px)); }
#main-sidebar {
    top: var(--gv-session-h, 0px);
    height: calc(100vh - var(--gv-session-h, 0px));
}
#meetings-detail-heading { top: var(--gv-session-h, 0px); }
.settings-side { top: calc(1rem + var(--gv-session-h, 0px)); }

/* Collapsed sidebar — hide labels, keep meeting steps as an icon rail */
#main-sidebar.sidebar-collapsed .sidebar-text {
    display: none;
}
/* Drop the tree indent/connector so sub-icons line up under the main nav icons */
#main-sidebar.sidebar-collapsed .nav-sub-group {
    margin-left: 0;
    padding-left: 0;
    border-left: none;
}
#main-sidebar.sidebar-collapsed .nav-sub-item {
    padding: 6px 10px;
}
#main-sidebar.sidebar-collapsed .nav-sub-item::before {
    display: none;
}
#main-sidebar.sidebar-collapsed .nav-sub-icon {
    display: inline-block;
}
/* Stack the logo over the chevron when collapsed (56px is too narrow for a row) */
#main-sidebar.sidebar-collapsed .brand-header {
    flex-direction: column;
    gap: 6px;
    padding-left: 0.25rem;
    padding-right: 0.25rem;
}

/* Agenda Preview Formatting - matches Ellis County style */
.agenda-preview {
    max-width: 700px;
    margin: 0 auto;
    font-family: Calibri, Arial, sans-serif !important;
    font-size: 12px;
    line-height: 1.5;
    color: #000;
}

.agenda-preview .header {
    text-align: center;
    margin-bottom: 20px;
}

.agenda-preview .header h1 {
    font-size: 16px;
    font-weight: bold;
    margin-bottom: 4px;
}

.agenda-preview .header h2 {
    font-size: 14px;
    font-weight: bold;
    margin-bottom: 12px;
}

.agenda-preview .members-row {
    display: flex;
    justify-content: space-between;
    font-size: 11px;
    margin-bottom: 16px;
    flex-wrap: wrap;
    gap: 4px;
}

.agenda-preview .notice {
    font-size: 12px;
    margin-bottom: 16px;
    text-align: justify;
}

.agenda-preview .section-title {
    font-weight: bold;
    font-size: 13px;
    margin-top: 16px;
    margin-bottom: 8px;
    text-transform: uppercase;
    border-bottom: 1px solid #000;
    padding-bottom: 2px;
}

.agenda-preview .agenda-item {
    margin-bottom: 8px;
    padding-left: 20px;
}

.agenda-preview .item-number {
    font-weight: bold;
}

.agenda-preview .item-official {
    font-style: italic;
    font-size: 11px;
}

/* Minutes Preview Formatting — Ellis County Style */
.minutes-preview {
    max-width: 720px;
    margin: 0 auto;
    font-family: Calibri, Arial, sans-serif !important;
    font-size: 12px;
    line-height: 1.5;
    color: #000;
    font-variant: small-caps;
}

.minutes-preview .minutes-seal {
    display: block;
    width: 60px;
    height: 60px;
    max-width: 60px;
    max-height: 60px;
    object-fit: contain;
    margin: 0 auto 8px;
}

.minutes-preview .header {
    text-align: center;
    margin-bottom: 24px;
}

.minutes-preview .header h1 {
    font-size: 16px;
    font-weight: normal;
    font-variant: small-caps;
    letter-spacing: 1px;
    margin-bottom: 2px;
}

.minutes-preview .header h2 {
    font-size: 13px;
    font-weight: normal;
    font-variant: small-caps;
    margin-bottom: 0;
}

.minutes-preview .minute-order-ref {
    text-align: right;
    font-size: 11px;
    font-variant: normal;
    margin-bottom: 16px;
    color: #333;
}

.minutes-preview .section-title {
    font-weight: bold;
    font-variant: small-caps;
    text-decoration: underline;
    font-size: 12px;
    margin-top: 20px;
    margin-bottom: 8px;
}

.minutes-preview .section-title .mo-number {
    text-decoration: none;
    float: right;
    font-weight: bold;
}

.minutes-preview .subsection-title {
    font-weight: bold;
    font-variant: small-caps;
    text-decoration: underline;
    font-size: 11px;
    margin-top: 12px;
    margin-bottom: 6px;
    padding-left: 12px;
}

.minutes-preview .minutes-item {
    margin-bottom: 10px;
    padding-left: 48px;
    text-indent: -28px;
}

.minutes-preview .minutes-item .item-num {
    font-weight: bold;
    font-variant: small-caps;
    display: inline-block;
    width: 28px;
}

.minutes-preview .minutes-item .item-presenter {
    font-style: italic;
    font-variant: normal;
}

.minutes-preview .vote-record {
    font-variant: small-caps;
    font-weight: normal;
    margin: 4px 0 4px 20px;
    font-size: 11px;
}

.minutes-preview .mo-label {
    font-weight: bold;
    font-variant: small-caps;
}

.minutes-preview .members-section {
    margin-bottom: 16px;
}

.minutes-preview .members-section .members-label {
    font-weight: bold;
    font-variant: small-caps;
    text-decoration: underline;
    display: inline-block;
    min-width: 140px;
}

.minutes-preview .members-section .member-line {
    padding-left: 20px;
    margin: 2px 0;
}

.minutes-preview .signature-block {
    margin-top: 40px;
    page-break-inside: avoid;
}

.minutes-preview .sig-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px 40px;
    margin-top: 20px;
}

.minutes-preview .sig-item {
    text-align: left;
}

.minutes-preview .sig-line {
    border-bottom: 1px solid #000;
    width: 240px;
    margin-top: 30px;
    margin-bottom: 4px;
}

.minutes-preview .attestation {
    margin-top: 30px;
    font-variant: small-caps;
}

.minutes-preview .attestation .seal-and-clerk {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    margin-top: 16px;
}

.minutes-preview .attestation .seal-img {
    width: 70px;
    height: 70px;
    max-width: 70px;
    max-height: 70px;
    object-fit: contain;
}

/* Drag & Drop */
.drag-over {
    border-color: #7c3aed !important; /* violet-600 — drop zone active */
    background-color: #ede9fe !important; /* violet-100 */
}

/* Meeting mode item cards */
.meeting-item-card {
    transition: all 0.2s;
}

.meeting-item-card.voted {
    border-left: 4px solid #94a3b8; /* slate-400 — generic "voted" marker; JS classes paint result color over it */
}

.meeting-item-card.no-action {
    border-left: 4px solid #9ca3af;
}

/* Vote buttons */
.vote-btn {
    padding: 6px 16px;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.15s;
}

.vote-btn.motion {
    background-color: #dbeafe;
    color: #1d4ed8;
    border: 1px solid #93c5fd;
}
.vote-btn.motion:hover { background-color: #bfdbfe; }

.vote-btn.second {
    background-color: #e0e7ff;
    color: #4338ca;
    border: 1px solid #a5b4fc;
}
.vote-btn.second:hover { background-color: #c7d2fe; }

.vote-btn.carried {
    background-color: #dff2c5;
    color: var(--gv-brand-800);
    border: 1px solid #cef17b;
}
.vote-btn.carried:hover { background-color: #cdedb3; }

.vote-btn.failed {
    background-color: #fee2e2;
    color: #991b1b;
    border: 1px solid #fca5a5;
}
.vote-btn.failed:hover { background-color: #fecaca; }

.vote-btn.no-action-btn {
    background-color: #f3f4f6;
    color: #4b5563;
    border: 1px solid #d1d5db;
}
.vote-btn.no-action-btn:hover { background-color: #e5e7eb; }

.vote-btn.active {
    outline: 2px solid currentColor;
    outline-offset: 1px;
}

/* Hides the scrollbar track on a scrollable element while keeping it scrollable
   (drag, trackpad, wheel, or JS scrollLeft) — for carousels with their own
   visible prev/next controls, where a second scrollbar is redundant. */
.no-scrollbar {
    scrollbar-width: none;       /* Firefox */
    -ms-overflow-style: none;    /* old Edge/IE */
}
.no-scrollbar::-webkit-scrollbar {
    display: none;               /* Chrome, Safari, new Edge */
}

/* Status badges */
.badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 10px;
    border-radius: 9999px;
    font-size: 12px;
    font-weight: 500;
}

.badge-pending {
    background-color: #fef3c7;
    color: #92400e;
}

.badge-approved {
    background-color: #dff2c5;
    color: var(--gv-brand-800);
}

.badge-deferred {
    background-color: #e0e7ff;
    color: #3730a3;
}

.badge-rejected {
    background-color: #fee2e2;
    color: #991b1b;
}

/* Dropdown menu - keep visible on hover */
.group:hover .group-hover\:block {
    display: block !important;
}

/* Animation */
@keyframes fadeIn {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: translateY(0); }
}

.view:not(.hidden) {
    animation: fadeIn 0.2s ease-out;
}

/* Editable minutes */
.minutes-editable:focus {
    outline: none;
}
.minutes-editable [contenteditable]:hover,
.minutes-editable div:hover,
.minutes-editable span:hover {
    background-color: #fefce8;
    cursor: text;
}
.minutes-editable::selection,
.minutes-editable *::selection {
    background-color: #bfdbfe;
}

/* Minutes Quill Editor */
#minutes-editor .ql-editor {
    min-height: 600px;
    max-height: calc(100vh - 300px);
    font-family: 'Georgia', 'Times New Roman', serif;
    font-size: 12px;
    line-height: 1.7;
    padding: 40px;
    overflow-y: auto;
}

#minutes-editor .ql-editor h1,
#minutes-editor .ql-editor h2 {
    font-family: 'Arial', sans-serif;
    text-transform: uppercase;
    border-bottom: 1px solid #000;
    padding-bottom: 4px;
    margin-top: 16px;
}

#minutes-editor .ql-editor h3 {
    font-family: 'Arial', sans-serif;
    font-size: 13px;
    text-transform: uppercase;
    margin-top: 14px;
}

#minutes-editor .ql-editor ul,
#minutes-editor .ql-editor ol {
    padding-left: 24px;
}

#minutes-editor .ql-editor li {
    margin-bottom: 4px;
}

#minutes-editor .ql-toolbar.ql-snow {
    border-color: #e5e7eb;
    border-radius: 0.75rem 0.75rem 0 0;
    background: #f9fafb;
}

#minutes-editor .ql-container.ql-snow {
    border-color: #e5e7eb;
    border-radius: 0 0 0.75rem 0.75rem;
}

/* Print styles */
@media print {
    nav, aside, .no-print { display: none !important; }
    main { padding: 0 !important; }
    /* Public minutes print */
    #public-minutes-viewer > div:first-child { display: none !important; }
    #public-minutes-viewer > div:last-child > div:last-child { display: none !important; }
    #public-minutes-viewer { background: white !important; }
    #public-minutes-body { border: none !important; box-shadow: none !important; padding: 0 !important; }
}

/* --- COLLAPSIBLE SECTIONS --- */
.section-collapse-btn {
    cursor: pointer;
    border: none;
    background: none;
    line-height: 1;
}
.section-collapse-btn i {
    display: inline-block;
    transition: transform 0.25s ease;
}
.section-collapse-btn.collapsed i {
    transform: rotate(-90deg);
}

/* --- QUILL RICH TEXT EDITOR (text sections) --- */
.text-section-editor .ql-toolbar {
    border-top-left-radius: 8px;
    border-top-right-radius: 8px;
    border-color: #e5e7eb;
    background: #f9fafb;
}
.text-section-editor .ql-container {
    border-bottom-left-radius: 8px;
    border-bottom-right-radius: 8px;
    border-color: #e5e7eb;
    min-height: 80px;
    font-size: 14px;
    font-family: inherit;
}
.text-section-editor .ql-editor {
    min-height: 80px;
    max-height: 320px;
    overflow-y: auto;
}
.text-section-editor .ql-editor.ql-blank::before {
    color: #9ca3af;
    font-style: italic;
}

/* Text section preview in agenda HTML */
.text-section-preview {
    padding-left: 8px;
    line-height: 1.6;
}
.text-section-preview p { margin: 2px 0; }
.text-section-preview ul, .text-section-preview ol {
    padding-left: 20px;
    margin: 4px 0;
}
.text-section-preview li { margin: 2px 0; }

/* --- Minutes Builder: Hover Insertion Zones --- */
.mb-insert-zone {
    height: 0;
    position: relative;
    z-index: 20;
    margin-top: 0 !important;
    margin-bottom: 0 !important;
    overflow: visible;
}

/* Hover target — covers full bar height (22px) plus a little extra */
.mb-insert-zone .mb-insert-hover-target {
    position: absolute;
    left: 0; right: 0;
    top: -13px;
    height: 26px;
    z-index: 25;
    cursor: default;
}

/* Hairline — two-tone gradient (blue left, amber right) */
.mb-insert-zone:hover::before {
    content: '';
    position: absolute;
    left: 8px; right: 8px;
    top: 0;
    height: 2px;
    background: linear-gradient(to right, #93c5fd 0%, #93c5fd 50%, #fcd34d 50%, #fcd34d 100%);
    border-radius: 1px;
    pointer-events: none;
}

/* Bar: centered on the hairline, full-width split */
.mb-insert-zone .mb-insert-bar {
    position: absolute;
    left: 8px; right: 8px;
    top: 0;
    height: 22px;
    transform: translateY(-50%);
    display: flex;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.13s ease;
    border-radius: 6px;
    overflow: hidden;
    box-shadow: 0 1px 4px rgba(0,0,0,0.12);
    z-index: 30;
}
.mb-insert-zone:hover .mb-insert-bar,
.mb-insert-zone .mb-insert-bar:hover {
    opacity: 1;
    pointer-events: auto;
}

/* Left / right halves — text centered inside */
.mb-insert-left, .mb-insert-right {
    flex: 1;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    font-size: 11px;
    font-weight: 500;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    transition: filter 0.1s ease;
}
.mb-insert-left:hover  { filter: brightness(0.94); }
.mb-insert-right:hover { filter: brightness(0.94); }
.mb-insert-left  { background: #ede9fe; color: #5b21b6; border-right: 1px solid rgba(196,181,253,0.5); } /* violet-100 / violet-800 — primary insert */
.mb-insert-right { background: #f1f5f9; color: #334155; } /* slate-100 / slate-700 — secondary insert */

/* --- Agenda Builder: Single-pill insert zone (no sub-items) --- */
.mb-insert-single {
    flex: 1;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    font-size: 11px;
    font-weight: 500;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    background: #dbeafe;
    color: #1d4ed8;
    border-radius: 6px;
    transition: filter 0.1s ease;
}
.mb-insert-single:hover { filter: brightness(0.94); }

/* Solid blue hairline for agenda (overrides blue/amber gradient) */
.agenda-insert-zone:hover::before {
    background: #93c5fd !important;
}

/* Inline title input for newly inserted agenda items */
.agenda-item-title-input {
    border: none;
    outline: none;
    background: transparent;
    font-size: 0.875rem;
    color: #111827;
    width: 100%;
    min-width: 0;
    padding: 0;
}
.agenda-item-title-input::placeholder { color: #9ca3af; font-style: italic; }

/* --- Minutes Builder: New Item Animation --- */
@keyframes mbItemSlideIn {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}
.mb-item-new {
    animation: mbItemSlideIn 0.25s ease-out forwards;
}

/* Placeholder for empty contenteditable elements that supply data-placeholder */
[contenteditable="true"][data-placeholder]:empty::before {
    content: attr(data-placeholder);
    color: #9ca3af;
    font-style: italic;
    pointer-events: none;
}


/* =============================================================================
   VIDEO PORTAL & ORG PUBLIC PORTAL
   ============================================================================= */

/* Video portal two-column grid — player width is user-controlled via size class */
.video-portal-grid {
    display: grid;
    grid-template-columns: 1fr var(--portal-player-width, 560px);
    gap: 1.5rem;
    align-items: start;
}
.video-portal-grid.size-s  { --portal-player-width: 380px; }
.video-portal-grid.size-m  { --portal-player-width: 560px; }
.video-portal-grid.size-l  { --portal-player-width: 760px; }
.video-portal-grid.size-xl { grid-template-columns: 1fr 1fr; }
@media (max-width: 768px) {
    .video-portal-grid,
    .video-portal-grid.size-s,
    .video-portal-grid.size-m,
    .video-portal-grid.size-l,
    .video-portal-grid.size-xl {
        grid-template-columns: 1fr;
        gap: 0.75rem;
    }
    /* Video panel ALWAYS visible — sits above the agenda and sticks under the header while you scroll */
    .video-portal-grid > .video-portal-sticky {
        order: -1;
        position: sticky;
        top: 56px; /* portal header height */
        z-index: 20;
        margin: 0 -1rem 0.5rem; /* bleed to viewport edges so it feels anchored */
        padding: 0.5rem 1rem;
        background: linear-gradient(135deg, rgba(8,71,52,0.97) 0%, rgba(10,90,64,0.97) 100%);
        backdrop-filter: blur(8px);
        -webkit-backdrop-filter: blur(8px);
    }
    /* Hide the secondary info card on mobile — it eats vertical space without adding info */
    .video-portal-sticky > .portal-glass-panel:nth-of-type(2) {
        display: none;
    }
}

.portal-size-btn {
    padding: 3px 9px; font-size: 11px; font-weight: 500;
    border-radius: 6px; border: 1px solid rgba(255,255,255,0.2);
    color: rgba(255,255,255,0.75); background: transparent;
    cursor: pointer; transition: all 0.15s;
}
.portal-size-btn:hover { color: #fff; background: rgba(255,255,255,0.1); }
.portal-size-btn.active { color: var(--gv-brand-900); background: #cef17b; border-color: #cef17b; }

/* Make YouTube IFrame fill its 16:9 wrapper exactly */
#yt-player-wrap, #yt-player-wrap iframe, #rec-player, #rec-player iframe {
    width: 100% !important;
    height: 100% !important;
    border: 0;
}

/* Sticky video column */
.video-portal-sticky {
    position: sticky;
    top: 4.5rem;
}

/* Glass card used on both portals */
.portal-glass-panel {
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-radius: 1rem;
    border: 1px solid rgba(255, 255, 255, 0.6);
    box-shadow: 0 4px 24px rgba(8, 71, 52, 0.12);
}

/* Agenda item rows in video portal */
.portal-item {
    border-radius: 0.5rem;
    transition: background 0.12s, border-left-color 0.12s;
    border-left: 3px solid transparent;
}
.portal-item:hover {
    background: rgba(206, 241, 123, 0.15);
    border-left-color: rgba(206, 241, 123, 0.5);
}
.portal-item-active {
    background: rgba(206, 241, 123, 0.25) !important;
    border-left-color: #cef17b !important;
}

/* LIVE badge pulsing dot */
.live-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #ef4444;
    animation: livePulse 1.5s ease-in-out infinite;
    flex-shrink: 0;
}
@keyframes livePulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%       { opacity: 0.5; transform: scale(0.75); }
}
.live-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* Org portal header */
.org-portal-header {
    background: linear-gradient(135deg, var(--gv-brand-900) 0%, #0d6647 100%);
}

/* Meeting card in org portal */
.meeting-card {
    background: white;
    border-radius: 1rem;
    border: 1px solid #e5e7eb;
    padding: 1.25rem;
}

/* Timestamp badge in video portal */
.portal-ts-badge {
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
}

/* Min height for left panel so it scrolls independently */
.max-h-screen-minus-header {
    max-height: calc(100vh - 5rem);
}

@keyframes rec-progress {
    0%   { transform: translateX(-100%); width: 30%; }
    50%  { width: 60%; }
    100% { transform: translateX(250%); width: 30%; }
}

/* =============================================================================
   PUBLIC MEETING VIEW — "Fusion" design (Direction D)
   Used by /public/minutes/{docId} and /public/portal/{orgId}
   Inter font + B-style cards + gray-boxed header & agenda + emerald accent
   ============================================================================= */

.pm-page { background: #fff; color: #0f1614; min-height: 100vh; font-family: 'Inter', system-ui, -apple-system, sans-serif; -webkit-font-smoothing: antialiased; }
.pm-wrap { max-width: 1200px; margin: 0 auto; padding: 16px; }
@media (min-width: 768px) { .pm-wrap { padding: 24px; } }

.pm-header { background: #f4f5f6; border: 1px solid #e6e8e7; border-radius: 16px; position: sticky; top: 8px; z-index: 30; backdrop-filter: blur(8px); margin-bottom: 20px; }
.pm-header-inner { padding: 12px 16px; display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
@media (min-width: 768px) { .pm-header-inner { padding: 12px 20px; } }

.pm-seal { width: 60px; height: 60px; border-radius: 50%; background: #fff; border: 2px solid var(--gv-brand-900); display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 13px; color: var(--gv-brand-900); letter-spacing: 0.05em; box-shadow: 0 1px 2px rgba(8,71,52,0.08); object-fit: cover; overflow: hidden; flex-shrink: 0; }
.pm-seal img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
.pm-title-seal { width: 80px; height: 80px; border-radius: 50%; object-fit: cover; border: 3px solid #e6e8e7; box-shadow: 0 2px 8px rgba(8,71,52,0.10); display: block; }

.pm-org { font-size: 10px; text-transform: uppercase; letter-spacing: 0.16em; font-weight: 600; color: #7a857f; }
.pm-meeting-title { font-size: 14px; font-weight: 600; color: #0f1614; line-height: 1.3; }

.pm-tabs { display: flex; gap: 6px; }
.pm-tab-btn { padding: 8px 18px; border-radius: 8px; font-size: 13px; font-weight: 500; transition: all 0.15s; color: #4b5651; border: none; background: transparent; cursor: pointer; }
.pm-tab-btn:hover { background: rgba(8,71,52,0.05); color: #0f1614; }
.pm-tab-btn.active { background: var(--gv-brand-900); color: #fff; font-weight: 600; }

/* The video column is fixed, so the width freed by dropping the left rail would
   all have gone to the text. Split it: the video gets bigger too. */
.pm-grid { display: grid; grid-template-columns: 1fr 620px; gap: 24px; align-items: start; }
/* .pm-grid.no-video collapsed this to one centred column when a meeting had a transcript
   but no video. Nothing reaches that state any more (#491): the column now holds a poster
   instead of being dropped, and the only case with neither video nor transcript returns
   before it builds a grid at all. */
.pm-video-col { position: sticky; top: 92px; align-self: start; }
@media (max-width: 900px) {
    .pm-grid { grid-template-columns: 1fr; }
    .pm-video-col { position: sticky; top: 76px; z-index: 20; }
}

.pm-agenda-box { background: #f4f5f6; border: 1px solid #e6e8e7; border-radius: 16px; padding: 8px; }

/* Meeting view switcher — a tab strip across the top, aligned right.
   It used to be a 200px left rail, which cost the content 228px of width for
   four or five words. Sticky so switching views stays reachable down a
   three-hour transcript. */
.pm-layout { margin-top: 14px; }
/* The tabs sit on the title's own line, bottom-aligned so they run with the
   date/time rather than opening a band of their own between the title and the
   content. The rule under them belongs to the row now, not to the title. */
.pm-title-row {
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: 16px 32px; flex-wrap: wrap;
    border-bottom: 1px solid #e6e8e7; margin-bottom: 10px;
}
.pm-sidenav {
    flex: 0 0 auto;
    display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 4px;
    padding-bottom: 22px;
}
.pm-sidenav-item { display: inline-flex; align-items: center; gap: 9px; font-size: 0.9rem; font-weight: 600; color: #4b5651; background: transparent; border: 1px solid transparent; border-radius: 10px; padding: 8px 14px; cursor: pointer; text-align: left; white-space: nowrap; transition: 0.15s; }
.pm-sidenav-item:hover { background: #eef1ef; color: var(--gv-brand-900); }
.pm-sidenav-item.active { background: var(--gv-brand-900); color: #fff; }
.pm-sidenav-item:focus-visible { outline: 2px solid var(--gv-brand-900); outline-offset: 2px; }
.pm-sidenav-item i { width: 16px; text-align: center; font-size: 0.82rem; }
.pm-sidenav-sep { width: 1px; align-self: stretch; background: #e3e6e5; margin: 4px 8px; }
.pm-download-btn { display: inline-flex; align-items: center; gap: 9px; font-size: 0.86rem; font-weight: 600; color: var(--gv-brand-900); background: #cef17b; border: none; border-radius: 10px; padding: 8px 14px; cursor: pointer; white-space: nowrap; transition: 0.15s; }
.pm-download-btn:hover { filter: brightness(0.96); }
.pm-download-btn i { width: 16px; text-align: center; }
/* Count badge on the Files nav item */
.pm-sidenav-badge { font-size: 0.72rem; font-weight: 700; background: #eef1ef; color: #4b5651; border-radius: 999px; padding: 1px 8px; }
.pm-sidenav-item.active .pm-sidenav-badge { background: rgba(255, 255, 255, 0.22); color: #fff; }
/* Files view rows */
.pm-file-row { display: flex; align-items: center; gap: 14px; padding: 13px 16px; border-bottom: 1px solid #eef1ef; text-decoration: none; transition: 0.15s; }
.pm-file-row:last-child { border-bottom: none; }
.pm-file-row:hover { background: #f7faf3; }
.pm-file-icon { font-size: 1.05rem; color: #7a857f; width: 20px; text-align: center; flex-shrink: 0; }
.pm-file-row:hover .pm-file-icon { color: var(--gv-brand-900); }
.pm-file-body { flex: 1; min-width: 0; }
.pm-file-name { font-size: 0.9rem; font-weight: 600; color: #0f1614; word-break: break-word; }
.pm-file-letter { display: inline-block; font-size: 0.66rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--gv-brand-900); background: #cef17b; border-radius: 5px; padding: 2px 7px; margin-right: 8px; vertical-align: 1px; }
.pm-file-context { font-size: 0.76rem; color: #7a857f; margin-top: 2px; }
.pm-file-size { font-size: 0.76rem; color: #7a857f; flex-shrink: 0; white-space: nowrap; }
.pm-file-action { font-size: 0.78rem; color: #c2cbc6; flex-shrink: 0; }
.pm-file-row:hover .pm-file-action { color: var(--gv-brand-900); }
.pm-main { min-width: 0; }
/* Full width, same as the Recording view and the header above it. This used to
   cap at 880px, which left the Agenda and Minutes as a narrow column pinned to
   the left of a much wider page. */
.pm-doc { max-width: none; }
/* Written minutes (the minutes-tool output), rendered as a document */
/* Full width, same as the Agenda. .pm-doc's cap came off with the left rail, but
   the minutes document carried its own and stayed a narrow column. */
.pm-minutes-doc { background: #fff; border: 1px solid #e6e8e7; border-radius: 16px; padding: 30px 34px; font-size: 0.9rem; line-height: 1.72; color: #1a2420; box-shadow: 0 1px 3px rgba(16,22,20,.05); }
.pm-minutes-doc .section-title { font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; font-size: 0.82rem; color: var(--gv-brand-900); margin: 20px 0 8px; }
.pm-minutes-doc h1, .pm-minutes-doc h2, .pm-minutes-doc h3, .pm-minutes-doc h4 { font-weight: 700; color: #0f1614; margin: 18px 0 8px; line-height: 1.3; }
.pm-minutes-doc p { margin-bottom: 11px; }
.pm-minutes-doc ul, .pm-minutes-doc ol { margin: 8px 0 12px 22px; }
.pm-minutes-doc li { margin-bottom: 5px; }
.pm-minutes-doc table { width: 100%; border-collapse: collapse; margin: 10px 0; }
.pm-minutes-doc td, .pm-minutes-doc th { padding: 5px 8px; }
.pm-minutes-doc img { max-width: 100%; height: auto; }
.pm-minutes-doc .header, .pm-minutes-doc h1:first-child { text-align: center; }
/* Nodes of the published minutes document (minutesDoc) */
.pm-md-header { padding-bottom: 14px; margin-bottom: 6px; border-bottom: 1px solid #eef1ef; }
.pm-md-header p { margin-bottom: 4px; }
/* A blank line between two lines of the header takes up a line, as it does on the page (#1163): an empty <p> has no
   height. One at its start or end stays as it was: a blank line typed under the title has no title above it here. */
.pm-md-header p:not(:empty) ~ p:empty:not(:last-child)::before { content: "\00a0"; }
.pm-md-section { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; color: var(--gv-brand-900); margin: 26px 0 10px; padding-bottom: 5px; border-bottom: 1px solid #e6e8e7; }
.pm-md-body { margin-bottom: 9px; }
/* The minutes' fonts, as the clerk set them on the Document tab (MB_ED_FONT_FAMILIES). */
.pm-minutes-doc.mb-doc-serif, .pm-minutes-doc .mb-font-serif { font-family: "Times New Roman", Times, serif; }
.pm-minutes-doc.mb-doc-mono, .pm-minutes-doc .mb-font-mono { font-family: "Courier New", Courier, monospace; }
.pm-minutes-doc .mb-font-sans { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; }
/* The fonts the PDF embeds are web fonts here too (#723), linked by _pmRenderMinutesDocument. */
.pm-minutes-doc.mb-doc-carlito, .pm-minutes-doc .mb-font-carlito { font-family: "Carlito", Calibri, sans-serif; }
.pm-minutes-doc.mb-doc-gelasio, .pm-minutes-doc .mb-font-gelasio { font-family: "Gelasio", Georgia, serif; }
.pm-minutes-doc.mb-doc-atkinson, .pm-minutes-doc .mb-font-atkinson { font-family: "Atkinson Hyperlegible", sans-serif; }
.pm-minutes-doc.mb-doc-publicsans, .pm-minutes-doc .mb-font-publicsans { font-family: "Public Sans", sans-serif; }
.pm-minutes-doc .mb-size-8 { font-size: 8pt; }
.pm-minutes-doc .mb-size-9 { font-size: 9pt; }
.pm-minutes-doc .mb-size-10 { font-size: 10pt; }
.pm-minutes-doc .mb-size-11 { font-size: 11pt; }
.pm-minutes-doc .mb-size-12 { font-size: 12pt; }
.pm-minutes-doc .mb-size-14 { font-size: 14pt; }
.pm-minutes-doc .mb-size-18 { font-size: 18pt; }
.pm-minutes-doc .mb-size-24 { font-size: 24pt; }
.pm-minutes-doc .mb-size-30 { font-size: 30pt; }
.pm-minutes-doc .mb-size-36 { font-size: 36pt; }
.pm-minutes-doc .mb-size-48 { font-size: 48pt; }
.pm-minutes-doc .mb-size-60 { font-size: 60pt; }
.pm-minutes-doc .mb-size-72 { font-size: 72pt; }
.pm-minutes-doc .mb-size-96 { font-size: 96pt; }
.pm-md-body p:last-child { margin-bottom: 0; }
.pm-md-body ul, .pm-md-action ul { list-style-type: disc; padding-left: 1.4em; margin: 5px 0; }
.pm-md-body ol, .pm-md-action ol { list-style-type: decimal; padding-left: 1.4em; margin: 5px 0; }
/* Nested lists as the editor shows them (Dom, 2026-09-24): 1. a. i., and disc, circle, square. */
.pm-md-body ol ol { list-style-type: lower-alpha; } .pm-md-body ol ol ol { list-style-type: lower-roman; }
.pm-md-body ul ul { list-style-type: circle; } .pm-md-body ul ul ul { list-style-type: square; }
.pm-md-body li, .pm-md-action li { margin-bottom: 3px; }
.pm-md-body u, .pm-md-action u, .pm-md-item-head u { text-decoration: underline; }
/* Indentation the clerk set in the Document editor (#609), half an inch a step as on the page. */
.pm-md-body .mb-fli { text-indent: 2em; }
:is(.pm-md-body, .pm-md-item-head) .mb-tab { white-space: pre; tab-size: 2em; -moz-tab-size: 2em; }
.pm-md-body .mb-indent-1 { margin-left: 2em; }
.pm-md-body .mb-indent-2 { margin-left: 4em; }
.pm-md-body .mb-indent-3 { margin-left: 6em; }
.pm-md-body .mb-indent-4 { margin-left: 8em; }
.pm-md-body .mb-indent-5 { margin-left: 10em; }
.pm-md-body .mb-indent-6 { margin-left: 12em; }
.pm-md-body .mb-indent-7 { margin-left: 14em; }
.pm-md-body .mb-indent-8 { margin-left: 16em; }
/* Colours, highlights, horizontal lines and tables the clerk set in the Document editor (#609).
   Colour, highlight and spacing reach every part of the minutes -- titles, the header, action
   lines -- not only item bodies (code review, 2026-09-22). */
.pm-minutes-doc .mb-c-black { color: #000000; }
.pm-minutes-doc .mb-c-dgray { color: #404040; }
.pm-minutes-doc .mb-c-gray { color: #7f7f7f; }
.pm-minutes-doc .mb-c-lgray { color: #bfbfbf; }
.pm-minutes-doc .mb-c-dred { color: #c00000; }
.pm-minutes-doc .mb-c-red { color: #ff0000; }
.pm-minutes-doc .mb-c-orange { color: #e36c09; }
.pm-minutes-doc .mb-c-gold { color: #bf8f00; }
.pm-minutes-doc .mb-c-green { color: #00b050; }
.pm-minutes-doc .mb-c-dgreen { color: #375623; }
.pm-minutes-doc .mb-c-lblue { color: #00b0f0; }
.pm-minutes-doc .mb-c-blue { color: #0070c0; }
.pm-minutes-doc .mb-c-dblue { color: #002060; }
.pm-minutes-doc .mb-c-purple { color: #7030a0; }
.pm-minutes-doc .mb-hl-yellow { background-color: #fff2a8; }
.pm-minutes-doc .mb-hl-green { background-color: #ccf2c4; }
.pm-minutes-doc .mb-hl-teal { background-color: #c4eef2; }
.pm-minutes-doc .mb-hl-blue { background-color: #cce0ff; }
.pm-minutes-doc .mb-hl-purple { background-color: #e6d9ff; }
.pm-minutes-doc .mb-hl-pink { background-color: #ffd6ec; }
.pm-minutes-doc .mb-hl-red { background-color: #ffd6d6; }
.pm-minutes-doc .mb-hl-orange { background-color: #ffe0b2; }
.pm-minutes-doc .mb-hl-gray { background-color: #e5e5e5; }
.pm-md-body hr { border: 0; border-top: 1px solid #6b7280; margin: 10px 0; }
.pm-md-body table { border-collapse: collapse; width: 100%; margin: 8px 0; }
.pm-md-body td, .pm-md-body th { border: 1px solid #1f2937; padding: 4px 8px; vertical-align: top; text-align: left; }
.pm-md-body th { font-weight: 700; background: #f3f4f6; }
.pm-md-body td > p, .pm-md-body th > p { margin: 0; }
/* Line and paragraph spacing the clerk set in the Document editor, scaled as on the page; space
   before and after as padding, so neighbouring paragraphs' spaces add up rather than collapse. */
.pm-minutes-doc .mb-lh-100 { line-height: 1.217; }
.pm-minutes-doc .mb-lh-125 { line-height: 1.522; }
.pm-minutes-doc .mb-lh-150 { line-height: 1.826; }
.pm-minutes-doc .mb-lh-175 { line-height: 2.13; }
.pm-minutes-doc .mb-lh-200 { line-height: 2.435; }
.pm-minutes-doc .mb-lh-250 { line-height: 3.043; }
.pm-minutes-doc .mb-lh-300 { line-height: 3.652; }
.pm-minutes-doc .mb-sb-0 { padding-top: 0pt; } .pm-minutes-doc .mb-sa-0 { padding-bottom: 0pt; }
.pm-minutes-doc .mb-sb-4 { padding-top: 4pt; } .pm-minutes-doc .mb-sa-4 { padding-bottom: 4pt; }
.pm-minutes-doc .mb-sb-6 { padding-top: 6pt; } .pm-minutes-doc .mb-sa-6 { padding-bottom: 6pt; }
.pm-minutes-doc .mb-sb-8 { padding-top: 8pt; } .pm-minutes-doc .mb-sa-8 { padding-bottom: 8pt; }
.pm-minutes-doc .mb-sb-10 { padding-top: 10pt; } .pm-minutes-doc .mb-sa-10 { padding-bottom: 10pt; }
.pm-minutes-doc .mb-sb-12 { padding-top: 12pt; } .pm-minutes-doc .mb-sa-12 { padding-bottom: 12pt; }
.pm-minutes-doc .mb-sb-18 { padding-top: 18pt; } .pm-minutes-doc .mb-sa-18 { padding-bottom: 18pt; }
.pm-minutes-doc .mb-sb-24 { padding-top: 24pt; } .pm-minutes-doc .mb-sa-24 { padding-bottom: 24pt; }
.pm-minutes-doc .mb-sb-36 { padding-top: 36pt; } .pm-minutes-doc .mb-sa-36 { padding-bottom: 36pt; }
.pm-md-body p.mb-action {
    position: relative;
    margin-top: 10px;
    padding-top: 9px;
    padding-left: 3.6rem;
    border-top: 1px solid #eef1ef;
    font-weight: 600;
    color: #1a2420;
}
.pm-md-body p.mb-action::before {
    content: 'Action';
    position: absolute;
    left: 0;
    top: 9px;
    font-size: 0.62rem;
    font-weight: 800;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: #7a857f;
}
.pm-md-item { margin: 0 0 20px; }
.pm-md-item-head { font-weight: 700; color: #0f1614; margin-bottom: 6px; display: flex; gap: 10px; align-items: baseline; }
.pm-md-num { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-weight: 700; color: #7a857f; flex-shrink: 0; }
.pm-md-mo { font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: #7a857f; text-align: right; margin-bottom: 2px; }
.pm-md-motion { font-style: italic; color: #3a443f; margin: 14px 0 4px; }
.pm-md-action { display: flex; gap: 10px; align-items: baseline; margin-top: 9px; padding-top: 9px; border-top: 1px solid #eef1ef; font-weight: 600; color: #1a2420; }
.pm-md-action-tag { font-size: 0.62rem; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: #7a857f; flex-shrink: 0; }
.pm-md-exref { font-size: 0.8rem; font-style: italic; color: #7a857f; margin-top: 5px; }
.pm-md-exhibits { border: 1px solid #e6e8e7; border-radius: 12px; overflow: hidden; }
.pm-md-exhibit { display: flex; align-items: center; gap: 13px; padding: 11px 14px; border-bottom: 1px solid #eef1ef; text-decoration: none; transition: 0.15s; }
.pm-md-exhibit:last-child { border-bottom: none; }
.pm-md-exhibit:hover { background: #f7faf3; }
.pm-md-exhibit:hover .pm-file-icon, .pm-md-exhibit:hover .pm-file-action { color: var(--gv-brand-900); }
.pm-md-sign { margin-top: 30px; padding-top: 18px; border-top: 1px solid #e6e8e7; }
.pm-md-approval { font-style: italic; margin-bottom: 22px; }
.pm-md-sign-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 26px 24px; }
.pm-md-sign-line { border-top: 1px solid #4b5651; padding-top: 6px; font-size: 0.82rem; color: #3a443f; }
@media (max-width: 640px) {
    .pm-minutes-doc { padding: 22px 18px; }
    .pm-md-sign-grid { grid-template-columns: 1fr; }
}
.pm-transcript-card { margin-top: 22px; background: #fff; border: 1px solid #e6e8e7; border-radius: 16px; padding: 18px 20px; }
.pm-transcript-card h3 { font-size: 0.7rem; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; color: #7a857f; margin-bottom: 10px; }
.pm-transcript-body { font-size: 0.86rem; line-height: 1.7; color: #3a443f; white-space: pre-wrap; max-height: 540px; overflow: auto; }

/* ── Public transcript view ─────────────────────────────────────────────────
   Searchable, click-to-seek meeting transcript on the citizen portal. The
   search bar sticks to the top of the panel because the point of it is finding
   a word in a six-hour meeting — it has to stay reachable while scrolling. */
.pt-panel { background: #fff; border: 1px solid #e6e8e7; border-radius: 16px; overflow: hidden; }
.pt-toolbar { position: sticky; top: 0; z-index: 5; display: flex; align-items: center; gap: 12px; padding: 12px 16px; background: #fff; border-bottom: 1px solid #eceeed; }
.pt-search-wrap { position: relative; flex: 1; min-width: 0; }
.pt-search-icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); font-size: 0.78rem; color: #66706b; pointer-events: none; }
.pt-search { width: 100%; font-size: 0.88rem; color: #23302b; background: #f6f8f7; border: 1px solid #e2e6e4; border-radius: 10px; padding: 9px 12px 9px 34px; outline: none; transition: 0.15s; }
.pt-search:focus { background: #fff; border-color: var(--gv-brand-900); box-shadow: 0 0 0 3px rgba(8, 71, 52, 0.1); }
.pt-search::-webkit-search-cancel-button { cursor: pointer; }
.pt-search-nav { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.pt-search-nav > span:last-child:not(:empty) { display: inline-flex; align-items: center; gap: 6px; }
.pt-count { font-size: 0.76rem; font-weight: 600; color: #66706b; font-variant-numeric: tabular-nums; white-space: nowrap; }
.pt-count:empty { display: none; }
.pt-count.pt-none { color: #b04a3a; }
.pt-nav-btn { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 7px; border: 1px solid #e2e6e4; background: #fff; color: #4b5651; font-size: 0.68rem; cursor: pointer; transition: 0.15s; }
.pt-nav-btn:hover { background: var(--gv-brand-900); border-color: var(--gv-brand-900); color: #fff; }
.pt-nav-btn:focus-visible { outline: 2px solid var(--gv-brand-900); outline-offset: 2px; }

/* A scrollable region has to be reachable by keyboard, so it carries tabindex=0
   and needs a focus ring to show where the caret went. */
.pt-body { max-height: calc(100vh - 220px); overflow-y: auto; padding: 6px 0 14px; }
.pt-body:focus-visible { outline: 2px solid var(--gv-brand-900); outline-offset: -2px; }
.pt-note { padding: 40px 20px; text-align: center; font-size: 0.86rem; color: #66706b; }

.pt-seg { padding: 2px 16px; border-left: 3px solid transparent; transition: background 0.15s, border-color 0.15s; }
.pt-seg.playing { background: #f2f8ec; border-left-color: var(--gv-brand-900); }
.pt-speaker { margin-top: 14px; margin-bottom: 2px; font-size: 0.72rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--gv-brand-900); }
.pt-line { display: flex; align-items: baseline; gap: 10px; }
.pt-time { flex-shrink: 0; width: 52px; text-align: right; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.72rem; font-variant-numeric: tabular-nums; color: #66706b; background: none; border: none; padding: 0; cursor: pointer; transition: color 0.15s; }
.pt-time:hover { color: var(--gv-brand-900); text-decoration: underline; }
.pt-time:focus-visible { outline: 2px solid var(--gv-brand-900); outline-offset: 2px; border-radius: 3px; color: var(--gv-brand-900); }
.pt-time-none { cursor: default; }
.pt-text { flex: 1; min-width: 0; margin: 0; font-size: 0.88rem; line-height: 1.65; color: #3a443f; }
.pt-seg.seekable .pt-text { cursor: pointer; }
.pt-seg.seekable .pt-text:hover { color: var(--gv-brand-900); }

.pt-hit { background: #fdf0a8; color: inherit; border-radius: 2px; padding: 0 1px; }
.pt-hit.current { background: #f6c344; box-shadow: 0 0 0 2px rgba(246, 195, 68, 0.45); }

/* "Jump to an item" — under the video, once the transcript has taken over the
   reading column. Only items the timeline placed appear here. */
.pm-jump-card { margin-top: 12px; max-height: 340px; overflow-y: auto; background: #fff; border: 1px solid #e6e8e7; border-radius: 14px; }
.pm-jump-head { position: sticky; top: 0; background: #fff; padding: 10px 14px; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: #66706b; border-bottom: 1px solid #eceeed; }
.pm-jump-row { display: flex; align-items: baseline; gap: 10px; width: 100%; padding: 8px 14px; background: none; border: none; border-bottom: 1px solid #f2f4f3; text-align: left; cursor: pointer; transition: background 0.15s; }
.pm-jump-row:last-child { border-bottom: none; }
.pm-jump-row:hover { background: #f2f8ec; }
.pm-jump-row:focus-visible { outline: 2px solid var(--gv-brand-900); outline-offset: -2px; }
.pm-jump-num { flex-shrink: 0; min-width: 20px; font-size: 0.74rem; font-weight: 700; color: #66706b; font-variant-numeric: tabular-nums; }
.pm-jump-title { flex: 1; min-width: 0; font-size: 0.84rem; line-height: 1.45; color: #3a443f; }
.pm-jump-time { flex-shrink: 0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.72rem; font-variant-numeric: tabular-nums; color: #66706b; }

@media (max-width: 820px) {
    .pt-body { max-height: none; }
    .pt-time { width: 44px; }
}

@media (max-width: 820px) {
    /* Narrow enough that right-aligning would strand the tabs away from a
       thumb, and the divider before Download PDF has no room to read as one.
       Not sticky either: the header wraps to three lines here, so a second
       pinned bar would collide with it and eat a phone screen. */
    .pm-sidenav { position: static; justify-content: flex-start; gap: 6px; }
    .pm-sidenav-item { padding: 8px 11px; }
    .pm-sidenav-sep { display: none; }
}

/* Live status / chips */
.pm-live-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; padding: 3px 9px; border-radius: 999px; background: #fee2e2; color: #b91c1c; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; }
.pm-live-dot { width: 7px; height: 7px; border-radius: 50%; background: #ef4444; animation: pm-pulse 1.4s ease-in-out infinite; }
@keyframes pm-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.4; transform: scale(0.8); } }

.pm-status-chip { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; padding: 3px 9px; border-radius: 999px; background: #f4f5f6; color: #4b5651; font-weight: 500; }

.pm-members { display: flex; flex-wrap: wrap; gap: 6px; padding: 10px; }
.pm-member-chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; background: #fff; border: 1px solid #e6e8e7; border-radius: 999px; font-size: 12px; color: #0f1614; }
.pm-member-chip.absent { color: #9ca3af; text-decoration: line-through; background: #fafbfa; }
.pm-member-chip .pm-member-title { color: #7a857f; font-size: 11px; }

.pm-section-label { font-size: 10px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: var(--gv-brand-900); padding: 16px 4px 8px; display: flex; align-items: center; gap: 8px; }
.pm-section-label::after { content: ''; flex: 1; height: 1px; background: #e6e8e7; }
.pm-section-label-icon { color: var(--gv-brand-900); opacity: 0.6; }

/* Agenda items */
.pm-item { background: #fff; border: 1px solid transparent; border-radius: 10px; padding: 12px 14px; cursor: pointer; transition: all 0.15s; }
.pm-item:hover { border-color: #e6e8e7; }
.pm-item.expanded { background: #ecf7d2; border-color: #cef17b; cursor: default; }
.pm-item.live-active { background: #fef3c7; border-color: #facc15; }
.pm-item + .pm-item { margin-top: 4px; }

.pm-item-row { display: flex; align-items: center; gap: 14px; }
.pm-item-num { font-weight: 700; font-size: 13px; color: var(--gv-brand-900); min-width: 32px; }
.pm-item-title { flex: 1; font-size: 14px; color: #0f1614; overflow: hidden; text-overflow: ellipsis; }
.pm-item.expanded .pm-item-title { font-weight: 600; color: var(--gv-brand-900); }
.pm-expand-chevron { font-size: 10px; color: #b0b8b4; transition: transform 0.2s; flex-shrink: 0; }
.pm-item.expanded .pm-expand-chevron { transform: rotate(180deg); color: var(--gv-brand-900); }

/* Agenda item description rich-text editor */
.ag-desc-wrap { flex: 1; min-width: 0; }
.ag-desc-toolbar { display: none; align-items: center; gap: 2px; padding: 2px 3px; background: #fff; border: 1px solid #e2e8f0; border-radius: 4px; margin-bottom: 3px; flex-wrap: wrap; }
.ag-desc-wrap:focus-within .ag-desc-toolbar { display: flex; }
.ag-desc-btn { min-width: 20px; height: 20px; border-radius: 3px; font-size: 10px; display: flex; align-items: center; justify-content: center; color: #64748b; cursor: pointer; padding: 0 3px; border: none; background: transparent; line-height: 1; }
.ag-desc-btn:hover { background: #f1f5f9; color: #1e293b; }
.ag-desc-sep { width: 1px; height: 12px; background: #e2e8f0; margin: 0 1px; flex-shrink: 0; }
.ag-desc-content ul { list-style-type: disc; padding-left: 1.25em; margin: 2px 0; }
.ag-desc-content ol { list-style-type: decimal; padding-left: 1.25em; margin: 2px 0; }
.ag-desc-content li { margin-bottom: 1px; }

/* Minutes body boxes — restore the formatting the Tailwind reset strips, so what
   the clerk applies is what the clerk sees. Every editable box in the minutes
   document carries .mb-rich. */
.mb-rich ul { list-style-type: disc; padding-left: 1.25em; margin: 3px 0; }
.mb-rich ol { list-style-type: decimal; padding-left: 1.25em; margin: 3px 0; }
.mb-rich li { margin-bottom: 2px; }
.mb-rich strong, .mb-rich b { font-weight: 600; }
.mb-rich em, .mb-rich i { font-style: italic; }
.mb-rich u { text-decoration: underline; }
.mb-rich p { margin: 0 0 4px 0; }
.mb-rich p:last-child { margin-bottom: 0; }

/* Speakers tab — the voices that said only a word or two, behind a toggle. */
.ts-minor-wrap { margin-top: var(--gv-space-2); }
.ts-minor-wrap > .gv-rows { margin-top: var(--gv-space-2); }

/* The .ts-mic accordion that used to live here is gone. Each voice is a .gv-row now, and
   the design system's delegated listener owns the disclosure — a hand-animated panel
   inside gv-row's own panel was two disclosures arguing over one row. */

/* The inline "Add to board? → Voting member?" prompts slide in as each answer
   advances the flow. */
@keyframes tsStepSlide {
  from { opacity: 0; transform: translateX(14px); }
  to   { opacity: 1; transform: none; }
}
.ts-step-slide { animation: tsStepSlide .18s ease-out; }

@media (prefers-reduced-motion: reduce) {
  .ts-step-slide { animation-duration: 1ms; }
}

.pm-chip { display: inline-flex; align-items: center; gap: 5px; font-size: 10px; padding: 2px 8px; border-radius: 4px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; }
.pm-chip-action { background: var(--gv-brand-900); color: #fff; }
.pm-chip-info { background: #fff; color: #7a857f; border: 1px solid #e6e8e7; }
.pm-chip-timed { background: #cef17b; color: var(--gv-brand-900); }
.pm-chip-exec { background: #ede9fe; color: #5b21b6; }
.pm-chip-carried { background: #d1fae5; color: #065f46; }
.pm-chip-failed { background: #fee2e2; color: #991b1b; }
.pm-chip-tabled { background: #fed7aa; color: #9a3412; }
.pm-chip-noaction { background: #e5e7eb; color: #4b5563; }

.pm-ts-pill { font-feature-settings: "tnum"; font-weight: 600; color: var(--gv-brand-900); background: #fff; border: 1px solid #e6e8e7; padding: 3px 10px; border-radius: 6px; font-size: 11px; min-width: 56px; text-align: center; }
.pm-item.expanded .pm-ts-pill { background: var(--gv-brand-900); color: #fff; border-color: var(--gv-brand-900); }
.pm-ts-empty { color: #7a857f; background: #f4f5f6; border-style: dashed; }

.pm-speakers-btn { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; padding: 3px 10px; border-radius: 6px; background: #ede9fe; color: #5b21b6; border: 1px solid #ddd6fe; font-weight: 600; cursor: pointer; }
.pm-speakers-btn:hover { background: #ddd6fe; }

/* Expanded packet */
.pm-packet { background: #fff; border-top: 1px solid #cef17b; margin-top: 10px; border-radius: 0 0 8px 8px; padding: 16px 18px; }
.pm-packet-grid { display: grid; grid-template-columns: 130px 1fr; gap: 10px 24px; font-size: 12.5px; line-height: 1.55; }
.pm-packet-label { font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: #7a857f; padding-top: 2px; }
.pm-packet-value { color: #0f1614; }

.pm-attach { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; padding: 6px 11px; background: #f4f5f6; border: 1px solid #e6e8e7; border-radius: 8px; color: var(--gv-brand-900); font-weight: 500; transition: all 0.15s; text-decoration: none; }
.pm-attach:hover { background: #ecf7d2; border-color: #cef17b; }
.pm-attach-size { color: #7a857f; font-weight: 400; }

/* Vote result block */
.pm-vote { padding: 12px 14px; background: #fafbfa; border: 1px solid #e6e8e7; border-radius: 8px; margin-top: 10px; }
.pm-vote-result { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.pm-vote-narrative { font-size: 13px; color: #4b5651; line-height: 1.5; margin-bottom: 8px; }
.pm-member-votes { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 4px 12px; font-size: 12px; }
.pm-member-vote { display: flex; align-items: center; gap: 6px; }
.pm-member-vote-icon { width: 14px; height: 14px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; font-size: 9px; color: #fff; font-weight: 700; }
.pm-mv-yea { background: #10b981; }
.pm-mv-nay { background: #ef4444; }
.pm-mv-abstain { background: #9ca3af; }
/* Absent for the vote (#641). Amber, apart from Abstain's grey: the two are different facts. */
.pm-mv-absent { background: #b45309; }

/* Video card */
.pm-video-card { background: #fff; border: 1px solid #e6e8e7; border-radius: 16px; overflow: hidden; }
.pm-video-info { padding: 12px 16px; border-top: 1px solid #e6e8e7; display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.pm-info-card { background: #f4f5f6; border: 1px solid #e6e8e7; border-radius: 12px; padding: 14px; font-size: 12px; line-height: 1.6; color: #4b5651; margin-top: 12px; }

/* PDF preview card */
.pm-pdf-card { background: #fff; border: 1px solid #e6e8e7; border-radius: 16px; overflow: hidden; margin-top: 12px; }
.pm-pdf-header { padding: 10px 14px; border-bottom: 1px solid #e6e8e7; display: flex; align-items: center; gap: 8px; background: #fafbfa; }
.pm-pdf-name { flex: 1; min-width: 0; font-size: 12px; font-weight: 600; color: #0f1614; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pm-pdf-open-link { flex-shrink: 0; font-size: 11px; color: var(--gv-brand-900); font-weight: 500; text-decoration: none; display: inline-flex; align-items: center; padding: 3px 8px; border: 1px solid #e6e8e7; border-radius: 6px; transition: all 0.15s; white-space: nowrap; }
.pm-pdf-open-link:hover { background: #ecf7d2; border-color: #cef17b; }
.pm-pdf-close-btn { flex-shrink: 0; width: 24px; height: 24px; border-radius: 6px; border: 1px solid #e6e8e7; background: #f4f5f6; color: #7a857f; display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 10px; transition: all 0.15s; }
.pm-pdf-close-btn:hover { background: #fee2e2; border-color: #fca5a5; color: #991b1b; }
.pm-pdf-frame-wrap { width: 100%; height: 480px; background: #f4f5f6; }
.pm-pdf-iframe { width: 100%; height: 100%; border: none; display: block; }

/* Attachment button / active state */
.pm-attach { cursor: pointer; background: none; font-family: inherit; }
.pm-attach-preview-icon { font-size: 9px; color: #7a857f; margin-left: 2px; }
.pm-attach.pm-attach-active { background: #ecf7d2; border-color: #cef17b; color: var(--gv-brand-900); }
.pm-attach.pm-attach-active .pm-attach-preview-icon { color: var(--gv-brand-900); }

/* Footer */
.pm-footer { margin-top: 40px; padding: 24px 8px; border-top: 1px solid #e6e8e7; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; font-size: 11px; color: #7a857f; }
.pm-footer a { color: var(--gv-brand-900); font-weight: 600; }

/* Mobile sticky video */
@media (max-width: 900px) {
    .pm-grid > .pm-video-col {
        order: -1;
        margin: 0 -16px 12px;
        padding: 8px 16px;
        background: rgba(255,255,255,0.96);
        backdrop-filter: blur(8px);
        border-bottom: 1px solid #e6e8e7;
    }
}

/* Org portal hub — same visual language */
.pm-org-hero { background: linear-gradient(135deg, var(--gv-brand-900) 0%, #0d6647 100%); border-radius: 20px; color: #fff; padding: 28px; margin-bottom: 24px; }
.pm-meeting-card { background: #f4f5f6; border: 1px solid #e6e8e7; border-radius: 14px; padding: 18px; transition: all 0.15s; cursor: pointer; }
.pm-meeting-card:hover { background: #fff; border-color: #cef17b; transform: translateY(-1px); box-shadow: 0 4px 12px rgba(8,71,52,0.08); }
.pm-meeting-tab { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; padding: 4px 10px; border-radius: 6px; font-weight: 500; background: #fff; color: #4b5651; border: 1px solid #e6e8e7; transition: all 0.15s; }
.pm-meeting-tab:hover { background: var(--gv-brand-900); color: #fff; border-color: var(--gv-brand-900); }
.pm-meeting-tab.live { background: #fee2e2; color: #b91c1c; border-color: #fecaca; }
.pm-meeting-tab.live::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: #ef4444; animation: pm-pulse 1.4s ease-in-out infinite; }

/* Public meeting page — editorial title block */
/* The rule below the title belongs to .pm-title-row now, so that it runs the
   full width under the tabs too rather than stopping where the title stops. */
.pm-title-block { flex: 1 1 320px; min-width: 0; padding: 32px 4px 22px; }
.pm-breadcrumb { font-size: 12px; color: #7a857f; margin-bottom: 12px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pm-breadcrumb a { color: var(--gv-brand-900); font-weight: 500; text-decoration: none; transition: opacity 0.15s; }
.pm-breadcrumb a:hover { opacity: 0.7; }
.pm-breadcrumb-sep { color: #d1d5db; }
.pm-kicker { font-size: 11px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; color: var(--gv-brand-900); margin-bottom: 10px; }
.pm-headline { font-size: 28px; line-height: 1.1; letter-spacing: -0.02em; font-weight: 700; color: #0f1614; margin: 0; }
@media (min-width: 768px) { .pm-headline { font-size: 36px; } }
.pm-meta-row { font-size: 14px; color: #4b5651; margin-top: 12px; display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.pm-meta-row span { display: inline-flex; align-items: center; }
.pm-meta-row i { color: var(--gv-brand-900); margin-right: 6px; font-size: 13px; }
.pm-meta-sep { color: #d1d5db; }

/* ===== SPEAKERS: Roll call and the voices, ONE panel (Dom, 2026-09-22) =====
   They were two panels with 24px of page between them, and the gap was the problem: a
   clerk naming a voice is READING the roster to do it, so on a thirteen-voice meeting the
   attendance being checked against scrolled away exactly when it was wanted. One object
   from the tab strip down, with Roll call held at its top.

   The panel gives up its own padding, because its first two rows are BANDS and a band has
   to reach the edges — the content below carries it instead (.ts-roster__pad). */
.ts-roster {
    background: var(--gv-surface);
    border: var(--gv-border-width) solid var(--gv-border);
    border-radius: var(--gv-radius-lg);
    /* Not overflow:hidden. That would make this the sticky containing block AND clip the
       row menus that open past its edge; the corners are squared by .mw-dock at the top
       and the last child rounds its own at the foot. */
}
.ts-roster__pad { padding: var(--gv-space-4); }

/* THE SCROLLBAR IS THE CARD'S OWN (Dom, 2026-09-23), as on Motions, Discussions and Minutes.
   The roster sat inside the step's generic scroller, so the page-height bar ran down the
   gap outside the card. On the stage that scroller stops scrolling and hands its height
   down: the card fills it, the Roll call bar stays at the card's top, and .ts-roster__scroll
   -- everything under the bar -- scrolls itself, so the scrollbar starts below the bar the
   way Motions' and Discussions' start below their filter rows. Keyed on #ts-speaker-section
   so the Recording step, which shares that scroller, keeps its own. */
.gv-stage__main > div:has(> #ts-speaker-section) {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding-right: 0;
}
#ts-speaker-section { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
#ts-speaker-section > .ts-roster {
    flex: 1 1 auto; min-height: 0;
    display: flex; flex-direction: column;
    overflow: hidden;
}
.ts-roster__scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* ROLL CALL, PINNED. Sticky on the HEAD alone, not the section: opening Roll call on a
   twelve-member board would otherwise pin the whole roster and eat the viewport. The head
   holds the top while its own members scroll under it, the same way the voices do.

   top: 0 against the step's scroller (.gv-stage__main's overflow-y wrapper), which starts
   at the tab strip — so pinned is exactly where the band already sits at rest, and
   nothing appears to move when it engages. */
/* display: contents, and it is the whole mechanism rather than a tidy-up. A sticky element
   can only travel inside its PARENT'S BOX, and this section is just its head while Roll
   call is folded — so the head had nowhere to stick and scrolled away with it, measured at
   -206px on a 300px scroll. Dissolving the section's box makes .ts-roster the head's
   containing block, which is the full height of the panel, so the head holds the top while
   everything below it scrolls. The section's own border, radius and shadow go with the box
   and were already zeroed here; its class still carries the band's typography to the head,
   and every selector below still matches. */
.ts-roster__rc { display: contents; }
.ts-roster__rc > .gv-card__head {
    position: sticky;
    top: 0;
    z-index: 3;
    /* The band's own tint, which .mw-dock hands the panel's first head. Restated because
       a sticky row paints over the rows it passes and MUST be opaque — inheriting a
       transparent head would let the voice list show through it. */
    background: var(--gv-band);
    border-bottom: var(--gv-border-width) solid var(--gv-border);
}
/* A folded band drops its rule everywhere else (.is-shut), and must not here: pinned, the
   rule is the only thing between Roll call and the voice sliding under it. */
.ts-roster__rc.is-shut > .gv-card__head { border-bottom: var(--gv-border-width) solid var(--gv-border); }
/* AND THE BODY CLOSES WITH ONE TOO (Dom, 2026-09-22). Open, Roll call ends on a quiet note
   about the board's names and the filter row started straight after it with nothing
   between — the two bands were separated and the thing between them was not. The rule goes
   on the BODY rather than on top of the filter row, so it exists only while Roll call is
   open: shut, the head's own rule already does this job and a second would draw 2px. */
.ts-roster__rc > .gv-card__body { border-bottom: var(--gv-border-width) solid var(--gv-border); }

/* The head is a <header> now, holding the roll call's play control (#1117). It still opens
   and shuts on a press anywhere, so it still reads as pressable. The caret is the real
   button the keyboard reaches, drawn as the glyph it replaced, and its ::after gives it the
   same 28px target Motions' caret has (.mbmv button.ichev). */
.ts-rc-head { cursor: pointer; }
/* ONE WIDTH, open or shut (Vinny, 2026-10-24): Font Awesome's down chevron is 10px wide at this
   size and its right one 6.25 (measured), so every toggle slid the title beside it 3.75px — on
   Attendance's head and on Speakers'. A box as wide as the wider glyph, the glyph centred in it. */
.ts-rc-chev {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 1em;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-size: 10px;
    line-height: 1;
    color: var(--gv-text-muted);
    cursor: pointer;
}
.ts-rc-chev::after { content: ''; position: absolute; inset: -8px; }
.ts-rc-chev:hover { color: var(--gv-brand-fg); }
.ts-rc-chev:focus-visible {
    outline: var(--gv-focus-width) solid var(--gv-focus-color);
    outline-offset: var(--gv-focus-offset);
    border-radius: var(--gv-radius-sm);
}
/* The play control sits by the heading, not with the count at the far end: it is about the
   roll call, the count is about the boxes. Its own cursor, because the head's pointer
   promises a fold this control does not do. */
.ts-rc-play { display: inline-flex; flex: 0 0 auto; cursor: default; }

/* What the recording says about a member (#1133), in their row's last column, where a voice row
   has its VoicePrint (#1185): the control that plays their moment of the roll call, with what was
   said as its hover. It was a line of its own under the row (#1133), then a sentence on the row
   with a Mark button beside it (#1139). A reading with no moment to play keeps the sentence on a
   quiet glyph in the same place (.ts-att-said), a control-xs square so it lines up with the
   play controls above and below it. */
.ts-att-play { display: inline-flex; flex: 0 0 auto; }
/* Every play glyph in one column (Vinny, 2026-10-23): the cell is right-aligned, so a 16:20 used
 * to push its glyph left of every 0:56. The time is mono, so 5ch holds anything to 59:59; an
 * h:mm:ss, which a roll call never is, still grows. */
.ts-att-play .gv-play__time { min-width: 5ch; text-align: right; }
/* A person's share of the speaking time (mbAttendanceShares), in the voice row's own small type,
 * the brand green the settled case has always had here. Its column is .ts-att-list's. */
.ts-att-share { display: inline-flex; align-items: center; flex: 0 0 auto; font-size: var(--gv-text-xs); font-variant-numeric: tabular-nums; }
.ts-att-said {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--gv-control-xs);
    height: var(--gv-control-xs);
    font-size: var(--gv-text-xs);
    color: var(--gv-text-subtle);
    cursor: help;
}
/* flex-wrap: with Add a person on the same line (#1139), Apply can run out of room in a
   narrow column; it drops to a line of its own rather than squeezing the labels. */
.ts-att-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--gv-space-3); margin-top: var(--gv-space-2); }
.ts-att-none { margin-right: auto; font-size: 11px; color: var(--gv-text-muted); }
/* Add a person (#1139): the first thing on the actions line under the members, held to the
   left so the recording's actions stay on the right, where they were. The small ghost button's
   12px padding already lines its icon up with the names in the rows above. "Doesn't say who was
   there" normally takes the left; beside Add it sits with Read again instead. */
.ts-rc-add { margin-right: auto; }
.ts-rc-add ~ .ts-att-none { margin-right: 0; }
/* On the head, beside the count, while the band is shut: the one thing in that line asking
   the clerk to do something. */
.ts-att-review { color: var(--gv-warning-fg); font-weight: 600; }

/* The second band: the SPEAKERS HEAD (mbSpeakersHeadHtml, Vinny, 2026-10-24), edge to edge and
   ruled like Attendance's, with its caret and title. It was the voices' filter row with no
   heading; the filter is inside it now, while it's open.
   position: relative for .gv-busy-bar along its bottom edge (#1147), which the filter inside
   hands up to it (position: static there). */
.ts-voices-head {
    position: relative;
    cursor: pointer;
    /* The band's grey, which the filter row did not have at all (Dom, 2026-09-22): Roll call
       above it was tinted and this was plain white, so the step's two rows of chrome did
       not match each other. */
    background: var(--gv-band);
    border-bottom: var(--gv-border-width) solid var(--gv-border);
}
/* Shut, it is the panel's last row, and the panel's own border closes it. */
.ts-voices-head.is-shut { border-bottom: 0; }
/* THE SAME HEIGHT OPEN OR SHUT, so nothing jumps (Vinny, 2026-10-24). Open, the search box made
 * the head 61px; shut, with only the count, it was 45, and the caret and title moved up 8px under
 * the pointer that had just pressed them. The head holds a control's height either way, and the
 * search box (below) is held to it. */
.ts-voices-head { min-height: calc(var(--gv-control-md) + 2 * var(--gv-space-3)); }
/* The filter takes the rest of the head's line. .gv-filter carries a bottom padding for the
   standalone case; in the head the head's padding replaces it. Its controls keep their own
   cursors (mbVoicesHeadClick lets them be). */
.ts-voices-head > .gv-filter { position: static; flex: 1 1 auto; min-width: 0; margin: 0; padding: 0; cursor: default; }
/* ONE LINE, beside the recording too (~610px, measured): the title and chips keep their size and
 * the search gives way, down to 6rem, rather than the row wrapping its chips under it. */
.ts-voices-head > .gv-card__title { flex: 0 0 auto; white-space: nowrap; }
.ts-voices-head > .gv-filter { flex-wrap: nowrap; }
/* 8rem at the least, so "Filter speakers" is never cut short; a control's height, so the head is
 * no taller open than shut. */
.ts-voices-head .gv-filter__search { flex: 1 1 9rem; min-width: 8rem; height: var(--gv-control-md); padding-top: 0; padding-bottom: 0; }
.ts-voices-head #ts-speaker-chips { flex: 0 0 auto; }
/* The ⋯ AT THE RIGHT EDGE, where the other steps put theirs (Dom, 2026-09-22). Motions
   pins it with .gv-filterbar__more's own margin-left:auto and Discussions' row is wide
   enough that it lands there anyway; this step has three chips and a short search box, so
   without the rule the menu sat against "Assigned" with half the row empty after it — the
   same control in a different place on the one step in the middle of the three.

   Last-child rather than by id: it is the row's trailing control that belongs on the edge,
   whatever the step later puts there. */
.ts-voices-head > .gv-filter > .gv-btn:last-child { margin-left: auto; }
/* Undo merge sits between the two bands when a merge has just happened. It is neither, so
   it gets the content padding rather than reaching the edges. */
.ts-roster__scroll > .ts-undo-merge { padding: var(--gv-space-3) var(--gv-space-4) 0; }

/* ===== MEETING WORKSPACE: the agenda table's head (#665) =====
   The step's ⋯ lives in this row now, and the column labels are worth keeping in view, so
   this was written as `top: var(--mw-head-h)` to pin the row under the meeting heading at
   the same measured height the toolbar used to.

   IT CANNOT PIN THERE, AND top HAD TO GO BACK TO 0. A sticky element offsets from its
   nearest SCROLLING ancestor, and this table sits inside a `.overflow-x-auto` wrapper —
   which makes that wrapper the scroll container, not the viewport (overflow-x: auto
   computes overflow-y to auto as well; there is no way to have one axis scroll and the
   other stay visible). So --mw-head-h was measured from the top of the table's own box
   and pushed the header row 94px DOWN into the agenda, where it painted over the second
   and third lines. It looked exactly like a rendering glitch and was reported as one.

   top: 0 makes it inert rather than wrong: the wrapper never scrolls vertically, so the
   head simply sits at the top of the table. Keeping `position: sticky` and the background
   costs nothing and means the row is already correct the day the table gets a scroller of
   its own — which is what the other four steps have (.gv-stage), and what this one would
   need for a head that genuinely follows a 60-row agenda.

   The cells carry the background, not the row: a <tr> cannot be a stacking context for a
   sticky position, so the grey would scroll away and leave the labels over the rows. */
.import-spreadsheet-table thead th {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--gv-band);
}
/* ===== REVIEW AGENDA: the card's top row (Dom, 2026-09-23) =====
   Any change requests waiting on the left, and on the right "DRAFT | Approve Agenda" (or
   "APPROVED | Revert to Draft") as one joined control, then the step's ⋯, the way Minutes
   carries them on its editor's menu row. The join is .gv-status-join in components.css,
   shared with Minutes (#843). They were on the tab row, far from the rows they are about;
   the ⋯ was in the column headings. Filled by agStatusBarHtml; empty — and gone — while the
   start panel is the whole screen. The buttons are the menu row's size. */
.ag-statusbar {
    display: flex;
    align-items: center;
    gap: var(--gv-space-2);
    padding: var(--gv-space-2) var(--gv-space-3);
    border-bottom: var(--gv-border-width) solid var(--gv-border);
}
.ag-statusbar:empty { display: none; }
.ag-statusbar__state { display: inline-flex; align-items: center; gap: var(--gv-space-2); min-width: 0; }
.ag-statusbar__end { margin-left: auto; display: inline-flex; align-items: center; gap: var(--gv-space-1); flex: none; }
.ag-statusbar .gv-btn {
    padding: calc(var(--gv-space-1) / 2) var(--gv-space-2);
    gap: var(--gv-space-1);
    font-size: var(--gv-text-xs);
    line-height: var(--gv-leading-tight);
    min-height: calc(var(--gv-text-xs) * var(--gv-leading-tight) + var(--gv-space-1) + 2 * var(--gv-border-width));
}
.ag-statusbar .gv-btn i { font-size: var(--gv-text-2xs); }
/* Approve Agenda's and Revert to Draft's colours are the joined control's, shared with Minutes
   (.gv-status-join in components.css, #843): nothing here, or the two screens drift. */

/* ===== MEETING WORKSPACE: sticky toolbar (#603) =====
   Review Agenda's toolbar pins directly under the sticky meeting heading, so Approve,
   PDF and Undo stay in reach down a long agenda. Only that step: the other five sit in
   a viewport-locked .gv-stage whose toolbars are already fixed in place, and several of
   them live inside an inner scroller, where a sticky offset would shove the bar down.
   top is the heading's live height (_mwWatchHeadHeight in app.js). z-index 20 keeps it
   under the heading (z-30).

   NO -20px/20px PAIR any more (#665). It reached up over the heading's mb-5 and painted
   that strip the page colour, so nothing scrolled visibly through the gap while the bar
   was pinned. The bar docks to the heading now and the mb-5 is gone — so the pair had
   nothing left to paint over and was simply 20px of padding holding the bar off the tabs
   it is supposed to hang from. It is the one thing that kept Review Agenda undocked while
   the other five steps moved.

   THE OVERLAP SURVIVES AT 2px, and it was tried at zero first. `top` is a MEASURED value
   -- _mwWatchHeadHeight writes --mw-head-h from a getBoundingClientRect, and the heading
   is 38.5px, not 38 -- so the bar's top and the heading's bottom meet on a fraction.
   Measured flush at rest and while pinned, but a hairline of the rows behind is what a
   sub-pixel disagreement between a sticky offset and a layout edge looks like, and it is
   the sort of thing that shows at one zoom level and not the next. Two pixels of reach,
   painted the page colour, costs nothing and cannot open.

   The background is what does that painting, which is why it is still here: the wrapper
   is otherwise exactly the bar's own box, and the bar is an opaque white card that paints
   itself. It is a LITERAL and not a token on purpose -- it has to equal the heading's own
   backdrop, which is Tailwind's bg-gray-50 (#f9fafb) on #meetings-detail-heading, and the
   nearest token is --gv-paper at #fafaf7, a warmer stop that would show as a seam exactly
   where this exists to hide one. Tokenising it means moving the heading and the body onto
   --gv-paper together, which is a page-wide colour decision and not this issue's. */
.mw-sticky-toolbar {
    position: sticky;
    top: calc(var(--gv-session-h, 0px) + var(--mw-head-h, 0px) - 2px);   /* under the heading, which is under the band (#1253) */
    z-index: 20;
    margin-top: -2px;
    padding-top: 2px;
    background: #f9fafb;
}

/* ===== PDF AGENDA IMPORT ===== */
.import-drop-zone {
    border: 2px dashed #d1d5db;
    border-radius: 12px;
    padding: 36px 24px;
    text-align: center;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
    background: #fafafa;
}
.import-drop-zone.drag-over {
    border-color: #3b5bdb;
    background: #eef2ff;
}
.import-drop-zone:hover { border-color: #9ca3af; }

.import-spreadsheet-table { border-collapse: collapse; }
.import-spreadsheet-table .import-th {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.import-spreadsheet-table td { border-bottom: 1px solid #f1f5f9; vertical-align: top; }
.import-spreadsheet-table tbody tr:last-child td { border-bottom: none; }

.import-section-row td { background: #f8fafc; border-bottom: 2px solid #e2e8f0 !important; }
.import-section-row:hover td { background: #f1f5f9; }

.import-item-row:hover td { background: #fafafa; }

.import-cell[contenteditable="true"] {
    outline: none;
    cursor: text;
    min-height: 20px;
    display: block;
    padding: 6px 8px;
    border-radius: 4px;
    line-height: 1.4;
    white-space: pre-wrap;
    word-break: break-word;
}
.import-cell[contenteditable="true"]:focus {
    background: #eff6ff;
    box-shadow: 0 0 0 2px #3b82f6;
}

.import-type-low { border-color: #f59e0b !important; }
.import-badge-warn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px; height: 16px;
    border-radius: 50%;
    background: #f59e0b;
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    margin-left: 4px;
    cursor: default;
    flex-shrink: 0;
}

.import-drag-handle {
    cursor: grab;
    color: #cbd5e1;
    padding: 4px 6px;
    font-size: 12px;
    line-height: 1;
}
.import-drag-handle:active { cursor: grabbing; }

.import-delete-row {
    background: none;
    border: none;
    color: #d1d5db;
    cursor: pointer;
    padding: 4px 6px;
    border-radius: 4px;
    font-size: 13px;
    line-height: 1;
    transition: color 0.1s, background 0.1s;
}
.import-delete-row:hover { color: #ef4444; background: #fef2f2; }

.import-section-name-input {
    font-weight: 600;
    font-size: 13px;
    border: none;
    background: transparent;
    outline: none;
    padding: 2px 4px;
    border-radius: 4px;
    color: #1e293b;
    min-width: 200px;
}
.import-section-name-input:focus { background: #eff6ff; box-shadow: 0 0 0 2px #3b82f6; }

.import-type-select {
    font-size: 11px;
    border: 1px solid #e2e8f0;
    border-radius: 6px;
    padding: 2px 6px;
    background: #fff;
    color: #475569;
    cursor: pointer;
    outline: none;
}
.import-type-select:focus { border-color: #3b82f6; }

/* editable cells + drag handle for the unified builder */
.u-cell {
    outline: none;
    border-radius: 4px;
    padding: 2px 4px;
    min-height: 1.2em;
}
.u-cell[contenteditable="true"]:hover { background: #f8fafc; }
.u-cell[contenteditable="true"]:focus { background: #eff6ff; box-shadow: 0 0 0 2px #3b82f6; }
.u-drag-handle { cursor: grab; padding: 2px 3px; font-size: 11px; }
.u-drag-handle:active { cursor: grabbing; }
.u-add-row td { border-top: 1px dashed #e2e8f0; }

/* subtle convert (item <-> header) toggle for the unified builder */
.u-convert-btn {
    background: none;
    border: none;
    color: #cbd5e1;
    cursor: pointer;
    padding: 3px 6px;
    font-size: 12px;
    line-height: 1;
    border-radius: 4px;
    transition: color 0.1s, background 0.1s;
}
.u-convert-btn:hover { color: #475569; background: #f1f5f9; }

/* Per-item "action item" (votable) toggle in the agenda builder */
.import-action-item-toggle {
    background: none;
    border: none;
    color: #cbd5e1;
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 4px;
    transition: color 0.1s, background 0.1s;
}
.import-action-item-toggle:hover { background: #f1f5f9; color: #64748b; }
.import-action-item-toggle.is-on { color: #b45309; }
.import-action-item-toggle.is-on:hover { color: #92400e; background: #fef3c7; }

/* indent / outdent controls for nested agenda items */
.import-indent-controls { white-space: nowrap; }
.import-indent-btn {
    background: none;
    border: none;
    color: #cbd5e1;
    cursor: pointer;
    padding: 2px 3px;
    font-size: 11px;
    line-height: 1;
    border-radius: 3px;
    transition: color 0.1s, background 0.1s;
}
.import-indent-btn:hover { color: #475569; background: #f1f5f9; }

/* nested item rows get a subtle left guide so depth reads at a glance */
.import-item-row[data-depth="1"] .import-cell[data-field="title"],
.import-item-row[data-depth="2"] .import-cell[data-field="title"],
.import-item-row[data-depth="3"] .import-cell[data-field="title"] {
    border-left: 2px solid #e2e8f0;
    padding-left: 8px;
}

/* sortable ghost/drag states */
.sortable-ghost { opacity: 0.4; background: #e0f2fe !important; }
.sortable-chosen { box-shadow: 0 2px 8px rgba(0,0,0,0.12); }

.import-prefix-input {
    width: 38px;
    text-align: center;
    font-weight: 600;
    font-size: 12px;
    border: 1px solid #e2e8f0;
    border-radius: 4px;
    padding: 2px 4px;
    background: #fff;
    color: #475569;
    outline: none;
}
.import-prefix-input:focus { border-color: #3b82f6; box-shadow: 0 0 0 2px rgba(59,130,246,0.2); }
.import-spreadsheet-table th:first-child,
.import-spreadsheet-table td:first-child { min-width: 70px; }

/* ============================================================
   REQUEST FORM — Phase 2
   Notion-style full-page submission form (view-request-form)
   ============================================================ */

/* Design tokens scoped to the form */
.rf-page {
  --rf-emerald-800: var(--gv-brand-800);
  --rf-emerald-700: #3d6b1c;
  --rf-emerald-600: #5a9326;
  --rf-emerald-100: #dff2c5;
  --rf-emerald-50:  #f5fbe6;
  --rf-ink-900: #111827;
  --rf-ink-700: #374151;
  --rf-ink-500: #6b7280;
  --rf-ink-400: #9ca3af;
  --rf-ink-200: #e5e7eb;
  --rf-ink-100: #f3f4f6;
  --rf-ink-50:  #f9fafb;
  --rf-radius:  8px;
  --rf-font-doc: 'Source Serif 4', Georgia, serif;
  --rf-font-ui:  system-ui, -apple-system, sans-serif;

  min-height: 100%;
  background: #fff;
}

/* Top bar — breadcrumb + actions */
.rf-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 24px;
  border-bottom: 1px solid var(--rf-ink-200);
  background: #fff;
  position: sticky;
  top: var(--gv-session-h, 0px);   /* under the band at the top of the app (#1253) */
  z-index: 10;
}

.rf-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-family: var(--rf-font-ui);
  color: var(--rf-ink-500);
  background: none;
  border: none;
  padding: 4px 6px;
  border-radius: 5px;
  cursor: pointer;
  transition: color .15s, background .15s;
  white-space: nowrap;
}
.rf-back:hover { color: var(--rf-ink-900); background: var(--rf-ink-100); }

.rf-header-right {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

/* Status pill */
.rf-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 600;
  font-family: var(--rf-font-ui);
  padding: 3px 9px;
  border-radius: 999px;
  white-space: nowrap;
}
.rf-pill--draft     { background: var(--rf-ink-100); color: var(--rf-ink-500); }
.rf-pill--submitted { background: #dbeafe; color: #1e40af; }
.rf-pill--review    { background: #fef3c7; color: #92400e; }
.rf-pill--returned  { background: #ffedd5; color: #9a3412; }
.rf-pill--approved  { background: #d1fae5; color: #065f46; }
.rf-pill--placed    { background: #d1fae5; color: #065f46; }
.rf-pill--rejected  { background: #fee2e2; color: #991b1b; }
.rf-pill-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: .7;
}

/* Buttons */
.rf-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 500;
  font-family: var(--rf-font-ui);
  padding: 7px 14px;
  border-radius: 6px;
  cursor: pointer;
  transition: background .15s, border-color .15s, opacity .15s;
  white-space: nowrap;
  border: 1px solid transparent;
}
.rf-btn--ghost {
  background: #fff;
  border-color: var(--rf-ink-200);
  color: var(--rf-ink-700);
}
.rf-btn--ghost:hover { background: var(--rf-ink-100); }
.rf-btn--primary {
  background: var(--rf-emerald-800);
  color: #fff;
  border-color: var(--rf-emerald-800);
}
.rf-btn--primary:hover { background: var(--rf-emerald-700); }
.rf-btn--danger {
  background: #fff;
  border-color: #fca5a5;
  color: #b91c1c;
}
.rf-btn--danger:hover { background: #fef2f2; }
.rf-btn--sm { padding: 5px 11px; font-size: 12px; }
.rf-btn:disabled {
  opacity: .45;
  cursor: not-allowed;
}

/* Document canvas */
.rf-doc {
  max-width: 780px;
  margin: 0 auto;
  padding: 40px 48px 80px;
}

/* Banners */
.rf-info-banner, .rf-exec-banner {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 16px;
  border-radius: var(--rf-radius);
  font-size: 13px;
  font-family: var(--rf-font-ui);
  line-height: 1.5;
  margin-bottom: 20px;
}
.rf-info-banner {
  background: #eff6ff;
  color: #1e40af;
  border: 1px solid #bfdbfe;
}
.rf-exec-banner {
  background: #fdf4ff;
  color: #6b21a8;
  border: 1px solid #e9d5ff;
}
.rf-exec-banner svg, .rf-info-banner svg { flex-shrink: 0; margin-top: 1px; }

/* Large document title */
.rf-doc-title {
  width: 100%;
  font-family: var(--rf-font-doc);
  font-size: 32px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -.02em;
  color: var(--rf-ink-900);
  border: none;
  outline: none;
  resize: none;
  padding: 0;
  margin-bottom: 4px;
  background: transparent;
  overflow: hidden;
}
.rf-doc-title::placeholder { color: var(--rf-ink-200); }
.rf-doc-title:focus { outline: none; }

.rf-field-err {
  font-size: 12px;
  color: #dc2626;
  font-family: var(--rf-font-ui);
  margin-top: 4px;
  margin-bottom: 8px;
}

/* Properties table (Notion-style) */
.rf-props {
  margin: 20px 0 28px;
  border: 1px solid var(--rf-ink-200);
  border-radius: var(--rf-radius);
  overflow: hidden;
  background: var(--rf-ink-50);
}
.rf-prop-row {
  display: grid;
  grid-template-columns: 160px 1fr;
  border-bottom: 1px solid var(--rf-ink-200);
}
.rf-prop-row:last-child { border-bottom: none; }
.rf-prop-label {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 9px 14px;
  font-size: 12px;
  font-weight: 500;
  font-family: var(--rf-font-ui);
  color: var(--rf-ink-500);
  background: var(--rf-ink-50);
  border-right: 1px solid var(--rf-ink-200);
  white-space: nowrap;
}
.rf-prop-value {
  padding: 6px 10px;
  background: #fff;
}
.rf-prop-input, .rf-prop-select {
  width: 100%;
  font-size: 13px;
  font-family: var(--rf-font-ui);
  color: var(--rf-ink-900);
  background: transparent;
  border: none;
  outline: none;
  padding: 3px 0;
}
.rf-prop-select { cursor: pointer; }
.rf-prop-readonly { font-size: 13px; color: var(--rf-ink-900); padding: 3px 0; display: block; }
.rf-req-star { color: #dc2626; margin-left: 2px; }
.rf-optional { color: var(--rf-ink-400); font-size: 11px; font-weight: 400; }

/* Content blocks */
.rf-block {
  margin-bottom: 28px;
}
.rf-block-head {
  font-size: 15px;
  font-weight: 600;
  font-family: var(--rf-font-ui);
  color: var(--rf-ink-900);
  margin: 0 0 8px;
  letter-spacing: -.01em;
}
.rf-block-textarea {
  width: 100%;
  font-size: 14px;
  font-family: var(--rf-font-ui);
  line-height: 1.65;
  color: var(--rf-ink-900);
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 10px;
  resize: vertical;
  background: var(--rf-ink-50);
  transition: border-color .15s, background .15s, box-shadow .15s;
  min-height: 80px;
}
.rf-block-textarea:hover { background: var(--rf-ink-100); }
.rf-block-textarea:focus {
  background: #fff;
  border-color: var(--rf-emerald-600);
  outline: none;
  box-shadow: 0 0 0 3px var(--rf-emerald-50);
}
.rf-block-textarea--short { min-height: 56px; resize: none; }

/* Attachment zone */
.rf-attach-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 8px;
  margin-bottom: 10px;
}
.rf-attach-tile {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--rf-ink-200);
  border-radius: 7px;
  background: var(--rf-ink-50);
  font-size: 12px;
  font-family: var(--rf-font-ui);
}
.rf-attach-tile .rf-file-icon {
  width: 28px; height: 34px;
  border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
  font-size: 8px; font-weight: 700; letter-spacing: .03em;
  flex-shrink: 0;
}
.rf-file-icon--pdf  { background: #fee2e2; color: #991b1b; }
.rf-file-icon--xlsx { background: #dcfce7; color: #14532d; }
.rf-file-icon--xls  { background: #dcfce7; color: #14532d; }
.rf-file-icon--docx { background: #dbeafe; color: #1e3a8a; }
.rf-file-icon--doc  { background: #dbeafe; color: #1e3a8a; }
.rf-file-icon--pptx { background: #ffedd5; color: #9a3412; }
.rf-file-icon--ppt  { background: #ffedd5; color: #9a3412; }
.rf-file-icon--img  { background: #fef3c7; color: #78350f; }
.rf-attach-tile .rf-tile-meta { flex: 1; min-width: 0; }
.rf-attach-tile .rf-tile-name {
  font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  color: var(--rf-ink-900);
}
.rf-attach-tile .rf-tile-size { color: var(--rf-ink-400); font-size: 10px; }
.rf-attach-remove {
  background: none; border: none; cursor: pointer;
  color: var(--rf-ink-400); padding: 2px; border-radius: 4px;
  flex-shrink: 0;
  line-height: 1;
}
.rf-attach-remove:hover { color: #dc2626; background: #fee2e2; }

.rf-drop-zone {
  border: 1.5px dashed var(--rf-ink-200);
  border-radius: var(--rf-radius);
  padding: 20px;
  text-align: center;
  background: var(--rf-ink-50);
  transition: border-color .15s, background .15s;
}
.rf-drop-zone.rf-drag-over {
  border-color: var(--rf-emerald-600);
  background: var(--rf-emerald-50);
}
.rf-drop-cta {
  display: inline-flex; align-items: center; gap: 8px;
  background: none; border: none; cursor: pointer;
  font-size: 13px; font-family: var(--rf-font-ui);
  color: var(--rf-ink-700);
  padding: 0; margin-bottom: 4px;
}
.rf-link { color: var(--rf-emerald-700); font-weight: 500; }
.rf-drop-hint { font-size: 11px; color: var(--rf-ink-400); font-family: var(--rf-font-ui); }

/* Bottom actions (legacy, kept for compatibility) */
.rf-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-top: 24px;
  border-top: 1px solid var(--rf-ink-200);
  margin-top: 8px;
}

/* ── New two-column request form layout ─────────────────────────── */

.rf-body {
  padding: 28px 32px 60px;
  background: #f9fafb;
  overflow-y: auto;
}

.rf-page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
}
.rf-page-title {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--rf-ink-900);
  margin: 0 0 3px;
  font-family: var(--rf-font-ui);
}
.rf-page-sub {
  font-size: 13px;
  color: var(--rf-ink-500);
  margin: 0;
  font-family: var(--rf-font-ui);
}
.rf-user-badge {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-shrink: 0;
}
.rf-user-avatar {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: #064e3b;
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700;
  font-family: var(--rf-font-ui);
  flex-shrink: 0;
}
.rf-user-name { font-size: 13px; font-weight: 600; color: var(--rf-ink-900); font-family: var(--rf-font-ui); }
.rf-user-role { font-size: 11px; color: var(--rf-ink-500); font-family: var(--rf-font-ui); }

/* Pipeline strip */
.rf-pipeline {
  display: grid;
  background: #fff;
  border: 1px solid var(--rf-ink-200);
  border-radius: 10px;
  padding: 13px 16px;
  margin-bottom: 20px;
  box-shadow: 0 1px 2px rgba(0,0,0,0.04);
  overflow-x: auto;
}
.rf-pipeline-step {
  display: flex; flex-direction: column; gap: 3px;
  position: relative;
  padding-right: 20px;
  min-width: 0;
}
.rf-pipeline-step:not(:last-child)::after {
  content: '';
  position: absolute;
  right: 0; top: 10px;
  width: 20px; height: 2px;
  background: var(--rf-ink-200);
}
.rf-pipeline-step--current:not(:last-child)::after { background: #10b981; }
.rf-pipeline-step__head { display: flex; align-items: center; gap: 7px; }
.rf-pipeline-step__circle {
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--rf-ink-100); color: var(--rf-ink-500);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 700; font-family: var(--rf-font-ui);
  flex-shrink: 0;
}
.rf-pipeline-step--done .rf-pipeline-step__circle { background: #10b981; color: #fff; }
.rf-pipeline-step--current .rf-pipeline-step__circle {
  background: #fff; border: 2px solid #10b981; color: #065f46;
  box-shadow: 0 0 0 3px #d1fae5;
}
.rf-pipeline-step__label {
  font-size: 12px; font-weight: 600; color: var(--rf-ink-700);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font-family: var(--rf-font-ui);
}
.rf-pipeline-step__sub {
  font-size: 11px; color: var(--rf-ink-500);
  margin-left: 29px; white-space: nowrap;
  font-family: var(--rf-font-ui);
}

/* Two-column grid */
.rf-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 20px;
  align-items: start;
}
@media (max-width: 900px) { .rf-grid { grid-template-columns: 1fr; } }

/* Form card */
.rf-form-card {
  background: #fff;
  border: 1px solid var(--rf-ink-200);
  border-radius: 10px;
  box-shadow: 0 1px 2px rgba(0,0,0,0.04);
  overflow: hidden;
}
.rf-form-card-head {
  padding: 20px 24px 16px;
  border-bottom: 1px solid var(--rf-ink-200);
}
/* The title is the one field people miss — borderless, it reads as text that's
   already there rather than something to fill in. Give it the same box every
   other field has, just larger. */
.rf-card-title {
  width: 100%; resize: none; overflow: hidden;
  border: 1px solid var(--rf-ink-200); border-radius: var(--rf-radius);
  padding: 11px 13px; margin: 0 0 6px; background: #fff;
  font-size: 17px; font-weight: 600; line-height: 1.4;
  font-family: var(--rf-font-ui); color: var(--rf-ink-900);
  transition: border-color .15s, box-shadow .15s;
}
.rf-card-title:hover { border-color: var(--rf-ink-300); }
.rf-card-title:focus {
  outline: none;
  border-color: var(--rf-emerald-600);
  box-shadow: 0 0 0 3px var(--rf-emerald-50);
}
.rf-card-title::placeholder { color: var(--rf-ink-400); font-weight: 400; }
.rf-card-sub { font-size: 12px; color: var(--rf-ink-400); font-family: var(--rf-font-ui); }
.rf-form-fields { padding: 20px 24px; }
.rf-field { margin-bottom: 18px; }
.rf-field:last-child { margin-bottom: 0; }
.rf-field > label {
  display: block; font-size: 12px; font-weight: 600;
  color: var(--rf-ink-700); margin-bottom: 5px;
  letter-spacing: 0.01em; font-family: var(--rf-font-ui);
}
.rf-input-std, .rf-select-std {
  width: 100%; padding: 9px 11px;
  border: 1px solid var(--rf-ink-200); border-radius: 7px;
  font-size: 14px; font-family: var(--rf-font-ui);
  background: #fff; color: var(--rf-ink-900);
  transition: border-color .15s, box-shadow .15s;
}
.rf-select-std { cursor: pointer; }
.rf-input-std:focus, .rf-select-std:focus {
  outline: none; border-color: #10b981;
  box-shadow: 0 0 0 3px #d1fae5;
}
.rf-textarea-std {
  width: 100%; padding: 9px 11px;
  border: 1px solid var(--rf-ink-200); border-radius: 7px;
  font-size: 13px; font-family: var(--rf-font-ui);
  background: #fff; color: var(--rf-ink-900);
  resize: vertical; line-height: 1.55; min-height: 72px;
  transition: border-color .15s, box-shadow .15s;
}
.rf-textarea-std:focus {
  outline: none; border-color: #10b981;
  box-shadow: 0 0 0 3px #d1fae5;
}
.rf-row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 18px; }
.rf-row-2 .rf-field { margin-bottom: 0; }
.rf-form-actions {
  display: flex; align-items: center; justify-content: flex-end; gap: 10px;
  padding: 14px 24px;
  border-top: 1px solid var(--rf-ink-200);
  background: var(--rf-ink-50);
}

/* Sidebar */
.rf-side-card {
  background: #fff; border: 1px solid var(--rf-ink-200);
  border-radius: 10px; padding: 16px 18px; margin-bottom: 14px;
  box-shadow: 0 1px 2px rgba(0,0,0,0.04);
}
.rf-side-card:last-child { margin-bottom: 0; }
.rf-side-card h3 {
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--rf-ink-500); margin: 0 0 12px;
  font-family: var(--rf-font-ui);
}
.rf-timeline { display: flex; flex-direction: column; gap: 14px; }
.rf-timeline-event { position: relative; padding-left: 20px; }
.rf-timeline-event::before {
  content: ''; position: absolute; left: 4px; top: 5px;
  width: 8px; height: 8px; border-radius: 50%; background: var(--rf-ink-200);
}
.rf-timeline-event--done::before { background: #10b981; }
.rf-timeline-event:not(:last-child)::after {
  content: ''; position: absolute; left: 7px; top: 14px;
  width: 2px; bottom: -14px; background: var(--rf-ink-100);
}
.rf-te-title { font-size: 13px; font-weight: 500; color: var(--rf-ink-900); font-family: var(--rf-font-ui); }
.rf-te-meta { font-size: 11px; color: var(--rf-ink-500); margin-top: 1px; font-family: var(--rf-font-ui); }
.rf-mini-list { display: flex; flex-direction: column; gap: 8px; }
.rf-mini-card {
  padding: 9px 11px; border: 1px solid var(--rf-ink-100); border-radius: 8px;
  cursor: pointer; transition: border-color .15s, background .15s;
}
.rf-mini-card:hover { border-color: var(--rf-ink-200); background: var(--rf-ink-50); }
.rf-mini-card__head {
  display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px;
}
.rf-mini-badge { font-size: 10px; font-weight: 600; padding: 2px 7px; border-radius: 999px; font-family: var(--rf-font-ui); }
.rf-mini-date { font-size: 11px; color: var(--rf-ink-400); font-family: var(--rf-font-ui); }
.rf-mini-title { font-size: 12px; font-weight: 500; color: var(--rf-ink-900); line-height: 1.35; margin-bottom: 2px; font-family: var(--rf-font-ui); }
.rf-mini-meta { font-size: 11px; color: var(--rf-ink-500); font-family: var(--rf-font-ui); }
.rf-tips-text { font-size: 12px; color: var(--rf-ink-500); margin: 0; line-height: 1.6; font-family: var(--rf-font-ui); }

/* AI Summary card */
.rf-ai-card { border-color: #d1fae5; background: #f0fdf4; }
.rf-ai-card h3 { color: #065f46; display: flex; align-items: center; gap: 5px; }
.rf-ai-summary-text { font-size: 13px; color: var(--rf-ink-800); line-height: 1.6; margin: 0; font-family: var(--rf-font-ui); }
.rf-ai-loading { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--rf-ink-400); font-family: var(--rf-font-ui); }
.rf-ai-loading::before {
  content: ''; width: 12px; height: 12px; border-radius: 50%;
  border: 2px solid #a7f3d0; border-top-color: #065f46;
  animation: rf-spin .8s linear infinite; flex-shrink: 0;
}
@keyframes rf-spin { to { transform: rotate(360deg); } }

/* Review comments thread */
.rf-comments-thread { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.rf-comment { padding: 9px 11px; border-radius: 8px; background: var(--rf-ink-50); }
.rf-comment--mine { background: #f0fdf4; }
.rf-comment-header { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 4px; gap: 8px; }
.rf-comment-author { font-size: 11px; font-weight: 700; color: var(--rf-ink-700); font-family: var(--rf-font-ui); }
.rf-comment-time { font-size: 10px; color: var(--rf-ink-400); font-family: var(--rf-font-ui); white-space: nowrap; }
.rf-comment-body { font-size: 13px; color: var(--rf-ink-800); line-height: 1.5; margin: 0; font-family: var(--rf-font-ui); white-space: pre-wrap; }
.rf-comment-empty { font-size: 12px; color: var(--rf-ink-400); font-family: var(--rf-font-ui); }
.rf-comment-composer { display: flex; flex-direction: column; gap: 7px; }
.rf-comment-input {
  width: 100%; border: 1px solid var(--rf-ink-200); border-radius: 7px;
  padding: 8px 10px; font-size: 13px; font-family: var(--rf-font-ui);
  color: var(--rf-ink-900); resize: none; outline: none;
  transition: border-color .15s; box-sizing: border-box;
}
.rf-comment-input:focus { border-color: var(--gv-brand-900); }

/* Sidebar attachments */
.rf-sidebar-attach-list { display: flex; flex-direction: column; gap: 7px; }
.rf-sidebar-attach-item {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 9px; border-radius: 7px; border: 1px solid var(--rf-ink-100);
  text-decoration: none; color: var(--rf-ink-800); background: var(--rf-ink-50);
  transition: border-color .15s, background .15s;
}
.rf-sidebar-attach-item:hover { border-color: var(--rf-ink-200); background: #fff; }
.rf-sidebar-attach-name { font-size: 12px; font-weight: 500; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--rf-font-ui); }
.rf-sidebar-attach-size { font-size: 11px; color: var(--rf-ink-400); white-space: nowrap; font-family: var(--rf-font-ui); }

/* Agenda preview accordion */
.rf-live-preview {
  margin-top: 20px; background: var(--rf-ink-50);
  border: 1px dashed var(--rf-ink-200); border-radius: 8px; overflow: hidden;
}
.rf-live-preview.open { background: #fff; border-style: solid; border-color: var(--rf-ink-200); }
.rf-live-preview__head {
  display: flex; align-items: center; gap: 8px;
  width: 100%; padding: 12px 16px; cursor: pointer;
  background: transparent; border: 0; text-align: left; color: inherit;
  font-family: var(--rf-font-ui);
}
.rf-live-preview__head:hover { background: rgba(0,0,0,0.02); }
.rf-live-preview__chev { color: var(--rf-ink-400); transition: transform .2s; flex-shrink: 0; }
.rf-live-preview.open .rf-live-preview__chev { transform: rotate(90deg); color: #065f46; }
.rf-live-preview__label { font-size: 12px; font-weight: 600; color: var(--rf-ink-700); font-family: var(--rf-font-ui); }
.rf-live-preview.open .rf-live-preview__label { color: #065f46; }
.rf-live-preview__hint { margin-left: auto; font-size: 11px; color: var(--rf-ink-400); font-family: var(--rf-font-ui); }
.rf-live-preview__body { display: none; padding: 4px 16px 16px; }
.rf-live-preview.open .rf-live-preview__body { display: block; }
.rf-preview-num { font-family: var(--rf-font-ui); font-size: 11px; color: #065f46; font-weight: 600; margin-bottom: 3px; }
.rf-preview-title { font-family: var(--rf-font-doc); font-size: 14px; font-weight: 600; margin-bottom: 5px; }
.rf-preview-details { font-family: var(--rf-font-doc); font-size: 13px; color: var(--rf-ink-700); }

/* =====================================================================
   AGENDA REVIEW PAGE
   ===================================================================== */

/* Top bar */
.agr-topbar {
    position: sticky;
    top: 0;
    z-index: 100;
    background: var(--gv-brand-900);
    color: #fff;
    padding: 12px 24px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    box-shadow: 0 2px 8px rgba(0,0,0,.18);
}
.agr-topbar-title { font-size: 15px; font-weight: 600; }
.agr-topbar-meta { font-size: 12px; color: #cef17b; font-weight: 500; }
.agr-topbar-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }

/* Decision banner shown after reviewer acts */
.agr-decided-banner {
    background: #f0fdf4;
    border-bottom: 2px solid #16a34a;
    color: #15803d;
    padding: 12px 24px;
    font-size: 13px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 8px;
}
.agr-decided-banner.changes { background: #fffbeb; border-color: #f59e0b; color: #92400e; }

/* Agenda content area */
.agr-body { max-width: 860px; margin: 0 auto; padding: 28px 20px 120px; }

/* Section header */
.agr-section-header {
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--gv-brand-900);
    padding: 10px 0 6px;
    border-bottom: 2px solid var(--gv-brand-900);
    margin-bottom: 6px;
}

/* Item card */
.agr-item {
    background: #fff;
    border: 1.5px solid #e5e7eb;
    border-radius: 10px;
    margin-bottom: 8px;
    overflow: hidden;
    transition: border-color .15s;
}
.agr-item.flagged { border-color: #f59e0b; }
.agr-item-header {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 14px;
    cursor: default;
}
.agr-item-num { font-size: 11px; font-weight: 700; color: #9ca3af; flex-shrink: 0; padding-top: 2px; min-width: 22px; }
.agr-item-text { flex: 1; min-width: 0; }
.agr-item-title { font-size: 14px; font-weight: 600; color: #111827; line-height: 1.4; }
.agr-item-dept { font-size: 11px; color: #6b7280; margin-top: 2px; }
.agr-item-details { font-size: 13px; color: #374151; margin-top: 6px; line-height: 1.5; }

/* Flag button */
.agr-flag-btn {
    flex-shrink: 0;
    width: 30px; height: 30px;
    border-radius: 6px;
    border: 1.5px solid #e5e7eb;
    background: #f9fafb;
    color: #d1d5db;
    font-size: 13px;
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: all .15s;
}
.agr-flag-btn:hover { border-color: #f59e0b; color: #f59e0b; background: #fffbeb; }
.agr-flag-btn.active { border-color: #f59e0b; color: #f59e0b; background: #fffbeb; }

/* Item comment area (shown when flagged) */
.agr-item-comments {
    border-top: 1px solid #fde68a;
    background: #fffdf5;
    padding: 12px 14px 14px;
    display: none;
}
.agr-item.flagged .agr-item-comments { display: block; }

/* Comment thread */
.agr-comment { display: flex; gap: 8px; margin-bottom: 8px; }
.agr-comment-avatar {
    width: 28px; height: 28px;
    border-radius: 50%;
    background: var(--gv-brand-900);
    color: #cef17b;
    font-size: 11px; font-weight: 700;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.agr-comment-avatar.admin { background: #e0e7ff; color: #3730a3; }
.agr-comment-bubble { background: #f3f4f6; border-radius: 0 8px 8px 8px; padding: 8px 10px; flex: 1; }
.agr-comment-author { font-size: 11px; font-weight: 700; color: #374151; margin-bottom: 2px; }
.agr-comment-body { font-size: 13px; color: #1f2937; line-height: 1.4; }
.agr-comment-time { font-size: 10px; color: #9ca3af; margin-top: 3px; }
.agr-comment-input-row { display: flex; gap: 8px; margin-top: 8px; }
.agr-comment-input-row textarea {
    flex: 1;
    border: 1px solid #e5e7eb;
    border-radius: 6px;
    padding: 6px 8px;
    font-size: 12px;
    resize: none;
    font-family: inherit;
    outline: none;
    transition: border-color .15s;
}
.agr-comment-input-row textarea:focus { border-color: #f59e0b; }
.agr-comment-send-btn {
    padding: 0 12px;
    border-radius: 6px;
    background: var(--gv-brand-900);
    color: #cef17b;
    font-size: 12px;
    font-weight: 600;
    border: none;
    cursor: pointer;
    flex-shrink: 0;
    transition: background .15s;
}
.agr-comment-send-btn:hover { background: #065f46; }

/* Overall comments section */
.agr-overall-comments {
    background: #fff;
    border: 1.5px solid #e5e7eb;
    border-radius: 12px;
    padding: 18px;
    margin-top: 24px;
}
.agr-overall-title { font-size: 13px; font-weight: 700; color: #374151; margin-bottom: 12px; }

/* Sticky action bar (reviewer) */
.agr-action-bar {
    position: fixed;
    bottom: 0; left: 0; right: 0;
    background: #fff;
    border-top: 1px solid #e5e7eb;
    padding: 14px 24px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
    z-index: 90;
    box-shadow: 0 -2px 12px rgba(0,0,0,.08);
}
.agr-btn-changes {
    background: #fffbeb;
    border: 1.5px solid #f59e0b;
    color: #92400e;
    padding: 10px 20px;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: all .15s;
}
.agr-btn-changes:hover { background: #fef3c7; }
.agr-btn-approve {
    background: var(--gv-brand-900);
    border: 1.5px solid var(--gv-brand-900);
    color: #cef17b;
    padding: 10px 24px;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: background .15s;
}
.agr-btn-approve:hover { background: #065f46; }
.agr-btn-approve:disabled, .agr-btn-changes:disabled {
    opacity: .45;
    cursor: not-allowed;
}
.agr-action-hint { font-size: 12px; color: #9ca3af; margin-right: auto; }

/* Request-changes note modal */
.agr-changes-modal {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0,0,0,.4);
    backdrop-filter: blur(2px);
}
.agr-changes-modal-box {
    background: #fff;
    border-radius: 16px;
    width: 100%;
    max-width: 440px;
    margin: 0 16px;
    overflow: hidden;
    box-shadow: 0 20px 60px rgba(0,0,0,.2);
}

/* Flag badge on admin item cards */
.ag-review-flag-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: #fffbeb;
    border: 1px solid #fde68a;
    color: #92400e;
    font-size: 10px;
    font-weight: 600;
    padding: 2px 6px;
    border-radius: 4px;
    cursor: pointer;
}
.ag-review-flag-badge:hover { background: #fef3c7; }

/* ============================================================
   REQUEST FORMS — the form badge, the picker, and custom fields
   rendered from a form definition. Reuses the rf-* tokens above.
   ============================================================ */

/* Which form this request is on. Replaces the old request-type dropdown —
   the form IS the type, so it's stated, not chosen again. */
.rf-form-badge {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 13px;
    background: var(--rf-emerald-50);
    border: 1px solid var(--rf-emerald-100);
    border-radius: var(--rf-radius);
}
.rf-form-badge .rf-fb-icon { font-size: 17px; line-height: 1; flex-shrink: 0; }
.rf-form-badge .rf-fb-name { font-size: 13.5px; font-weight: 600; color: var(--rf-emerald-800); }
.rf-form-badge .rf-fb-sub  { font-size: 11.5px; color: var(--rf-emerald-700); opacity: .8; margin-top: 1px; }
.rf-form-badge .rf-fb-change {
    margin-left: auto; flex-shrink: 0;
    background: none; border: none; cursor: pointer;
    font-size: 12px; font-weight: 600; color: var(--rf-emerald-700);
    font-family: var(--rf-font-ui);
    padding: 4px 8px; border-radius: 6px;
}
.rf-form-badge .rf-fb-change:hover { background: #fff; }

/* Internal-only marker on a field the public never sees */
.rf-internal-tag {
    font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
    color: #92400e; background: #fef3c7;
    padding: 2px 7px; border-radius: 999px; margin-left: 6px; vertical-align: middle;
}
.rf-field-help { font-size: 11.5px; color: var(--rf-ink-400); margin-top: 4px; line-height: 1.45; }

/* Checkbox field */
.rf-check-row { display: flex; align-items: center; gap: 8px; cursor: pointer; font-weight: normal; }
.rf-check-row input { width: 15px; height: 15px; accent-color: var(--gv-brand-900); cursor: pointer; flex-shrink: 0; }

/* Line-items table — the repeating account / description / amount grid */
.rf-li-table { border: 1px solid var(--rf-ink-200); border-radius: var(--rf-radius); overflow: hidden; }
.rf-li-row {
    display: grid; grid-template-columns: 1.4fr 2fr 1fr 34px;
    border-bottom: 1px solid var(--rf-ink-200);
}
.rf-li-row:last-child { border-bottom: none; }
.rf-li-head {
    background: var(--rf-ink-50);
    font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
    color: var(--rf-ink-500);
}
.rf-li-head > div { padding: 8px 11px; }
.rf-li-cell input {
    width: 100%; border: none; padding: 9px 11px;
    font-size: 13px; font-family: var(--rf-font-ui);
    background: transparent; border-right: 1px solid var(--rf-ink-100);
    color: #111827;
}
.rf-li-cell input:focus { outline: none; background: var(--rf-emerald-50); }
.rf-li-x {
    display: flex; align-items: center; justify-content: center;
    color: var(--rf-ink-400); cursor: pointer; background: none; border: none; font-size: 15px;
}
.rf-li-x:hover { color: #dc2626; }
.rf-li-total {
    display: flex; justify-content: space-between; align-items: center;
    padding: 10px 12px; background: var(--rf-emerald-50);
    font-size: 13px; font-weight: 700; color: var(--rf-emerald-800);
}
.rf-li-add {
    background: none; border: none; cursor: pointer;
    font-size: 12px; font-weight: 600; color: var(--rf-emerald-700);
    font-family: var(--rf-font-ui);
    padding: 8px 2px; display: inline-flex; align-items: center; gap: 6px;
}
.rf-li-add:hover { text-decoration: underline; }

/* Form picker — the "what are you submitting?" step.
   This modal is appended to document.body, OUTSIDE .rf-page, so it cannot use
   the --rf-* tokens: they're scoped to the form and resolve to nothing here,
   which is what silently erased these cards' borders. Literal values only. */
.rf-picker-grid { display: grid; grid-template-columns: 1fr; gap: 10px; }
@media (min-width: 640px) { .rf-picker-grid { grid-template-columns: 1fr 1fr; } }

.rf-picker-tile {
    display: flex; align-items: flex-start; gap: 12px; width: 100%;
    border: 1px solid #e5e7eb; border-radius: 10px; padding: 14px;
    background: #fff; cursor: pointer; text-align: left; transition: .15s;
    font-family: system-ui, -apple-system, sans-serif;
}
.rf-picker-tile:hover {
    border-color: var(--gv-brand-900); background: #f7fbf3;
    box-shadow: 0 2px 10px rgba(0,0,0,.07);
}
.rf-picker-tile .rf-pt-icon {
    width: 36px; height: 36px; border-radius: 9px; flex-shrink: 0;
    background: #eef7e6; color: #2f6b1f;
    display: flex; align-items: center; justify-content: center; font-size: 15px;
}
.rf-picker-tile:hover .rf-pt-icon { background: #dff2c5; }
.rf-picker-tile .rf-pt-body { flex: 1; min-width: 0; }
.rf-picker-tile h4 {
    font-size: 14px; font-weight: 700; margin: 0 0 2px; color: #111827; line-height: 1.3;
}
.rf-picker-tile p {
    font-size: 12px; color: #6b7280; margin: 0; line-height: 1.45;
}
.rf-picker-tile .rf-pt-meta {
    font-size: 11px; color: #9ca3af; margin-top: 6px;
    display: flex; align-items: center; gap: 5px;
}
.rf-picker-tile .rf-pt-go {
    color: #d1d5db; flex-shrink: 0; font-size: 12px; margin-top: 11px;
}
.rf-picker-tile:hover .rf-pt-go { color: var(--gv-brand-900); }

/* The empty agenda's start panel (#186) is .gv-start in components.css now, shared with
   the Recording step's (#671). */

/* ============================================================
   PORTAL FILES — category chips and per-file category tags.
   A resident filtering to "Resolutions" is the whole point of
   the form name carrying the county's own terminology.
   ============================================================ */
.pm-file-chips {
    display: flex; flex-wrap: wrap; gap: 7px;
    padding: 11px 14px 3px;
}
.pm-file-chip {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 12px; font-weight: 600;
    padding: 6px 12px; border-radius: 999px;
    border: 1px solid #e5e7eb; background: #fff; color: #4b5563;
    cursor: pointer; transition: .12s; font-family: inherit;
}
.pm-file-chip:hover { border-color: var(--gv-brand-900); color: var(--gv-brand-900); }
.pm-file-chip span {
    font-size: 11px; font-weight: 700; color: #9ca3af;
    font-variant-numeric: tabular-nums;
}
.pm-file-chip.is-on { background: var(--gv-brand-900); border-color: var(--gv-brand-900); color: #fff; }
.pm-file-chip.is-on span { color: rgba(255, 255, 255, .7); }

/* The category a file is filed under, on the row itself */
.pm-file-cat {
    flex-shrink: 0; white-space: nowrap;
    font-size: 11px; font-weight: 600;
    padding: 3px 9px; border-radius: 999px;
    background: #f3f4f6; color: #6b7280;
}
@media (max-width: 640px) { .pm-file-cat { display: none; } }

/* ============================================================
   READY FOR AGENDA — a terse list that reads like the agenda it's
   about to become, plus the detail overlay behind each row.
   ============================================================ */
.rfa-list { border: 1px solid #e5e7eb; border-radius: 10px; overflow: hidden; background: #fff; }
.rfa-row {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 12px; border-top: 1px solid #f3f4f6;
    cursor: pointer; transition: background .12s;
}
.rfa-row:first-child { border-top: none; }
.rfa-row:hover { background: #fffbeb; }
.rfa-row:focus-visible { outline: 2px solid var(--gv-brand-900); outline-offset: -2px; }
.rfa-num {
    width: 22px; flex-shrink: 0; text-align: right;
    font-size: 12px; font-weight: 700; color: #d1d5db; font-variant-numeric: tabular-nums;
}
.rfa-title {
    font-size: 13.5px; color: #111827; font-weight: 500;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.rfa-meta {
    font-size: 11.5px; color: #9ca3af; flex: 1; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rfa-clip { font-size: 11px; color: #9ca3af; flex-shrink: 0; display: inline-flex; gap: 3px; align-items: center; }
.rfa-place {
    flex-shrink: 0; margin-left: auto;
    font-size: 11.5px; font-weight: 600; white-space: nowrap;
    padding: 4px 10px; border-radius: 6px;
    background: var(--gv-brand-900); color: #fff; border: none; cursor: pointer; transition: background .12s;
}
.rfa-place:hover { background: #0a5a42; }
.rfa-row:not(:hover) .rfa-place { background: #fff; color: var(--gv-brand-900); border: 1px solid #d1d5db; }

/* Detail overlay — slides in from the right */
.rfa-pv-scrim {
    position: fixed; inset: 0; z-index: 70;
    background: rgba(0,0,0,0); transition: background .2s;
}
.rfa-pv-scrim.is-open { background: rgba(0,0,0,.35); }
.rfa-pv-panel {
    position: absolute; top: 0; right: 0; bottom: 0;
    width: min(460px, 92vw); background: #fff;
    box-shadow: -8px 0 30px rgba(0,0,0,.14);
    display: flex; flex-direction: column;
    transform: translateX(100%); transition: transform .22s cubic-bezier(.4,0,.2,1);
}
.rfa-pv-scrim.is-open .rfa-pv-panel { transform: translateX(0); }
.rfa-pv-head {
    display: flex; align-items: flex-start; gap: 12px;
    padding: 18px 20px 14px; border-bottom: 1px solid #e5e7eb;
}
.rfa-pv-kicker {
    font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em;
    color: #6b7280; margin-bottom: 3px;
}
.rfa-pv-title { font-size: 16px; font-weight: 700; color: #111827; margin: 0; line-height: 1.35; }
.rfa-pv-x {
    margin-left: auto; flex-shrink: 0; background: none; border: none; cursor: pointer;
    color: #9ca3af; width: 28px; height: 28px; border-radius: 6px;
}
.rfa-pv-x:hover { background: #f3f4f6; color: #374151; }
.rfa-pv-body { flex: 1; overflow-y: auto; padding: 4px 20px 20px; }
.rfa-pv-row { padding: 13px 0; border-bottom: 1px solid #f3f4f6; }
.rfa-pv-row:last-child { border-bottom: none; }
.rfa-pv-label {
    font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
    color: #9ca3af; margin-bottom: 4px;
}
.rfa-pv-value { font-size: 13.5px; color: #111827; line-height: 1.5; }
.rfa-pv-prose { white-space: pre-wrap; }
.rfa-pv-line {
    display: grid; grid-template-columns: 1fr 1.6fr auto; gap: 8px;
    font-size: 12.5px; padding: 3px 0; border-bottom: 1px dotted #e5e7eb; color: #374151;
}
.rfa-pv-total { font-size: 12.5px; font-weight: 700; color: var(--gv-brand-900); padding-top: 6px; text-align: right; }
.rfa-pv-file {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 12.5px; color: var(--gv-brand-900); text-decoration: none;
    border: 1px solid #e5e7eb; border-radius: 6px; padding: 5px 9px; margin: 0 6px 6px 0;
}
.rfa-pv-file:hover { border-color: var(--gv-brand-900); background: #f7fbf3; }
.rfa-pv-foot {
    display: flex; justify-content: flex-end; gap: 8px;
    padding: 14px 20px; border-top: 1px solid #e5e7eb; background: #f9fafb;
}
.rfa-pv-cancel {
    font-size: 13px; padding: 8px 14px; border-radius: 8px;
    border: 1px solid #e5e7eb; background: #fff; color: #4b5563; cursor: pointer;
}
.rfa-pv-place {
    font-size: 13px; font-weight: 600; padding: 8px 14px; border-radius: 8px;
    border: none; background: var(--gv-brand-900); color: #fff; cursor: pointer;
}
.rfa-pv-place:hover { background: #0a5a42; }

/* ── Flat agenda builder: placement mode ─────────────────────────────────────
   Clicking means something different while placing, so the whole table has to
   read as "pick a spot" rather than "edit a row". */
.flat-placing-banner {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 14px; margin-bottom: 10px;
    background: #ecfdf5; border: 1px solid #a7f3d0; border-radius: 10px;
    font-size: 13px; color: #065f46;
}
.flat-placing-banner i { color: #059669; }
.flat-placing-banner span { flex: 1; min-width: 0; }
.flat-placing-banner strong { font-weight: 600; }
.flat-placing-banner button {
    flex-shrink: 0; padding: 4px 10px; border-radius: 6px;
    border: 1px solid #a7f3d0; background: #fff; color: #065f46;
    font-size: 12px; font-weight: 500;
}
.flat-placing-banner button:hover { border-color: #059669; }

/* A drop zone is a thin gap that opens up on hover — it should feel like the
   list parting to make room, not like another row. */
.flat-drop td { padding: 0 !important; }
.flat-drop-inner {
    display: flex; align-items: center; gap: 10px;
    padding: 3px 8px; margin: 1px 0;
    border-radius: 6px; cursor: pointer;
    opacity: .45; transition: opacity .12s, background .12s, padding .12s;
}
.flat-drop-inner:hover { opacity: 1; background: #ecfdf5; padding: 8px; }
.flat-drop-line { flex: 1; height: 2px; border-radius: 2px; background: #6ee7b7; }
.flat-drop-label { font-size: 12px; color: #065f46; white-space: nowrap; }
.flat-drop-label strong { font-weight: 700; }
.flat-drop-dots { display: inline-flex; align-items: center; gap: 4px; }

/* One dot per LEGAL level, indented to show the nesting it would produce, and
   labelled with the number the entry would actually take. */
.flat-drop-dot {
    min-width: 24px; height: 22px; padding: 0 6px;
    border-radius: 6px; border: 1px solid #d1d5db; background: #fff;
    font-size: 11px; font-weight: 600; color: #6b7280; line-height: 1;
}
.flat-drop-dot:hover { border-color: #059669; color: #065f46; background: #f0fdf4; }
.flat-drop-dot.is-default { border-color: #059669; background: #059669; color: #fff; }

/* ── Flat builder: per-line emphasis ─────────────────────────────────────────
   Quiet until the row is hovered, so a long agenda isn't a wall of buttons —
   but always visible when the line actually has emphasis set. */
.flat-fmt-group { display: inline-flex; align-items: center; gap: 1px; margin-right: 6px; }
.flat-fmt {
    width: 22px; height: 22px; border: 0; background: transparent;
    border-radius: 5px; color: #cbd5e1; font-size: 10.5px; cursor: pointer;
    opacity: 0; transition: opacity .12s, color .12s, background .12s;
}
.flat-row:hover .flat-fmt { opacity: 1; }
/* The number cell and its bullet button, side by side (an agenda numbered by its PDF). */
.flat-num-wrap { display: inline-flex; align-items: center; gap: 1px; vertical-align: middle; }
.flat-num-wrap .flat-num-cell { min-width: 1.6em; }
.flat-fmt:hover { color: #475569; background: #f1f5f9; }
.flat-fmt.is-on { opacity: 1; color: #0f172a; background: #e2e8f0; }
.flat-fmt.is-on:hover { background: #cbd5e1; }

/* ── Original agenda PDF viewer (#489, super admins) ──────────────────────────
   A floating window, not a modal: no scrim, so the agenda under it stays usable. */
.ag-src-win {
    position: fixed; z-index: 60; display: flex; flex-direction: column;
    background: #fff; border: 1px solid #cbd5e1; border-radius: 10px; overflow: hidden;
    box-shadow: 0 18px 40px -12px rgba(15, 23, 42, .35), 0 2px 6px rgba(15, 23, 42, .12);
}
.ag-src-win__bar {
    display: flex; align-items: center; gap: 8px; padding: 6px 6px 6px 10px;
    background: #f8fafc; border-bottom: 1px solid #e2e8f0; cursor: move; user-select: none; touch-action: none;
}
.ag-src-win__grip { color: #94a3b8; font-size: 12px; }
.ag-src-win__heading { flex: 1; min-width: 0; }
.ag-src-win__title { font-size: 13px; font-weight: 600; color: #0f172a; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ag-src-win__meta { font-size: 11px; color: #64748b; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ag-src-win__btn {
    width: 28px; height: 28px; border: 0; border-radius: 6px; background: transparent;
    color: #475569; cursor: pointer; flex-shrink: 0;
}
.ag-src-win__btn:hover { background: #e2e8f0; color: #0f172a; }
.ag-src-win__body { flex: 1; min-height: 0; background: #f1f5f9; }
.ag-src-win__frame { width: 100%; height: 100%; border: 0; display: block; }
.ag-src-win.is-dragging .ag-src-win__frame { pointer-events: none; }
.ag-src-win__note { display: flex; align-items: center; justify-content: center; gap: 8px; height: 100%; margin: 0; padding: 0 16px; font-size: 13px; color: #64748b; text-align: center; }
.ag-src-win__note--error { color: #b91c1c; }
.ag-src-win__resize {
    position: absolute; right: 0; bottom: 0; width: 16px; height: 16px; cursor: nwse-resize; touch-action: none;
    background: linear-gradient(135deg, transparent 50%, #94a3b8 50%, #94a3b8 60%, transparent 60%, transparent 72%, #94a3b8 72%, #94a3b8 82%, transparent 82%);
}

/* ── Flat builder: a number carried from the uploaded PDF (#489) ─────────────
   Editable text, not a computed label. Wide enough to click into when it is
   empty — a new line has no number until the clerk types one. */
.flat-num-cell {
    display: inline-block; min-width: 2.5em; min-height: 1.4em; padding: 1px 4px;
    border-radius: 4px; outline: none; cursor: text; vertical-align: middle;
}
.flat-num-cell:empty { background: #f8fafc; box-shadow: inset 0 0 0 1px #e2e8f0; }
.flat-num-cell:focus { background: #eff6ff; box-shadow: 0 0 0 2px #3b82f6; }

/* Speakers tab — the transient "Undo merge", which only appears just after a merge. */
.ts-undo-merge { display: flex; justify-content: flex-end; margin-bottom: var(--gv-space-3); }

/* Speakers tab — the voice row's right-hand end. The person control keeps gv-row's own
 * position (pinned right, fixed width) and the voiceprint sits immediately to its left.
 * The voice takes whatever is left, with min-width:0 so a long label truncates instead of
 * pushing the columns apart — constraining .gv-row__body instead collapsed the lede onto
 * its caret, and a fixed-width lede beside the 14rem picker overflowed the row. */
#ts-speaker-list .gv-row__lede { flex: 1 1 auto; min-width: 0; }
/* 4px between the person control and the icons, matching the gap BETWEEN the icons,
 * so the three read as one cluster belonging to that person rather than as two
 * groups. gv-row's own aside gap is 8px, which is right where an aside holds
 * unrelated controls; here it does not. */
#ts-speaker-list .gv-row__aside { gap: var(--gv-space-1); }
/* 8px from the fingerprint to the row's outer edge, down from 12. The row draws its own
 * 1px border, so the padding is one border-width short of the 8px the eye measures against.
 * Scoped to the roster: .gv-row__head's 12px is right on Discussions and Votes, where the
 * aside carries wider controls that would crowd the edge at 8. */
#ts-speaker-list .gv-row__head { padding-right: calc(var(--gv-space-2) - var(--gv-border-width)); }
/* The voiceprint: one control per row, and it is the state as well. 24px rather than the
 * 22px of the icon buttons — this one is genuinely interactive, and 22 is under the WCAG
 * 2.5.8 target-size minimum.
 *
 * Three tones, and the first two are the step palette rather than tones of their own:
 * --gv-step-done where the VoicePrint exists, --gv-step-progress where it still has to be
 * trained. A trained voice is a finished piece of work and an untrained one is work in
 * progress, so they read as the green and amber a clerk already knows from the dashboard
 * chain and the tab strip. Faint stays faint for "no person assigned", which is not a step
 * that has not started — it is a step that does not apply, and the control is disabled.
 * The rule and wash arrive on hover AND focus — a control whose only affordance is :hover
 * is a control a keyboard user never learns is one. */
.ts-voice-state { flex: 0 0 auto; display: flex; align-items: center; }
.ts-voice-print {
  width: 24px; height: 24px;
  display: inline-flex; align-items: center; justify-content: center;
  border: var(--gv-border-width) solid transparent;
  border-radius: var(--gv-radius-sm);
  background: transparent;
  font-size: var(--gv-text-sm);
  cursor: pointer;
}
.ts-voice-print.is-on   { color: var(--gv-step-done); }
/* NOT YET IS GREY (Vinny, 2026-10-24), not the step amber above. On this list amber is the edge
 * on a voice nobody is on, the one thing still owed; an untrained VoicePrint beside an assigned
 * voice wore the same colour and read as a second thing wrong. Training is optional work, so it
 * is quiet until pointed at, and its hover is the neutral wash. */
.ts-voice-print.is-off  { color: var(--gv-text-subtle); }
/* An AI guess (#178, option B): a person the clerk still has to confirm, so it keeps the amber,
 * with the AI nib. */
.ts-voice-print.is-guess { color: var(--gv-step-progress); }
.ts-voice-print.is-guess:hover:not(:disabled), .ts-voice-print.is-guess:focus-visible {
  color: var(--gv-step-progress-hover);
  border-color: var(--gv-warning-border); background: var(--gv-warning-bg);
}
.ts-voice-print.is-none { color: var(--gv-border); cursor: not-allowed; }
.ts-voice-print.is-on:hover:not(:disabled), .ts-voice-print.is-on:focus-visible {
  color: var(--gv-step-done-hover);
  border-color: var(--gv-brand-border); background: var(--gv-brand-bg);
}
.ts-voice-print.is-off:hover:not(:disabled), .ts-voice-print.is-off:focus-visible {
  color: var(--gv-text);
  border-color: var(--gv-border-strong); background: var(--gv-surface-sunk);
}
/* Held while VoicePrints match (#1147) as well as with nobody assigned: .gv-btn's disabled look. */
.ts-voice-print:disabled { cursor: not-allowed; opacity: 0.55; }
/* Whether a voice's line moves have saved (#897): quiet while it goes well, the danger stop
   with a Try again when it does not. Sits at the far end of the panel's count line. */
.ts-bd-save {
    display: inline-flex;
    align-items: center;
    gap: var(--gv-space-2);
    font-size: var(--gv-text-2xs);
    color: var(--gv-text-muted);
    white-space: nowrap;
}
.ts-bd-save .is-error { color: var(--gv-danger-fg); font-weight: var(--gv-weight-medium); }
/* Settings → Boards → Members (#860). A board's own group name, edited in place: it is
 * the heading, so it looks like one until you click it. */
/* A "?" beside a column heading that explains it on hover or keyboard focus. */
.bm-hint { position: relative; color: var(--gv-text-subtle); font-size: 11px; line-height: 1; cursor: help; text-transform: none; letter-spacing: 0; }
.bm-hint:hover, .bm-hint:focus-visible { color: var(--gv-text-muted); }
.bm-hint::after {
  content: attr(data-hint);
  position: absolute; z-index: 30; top: calc(100% + 6px); left: 50%; transform: translateX(-50%);
  width: 16rem; padding: 8px 10px;
  background: var(--gv-text); color: #fff;
  font-size: 12px; font-weight: 400; line-height: 1.4; text-align: left; white-space: normal;
  border-radius: var(--gv-radius-sm);
  box-shadow: 0 4px 12px rgba(0,0,0,.15);
  opacity: 0; pointer-events: none; transition: opacity var(--gv-dur-fast);
}
.bm-hint:hover::after, .bm-hint:focus-visible::after { opacity: 1; }

/* The same two states on Settings → Boards → Voice prints, where a member's card reports
 * whether their VoicePrint exists. It reads from the same tokens as the fingerprint above
 * rather than from tones of its own: green means trained on both screens, grey means not yet
 * on both (amber until 2026-10-24), and a clerk who learns it in one place has learned it in
 * the other. The card's per-member gradient is identity, not status, and is left alone.
 *
 * These classes exist because the values used to be a Tailwind literal (text-emerald-600)
 * and an inline style. Both beat a token class — the literal on specificity and source
 * order, the inline style outright — so the call site had to stop painting for the token
 * to mean anything. That is the failure #385 ended for the step chain. */
.vp-state.is-on  { color: var(--gv-step-done); }
.vp-state.is-off { color: var(--gv-text-subtle); }

/* A duplicate's merge mark: a real button, because a clickable pill that is not one is
 * unreachable by keyboard. Since #178 it is the design system's quiet text control
 * (.gv-barlink: dotted underline at rest, solid on hover) in the warning text tone, with the
 * merge glyph, on the name's line: the pill it replaced wrapped the row onto two. Still 24px
 * tall, the floor the fingerprint holds, because WCAG 2.5.8 sets 24px as the minimum target;
 * the height is on the BOX, so the label stays small while the target doesn't. */
.ts-voice-dup {
  display: inline-flex;
  align-items: center;
  gap: var(--gv-space-1);
  min-height: 24px;
  flex: 0 1 auto;
  min-width: 0;
  color: var(--gv-warning-fg);
  font-size: var(--gv-text-2xs);
  white-space: nowrap;
}
.ts-voice-dup .fa-code-merge { font-size: var(--gv-text-3xs); }
.ts-voice-dup__text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ts-voice-dup:disabled { cursor: not-allowed; opacity: 0.55; }
/* Never into the Title column: the mark is the last thing on the name's line and the one that
 * gives way, ending in an ellipsis inside its own box rather than spilling over. */
#ts-speaker-list .gv-row__titleline { overflow: hidden; }

/* A voice row titled by its person (#178): the name is the picker, then Title, Group and
 * VoicePrint across the line as columns, each changed by clicking it where it is. Every one
 * of those is the design system's quiet text control, .gv-barlink, the same one the
 * transcript's "Other ▾" uses; .ts-voice-link only lays it out (one line, trimmed, a 24px
 * target). Fixed widths, shared with the headings (mbSpeakerColsHtml), so the columns line up
 * down the list and the slack goes after the last one, not between a name and its title. */
/* ONE grid for the headings and every row (#178), as Settings → Boards → Members has one grid
 * for its heading row and its lines (#1064), so the columns can't drift apart: flex let a row
 * with "+ Add title" shrink differently from one with a title, and Group and VoicePrint wandered.
 * The row's aside, and the headings' cells, are display: contents, so each cell is a track of
 * the row itself. The row runs the full width (Ryan, 2026-10-23): the name and Time spoken
 * keep the left, VoicePrint sits against the right edge, and Title and Group sit just left of
 * it, so the slack goes between Time spoken and Title rather than squeezing the columns.
 * When space is short, Title and Group shrink before anything is hidden, ending in an ellipsis
 * (the full text is in each one's hover and label). */
#ts-speaker-list .gv-row__head, .ts-voice-cols {
  display: grid;
  grid-template-columns: minmax(17rem, 1fr) minmax(4.5rem, 13rem) minmax(4.5rem, 11rem) minmax(6rem, 7rem);
  column-gap: var(--gv-space-2);
  align-items: center;
}
#ts-speaker-list .gv-row__aside, .ts-voice-cols__cells { display: contents; }
#ts-speaker-list .gv-row__lede { min-width: 0; }
/* The voices as ONE card with dividers (#178), the way Settings → Boards → Members lists its
 * people, rather than a separate box per voice: 28 voices were 28 boxes. Scoped to this list,
 * so Discussions and Votes keep their own rows. The left edges (done / still owed) stay. An
 * open or pointed-at row sits above its neighbours, so its own border shows. */
#ts-speaker-list .gv-rows { gap: 0; }
#ts-speaker-list .gv-rows > .gv-row { position: relative; border-radius: 0; margin-top: calc(-1 * var(--gv-border-width)); }
#ts-speaker-list .gv-rows > .gv-row:first-child { margin-top: 0; border-top-left-radius: var(--gv-radius-md); border-top-right-radius: var(--gv-radius-md); }
#ts-speaker-list .gv-rows > .gv-row:last-child { border-bottom-left-radius: var(--gv-radius-md); border-bottom-right-radius: var(--gv-radius-md); }
#ts-speaker-list .gv-rows > .gv-row.is-open, #ts-speaker-list .gv-rows > .gv-row:hover { z-index: 1; }
#ts-speaker-list .gv-row__aside { margin-left: 0; }
#ts-speaker-list .gv-row__titleicon { width: 1rem; text-align: center; }
.ts-voice-cell { min-width: 0; display: flex; align-items: center; }
/* VoicePrint against the right edge, its heading with it. */
#ts-speaker-list .gv-row__head > .gv-row__aside > .ts-voice-state, .ts-voice-cols .ts-voice-state { justify-content: flex-end; }
.ts-voice-link {
  display: inline-flex; align-items: center; gap: var(--gv-space-1);
  max-width: 100%; min-width: 0; min-height: var(--gv-control-xs);
  font-size: var(--gv-text-sm); text-align: left; white-space: nowrap;
}
.ts-voice-cell__text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A cell never paints past its column: the link inside it is held to the cell's width. */
.ts-voice-cell > .ts-voice-link { max-width: 100%; overflow: hidden; }
.ts-voice-link .fa-chevron-down { flex: 0 0 auto; font-size: var(--gv-text-3xs); color: var(--gv-text-subtle); }
.ts-voice-link .fa-plus { font-size: var(--gv-text-3xs); }
.ts-voice-link.is-empty { color: var(--gv-text-subtle); }
.ts-voice-title .ts-voice-link.is-empty { font-size: var(--gv-text-xs); }
.ts-voice-link:disabled { cursor: not-allowed; opacity: 0.55; text-decoration: none; }
/* No underline in the voices or on Attendance, at rest or under the pointer (Vinny, 2026-10-23):
 * every name, title and group carried .gv-barlink's dotted one, and the lists read as a page of
 * links. They are still buttons: the pointer, the keyboard focus ring and the field that opens
 * in place are what say a cell can be changed. :hover is named so .gv-barlink's solid one
 * can't come back on source order. */
#ts-speaker-list .ts-voice-link, #ts-speaker-list .ts-voice-link:hover,
.ts-person-list .ts-voice-link, .ts-person-list .ts-voice-link:hover { text-decoration: none; }
/* The name leads the row, so it carries the title's size, at a set width so every row's Time
 * spoken starts at the same x. A long name ends in an ellipsis; the full name is in the
 * button's label. Regular weight (Vinny, 2026-10-23): a column of bold names down two lists was
 * the heaviest thing on the step; the size and the first column already say it leads. */
#ts-speaker-list .ts-voice-name { flex: 0 0 10rem; max-width: 10rem; font-size: var(--gv-text-base); font-weight: var(--gv-weight-normal); }
/* A voice with nobody on it: its own label in the name's place, in the warning text tone
 * (4.5:1 on white), matching the amber edge that marks the row as still owed. */
.ts-voice-name.is-todo, .ts-voice-name.is-todo .fa-chevron-down { color: var(--gv-warning-fg); }
/* A voice the clerk set aside (#585): "Ignored" after its label, the size and quiet of the
 * VoicePrint column's Not yet (.bm-vp-word.is-off). The row's dotted rail says the rest. */
.ts-voice-ignored { flex: 0 0 auto; font-size: var(--gv-text-xs); color: var(--gv-text-subtle); }
/* The fingerprint with its word inside: the whole of "◉ Saved" trains. .ts-voice-print's own
 * height, rule and wash, right-aligned in its column so the words line up there. Saved / Not yet is
 * Settings → Boards → Members' .bm-vp-word. */
.ts-voice-state .ts-voice-print { width: auto; gap: var(--gv-space-1); padding: 0 var(--gv-space-2); }
/* Room on the right (Ryan, 2026-10-23): flush against the card's edge it read as crowded. */
#ts-speaker-list .gv-row__head > .gv-row__aside > .ts-voice-state, .ts-voice-cols .ts-voice-state { padding-right: var(--gv-space-3); }
.ts-voice-state .bm-vp-word { margin-left: 0; font-size: var(--gv-text-xs); }
/* The share of speaking time as plain grey text, not a pill: it's on every row, and the pill
 * was chrome around a number. Still the .gv-badge node, which a line move rewrites in place
 * (mbBdBadgesRepaint). */
#ts-speaker-list .gv-row__titleline > .gv-badge {
  padding: 0; border: none; background: none;
  font-size: var(--gv-text-xs); font-weight: var(--gv-weight-normal); color: var(--gv-text-subtle);
}
/* The shares RIGHT-ALIGNED, here and on Attendance (.ts-att-share), in a box as wide as "100%",
 * the widest a share reads (33.8px at this size, measured), so the % signs line up down both
 * lists; their mic headings sit over that edge (Vinny, 2026-10-23). min-width, so a wider face
 * grows the box rather than cutting the number. */
#ts-speaker-list .gv-row__titleline > .gv-badge, .ts-att-share { min-width: 2.25rem; justify-content: flex-end; }
.ts-voice-cols__time, .ts-person-cols__time { flex: 0 0 2.25rem; text-align: right; }
/* A name or title typed in its own place: .gv-input at the cell's width, so nothing shifts. */
.ts-voice-name__input { flex: 0 0 10rem; width: 10rem; font-weight: var(--gv-weight-normal); }
.ts-voice-cell__input { width: 100%; min-height: var(--gv-control-xs); padding-top: 0; padding-bottom: 0; font-size: var(--gv-text-sm); }
/* The headings: the row head's padding, the caret's width and the gaps the row uses, so
 * Speaker sits over the names and the rest over their cells. Settings → Boards → Members'
 * heading type (.bm-cols): small, semibold, subtle. */
.ts-voice-cols {
  padding: 0 calc(var(--gv-space-2) - var(--gv-border-width)) var(--gv-space-1) calc(var(--gv-space-3) + var(--gv-border-width));
  font-size: var(--gv-text-2xs); font-weight: var(--gv-weight-semibold); color: var(--gv-text-subtle);
}
.ts-voice-cols__who { display: flex; min-width: 0; padding-left: calc(var(--gv-control-xs) + var(--gv-space-2)); }
/* Headings stay on one line, as the rows do, so the heading row never grows taller than a row. */
.ts-voice-cols span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* Over the name: the mic's 1rem, the title line's two gaps and the name's 10rem, so Time
 * spoken starts where the shares do. */
.ts-voice-cols__name { flex: 0 0 calc(1rem + 2 * var(--gv-space-2) + 10rem); }
/* The columns answer to the LIST's width, not the window's. Beside the recording on a 1280px
 * screen the list is ~610px (measured). Title and Group are only changed here, so they never
 * go: below their set widths they shrink and end in an ellipsis (the full text is in each
 * one's hover and label). Time spoken stays (Vinny, 2026-10-23): it gave way under 46rem, which
 * beside the recording is always, and it is in no hover, so the share was simply gone there.
 * The name column holds it at the narrowest the grid allows. Only a phone-narrow list drops
 * Title, Group, the share and the headings. */
#ts-speaker-list { container: ts-voices / inline-size; }
@container ts-voices (max-width: 36rem) {
  .ts-voice-title, .ts-voice-group, .ts-voice-cols { display: none; }
  #ts-speaker-list .gv-row__titleline > .gv-badge { display: none; }
  #ts-speaker-list .gv-row__head { grid-template-columns: minmax(0, 1fr) auto; }
  /* The name keeps its width and the merge mark wraps under it, rather than the name
   * shrinking to "B…" to make room for it. */
  #ts-speaker-list .gv-row__titleline { flex-wrap: wrap; row-gap: var(--gv-space-1); }
  #ts-speaker-list .ts-voice-name { flex: 0 0 auto; max-width: 100%; }
}

/* Attendance, the shape of the voice rows and in their columns (#1185): one
 * card with dividers under headings that share one grid with the rows, and a person's name and
 * title changed by clicking them where they are. Each row is a static GV.row (nothing opens),
 * titled by the name control; its cells are the voice rows' (.ts-voice-cell, .ts-voice-link).
 * Rules of their own rather than added to the #ts-speaker-list selectors, which
 * check-speaker-card.js pins.
 *
 * THE VOICE LIST'S GRID, track for track, with its head padding and its last cell's (Vinny,
 * 2026-10-23): the three lists sit in the same panel at the same width, so Title stands over
 * Title and Group over Group from the top of the panel to the bottom.
 *   Name     the tick (Attendance) or the person glyph, the name and its tags
 *   Title    as a voice's
 *   Group    as a voice's; empty on an added speaker, who has none
 *   (last)   where a voice has its VoicePrint, unheaded: the roll call's play control, or the
 *            remove for someone added by hand, whom the roll call never named
 * --ts-person-name-x is where the name starts inside a row: the reserved caret, the lead (the
 * tick) or the person glyph, and the two gaps between them. The Name heading, the divider and
 * the board note start there too. */
.ts-person-list {
  container: ts-people / inline-size;
  --ts-person-name-x: calc(var(--gv-text-sm) * var(--gv-leading-snug) + var(--gv-control-3xs) + 2 * var(--gv-space-2));
}
.ts-person-list .gv-row__head, .ts-person-cols {
  display: grid;
  grid-template-columns: minmax(17rem, 1fr) minmax(4.5rem, 13rem) minmax(4.5rem, 11rem) minmax(6rem, 7rem);
  column-gap: var(--gv-space-2);
  align-items: center;
}
.ts-person-list .gv-row__head { padding-right: calc(var(--gv-space-2) - var(--gv-border-width)); }
.ts-person-list .gv-row__head > .gv-row__aside > .ts-person-state, .ts-person-cols .ts-person-state {
  justify-content: flex-end;
  padding-right: var(--gv-space-3);
}
.ts-person-list .gv-row__aside { display: contents; }
.ts-person-list .gv-row__lede { min-width: 0; }
.ts-person-list .gv-row__titleline { overflow: hidden; }
/* ...except while a name is typed in it (Vinny, 2026-10-23): the line is the field's height, so
 * the clip cut the top and bottom off the focus ring and left two green brackets either side.
 * The field holds its own width (.ts-person-name__input), so nothing spills while it's open. The
 * voice rows clip their line for the same reason, and open the same field. */
.ts-person-list .gv-row__titleline:has(> .gv-input),
#ts-speaker-list .gv-row__titleline:has(> .gv-input) { overflow: visible; }
.ts-person-list .gv-row__titleicon { width: 1rem; text-align: center; color: var(--gv-text-disabled); }
/* One card with dividers, as #ts-speaker-list draws its voices: every row (and the group
 * divider) shares the border of the one above it, and only the card's corners are round. */
.ts-person-list .gv-rows { gap: 0; }
.ts-person-list .gv-rows > * { position: relative; border-radius: 0; margin-top: calc(-1 * var(--gv-border-width)); }
.ts-person-list .gv-rows > :first-child { margin-top: 0; border-top-left-radius: var(--gv-radius-md); border-top-right-radius: var(--gv-radius-md); }
.ts-person-list .gv-rows > :last-child { border-bottom-left-radius: var(--gv-radius-md); border-bottom-right-radius: var(--gv-radius-md); }
.ts-person-list .gv-rows > .gv-row:hover { z-index: 1; }
/* The Non-voting members divider (#1133, #1139): a labelled break inside the card, so nobody
 * reads those people as part of the count above, in the headings' type. */
.ts-person-divider {
  padding: var(--gv-space-1) var(--gv-space-3) var(--gv-space-1) calc(var(--gv-space-3) + var(--ts-person-name-x));
  border: var(--gv-border-width) solid var(--gv-border);
  background: var(--gv-surface-sunk);
  font-size: var(--gv-text-2xs);
  font-weight: var(--gv-weight-semibold);
  color: var(--gv-text-subtle);
}
/* The name leads the row, at a voice name's size and weight; it shrinks to an ellipsis before
 * its tags do, and the full name is its hover and label. */
.ts-person-list .ts-person-name { flex: 0 1 auto; font-size: var(--gv-text-base); font-weight: var(--gv-weight-normal); }
.ts-person-name__input { flex: 1 1 auto; min-width: 8rem; font-weight: var(--gv-weight-normal); }
.ts-person-title .ts-voice-link.is-empty { font-size: var(--gv-text-xs); }
/* A group that can't be changed here (a voting member's, an alternate's) is plain text in the
 * picker's own size, so the column reads as one column whichever it is. A step quieter than the
 * name and title (Vinny, 2026-10-23): it is the same "Voting Members" on most rows and can't be
 * clicked, so the cells that can stand out from it. */
.ts-person-group > .ts-voice-cell__text { font-size: var(--gv-text-sm); color: var(--gv-text-muted); }
/* The alt and this meeting tags say what the Group column says, so they show only where it's
 * hidden. */
.ts-person-tag { display: none; }
/* The board note while a board member's name or title is open (#1138), under the row's head and
 * level with the name it is about. */
.ts-person-note {
  margin: 0;
  padding: 0 var(--gv-space-3) var(--gv-space-2) calc(var(--gv-space-3) + var(--ts-person-name-x));
}
/* The headings, in the voice list's heading type and padding (.ts-voice-cols), and the name's own
 * start, so each sits over its column. */
.ts-person-cols {
  padding: 0 calc(var(--gv-space-2) - var(--gv-border-width)) var(--gv-space-1) calc(var(--gv-space-3) + var(--gv-border-width));
  font-size: var(--gv-text-2xs); font-weight: var(--gv-weight-semibold); color: var(--gv-text-subtle);
}
.ts-person-cols__name { padding-left: var(--ts-person-name-x); }
/* ATTENDANCE'S SHARE COLUMN, at the voices' (Vinny, 2026-10-23): under a mic heading, as the
 * voice list heads its own, and starting at the same x, so the two lists' shares line up down the
 * panel. A voice's share starts after the caret button, a gap, the mic's 1rem, a gap, the 10rem
 * name and a gap; --ts-att-name-w is what's left of that once an Attendance name has started
 * (--ts-person-name-x) and before its own gap, so the name is held to it, open field included. */
.ts-att-list { --ts-att-name-w: calc(var(--gv-control-xs) + 2 * var(--gv-space-2) + 11rem - var(--ts-person-name-x)); }
.ts-att-list .ts-person-name { flex: 0 0 auto; width: var(--ts-att-name-w); max-width: var(--ts-att-name-w); }
.ts-att-list .ts-person-name__input { flex: 0 0 var(--ts-att-name-w); width: var(--ts-att-name-w); min-width: 0; }
.ts-person-cols__who { display: flex; }
.ts-att-list .ts-person-cols__label { flex: 0 0 calc(var(--ts-att-name-w) + var(--gv-space-2)); }
.ts-person-cols span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* A phone-narrow list drops Title, Group and the headings, as the voice list does at the same
 * width, and the tags come back to say what Group did. */
@container ts-people (max-width: 36rem) {
  .ts-person-title, .ts-person-group, .ts-person-cols { display: none; }
  .ts-person-list .gv-row__head { grid-template-columns: minmax(0, 1fr) auto; }
  /* No share heading to line up under, so the name takes what it needs, as a voice's does. */
  .ts-att-list .ts-person-name { flex: 0 1 auto; width: auto; max-width: 100%; }
  .ts-person-tag { display: inline; }
}

/* Training, displaced into the panel on a row where Merge took the slot. */
/* .ts-voice-panel-actions and .ts-voice-hint are gone with the panel copy of the
 * Train button: the row shows it directly now, on every assigned voice. */


/* =============================================================================
 * Sign-in screen (#auth-screen in app.html). Half of it is a short pitch for
 * people who land on app.govably.com without knowing Govably (ChatGPT links
 * here), styled after govably.com's homepage: cream panel, Fraunces headline.
 * Layout is Tailwind in the markup; these are the parts Tailwind can't say.
 * ============================================================================= */
.auth-pitch { background: var(--gv-paper-2); }
.auth-brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; }
.auth-brand img { width: 34px; height: 34px; padding: 6px; border-radius: 9px; background: var(--gv-brand-900); object-fit: contain; }
.auth-brand span { font-size: 21px; font-weight: 700; color: var(--gv-brand-900); letter-spacing: -.01em; }
.auth-eyebrow { font-family: var(--gv-font-mono); font-size: 12px; letter-spacing: .16em; text-transform: uppercase; color: var(--gv-brand-700); margin: 0 0 14px; }
.auth-h1 { font-family: 'Fraunces', Georgia, serif; font-weight: 700; font-size: clamp(36px, 4vw, 54px); line-height: 1.04; letter-spacing: -.02em; color: var(--gv-brand-900); margin: 0 0 18px; }
/* The hand-drawn underline, as a mask so its colour comes from the token. */
.auth-scribble { position: relative; white-space: nowrap; }
.auth-scribble::after {
    content: ''; position: absolute; left: -4px; right: -4px; bottom: -6px; height: 8px;
    background: var(--gv-brand-600);
    -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 8' preserveAspectRatio='none'><path d='M2 5 Q 25 1, 50 4 T 100 4 T 150 4 T 198 4' stroke='black' stroke-width='2.5' fill='none' stroke-linecap='round'/></svg>") no-repeat 0 0 / 100% 100%;
            mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 8' preserveAspectRatio='none'><path d='M2 5 Q 25 1, 50 4 T 100 4 T 150 4 T 198 4' stroke='black' stroke-width='2.5' fill='none' stroke-linecap='round'/></svg>") no-repeat 0 0 / 100% 100%;
}
.auth-benefit { display: flex; gap: 12px; align-items: flex-start; font-size: 15.5px; line-height: 1.5; color: var(--gv-ink-700); }
.auth-benefit b { color: var(--gv-text); }
.auth-benefit i { flex: none; width: 28px; height: 28px; border-radius: 8px; background: var(--gv-brand-100); color: var(--gv-brand-800); display: grid; place-items: center; font-size: 13px; margin-top: 1px; }
.auth-proof { margin-top: 34px; padding-top: 22px; border-top: 1px solid var(--gv-ink-200); display: flex; align-items: center; gap: 18px; }
.auth-proof p { margin: 0; font-size: 14px; color: var(--gv-text-muted); line-height: 1.45; }
.auth-proof-nums { font-weight: 800; font-size: 22px; letter-spacing: -.02em; white-space: nowrap; }
.auth-proof-nums s { color: var(--gv-ink-400); text-decoration-thickness: 2px; }
.auth-proof-nums i { color: var(--gv-brand-600); font-size: 14px; margin: 0 6px; }
.auth-proof-nums b { color: var(--gv-brand-800); }
@media (max-width: 1023px) {
    .auth-proof { flex-direction: column; align-items: flex-start; gap: 6px; }
}

