/* Refresh components — page chrome + every shared UI component.
   Split out of the original refresh_shell.css; tokens live in tokens.css. */

/* ===== Baseline ===== */
html, body {
    background: var(--pt-bg);
    color: var(--pt-fg);
    font-family: "DM Sans", ui-sans-serif, system-ui, sans-serif;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}
:where(button, a, input, textarea, select, [tabindex]):focus { outline: none; }
:where(button, a, input, textarea, select, [tabindex]):focus-visible {
    outline: none;
    box-shadow: var(--pt-focus-ring);
    border-radius: var(--pt-radius-sm);
}
[x-cloak] { display: none !important; }

/* ===== Icon button (shared, used by pages) ===== */
.icon-btn {
    width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--pt-radius-pill); border: 1px solid var(--pt-border);
    background: var(--pt-surface); color: var(--pt-fg-muted); cursor: pointer;
    transition: color var(--pt-dur-instant), border-color var(--pt-dur-instant),
                transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.icon-btn:hover { color: var(--pt-fg); border-color: var(--pt-fg); }
.icon-btn.is-on { background: var(--pt-fg); color: var(--pt-surface); border-color: var(--pt-fg); }
.icon-btn [class^="ph-"], .icon-btn [class*=" ph-"] { font-size: var(--pt-text-md); }

.avatar-circle {
    width: 36px; height: 36px; border-radius: 50%;
    background: var(--pt-rocket-flame-20); color: var(--pt-ink-on-flame-20);
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 600; font-size: var(--pt-text-xs);
}
[data-theme="dark"] .avatar-circle { color: var(--pt-rocket-flame); }

/* ===== Sidebar ===== */
.sidebar {
    position: fixed; top: 0; left: 0; bottom: 0; width: var(--sidebar-w); z-index: 100;
    background: var(--pt-bg); display: flex; flex-direction: column;
    border-right: 1px solid var(--pt-border);
    /* Collapse animates width here, margin on .main-content and left on .save-bar, all
       off the same --sidebar-w flip. None can be a transform (the rail's contents
       genuinely reflow and the main column must actually get wider), so every frame
       relayouts the document — including a long data table. Kept at --pt-dur-fast to
       keep that relayout window short. */
    transition: transform var(--pt-dur-fast) var(--pt-ease-paper),
                width var(--pt-dur-fast) var(--pt-ease-paper);
}
.sidebar-brand {
    display: flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-4) var(--pt-space-4) var(--pt-space-3);
}
.sidebar-brand-link {
    display: inline-flex; flex-direction: column; align-items: flex-start; gap: var(--pt-space-1);
    text-decoration: none; flex: 1; min-width: 0;
}
.sidebar-brand-row { display: flex; align-items: center; gap: var(--pt-space-3); align-self: stretch; min-width: 0; }
.sidebar-brand-mark { width: 42px; height: auto; display: block; flex: none; }
.sidebar-brand-title { font-weight: 600; font-size: var(--pt-text-lg); color: var(--pt-fg); letter-spacing: -0.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.sidebar-search {
    margin: 0 var(--pt-space-3) var(--pt-space-2);
    position: relative;
}
/* Styled like a search input, but it's a button that opens the command palette. */
.sidebar-search-btn {
    width: 100%; height: 38px; display: block;
    /* Off-grid padding = clearance for the absolutely-positioned magnifier (left)
       and the ⌘K kbd chip (right), not rhythm spacing. */
    padding: 0 44px 0 38px; font-size: var(--pt-text-sm); text-align: left;
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-md);
    color: var(--pt-fg-muted); font-family: inherit; cursor: pointer;
}
.sidebar-search-btn:hover { border-color: var(--pt-fg-muted); }
.sidebar-search-btn__label { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-search [class^="ph-"],
.sidebar-search [class*=" ph-"] {
    position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
    color: var(--pt-fg-muted); font-size: var(--pt-text-md); pointer-events: none;
}
.sidebar-search kbd {
    position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
    font-size: var(--pt-text-2xs); font-weight: 600; padding: 2px var(--pt-space-2); line-height: 16px;
    background: var(--pt-bg); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-md); color: var(--pt-fg-muted);
    font-family: inherit;
}

.sidebar-nav { flex: 1; padding: var(--pt-space-1) var(--pt-space-2) var(--pt-space-4); overflow-y: auto; }
.nav-section-header {
    font-size: var(--pt-text-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em;
    color: var(--pt-fg-muted); padding: 0 var(--pt-space-3); margin-bottom: var(--pt-space-2);
}
.sidebar-link {
    display: flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-2) var(--pt-space-3); font-size: var(--pt-text-sm); font-weight: 500;
    color: var(--pt-fg); border-radius: var(--pt-radius-md); text-decoration: none;
    transition: background var(--pt-dur-instant);
    border: 0; background: transparent; cursor: pointer; text-align: left;
    width: 100%;
}
.sidebar-link:hover { background: var(--pt-surface); }
.sidebar-link.active { background: var(--pt-rocket-flame-20); color: var(--pt-ink-on-flame-20); font-weight: 600; }
[data-theme="dark"] .sidebar-link.active { color: var(--pt-rocket-flame); }
.sidebar-link [class^="ph-"], .sidebar-link [class*=" ph-"] { font-size: var(--pt-text-lg); opacity: 0.85; }
.sidebar-link .count { margin-left: auto; font-size: var(--pt-text-xs); font-weight: 500; color: var(--pt-fg-muted); }
.sidebar-link.active .count { color: var(--pt-ink-on-flame-20); }
[data-theme="dark"] .sidebar-link.active .count { color: var(--pt-rocket-flame); }

/* ===== Workspace accordion ===== */
.workspace-group { margin-bottom: var(--pt-space-1); }
.workspace-header {
    display: flex; align-items: center; gap: var(--pt-space-2);
    width: 100%; padding: var(--pt-space-2) var(--pt-space-3);
    font-size: var(--pt-text-sm); font-weight: 600;
    color: var(--pt-fg); background: transparent; border: 0;
    border-radius: var(--pt-radius-md);
    cursor: pointer; text-align: left;
    transition: background var(--pt-dur-instant);
}
.workspace-header:hover { background: var(--pt-surface); }
.workspace-header [class^="ph-"], .workspace-header [class*=" ph-"] { font-size: var(--pt-text-lg); }
.workspace-header .workspace-label { flex: 1; min-width: 0; }
.workspace-chev {
    font-size: var(--pt-text-xs) !important; color: var(--pt-fg-muted);
    /* Same clock as the panel below — a faster chevron finishes first and reads as
       two separate movements. */
    transition: transform var(--pt-dur-base) var(--pt-ease-paper);
}
.workspace-group.is-open .workspace-chev { transform: rotate(90deg); }

/* Closed = a zero-height grid row (not display:none) so open/close can animate.
   0fr -> 1fr interpolates natively, so the whole thing is CSS: no measuring, no inline
   pixel height, nothing for the toggle to keep in sync. __clip supplies the min-height:0
   + overflow:hidden that make the fractional row actually clip its content.
   visibility keeps closed links out of the tab order; padding + border-color ride along
   so no sliver of rail shows when closed. */
.workspace-children {
    display: grid; grid-template-rows: 0fr;
    visibility: hidden;
    padding: 0 0 0 var(--pt-space-3);
    margin-left: var(--pt-space-2);
    border-left: 1px solid transparent;
    transition: grid-template-rows var(--pt-dur-base) var(--pt-ease-paper),
                padding var(--pt-dur-base) var(--pt-ease-paper),
                border-color var(--pt-dur-base) var(--pt-ease-paper),
                visibility var(--pt-dur-base);
}
.workspace-group.is-open .workspace-children {
    grid-template-rows: 1fr;
    visibility: visible;
    padding: var(--pt-space-1) 0 var(--pt-space-2) var(--pt-space-3);
    border-left-color: var(--pt-border);
}
.workspace-children__clip { min-height: 0; overflow: hidden; }
.workspace-children .sidebar-link { padding: var(--pt-space-2) var(--pt-space-3); font-size: var(--pt-text-sm); }
.workspace-children .sidebar-link [class^="ph-"],
.workspace-children .sidebar-link [class*=" ph-"] { font-size: var(--pt-text-lg); }
.workspace-subheader {
    margin-top: var(--pt-space-2); padding: 0 var(--pt-space-3);
}
/* Flyout title — only shown inside the hover flyout when the rail is collapsed. */
.flyout-title {
    display: none;
    font-size: var(--pt-text-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em;
    color: var(--pt-fg-muted); padding: var(--pt-space-1) var(--pt-space-3) var(--pt-space-2);
}

.sidebar-footer {
    /* min-height (not height) so the collapsed vertical icon stack can grow past it. */
    min-height: var(--bottom-bar-h); box-sizing: border-box;
    padding: var(--pt-space-2); border-top: 1px solid var(--pt-border);
    display: flex; align-items: center; gap: var(--pt-space-2);
}
.profile-card {
    display: flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-2); border-radius: var(--pt-radius-md);
    background: transparent; border: 0;
    flex: 1; min-width: 0; text-align: left; cursor: pointer;
    transition: background var(--pt-dur-instant);
}
.profile-card:hover { background: var(--pt-surface); }
.profile-card > span:nth-child(2) { flex: 1; min-width: 0; overflow: hidden; }
.profile-card-name { font-size: var(--pt-text-xs); font-weight: 600; line-height: 1.2; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.profile-card-role { font-size: var(--pt-text-2xs); color: var(--pt-fg-muted); display: block; }
.sidebar-icon-btn {
    width: 32px; height: 32px; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--pt-radius-md); border: 0;
    background: transparent; color: var(--pt-fg-muted); cursor: pointer;
    transition: background var(--pt-dur-instant), color var(--pt-dur-instant), transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.sidebar-icon-btn:hover { background: var(--pt-surface); color: var(--pt-fg); }
.sidebar-icon-btn [class^="ph-"], .sidebar-icon-btn [class*=" ph-"] { font-size: var(--pt-text-md); }

.mobile-sidebar-toggle {
    display: none;
    position: fixed; top: 12px; left: 12px; z-index: 120;
    width: 36px; height: 36px;
    border-radius: var(--pt-radius-md); border: 1px solid var(--pt-border);
    background: var(--pt-bg); color: var(--pt-fg); cursor: pointer;
    align-items: center; justify-content: center;
}
.mobile-sidebar-toggle [class^="ph-"], .mobile-sidebar-toggle [class*=" ph-"] { font-size: var(--pt-text-lg); }

/* Collapse toggle — lives in the brand row, reuses the sidebar-icon-btn look. */
.sidebar-collapse-btn { flex-shrink: 0; }

/* ===== Collapsed rail (desktop only) =====
   Driven by data-sidebar-collapsed on <html>. Mobile keeps the full off-canvas
   panel, so all of this is scoped to the desktop breakpoint. */
@media (min-width: 1024px) {
    :root[data-sidebar-collapsed="true"] { --sidebar-w: 64px; }

    /* Brand: center the rocket, drop the wordmark. */
    [data-sidebar-collapsed="true"] .sidebar-brand { justify-content: center; padding: var(--pt-space-4) var(--pt-space-2) var(--pt-space-3); }
    [data-sidebar-collapsed="true"] .sidebar-brand-link { flex: none; align-items: center; }
    [data-sidebar-collapsed="true"] .sidebar-brand-row { justify-content: center; }
    [data-sidebar-collapsed="true"] .sidebar-brand-title { display: none; }

    /* Search collapses to a single icon button sized like the workspace icons:
       same 8px side inset (matching .sidebar-nav padding) and 40px height, so it
       doesn't read as a smaller pill. */
    [data-sidebar-collapsed="true"] .sidebar-search { margin: 0 var(--pt-space-2) var(--pt-space-2); }
    [data-sidebar-collapsed="true"] .sidebar-search-btn {
        height: 40px; padding: 0;
        display: flex; align-items: center; justify-content: center;
    }
    [data-sidebar-collapsed="true"] .sidebar-search-btn__label,
    [data-sidebar-collapsed="true"] .sidebar-search kbd { display: none; }
    [data-sidebar-collapsed="true"] .sidebar-search [class^="ph-"],
    [data-sidebar-collapsed="true"] .sidebar-search [class*=" ph-"] { position: static; transform: none; font-size: var(--pt-text-lg); }

    /* Let the flyout escape the nav's scroll box (4 icons never need to scroll). */
    [data-sidebar-collapsed="true"] .sidebar-nav { overflow: visible; }

    /* Workspace headers become centered icons; labels + chevrons hide. */
    [data-sidebar-collapsed="true"] .workspace-group { position: relative; }
    [data-sidebar-collapsed="true"] .workspace-header { justify-content: center; padding: var(--pt-space-3) 0; }
    [data-sidebar-collapsed="true"] .workspace-label,
    [data-sidebar-collapsed="true"] .workspace-chev { display: none; }
    /* Only the active workspace keeps a flame tint so "you are here" still reads.
       Keyed on is-current (not is-open) so persisted-open accordions don't all light up. */
    [data-sidebar-collapsed="true"] .workspace-group.is-current .workspace-header {
        background: var(--pt-rocket-flame-20); color: var(--pt-ink-on-flame-20);
    }
    [data-theme="dark"][data-sidebar-collapsed="true"] .workspace-group.is-current .workspace-header { color: var(--pt-rocket-flame); }

    /* Children pop out as a hover flyout instead of expanding inline. An open accordion
       closes through its own grid-row animation (mirrors the closed state above) rather
       than blinking out, so it rides the width tween. The hover flyout rule below still
       overrides all of this on hover, where the panel is sized by its content instead of
       by a grid row. */
    [data-sidebar-collapsed="true"] .workspace-children,
    [data-sidebar-collapsed="true"] .workspace-group.is-open .workspace-children {
        grid-template-rows: 0fr; visibility: hidden;
        padding: 0 0 0 var(--pt-space-3); border-left-color: transparent;
    }
    [data-sidebar-collapsed="true"] .workspace-group:hover .workspace-children {
        display: block; visibility: visible;
        position: absolute; left: calc(100% + 8px); top: 0; z-index: 110;
        min-width: 200px; padding: var(--pt-space-2); margin: 0; border: 1px solid var(--pt-border);
        border-radius: var(--pt-radius-md); background: var(--pt-surface);
    }
    /* Invisible bridge across the icon→flyout gap so the cursor can travel into the
       flyout diagonally without dropping :hover (which would close it). */
    [data-sidebar-collapsed="true"] .workspace-group:hover .workspace-children::before {
        content: ""; position: absolute; top: 0; bottom: 0; left: -14px; width: 14px;
    }
    [data-sidebar-collapsed="true"] .workspace-group:hover .flyout-title { display: block; }
    [data-sidebar-collapsed="true"] .workspace-children .sidebar-link { font-size: var(--pt-text-sm); padding: var(--pt-space-2) var(--pt-space-3); }
    [data-sidebar-collapsed="true"] .workspace-children .sidebar-link [class^="ph-"],
    [data-sidebar-collapsed="true"] .workspace-children .sidebar-link [class*=" ph-"] { font-size: var(--pt-text-lg); }
    [data-sidebar-collapsed="true"] .workspace-subheader { margin-top: var(--pt-space-1); }

    /* Footer stacks: avatar over theme toggle. */
    [data-sidebar-collapsed="true"] .sidebar-footer { flex-direction: column; gap: var(--pt-space-2); padding: var(--pt-space-2) 0; }
    [data-sidebar-collapsed="true"] .profile-card { justify-content: center; padding: var(--pt-space-2) 0; }
    [data-sidebar-collapsed="true"] .profile-card > span:nth-child(2) { display: none; }
}

/* In-flight feedback for the live table region (search / filter / sort / paginate).
   Without it the table just sits on a slow query, then jumps to new rows. The
   delay means only requests that outlive ~150ms ever dim — the common fast swap
   stays visually instant instead of flickering on every keystroke. */
#table-results.htmx-request {
    opacity: 0.6;
    transition: opacity var(--pt-dur-instant) var(--pt-ease-paper);
    transition-delay: 150ms;
}
/* Requests that outlive ~600ms also pulse the stale rows — the static dim alone
   reads as frozen on a genuinely slow query. Opacity keyframes, not a gradient
   shimmer (brand: no gradients). */
#table-results.htmx-request .data-table tbody { animation: rows-pulse 1.6s var(--pt-ease-paper) 600ms infinite; }
@keyframes rows-pulse { 50% { opacity: 0.45; } }
@media (prefers-reduced-motion: reduce) {
    /* The global 0.01ms clamp would turn an infinite pulse into a strobe. */
    #table-results.htmx-request .data-table tbody { animation: none; }
}

/* ===== Layout ===== */
/* NOTE: this is the same element as #app-main (<main id="app-main" class="main-content">),
   so the collapse and the nav fade have to share ONE transition declaration — an
   #app-main rule would outrank this one on specificity and silently drop margin-left. */
.main-content {
    margin-left: var(--sidebar-w); min-height: 100vh;
    padding: var(--pt-space-6);
    /* margin-left matches the sidebar's collapse timing (see .sidebar); opacity/filter
       drive the shell navigation fade-in below. */
    transition: margin-left var(--pt-dur-fast) var(--pt-ease-paper),
                opacity var(--pt-dur-fast) var(--pt-ease-paper),
                filter var(--pt-dur-fast) var(--pt-ease-paper);
}

/* ===== Shell navigation fade-in =====
   Boosted nav swaps #app-main while the sidebar stays put, so without this the whole
   content region hard-cuts to a different page. Incoming content only — the outgoing
   page is never faded out, so the content area never sits blank waiting on the request
   (that read as a flash of nothing). Paired with swap:0ms / settle:20ms on the hx-swap
   declarations: the old markup holds until the response lands, then the new markup
   fades up from the settling state. Falls back to no fade (opacity 1) when htmx is
   absent, since the class is only ever added by htmx. */
#app-main.htmx-settling { opacity: 0; filter: blur(2px); }
@media (prefers-reduced-motion: reduce) {
    /* The fade explains that the page changed — keep it, drop the blur. */
    #app-main.htmx-settling { filter: none; }
}
@media (min-width: 1600px) { .main-content { padding: var(--pt-space-6) var(--pt-space-8); } }
/* Edit-form pages reserve room for the sticky save-bar */
.main-content.has-save-bar { padding-bottom: var(--pt-space-24); }

/* One full-width content column — record metadata lives in a Details tab, not a sidebar. */
.layout-grid { display: grid; gap: var(--pt-space-4); grid-template-columns: minmax(0, 1fr); }

/* ===== Breadcrumb + record pager ===== */
.breadcrumb { display: flex; align-items: center; gap: var(--pt-space-2); font-size: var(--pt-text-xs); color: var(--pt-fg-muted); }
.breadcrumb a { color: var(--pt-fg-muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--pt-fg); }
.breadcrumb .sep { color: var(--pt-border); }
.breadcrumb .current { color: var(--pt-fg); font-weight: 500; }
.record-pager { display: inline-flex; align-items: center; gap: var(--pt-space-1); font-size: var(--pt-text-xs); color: var(--pt-fg-muted); }
.record-pager .meta { padding: 0 var(--pt-space-2); font-variant-numeric: tabular-nums; }

/* ===== Buttons ===== */
.btn-primary {
    display: inline-flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-2) var(--pt-space-4); font-size: var(--pt-text-sm); font-weight: 600;
    color: var(--pt-white); background: var(--pt-rocket-flame); border: 0; border-radius: var(--pt-radius-pill);
    cursor: pointer; white-space: nowrap;
    transition: background var(--pt-dur-instant),
                transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.btn-primary:hover { background: var(--pt-rocket-flame-hover); }
.btn-primary:disabled { opacity: 0.5; cursor: not-allowed; }
/* Destructive primary — for confirm-delete/void actions inside modals */
.btn-primary--danger { background: var(--pt-red-alert); }
.btn-primary--danger:hover { background: var(--pt-red-alert-hover); }
.btn-secondary {
    display: inline-flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-2) var(--pt-space-4); font-size: var(--pt-text-sm); font-weight: 500;
    color: var(--pt-fg); background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-pill); cursor: pointer; white-space: nowrap;
    transition: border-color var(--pt-dur-instant),
                transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.btn-secondary:hover { border-color: var(--pt-fg); }
.btn-secondary--sm { padding: var(--pt-space-2) var(--pt-space-3); font-size: var(--pt-text-xs); }
/* Bordered destructive secondary — a low-emphasis red trigger that keeps the
   secondary button shape (sits beside other secondaries without a filled CTA). */
.btn-secondary--danger { color: var(--pt-red-alert); }
.btn-secondary--danger:hover { border-color: var(--pt-red-alert); }
.btn-secondary .count {
    color: var(--pt-fg-muted); font-weight: 500;
    padding-left: var(--pt-space-1); border-left: 1px solid var(--pt-border);
    margin-left: var(--pt-space-1); padding-right: 0;
}
.btn-ghost {
    display: inline-flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-2) var(--pt-space-3); font-size: var(--pt-text-xs); font-weight: 500;
    color: var(--pt-fg-muted); background: transparent; border: 0;
    border-radius: var(--pt-radius-pill); cursor: pointer;
    transition: color var(--pt-dur-instant), background var(--pt-dur-instant),
                transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.btn-ghost:hover { color: var(--pt-fg); background: var(--surface-muted); }
.btn-ghost.is-on { background: var(--pt-fg); color: var(--pt-surface); }
.btn-ghost.danger { color: var(--pt-red-alert); }
.btn-ghost.danger:hover { background: var(--pt-red-alert-20); }

/* Press feedback — motion earns its place on high-frequency controls here because it
   confirms the press landed. Subtle and short; disabled buttons don't respond. */
.btn-primary:active:not(:disabled),
.btn-secondary:active:not(:disabled),
.btn-ghost:active:not(:disabled),
.icon-btn:active:not(:disabled),
.sidebar-icon-btn:active,
.row-action:active,
.star-btn:active,
.copy-btn:active,
.rt-btn:active,
.toast__close:active,
.filter-chip .chip-x:active,
.multi-picker__chip__remove:active,
.pager-btn:active:not(.is-disabled):not(.is-current),
.toast__action:active,
.view-tab__remove:active,
.view-tab--add:active,
.filter-add:active,
.review-nav-btn:active:not(.is-disabled) {
    transform: scale(0.97);
}
@media (prefers-reduced-motion: reduce) {
    .btn-primary, .btn-secondary, .btn-ghost, .icon-btn,
    .sidebar-icon-btn, .row-action, .star-btn, .copy-btn, .rt-btn,
    .toast__close, .filter-chip .chip-x,
    .multi-picker__chip__remove, .pager-btn, .review-nav-btn,
    .toast__action, .view-tab__remove, .view-tab--add, .filter-add {
        transition-property: color, background, border-color, opacity;
    }
    .btn-primary:active:not(:disabled),
    .btn-secondary:active:not(:disabled),
    .btn-ghost:active:not(:disabled),
    .icon-btn:active:not(:disabled),
    .sidebar-icon-btn:active,
    .row-action:active,
    .star-btn:active,
    .copy-btn:active,
    .rt-btn:active,
    .toast__close:active,
    .filter-chip .chip-x:active,
    .multi-picker__chip__remove:active,
    .pager-btn:active,
    .toast__action:active,
    .view-tab__remove:active,
    .view-tab--add:active,
    .filter-add:active,
    .review-nav-btn:active { transform: none; }
}
.btn-text-link {
    display: inline-flex; align-items: center; gap: var(--pt-space-1);
    font-size: var(--pt-text-sm); font-weight: 600; color: var(--pt-rocket-flame);
    background: transparent; border: 0; padding: 0; cursor: pointer;
}
.btn-text-link:hover { text-decoration: underline; }

/* Small primary — matches btn-secondary--sm so the two pair on compact rows */
.btn-primary--sm { padding: var(--pt-space-2) var(--pt-space-3); font-size: var(--pt-text-xs); }

/* ===== Avatars ===== */
.av {
    width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 600; font-size: var(--pt-text-2xs);
}
.av-sm { width: 24px; height: 24px; font-size: var(--pt-text-2xs); }
/* User avatar — fixed brand tone (ink-on-blue-20 remaps in dark mode). */
.av--user { background: var(--pt-atmosphere-blue-20); color: var(--pt-ink-on-blue-20); }
/* Logo avatar — real company mark on a neutral tile instead of initials. */
.av--logo { background: var(--pt-white); border: 1px solid var(--pt-border); padding: var(--pt-space-1); }
.av--logo img { width: 100%; height: 100%; object-fit: contain; border-radius: inherit; }
/* Photo avatar — a profile image (or the generic person placeholder) instead of initials. */
.av--photo, .avatar-circle--photo { background: none; padding: 0; overflow: hidden; }
.av--photo img, .avatar-circle--photo img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; display: block; }
.company-logo {
    width: 64px; height: 64px; border-radius: 50%;
    flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
    background: var(--pt-graphite-core); color: var(--pt-white);
    font-weight: 600; font-size: var(--pt-text-xl); letter-spacing: -0.02em;
}
[data-theme="dark"] .company-logo { background: var(--pt-white); color: var(--pt-graphite-core); }
/* Company logo as a real image — neutral tile, mark contained with padding. */
.company-logo--img { background: var(--pt-white); border: 1px solid var(--pt-border); padding: var(--pt-space-2); }
[data-theme="dark"] .company-logo--img { background: var(--pt-white); }
.company-logo--img img { width: 100%; height: 100%; object-fit: contain; }
/* Person photo (e.g. a match's candidate) — fills the circular tile. */
.company-logo--photo { background: none; padding: 0; overflow: hidden; }
.company-logo--photo img { width: 100%; height: 100%; object-fit: cover; }

/* ===== Badges, tags, labels, chips ===== */
.status-badge {
    display: inline-flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-1) var(--pt-space-3); font-size: var(--pt-text-xs); font-weight: 600;
    line-height: 16px; border-radius: var(--pt-radius-pill); white-space: nowrap;
}
.status-badge::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.status-badge--green { background: var(--pt-galactic-seafoam-20); color: var(--pt-ink-on-seafoam-20); }
.status-badge--gold { background: var(--pt-solar-gold-20); color: var(--pt-ink-on-gold-20); }
.status-badge--red { background: var(--pt-red-alert-20); color: var(--pt-ink-on-red-20); }
.status-badge--blue { background: var(--pt-atmosphere-blue-20); color: var(--pt-ink-on-blue-20); }
.status-badge--purple { background: var(--pt-voyager-purple-20); color: var(--pt-ink-on-purple-20); }
.status-badge--flame { background: var(--pt-rocket-flame-20); color: var(--pt-ink-on-flame-20); }
.status-badge--black { background: var(--pt-graphite-core); color: var(--pt-white); }
.status-badge--neutral { background: var(--surface-muted); color: var(--pt-fg-muted); }
[data-theme="dark"] .status-badge--green { color: var(--pt-galactic-seafoam); }
[data-theme="dark"] .status-badge--gold { color: var(--pt-solar-gold); }
[data-theme="dark"] .status-badge--red { color: var(--pt-red-alert); }
[data-theme="dark"] .status-badge--blue { color: var(--pt-atmosphere-blue); }
[data-theme="dark"] .status-badge--purple { color: var(--pt-voyager-purple); }
[data-theme="dark"] .status-badge--flame { color: var(--pt-rocket-flame); }
/* Processing chip is a solid dark pill in light mode; invert so it stays legible on dark surfaces. */
[data-theme="dark"] .status-badge--black { background: var(--pt-white); color: var(--pt-graphite-core); }

/* Compact list-cell variant of status-badge */
.status-badge--list { padding: 2px var(--pt-space-2); font-size: var(--pt-text-xs); line-height: 16px; }

/* Neutral metadata label (no status dot) */
.tag {
    display: inline-flex; align-items: center;
    padding: 3px var(--pt-space-3); font-size: var(--pt-text-xs); font-weight: 500;
    background: var(--surface-muted); color: var(--pt-fg);
    border-radius: var(--pt-radius-pill); white-space: nowrap;
}
.tag--xs { padding: 2px var(--pt-space-2); font-size: var(--pt-text-2xs); line-height: 16px; }

/* UI label = neutral pill with optional leading icon */
.ui-label {
    display: inline-flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-1) var(--pt-space-3); border-radius: var(--pt-radius-pill);
    font-size: var(--pt-text-xs); font-weight: 500;
    background: var(--surface-muted); color: var(--pt-fg);
}
.ui-label__icon { color: var(--pt-fg-muted); font-size: var(--pt-text-sm); }
.ui-label a { color: var(--pt-fg); text-decoration: none; }
.ui-label a:hover { color: var(--pt-rocket-flame); }

/* FK chip = avatar + name in a single pill */
.fk-chip {
    display: inline-flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-1) var(--pt-space-3) var(--pt-space-1) var(--pt-space-1); border-radius: var(--pt-radius-pill);
    background: var(--surface-muted); color: var(--pt-fg);
    font-size: var(--pt-text-xs); font-weight: 500; text-decoration: none;
}
.fk-chip:hover { background: var(--pt-border); }
.fk-chip__av {
    width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 600; font-size: var(--pt-text-2xs);
    background: var(--pt-atmosphere-blue-20); color: var(--pt-ink-on-blue-20);
}
[data-theme="dark"] .fk-chip__av { color: var(--pt-atmosphere-blue); }

/* ===== Hero ===== */
.detail-hero {
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-md); padding: var(--pt-space-6); margin-bottom: var(--pt-space-4);
}
.hero-row { display: flex; align-items: center; gap: var(--pt-space-5); flex-wrap: wrap; }
.hero-avatar {
    width: 64px; height: 64px; border-radius: 50%; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 600; font-size: var(--pt-text-xl);
    background: var(--pt-rocket-flame-20); color: var(--pt-ink-on-flame-20);
}
[data-theme="dark"] .hero-avatar { color: var(--pt-rocket-flame); }
.hero-main { flex: 1; min-width: 280px; }
.hero-name {
    font-size: var(--pt-text-2xl); font-weight: 600; line-height: 1.1; margin: 0;
    letter-spacing: -0.01em;
    display: flex; align-items: center; gap: var(--pt-space-3); flex-wrap: wrap;
}
.hero-sub { color: var(--pt-fg-muted); font-size: var(--pt-text-sm); margin-top: var(--pt-space-2); }
.hero-sub a { color: var(--pt-fg); font-weight: 500; text-decoration: none; }
.hero-sub a:hover { color: var(--pt-rocket-flame); }
.hero-pipeline { margin-top: var(--pt-space-5); }
.hero-meta { display: flex; flex-wrap: wrap; gap: var(--pt-space-2); margin-top: var(--pt-space-3); }
.hero-actions { display: flex; flex-wrap: wrap; gap: var(--pt-space-2); align-items: center; }

/* ===== Popover motion (shared: action panel, filter-chip editor) =====
   Panels grow from the corner they're anchored to, so they read as coming out of
   their trigger rather than materialising in mid-air. Each panel sets its own
   transform-origin to match its anchor. Exit snaps quicker than the entrance. */
.pop-enter-active {
    transition: opacity var(--pt-dur-fast) var(--pt-ease-paper),
                transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.pop-leave-active {
    transition: opacity var(--pt-dur-instant) var(--pt-ease-paper),
                transform var(--pt-dur-instant) var(--pt-ease-paper);
}
.pop-hidden { opacity: 0; transform: scale(0.96); }
.pop-shown { opacity: 1; transform: scale(1); }
@media (prefers-reduced-motion: reduce) {
    /* Keep the fade, drop the scale. */
    .pop-hidden { transform: none; }
}

/* ===== Action popover ===== */
.action-panel {
    position: absolute; right: 0; top: calc(100% + 8px); width: 320px;
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-md); padding: var(--pt-space-2); z-index: 50;
    transform-origin: top right; /* anchored under the trigger's right edge */
}
.action-group-label {
    padding: var(--pt-space-2) var(--pt-space-3) var(--pt-space-1); font-size: var(--pt-text-2xs); font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.1em; color: var(--pt-fg-muted);
}
.action-item {
    display: flex; align-items: flex-start; gap: var(--pt-space-3);
    padding: var(--pt-space-2) var(--pt-space-3); border-radius: var(--pt-radius-sm); cursor: pointer;
    color: var(--pt-fg); text-decoration: none; border: 0; background: none;
    width: 100%; text-align: left; font: inherit;
}
.action-item:hover { background: var(--surface-muted); }
.action-item.danger { color: var(--pt-red-alert); }
.action-item__icon {
    width: 32px; height: 32px; border-radius: var(--pt-radius-sm);
    display: inline-flex; align-items: center; justify-content: center;
    flex-shrink: 0; font-size: var(--pt-text-md);
}
.action-item__icon--info { background: var(--pt-atmosphere-blue-20); color: var(--pt-ink-on-blue-20); }
.action-item__icon--success { background: var(--pt-galactic-seafoam-20); color: var(--pt-ink-on-seafoam-20); }
.action-item__icon--neutral { background: var(--surface-muted); color: var(--pt-fg-muted); }
.action-item__icon--danger { background: var(--pt-red-alert-20); color: var(--pt-ink-on-red-20); }
[data-theme="dark"] .action-item__icon--info { color: var(--pt-atmosphere-blue); }
[data-theme="dark"] .action-item__icon--success { color: var(--pt-galactic-seafoam); }
[data-theme="dark"] .action-item__icon--danger { color: var(--pt-red-alert); }
.action-item__main { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.action-item__label { font-size: var(--pt-text-sm); font-weight: 500; line-height: 16px; }
.action-item__desc { font-size: var(--pt-text-2xs); color: var(--pt-fg-muted); line-height: 14px; margin-top: var(--pt-space-1); }
.action-divider { height: 1px; margin: var(--pt-space-2) var(--pt-space-3); background: var(--pt-border); }

/* ===== Small label + caption (shared; used by the invoice financial summary) ===== */
.kpi-label { font-size: var(--pt-text-xs); font-weight: 500; color: var(--pt-fg-muted); }
.kpi-meta { font-size: var(--pt-text-2xs); color: var(--pt-fg-muted); margin-top: var(--pt-space-1); }

/* ===== Tabs (view + detail) ===== */
.view-tabs, .detail-tabs {
    display: flex; align-items: center; border-bottom: 1px solid var(--pt-border);
    overflow-x: auto; overflow-y: hidden;
}
.view-tabs { gap: 0; }
.detail-tabs { gap: 0; margin-bottom: var(--pt-space-6); }
.view-tab, .detail-tab {
    display: inline-flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-3) var(--pt-space-4); font-size: var(--pt-text-sm); font-weight: 500;
    color: var(--pt-fg-muted); border: 0; background: transparent;
    border-bottom: 2px solid transparent; margin-bottom: -1px;
    cursor: pointer; white-space: nowrap;
    transition: color var(--pt-dur-instant);
}
.view-tab:hover, .detail-tab:hover { color: var(--pt-fg); }
.view-tab.active, .detail-tab.active { color: var(--pt-fg); border-bottom-color: var(--pt-fg); font-weight: 600; }
.view-tab .count, .view-tab .n,
.detail-tab .count { color: var(--pt-fg-muted); font-weight: 500; }
.view-tab.active .count, .view-tab.active .n,
.detail-tab.active .count { color: var(--pt-fg); }
.view-tab--add { color: var(--pt-fg-muted); padding: var(--pt-space-3); transition: color var(--pt-dur-instant), transform var(--pt-dur-fast) var(--pt-ease-paper); }

/* User-saved views (savedViews in refresh.js): the tab is a span so the nav
   link and the delete button don't nest interactive elements. */
.view-tab--saved { cursor: default; }
.view-tab__link { color: inherit; text-decoration: none; cursor: pointer; }
.view-tab__remove {
    display: inline-flex; border: 0; background: none; padding: 0;
    color: var(--pt-fg-muted); font-size: var(--pt-text-2xs); cursor: pointer;
    border-radius: var(--pt-radius-xs);
    opacity: 0; transition: opacity var(--pt-dur-instant), transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.view-tab--saved:hover .view-tab__remove, .view-tab__remove:focus-visible { opacity: 1; }
.view-tab__remove:hover { color: var(--pt-red-alert); }

/* Entrance for tabs created by savedViews.save() this session only —
   persisted tabs render without the flag so page loads stay still. */
.view-tab--fresh {
    transition: opacity var(--pt-dur-fast) var(--pt-ease-paper),
                transform var(--pt-dur-fast) var(--pt-ease-paper);
}
@starting-style {
    .view-tab--fresh { opacity: 0; transform: translateY(-4px); }
}
@media (prefers-reduced-motion: reduce) {
    /* Keep the fade, drop the lift. */
    .view-tab--fresh { transition-property: opacity; }
    @starting-style {
        .view-tab--fresh { transform: none; }
    }
}

/* ===== Section cards ===== */
.section-card {
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-md); overflow: hidden;
}
.section-card + .section-card { margin-top: var(--pt-space-4); }
.section-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: var(--pt-space-4) var(--pt-space-6); border-bottom: 1px solid var(--pt-border); gap: var(--pt-space-3);
}
.section-title { font-size: var(--pt-text-md); font-weight: 600; display: inline-flex; align-items: center; gap: var(--pt-space-2); }
.count-pill {
    font-size: var(--pt-text-2xs); font-weight: 600; padding: 2px var(--pt-space-2);
    border-radius: var(--pt-radius-pill);
    background: var(--surface-muted); color: var(--pt-fg-muted);
}
.section-body { padding: var(--pt-space-6); }
.view-all { font-size: var(--pt-text-sm); font-weight: 600; color: var(--pt-fg-muted); text-decoration: none; }
.view-all:hover { color: var(--pt-rocket-flame); }

/* ===== Detail field grid (display only — see .form-card .field-grid below for form input grid) ===== */
.fields {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--pt-space-6) var(--pt-space-8);
}
.fields .field-label {
    font-size: var(--pt-text-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em;
    color: var(--pt-fg-muted); margin-bottom: var(--pt-space-2);
}
.fields .field-value {
    font-size: var(--pt-text-sm); color: var(--pt-fg); font-weight: 500;
    min-height: 20px; display: flex; align-items: center; gap: var(--pt-space-2);
}
.fields .field-value a { color: var(--pt-fg); text-decoration: none; }
.fields .field-value a:hover { color: var(--pt-rocket-flame); }
.fields .field-value--empty,
.fields .field-value--muted { color: var(--pt-fg-muted); font-weight: 400; }
.fields .field-value--mono { font-family: var(--pt-font-mono); font-size: var(--pt-text-xs); }
/* Neutral at rest with a muted underline carrying the link affordance; flame
   answers the hover (accent as punctuation, not upholstery). */
.fields .field-value--link {
    color: var(--pt-fg); cursor: pointer;
    text-decoration: underline; text-decoration-color: var(--pt-border); text-underline-offset: 3px;
}
.fields .field-value--link:hover { color: var(--pt-rocket-flame); text-decoration-color: currentColor; }

.copy-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 24px; height: 24px; border-radius: var(--pt-radius-pill);
    background: transparent; border: 0; color: var(--pt-fg-muted); cursor: pointer;
    transition: transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.copy-btn:hover { background: var(--surface-muted); color: var(--pt-fg); }

/* ===== Related table ===== */
.rel-table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.rel-table th {
    text-align: left; font-size: var(--pt-text-2xs); font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.1em; color: var(--pt-fg-muted);
    padding: var(--pt-space-3) var(--pt-space-6); background: var(--surface-muted);
    border-bottom: 1px solid var(--pt-border); white-space: nowrap;
}
.rel-table td {
    padding: var(--pt-space-4) var(--pt-space-6); font-size: var(--pt-text-sm);
    border-bottom: 1px solid var(--pt-border); vertical-align: middle;
    font-variant-numeric: tabular-nums;
}
.rel-table th.col-numeric, .rel-table td.col-numeric { text-align: right; }
.rel-table tbody tr:last-child td { border-bottom: 0; }
.rel-table tbody tr:hover { background: var(--surface-muted); cursor: pointer; }
.rel-table a { color: var(--pt-fg); font-weight: 600; text-decoration: none; }
.rel-table a:hover { color: var(--pt-rocket-flame); }

.cell-name { display: flex; align-items: center; gap: var(--pt-space-3); }
.cell-name__title { font-weight: 600; color: var(--pt-fg); line-height: 1.2; text-decoration: none; }
.cell-name__sub { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); line-height: 1.2; margin-top: var(--pt-space-1); }
.cell-user { display: inline-flex; align-items: center; gap: var(--pt-space-2); white-space: nowrap; }
.cell-muted { color: var(--pt-fg-muted); }
/* Money + link cells in list tables */
.cell-amount { font-family: var(--pt-font-mono); font-weight: 500; font-variant-numeric: tabular-nums; }
/* Record-id links (e.g. invoice numbers): mono + neutral at rest — color is
   punctuation, so flame only answers the hover. The row hover already signals
   clickability. */
.cell-link { font-family: var(--pt-font-mono); color: var(--pt-fg); text-decoration: none; font-weight: 500; }
.cell-link:hover { color: var(--pt-rocket-flame); }

/* Credit amounts read red; received payments read seafoam. */
.cell-amount--credit { color: var(--pt-red-alert); }
.cell-amount--paid { color: var(--pt-galactic-seafoam); }

/* Figure strip — the invoice overview's subtotal / adjustments / total divided as
   one group with balance due split off to the right, reused by the metrics panel. */
.fin-summary {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: var(--pt-space-6); padding: var(--pt-space-6); flex-wrap: wrap;
}
.fin-summary__figures { display: flex; align-items: flex-start; flex: 1; min-width: 0; }
.fin-summary__cell { padding: 0 var(--pt-space-6); }
.fin-summary__figures .fin-summary__cell:first-child { padding-left: 0; }
.fin-summary__figures .fin-summary__cell + .fin-summary__cell { border-left: 1px solid var(--pt-border); }
.fin-summary__cell--balance {
    text-align: right; padding-right: 0; border-left: 1px solid var(--pt-border); flex-shrink: 0;
}
.fin-summary__value {
    margin-top: var(--pt-space-1); font-family: var(--pt-font-mono);
    font-size: var(--pt-text-2xl); font-weight: 700; font-variant-numeric: tabular-nums;
}
.fin-summary__value--credit { color: var(--pt-red-alert); }
.fin-summary__value--paid { color: var(--pt-galactic-seafoam); }
.fin-summary__value--draft { color: var(--pt-solar-gold); }

/* Invoice flags / entity checks — one line per warning, info, or passing check. */
.note-list { display: flex; flex-direction: column; gap: var(--pt-space-3); }
.note-item { display: flex; align-items: flex-start; gap: var(--pt-space-2); font-size: var(--pt-text-sm); }
.note-item i { line-height: 1.5; flex-shrink: 0; }
.note-item--warning i { color: var(--pt-solar-gold); }
.note-item--info i { color: var(--pt-atmosphere-blue); }
.note-item--ok i { color: var(--pt-galactic-seafoam); }

/* ===== Big data table (list view) ===== */
.table-card {
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-md); overflow: hidden;
}
.table-wrap { overflow-x: auto; }
/* tabular-nums table-wide so dates, percentages, and amounts align down columns. */
.data-table { width: 100%; border-collapse: separate; border-spacing: 0; min-width: 100%; font-variant-numeric: tabular-nums; }
.data-table thead th {
    text-align: left; font-size: var(--pt-text-2xs); font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.1em; color: var(--pt-fg-muted);
    padding: var(--pt-space-3) var(--pt-space-4); background: var(--surface-muted);
    border-bottom: 1px solid var(--pt-border); white-space: nowrap;
    position: sticky; top: 0; z-index: 1;
}
.data-table thead th.col-numeric { text-align: right; }
.data-table thead th.is-sticky-l {
    left: 0; z-index: 2; background: var(--surface-muted);
    border-right: 1px solid var(--pt-border);
}
.data-table thead th a { color: inherit; text-decoration: none; display: inline-flex; align-items: center; gap: var(--pt-space-1); }
.data-table thead th a:hover { color: var(--pt-fg); }
.sort-caret { opacity: 0.4; font-size: var(--pt-text-xs); }
.sort-caret.is-active { opacity: 1; color: var(--pt-fg); }

.data-table tbody tr {
    --row-bg: var(--pt-surface);
    background: var(--row-bg); cursor: pointer;
    /* opacity carries the optimistic bulk-removal fade (and its Undo fade-back) */
    transition: background var(--pt-dur-instant) var(--pt-ease-paper),
                opacity var(--pt-dur-fast) var(--pt-ease-paper);
}
/* Optimistic bulk removal: rows fade out, then hide; Undo unhides + fades back. */
.data-table tbody tr.row-vanish { opacity: 0; }
.data-table tbody tr:hover { --row-bg: var(--surface-muted); }
.data-table tbody tr.is-selected { --row-bg: var(--pt-atmosphere-blue-20); }
/* Keyboard cursor (j/k). --row-bg so sticky cells follow; the flame bar on the
   first cell marks the cursor without fighting .is-selected's tint. */
.data-table tbody tr.kb-active { --row-bg: var(--surface-muted); }
.data-table tbody tr.kb-active > td:first-child { box-shadow: inset 2px 0 0 var(--pt-rocket-flame); }
.data-table tbody td {
    padding: var(--pt-space-3) var(--pt-space-4); font-size: var(--pt-text-sm); color: var(--pt-fg);
    border-bottom: 1px solid var(--pt-border); vertical-align: middle;
}
.data-table tbody tr:last-child td { border-bottom: 0; }
.data-table tbody td.col-numeric { text-align: right; font-variant-numeric: tabular-nums; }
/* Same transition as the row — the sticky cell reads --row-bg from the <tr>, and
   without this it snaps to the hover color while the rest of the row fades. */
.data-table tbody td.is-sticky-l {
    position: sticky; left: 0; background: var(--row-bg); border-right: 1px solid var(--pt-border);
    transition: background var(--pt-dur-instant) var(--pt-ease-paper);
}

/* List-table support cells */
.row-action {
    width: 28px; height: 28px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--pt-fg-muted); background: transparent; border: 0; cursor: pointer;
    transition: background var(--pt-dur-instant), color var(--pt-dur-instant), transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.row-action:hover { background: var(--pt-border); color: var(--pt-fg); }
.priority-star { color: var(--pt-solar-gold); font-size: var(--pt-text-md); }
.priority-star--off { color: var(--pt-border); }
/* Starred state lives on the row — tr.is-starred is the data-optimistic flip
   target — so the button ships both icon weights and the row class picks one. */
.priority-star--on { display: none; }
tr.is-starred .priority-star--on { display: inline; }
tr.is-starred .priority-star--off { display: none; }
.star-btn {
    background: none; border: 0; padding: var(--pt-space-1); line-height: 0; cursor: pointer;
    display: inline-flex; border-radius: 50%;
    transition: background var(--pt-dur-instant), transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.star-btn:hover { background: var(--pt-border); }
.star-btn:hover .priority-star--off { color: var(--pt-solar-gold); }

/* Second sticky-left column (a locked priority/star column after the checkbox).
   Offset = rendered width of the sticky checkbox cell: 40px content + 16px×2
   padding − overlap ≈ 49px. Named here so the one place that must track the
   checkbox width is obvious if that cell ever changes. */
.data-table { --col-select-w: 49px; }
.data-table thead th.is-sticky-l.col-sticky-2,
.data-table tbody td.is-sticky-l.col-sticky-2 { left: var(--col-select-w); }
/* Keep the star column as narrow as the checkbox, content centred. */
.data-table th.col-priority,
.data-table td.col-priority { width: 40px; text-align: center; }
.col-priority__head { font-size: var(--pt-text-md); color: var(--pt-fg-muted); }

/* ===== Empty state (table body with no rows) ===== */
.empty-state {
    display: flex; flex-direction: column; align-items: center;
    gap: var(--pt-space-1); padding: var(--pt-space-12) var(--pt-space-6); text-align: center;
}
.empty-state__icon { font-size: 40px; color: var(--pt-fg-muted); margin-bottom: var(--pt-space-2); }
.empty-state__title { font-size: var(--pt-text-md); font-weight: 600; color: var(--pt-fg); }
.empty-state__sub { font-size: var(--pt-text-sm); line-height: var(--pt-leading-sm); color: var(--pt-fg-muted); max-width: 360px; }
.empty-state .btn-secondary { margin-top: var(--pt-space-4); }
/* The empty row is the table's only row — no hover tint, no trailing rule. */
.data-table tbody tr.empty-row:hover { --row-bg: transparent; }
.data-table tbody tr.empty-row td { border-bottom: 0; }

/* ===== Match ring ===== */
/* Tier dot: high (default) seafoam, mid gold, low red. Color encodes the tier;
   the numeric % sits next to it so the visualization is redundant by design. */
.match-ring {
    width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0;
    background: var(--pt-galactic-seafoam);
}
.match-ring.mid { background: var(--pt-solar-gold); }
.match-ring.low { background: var(--pt-red-alert); }
.cell-match { display: inline-flex; align-items: center; gap: var(--pt-space-2); font-variant-numeric: tabular-nums; font-weight: 600; }

/* ===== Stage breakdown bar ===== */
.stage-bar {
    display: flex; gap: var(--pt-space-1); align-items: stretch;
    height: 8px; border-radius: var(--pt-radius-pill);
    overflow: hidden; background: var(--surface-muted);
}
.stage-bar__seg { transition: opacity var(--pt-dur-instant); }
.stage-bar__seg:hover { opacity: 0.85; }
.stage-legend { display: flex; flex-wrap: wrap; gap: var(--pt-space-4) var(--pt-space-6); margin-top: var(--pt-space-4); }
.stage-legend__item { display: inline-flex; align-items: center; gap: var(--pt-space-2); font-size: var(--pt-text-sm); }
.stage-legend__swatch { width: 12px; height: 12px; border-radius: var(--pt-radius-xs); }
.stage-legend__label { color: var(--pt-fg-muted); }
.stage-legend__value { font-weight: 600; color: var(--pt-fg); font-variant-numeric: tabular-nums; }

/* Interactive variants — only on pages that carry a board for the click to land on.
   The segment grows a little rather than only lightening, so the bar reads as a row
   of targets without needing a hover to discover it. */
.stage-bar { padding: 1px 0; }
.stage-bar__seg--linked {
    border: 0; padding: 0; cursor: pointer; border-radius: var(--pt-radius-xs);
    transition: opacity var(--pt-dur-instant), transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.stage-bar__seg--linked:hover { opacity: 1; transform: scaleY(1.6); }
.stage-legend__item--linked {
    border: 0; background: none; padding: var(--pt-space-1) var(--pt-space-2);
    margin: calc(var(--pt-space-1) * -1) calc(var(--pt-space-2) * -1);
    border-radius: var(--pt-radius-sm); cursor: pointer; font: inherit;
    transition: background var(--pt-dur-instant);
}
.stage-legend__item--linked:hover { background: var(--surface-muted); }
.stage-legend__item--linked:hover .stage-legend__label { color: var(--pt-fg); }

/* ===== Stage board (the Candidates tab's second rendering) ===== */
/* The toolbar keeps its own margin; the switch sits at the end of the same row. */
.controls-row { display: flex; align-items: flex-start; gap: var(--pt-space-3); }
.controls-row > form { flex: 1; min-width: 0; }

.view-switch {
    display: inline-flex; flex-shrink: 0; margin-bottom: var(--pt-space-4);
    background: var(--surface-muted); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-md); padding: 2px;
}
.view-switch__btn {
    display: inline-flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-2) var(--pt-space-3); border: 0; background: none;
    border-radius: calc(var(--pt-radius-md) - 3px); cursor: pointer;
    font-size: var(--pt-text-sm); font-weight: 500; color: var(--pt-fg-muted);
    transition: background var(--pt-dur-fast) var(--pt-ease-paper), color var(--pt-dur-fast) var(--pt-ease-paper);
}
.view-switch__btn:hover { color: var(--pt-fg); }
.view-switch__btn.active { background: var(--pt-surface); color: var(--pt-fg); }

/* The board occupies exactly the table's footprint — same column, same edges, the
   inspector still alongside — so switching views moves nothing but the content.
   The card's panel drops away beneath it: the stage columns are the surfaces here,
   and a white sheet behind them just muddies the stack. */
.table-card--board { background: none; border-color: transparent; }

/* Flush to the container on every edge; the columns' own gap is the only inset, so
   the first column starts exactly where the table's first cell did. */
.board { display: flex; gap: var(--pt-space-3); overflow-x: auto; }
.board-col {
    display: flex; flex-direction: column; flex: 0 0 260px;
    background: var(--surface-muted); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-md); max-height: 70vh;
}
.board-col__head {
    display: flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-3); border-top: 3px solid transparent;
    border-radius: var(--pt-radius-md) var(--pt-radius-md) 0 0;
}
.board-col__icon { flex-shrink: 0; font-size: 18px; line-height: 1; }
.board-col__title {
    flex: 1; min-width: 0; margin: 0; font-size: var(--pt-text-xs); font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.06em; color: var(--pt-fg-muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.board-col__count {
    font-size: var(--pt-text-xs); font-weight: 600; color: var(--pt-fg);
    font-variant-numeric: tabular-nums;
}
.board-col__body {
    display: flex; flex-direction: column; gap: var(--pt-space-2);
    padding: 0 var(--pt-space-2) var(--pt-space-3); overflow-y: auto;
}
.board-col__empty {
    margin: 0; padding: var(--pt-space-5) 0; text-align: center;
    font-size: var(--pt-text-xs); color: var(--pt-fg-muted);
}
/* Landing flash after a stage-bar click — a brief ring, not a colour change, so it
   reads as "here" without competing with the stage colours. */
@keyframes board-col-flash {
    from { box-shadow: 0 0 0 3px var(--pt-rocket-flame); }
    to { box-shadow: 0 0 0 3px transparent; }
}
.board-col--flash { animation: board-col-flash 600ms var(--pt-ease-paper); }

.board-card {
    display: block; padding: var(--pt-space-3); text-decoration: none;
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-sm);
    /* No grab cursor: the card opens the peek modal on click and cannot be moved. */
    cursor: pointer; touch-action: pan-y;
    transition: border-color var(--pt-dur-fast) var(--pt-ease-paper);
}
.board-card:hover { border-color: var(--pt-fg-muted); }
/* Held against a drag: no transition, so the card tracks the pointer 1:1 within its
   resistance limit. Releasing drops this class and --springing eases it home. */
.board-card--refusing { transition: none; cursor: not-allowed; }
.board-card--springing { transition: transform var(--pt-dur-base) var(--pt-ease-paper); }
/* Peek fetch in flight — the card dims rather than showing a spinner it has no room for. */
.board-card.is-loading { opacity: 0.6; }

.board-card__top { display: flex; align-items: center; gap: var(--pt-space-2); }
.board-card__name {
    flex: 1; min-width: 0; font-size: var(--pt-text-sm); font-weight: 500; color: var(--pt-fg);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.board-card__star { color: var(--pt-solar-gold); flex-shrink: 0; }
.board-card__meta {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--pt-space-2); margin-top: var(--pt-space-2);
    font-size: var(--pt-text-xs); font-variant-numeric: tabular-nums;
}
/* Affinity reuses the list's .cell-match + .match-ring — one dot-and-figure
   treatment across both views, so a score reads the same wherever it appears. */
.board-card__meta .cell-match { font-size: var(--pt-text-xs); }
/* Days in stage. Neutral until it crosses the warn threshold — an always-coloured
   clock would make a healthy pipeline look alarming. */
.board-card__age { display: inline-flex; align-items: center; gap: 4px; color: var(--pt-fg-muted); }
.board-card--warn .board-card__age { color: var(--pt-solar-gold); }
.board-card--stale .board-card__age { color: var(--pt-rocket-flame); font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
    .stage-bar__seg--linked:hover { transform: none; }
    .board-col--flash { animation: none; }
    .board-card--springing { transition: none; }
}

/* ===== Metadata rows (Details panel, invoice totals) ===== */
.inspector-label {
    font-size: var(--pt-text-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em;
    color: var(--pt-fg-muted); margin-bottom: var(--pt-space-3);
}
.inspector-row {
    display: flex; justify-content: space-between; align-items: center;
    gap: var(--pt-space-3); margin-bottom: var(--pt-space-2);
}
.inspector-row:last-child { margin-bottom: 0; }
.inspector-row .k { color: var(--pt-fg-muted); flex-shrink: 0; }
.inspector-row .v { color: var(--pt-fg); font-weight: 500; text-align: right; display: inline-flex; align-items: center; gap: var(--pt-space-2); min-width: 0; }
.inspector-row .v.muted { color: var(--pt-fg-muted); font-weight: 400; }

/* Details panel — a record's metadata sections laid out full width as a grid. */
.details-panel {
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-md); padding: var(--pt-space-6); font-size: var(--pt-text-sm);
    display: grid; gap: var(--pt-space-6); grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 768px) {
    .details-panel { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--pt-space-10); }
}
@media (min-width: 1280px) {
    .details-panel { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Rich FK card (inspector + detail body) */
.fk-card {
    display: flex; align-items: center; gap: var(--pt-space-3);
    padding: var(--pt-space-3); border-radius: var(--pt-radius-sm);
    background: var(--surface-muted); text-decoration: none; color: var(--pt-fg);
    transition: background var(--pt-dur-instant);
}
.fk-card:hover { background: var(--pt-border); }
.fk-card__main { flex: 1; min-width: 0; }
.fk-card__title { font-size: var(--pt-text-sm); font-weight: 600; line-height: 1.2; }
.fk-card__sub { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); line-height: 1.2; margin-top: var(--pt-space-1); }
.fk-card [class^="ph-"], .fk-card [class*=" ph-"] { color: var(--pt-fg-muted); }

/* ===== Forms ===== */
.form-card {
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-md); overflow: hidden;
}
.form-card + .form-card { margin-top: var(--pt-space-4); }
.form-card-head { padding: var(--pt-space-4) var(--pt-space-6); border-bottom: 1px solid var(--pt-border); }
.form-card-title { font-size: var(--pt-text-md); font-weight: 600; }
.form-card-sub { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); margin-top: var(--pt-space-1); }
.form-card-body { padding: var(--pt-space-6); }

/* Form field grid */
.field-grid { display: grid; grid-template-columns: 1fr; gap: var(--pt-space-5) var(--pt-space-6); }
@media (min-width: 768px) { .field-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.field-grid .full { grid-column: 1 / -1; }

.field { display: flex; flex-direction: column; gap: var(--pt-space-2); }
.field-label {
    font-size: var(--pt-text-xs); font-weight: 600; color: var(--pt-fg);
    display: flex; align-items: center; gap: var(--pt-space-2);
}
.field-label .req { color: var(--pt-red-alert); }
.field-label [class^="ph-"], .field-label [class*=" ph-"] { color: var(--pt-fg-muted); font-size: var(--pt-text-sm); cursor: help; }
.field-help { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); line-height: 1.4; }
.field-error { font-size: var(--pt-text-xs); color: var(--pt-red-alert); display: flex; align-items: center; gap: var(--pt-space-1); }

.input, .select, .textarea {
    width: 100%; padding: var(--pt-space-2) var(--pt-space-3); font: inherit; font-size: var(--pt-text-sm); color: var(--pt-fg);
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-sm); outline: none;
    transition: border-color var(--pt-dur-instant);
}
.input::placeholder, .textarea::placeholder { color: var(--pt-fg-muted); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--pt-fg-muted); }
/* Focus is the shared ring (:focus-visible at the top of this file) and nothing else —
   darkening the border on top of it drew a second line inside the ring's gap and read
   as a double outline. Same rule for every field-ish control below: one indicator, and
   where focus lands on an inner input, the wrapper carries the ring (see .input-affix). */
.input.has-error, .select.has-error, .textarea.has-error { border-color: var(--pt-red-alert); }
.textarea { resize: vertical; min-height: 96px; line-height: 1.5; }

.select {
    appearance: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23727779' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat; background-position: right 12px center;
    padding-right: 36px; cursor: pointer;
}

.input-affix {
    display: flex; align-items: stretch; border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-sm); background: var(--pt-surface);
    transition: border-color var(--pt-dur-instant);
}
.input-affix:hover { border-color: var(--pt-fg-muted); }
.input-affix.has-error { border-color: var(--pt-red-alert); }
/* The ring goes on the wrapper, not the bare inner input — otherwise it lands inside
   the affix border and boxes the text field within its own prefix/suffix. */
.input-affix:focus-within { box-shadow: var(--pt-focus-ring); }
.input-affix input:focus-visible { box-shadow: none; }
.input-affix__prefix, .input-affix__suffix {
    display: inline-flex; align-items: center; padding: 0 var(--pt-space-3);
    color: var(--pt-fg-muted); font-size: var(--pt-text-sm);
}
.input-affix__prefix { border-right: 1px solid var(--pt-border); }
.input-affix__suffix { border-left: 1px solid var(--pt-border); }
.input-affix input {
    flex: 1; padding: var(--pt-space-2) var(--pt-space-3); font: inherit; font-size: var(--pt-text-sm);
    color: var(--pt-fg); background: transparent; border: 0; outline: none; min-width: 0;
    font-variant-numeric: tabular-nums;
}

.range-pair { display: flex; align-items: center; gap: var(--pt-space-2); }
.range-pair > * { flex: 1; min-width: 0; }
.range-pair__sep { flex: 0 0 auto; color: var(--pt-fg-muted); font-size: var(--pt-text-sm); }

.radio-group {
    display: inline-flex; padding: 2px; gap: 2px;
    background: var(--surface-muted); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-pill); flex-wrap: wrap;
}
.radio-pill { position: relative; cursor: pointer; }
.radio-pill input { position: absolute; opacity: 0; pointer-events: none; }
.radio-pill__label {
    display: inline-flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-2) var(--pt-space-4); font-size: var(--pt-text-sm); font-weight: 500;
    color: var(--pt-fg-muted); border-radius: var(--pt-radius-pill);
    transition: color var(--pt-dur-instant), background var(--pt-dur-instant);
}
.radio-pill:hover .radio-pill__label { color: var(--pt-fg); }
.radio-pill input:checked + .radio-pill__label { background: var(--pt-fg); color: var(--pt-surface); }

.toggle { position: relative; display: inline-flex; align-items: center; gap: var(--pt-space-3); cursor: pointer; user-select: none; }
.toggle input { position: absolute; opacity: 0; pointer-events: none; }
.toggle__track {
    width: 36px; height: 20px; background: var(--pt-border);
    border-radius: var(--pt-radius-pill); position: relative;
    transition: background var(--pt-dur-instant); flex-shrink: 0;
}
.toggle__track::after {
    content: ''; position: absolute; top: 2px; left: 2px;
    width: 16px; height: 16px; border-radius: 50%; background: var(--pt-surface);
    transition: transform var(--pt-dur-instant) var(--pt-ease-paper);
}
.toggle input:checked + .toggle__track { background: var(--pt-rocket-flame); }
.toggle input:checked + .toggle__track::after { transform: translateX(16px); }

.chk {
    appearance: none; width: 16px; height: 16px; border: 1.5px solid var(--pt-border);
    border-radius: var(--pt-radius-xs); cursor: pointer; background: var(--pt-surface);
    background-repeat: no-repeat; background-position: center;
    background-size: 12px 12px;
    transition: background var(--pt-dur-instant), border-color var(--pt-dur-instant);
    flex-shrink: 0;
}
.chk:checked {
    background-color: var(--pt-rocket-flame);
    border-color: var(--pt-rocket-flame);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='5 12 10 17 19 8'/></svg>");
}
.chk--lg { width: 20px; height: 20px; }
.chk--lg:checked { background-size: 14px 14px; }

/* FK picker (single FK select with search popover) */
.fk-picker { position: relative; }
.fk-picker__trigger {
    display: flex; align-items: center; gap: var(--pt-space-3);
    width: 100%; padding: var(--pt-space-2) 36px var(--pt-space-2) var(--pt-space-3); font: inherit; font-size: var(--pt-text-sm);
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-sm); cursor: pointer; text-align: left;
    transition: border-color var(--pt-dur-instant);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23727779' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat; background-position: right 12px center;
}
.fk-picker__trigger:hover { border-color: var(--pt-fg-muted); }
.fk-picker__current { display: flex; align-items: center; gap: var(--pt-space-3); flex: 1; min-width: 0; }
.fk-picker__avatar {
    width: 24px; height: 24px; border-radius: 50%; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 600; font-size: var(--pt-text-2xs);
}
.fk-picker__avatar--square { border-radius: var(--pt-radius-xs); }
.fk-picker__title { font-weight: 500; line-height: 1.2; }
.fk-picker__sub { font-size: var(--pt-text-2xs); color: var(--pt-fg-muted); line-height: 1.2; font-variant-numeric: tabular-nums; }
.fk-picker__empty { color: var(--pt-fg-muted); }

.fk-popover {
    position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 30;
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-sm); padding: var(--pt-space-1);
    max-height: 320px; overflow-y: auto;
}
.fk-popover__search { position: relative; margin-bottom: var(--pt-space-1); }
.fk-popover__search input {
    width: 100%; padding: var(--pt-space-2) var(--pt-space-3) var(--pt-space-2) var(--pt-space-8); font: inherit; font-size: var(--pt-text-sm);
    background: var(--surface-muted); border: 1px solid transparent; border-radius: var(--pt-radius-sm);
    outline: none; color: var(--pt-fg);
    transition: border-color var(--pt-dur-instant), background var(--pt-dur-instant);
}
.fk-popover__search input:focus { background: var(--pt-bg); }
.fk-popover__search [class^="ph-"],
.fk-popover__search [class*=" ph-"] { position: absolute; left: 12px; top: 8px; color: var(--pt-fg-muted); font-size: var(--pt-text-sm); }

.fk-option {
    display: flex; align-items: center; gap: var(--pt-space-3);
    padding: var(--pt-space-2) var(--pt-space-3); border-radius: var(--pt-radius-sm); cursor: pointer;
    width: 100%; text-align: left; border: 0; background: transparent; font: inherit;
}
.fk-option:hover, .fk-option.is-active { background: var(--surface-muted); }
.fk-option__main { flex: 1; min-width: 0; }
.fk-option__title { font-size: var(--pt-text-sm); font-weight: 500; line-height: 1.2; }
.fk-option__sub { font-size: var(--pt-text-2xs); color: var(--pt-fg-muted); line-height: 1.2; margin-top: var(--pt-space-1); font-variant-numeric: tabular-nums; }
.fk-option__check { color: var(--pt-rocket-flame); }
.fk-option__none {
    padding: var(--pt-space-2) var(--pt-space-3); font-size: var(--pt-text-sm); color: var(--pt-fg-muted);
    text-align: left; cursor: pointer; border-radius: var(--pt-radius-sm);
    background: transparent; border: 0; width: 100%; font: inherit;
}
.fk-option__none:hover { background: var(--surface-muted); }

/* Multi-FK / tag picker (chips inside an input field) */
.multi-picker { position: relative; }
.multi-picker__field {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--pt-space-1);
    width: 100%; min-height: 40px; padding: var(--pt-space-1) var(--pt-space-2);
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-sm); cursor: text;
    transition: border-color var(--pt-dur-instant);
}
.multi-picker__field:hover { border-color: var(--pt-fg-muted); }
/* Ring on the chip field, not the bare inner input (same reason as .input-affix). */
.multi-picker__field.is-focused { box-shadow: var(--pt-focus-ring); }
.multi-picker__input:focus-visible { box-shadow: none; }
.multi-picker__chip {
    display: inline-flex; align-items: center; gap: var(--pt-space-1);
    padding: var(--pt-space-1) var(--pt-space-1) var(--pt-space-1) var(--pt-space-3); background: var(--surface-muted);
    border-radius: var(--pt-radius-pill); font-size: var(--pt-text-xs); font-weight: 500;
}
.multi-picker__chip__remove {
    display: inline-flex; align-items: center; justify-content: center;
    width: 20px; height: 20px; border-radius: 50%;
    color: var(--pt-fg-muted); border: 0; background: transparent; cursor: pointer;
    transition: transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.multi-picker__chip__remove:hover { background: var(--pt-border); color: var(--pt-fg); }
.multi-picker__input {
    flex: 1; min-width: 80px; padding: var(--pt-space-1); border: 0; outline: none;
    font: inherit; font-size: var(--pt-text-sm); background: transparent; color: var(--pt-fg);
}
.multi-picker__input::placeholder { color: var(--pt-fg-muted); }

/* File drop area */
.file-drop {
    display: flex; align-items: center; gap: var(--pt-space-4);
    padding: var(--pt-space-4); border: 1px dashed var(--pt-border);
    border-radius: var(--pt-radius-sm); cursor: pointer;
    transition: border-color var(--pt-dur-instant), background var(--pt-dur-instant);
}
.file-drop:hover { border-color: var(--pt-fg); background: var(--surface-muted); }
.file-drop__icon {
    width: 40px; height: 40px; border-radius: var(--pt-radius-sm);
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--pt-atmosphere-blue-20); color: var(--pt-ink-on-blue-20);
    flex-shrink: 0; font-size: var(--pt-text-lg);
}
[data-theme="dark"] .file-drop__icon { color: var(--pt-atmosphere-blue); }
.file-drop__main { flex: 1; min-width: 0; }
.file-drop__title { font-size: var(--pt-text-sm); font-weight: 600; }
.file-drop__sub { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); margin-top: var(--pt-space-1); }
.file-current {
    display: inline-flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-2) var(--pt-space-3); background: var(--surface-muted);
    border-radius: var(--pt-radius-sm); font-size: var(--pt-text-xs);
}

/* Existing-file chip (read-only display) */
.file-chip {
    display: inline-flex; align-items: center; gap: var(--pt-space-3);
    padding: var(--pt-space-3) var(--pt-space-4); background: var(--surface-muted);
    border-radius: var(--pt-radius-sm); text-decoration: none; color: var(--pt-fg);
}
.file-chip:hover { background: var(--pt-border); }
.file-chip__icon {
    width: 32px; height: 32px; border-radius: var(--pt-radius-xs);
    display: inline-flex; align-items: center; justify-content: center;
    flex-shrink: 0; font-size: var(--pt-text-md);
    background: var(--pt-atmosphere-blue-20); color: var(--pt-ink-on-blue-20);
}
[data-theme="dark"] .file-chip__icon { color: var(--pt-atmosphere-blue); }
.file-chip__main { line-height: 1.2; }
.file-chip__sub { font-size: var(--pt-text-2xs); color: var(--pt-fg-muted); margin-top: var(--pt-space-1); }

/* Markdown editor toolbar */
.rt-toolbar {
    display: flex; align-items: center; gap: var(--pt-space-1);
    padding: var(--pt-space-2); border: 1px solid var(--pt-border); border-bottom: 0;
    border-radius: var(--pt-radius-sm) var(--pt-radius-sm) 0 0;
    background: var(--surface-muted);
}
.rt-toolbar + .textarea { border-radius: 0 0 var(--pt-radius-sm) var(--pt-radius-sm); }
.rt-btn {
    width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;
    color: var(--pt-fg-muted); background: transparent; border: 0;
    border-radius: var(--pt-radius-pill); cursor: pointer; font-size: var(--pt-text-sm);
    transition: transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.rt-btn:hover { background: var(--pt-border); color: var(--pt-fg); }
.rt-sep { width: 1px; height: 16px; background: var(--pt-border); margin: 0 var(--pt-space-1); }

/* Sticky save bar */
.save-bar {
    position: fixed; left: var(--sidebar-w); right: 0; bottom: 0; z-index: 50;
    /* Shares --bottom-bar-h with the sidebar footer so the two align exactly. */
    height: var(--bottom-bar-h); box-sizing: border-box;
    display: flex; align-items: center; justify-content: space-between; gap: var(--pt-space-4);
    padding: 0 var(--pt-space-6); background: var(--pt-surface); border-top: 1px solid var(--pt-border);
    /* Matches the sidebar's collapse timing (see .sidebar). */
    transition: left var(--pt-dur-fast) var(--pt-ease-paper);
}
@media (min-width: 1600px) { .save-bar { padding: 0 var(--pt-space-8); } }
.save-bar__status { display: inline-flex; align-items: center; gap: var(--pt-space-2); font-size: var(--pt-text-sm); color: var(--pt-fg-muted); }
.save-bar__dot {
    width: 8px; height: 8px; border-radius: 50%; background: var(--pt-solar-gold);
    transition: background var(--pt-dur-base) var(--pt-ease-paper);
}
.save-bar__dot.saved { background: var(--pt-galactic-seafoam); }
.save-bar__actions { display: flex; gap: var(--pt-space-2); }

/* List view: requirement / team list editor rows (used in role edit) */
.req-editor-row { display: flex; align-items: center; gap: var(--pt-space-3); padding: var(--pt-space-2) 0; }
/* Entrance for rows added via the editor's Add button only — listEditor flags them
   `fresh`, so seeded rows don't animate when Alpine renders them on page load. */
.req-editor-row--new {
    transition: opacity var(--pt-dur-fast) var(--pt-ease-paper),
                transform var(--pt-dur-fast) var(--pt-ease-paper);
}
@starting-style {
    .req-editor-row--new { opacity: 0; transform: translateY(-4px); }
}
@media (prefers-reduced-motion: reduce) {
    /* Keep the fade, drop the lift. */
    .req-editor-row--new { transition-property: opacity; }
    @starting-style {
        .req-editor-row--new { transform: none; }
    }
}
.req-editor-row .input { flex: 1; }
.req-editor-row__type { width: 160px; flex-shrink: 0; }
.team-editor-row {
    display: flex; align-items: center; gap: var(--pt-space-3);
    padding: var(--pt-space-3) 0; border-bottom: 1px solid var(--pt-border);
}
.team-editor-row:first-child { padding-top: 0; }
.team-editor-row:last-child { padding-bottom: 0; border-bottom: 0; }
.team-editor-row__name { font-size: var(--pt-text-sm); font-weight: 600; line-height: 1.2; }
.team-editor-row__sub { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); line-height: 1.2; margin-top: var(--pt-space-1); }

/* Full-page edit: constrain the stacked form cards to a comfortable reading width. */
.form-stack { max-width: 880px; }

/* ===== List view toolbar pieces ===== */
.page-headline { font-size: var(--pt-text-2xl); font-weight: 600; line-height: 1.1; color: var(--pt-fg); margin: 0; letter-spacing: -0.01em; }
.page-subtitle { color: var(--pt-fg-muted); font-size: var(--pt-text-sm); margin-top: var(--pt-space-2); }

.eyebrow {
    font-size: var(--pt-text-2xs); font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.1em;
    color: var(--pt-fg-muted);
}

.search-input {
    display: inline-flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-2) var(--pt-space-4); background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-pill); min-width: 280px;
    transition: border-color var(--pt-dur-instant);
}
.search-input:focus-within { border-color: var(--pt-fg); }
.search-input input {
    flex: 1; background: transparent; border: 0; outline: none;
    font: inherit; font-size: var(--pt-text-sm); color: var(--pt-fg); min-width: 0;
}
/* The pill shows focus via :focus-within border; suppress the global focus ring
   so there's no inner rounded-rect highlight inside the pill. */
.search-input input:focus-visible { box-shadow: none; }
.search-input input::placeholder { color: var(--pt-fg-muted); }
.search-input [class^="ph-"], .search-input [class*=" ph-"] { color: var(--pt-fg-muted); font-size: var(--pt-text-md); }

.filter-chip {
    display: inline-flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-1) var(--pt-space-1) var(--pt-space-1) var(--pt-space-3); font-size: var(--pt-text-xs); font-weight: 500;
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-pill); color: var(--pt-fg);
    cursor: pointer;
    transition: border-color var(--pt-dur-instant);
}
.filter-chip:hover { border-color: var(--pt-fg); }
.filter-chip .chip-op { color: var(--pt-fg-muted); font-weight: 400; }
.filter-chip .chip-val { font-weight: 600; }
.filter-chip .chip-x {
    display: inline-flex; align-items: center; justify-content: center;
    width: 20px; height: 20px; border-radius: 50%;
    color: var(--pt-fg-muted); border: 0; background: transparent; cursor: pointer;
    transition: transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.filter-chip .chip-x:hover { background: var(--surface-muted); color: var(--pt-fg); }

/* Filter chip edit popover (click a chip to refine it) */
.filter-chip .chip-body {
    display: inline-flex; align-items: center; gap: var(--pt-space-2);
    background: transparent; border: 0; font: inherit;
    font-size: var(--pt-text-xs); font-weight: 500; cursor: pointer; color: inherit; padding: 0;
}
.chip-edit-panel {
    position: absolute; left: 0; top: calc(100% + 8px); z-index: 60;
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-md); padding: var(--pt-space-1); min-width: 210px;
    transform-origin: top left; /* anchored under the chip's left edge */
}
.chip-edit-panel--wide { min-width: 240px; }
.chip-edit-panel__header {
    font-size: var(--pt-text-2xs); font-weight: 600; text-transform: uppercase;
    letter-spacing: 0.1em; color: var(--pt-fg-muted); padding: var(--pt-space-2) var(--pt-space-3) var(--pt-space-1);
}
.chip-edit-option {
    display: flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-2) var(--pt-space-3); border-radius: var(--pt-radius-sm); cursor: pointer; font-size: var(--pt-text-sm);
}
.chip-edit-option:hover { background: var(--surface-muted); }
.chip-edit-panel__footer {
    display: flex; justify-content: flex-end; gap: var(--pt-space-2);
    padding: var(--pt-space-2); border-top: 1px solid var(--pt-border); margin-top: var(--pt-space-1);
}

.filter-add {
    display: inline-flex; align-items: center; gap: var(--pt-space-1);
    padding: var(--pt-space-2) var(--pt-space-3); font-size: var(--pt-text-xs); font-weight: 500;
    color: var(--pt-fg-muted); background: transparent;
    border: 1px dashed var(--pt-border); border-radius: var(--pt-radius-pill); cursor: pointer;
    transition: border-color var(--pt-dur-instant), color var(--pt-dur-instant), transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.filter-add:hover { border-style: solid; border-color: var(--pt-fg); color: var(--pt-fg); }

/* Pagination */
.pager {
    display: flex; align-items: center; justify-content: space-between;
    padding: var(--pt-space-3) var(--pt-space-4); border-top: 1px solid var(--pt-border); background: var(--pt-surface);
}
.pager-info { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); }
.pager-info strong { color: var(--pt-fg); font-weight: 600; }
.pager-controls { display: flex; align-items: center; gap: var(--pt-space-1); }
.pager-btn {
    min-width: 32px; height: 32px; padding: 0 var(--pt-space-3);
    display: inline-flex; align-items: center; justify-content: center; gap: var(--pt-space-1);
    font-size: var(--pt-text-xs); font-weight: 500; color: var(--pt-fg); background: var(--pt-surface);
    border: 1px solid var(--pt-border); border-radius: var(--pt-radius-pill); cursor: pointer;
    transition: border-color var(--pt-dur-instant), transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.pager-btn { text-decoration: none; }
.pager-btn:hover { border-color: var(--pt-fg); }
.pager-btn.is-current { background: var(--pt-fg); color: var(--pt-surface); border-color: var(--pt-fg); }
.pager-btn.is-disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
.pager-ellipsis { color: var(--pt-fg-muted); padding: 0 var(--pt-space-1); }

/* Entrance only — @starting-style fires on the display:none -> flex flip when the
   first row is selected. Opacity alone (no travel): this swaps in tens of times a
   day, so it must stay near-imperceptible. Deselection snaps deliberately. */
.bulk-bar {
    display: flex; align-items: center; gap: var(--pt-space-4);
    transition: opacity var(--pt-dur-fast) var(--pt-ease-paper);
}
@starting-style {
    .bulk-bar { opacity: 0; }
}
.bulk-action {
    display: inline-flex; align-items: center; gap: var(--pt-space-2);
    font-size: var(--pt-text-sm); font-weight: 600; color: var(--pt-fg); cursor: pointer;
    background: transparent; border: 0; padding: 0;
}
.bulk-action:hover { color: var(--pt-rocket-flame); }
.bulk-action.danger:hover { color: var(--pt-red-alert); }

/* ===== Drawer (list view column picker) ===== */
/* Both halves rest in their CLOSED state and flip on .is-open (bound in
   _column_picker.html), rather than being mounted and class-swapped by an Alpine
   x-transition. Two things come out of that: the panel is laid out and painted once
   at page load, so opening is pure compositing with no first-frame hitch; and a
   plain CSS transition is interruptible, so toggling mid-travel reverses from wherever
   the panel is instead of snapping to the end state and starting over.
   The scrim fades on the same curve/duration as the panel so the dimming doesn't land
   before the thing it's dimming for. Exit uses ease-out (never ease-in — it would stall
   on the frame the user is watching) and is quicker than the entrance: the closed rules
   carry the exit duration, the .is-open rules override it with the slower entrance. */
.drawer-backdrop {
    position: fixed; inset: 0; background: var(--pt-scrim); z-index: 200;
    opacity: 0; pointer-events: none;
    transition: opacity var(--pt-dur-fast) var(--pt-ease-drawer);
}
.drawer-backdrop.is-open {
    opacity: 1; pointer-events: auto;
    transition-duration: var(--pt-dur-base);
}
.drawer {
    position: fixed; top: 0; right: 0; bottom: 0; width: 380px; z-index: 201;
    background: var(--pt-surface); border-left: 1px solid var(--pt-border);
    display: flex; flex-direction: column;
    /* visibility (not display) keeps the closed panel out of the tab order without
       costing a layout pass on open; it flips at the end of the exit so it can't
       blank the panel mid-slide. */
    transform: translateX(100%); visibility: hidden;
    transition: transform var(--pt-dur-fast) var(--pt-ease-drawer),
                visibility var(--pt-dur-fast);
}
.drawer.is-open {
    transform: none; visibility: visible;
    transition-duration: var(--pt-dur-base);
}
.drawer-header {
    padding: var(--pt-space-5) var(--pt-space-6); border-bottom: 1px solid var(--pt-border);
    display: flex; align-items: center; justify-content: space-between;
}
.drawer-title { font-size: var(--pt-text-md); font-weight: 600; }
.drawer-sub { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); margin-top: var(--pt-space-1); }
.drawer-body { flex: 1; overflow-y: auto; padding: var(--pt-space-4); }
.drawer-footer {
    padding: var(--pt-space-4) var(--pt-space-6); border-top: 1px solid var(--pt-border);
    display: flex; justify-content: space-between; gap: var(--pt-space-2); align-items: center;
}
.col-search {
    width: 100%; padding: var(--pt-space-2) var(--pt-space-3) var(--pt-space-2) 36px;
    background: var(--surface-muted); border: 1px solid transparent;
    border-radius: var(--pt-radius-pill); font: inherit; font-size: var(--pt-text-sm);
    color: var(--pt-fg); outline: none;
}
.col-search:focus { background: var(--pt-surface); }
.col-item {
    display: flex; align-items: center; gap: var(--pt-space-3);
    padding: var(--pt-space-2) var(--pt-space-3); border-radius: var(--pt-radius-sm);
    transition: background var(--pt-dur-instant);
}
.col-item:hover { background: var(--surface-muted); }
.col-item.is-dragging { opacity: 0.4; }
.col-item.is-drop-target { background: var(--pt-rocket-flame-20); }
.col-item.is-hidden { opacity: 0.6; }
.col-item__handle { color: var(--pt-fg-muted); font-size: var(--pt-text-md); cursor: grab; }
.col-item__handle:active { cursor: grabbing; }
.col-item__label { flex: 1; font-size: var(--pt-text-sm); font-weight: 500; }
.col-item__type {
    font-size: var(--pt-text-2xs); font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.1em;
    color: var(--pt-fg-muted);
}
.section-label {
    font-size: var(--pt-text-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em;
    color: var(--pt-fg-muted); margin: var(--pt-space-4) 0 var(--pt-space-1); padding: 0 var(--pt-space-3);
}
.section-label:first-child { margin-top: var(--pt-space-1); }

/* ===== Cost drawer (slide-over cost creator) ===== */
/* Rides the generic .drawer shell above; the swapped content states own their
   layout — a full-height pane with a scrolling middle and a pinned footer. */
.cost-drawer { width: 420px; max-width: 100vw; }
.cost-drawer__content { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.cost-drawer__pane { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.cost-drawer__scroll {
    flex: 1; overflow-y: auto; padding: var(--pt-space-5) var(--pt-space-6);
    display: flex; flex-direction: column; gap: var(--pt-space-5); align-items: stretch;
}
.cost-drawer__footer {
    padding: var(--pt-space-4) var(--pt-space-6); border-top: 1px solid var(--pt-border);
    display: flex; align-items: center; gap: var(--pt-space-2);
}
.cost-drawer__nested { margin-left: calc(16px + var(--pt-space-2)); }

.drawer-hint { font-size: var(--pt-text-sm); color: var(--pt-fg-muted); }
.drawer-back {
    align-self: flex-start; display: inline-flex; align-items: center; gap: var(--pt-space-1);
    background: none; border: 0; padding: 0; font: inherit;
    font-size: var(--pt-text-xs); font-weight: 600; color: var(--pt-fg-muted); cursor: pointer;
}
.drawer-back:hover { color: var(--pt-fg); }
.drawer-note {
    display: flex; align-items: center; gap: var(--pt-space-2);
    padding: var(--pt-space-3) var(--pt-space-4); border-radius: var(--pt-radius-sm);
    font-size: var(--pt-text-sm); font-weight: 500;
}
.drawer-note--success { background: var(--pt-galactic-seafoam-20); color: var(--pt-ink-on-seafoam-20); }

.cost-cat-list { display: flex; flex-direction: column; gap: var(--pt-space-2); }
.cost-cat {
    display: flex; align-items: center; gap: var(--pt-space-3); width: 100%; text-align: left;
    padding: var(--pt-space-3) var(--pt-space-4); font: inherit; color: var(--pt-fg);
    background: var(--pt-surface); border: 1px solid var(--pt-border); border-radius: var(--pt-radius-md);
    cursor: pointer; transition: border-color var(--pt-dur-instant);
}
.cost-cat:hover { border-color: var(--pt-rocket-flame); }
.cost-cat__icon {
    flex: 0 0 auto; width: 36px; height: 36px; border-radius: var(--pt-radius-sm);
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--pt-rocket-flame-20); color: var(--pt-ink-on-flame-20);
    font-size: var(--pt-text-lg);
}
.cost-cat__text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.cost-cat__label { font-size: var(--pt-text-sm); font-weight: 600; }
.cost-cat__desc { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); }
.cost-cat__caret { color: var(--pt-fg-muted); transition: color var(--pt-dur-instant), transform var(--pt-dur-instant); }
.cost-cat:hover .cost-cat__caret { color: var(--pt-rocket-flame); transform: translateX(2px); }

.check-row {
    display: flex; align-items: center; gap: var(--pt-space-2);
    font-size: var(--pt-text-sm); cursor: pointer;
}
.choice-card {
    display: flex; align-items: flex-start; gap: var(--pt-space-2);
    padding: var(--pt-space-3); border: 1px solid var(--pt-border); border-radius: var(--pt-radius-sm);
    cursor: pointer; transition: border-color var(--pt-dur-instant), background var(--pt-dur-instant);
}
.choice-card:has(input:checked) { border-color: var(--pt-rocket-flame); background: var(--pt-rocket-flame-20); }
.choice-card__text { display: flex; flex-direction: column; gap: 2px; }
.choice-card__label { font-size: var(--pt-text-sm); font-weight: 500; }
.choice-card__desc { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); }

/* A just-created row announces itself, then settles. */
tr.row-flash > td { animation: row-flash 1.2s var(--pt-ease-paper); }
@keyframes row-flash {
    0%, 40% { background: var(--pt-rocket-flame-20); }
    100% { background: transparent; }
}
@media (prefers-reduced-motion: reduce) {
    tr.row-flash > td { animation: none; }
    .cost-cat:hover .cost-cat__caret { transform: none; }
}

/* ===== Toast ===== */
.toast-stack {
    position: fixed; top: 24px; left: 50%; transform: translateX(-50%); z-index: 300;
    display: flex; flex-direction: column;
    width: min(380px, calc(100vw - 32px));
    pointer-events: none; /* let clicks through the gaps; each toast re-enables */
}
/* Each toast sits in a cell that collapses as the toast leaves, so its neighbours
   slide up instead of teleporting when the node is removed. The travel is an inline
   pixel height set by dismissToast, since height:auto isn't interpolatable. The 10px
   spacing lives here rather than as
   the stack's gap so it collapses on the same transition. overflow:hidden only while
   leaving, so the toast's box-shadow isn't clipped at rest. */
.toast-cell {
    margin-bottom: var(--pt-space-2);
    transition: height var(--pt-dur-fast) var(--pt-ease-paper),
                margin-bottom var(--pt-dur-fast) var(--pt-ease-paper);
}
.toast-cell--leaving { margin-bottom: 0; overflow: hidden; }
.toast {
    pointer-events: auto;
    display: flex; align-items: flex-start; gap: var(--pt-space-3);
    padding: var(--pt-space-3) var(--pt-space-4);
    background: var(--pt-surface); color: var(--pt-fg);
    border: 1px solid var(--pt-border);
    border-left: 3px solid var(--pt-fg-muted);
    border-radius: var(--pt-radius-sm);
    box-shadow: 0 8px 24px rgba(18, 19, 20, 0.14);
    font-size: var(--pt-text-sm); line-height: 1.4;
}
/* Transitions (not keyframes) so a toast dismissed mid-entry retargets from wherever
   it is instead of restarting from zero — toasts stack and get dismissed rapidly. */
.toast {
    opacity: 1; transform: translateY(0);
    transition: opacity var(--pt-dur-base) var(--pt-ease-paper),
                transform var(--pt-dur-base) var(--pt-ease-paper);
}
@starting-style {
    .toast { opacity: 0; transform: translateY(-8px); }
}
.toast--leaving {
    opacity: 0; transform: translateY(-8px);
    transition-duration: var(--pt-dur-fast);
}
@media (prefers-reduced-motion: reduce) {
    /* Keep the opacity fade (it explains that a toast arrived/left), drop the travel. */
    .toast { transform: none; }
    @starting-style {
        .toast { transform: none; }
    }
    .toast--leaving { transform: none; }
}
.toast__icon { flex-shrink: 0; margin-top: 1px; font-size: var(--pt-text-lg); color: var(--pt-fg-muted); }
.toast__body { flex: 1; min-width: 0; }
.toast__title { font-weight: 600; margin-bottom: 2px; }
.toast__msg { font-weight: 500; word-break: break-word; }
.toast__title + .toast__msg { font-weight: 400; color: var(--pt-fg-muted); }
/* Inline action (e.g. Undo) — the primitive that lets reversible bulk actions
   skip the confirm dialog. */
.toast__action {
    flex-shrink: 0; align-self: center;
    padding: var(--pt-space-1) var(--pt-space-2);
    font-family: inherit; font-size: var(--pt-text-xs); font-weight: 600; line-height: 1;
    background: none; border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-sm); color: var(--pt-fg); cursor: pointer;
    transition: transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.toast__action:hover { background: var(--surface-muted); }
.toast__close {
    flex-shrink: 0; padding: 2px; margin: -2px -2px 0 0;
    background: none; border: 0; cursor: pointer; line-height: 1;
    font-size: var(--pt-text-sm); color: var(--pt-fg-muted); border-radius: var(--pt-radius-xs);
    transition: transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.toast__close:hover { color: var(--pt-fg); background: var(--surface-muted); }

/* Type accents — left bar + icon pick up the brand color for the level. */
.toast--success { border-left-color: var(--pt-galactic-seafoam); }
.toast--success .toast__icon { color: var(--pt-galactic-seafoam); }
.toast--error   { border-left-color: var(--pt-red-alert); }
.toast--error   .toast__icon { color: var(--pt-red-alert); }
.toast--warning { border-left-color: var(--pt-solar-gold); }
.toast--warning .toast__icon { color: var(--pt-solar-gold); }
.toast--info    { border-left-color: var(--pt-atmosphere-blue); }
.toast--info    .toast__icon { color: var(--pt-atmosphere-blue); }

/* ===== Modal / confirmation dialog ===== */
.modal-backdrop {
    position: fixed; inset: 0; z-index: 400;
    display: flex; align-items: center; justify-content: center; padding: var(--pt-space-6);
    background: rgba(18, 19, 20, 0.45); /* dim slightly */
    -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
    opacity: 1;
    transition: opacity var(--pt-dur-base) var(--pt-ease-paper);
}
@starting-style {
    .modal-backdrop { opacity: 0; }
}
.modal {
    width: min(440px, 100%); max-height: calc(100vh - 48px); overflow-y: auto;
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-md);
    box-shadow: 0 24px 60px rgba(18, 19, 20, 0.28);
    outline: none;
    opacity: 1; transform: none;
    transition: transform var(--pt-dur-base) var(--pt-ease-paper),
                opacity var(--pt-dur-base) var(--pt-ease-paper);
}
@starting-style {
    .modal { opacity: 0; transform: translateY(8px) scale(0.97); }
}
.modal--lg { width: min(640px, 100%); }
.modal-header { display: flex; align-items: flex-start; gap: var(--pt-space-4); padding: var(--pt-space-6) var(--pt-space-6) 0; }
.modal-icon {
    flex-shrink: 0; width: 40px; height: 40px; border-radius: var(--pt-radius-pill);
    display: flex; align-items: center; justify-content: center; font-size: var(--pt-text-lg);
    background: var(--pt-atmosphere-blue-20); color: var(--pt-ink-on-blue-20);
}
.modal-icon--danger  { background: var(--pt-red-alert-20);       color: var(--pt-ink-on-red-20); }
.modal-icon--warning { background: var(--pt-solar-gold-20);      color: var(--pt-ink-on-gold-20); }
.modal-icon--success { background: var(--pt-galactic-seafoam-20); color: var(--pt-ink-on-seafoam-20); }
.modal-title { font-size: var(--pt-text-md); font-weight: 600; line-height: 1.3; padding-top: var(--pt-space-2); }
.modal-header + .modal-body { padding-top: var(--pt-space-2); }
.modal-body { padding: var(--pt-space-6) var(--pt-space-6) 0; }
.modal-header .modal-icon + .modal-title { /* aligns title beside the icon badge */ }
.modal-message { font-size: var(--pt-text-sm); line-height: 1.55; color: var(--pt-fg-muted); }
/* promptModal's text field; the message (when present) sits directly above. */
.prompt-input {
    width: 100%; margin-top: var(--pt-space-3);
    padding: var(--pt-space-2) var(--pt-space-3);
    font: inherit; font-size: var(--pt-text-sm); color: var(--pt-fg);
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-sm);
}
.prompt-input::placeholder { color: var(--pt-fg-muted); }
.modal-footer { display: flex; justify-content: flex-end; gap: var(--pt-space-2); padding: var(--pt-space-6); }
/* Exit is deliberately quicker than the entrance — the system's response snaps. */
.modal-backdrop.is-leaving { opacity: 0; transition-duration: var(--pt-dur-fast); }
.modal-backdrop.is-leaving .modal {
    transform: translateY(8px) scale(0.98); opacity: 0;
    transition-duration: var(--pt-dur-fast);
}
@media (prefers-reduced-motion: reduce) {
    /* Keep both fades — the scrim and dialog still explain themselves — drop the travel. */
    .modal { transition-property: opacity; }
    @starting-style {
        .modal { transform: none; }
    }
    .modal-backdrop.is-leaving .modal { transform: none; }
}

/* ===== Board peek (the modal a board card opens into) ===== */
/* Lives in a .modal--lg body: identity strip, fact grid, then the work-item
   rows. Deliberately the same label + .status-badge pairing as the list cells so
   a status reads the same wherever it appears. */
/* The root takes the opening focus; scroll-margin keeps the modal-body padding
   above it, so focusing it doesn't nudge the dialog off its own top. */
.peek { scroll-margin-top: var(--pt-space-6); outline: none; }
.peek__head { display: flex; align-items: flex-start; gap: var(--pt-space-3); }
.peek__av { width: 40px; height: 40px; font-size: var(--pt-text-xs); }
.peek__ident { min-width: 0; flex: 1; }
.peek__name {
    display: flex; align-items: center; gap: var(--pt-space-2);
    font-size: var(--pt-text-md); font-weight: 600; line-height: 1.3;
}
.peek__star { color: var(--pt-solar-gold); font-size: var(--pt-text-sm); }
.peek__sub { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); margin-top: 2px; }
.peek__badges { display: flex; flex-direction: column; align-items: flex-end; gap: var(--pt-space-2); flex-shrink: 0; }
.peek__match { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); }

.peek__facts {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
    gap: var(--pt-space-3); margin-top: var(--pt-space-5);
    padding: var(--pt-space-4) 0; border-top: 1px solid var(--pt-border); border-bottom: 1px solid var(--pt-border);
}
.peek__fact dt {
    display: flex; align-items: center; gap: var(--pt-space-1);
    font-size: var(--pt-text-2xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--pt-fg-muted);
}
.peek__fact dd { margin-top: 2px; font-size: var(--pt-text-sm); font-weight: 600; }

.peek__section { margin-top: var(--pt-space-5); }
.peek__section-title {
    font-size: var(--pt-text-2xs); text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--pt-fg-muted); margin-bottom: var(--pt-space-2);
}
.peek__items { display: flex; flex-direction: column; gap: var(--pt-space-2); }
.peek__item {
    display: flex; align-items: center; justify-content: space-between; gap: var(--pt-space-3);
    padding: var(--pt-space-3); border: 1px solid var(--pt-border); border-radius: var(--pt-radius-sm);
    background: var(--pt-bg);
}
.peek__item-text { min-width: 0; }
.peek__item-label { display: block; font-size: var(--pt-text-sm); font-weight: 500; }
.peek__item-detail { display: block; font-size: var(--pt-text-xs); color: var(--pt-fg-muted); margin-top: 2px; }
.peek__item .status-badge { flex-shrink: 0; gap: var(--pt-space-1); }
/* The invite/booking rows carry their own icon, so the badge's dot would double up. */
.peek__item .status-badge:has(i)::before { display: none; }
/* Banked work is context, not the thing being scanned — mute it a step. */
.peek__items--done .peek__item { background: transparent; }
.peek__items--done .peek__item-label { color: var(--pt-fg-muted); font-weight: 400; }

.peek__next {
    display: flex; align-items: center; gap: var(--pt-space-2);
    margin-top: var(--pt-space-5); font-size: var(--pt-text-xs); color: var(--pt-fg-muted);
}

/* ===== Command palette (⌘K) ===== */
.palette-backdrop {
    position: fixed; inset: 0; z-index: 400;
    display: flex; justify-content: center; align-items: flex-start;
    padding: 12vh var(--pt-space-6) var(--pt-space-6);
    background: rgba(18, 19, 20, 0.45);
    -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
    opacity: 1;
    transition: opacity var(--pt-dur-instant) var(--pt-ease-paper);
}
@starting-style {
    .palette-backdrop { opacity: 0; }
}
.palette {
    width: min(560px, 100%); max-height: min(420px, 76vh);
    display: flex; flex-direction: column; overflow: hidden;
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-md);
    box-shadow: 0 24px 60px rgba(18, 19, 20, 0.28);
    /* Keyboard-initiated and used constantly — entrance stays at the instant
       tier (unlike the modal's base tier) so it never reads as lag. */
    opacity: 1; transform: none;
    transition: transform var(--pt-dur-instant) var(--pt-ease-paper),
                opacity var(--pt-dur-instant) var(--pt-ease-paper);
}
@starting-style {
    .palette { opacity: 0; transform: scale(0.99); }
}
.palette-backdrop.is-leaving { opacity: 0; transition-duration: var(--pt-dur-instant); }
.palette-input {
    display: flex; align-items: center; gap: var(--pt-space-3); padding: var(--pt-space-1) var(--pt-space-4);
    border-bottom: 1px solid var(--pt-border); flex-shrink: 0;
}
.palette-input [class^="ph-"] { color: var(--pt-fg-muted); font-size: var(--pt-text-md); }
.palette-input input {
    flex: 1; height: 46px; min-width: 0; border: 0; background: none; outline: none;
    font-family: inherit; font-size: var(--pt-text-md); color: var(--pt-fg);
}
.palette-input input::placeholder { color: var(--pt-fg-muted); }
.palette-input input:focus-visible { box-shadow: none; }
.palette-input kbd, .palette-footer kbd, .kbd-row kbd {
    font-size: var(--pt-text-2xs); font-weight: 600; padding: 2px var(--pt-space-2); line-height: 16px;
    background: var(--pt-bg); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-md); color: var(--pt-fg-muted); font-family: inherit;
}

/* Keyboard-help grid (the "?" modal). */
.kbd-grid { display: grid; grid-template-columns: 1fr; gap: var(--pt-space-3); }
@media (min-width: 480px) { .kbd-grid { grid-template-columns: 1fr 1fr; column-gap: var(--pt-space-8); } }
.kbd-row {
    display: flex; align-items: center; justify-content: space-between; gap: var(--pt-space-4);
    font-size: var(--pt-text-sm); color: var(--pt-fg);
}
.kbd-keys { display: inline-flex; gap: var(--pt-space-1); }
.palette-results { overflow-y: auto; padding: var(--pt-space-2); flex: 1; }
.palette-group-label {
    font-size: var(--pt-text-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em;
    color: var(--pt-fg-muted); padding: var(--pt-space-3) var(--pt-space-3) var(--pt-space-1);
}
.palette-item {
    display: flex; align-items: center; gap: var(--pt-space-3); width: 100%;
    padding: var(--pt-space-3) var(--pt-space-3); border: 0; border-radius: var(--pt-radius-sm);
    background: none; text-align: left; cursor: pointer;
    font-family: inherit; color: var(--pt-fg);
}
.palette-item [class^="ph-"] { font-size: var(--pt-text-lg); color: var(--pt-fg-muted); flex-shrink: 0; }
.palette-item__title {
    font-size: var(--pt-text-sm); font-weight: 500;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.palette-item__sub {
    margin-left: auto; padding-left: var(--pt-space-3); flex-shrink: 0;
    font-size: var(--pt-text-xs); color: var(--pt-fg-muted); white-space: nowrap;
}
/* Highlight follows keyboard + hover; flame accent marks the committed row. */
.palette-item.is-active { background: var(--surface-muted); box-shadow: inset 2px 0 0 var(--pt-rocket-flame); }
.palette-item.is-active [class^="ph-"] { color: var(--pt-fg); }
.palette-empty { padding: var(--pt-space-6) var(--pt-space-4); text-align: center; font-size: var(--pt-text-sm); color: var(--pt-fg-muted); }
.palette-footer {
    display: flex; gap: var(--pt-space-4); padding: var(--pt-space-2) var(--pt-space-4); flex-shrink: 0;
    border-top: 1px solid var(--pt-border);
    font-size: var(--pt-text-xs); color: var(--pt-fg-muted);
}
.palette-footer span { display: inline-flex; align-items: center; gap: var(--pt-space-1); }
@media (prefers-reduced-motion: reduce) {
    .palette { transition-property: opacity; }
    @starting-style {
        .palette { transform: none; }
    }
}

/* ===== History / activity timeline ===== */
/* Structured, not prose: when / rail / who / what are four tracks that line up
   down the whole log, so a reader can scan one column at a time. --history-cols
   is declared once and reused by the header row and every event row. */
.history {
    --history-cols: 12px 76px 112px minmax(0, 1fr);
    display: flex; flex-direction: column;
}
.history-cols,
.history-row {
    display: grid; grid-template-columns: var(--history-cols); gap: var(--pt-space-3);
}
.history-cols {
    font-size: var(--pt-text-2xs); font-weight: 600; color: var(--pt-fg-muted);
    text-transform: uppercase; letter-spacing: 0.04em;
    padding-bottom: var(--pt-space-3); margin-bottom: var(--pt-space-4);
    border-bottom: 1px solid var(--pt-border);
}
/* Dissolves so when/who land in the outer grid's own tracks; becomes a real box
   again in the narrow layout below. */
.history-meta { display: contents; }

.history-when {
    font-size: var(--pt-text-xs); color: var(--pt-fg-muted);
    font-variant-numeric: tabular-nums; padding-bottom: var(--pt-space-5);
}
.history-who {
    font-size: var(--pt-text-xs); font-weight: 500; color: var(--pt-fg);
    padding-bottom: var(--pt-space-5); min-width: 0; overflow-wrap: break-word;
}
.history-what { min-width: 0; padding-bottom: var(--pt-space-5); }
.history-row:last-child .history-when,
.history-row:last-child .history-who,
.history-row:last-child .history-what { padding-bottom: 0; }

.history-rail { display: flex; flex-direction: column; align-items: center; flex-shrink: 0; }
/* Uniform: the dot marks where an entry starts, nothing more. Colouring it by
   event type implied a severity the log doesn't have. */
.history-dot {
    width: 10px; height: 10px; border-radius: 50%; margin-top: 4px;
    background: var(--pt-polished-steel); flex-shrink: 0;
}
.history-line { flex: 1; width: 2px; background: var(--pt-border); margin-top: var(--pt-space-1); }
.history-row:last-child .history-line { display: none; }

.history-event { font-size: var(--pt-text-sm); display: flex; flex-wrap: wrap; gap: var(--pt-space-2); align-items: baseline; }
.history-action { font-weight: 600; color: var(--pt-fg); }
/* The candidate an event happened to — sits beside the action, links to their match. */
.history-subject { font-weight: 600; color: var(--pt-rocket-flame); text-decoration: none; }
.history-subject:hover { text-decoration: underline; }

/* Only the field name gets a track. The values read as one phrase —
   old → new, a single space either side of the arrow — so the eye never has to
   cross a gap to find what it became. */
.history-changes { margin-top: var(--pt-space-2); display: flex; flex-direction: column; gap: var(--pt-space-1); }
.history-change {
    display: grid; grid-template-columns: 104px minmax(0, 1fr);
    align-items: baseline; gap: var(--pt-space-2); font-size: var(--pt-text-xs);
}
.history-change__field { color: var(--pt-fg-muted); font-weight: 500; }
.history-change__values {
    display: inline-flex; flex-wrap: wrap; align-items: baseline;
    gap: 0 var(--pt-space-2); min-width: 0;
}
.history-change__from { color: var(--pt-fg-muted); text-decoration: line-through; }
.history-change__arrow { color: var(--pt-fg-muted); font-size: var(--pt-text-xs); }
.history-change__to { color: var(--pt-fg); font-weight: 500; }

.history-empty { font-size: var(--pt-text-sm); color: var(--pt-fg-muted); }

/* Narrow: the fixed when/who tracks stop fitting, so the meta box reassembles as
   one line above the event and the rail spans both rows beside it. */
@media (max-width: 719px) {
    .history { --history-cols: 12px minmax(0, 1fr); }
    .history-cols { display: none; }
    .history-rail { grid-row: 1 / span 2; }
    .history-meta {
        display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--pt-space-2);
        grid-column: 2; grid-row: 1; margin-bottom: var(--pt-space-1);
    }
    .history-when, .history-who { padding-bottom: 0; }
    .history-what { grid-column: 2; grid-row: 2; }
    /* The field name stacks above its values; the old → new phrase stays intact. */
    .history-change { grid-template-columns: minmax(0, 1fr); gap: 0; }
}

/* ===== Long-text prose ===== */
.markdown {
    font-size: var(--pt-text-sm); line-height: 1.65; color: var(--pt-fg);
}
.markdown h1, .markdown h2, .markdown h3 { color: var(--pt-fg); font-weight: 600; margin: var(--pt-space-4) 0 var(--pt-space-2); }
.markdown h1 { font-size: var(--pt-text-lg); }
.markdown h2 { font-size: var(--pt-text-md); }
.markdown h3 { font-size: var(--pt-text-sm); }
.markdown p { margin-bottom: var(--pt-space-3); }
.markdown ul, .markdown ol { margin-bottom: var(--pt-space-3); padding-left: var(--pt-space-5); }
.markdown ul { list-style: disc; }
.markdown ol { list-style: decimal; }
.markdown li { margin-bottom: var(--pt-space-1); }
.markdown a { color: var(--pt-rocket-flame); text-decoration: underline; }
.prose-card-content {
    font-size: var(--pt-text-sm); color: var(--pt-fg);
    line-height: 1.65; white-space: pre-wrap;
}

/* ===== Candidate review (three-column desk) ===== */
/* Breadcrumb row doubles as the pipeline pager — the decision lives at the foot
   of the assessment column, so the desk carries no bar of its own. */
/* The breadcrumb keeps its own box — same top edge, same margin below it as on
   every other page. Anything else shifts the crumb during a shell swap, since
   the swap leaves it on screen while the rest of the page changes underneath. */
.desk-topbar {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: var(--pt-space-4); flex-wrap: wrap;
}
/* Half the difference between the 32px pager and the 18px crumb line: centres
   the pager on that line rather than growing the row and pushing the crumb down. */
.desk-pager { display: inline-flex; align-items: center; gap: var(--pt-space-2); margin-top: -7px; }
.desk-pager__count { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); font-variant-numeric: tabular-nums; padding: 0 var(--pt-space-1); }
.desk-pager__count strong { color: var(--pt-fg); font-weight: 600; }
.review-nav-btn {
    width: 32px; height: 32px; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--pt-radius-pill); border: 1px solid var(--pt-border);
    background: var(--pt-surface); color: var(--pt-fg); text-decoration: none;
    transition: border-color var(--pt-dur-instant), transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.review-nav-btn:hover { border-color: var(--pt-fg); }
.review-nav-btn [class^="ph-"], .review-nav-btn [class*=" ph-"] { font-size: var(--pt-text-sm); }
.review-nav-btn.is-disabled { opacity: 0.4; pointer-events: none; }

/* Role · candidate · assessment. Stacked and page-scrolled by default; the
   viewport-filling desk with three self-scrolling columns starts at 1280px. */
.review-desk { display: grid; gap: var(--pt-space-4); grid-template-columns: minmax(0, 1fr); }
.desk-col {
    min-width: 0; display: flex; flex-direction: column;
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-md); overflow: hidden;
}
/* One card per column: the section-cards stacked inside are seams, not cards, so
   they shed their own chrome and separate on a hairline instead. */
.desk-col .section-card { border: 0; border-radius: 0; background: transparent; overflow: visible; }
.desk-col .section-card + .section-card { margin-top: 0; border-top: 1px solid var(--pt-border); }
.desk-col__head {
    display: flex; align-items: flex-start; gap: var(--pt-space-4); flex: none;
    padding: var(--pt-space-6); border-bottom: 1px solid var(--pt-border);
}
.desk-col__head-action { flex-shrink: 0; }
.desk-col__scroll { min-height: 0; }

@media (min-width: 1280px) {
    /* No page scroll: the shell owns the viewport and each column scrolls itself,
       so the decision and the candidate's name never leave the screen. */
    .main-content.review-page {
        height: 100vh; min-height: 0; display: flex; flex-direction: column; overflow: hidden;
    }
    .review-desk {
        flex: 1; min-height: 0;
        grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.16fr) minmax(0, 1fr);
    }
    .desk-col__scroll { flex: 1; overflow-y: auto; }
}

/* Resume, filling the rest of the candidate column. */
.desk-doc__bar {
    display: flex; align-items: center; justify-content: space-between; gap: var(--pt-space-3);
    flex: none; padding: var(--pt-space-3) var(--pt-space-6); border-bottom: 1px solid var(--pt-border);
}
.desk-doc__name {
    display: inline-flex; align-items: center; gap: var(--pt-space-2); min-width: 0;
    font-size: var(--pt-text-xs); color: var(--pt-fg-muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.desk-doc__actions { display: inline-flex; align-items: center; gap: var(--pt-space-2); flex-shrink: 0; }
.desk-doc { flex: 1; min-height: 0; background: var(--surface-muted); }
.desk-doc__frame { display: block; width: 100%; height: 100%; min-height: 420px; border: 0; }
.desk-doc__fallback {
    display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%;
    gap: var(--pt-space-3); padding: var(--pt-space-16) var(--pt-space-6); text-align: center;
    color: var(--pt-fg-muted); font-size: var(--pt-text-sm);
}
.desk-doc__fallback [class^="ph-"], .desk-doc__fallback [class*=" ph-"] { font-size: 40px; }
.desk-doc__fallback a { color: var(--pt-rocket-flame); text-decoration: underline; }

/* Decision, pinned to the foot of the column it follows from. */
.desk-decide {
    display: flex; align-items: center; gap: var(--pt-space-2); flex: none;
    padding: var(--pt-space-4) var(--pt-space-6); border-top: 1px solid var(--pt-border);
    background: var(--pt-surface);
}
.desk-decide__advance { flex: 1; justify-content: center; }

/* Identity block in a column head — logo/photo, name, sub, meta chips. */
.rev-hero__logo { width: 48px; height: 48px; padding: var(--pt-space-2); flex-shrink: 0; }
.rev-hero__photo { width: 48px; height: 48px; font-size: var(--pt-text-md); flex-shrink: 0; }
.rev-hero__main { flex: 1; min-width: 0; }
.rev-hero__name {
    font-size: var(--pt-text-lg); font-weight: 600; line-height: 1.2; letter-spacing: -0.01em;
    display: flex; align-items: center; gap: var(--pt-space-3); flex-wrap: wrap;
}
.rev-hero__affinity { font-size: var(--pt-text-sm); }
.rev-hero__sub { color: var(--pt-fg-muted); font-size: var(--pt-text-xs); margin-top: var(--pt-space-2); }
.rev-hero__sub a { color: var(--pt-fg); font-weight: 500; text-decoration: none; }
.rev-hero__sub a:hover { color: var(--pt-rocket-flame); }
.rev-hero__meta { display: flex; flex-wrap: wrap; gap: var(--pt-space-2); margin-top: var(--pt-space-3); }

/* Requirement scorecard — verdict icon + text + verdict label. */
.req-list { display: flex; flex-direction: column; }
.req-row {
    display: flex; align-items: flex-start; gap: var(--pt-space-3);
    padding: var(--pt-space-3) 0; border-bottom: 1px solid var(--pt-border); font-size: var(--pt-text-sm);
}
.req-row:first-child { padding-top: 0; }
.req-row:last-child { padding-bottom: 0; border-bottom: 0; }
.req-icon {
    width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0; margin-top: 1px;
    display: inline-flex; align-items: center; justify-content: center; font-size: var(--pt-text-xs);
}
.req-icon--met { background: var(--pt-galactic-seafoam-20); color: var(--pt-ink-on-seafoam-20); }
.req-icon--partial { background: var(--pt-solar-gold-20); color: var(--pt-ink-on-gold-20); }
.req-icon--gap { background: var(--surface-muted); color: var(--pt-fg-muted); }
[data-theme="dark"] .req-icon--met { color: var(--pt-galactic-seafoam); }
[data-theme="dark"] .req-icon--partial { color: var(--pt-solar-gold); }
.req-row__text { flex: 1; line-height: 1.5; }
.req-row__verdict {
    flex-shrink: 0; font-size: var(--pt-text-2xs); font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.08em; color: var(--pt-fg-muted);
}
.req-row__verdict--met { color: var(--pt-ink-on-seafoam-20); }
.req-row__verdict--partial { color: var(--pt-ink-on-gold-20); }
[data-theme="dark"] .req-row__verdict--met { color: var(--pt-galactic-seafoam); }
[data-theme="dark"] .req-row__verdict--partial { color: var(--pt-solar-gold); }

/* Score rows. There is no edit mode: the slider IS the bar, the number IS the
   readout, and either one committing saves the row (see commitScore). */
.score-row + .score-row { margin-top: var(--pt-space-4); }
.score-row__head { display: flex; align-items: center; justify-content: space-between; gap: var(--pt-space-3); }
.score-row__label { font-size: var(--pt-text-sm); font-weight: 500; }

/* Quiet until you reach for it — no field chrome sitting in the column at rest. */
.score-row__value {
    display: inline-flex; align-items: baseline; flex-shrink: 0;
    font-size: var(--pt-text-sm); font-weight: 600; font-variant-numeric: tabular-nums;
}
.score-num {
    width: 40px; padding: 2px 1px 2px var(--pt-space-1); text-align: right;
    font: inherit; color: inherit;
    background: transparent; border: 1px solid transparent; border-radius: var(--pt-radius-sm);
    outline: none; transition: border-color var(--pt-dur-instant);
    /* The spinners would sit between the number and its % sign. */
    -moz-appearance: textfield; appearance: textfield;
}
.score-num:hover, .score-num:focus { border-color: var(--pt-border); }
.score-num::-webkit-inner-spin-button, .score-num::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

.score-range {
    -webkit-appearance: none; appearance: none;
    display: block; width: 100%; margin-top: var(--pt-space-2);
    background: transparent; cursor: pointer;
}
.score-range::-webkit-slider-runnable-track {
    height: 8px; border-radius: var(--pt-radius-pill);
    background: linear-gradient(to right,
        var(--score-tier) 0 var(--score-fill), var(--surface-muted) var(--score-fill) 100%);
}
.score-range::-moz-range-track {
    height: 8px; border-radius: var(--pt-radius-pill);
    background: linear-gradient(to right,
        var(--score-tier) 0 var(--score-fill), var(--surface-muted) var(--score-fill) 100%);
}
.score-range::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 16px; height: 16px; margin-top: -4px; border-radius: 50%;
    background: var(--pt-surface); border: 2px solid var(--score-tier);
    transition: transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.score-range::-moz-range-thumb {
    width: 16px; height: 16px; border-radius: 50%;
    background: var(--pt-surface); border: 2px solid var(--score-tier);
}
.score-range:active::-webkit-slider-thumb { transform: scale(1.15); }
@media (prefers-reduced-motion: reduce) {
    /* The thumb already tracks the pointer — the grow is decoration, not feedback. */
    .score-range::-webkit-slider-thumb { transition: none; }
    .score-range:active::-webkit-slider-thumb { transform: none; }
}
/* The shared ring would box the whole full-width input; put it on the thumb. */
.score-range:focus-visible { box-shadow: none; }
.score-range:focus-visible::-webkit-slider-thumb { box-shadow: var(--pt-focus-ring); }
.score-range:focus-visible::-moz-range-thumb { box-shadow: var(--pt-focus-ring); }

/* Comment composer + thread. */
.comment-composer { display: flex; flex-direction: column; gap: var(--pt-space-2); padding-bottom: var(--pt-space-5); border-bottom: 1px solid var(--pt-border); }
.comment-composer__actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--pt-space-3); }
.comment-thread { display: flex; flex-direction: column; }
.comment-row { display: flex; gap: var(--pt-space-3); padding: var(--pt-space-4) 0; border-bottom: 1px solid var(--pt-border); }
.comment-row:last-child { padding-bottom: 0; border-bottom: 0; }
/* Entrance for client-inserted comments only — server-rendered rows must not
   carry this class or the whole thread animates on page load. */
.comment-row--new {
    transition: opacity var(--pt-dur-base) var(--pt-ease-paper),
                transform var(--pt-dur-base) var(--pt-ease-paper);
}
@starting-style {
    .comment-row--new { opacity: 0; transform: translateY(-4px); }
}
@media (prefers-reduced-motion: reduce) {
    /* Keep the fade, drop the lift. */
    .comment-row--new { transition-property: opacity; }
    @starting-style {
        .comment-row--new { transform: none; }
    }
}
.comment-row__main { min-width: 0; flex: 1; }
.comment-row__meta { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); }
.comment-row__meta strong { color: var(--pt-fg); font-weight: 600; }
.comment-row__body { font-size: var(--pt-text-sm); line-height: 1.6; margin-top: var(--pt-space-1); }
/* In flight: the row is already there and already readable, just not yet real. */
.comment-row--pending { opacity: 0.55; }

/* ===== Inline editing ===== */

/* Right-hand cluster in a .section-head (save caption, toggle, Edit). */
.section-actions { display: flex; align-items: center; gap: var(--pt-space-2); flex-shrink: 0; }

/* Optimistic-save caption. Sized so swapping between states can't reflow the head. */
.save-status { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); }
.save-status__item { display: inline-flex; align-items: center; gap: var(--pt-space-1); }
.save-status__item--ok { color: var(--pt-galactic-seafoam); }
.save-status__item--bad { color: var(--pt-red-alert); }
.save-status__spin { display: inline-block; animation: save-spin 700ms linear infinite; }
@keyframes save-spin { to { transform: rotate(360deg); } }

.inline-edit-actions {
    display: flex; align-items: center; justify-content: flex-end;
    gap: var(--pt-space-3); margin-top: var(--pt-space-4);
}
.inline-edit-hint { font-size: var(--pt-text-2xs); color: var(--pt-fg-muted); margin-right: auto; }

/* ===== Email templates panel ===== */
.tpl-list { display: flex; flex-direction: column; gap: var(--pt-space-4); }
.tpl-head { min-width: 0; }
.tpl-desc { font-size: var(--pt-text-xs); color: var(--pt-fg-muted); margin-top: var(--pt-space-1); }
.tpl-scope {
    font-size: var(--pt-text-2xs); font-weight: 600; padding: 2px var(--pt-space-2);
    border-radius: var(--pt-radius-pill); text-transform: uppercase; letter-spacing: 0.04em;
}
.tpl-scope--role { background: var(--pt-rocket-flame-20); color: var(--pt-ink-on-flame-20); }
.tpl-scope--global { background: var(--surface-muted); color: var(--pt-fg-muted); }
.tpl-version { font-size: var(--pt-text-2xs); color: var(--pt-fg-muted); font-variant-numeric: tabular-nums; }

/* Off means "invites stop going out" — red, full-width, above the fold of the card. */
.tpl-alert {
    display: flex; align-items: flex-start; gap: var(--pt-space-2);
    padding: var(--pt-space-3) var(--pt-space-6);
    background: var(--pt-red-alert-20); color: var(--pt-fg);
    font-size: var(--pt-text-xs); line-height: 1.5;
    border-bottom: 1px solid var(--pt-border);
}
.tpl-alert i { color: var(--pt-red-alert); margin-top: 2px; flex-shrink: 0; }

.tpl-field + .tpl-field { margin-top: var(--pt-space-4); }
.tpl-label {
    display: block; font-size: var(--pt-text-2xs); font-weight: 600; color: var(--pt-fg-muted);
    text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: var(--pt-space-1);
}
.tpl-subject { font-size: var(--pt-text-sm); font-weight: 500; }
.tpl-body {
    font-size: var(--pt-text-sm); line-height: 1.6; color: var(--pt-fg);
    white-space: pre-wrap; word-break: break-word; font-family: inherit;
}

/* Placeholder chips — the only supported way to put a value in, since the
   allow-set is fixed by the intent's value_builder. */
.tpl-chips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--pt-space-2); margin-top: var(--pt-space-4); }
.tpl-chips .tpl-label { margin-bottom: 0; }
.tpl-chip {
    font-family: var(--pt-font-mono); font-size: var(--pt-text-2xs);
    padding: 2px var(--pt-space-2); border-radius: var(--pt-radius-pill);
    background: var(--surface-muted); color: var(--pt-fg-muted);
    border: 1px solid var(--pt-border); cursor: pointer;
    transition: color var(--pt-dur-instant), border-color var(--pt-dur-instant);
}
.tpl-chip:hover { color: var(--pt-fg); border-color: var(--pt-fg); }

.tpl-meta {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
    gap: var(--pt-space-2); margin-top: var(--pt-space-5);
    padding-top: var(--pt-space-3); border-top: 1px solid var(--pt-border);
    font-size: var(--pt-text-2xs); color: var(--pt-fg-muted);
}
.tpl-key { font-family: var(--pt-font-mono); font-size: var(--pt-text-2xs); }

.tpl-toggle {
    display: inline-flex; align-items: center; gap: var(--pt-space-2);
    font-size: var(--pt-text-xs); font-weight: 500; color: var(--pt-fg-muted);
    background: transparent; border: 0; padding: 0; cursor: pointer;
}
.tpl-toggle.is-on { color: var(--pt-fg); }
.tpl-toggle__track {
    width: 32px; height: 18px; border-radius: var(--pt-radius-pill);
    background: var(--pt-border); padding: 2px; display: block;
    transition: background var(--pt-dur-fast) var(--pt-ease-paper);
}
.tpl-toggle.is-on .tpl-toggle__track { background: var(--pt-galactic-seafoam); }
.tpl-toggle__knob {
    width: 14px; height: 14px; border-radius: 50%; background: var(--pt-surface); display: block;
    transition: transform var(--pt-dur-fast) var(--pt-ease-paper);
}
.tpl-toggle.is-on .tpl-toggle__knob { transform: translateX(14px); }

/* ===== Responsive ===== */
@media (max-width: 1023px) {
    .sidebar { transform: translateX(-100%); }
    .sidebar.is-open { transform: translateX(0); }
    /* Off-canvas slide, not a width collapse — ride the drawer curve like the
       columns panel. Exit (closing) is quicker than the entrance. */
    .sidebar { transition: transform var(--pt-dur-fast) var(--pt-ease-drawer); }
    .sidebar.is-open { transition: transform var(--pt-dur-base) var(--pt-ease-drawer); }
    .main-content { margin-left: 0; padding: var(--pt-space-16) var(--pt-space-4) var(--pt-space-4); }
    .main-content.has-save-bar { padding-bottom: var(--pt-space-24); }
    .mobile-sidebar-toggle { display: inline-flex; }
    .save-bar { left: 0; }
    .hero-name { font-size: var(--pt-text-xl); }
    .page-headline { font-size: var(--pt-text-xl); }
}
@media (max-width: 640px) { .search-input { min-width: 0; flex: 1; } }

/* ---------- "Catch Britt" easter-egg game ---------- */
#britt-bored {
    position: fixed; right: 10px; bottom: 8px; z-index: 150;
    font-size: var(--pt-text-xs); line-height: 1; letter-spacing: 0.04em;
    color: var(--pt-fg-muted); text-decoration: none; opacity: 0.5;
    user-select: none;
    transition: opacity var(--pt-dur-instant) var(--pt-ease-paper), color var(--pt-dur-instant);
}
#britt-bored:hover { opacity: 1; color: var(--pt-rocket-flame); }

/* Pure overlay — captures clicks so the page underneath is inert, but no dim. */
#britt-overlay { position: fixed; inset: 0; z-index: 900; display: none; background: transparent; cursor: grab; }
#britt-overlay.is-open { display: block; }
#britt-overlay:active { cursor: grabbing; }
#britt-stage { position: absolute; inset: 0; }
#britt-stage canvas { display: block; }

/* Instruction that pops up next to Britt on launch, then fades after ~3s. */
#britt-hint {
    position: absolute; left: 0; top: 0; transform: translate(-50%, -50%);
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-pill); padding: var(--pt-space-2) var(--pt-space-4);
    font-size: var(--pt-text-xs); color: var(--pt-fg); white-space: nowrap;
    pointer-events: none; opacity: 0;
    transition: opacity 600ms var(--pt-ease-paper);
}
#britt-hint.show { opacity: 1; transition-duration: 200ms; }

#britt-caught {
    position: absolute; inset: 0; display: grid; place-items: center;
    pointer-events: none; opacity: 0;
    transition: opacity 280ms var(--pt-ease-paper);
}
#britt-caught.show { opacity: 1; transition-duration: 200ms; }
.britt-caught__card {
    background: var(--pt-surface); border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-lg); padding: var(--pt-space-8) var(--pt-space-10); text-align: center;
    min-width: 280px;
    transform: translateY(8px) scale(0.98);
    transition: transform var(--pt-dur-base) var(--pt-ease-paper);
}
#britt-caught.show .britt-caught__card { transform: none; }
.britt-caught__title {
    font-family: var(--pt-font-display); font-weight: 400;
    font-size: var(--pt-text-display); line-height: 1.05; letter-spacing: -0.01em;
    color: var(--pt-rocket-flame);
}
.britt-caught__sub { margin-top: var(--pt-space-2); font-size: var(--pt-text-md); color: var(--pt-fg-muted); }
.britt-caught__sub b { color: var(--pt-fg); font-weight: 600; }

/* Leaderboard — dead simple ranked list, current player highlighted. */
.britt-board {
    list-style: none; margin: var(--pt-space-6) 0 0; padding: var(--pt-space-4) 0 0; text-align: left;
    border-top: 1px solid var(--pt-border);
}
.britt-board li {
    display: grid; grid-template-columns: 24px 1fr auto; align-items: baseline;
    gap: var(--pt-space-3); padding: var(--pt-space-2) var(--pt-space-3); border-radius: var(--pt-radius-sm);
    font-size: var(--pt-text-sm); color: var(--pt-fg);
}
.britt-board li .rank { color: var(--pt-fg-muted); font-variant-numeric: tabular-nums; }
.britt-board li .secs { color: var(--pt-fg-muted); font-variant-numeric: tabular-nums; }
.britt-board li.you {
    background: var(--pt-rocket-flame-20); color: var(--pt-ink-on-flame-20); font-weight: 600;
}
.britt-board li.you .rank, .britt-board li.you .secs { color: var(--pt-ink-on-flame-20); }

/* ===== Reduced motion =====
   Reduced motion means fewer and gentler animations, not zero: everything that
   TRAVELS across the screen is listed here and snaps instead, while the color and
   opacity feedback that explains state (hovers, focus rings, checkbox fills, the
   toast/modal/page fades) is deliberately kept.

   This block lives at the END of the file on purpose. A media query adds no
   specificity, so these rules only beat the component declarations above by coming
   later in source order — moving it back to the top silently disables it. Components
   whose reduced-motion state needs more than "no transition" (keep the fade, drop the
   travel) carry their own block beside their rules: .toast, .modal, .pop-hidden,
   #app-main, .score-range, .comment-row--new, .req-editor-row--new, and the
   buttons' press feedback. */
@media (prefers-reduced-motion: reduce) {
    .sidebar,
    /* Matches the mobile off-canvas override, which is .sidebar.is-open — a bare
       .sidebar here is less specific and would lose to it, letting the drawer
       still slide open under reduced motion. */
    .sidebar.is-open,
    .save-bar,
    .workspace-chev,
    .workspace-children,
    .toast-cell,
    .toggle__track::after,
    .tpl-toggle__track,
    .tpl-toggle__knob,
    .britt-caught__card {
        transition: none;
    }
    /* The global 0.01ms clamp would turn this infinite spin into a strobe. The
       caption still reads "Saving…", which is the part that carries the meaning. */
    .save-status__spin { animation: none; }
    /* Scrim fade explains that the drawer opened/closed — keep it, drop the panel's
       travel (its states only move transform + visibility). */
    .drawer,
    .drawer.is-open {
        transition: none;
    }
    /* Not `transition: none` — this element also carries the nav fade-in, and the
       fade is what explains that the page changed. Drop the collapse travel only. */
    .main-content { transition-property: opacity; }
}
