/* Library-wide styles. Bootstrap does the rest, retuned through its own variables below. */

/* Design tokens. Everything else reads these, so the look changes in one place. */
:root {
    --nbd-ink: #15202B;
    --nbd-ink-soft: #2B3846;
    --nbd-ground: #EDEFF3;
    --nbd-surface: #FFFFFF;
    --nbd-surface-sunk: #F3F5F8;
    --nbd-border: #DCE1E8;
    --nbd-border-hover: var(--nbd-border-hover);
    --nbd-field-border: var(--nbd-field-border);
    --nbd-control-border: #9AA6B2;
    --nbd-line: #E3E7ED;
    --nbd-line-faint: #EEF1F5;
    --nbd-chip: #DDE2E9;
    --nbd-muted: #5A6775;
    --nbd-faint: #A3A9B3;
    --nbd-shadow-rgb: 21, 32, 43;
    /* --nbd-accent is for text, links and rules; a filled accent with white on it is --nbd-accent-fill. */
    --nbd-accent: #2443C4;
    --nbd-accent-rgb: 36, 67, 196;
    --nbd-accent-strong: #152C8C;
    --nbd-accent-fill: #2443C4;
    --nbd-accent-fill-strong: #152C8C;
    --nbd-accent-soft: #E0E8FB;
    --nbd-accent-soft-ink: #1E3A8A;
    --nbd-hit: #E8772E;
    --nbd-hit-ink: #1F1206;
    --nbd-hit-soft: #FCE3CF;
    --nbd-hit-soft-ink: #1F1206;
    --nbd-highlight: #FFF4D6;
    --nbd-success: #1F8A4C;
    --nbd-success-soft: #DCF3E4;
    --nbd-success-soft-ink: #14532D;
    --nbd-warning-soft: #FDF0C8;
    --nbd-warning-soft-ink: #6B4200;
    --nbd-danger: var(--nbd-danger);
    --nbd-danger-soft: #FDE8E8;
    --nbd-caution-soft: #FFF4ED;
    --nbd-caution-border: #F4B183;
    --nbd-caution-ink: #7A2E0B;
    --nbd-heat-1: #D9E1F7;
    --nbd-heat-2: #A9BAEE;
    --nbd-heat-3: #6E87DD;
    --nbd-heat-3-ink: var(--nbd-ink);
    --nbd-header: #15202B;
    --nbd-header-field: #243241;
    --nbd-header-muted: #C3CDD8;
    /* What is pressed or picked (a segmented button, a chosen filter, a tooltip): the opposite of the page. */
    --nbd-inverse: #15202B;
    --nbd-on-inverse: #FFFFFF;
    /* The dark card that carries an estimate's total, dark in both themes. */
    --nbd-feature: #15202B;
    --nbd-feature-line: #33424F;
    --nbd-feature-highlight: #2B3A66;
    /* A document page: white in both themes, as the page images are. */
    --nbd-paper: #FFFFFF;
    --nbd-paper-ink: #15202B;
    --nbd-paper-muted: #5A6775;
    --nbd-paper-rule: #E3E7ED;
    --nbd-paper-rule-strong: #D5DAE2;
    --nbd-paper-stripe: #EEF1F5;
    --nbd-font-body: 'Hanken Grotesk', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --nbd-font-display: 'Bricolage Grotesque', 'Hanken Grotesk', system-ui, sans-serif;

    --bs-body-font-family: var(--nbd-font-body);
    /*
     * Bootstrap fills inputs, cards, tables and dropdowns with --bs-body-bg, so it stays the
     * surface color; the gray ground goes on body alone, below. Mapping it to the ground made
     * every field the same gray as the page around it.
     */
    --bs-body-bg: var(--nbd-surface);
    --bs-body-color: var(--nbd-ink);
    --bs-secondary-color: var(--nbd-muted);
    --bs-border-color: var(--nbd-border);
    --bs-primary: var(--nbd-accent);
    --bs-primary-rgb: var(--nbd-accent-rgb);
    --bs-link-color: var(--nbd-accent);
    --bs-link-color-rgb: var(--nbd-accent-rgb);
    --bs-link-hover-color: var(--nbd-accent-strong);
    --bs-tertiary-bg: var(--nbd-surface-sunk);
}

/*
 * Dark mode: the same tokens, retuned. base.html.twig sets data-bs-theme from the person's choice on the settings
 * page, which also turns on Bootstrap's own dark colors for whatever it draws. A color written out anywhere below
 * is the same in both themes, so a new one goes in as a token here and above.
 */
[data-bs-theme="dark"] {
    --nbd-ink: #E3E8EE;
    --nbd-ink-soft: #C8D1DB;
    --nbd-ground: #0F151B;
    --nbd-surface: #18212A;
    --nbd-surface-sunk: #1F2933;
    --nbd-border: #2D3946;
    --nbd-border-hover: #4A5866;
    --nbd-field-border: #3C4957;
    --nbd-control-border: #6A7887;
    --nbd-line: #2A3540;
    --nbd-line-faint: #222C36;
    --nbd-chip: #28333E;
    --nbd-muted: #9AA7B5;
    --nbd-faint: #6B7785;
    --nbd-shadow-rgb: 0, 0, 0;
    --nbd-accent: #8FA7FF;
    --nbd-accent-rgb: 143, 167, 255;
    --nbd-accent-strong: #B9C8FF;
    --nbd-accent-fill: #3654D1;
    --nbd-accent-fill-strong: #4766E6;
    --nbd-accent-soft: #263257;
    --nbd-accent-soft-ink: #C3CFFF;
    --nbd-hit-soft: #5A3216;
    --nbd-hit-soft-ink: #FCE3CF;
    --nbd-highlight: #3D3418;
    --nbd-success: #4ADE80;
    --nbd-success-soft: #173A27;
    --nbd-success-soft-ink: #A7EBC0;
    --nbd-warning-soft: #3D3115;
    --nbd-warning-soft-ink: #F3D58C;
    --nbd-danger: #F87171;
    --nbd-danger-soft: #45201F;
    --nbd-caution-soft: #3A2318;
    --nbd-caution-border: #8A4A26;
    --nbd-caution-ink: #F8C6A6;
    --nbd-heat-1: #1F2A49;
    --nbd-heat-2: #2A3B72;
    --nbd-heat-3: #3A52A8;
    --nbd-heat-3-ink: #FFFFFF;
    --nbd-header: #0B1015;
    --nbd-header-field: #1B252F;
    --nbd-inverse: #E3E8EE;
    --nbd-on-inverse: #15202B;
    --nbd-feature: #24314A;
    --nbd-feature-line: #3A4B66;
    --nbd-feature-highlight: #3A4F86;

    --bs-secondary-bg: var(--nbd-chip);
}

/* The header is darker than the page in dark mode, so a rule keeps it from running into it. */
[data-bs-theme="dark"] .app-header { border-bottom: 1px solid var(--nbd-border); }

/* Bootstrap's gray outline buttons are too faint on the dark page. */
[data-bs-theme="dark"] .btn-outline-secondary {
    --bs-btn-color: var(--nbd-ink-soft);
    --bs-btn-border-color: var(--nbd-field-border);
    --bs-btn-hover-color: var(--nbd-ink);
    --bs-btn-hover-bg: var(--nbd-chip);
    --bs-btn-hover-border-color: var(--nbd-border-hover);
    --bs-btn-active-color: var(--nbd-ink);
    --bs-btn-active-bg: var(--nbd-chip);
    --bs-btn-active-border-color: var(--nbd-border-hover);
    --bs-btn-disabled-color: var(--nbd-muted);
    --bs-btn-disabled-border-color: var(--nbd-border);
}

/* Document kinds. One --kind-color per DocumentKind::cssClass(), each 4.5:1 against white. */
.kind-rfp { --kind-color: #5B47C2; }
.kind-rfi { --kind-color: #2F6FAE; }
.kind-addendum { --kind-color: #7445A8; }
.kind-attachment { --kind-color: #3E6687; }
.kind-brief { --kind-color: #A13D63; }
.kind-proposal { --kind-color: #187565; }
.kind-presentation { --kind-color: #B4531A; }
.kind-estimator { --kind-color: #15803D; }
.kind-forms { --kind-color: #5E6B3A; }
.kind-other { --kind-color: #7A4E86; }

/* A document's kind as a badge, in the same color as its sheet in a stack. */
.kind-badge {
    background: var(--kind-color);
    color: #FFFFFF;
}

body {
    background: var(--nbd-ground);
}

/* Fields get a firmer edge than the hairlines between table rows. */
.form-control,
.form-select {
    --bs-border-color: var(--nbd-field-border);
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    font-family: var(--nbd-font-display);
    font-weight: 700;
}

/* Bootstrap compiles button colors into each variant, so --bs-primary alone does not reach them. */
.btn-primary {
    --bs-btn-bg: var(--nbd-accent-fill);
    --bs-btn-border-color: var(--nbd-accent-fill);
    --bs-btn-hover-bg: var(--nbd-accent-fill-strong);
    --bs-btn-hover-border-color: var(--nbd-accent-fill-strong);
    --bs-btn-active-bg: var(--nbd-accent-fill-strong);
    --bs-btn-active-border-color: var(--nbd-accent-fill-strong);
    --bs-btn-disabled-bg: var(--nbd-accent-fill);
    --bs-btn-disabled-border-color: var(--nbd-accent-fill);
}

.btn-outline-primary {
    --bs-btn-color: var(--nbd-accent);
    --bs-btn-border-color: var(--nbd-accent);
    --bs-btn-hover-bg: var(--nbd-accent-fill);
    --bs-btn-hover-border-color: var(--nbd-accent-fill);
    --bs-btn-active-bg: var(--nbd-accent-fill-strong);
    --bs-btn-active-border-color: var(--nbd-accent-fill-strong);
    --bs-btn-disabled-color: var(--nbd-accent);
    --bs-btn-disabled-border-color: var(--nbd-accent);
}

/* Table heads: Bootstrap's table-light is light in either theme, so it takes the sunk surface instead. */
.table-light {
    --bs-table-bg: var(--nbd-surface-sunk);
    --bs-table-color: var(--nbd-ink);
    --bs-table-border-color: var(--nbd-border);
}

.card {
    --bs-card-border-color: var(--nbd-border);
    --bs-card-border-radius: 0.75rem;
}

/* The header: brand, search, navigation. */
.app-header {
    background: var(--nbd-header);
}

.app-header .navbar-brand {
    font-family: var(--nbd-font-display);
    font-weight: 700;
}


/* The settings page: a theme is a picture of it to pick, the rest are switches. */
.settings-page { max-width: 48rem; }
.settings-section { padding: 1.25rem 0; border-top: 1px solid var(--nbd-border); }
.settings-section:first-of-type { margin-top: 1.25rem; }
.theme-picker {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: 0.75rem;
    margin: 0;
    padding: 0;
    border: 0;
}
.theme-option {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    height: 100%;
    padding: 0.75rem;
    border: 1px solid var(--nbd-border);
    border-radius: 0.75rem;
    background: var(--nbd-surface);
    cursor: pointer;
}
.theme-option:hover { border-color: var(--nbd-border-hover); }
.btn-check:checked + .theme-option { border-color: var(--nbd-accent); box-shadow: inset 0 0 0 1px var(--nbd-accent); }
.btn-check:focus-visible + .theme-option { outline: 3px solid rgba(var(--nbd-accent-rgb), 0.4); outline-offset: 2px; }
.theme-option-label { font-weight: 600; }
.theme-option-hint { font-size: 0.825rem; color: var(--nbd-muted); }

/* Each theme drawn in its own colors, whichever is in force: a header, and a card with a heading and two lines. */
.theme-preview {
    position: relative;
    display: block;
    height: 5.5rem;
    margin-bottom: 0.5rem;
    overflow: hidden;
    border: 1px solid var(--nbd-border);
    border-radius: 0.5rem;
    background: var(--preview-ground);
}
.theme-preview-bar { display: block; height: 1rem; background: var(--preview-bar); }
.theme-preview-card {
    position: absolute;
    inset: 1.6rem 0.6rem 0.6rem;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    padding: 0.5rem;
    border-radius: 0.35rem;
    background: var(--preview-surface);
}
.theme-preview-card span { display: block; height: 0.35rem; border-radius: 999px; background: var(--preview-line); }
.theme-preview-card span:first-child { width: 45%; background: var(--preview-accent); }
.theme-preview-card span:nth-child(2) { width: 80%; }
.theme-preview-card span:nth-child(3) { width: 62%; }
.theme-preview-light { --preview-ground: #EDEFF3; --preview-bar: #15202B; --preview-surface: #FFFFFF; --preview-line: #DCE1E8; --preview-accent: #2443C4; }
.theme-preview-dark { --preview-ground: #0F151B; --preview-bar: #0B1015; --preview-surface: #18212A; --preview-line: #2D3946; --preview-accent: #8FA7FF; }
/* Automatic: light on the left, dark on the right. */
.theme-preview-system {
    --preview-ground: linear-gradient(105deg, #EDEFF3 50%, #0F151B 50%);
    --preview-bar: #15202B;
    --preview-surface: linear-gradient(105deg, #FFFFFF 50%, #18212A 50%);
    --preview-line: #7D8996;
    --preview-accent: linear-gradient(105deg, #2443C4 50%, #8FA7FF 50%);
}

/* The watcher (eyes_controller.js). Each layer does one job so the effects combine: .eye-look moves (set from
   JavaScript), .eye-iris dilates, .eye-ball widens, .eye-lid blinks, in the header's own color. */
.eyes-wrap { position: relative; margin-right: 0.6rem; }
.eyes { display: block; width: 46px; height: 25px; padding: 0; border: 0; background: none; cursor: pointer; }
.eyes svg { width: 100%; height: 100%; overflow: visible; }
.eye-white { fill: #FDFCFF; }
.eye-rim { fill: none; stroke: var(--nbd-header-muted); stroke-width: 3; }
.eye-pupil { fill: var(--nbd-paper-ink); }
.eye-glint { fill: #FFF; }
.eye-look { transition: transform 120ms ease-out; }
.eye-iris, .eye-ball { transform-box: fill-box; transform-origin: center; transition: transform 200ms ease-out; }
.eye-lid { fill: var(--nbd-header); transform: translateY(-62px); transition: transform 70ms ease-in; }
.is-blinking .eye-lid, .is-sleepy.is-blinking .eye-lid { transform: translateY(0); }
.is-sleepy .eye-lid { transform: translateY(-30px); transition-duration: 900ms; }
.is-interested .eye-iris { transform: scale(1.35); }
.is-interested .eye-ball { transform: scale(1.07); }
.is-surprised .eye-ball { animation: eyes-boing 450ms cubic-bezier(.3, 1.6, .5, 1); }
@keyframes eyes-boing { 30% { transform: scale(1.18, 0.9); } 60% { transform: scale(0.94, 1.08); } }

.eyes-bubble {
    position: absolute;
    top: calc(100% + 12px);
    left: 0;
    z-index: 1050;
    width: max-content;
    max-width: 240px;
    padding: 0.4rem 0.75rem;
    border-radius: 0.6rem;
    background: var(--nbd-surface);
    color: var(--nbd-ink);
    box-shadow: 0 6px 20px rgba(var(--nbd-shadow-rgb), 0.25);
    font-size: 0.85rem;
    font-weight: 600;
}
.eyes-bubble::before {
    content: "";
    position: absolute;
    top: -5px;
    left: 16px;
    width: 10px;
    height: 10px;
    background: inherit;
    transform: rotate(45deg);
}
@keyframes bubble-pop { from { transform: scale(0.6); opacity: 0; } }
@media (prefers-reduced-motion: no-preference) {
    .is-talking .eyes-bubble { animation: bubble-pop 220ms cubic-bezier(.2, 1.4, .4, 1); transform-origin: 20px 0; }
}
@media (prefers-reduced-motion: reduce) {
    .eye-look, .eye-iris, .eye-ball, .eye-lid { transition: none; }
}

.app-header .nav-link {
    --bs-nav-link-color: var(--nbd-header-muted);
    --bs-nav-link-hover-color: #FFFFFF;
    --bs-navbar-active-color: #FFFFFF;
}

/* The bell: what someone was @mentioned in, with a count of the unread. */
.notification-bell { position: relative; display: inline-flex; align-items: center; padding-inline: 0.35rem; }
.app-header .notification-bell.active { color: #FFFFFF; }
.notification-count {
    position: absolute;
    top: 0;
    right: -0.35rem;
    min-width: 1.1rem;
    height: 1.1rem;
    padding: 0 0.25rem;
    border-radius: 999px;
    background: var(--nbd-hit);
    color: var(--nbd-hit-ink);
    font-size: 0.68rem;
    font-weight: 700;
    line-height: 1.1rem;
    text-align: center;
}

/* The person's name, which opens their settings: it sits outside the nav list, so it marks its own page. */
.app-header .settings-link.active { color: #FFFFFF; }

.app-search {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex: 1 0 100%;
    background: var(--nbd-header-field);
    border-radius: 0.5rem;
    padding: 0 0.85rem;
}

.app-search:focus-within {
    box-shadow: 0 0 0 2px var(--nbd-hit);
}

.app-search input {
    flex: 1 1 auto;
    min-width: 0;
    border: 0;
    outline: 0;
    background: transparent;
    color: #FFFFFF;
    padding: 0.6rem 0;
    font: inherit;
}

.app-search input::placeholder {
    color: var(--nbd-header-muted);
}

/* The prompt with its cycling example (search_examples_controller.js), drawn over the input. */
.app-search-field {
    position: relative;
    display: flex;
    flex: 1 1 auto;
    min-width: 0;
}

.app-search-field input {
    width: 100%;
}

.app-search-hint {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    overflow: hidden;
    white-space: nowrap;
    color: var(--nbd-header-muted);
    pointer-events: none;
    transition: opacity 0.15s ease;
}

.app-search-hint.is-hidden {
    opacity: 0;
}

.app-search-example {
    display: inline-block;
    overflow: hidden;
    text-overflow: ellipsis;
    color: #FFFFFF;
    opacity: 0.85;
    transition: transform 0.28s cubic-bezier(0.2, 0.7, 0.2, 1), opacity 0.28s ease;
}

.app-search-example.is-leaving {
    opacity: 0;
    transform: translateY(-60%);
}

.app-search-example.is-entering {
    opacity: 0;
    transform: translateY(60%);
    transition: none;
}

/* On a phone the prompt gives way, so the example is still what shows. */
@media (max-width: 575.98px) {
    .app-search-prompt {
        display: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .app-search-example,
    .app-search-example.is-leaving {
        transform: none;
        transition: opacity 0.01s linear;
    }
}

.app-search svg {
    flex: none;
    color: var(--nbd-header-muted);
}

@media (min-width: 992px) {
    .app-search {
        flex: 1 1 auto;
        max-width: 36rem;
    }
}

.page-text {
    white-space: pre-wrap;
    font-family: var(--bs-font-monospace);
    font-size: 0.85rem;
    line-height: 1.45;
    max-height: 80vh;
    overflow: auto;
}

.page-image {
    max-width: 100%;
    height: auto;
    border: 1px solid var(--bs-border-color);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
    background: var(--nbd-paper);
}

.page-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 1rem;
}

.page-grid a {
    text-decoration: none;
    color: inherit;
}

.page-thumb {
    width: 100%;
    height: auto;
    border: 1px solid var(--bs-border-color);
    background: var(--nbd-paper);
}

.page-thumb-empty {
    aspect-ratio: 8.5 / 11;
}

mark {
    padding: 0 0.1em;
    background: var(--nbd-hit-soft);
    color: inherit;
}

.snippet {
    font-size: 0.9rem;
}

.tag-chip {
    cursor: pointer;
}

/* Claude's distilled Markdown, rendered. */
.distilled {
    max-width: 52rem;
    line-height: 1.55;
}

.distilled h1 {
    font-size: 1.6rem;
    margin-bottom: 1rem;
}

.distilled h2 {
    font-size: 1.2rem;
    margin-top: 2rem;
    padding-bottom: 0.25rem;
    border-bottom: 1px solid var(--bs-border-color);
}

.distilled h3 {
    font-size: 1.05rem;
    margin-top: 1.5rem;
}

.distilled table {
    width: 100%;
    margin: 1rem 0;
    border-collapse: collapse;
    font-size: 0.95rem;
}

.distilled th,
.distilled td {
    padding: 0.4rem 0.6rem;
    border: 1px solid var(--bs-border-color);
    vertical-align: top;
}

.distilled th {
    background: var(--nbd-surface-sunk);
    text-align: left;
}

.distilled blockquote {
    border-left: 3px solid var(--bs-border-color);
    padding-left: 1rem;
    color: var(--bs-secondary-color);
}

/* A page that matched the search the reader arrived from. */
.page-grid a.page-match .page-thumb {
    outline: 3px solid var(--nbd-hit);
    outline-offset: -1px;
}

/* Upload drop zone. Hidden until the Stimulus controller takes over from the file input. */
.dropzone {
    border: 2px dashed var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    background: var(--bs-tertiary-bg);
    cursor: pointer;
    transition: border-color 0.15s ease-in-out, background-color 0.15s ease-in-out;
}

.dropzone:hover,
.dropzone:focus-visible {
    border-color: var(--bs-primary);
}

.dropzone.dropzone-over {
    border-color: var(--bs-primary);
    background: rgba(var(--bs-primary-rgb), 0.08);
}

/* Color swatches: a radio group, each label filled with its own --swatch. */
.swatch-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0;
    padding: 0;
    border: 0;
}

.swatch {
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 0.4rem;
    background: var(--swatch);
    cursor: pointer;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.12);
}

.btn-check:checked + .swatch {
    outline: 3px solid var(--bs-body-color);
    outline-offset: 2px;
}

.btn-check:focus-visible + .swatch {
    outline: 3px solid var(--bs-primary);
    outline-offset: 2px;
}

/* A sector's name with its color in front. */
.sector-label {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

.sector-dot {
    width: 0.65rem;
    height: 0.65rem;
    border-radius: 0.2rem;
    background: var(--swatch);
    flex: none;
}

/* ---- The library ------------------------------------------------------------------------- */

.library-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1rem;
    margin-bottom: 1.25rem;
}

.library-title {
    margin: 0;
    font-size: clamp(1.6rem, 1.2rem + 1.4vw, 2.1rem);
}

.library-count {
    color: var(--nbd-muted);
}

.library-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1.75rem;
}

@media (min-width: 992px) {
    .library-layout {
        grid-template-columns: 15rem minmax(0, 1fr);
    }
}

.library-main {
    min-width: 0;
}

/* List / Calendar / Counts. */
.view-tabs {
    display: inline-flex;
    margin-left: auto;
    padding: 3px;
    border-radius: 0.5rem;
    background: var(--nbd-chip);
}

.view-tabs a {
    padding: 0.4rem 0.9rem;
    border-radius: 0.375rem;
    color: var(--nbd-ink-soft);
    font-size: 0.9rem;
    text-decoration: none;
}

.view-tabs a:hover {
    color: var(--nbd-ink);
}

.view-tabs a[aria-current="page"] {
    background: var(--nbd-surface);
    color: var(--nbd-ink);
    font-weight: 600;
    box-shadow: 0 1px 2px rgba(var(--nbd-shadow-rgb), 0.08);
}

/* The filter rail. */
.filter-rail {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
}

.filter-rail-group {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.filter-rail-heading {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--nbd-muted);
}

.filter-check {
    display: grid;
    grid-template-columns: 1.1rem minmax(0, 1fr) auto;
    gap: 0.6rem;
    align-items: center;
    color: var(--nbd-ink);
    text-decoration: none;
    padding: 0.15rem 0;
}

.filter-check-box {
    width: 1.05rem;
    height: 1.05rem;
    border: 1.5px solid var(--nbd-control-border);
    border-radius: 0.25rem;
    background: var(--nbd-surface);
}

.filter-check[aria-current="true"] .filter-check-box {
    border-color: var(--nbd-accent-fill);
    background: var(--nbd-accent-fill) url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e") center / 100% no-repeat;
}

.filter-check:hover .filter-check-box {
    border-color: var(--nbd-accent);
}

.filter-check-label {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
}

.filter-check-bar {
    height: 6px;
    border-radius: 3px;
    background: var(--nbd-chip);
}

.filter-check-bar span {
    display: block;
    height: 6px;
    border-radius: 3px;
    width: var(--share);
    background: var(--swatch);
}

.filter-check-count {
    font-size: 0.85rem;
    color: var(--nbd-muted);
}

.filter-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.filter-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.75rem;
    border: 1px solid var(--nbd-field-border);
    border-radius: 999px;
    background: var(--nbd-surface);
    color: var(--nbd-ink);
    font-size: 0.85rem;
    text-decoration: none;
}

.filter-chip:hover {
    border-color: var(--nbd-accent);
    color: var(--nbd-ink);
}

.filter-chip[aria-current="true"] {
    border-color: var(--nbd-inverse);
    background: var(--nbd-inverse);
    color: var(--nbd-on-inverse);
}

.filter-chip-plain {
    border-radius: 0.375rem;
    border-color: transparent;
    background: var(--nbd-chip);
}

.filter-chip-dot {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 2px;
    background: var(--kind-color, var(--nbd-muted));
    flex: none;
}

.filter-chip-count {
    color: inherit;
    opacity: 0.75;
}

/* Cover cards. */
.cover-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(17.5rem, 100%), 1fr));
    gap: 1.1rem;
}

.cover-grid-compact {
    grid-template-columns: repeat(auto-fill, minmax(min(13.5rem, 100%), 1fr));
}

.cover-card {
    position: relative;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border: 1px solid var(--nbd-border);
    border-radius: 0.75rem;
    background: var(--nbd-surface);
    color: var(--nbd-ink);
    text-decoration: none;
    transition: box-shadow 0.15s ease, border-color 0.15s ease;
}

.cover-card:hover,
.cover-card:focus-within {
    color: var(--nbd-ink);
    border-color: var(--nbd-border-hover);
    box-shadow: 0 6px 18px rgba(var(--nbd-shadow-rgb), 0.10);
}

.cover-card-art {
    display: block;
    background: var(--nbd-surface-sunk);
    padding: 1.4rem 0 1rem;
}

.cover-card-body {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding: 1rem 1.1rem 1.15rem;
}

.cover-card-kicker {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.8rem;
    color: var(--nbd-muted);
}

/* The name's link reaches over the whole card, so anywhere but a sheet opens the project. */
.cover-card-link { color: inherit; text-decoration: none; }
.cover-card-link::after { content: ''; position: absolute; inset: 0; z-index: 1; }
.cover-card-link:focus-visible { outline: none; }
.cover-card:has(.cover-card-link:focus-visible) { outline: 2px solid var(--nbd-accent); outline-offset: 2px; }

.cover-card-title {
    font-family: var(--nbd-font-display);
    font-weight: 700;
    font-size: 1.2rem;
    line-height: 1.2;
}

.cover-card-client,
.cover-card-meta {
    font-size: 0.85rem;
    color: var(--nbd-muted);
}

.cover-card-note {
    align-self: flex-start;
    font-size: 0.78rem;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: var(--nbd-chip);
    color: var(--nbd-ink-soft);
}

.cover-card-note-warn {
    background: var(--nbd-caution-soft);
    color: var(--nbd-caution-ink);
}

/*
 * A document stack: up to three sheets fanned about the middle. --i is the sheet's place,
 * --n how many there are; the size class sets the sheet and how far apart they sit.
 */
.doc-stack {
    --sheet-w: 108px;
    --sheet-h: 140px;
    --spread: 62px;
    --tilt: 7deg;
    --band: 26px;
    position: relative;
    height: calc(var(--sheet-h) + 24px);
}

.doc-stack-sm {
    --sheet-w: 66px;
    --sheet-h: 86px;
    --spread: 36px;
    --band: 16px;
}

.doc-stack-xs {
    --sheet-w: 26px;
    --sheet-h: 34px;
    --spread: 11px;
    --tilt: 9deg;
    --band: 7px;
    width: 52px;
    height: 44px;
    flex: none;
}

.doc-sheet {
    --offset: calc(var(--i) - (var(--n) - 1) / 2);
    position: absolute;
    top: 50%;
    left: 50%;
    width: var(--sheet-w);
    height: var(--sheet-h);
    margin: calc(var(--sheet-h) / -2) 0 0 calc(var(--sheet-w) / -2);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-radius: 3px;
    background: var(--nbd-paper);
    box-shadow: 0 5px 14px rgba(var(--nbd-shadow-rgb), 0.16), 0 1px 2px rgba(var(--nbd-shadow-rgb), 0.12);
    /* --gather pulls the fan into a pile (1) for the wrap-around shuffle; 0 the rest of the time. */
    transform:
        translateX(calc(var(--offset) * var(--spread) * (1 - var(--gather))))
        translateY(calc(var(--lift, 0px) - var(--gather) * 12px))
        rotate(calc(var(--offset) * var(--tilt) * var(--tilt-k, 1) * (1 - var(--gather))))
        scale(var(--grow, 1));
}

/*
 * The shuffle when a stack's turning wraps round to its newest sheet again (stack_controller.js): the
 * sheets gather into a pile, hop, and fan back out. A registered property, so the keyframes can animate it.
 */
@property --gather {
    syntax: '<number>';
    inherits: true;
    initial-value: 0;
}
.doc-stack.is-wrapping { animation: stack-shuffle 0.7s cubic-bezier(0.3, 0.7, 0.2, 1); }
/* The moment the new order goes in, inside the pile: no transition, or the sheets would slide past each other. */
.doc-stack.is-instant .doc-sheet { transition: none; }
@keyframes stack-shuffle {
    0% { --gather: 0; }
    40% { --gather: 1; }
    55% { --gather: 1; }
    100% { --gather: 0; }
}
@media (prefers-reduced-motion: reduce) {
    .doc-stack.is-wrapping { animation: none; }
}

/*
 * A stack whose sheets open their document or estimate: it sits above the card's own link, but only
 * the sheets catch the pointer, so the space around them still opens the project. A sheet lifts and
 * straightens a little under the pointer or keyboard focus.
 */
.doc-stack.has-links { z-index: 2; pointer-events: none; }
.doc-sheet-link {
    pointer-events: auto;
    color: inherit;
    text-decoration: none;
    transition: transform 0.35s cubic-bezier(0.3, 0.7, 0.2, 1), opacity 0.3s ease, box-shadow 0.18s ease;
}

/* A sheet turned out of sight (stack_controller.js): faded past the right of the fan, and not clickable. */
.doc-sheet.is-off { opacity: 0; pointer-events: none; }

/* The arrows that turn a stack with more sheets than it fans out: faint until the card is hovered. */
.doc-stack-frame { position: relative; }
.stack-turn {
    position: absolute;
    top: 50%;
    z-index: 3;
    width: 30px;
    height: 30px;
    margin-top: -15px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--nbd-border);
    border-radius: 50%;
    background: var(--nbd-surface);
    color: var(--nbd-ink);
    box-shadow: 0 2px 6px rgba(var(--nbd-shadow-rgb), 0.12);
    opacity: 0.55;
    transition: opacity 0.15s ease, background 0.15s ease;
}
/* A bigger target than it looks. */
.stack-turn::before { content: ''; position: absolute; inset: -7px; }
.stack-turn-prev { left: 0.6rem; }
.stack-turn-next { right: 0.6rem; }
.doc-stack-frame:hover .stack-turn,
.stack-turn:focus-visible { opacity: 1; }
.stack-turn:hover { background: var(--nbd-accent-soft); color: var(--nbd-accent-strong); }
.stack-turn:focus-visible { outline: 2px solid var(--nbd-accent); outline-offset: 2px; }
@media (hover: none) { .stack-turn { opacity: 1; } }
.doc-sheet-link:hover,
.doc-sheet-link:focus-visible {
    --lift: -10px;
    --tilt-k: 0.35;
    --grow: 1.06;
    z-index: 5;
    box-shadow: 0 12px 26px rgba(var(--nbd-shadow-rgb), 0.24), 0 2px 4px rgba(var(--nbd-shadow-rgb), 0.14);
}
.doc-sheet-link:focus-visible { outline: 2px solid var(--nbd-accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
    .doc-sheet-link { transition: none; }
    .doc-sheet-link:hover,
    .doc-sheet-link:focus-visible { --lift: 0px; --tilt-k: 1; --grow: 1; }
}

.doc-stack-xs .doc-sheet {
    border-radius: 2px;
    box-shadow: 0 1px 4px rgba(var(--nbd-shadow-rgb), 0.24);
}

.doc-sheet-band {
    flex: none;
    height: var(--band);
    display: flex;
    align-items: center;
    /* The sheet in front covers the left of the ones behind it, so labels sit on the right, where they show. */
    justify-content: flex-end;
    padding: 0 0.5em;
    background: var(--kind-color, #9AA6B2);
    color: #FFFFFF;
    font-size: 0.62rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    white-space: nowrap;
    overflow: hidden;
}

.doc-stack-sm .doc-sheet-band {
    font-size: 0.5rem;
}

/* A drawn page sits under the thumbnail, so a sheet with no render still reads as a page. */
.doc-sheet-page {
    flex: 1 1 auto;
    position: relative;
    background:
        repeating-linear-gradient(to bottom, transparent 0 7px, var(--nbd-paper-rule) 7px 10px) 12% 14% / 76% 60% no-repeat,
        var(--nbd-paper);
}

.doc-stack-xs .doc-sheet-page {
    background:
        repeating-linear-gradient(to bottom, transparent 0 3px, var(--nbd-paper-rule) 3px 5px) 18% 30% / 64% 50% no-repeat,
        var(--nbd-paper);
}

.doc-sheet-page img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: top;
    background: var(--nbd-paper);
}

/* An estimate's sheet: a drawn table (ruled rows, two column rules), under the picture of one and in the calendar's tiny sheets. */
.doc-sheet-estimate .doc-sheet-page {
    background:
        linear-gradient(to right, transparent 58%, var(--nbd-paper-rule-strong) 58% calc(58% + 1px), transparent calc(58% + 1px) 80%, var(--nbd-paper-rule-strong) 80% calc(80% + 1px), transparent calc(80% + 1px)) 8% 46% / 84% 46% no-repeat,
        repeating-linear-gradient(to bottom, var(--nbd-paper-stripe) 0 6px, var(--nbd-paper) 6px 12px) 8% 46% / 84% 46% no-repeat,
        var(--nbd-paper);
}
.doc-stack-xs .doc-sheet-estimate .doc-sheet-page {
    background:
        repeating-linear-gradient(to bottom, var(--nbd-paper-rule) 0 2px, var(--nbd-paper) 2px 5px) 15% 30% / 70% 55% no-repeat,
        var(--nbd-paper);
}
.doc-sheet-caption {
    position: absolute;
    z-index: 1;
    text-align: right;
    top: 0.3rem;
    right: 0.3rem;
    max-width: calc(100% - 0.6rem);
    padding: 0.1rem 0.3rem;
    border-radius: 3px;
    background: rgba(255, 255, 255, 0.94);
    box-shadow: 0 1px 2px rgba(var(--nbd-shadow-rgb), 0.18);
    font-size: 0.62rem;
    font-weight: 700;
    line-height: 1.2;
    color: var(--nbd-paper-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.doc-sheet-caption span { font-weight: 500; color: var(--nbd-paper-muted); }
.doc-stack-sm .doc-sheet-caption { top: 0.2rem; right: 0.2rem; font-size: 0.5rem; }

.doc-sheet-empty {
    opacity: 0.6;
}

/* Search results. */
.result-card {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    margin-bottom: 1rem;
    overflow: hidden;
    border: 1px solid var(--nbd-border);
    border-radius: 0.75rem;
    background: var(--nbd-surface);
}

@media (min-width: 768px) {
    .result-card {
        grid-template-columns: 14rem minmax(0, 1fr);
    }
}

.result-card-side {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 1rem;
    background: var(--nbd-surface-sunk);
}

.result-card-title {
    font-family: var(--nbd-font-display);
    font-weight: 700;
    font-size: 1.1rem;
    line-height: 1.2;
    color: var(--nbd-ink);
    text-decoration: none;
}

.result-card-title:hover {
    color: var(--nbd-accent);
}

.result-card-main {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    padding: 1.1rem 1.25rem;
    min-width: 0;
}

.result-card-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.9rem;
    font-size: 0.85rem;
}

.result-card-doc {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    color: var(--nbd-ink);
    text-decoration: none;
}

.result-card-doc:hover {
    text-decoration: underline;
}

.result-card-snippet {
    margin: 0;
    line-height: 1.55;
}

.result-card-source {
    margin-right: 0.5rem;
    font-size: 0.8rem;
    color: var(--nbd-muted);
}

.hit-badge {
    display: inline-block;
    padding: 0.15rem 0.6rem;
    border-radius: 999px;
    background: var(--nbd-hit);
    color: var(--nbd-hit-ink);
    font-size: 0.78rem;
    font-weight: 600;
    white-space: nowrap;
}

.hit-badge-sm {
    padding: 0 0.4rem;
    font-size: 0.7rem;
}

.hit-strip {
    display: flex;
    gap: 0.75rem;
    margin: 0;
    padding: 0 0 0.25rem;
    list-style: none;
    overflow-x: auto;
}

.hit-strip-page {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    width: 5.5rem;
    color: var(--nbd-ink-soft);
    text-decoration: none;
}

.hit-strip-thumb {
    display: block;
    aspect-ratio: 8.5 / 11;
    overflow: hidden;
    border: 2px solid var(--kind-color, var(--nbd-border));
    border-radius: 3px;
    background:
        repeating-linear-gradient(to bottom, transparent 0 7px, var(--nbd-paper-rule) 7px 10px) 14% 18% / 72% 60% no-repeat,
        var(--nbd-paper);
}

.hit-strip-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: top;
}

.hit-strip-page:hover .hit-strip-thumb {
    box-shadow: 0 4px 10px rgba(var(--nbd-shadow-rgb), 0.16);
}

.hit-strip-label {
    font-size: 0.75rem;
    line-height: 1.25;
}

.hit-strip-more {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 5.5rem;
    aspect-ratio: 8.5 / 11;
    border: 1px dashed var(--nbd-field-border);
    border-radius: 3px;
    font-size: 0.8rem;
    color: var(--nbd-muted);
    text-align: center;
    padding: 0.5rem;
}

/*
 * The calendar and the counts: sectors down, years across. --years (set on the table) gives each
 * year column a floor, so a long history scrolls sideways instead of squeezing every tile until
 * its project name is two letters long.
 */
.grid-matrix-scroll {
    overflow-x: auto;
    border-radius: 0.75rem;
    background: var(--nbd-surface);
    padding: 0.5rem 1.25rem 1rem;
}

.grid-matrix {
    --year-min: 12.5rem;
    --label-width: 10rem;
    width: 100%;
    min-width: calc(var(--label-width) + var(--years, 4) * var(--year-min));
    border-collapse: separate;
    border-spacing: 0.75rem 0;
    table-layout: fixed;
}

.grid-matrix-counts {
    --year-min: 7rem;
}

.grid-matrix thead th {
    padding: 0.9rem 0.25rem;
    border-bottom: 1px solid var(--nbd-line);
    font-family: var(--nbd-font-display);
    font-weight: 700;
    font-size: 1.1rem;
    color: var(--nbd-ink-soft);
}

.grid-matrix thead th:first-child {
    width: var(--label-width);
}

.grid-matrix tbody th,
.grid-matrix tbody td {
    padding: 0.9rem 0;
    border-bottom: 1px solid var(--nbd-line-faint);
    vertical-align: top;
}

.grid-matrix tbody th {
    font-size: 0.95rem;
    font-weight: 600;
}

.grid-matrix-total {
    display: block;
    padding: 0.2rem 0 0 1.15rem;
    font-size: 0.8rem;
    font-weight: 400;
    color: var(--nbd-muted);
}

.grid-matrix tbody td.is-filled {
    border-radius: 0.75rem;
    background: var(--nbd-surface-sunk);
    padding: 0.6rem;
}

.grid-cell-count {
    display: block;
    padding: 0.1rem 0.25rem 0.5rem;
    font-size: 0.8rem;
    color: var(--nbd-muted);
}

.grid-cell-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

/*
 * The calendar as a canvas (pan_canvas_controller.js): it runs to the window's right and bottom
 * edges and a mouse drag pans it. The year row and the sector column stay put while it moves,
 * so the reader always knows which cell they are looking at.
 */
.grid-canvas {
    overflow: auto;
    overscroll-behavior: contain;
    padding-top: 0;
    cursor: grab;
}

.grid-canvas.is-panning {
    cursor: grabbing;
    user-select: none;
}

.grid-canvas.is-panning a {
    cursor: grabbing;
}

.grid-canvas thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--nbd-surface);
}

.grid-canvas tbody th {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--nbd-surface);
    /* Covers the gap border-spacing leaves to its right, so cells pass under it cleanly. */
    box-shadow: 0.75rem 0 0 var(--nbd-surface);
}

.grid-canvas thead th.grid-matrix-corner {
    left: 0;
    z-index: 3;
    box-shadow: 0.75rem 0 0 var(--nbd-surface);
}

/* Newest first / oldest first, in the grid's empty corner. */
.grid-matrix-corner {
    vertical-align: middle;
}

.sort-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.7rem;
    border: 1px solid var(--nbd-field-border);
    border-radius: 999px;
    background: var(--nbd-surface);
    color: var(--nbd-ink);
    font-family: var(--nbd-font-body);
    font-size: 0.85rem;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

.sort-toggle:hover {
    border-color: var(--nbd-accent);
    color: var(--nbd-accent);
}

/* A project in a calendar cell: its stack above, its name below, allowed two lines. */
.grid-tile {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.65rem 0.75rem 0.7rem;
    border: 1px solid var(--nbd-border);
    border-radius: 0.5rem;
    background: var(--nbd-surface);
    color: var(--nbd-ink);
    text-decoration: none;
}

.grid-tile:hover {
    border-color: var(--nbd-border-hover);
    color: var(--nbd-ink);
}

.grid-tile .doc-stack-xs {
    align-self: flex-start;
}

.grid-tile-text {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    min-width: 0;
}

.grid-tile-name {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    font-weight: 600;
    font-size: 0.875rem;
    line-height: 1.3;
}

.grid-tile-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0.4rem;
    font-size: 0.75rem;
    line-height: 1.35;
    color: var(--nbd-muted);
}

.grid-cell-more {
    display: inline-block;
    padding: 0.5rem 0.25rem 0;
    font-size: 0.85rem;
    font-weight: 600;
    text-decoration: none;
}

.grid-matrix-counts tbody td,
.grid-matrix-counts tbody th {
    vertical-align: middle;
}

.grid-matrix-counts thead th {
    text-align: center;
}

.grid-matrix-counts thead th:first-child {
    text-align: left;
}

.grid-matrix-sum {
    width: 4.5rem;
    text-align: right;
    font-family: var(--nbd-font-display);
    font-weight: 700;
    font-size: 1.1rem;
    color: var(--nbd-ink-soft);
}

.grid-matrix thead th.grid-matrix-sum {
    font-family: var(--nbd-font-body);
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--nbd-muted);
    text-align: right;
}

/* Shades for the counts. 0 is empty; 4 is the busiest cell on show. */
.heat-cell {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    min-height: 4.25rem;
    border-radius: 0.6rem;
    color: var(--nbd-ink);
    text-decoration: none;
}

a.heat-cell:hover {
    outline: 2px solid var(--nbd-ink);
    outline-offset: 2px;
    color: inherit;
}

a.heat-cell[aria-current="true"] {
    outline: 3px solid var(--nbd-hit);
    outline-offset: 3px;
}

.heat-0 { background: var(--nbd-surface-sunk); color: var(--nbd-muted); }
.heat-1 { background: var(--nbd-heat-1); }
.heat-2 { background: var(--nbd-heat-2); }
.heat-3 { background: var(--nbd-heat-3); color: var(--nbd-heat-3-ink); }
.heat-4 { background: var(--nbd-accent-fill); color: #FFFFFF; }

a.heat-4:hover { color: #FFFFFF; }

.heat-cell-number {
    font-family: var(--nbd-font-display);
    font-weight: 700;
    font-size: 1.7rem;
    line-height: 1;
}

.heat-cell-unit {
    font-size: 0.75rem;
}

.heat-legend {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.75rem;
    font-size: 0.75rem;
    color: var(--nbd-muted);
}

.heat-legend .heat-cell {
    min-height: 0;
    width: 1.75rem;
    height: 0.75rem;
    border-radius: 3px;
}

/* Claude usage: the two summary cards over the call log. */
.usage-summary {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr));
    gap: 1rem;
    margin-bottom: 0.75rem;
}

.usage-card {
    padding: 1.1rem 1.25rem;
    border: 1px solid var(--nbd-border);
    border-radius: 0.75rem;
    background: var(--nbd-surface);
}

.usage-card-title {
    margin: 0 0 0.75rem;
    font-size: 1rem;
    color: var(--nbd-muted);
}

.usage-figures {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
    gap: 0.75rem 1rem;
    margin: 0;
}

.usage-figures dt {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--nbd-muted);
}

.usage-figures dd {
    margin: 0;
    font-family: var(--nbd-font-display);
    font-weight: 700;
    font-size: 1.5rem;
}

/* A row of labeled facts, such as a project's dates and outcome: label above, value below. */
.fact-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    gap: 0.75rem 1rem;
}

.fact-grid dt {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--nbd-muted);
}

.fact-grid dd {
    margin: 0;
    font-weight: 600;
}

.usage-failed {
    font-family: var(--nbd-font-body);
    font-size: 0.8rem;
    font-weight: 400;
    color: var(--nbd-danger);
}

.usage-table td,
.usage-table th {
    white-space: nowrap;
}

/*
 * The estimate editor (assets/controllers/estimate_editor_controller.js). Two designs, Workbench
 * and Ledger, built from the same parts; figures are monospaced-width digits so columns line up.
 */
.estimate-editor {
    --editor-gap: 1rem;
    display: flex;
    flex-direction: column;
    gap: var(--editor-gap);
    font-variant-numeric: tabular-nums;
}

.editor-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}

.draft-banner {
    background: var(--nbd-accent-fill);
    color: #FFFFFF;
    border-radius: 0.6rem;
    padding: 0.5rem 0.6rem 0.5rem 1rem;
    font-size: 0.925rem;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 1rem;
    flex: 1 1 32rem;
}

.draft-banner-actions {
    display: inline-flex;
    gap: 0.4rem;
}

.stale-banner {
    flex-basis: 100%;
    background: var(--nbd-caution-soft);
    border: 1px solid var(--nbd-caution-border);
    color: var(--nbd-caution-ink);
    border-radius: 0.6rem;
    padding: 0.5rem 1rem;
    font-size: 0.9rem;
}

.stale-banner a { color: inherit; font-weight: 600; }

/* An estimate's title row: breadcrumb above, the title and its badges on the left, buttons on the right. */
.estimate-heading {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.estimate-heading-title {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.estimate-heading-title .badge { font-size: 0.75rem; }

.estimate-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

/* Quiet badges: a tinted ground and dark text in the same hue. */
.badge-soft-success { background: var(--nbd-success-soft); color: var(--nbd-success-soft-ink); }
.badge-soft-accent { background: var(--nbd-accent-soft); color: var(--nbd-accent-soft-ink); text-decoration: none; }
.badge-soft-warning { background: var(--nbd-warning-soft); color: var(--nbd-warning-soft-ink); }
/* What would be a dark badge, as the opposite of the page in either theme. */
.badge-inverse { background: var(--nbd-inverse); color: var(--nbd-on-inverse); }
.badge-soft-neutral { background: var(--nbd-surface-sunk); color: var(--nbd-muted); font-weight: 600; }

/*
 * The published version page (version_drawer_controller.js): the estimate at full width and a
 * drawer of comments, changes, history and drafts laid over its right side. Without JavaScript
 * the drawer is plain sections under the estimate.
 */
.version-body {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

/* A part of the page the activity poll redraws: no box of its own, so its contents lay out as if it were not there. */
.activity-slot { display: contents; }

/* What others are doing while a version is open: a newer version, someone editing now. */
.live-notice {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.75rem;
    border-radius: 0.75rem;
    padding: 0.6rem 1rem;
    font-size: 0.9rem;
    background: var(--nbd-success-soft);
    color: var(--nbd-success-soft-ink);
}
.live-notice-version { background: var(--nbd-warning-soft); color: var(--nbd-warning-soft-ink); }
.live-notice a { font-weight: 600; color: inherit; }
.live-now { display: inline-flex; align-items: center; gap: 0.3rem; font-weight: 600; color: var(--nbd-success); }
.live-dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: #16A34A; flex: none; animation: live-pulse 2s ease-in-out infinite; }
@keyframes live-pulse { 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) {
    .live-dot { animation: none; }
}

.version-strip {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 1rem;
    background: var(--nbd-surface);
    border: 1px solid var(--nbd-border);
    border-radius: 0.75rem;
    padding: 0.75rem 1rem;
    font-size: 0.9rem;
}

.version-strip-note { flex-basis: 100%; }

.drawer-toggle { display: inline-flex; align-items: center; gap: 0.4rem; }

/* Open: filled, like a pressed button, so it reads as the thing holding the drawer open. */
.drawer-toggle[aria-expanded="true"] {
    background: var(--bs-btn-hover-bg);
    border-color: var(--bs-btn-hover-border-color);
    color: var(--bs-btn-hover-color);
}

.version-drawer {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.drawer-sticky {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.drawer-panel {
    background: var(--nbd-surface);
    border: 1px solid var(--nbd-border);
    border-radius: 0.75rem;
    padding: 1rem 1.15rem;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.drawer-panel-title { font-size: 1rem; font-weight: 700; margin: 0; }
.drawer-title { font-size: 1.1rem; font-weight: 700; margin: 0; }
.drawer-hint { font-size: 0.825rem; color: var(--nbd-muted); margin: 0; }

.drawer-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 0.5rem;
}

.drawer-close {
    flex: none;
    width: 2.5rem;
    height: 2.5rem;
    border: 0;
    border-radius: 0.4rem;
    background: transparent;
    color: var(--nbd-muted);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.drawer-close:hover { background: rgba(var(--nbd-accent-rgb), 0.08); color: var(--nbd-accent); }

.drawer-tabs {
    display: flex;
    gap: 1.1rem;
    padding: 0 1.25rem;
}

.drawer-tabs [role="tab"] {
    border: 0;
    border-bottom: 2px solid transparent;
    background: transparent;
    padding: 0.55rem 0;
    min-height: 2.75rem;
    font: inherit;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--nbd-muted);
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

.drawer-tabs [role="tab"]:hover { color: var(--nbd-ink); }
.drawer-tabs [role="tab"][aria-selected="true"] { color: var(--nbd-accent); border-bottom-color: var(--nbd-accent); }

.drawer-bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.825rem;
    color: var(--nbd-muted);
}

.drawer-compare {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--nbd-muted);
}

.drawer-compare-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.5rem;
    font-size: 0.9rem;
}

/* With JavaScript: an overlay as tall as the page, its head and the short tabs kept in view. */
.has-drawer .version-drawer {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(25rem, 100%);
    gap: 0;
    background: var(--nbd-surface-sunk);
    border: 1px solid var(--nbd-border);
    border-radius: 0.75rem 0 0 0.75rem;
    box-shadow: -1.5rem 0 3rem -1.5rem rgba(var(--nbd-shadow-rgb), 0.35);
    z-index: 20;
}

/*
 * The drawer moves to the left when what its active comment is about sits under its usual place.
 * It slides across rather than jumping: a transform animates where left and right cannot, so the
 * controller sets --drawer-shift to the distance between the two sides.
 */
.has-drawer .version-drawer {
    transition: transform 0.35s cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 0.35s, border-radius 0.35s;
}

.has-drawer .version-drawer.is-left {
    transform: translateX(calc(-1 * var(--drawer-shift, 0px)));
    border-radius: 0 0.75rem 0.75rem 0;
    box-shadow: 1.5rem 0 3rem -1.5rem rgba(var(--nbd-shadow-rgb), 0.35);
}

@media (prefers-reduced-motion: reduce) {
    .has-drawer .version-drawer { transition: none; }
}

.has-drawer .version-drawer.is-left .drawer-sticky { border-radius: 0 0.75rem 0 0; }

.has-drawer .drawer-sticky {
    position: sticky;
    top: 0;
    z-index: 2;
    gap: 0;
    max-height: 100vh;
    overflow-y: auto;
    background: var(--nbd-surface);
    border-bottom: 1px solid var(--nbd-border);
    border-radius: 0.75rem 0 0 0;
}

.has-drawer .drawer-head { padding: 0.9rem 0.75rem 0 1.25rem; }
.has-drawer .drawer-panel-title { display: none; }

.has-drawer .drawer-panel {
    background: transparent;
    border: 0;
    border-radius: 0;
    padding: 1rem 1.25rem 1.25rem;
}

.has-drawer .drawer-panel[data-tab="comments"] {
    padding: 0.5rem 1.25rem;
    background: var(--nbd-surface-sunk);
    border-top: 1px solid var(--nbd-border);
}

.comment-lane {
    position: relative;
    flex: 1;
    min-height: 12rem;
}

/* A thread's card. Placed level with its row by layout(); in a stacked lane it just follows the last. */
.comment-card {
    position: absolute;
    left: 0.75rem;
    right: 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: 0.75rem;
    background: var(--nbd-surface);
    border: 1px solid var(--nbd-border);
    border-radius: 0.6rem;
    box-shadow: 0 2px 6px rgba(var(--nbd-shadow-rgb), 0.06);
    cursor: pointer;
    transition: top 0.2s ease-out, box-shadow 0.15s, border-color 0.15s;
}

.comment-card.is-active {
    border-color: var(--nbd-accent);
    box-shadow: 0 0 0 3px rgba(var(--nbd-accent-rgb), 0.14), 0 10px 24px -10px rgba(var(--nbd-shadow-rgb), 0.35);
    cursor: default;
    z-index: 1;
}

.comment-card.is-resolved { background: var(--nbd-surface-sunk); padding-block: 0.5rem; }

.comment-lane.is-stacked { display: flex; flex-direction: column; gap: 0.6rem; padding: 0.75rem; min-height: 0; }
.comment-lane.is-stacked .comment-card { position: static; }

@media (prefers-reduced-motion: reduce) {
    .comment-card { transition: none; }
}

.comment-card-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.comment-card-label {
    border: 0;
    background: transparent;
    padding: 0;
    min-width: 0;
    font-size: 0.775rem;
    font-weight: 600;
    color: var(--nbd-muted);
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.comment-card-label:hover { color: var(--nbd-accent); text-decoration: underline; }

.comment {
    display: grid;
    grid-template-columns: 1.75rem minmax(0, 1fr);
    gap: 0.5rem;
}

.comment-avatar {
    /* The letters are trimmed to their capitals and padded out to the circle, so they sit in its exact middle.
       Centering the text with flexbox centers the font's line box instead, which leaves them a pixel or two high. */
    --avatar-size: 1.75rem;
    display: inline-block;
    width: var(--avatar-size);
    padding-block: calc((var(--avatar-size) - 1cap) / 2);
    border-radius: 50%;
    color: #FFFFFF;
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0;
    text-align: center;
    white-space: nowrap;
    text-box: trim-both cap alphabetic;
    /* Its own size, not stretched to the comment's height. */
    align-self: start;
}

.comment-main { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.comment-meta { margin: 0; font-size: 0.8rem; color: var(--nbd-muted); }
.comment-meta strong { color: var(--nbd-ink); }
.comment-body { margin: 0; font-size: 0.875rem; line-height: 1.45; white-space: pre-line; overflow-wrap: anywhere; }

.comment-actions { display: flex; gap: 0.5rem; margin: -0.25rem 0 -0.35rem; }
.comment-composer { display: flex; flex-direction: column; gap: 0.35rem; }
.comment-composer .comment-actions { margin: 0; }
.comment-composer-label { font-size: 0.775rem; font-weight: 600; color: var(--nbd-muted); }
.comment-input { font-size: 0.875rem; resize: vertical; }
.comment-error { margin: 0; font-size: 0.825rem; color: var(--nbd-danger); }
.comment-empty { margin: 0.75rem 1.25rem; font-size: 0.875rem; color: var(--nbd-muted); }

.comment-link {
    border: 0;
    background: transparent;
    padding: 0.3rem 0.15rem;
    min-height: 2rem;
    font: inherit;
    font-size: 0.825rem;
    font-weight: 600;
    color: var(--nbd-accent);
}

.comment-link:hover { color: var(--nbd-accent-strong); text-decoration: underline; }
.comment-meta .comment-delete { min-height: 0; padding: 0 0 0 0.4rem; font-size: 0.775rem; color: var(--nbd-muted); }

/* The speech bubble beside a line, a phase or the total: faint until the row is hovered or it has a thread. */
.comment-button {
    flex: none;
    width: 2.1rem;
    height: 1.9rem;
    border: 0;
    border-radius: 0.4rem;
    background: transparent;
    color: var(--nbd-faint);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.15rem;
    font-size: 0.75rem;
    font-weight: 700;
    opacity: 0;
    transition: opacity 0.12s;
}

[data-anchor]:hover .comment-button:not(.comment-button-cell),
.comment-button:focus-visible,
.comment-button.has-thread,
.is-commented-on .comment-button { opacity: 1; }

.comment-button:hover { background: rgba(var(--nbd-accent-rgb), 0.1); color: var(--nbd-accent); }
.comment-button.has-thread { background: rgba(var(--nbd-accent-rgb), 0.1); color: var(--nbd-accent); }
.comment-button-dark { color: #AEBBC7; }
.comment-button-dark:hover,
.comment-button-dark.has-thread { background: rgba(255, 255, 255, 0.16); color: #FFFFFF; }

@media (hover: none) {
    .comment-button { opacity: 1; }
}

/* The row a card in the drawer is about. */
.is-commented-on { background: var(--nbd-highlight) !important; transition: background 0.15s; }
.tile-dark.is-commented-on,
.total-card.is-commented-on { background: var(--nbd-feature-highlight) !important; }

/*
 * A comment button that floats beside a number instead of taking room in the layout: before it,
 * after it, or in the corner of its tile. Shown on hover or once there is a thread, like the rest.
 */
.float-host { position: relative; display: inline-block; }

/* A number in the table: a small badge on its corner, so the columns never move. */
.float-cell { position: relative; display: inline-block; min-width: 0; }
.ledger-row > .float-cell,
.line-row > .float-cell { display: block; }
.float-cell > [data-fig] { display: block; }

.comment-button.comment-button-cell {
    position: absolute;
    top: 0;
    right: 0;
    transform: translate(70%, -60%);
    z-index: 2;
    width: auto;
    min-width: 1.15rem;
    height: 1.15rem;
    padding: 0 0.2rem;
    gap: 0.1rem;
    border: 1px solid var(--nbd-border);
    border-radius: 999px;
    background: var(--nbd-surface);
    color: var(--nbd-muted);
    font-size: 0.625rem;
    line-height: 1;
}

.comment-button-cell .icon svg { width: 0.65rem; height: 0.65rem; }

/* The total card's big figures: the badge is centered beside the figure, in the room it already has. */
.total-card .comment-button.comment-button-cell { top: 50%; transform: translateY(-50%); }
.total-card .comment-button.comment-button-cell.float-badge-after { left: 100%; right: auto; margin-left: 0.4rem; }
.total-card .comment-button.comment-button-cell.float-badge-before { right: 100%; margin-right: 0.4rem; }
.comment-button-cell:not(.has-thread) .comment-count { display: none; }

[data-anchor]:hover .comment-button-row,
.float-cell:hover > .comment-button-cell,
.is-commented-on > .comment-button-cell { opacity: 1; }

.comment-button.comment-button-cell.has-thread,
.comment-button.comment-button-cell:hover {
    background: var(--nbd-accent-soft);
    border-color: var(--nbd-accent-soft);
    color: var(--nbd-accent);
}

.float-cell.is-commented-on { border-radius: 0.3rem; box-shadow: 0 0 0 2px #F5C04A; }
.comment-button-float { position: absolute; z-index: 1; width: 1.8rem; height: 1.5rem; }
.comment-button-float.float-before { right: 100%; top: 50%; transform: translateY(-50%); margin-right: 0.2rem; }
.comment-button-float.float-after { left: 100%; top: 50%; transform: translateY(-50%); margin-left: 0.2rem; }
.comment-button-float.float-corner { top: 0.3rem; right: 0.3rem; }
.float-host:hover > .comment-button { opacity: 1; }
.tile { position: relative; }
.total-card label .float-host { display: block; }
.total-card label .float-host .comment-button-float.float-after { left: auto; right: 0; }
/* A tinted figure in the dark card: the tint reaches a little past the text on every side without moving it. */
.total-card [data-anchor] { border-radius: 0.4rem; transition: background 0.15s, box-shadow 0.15s; }
.total-card .is-commented-on { background: var(--nbd-feature-highlight) !important; box-shadow: 0 0 0 0.35rem var(--nbd-feature-highlight); }
.media-card { position: relative; }
.comment-button-corner { position: absolute; top: 0.5rem; right: 0.5rem; }

/* Room for the corner badge on the last column: the scroller reaches into the card's padding, so nothing moves. */
.is-readonly .phase-card .scroll-x { padding: 0.4rem 1.05rem 0 0; margin: -0.4rem -1.05rem 0 0; }

.ledger-grid.has-gutter .ledger-row { padding-left: 0.25rem; }
.ledger-grid.has-gutter .ledger-phase-head { padding-left: 0.25rem; }
.ledger-grid.has-gutter .ledger-span-2 { grid-column: span 1; }

@media (max-width: 991.98px) {
    .has-drawer .version-drawer {
        position: fixed;
        inset: 0;
        width: 100%;
        border-radius: 0;
        overflow-y: auto;
        z-index: 1040;
    }

    .has-drawer .drawer-sticky { max-height: none; overflow: visible; border-radius: 0; }
}

/* A list of changes between two versions; additions, removals and edits marked at the left. */
.change-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    font-size: 0.9rem;
}

.change-list li {
    border-left: 3px solid var(--nbd-border);
    padding-left: 0.6rem;
}

.change-list .change-added { border-left-color: var(--nbd-success); }
.change-list .change-removed { border-left-color: var(--nbd-danger); }
.change-list .change-changed { border-left-color: var(--nbd-accent); }
.change-amount { font-weight: 600; white-space: nowrap; }

.publish-columns {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
    gap: 1rem;
}

.publish-theirs { background: var(--nbd-caution-soft); border-color: var(--nbd-caution-border); }

.history-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.history-list li {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.4rem;
    border-radius: 0.5rem;
}

.history-list li.is-current { background: rgba(var(--nbd-accent-rgb), 0.07); }

.history-list li > a:first-child {
    display: flex;
    gap: 0.6rem;
    text-decoration: none;
    color: inherit;
}

.history-badge {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.2rem;
    height: 2.2rem;
    border-radius: 50%;
    background: var(--nbd-muted);
    color: #FFFFFF;
    font-family: var(--nbd-font-display);
    font-weight: 700;
    font-size: 0.85rem;
}

.is-current .history-badge { background: var(--nbd-accent-fill); }
.history-body { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; flex: 1; font-size: 0.875rem; }
.history-top { display: flex; justify-content: space-between; gap: 0.5rem; }
.history-note { color: var(--nbd-muted); }
.history-meta { display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center; font-size: 0.8rem; color: var(--nbd-muted); }
.history-list li > a.small { padding-left: 2.8rem; }

.draft-row {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.875rem;
    border-top: 1px solid var(--nbd-border);
    padding-top: 0.4rem;
}

.editor-tools {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.save-status {
    font-size: 0.875rem;
    color: var(--nbd-muted);
    min-width: 9rem;
    text-align: right;
}

.save-status::before {
    content: '';
    display: inline-block;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    margin-right: 0.4rem;
    background: var(--nbd-success);
}

.save-status[data-state="pending"]::before,
.save-status[data-state="saving"]::before { background: #B7791F; }

.save-status[data-state="retrying"]::before,
.save-status[data-state="conflict"]::before,
.save-status[data-state="refused"]::before { background: var(--nbd-danger); }

.save-status[data-state="conflict"],
.save-status[data-state="refused"] { color: var(--nbd-danger); font-weight: 600; }

/* A row of toggle buttons where one is pressed, such as Workbench | Ledger or $ | %. */
.segmented {
    display: inline-flex;
    border: 1px solid var(--nbd-field-border);
    border-radius: 0.5rem;
    overflow: hidden;
    background: var(--nbd-surface);
}

.segmented button {
    border: 0;
    background: transparent;
    padding: 0.3rem 0.8rem;
    font: inherit;
    font-size: 0.875rem;
    color: var(--nbd-muted);
    min-height: 2rem;
}

.segmented button[aria-pressed="true"] {
    background: var(--nbd-inverse);
    color: var(--nbd-on-inverse);
}

.editor-columns {
    display: flex;
    flex-wrap: wrap;
    gap: var(--editor-gap);
    align-items: flex-start;
}

.editor-main {
    flex: 999 1 640px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--editor-gap);
}

.editor-rail {
    flex: 1 1 320px;
    min-width: 280px;
    display: flex;
    flex-direction: column;
    gap: var(--editor-gap);
}

.editor-stack {
    display: flex;
    flex-direction: column;
    gap: var(--editor-gap);
}

.editor-panel {
    background: var(--nbd-surface);
    border: 1px solid var(--nbd-border);
    border-radius: 0.75rem;
    padding: 1rem 1.15rem;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

/* Converting an old Excel estimator: one panel per sheet. */
.import-sheet-head {
    display: flex;
    flex-wrap: wrap;
    align-items: end;
    justify-content: space-between;
    gap: 0.5rem 1.5rem;
}

.import-sheet-name { width: min(100%, 20rem); }

.import-totals {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 2.5rem;
    margin: 0;
}

.import-totals dt {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--nbd-muted);
}

.import-totals dd { margin: 0; }

.import-totals dd[data-role="our-total"] {
    font-size: 1.25rem;
    font-weight: 600;
}

.import-match { color: var(--nbd-success); font-weight: 600; }

.import-phases { font-size: 0.875rem; }

.import-notes {
    padding: 0.5rem 0.75rem 0.5rem 1.75rem;
    background: var(--nbd-hit-soft);
    color: var(--nbd-hit-soft-ink);
    border-radius: 0.5rem;
}

.panel-heading {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem 0.9rem;
}

.panel-title {
    font-size: 1rem;
    margin: 0;
}

.panel-hint {
    font-size: 0.825rem;
    color: var(--nbd-muted);
    margin: 0;
}

.panel-figure {
    margin-left: auto;
    font-family: var(--nbd-font-display);
    font-weight: 700;
    font-size: 1.15rem;
}

.scroll-x {
    overflow-x: auto;
}

.num { text-align: right; }
.muted { color: var(--nbd-muted); }

/* An input that looks like text until it is hovered or focused, for dense tables. */
.cell-input {
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
    border: 1px solid transparent;
    background: transparent;
    border-radius: 0.3rem;
    padding: 0.35rem 0.4rem;
    font: inherit;
    font-size: 0.9rem;
    color: inherit;
    min-height: 2.1rem;
}

.cell-input:hover { border-color: var(--nbd-border); }

.cell-input:focus {
    outline: none;
    border-color: var(--nbd-accent);
    background: var(--nbd-surface);
    box-shadow: 0 0 0 3px rgba(var(--nbd-accent-rgb), 0.15);
}

.cell-input.boxed { border-color: var(--nbd-field-border); background: var(--nbd-surface); }

/* A task: "…" and a tooltip when folded; while focused it widens over the hour boxes beside it. */
.cell-expand { display: block; position: relative; min-width: 0; }
.cell-expand.grow { flex: 1; min-width: 12rem; }
.cell-input.expandable {
    display: block;
    resize: none;
    overflow: hidden;
    white-space: pre;
    line-height: 1.35;
    height: 2.1rem;
}

/* Textareas ignore text-overflow, so the "…" is drawn over the end of a folded one that is cut off. */
.cell-expand.is-clipped::after {
    content: '…';
    position: absolute;
    top: 1px;
    right: 1px;
    bottom: 1px;
    display: flex;
    align-items: center;
    padding: 0 0.4rem 0 1rem;
    border-radius: 0 0.3rem 0.3rem 0;
    background: linear-gradient(to right, transparent, var(--nbd-surface) 45%);
    pointer-events: none;
}

.cell-expand:focus-within::after { display: none; }
.cell-input.expandable.is-expanded {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 5;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    border-color: var(--nbd-accent);
    background: var(--nbd-surface);
    box-shadow: 0 0 0 3px rgba(var(--nbd-accent-rgb), 0.15), 0 12px 28px -8px rgba(var(--nbd-shadow-rgb), 0.28);
    transition: width 0.16s ease-out;
}

/* A note grows leftward, over the hours, from its right edge. */
.cell-input.expandable.is-expanded[data-expand="left"] { left: auto; right: 0; }

@media (prefers-reduced-motion: reduce) {
    .cell-input.expandable.is-expanded { transition: none; }
}

.cell-tip {
    position: absolute;
    z-index: 1080;
    padding: 0.4rem 0.6rem;
    border-radius: 0.4rem;
    background: var(--nbd-inverse);
    color: var(--nbd-on-inverse);
    font-size: 0.825rem;
    line-height: 1.35;
    box-shadow: 0 8px 20px -6px rgba(var(--nbd-shadow-rgb), 0.35);
    pointer-events: none;
}
/* A published version: the same layout with its figures as plain text, not boxes to type in. */
.is-readonly .cell-input,
.is-readonly .cell-input.boxed,
.is-readonly .cell-input.hours:placeholder-shown,
.is-readonly .team-chip .cell-input.team-chip-rate {
    border-color: transparent;
    background: transparent;
    box-shadow: none;
    cursor: default;
}

/* A published version's phase name, sized to its text (see makeReadonly) so its comment badge sits beside it. */
.is-readonly .phase-card-head > .float-cell { flex: 0 1 auto; min-width: 0; max-width: 36rem; }
.is-readonly .cell-input.phase-name { width: auto; max-width: 100%; field-sizing: content; }
.is-readonly .cell-input.expandable.phase-name { white-space: pre-wrap; }
.is-readonly .phase-card-head > .phase-figures { margin-left: auto; }
/* The Ledger's phase row is the sunk gray, so the "…" fades into that rather than white. */
.ledger-phase-head .cell-expand.is-clipped::after { background: linear-gradient(to right, transparent, var(--nbd-surface-sunk) 45%); }

/* Opened to read in full, a long task or note covers the hours again, as it does while editing. */
.is-readonly .cell-input.expandable.is-expanded {
    background: var(--nbd-surface);
    border-color: var(--nbd-border);
    box-shadow: 0 12px 28px -8px rgba(var(--nbd-shadow-rgb), 0.28);
    cursor: text;
}

.is-readonly .total-card-fields .cell-input { color: #FFFFFF; padding-left: 0; }
.is-readonly .tile .cell-input { padding-left: 0; font-weight: 600; }

.cell-input.strong { font-weight: 600; }
.cell-input.hours { text-align: center; padding-inline: 0.15rem; }
.cell-input.hours:placeholder-shown { background: var(--nbd-surface-sunk); }
.cell-input.num { text-align: right; }
.cell-input.muted { font-size: 0.85rem; }
.cell-input.grow { flex: 1; min-width: 12rem; }
.cell-input.rate { width: 5rem; flex: none; }
.cell-input.phase-name { font-family: var(--nbd-font-display); font-weight: 700; font-size: 1.05rem; }

/*
 * A phase name is as wide as its text (up to the width it used to take), so the move and delete buttons
 * sit right after it; past that it ends in "…". Being edited it grows in place, wider then onto more
 * lines (the editor's growName; `cols` where field-sizing is missing).
 */
.cell-expand:has(> .phase-name) { flex: 0 1 auto; min-width: 0; max-width: 36rem; }
.cell-input.expandable.phase-name { width: auto; max-width: 100%; height: auto; min-height: 2.1rem; field-sizing: content; }
.cell-input.expandable.phase-name:focus { white-space: pre-wrap; }
.phase-card-head > .phase-figures { margin-left: auto; }

.icon-btn {
    width: 2rem;
    height: 2rem;
    border: 0;
    border-radius: 0.35rem;
    background: transparent;
    color: var(--nbd-muted);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
}

.icon-btn:hover { background: rgba(var(--nbd-accent-rgb), 0.08); color: var(--nbd-accent); }
.icon-btn-danger:hover { background: var(--nbd-danger-soft); color: var(--nbd-danger); }
.icon-btn:disabled { color: var(--nbd-control-border); opacity: 0.6; background: transparent; }
.icon { display: inline-flex; }

.row-controls {
    display: inline-flex;
    justify-content: flex-end;
}

.chip-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
}

.team-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    border: 1px solid var(--nbd-field-border);
    border-radius: 999px;
    padding: 0.15rem 0.2rem 0.15rem 0.8rem;
    font-size: 0.875rem;
    background: var(--nbd-surface);
}

.team-chip-name { font-weight: 600; }
.team-chip-unit,
.team-chip-hours { color: var(--nbd-muted); font-size: 0.8rem; }
.team-chip-hours::after { content: ' h'; }
.team-chip .cell-input.team-chip-rate { width: 3.6rem; min-height: 1.75rem; padding: 0.1rem 0.3rem; text-align: right; background: var(--nbd-surface-sunk); }

.chip-add {
    display: inline-flex;
    gap: 0.35rem;
}

.chip-add input { width: 10rem; }

/* Workbench: phase cards. */
.phase-card-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.phase-tag {
    font-family: var(--nbd-font-display);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--nbd-accent);
    white-space: nowrap;
}

.phase-figures {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    min-width: 7rem;
}

.phase-total { font-family: var(--nbd-font-display); font-weight: 700; font-size: 1.2rem; }
.phase-hours { font-size: 0.825rem; color: var(--nbd-muted); }

.line-grid { width: 100%; min-width: min-content; }

.line-row {
    display: grid;
    grid-template-columns: var(--cols);
    column-gap: 0.35rem;
    align-items: center;
}

.line-head {
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--nbd-muted);
    padding-bottom: 0.25rem;
}

.line-block {
    border-top: 1px solid var(--nbd-border);
    padding: 0.4rem 0;
}

.line-meta .row-controls,
.line-meta > .comment-button { margin-left: auto; }

.line-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.825rem;
    color: var(--nbd-muted);
}

.line-meta-rate {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
}

.phase-card-foot {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem;
}

/* The dark totals card at the top of the Workbench rail. */
.total-card {
    background: var(--nbd-feature);
    color: #FFFFFF;
    border-radius: 0.75rem;
    padding: 1.15rem;
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}

.total-card-top {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    gap: 1rem;
}

.total-card-hours {
    border-left: 1px solid var(--nbd-feature-line);
    padding-left: 1rem;
    text-align: right;
}

.total-card-label { font-size: 0.8rem; font-weight: 600; color: #AEBBC7; }
.total-card-figure { display: block; font-family: var(--nbd-font-display); font-weight: 700; font-size: 2.1rem; line-height: 1.1; }

.total-card-lines,
.totals-list {
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    font-size: 0.9rem;
}

.total-card-lines div,
.totals-list div {
    display: flex;
    justify-content: space-between;
    gap: 0.75rem;
}

.total-card-lines dt { font-weight: 400; color: #C6D0D9; }
.total-card-lines dd,
.totals-list dd { margin: 0; }
.totals-list dt { font-weight: 400; }
.totals-rule { border-top: 1px solid var(--nbd-border); padding-top: 0.35rem; font-weight: 600; }
.totals-grand { border-top: 2px solid var(--nbd-ink); padding-top: 0.45rem; font-size: 1.1rem; font-weight: 700; }

.total-card-fields {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.6rem;
    border-top: 1px solid var(--nbd-feature-line);
    padding-top: 0.75rem;
}

.total-card-fields label {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    font-size: 0.8rem;
    font-weight: 600;
    color: #C6D0D9;
}

.total-card-fields .cell-input { color: var(--nbd-ink); }

.budget-meter-track,
.bar-track {
    display: block;
    height: 0.5rem;
    border-radius: 999px;
    background: var(--nbd-surface-sunk);
    overflow: hidden;
}

.budget-meter-track { background: var(--nbd-feature-line); }
.budget-meter-bar { height: 100%; background: #5EEAD4; }
.budget-meter-bar.is-over { background: #FB923C; }
.budget-meter-text.is-over { color: #FDBA74; font-weight: 600; }
.tile-note.is-over { color: var(--nbd-danger); font-weight: 600; }
.budget-meter-text { display: block; font-size: 0.825rem; color: #C6D0D9; margin-top: 0.3rem; }

.media-card { border-style: dashed; }
.media-card-label { display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.85rem; font-weight: 600; }


.bar-fill { display: block; height: 100%; border-radius: 999px; background: var(--nbd-accent-fill); }
.bar-fill-alt { background: var(--nbd-hit); }

/* A share panel (the Workbench's hours by team and by phase): name and percent, bar, figures. */
.share-list { display: flex; flex-direction: column; }

.share-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    gap: 0.3rem 0.75rem;
    padding: 0.5rem 0;
    border-top: 1px solid var(--nbd-surface-sunk);
}

.share-row:first-child { border-top: 0; padding-top: 0.25rem; }
.share-name { font-size: 0.875rem; font-weight: 600; color: var(--nbd-ink); }
.share-pct { font-size: 0.875rem; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--nbd-ink); }
.share-row .bar-track { grid-column: 1 / -1; }
.share-meta { grid-column: 1 / -1; font-size: 0.775rem; color: var(--nbd-muted); font-variant-numeric: tabular-nums; }
.share-row.is-empty .share-name,
.share-row.is-empty .share-pct { color: var(--nbd-muted); font-weight: 500; }

/* Outside expenses and discounts, shared by both designs. */
.expense-table { min-width: 44rem; }

.expense-row {
    display: grid;
    grid-template-columns: minmax(12rem, 1.5fr) 11rem 7rem minmax(10rem, 1.2fr) 2rem;
    gap: 0.35rem;
    align-items: center;
}

.expense-table.has-gutter .expense-row { grid-template-columns: 2.1rem minmax(12rem, 1.5fr) 11rem 7rem minmax(10rem, 1.2fr); }
.expense-table.has-gutter .expense-group-head { padding-left: 2.45rem; }

.expense-head {
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--nbd-muted);
}

.expense-group { border-top: 1px solid var(--nbd-border); padding: 0.4rem 0; }
.expense-group-head { display: flex; justify-content: space-between; font-size: 0.825rem; font-weight: 600; color: var(--nbd-muted); padding: 0.2rem 0; }
.expense-add { padding-top: 0.3rem; }

/* Two lines, so it fits a rail: the label, then $ or %, the value, its effect and remove. */
.adjustment-row {
    display: grid;
    grid-template-columns: auto minmax(3rem, 1fr) auto 2rem;
    gap: 0.3rem 0.4rem;
    align-items: center;
    padding-bottom: 0.4rem;
}

.adjustment-row > :first-child { grid-column: 1 / -1; }

/* Ledger: tiles and the dense table. */
.tile-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: 1px;
    background: var(--nbd-border);
    border: 1px solid var(--nbd-border);
    border-radius: 0.6rem;
    overflow: hidden;
}

.tile { background: var(--nbd-surface); padding: 0.7rem 0.85rem; display: flex; flex-direction: column; gap: 0.2rem; }
.tile-label { font-size: 0.75rem; color: var(--nbd-muted); }
.tile-figure { font-family: var(--nbd-font-display); font-size: 1.35rem; font-weight: 700; }
.tile-note { display: block; font-size: 0.8rem; color: var(--nbd-muted); padding-top: 0.2rem; }
.tile-dark { background: var(--nbd-feature); color: #FFFFFF; }
.tile-dark .tile-label { color: #AEBBC7; }
.tile-sunk { background: var(--nbd-surface-sunk); }

.ledger-grid { width: 100%; min-width: min-content; }

.ledger-row {
    display: grid;
    grid-template-columns: var(--cols);
    column-gap: 0.25rem;
    align-items: center;
    padding: 0.1rem 0.75rem;
}

.ledger-head {
    position: relative;
    z-index: 3;
    background: var(--nbd-surface);
    border-radius: 0.75rem 0.75rem 0 0;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--nbd-muted);
    padding-block: 0.7rem 0.5rem;
    border-bottom: 1px solid var(--nbd-border);
}

/* The column heads follow the screen down the table (pinHead in the editor): sticky when the table fits. */
.ledger-panel.is-fitting { overflow-x: visible; }
.ledger-panel.is-fitting .ledger-head { position: sticky; top: 0; }
.ledger-head.is-pinned { border-radius: 0; box-shadow: 0 6px 10px -8px rgba(var(--nbd-shadow-rgb), 0.35); }

.ledger-phase { border-bottom: 1px solid var(--nbd-border); }
.ledger-phase .ledger-row + .ledger-row { border-top: 1px solid var(--nbd-surface-sunk); }

.ledger-phase-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem 0.75rem 0.3rem 1rem;
    background: var(--nbd-surface-sunk);
}

.phase-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.4rem;
    height: 1.4rem;
    border-radius: 50%;
    background: var(--nbd-accent-fill);
    color: #FFFFFF;
    font-size: 0.75rem;
    font-weight: 700;
}

.ledger-subtotal { font-weight: 600; font-size: 0.875rem; padding-block: 0.5rem 0.7rem; }
.ledger-span-2 { grid-column: span 2; font-size: 0.825rem; padding-left: 0.4rem; }
.ledger-total { background: var(--nbd-feature); color: #FFFFFF; font-weight: 700; padding-block: 0.7rem; }

/* combobox_controller.js: a text input whose suggestions open on focus. */
.combobox { position: relative; }

.combobox-list {
    position: absolute;
    z-index: 1000;
    max-height: 20rem;
    overflow-y: auto;
    margin: 0;
    padding: 0.25rem 0;
    list-style: none;
    background: var(--nbd-surface);
    border: 1px solid var(--nbd-border);
    border-radius: 0.5rem;
    box-shadow: 0 8px 24px rgba(var(--nbd-shadow-rgb), 0.12);
}

.combobox-list [role="option"] {
    padding: 0.4rem 0.75rem;
    cursor: pointer;
}

.combobox-list [role="option"]:hover,
.combobox-list [role="option"][aria-selected="true"] {
    background: rgba(var(--nbd-accent-rgb), 0.08);
    color: var(--nbd-accent);
}

/*
 * With or without JavaScript (html.js / html.no-js, switched in base.html.twig's head before anything is
 * drawn): a placeholder where a controller will draw, and the plain fallback only where none will.
 */
.no-js .js-only,
.js .no-js-only { display: none !important; }

/* The version page's drawer is plain sections without JavaScript; with it, hidden until its controller connects. */
.js .version-page:not(.has-drawer) .version-drawer { display: none; }

/* An estimate's shape in gray while its editor loads (estimate/_skeleton.html.twig). */
.estimate-skeleton { display: flex; flex-direction: column; gap: 1rem; }
.skeleton-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    border: 1px solid var(--nbd-border);
    border-radius: 0.75rem;
    overflow: hidden;
    background: var(--nbd-surface);
}
.skeleton-tile { display: flex; flex-direction: column; gap: 0.6rem; padding: 0.9rem 1rem 1.1rem; border-right: 1px solid var(--nbd-border); }
.skeleton-panel {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    padding: 1rem 1.15rem;
    border: 1px solid var(--nbd-border);
    border-radius: 0.75rem;
    background: var(--nbd-surface);
}
.skeleton-dark { background: var(--nbd-feature); border-color: var(--nbd-feature); }
.skeleton-dark .skeleton-bar { background: var(--nbd-feature-line); }
.skeleton-columns { display: grid; grid-template-columns: minmax(0, 1fr) 20rem; gap: 1rem; align-items: start; }
.skeleton-main, .skeleton-side { display: flex; flex-direction: column; gap: 1rem; }
.skeleton-chips { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.skeleton-row { display: flex; align-items: center; gap: 0.5rem; }
.skeleton-row > .skeleton-bar { flex: 1; max-width: 22rem; }
.skeleton-bar, .skeleton-chip, .skeleton-box {
    display: block;
    border-radius: 0.35rem;
    background: var(--nbd-line);
    animation: skeleton-shimmer 1.4s ease-in-out infinite;
}
.skeleton-bar { height: 0.7rem; }
.skeleton-title { height: 1rem; margin-top: 0.4rem; }
.skeleton-figure { height: 1.4rem; }
.skeleton-chip { width: 8.5rem; height: 2.1rem; border-radius: 999px; }
.skeleton-box { width: 2.6rem; height: 1.9rem; flex: none; }
@keyframes skeleton-shimmer { 50% { opacity: 0.55; } }
@media (max-width: 991.98px) {
    .skeleton-columns { grid-template-columns: minmax(0, 1fr); }
}
@media (prefers-reduced-motion: reduce) {
    .skeleton-bar, .skeleton-chip, .skeleton-box { animation: none; }
}

/* A project's or document's edit history (_partials/edit_history.html.twig), folded at the foot of its page. */
.edit-history { margin-top: 2rem; }
.edit-history > summary { font-family: var(--nbd-font-display); font-weight: 700; font-size: 1.1rem; cursor: pointer; }
.edit-history-empty { margin: 0.75rem 0 0; color: var(--nbd-muted); }
.edit-history-list {
    list-style: none;
    margin: 0.75rem 0 0;
    padding: 0;
    border: 1px solid var(--nbd-border);
    border-radius: 0.75rem;
    background: var(--nbd-surface);
}
.edit-history-list li {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.6rem 1rem;
    font-size: 0.9rem;
    border-top: 1px solid var(--nbd-line-faint);
}
.edit-history-list li:first-child { border-top: 0; }
.edit-history-meta { font-size: 0.8rem; color: var(--nbd-muted); }
.edit-history-change > summary { cursor: pointer; }
.edit-history-text { margin: 0.35rem 0 0; white-space: pre-line; overflow-wrap: anywhere; }

/* A document's versions, newest first: the current file, then the earlier ones to download. */
.version-list {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 1px solid var(--nbd-border);
    border-radius: 0.75rem;
    background: var(--nbd-surface);
}
.version-list li {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem 1rem;
    border-top: 1px solid var(--nbd-line-faint);
}
.version-list li:first-child { border-top: 0; }
.version-list-number { flex: none; width: 2.2rem; font-family: var(--nbd-font-display); font-weight: 700; color: var(--nbd-muted); }
.version-list .is-current .version-list-number { color: var(--nbd-accent); }
.version-list-body { display: flex; flex-direction: column; min-width: 0; flex: 1; overflow-wrap: anywhere; }
.version-list-meta { font-size: 0.825rem; color: var(--nbd-muted); }

/* The notifications page: who mentioned you, where, and what they said, as a plain list. Unread is a dot. */
.notification-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--nbd-border); }
.notification-list li { border-bottom: 1px solid var(--nbd-border); }
.notification-list a { display: flex; align-items: flex-start; gap: 0.75rem; padding: 0.9rem 0.25rem; color: inherit; text-decoration: none; }
.notification-list a:hover .notification-what { text-decoration: underline; }
.notification-list .comment-avatar { --avatar-size: 2rem; flex: none; font-size: 0.75rem; }
.notification-main { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; flex: 1; }
.notification-what { color: var(--nbd-muted); }
.notification-what strong { color: var(--nbd-ink); }
.notification-quote { color: var(--nbd-ink); white-space: pre-line; overflow-wrap: anywhere; }
.notification-when { font-size: 0.8rem; color: var(--nbd-muted); }
.notification-dot { flex: none; width: 0.55rem; height: 0.55rem; margin-top: 0.5rem; border-radius: 50%; background: var(--nbd-accent); }

/* An @mention in a comment, and the composer's suggestions after "@". */
.mention-chip {
    /* A pill exactly one line tall: the circle is centered in it, and the name sits on the baseline of the words
       around it (it alone takes part in baseline alignment, so it is what the pill lines up by). */
    display: inline-flex;
    align-items: center;
    gap: 0.3em;
    height: 1.5em;
    padding: 0 0.5em 0 0.15em;
    border-radius: 999px;
    background: var(--nbd-chip);
    color: var(--nbd-ink);
    font-weight: 600;
    line-height: 1.5em;
    white-space: nowrap;
}
.mention-chip-name { align-self: baseline; }
.mention-chip-avatar {
    /* Centered as .comment-avatar is, in its own smaller type: 2 × 0.6em is 1.2em of the pill's. */
    --avatar-size: 2em;
    flex: none;
    display: block;
    width: var(--avatar-size);
    padding-block: calc((var(--avatar-size) - 1cap) / 2);
    border-radius: 50%;
    color: #FFFFFF;
    font-size: 0.6em;
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0;
    text-align: center;
    text-box: trim-both cap alphabetic;
}
.mention-host { position: relative; }
.mention-list {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 30;
    margin: 0.2rem 0 0;
    padding: 0.25rem 0;
    list-style: none;
    max-height: 13rem;
    overflow-y: auto;
    background: var(--nbd-surface);
    border: 1px solid var(--nbd-border);
    border-radius: 0.5rem;
    box-shadow: 0 8px 24px rgba(var(--nbd-shadow-rgb), 0.12);
    font-size: 0.875rem;
}
.mention-list [role="option"] { padding: 0.35rem 0.75rem; cursor: pointer; }
.mention-list [role="option"][aria-selected="true"],
.mention-list [role="option"]:hover { background: rgba(var(--nbd-accent-rgb), 0.08); color: var(--nbd-accent); }
.comment-edited { font-size: 0.75rem; color: var(--nbd-muted); }

/* Moving a phase or line by its grip (estimate/drag.js): the row fades, a bar shows where it will land. */
.drag-handle { cursor: grab; touch-action: none; }
.is-dragging-row, .is-dragging-row * { cursor: grabbing !important; user-select: none; }
.is-dragging { opacity: 0.4; }
.drop-indicator {
    position: absolute;
    z-index: 1060;
    height: 3px;
    border-radius: 2px;
    background: var(--nbd-accent);
    box-shadow: 0 0 0 2px rgba(var(--nbd-accent-rgb), 0.25);
    pointer-events: none;
}
