/* ============================================
   ZOOM CONTROLS
   ============================================ */

.zoom-controls {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    background: var(--bg-tertiary);
    padding: 0.2rem 0.4rem;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-color);
}

.zoom-controls .zoom-btn {
    width: 24px;
    height: 24px;
    border: none;
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    border-radius: 3px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.9rem;
    transition: all 0.15s;
}

.zoom-controls .zoom-btn:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}

.zoom-controls .zoom-input {
    width: 48px;
    height: 22px;
    border: 1px solid var(--border-color);
    border-radius: 3px;
    background: var(--bg-primary);
    color: var(--text-primary);
    font-size: 0.7rem;
    font-weight: 600;
    text-align: center;
    padding: 0 2px;
    -moz-appearance: textfield;
}

.zoom-controls .zoom-input::-webkit-outer-spin-button,
.zoom-controls .zoom-input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.zoom-controls .zoom-input:focus {
    outline: 1px solid var(--accent-orange);
    border-color: var(--accent-orange);
}

.zoom-controls .zoom-pct {
    font-size: 0.65rem;
    color: var(--text-secondary);
    font-weight: 600;
    margin-left: -2px;
}

/* ============================================
   ENHANCED FOCUS COLORS - LIGHTER SELECTION
   ============================================ */

/* Allow text selection in inputs */
.excel-table input {
    user-select: text !important;
    -webkit-user-select: text !important;
    -moz-user-select: text !important;
    -ms-user-select: text !important;
}

/* Row selection — unified token fill so cell + row share ONE look (Bug 3) and
   light theme is Harbor teal, never dark navy (Bug 1). */
.excel-table tbody tr.selected td {
    background: var(--grid-sel-fill) !important;
}

/* Row-number (#) cell of a selected row — the row's anchor; keep distinct. */
.excel-table tbody tr.selected td:first-child {
    background: var(--grid-sel-border) !important;
    color: #fff !important;
}

/* Focused cell inside a selected row keeps the same selection fill. */
.excel-table tbody tr.selected td.selected-cell,
.excel-table tbody tr.selected td:has(input:focus) {
    background: var(--grid-sel-fill) !important;
}

/* Individual cell selection — SAME palette as the row (Bug 3). Inputs keep their
   own theme text color (no forced dark) so both themes stay readable. */
.excel-table tbody tr td.cell-selected {
    background: var(--grid-sel-fill) !important;
    /* Single clean 2px border (matches .selected-cell) — NOT an extra inset
       box-shadow, which doubled up into a heavy dark-blue frame on click. */
    border: 2px solid var(--grid-sel-border) !important;
    position: relative;
    z-index: 1;
}

.excel-table tbody tr td.cell-selected input {
    background: transparent !important;
}

/* Hover state for rows - bright background for readability */
.excel-table tbody tr:hover td {
    background: #f0f9ff !important; /* Very light blue - excellent contrast */
}

.excel-table tbody tr:hover td:first-child {
    background: #bae6fd !important; /* Light blue for row numbers */
    color: #1e293b !important;
}

/* Selected row + hover - same light blue as regular hover */
.excel-table tbody tr.selected:hover td {
    background: #f0f9ff !important; /* Same very light blue as hover */
}

.excel-table tbody tr.selected:hover td:first-child {
    background: #bae6fd !important; /* Same light blue as regular row number hover */
    color: #1e293b !important;
}

/* Ensure text remains dark and visible on hover */
.excel-table tbody tr:hover td input {
    color: #1e293b !important; /* Dark text for maximum contrast */
}

/* Column selection highlight - enhanced visibility */
.excel-table th.col-selected {
    background: linear-gradient(180deg, #60a5fa 0%, #3b82f6 100%) !important;
    color: white !important;
    box-shadow: 0 0 0 2px #3b82f6;
    position: relative;
    z-index: 15;
}

.excel-table td.col-selected {
    background: #dbeafe !important; /* Light blue 100 - improved contrast */
    border-left: 2px solid #60a5fa !important;
    border-right: 2px solid #60a5fa !important;
}

/* First and last cell in column selection get top/bottom borders */
.excel-table tbody tr:first-child td.col-selected {
    border-top: 2px solid #60a5fa !important;
}

.excel-table tbody tr:last-child td.col-selected {
    border-bottom: 2px solid #60a5fa !important;
}

/* Column selected cells on hover - brighter highlight */
.excel-table td.col-selected:hover {
    background: #bfdbfe !important; /* Sky blue 200 - brighter on hover */
}

/* Multiple column selection indicator */
.excel-table th.col-selected::after {
    content: '✓';
    position: absolute;
    top: 4px;
    right: 4px;
    font-size: 0.7rem;
    background: white;
    color: #3b82f6;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: bold;
}

/* Multi-select drag indicator */
.excel-table tbody tr.multi-drag-source {
    opacity: 0.6;
    outline: 2px dashed #60a5fa;
}

.excel-table tbody tr.drag-target-above {
    border-top: 3px solid #f97316 !important;
}

.excel-table tbody tr.drag-target-below {
    border-bottom: 3px solid #f97316 !important;
}

/* ============================================
   LIGHT THEME - ROW & COLUMN SELECTION OVERRIDES
   ============================================ */

/* Light theme hover state */
[data-theme="light"] .excel-table tbody tr:hover td {
    background: #f0f9ff !important;
}

[data-theme="light"] .excel-table tbody tr:hover td:first-child {
    background: #bae6fd !important;
    color: #1e293b !important;
}

/* Light theme selected row — unified token fill (Harbor teal, not dark navy). */
[data-theme="light"] .excel-table tbody tr.selected td {
    background: var(--grid-sel-fill) !important;
}

[data-theme="light"] .excel-table tbody tr.selected td:first-child {
    background: var(--grid-sel-border) !important;
    color: #fff !important;
}

/* Light theme - focused cell in a selected row keeps the same fill. */
[data-theme="light"] .excel-table tbody tr.selected td.selected-cell,
[data-theme="light"] .excel-table tbody tr.selected td:has(input:focus) {
    background: var(--grid-sel-fill) !important;
}

/* Light theme individual cell selection — same token palette as the row,
   single clean border (no doubled inset box-shadow frame). */
[data-theme="light"] .excel-table tbody tr td.cell-selected {
    background: var(--grid-sel-fill) !important;
    border: 2px solid var(--grid-sel-border) !important;
}

[data-theme="light"] .excel-table tbody tr td.cell-selected input {
    background: transparent !important;
}

/* Light theme selected row + hover - same light blue as regular hover */
[data-theme="light"] .excel-table tbody tr.selected:hover td {
    background: #f0f9ff !important;
}

[data-theme="light"] .excel-table tbody tr.selected:hover td:first-child {
    background: #bae6fd !important;
    color: #1e293b !important;
}

/* Light theme column selection */
[data-theme="light"] .excel-table th.col-selected {
    background: linear-gradient(180deg, #475569 0%, #334155 100%) !important;
    color: white !important;
    box-shadow: 0 0 0 2px #475569 !important;
}

[data-theme="light"] .excel-table td.col-selected {
    background: rgba(71, 85, 105, 0.1) !important;
    border-left: 2px solid #475569 !important;
    border-right: 2px solid #475569 !important;
}

[data-theme="light"] .excel-table tbody tr:first-child td.col-selected {
    border-top: 2px solid #475569 !important;
}

[data-theme="light"] .excel-table tbody tr:last-child td.col-selected {
    border-bottom: 2px solid #475569 !important;
}

[data-theme="light"] .excel-table td.col-selected:hover {
    background: rgba(71, 85, 105, 0.15) !important;
}

/* Light theme column selected header checkmark */
[data-theme="light"] .excel-table th.col-selected::after {
    background: white !important;
    color: #475569 !important;
}

/* Light theme inputs in selected rows */
[data-theme="light"] .excel-table tbody tr.selected td input {
    color: #1e293b !important;
}

[data-theme="light"] .excel-table tbody tr:hover td input {
    color: #1e293b !important;
}

/* ============================================
   COLOR PICKER MODAL (Simple - No Gradients)
   ============================================ */

/* Popover behaviour — no full-screen backdrop. The panel is positioned
   in JS underneath the ribbon tool that opened it (see ColorPicker.open).
   The wrapper is a transparent overlay only so click-outside still has a
   sane bubble target; pointer-events pass through everything except the
   panel itself. */
.color-picker-modal {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: transparent;
    z-index: 2000;
    display: none;
    pointer-events: none;
}

.color-picker-modal.visible {
    display: block;
}

.color-picker-panel {
    /* The panel has no scroll of its own and open() only flips above/below, so a
       taller panel used to be clipped with no way to reach the bottom. */
    max-height: calc(100vh - 24px);
    overflow-y: auto;
    position: fixed; /* concrete left/top set inline by ColorPicker.open */
    pointer-events: auto;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
    width: 360px;
    max-width: 95vw;
    animation: fadeIn 0.15s ease;
}

/* The BG/Text tab switcher is gone — each ribbon tool opens its own
   single-mode popover. Hide the rule defensively in case any cached
   markup renders before the new JS. */
.cp-mode-tabs { display: none !important; }

.color-picker-header {
    padding: 0.75rem 1.25rem;
    border-bottom: 1px solid var(--border-color);
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.color-picker-header h3 {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 0.9rem;
    white-space: nowrap;
}

.cp-mode-tabs {
    display: flex;
    gap: 2px;
    background: var(--bg-tertiary);
    border-radius: 4px;
    padding: 2px;
}

.cp-tab {
    padding: 0.25rem 0.6rem;
    border: none;
    border-radius: 3px;
    background: transparent;
    color: var(--text-muted);
    font-size: 0.68rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.15s;
}

.cp-tab.active {
    background: var(--accent-orange);
    color: #fff;
}

.color-picker-close {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 1.25rem;
    cursor: pointer;
    padding: 0.25rem;
    line-height: 1;
    margin-left: auto;
}

.color-picker-close:hover {
    color: var(--text-primary);
}

.color-picker-body {
    padding: 0.75rem 1.25rem;
}

/* Color Sections */
.color-section {
    margin-bottom: 0.75rem;
}

.color-section label {
    display: block;
    font-size: 0.65rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 0.35rem;
}

/* Favorites section header: hint + Clear link */
.cp-fav-hint {
    text-transform: none;
    letter-spacing: 0;
    font-size: 0.6rem;
    color: var(--text-muted);
    opacity: 0.75;
    margin-left: 0.3rem;
}
.cp-fav-clear {
    float: right;
    text-transform: none;
    letter-spacing: 0;
    font-size: 0.62rem;
    color: #0a5989;
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
}
.cp-fav-clear:hover { text-decoration: underline; }
.cp-fav-empty {
    font-size: 0.62rem;
    color: var(--text-muted);
    text-transform: none;
    letter-spacing: 0;
    opacity: 0.7;
}

/* Color Row Grid */
.color-row {
    display: flex;
    gap: 3px;
    flex-wrap: wrap;
}

/* Office-style 10-column theme grid: base hue per column, tints/shades
   running down the rows. Tight 2px gaps and small swatches keep the whole
   palette compact enough for a ribbon dropdown. */
.cp-theme-grid {
    display: grid;
    grid-template-columns: repeat(10, 1fr);
    gap: 2px;
}

.cp-theme-grid .color-swatch {
    width: 100%;
    height: 22px;
    border-radius: 2px;
}

.color-swatch {
    width: 28px;
    height: 28px;
    border-radius: 3px;
    cursor: pointer;
    transition: all 0.15s;
    border: 2px solid transparent;
}

.color-swatch:hover {
    transform: scale(1.2);
    border-color: var(--text-primary);
    z-index: 5;
    position: relative;
    box-shadow: 0 4px 12px rgba(0,0,0,0.3);
}

/* Rainbow canvas */
.cp-rainbow {
    width: 100%;
    height: 140px;
    border-radius: 4px;
    cursor: crosshair;
    border: 1px solid var(--border-color);
    display: block;
}

.cp-hue-strip {
    width: 100%;
    height: 16px;
    border-radius: 3px;
    cursor: pointer;
    margin-top: 4px;
    border: 1px solid var(--border-color);
    display: block;
}

/* Preview swatch */
.cp-preview-swatch {
    width: 36px;
    height: 30px;
    border-radius: 4px;
    border: 2px solid var(--border-color);
    flex-shrink: 0;
}

/* Custom Color Section */
.custom-section {
    padding-top: 0.6rem;
    border-top: 1px solid var(--border-color);
    margin-top: 0.5rem;
}

.custom-color-row {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    flex-wrap: wrap;
}

/* Actions get their own line — five controls of five different heights crammed
   onto one 6px-gap row was the "cramped" complaint. */
.custom-action-row {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    flex-wrap: wrap;
    margin-top: 0.55rem;
}
.custom-action-row .btn { flex: 1 1 auto; justify-content: center; }
/* stop the primary button's 1px hover lift from nudging the row */
.custom-action-row .btn-primary:hover { transform: none; }

.custom-color-row input[type="text"] {
    flex: 1 1 120px;
    min-width: 96px;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    background: var(--bg-tertiary);
    color: var(--text-primary);
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.72rem;
}

/* Color Picker Footer */
.color-picker-footer {
    padding: 0.5rem 1.25rem;
    border-top: 1px solid var(--border-color);
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.cp-favorites-row {
    display: flex;
    gap: 3px;
    flex: 1;
    justify-content: center;
}

.cp-fav-swatch {
    width: 22px;
    height: 22px;
}

/* Empty personalised-colour slot: a dashed placeholder that opens the colour
   picker and keeps whatever you choose. Nine of these are always rendered so
   there is somewhere obvious to park a colour. */
.cp-fav-empty-slot {
    background: transparent !important;
    border: 1px dashed rgba(255, 255, 255, 0.35);
    color: rgba(255, 255, 255, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    line-height: 1;
    cursor: pointer;
}
.cp-fav-empty-slot:hover {
    border-color: var(--accent-orange);
    color: var(--accent-orange);
}
[data-theme="light"] .cp-fav-empty-slot {
    border-color: rgba(71, 85, 105, 0.45);
    color: #64748b;
}
/* The favourites row now holds 9 slots — let it wrap instead of squeezing. */
#cpFavoritesRow {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}

/* Format buttons */
.fmt-btn {
    min-width: 28px;
    justify-content: center;
    font-size: 0.8rem;
}

.fmt-btn strong {
    font-size: 0.85rem;
    font-weight: 800;
}

/* ============================================
   LIVE SYNC INDICATOR & USER AVATARS
   ============================================ */

/* Live Sync Indicator — "Live B" minimal-breath design.
   Chip-less: a small breathing dot + uppercase label sit directly in the
   nav. When connected users are present, a thin divider and an avatar
   stack are rendered beside it via the existing .users-online-container. */
.live-sync-indicator {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-size: 0.65rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    /* The top-nav is dark in both themes (gradient in dark, Harbor Blue
       #0a5989 in light), so we use a light text colour regardless of
       theme — same scale as .nav-link's resolved colour. */
    color: rgba(255, 255, 255, 0.78);
    padding: 0;
    background: transparent;
    border: none;
    border-radius: 0;
}

.live-sync-indicator .sync-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--accent-green);
    box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.55);
    animation: liveBreath 1.8s ease-in-out infinite;
}

.live-sync-indicator.syncing .sync-dot {
    background: var(--accent-yellow);
    animation-name: liveBreathYellow;
}

.live-sync-indicator.offline .sync-dot {
    background: var(--accent-red);
    box-shadow: none;
    animation: none;
}

.live-sync-indicator .sync-status {
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

/* Light-theme dot ripple uses the muted Harbor-Blue green so the breath
   reads against the brighter background. */
[data-theme="light"] .live-sync-indicator .sync-dot {
    animation-name: liveBreathLight;
}

@keyframes liveBreath {
    0%, 100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.55); }
    50%      { box-shadow: 0 0 0 6px rgba(34, 197, 94, 0); }
}
@keyframes liveBreathLight {
    0%, 100% { box-shadow: 0 0 0 0 rgba(44, 140, 98, 0.55); }
    50%      { box-shadow: 0 0 0 6px rgba(44, 140, 98, 0); }
}
@keyframes liveBreathYellow {
    0%, 100% { box-shadow: 0 0 0 0 rgba(234, 179, 8, 0.55); }
    50%      { box-shadow: 0 0 0 6px rgba(234, 179, 8, 0); }
}

/* User Avatars Container */
.users-online-container {
    display: flex;
    align-items: center;
    margin-left: 0.5rem;
    padding-left: 0.75rem;
    border-left: 1px solid var(--border-color);
    position: relative;
}

.users-avatars {
    display: flex;
    align-items: center;
}

.user-avatar {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.65rem;
    color: white;
    font-weight: 600;
    margin-left: -8px;
    border: 2px solid var(--bg-secondary);
    cursor: pointer;
    transition: transform 0.15s, z-index 0.15s;
    position: relative;
    text-transform: uppercase;
}

.user-avatar:first-child {
    margin-left: 0;
}

.user-avatar:hover {
    transform: scale(1.15);
    z-index: 10;
}

.user-avatar.you {
    border-color: var(--accent-green);
}

.user-avatar.more-users {
    background: #4b5563 !important;
    font-size: 0.6rem;
    cursor: pointer;
}

/* User Tooltip */
.user-avatar .avatar-tooltip {
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%);
    background: var(--bg-primary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 0.4rem 0.6rem;
    white-space: nowrap;
    font-size: 0.65rem;
    color: var(--text-primary);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.15s, visibility 0.15s;
    z-index: 100;
    box-shadow: 0 4px 12px rgba(0,0,0,0.3);
}

.user-avatar .avatar-tooltip::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 5px solid transparent;
    border-top-color: var(--border-color);
}

.user-avatar:hover .avatar-tooltip {
    opacity: 1;
    visibility: visible;
}

/* More Users Dropdown */
.more-users-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    background: var(--bg-primary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    padding: 0.5rem 0;
    min-width: 180px;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.15s, visibility 0.15s;
    z-index: 100;
    box-shadow: 0 8px 24px rgba(0,0,0,0.4);
}

.more-users-dropdown.visible {
    opacity: 1;
    visibility: visible;
}

.more-users-dropdown .dropdown-header {
    padding: 0.4rem 0.75rem;
    font-size: 0.6rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border-bottom: 1px solid var(--border-color);
    margin-bottom: 0.25rem;
}

.more-users-dropdown .user-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.75rem;
    font-size: 0.7rem;
    color: var(--text-primary);
}

.more-users-dropdown .user-item:hover {
    background: var(--bg-hover);
}

.more-users-dropdown .user-item .mini-avatar {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.55rem;
    color: white;
    font-weight: 600;
    text-transform: uppercase;
}

.more-users-dropdown .user-item .user-name {
    flex: 1;
}

.more-users-dropdown .user-item .you-badge {
    font-size: 0.55rem;
    background: var(--accent-green);
    color: white;
    padding: 0.1rem 0.3rem;
    border-radius: 3px;
}

/* ── Light theme — connected-users widget, live tag & avatars ──
   The top-nav is navy (#0a5989) in light theme, so the live tag + avatar
   initials use white; the dropdown floats over the white page, so it gets a
   solid white surface with dark text (var(--bg-primary) is poisoned to dark /
   reads transparent here, so hardcode it). */
[data-theme="light"] .live-sync-indicator,
[data-theme="light"] .live-sync-indicator .sync-status { color: #ffffff !important; }

[data-theme="light"] .more-users-dropdown {
    background: #ffffff !important;
    border-color: #cbd5e1 !important;
    box-shadow: 0 10px 28px rgba(16, 49, 107, 0.20) !important;
}
[data-theme="light"] .more-users-dropdown .dropdown-header {
    color: #475569 !important;
    border-bottom-color: #e2e8f0 !important;
}
[data-theme="light"] .more-users-dropdown .user-item { color: #102033 !important; }
[data-theme="light"] .more-users-dropdown .user-item:hover { background: #eef4f8 !important; }
[data-theme="light"] .more-users-dropdown .user-item .user-status { color: #64748b !important; }
[data-theme="light"] .more-users-dropdown .user-item.user-item-empty { color: #94a3b8 !important; }

/* Avatar initials legible on any hashed avatar color + a white ring so they
   stand out against the navy nav. */
[data-theme="light"] .user-avatar { border-color: #ffffff !important; }
[data-theme="light"] .user-avatar,
[data-theme="light"] .more-users-dropdown .user-item .mini-avatar {
    color: #ffffff !important;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);
}

/* ============================================
   CELL COMMENTS — Google-Sheets-style corner badge + hover tooltip
   ============================================ */

/* The td needs to be a positioning context for the absolute badge. The
   cells themselves are display:table-cell with no `position` rule, so
   add it here without disturbing other layout.  */
.excel-table td.has-cell-comment {
    position: relative;
}

/* Pure-CSS chat-bubble: rounded square with a small tail in the
   bottom-left, white "!" inside. Background color comes from one of the
   .flag-* modifier classes (or .solved for the green check). No SVG,
   no icon font dependency. */
.cell-comment-badge {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 16px;
    height: 16px;
    background: var(--cell-comment-bg, #f97316); /* default = medium */
    color: #ffffff;
    border-radius: 4px 4px 4px 1px;
    pointer-events: auto;
    cursor: help;
    z-index: 3;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: 'Inter', system-ui, sans-serif;
    font-weight: 800;
    font-size: 10.5px;
    line-height: 1;
    text-align: center;
    user-select: none;
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.25));
    transition: transform 0.12s ease;
}

.cell-comment-badge:hover {
    transform: scale(1.15);
}

/* Severity flag colors. Single CSS variable drives both the badge fill
   and its tail so they stay in sync. */
.cell-comment-badge.flag-low    { --cell-comment-bg: #3b82f6; background: #3b82f6; }
.cell-comment-badge.flag-medium { --cell-comment-bg: #f97316; background: #f97316; }
.cell-comment-badge.flag-high   { --cell-comment-bg: #dc2626; background: #dc2626; }
/* Solved overrides the flag color with green so a resolved item is
   visibly distinct from an open one of any severity. The check glyph
   is set in JS (textContent = '✓'). */
.cell-comment-badge.solved      { --cell-comment-bg: #22c55e; background: #22c55e; }

/* Tail of the chat bubble — same color as the bubble via the variable. */
.cell-comment-badge::after {
    content: '';
    position: absolute;
    bottom: -3px;
    left: 1px;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 4px 4px 0 0;
    border-color: var(--cell-comment-bg, #f97316) transparent transparent transparent;
}

/* Invisible hover surface so the tooltip stays open while the cursor
   is moving from the badge into the floating tooltip portal. */
.cell-comment-badge::before {
    content: '';
    position: absolute;
    top: -4px;
    right: -4px;
    width: 28px;
    height: 28px;
}

/* The original CSS-only `.cell-comment-tooltip` lived inside the badge
   and was clipped by .excel-scroll's overflow — replaced by the
   body-level singleton `.cell-comment-tooltip-portal`. The shared
   typography rules below apply to both legacy and current markup so
   future single-comment uses still render readable. */

.cell-comment-tooltip-head {
    font-size: 10.5px;
    color: #9ca3af;
    margin-bottom: 4px;
    letter-spacing: 0.2px;
}

.cell-comment-tooltip-body {
    white-space: pre-wrap;
    word-break: break-word;
}

/* Body-level singleton tooltip — escapes the .excel-scroll overflow.
   The original CSS-only tooltip lived inside the badge, but the table
   wrapper has overflow:auto which clipped it. JS positions this one
   `fixed` near the hovered badge, so it always renders on top. */
.cell-comment-tooltip-portal {
    position: fixed;
    top: 0;
    left: 0;
    min-width: 200px;
    max-width: 320px;
    background: #1f2937;
    color: #f9fafb;
    border-radius: 6px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
    padding: 8px 10px;
    font-family: 'Inter', system-ui, sans-serif;
    font-size: 12px;
    line-height: 1.4;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-2px);
    transition: opacity 0.12s, visibility 0.12s, transform 0.12s;
    z-index: 2200;
    pointer-events: auto;
}

/* Light theme: a white comment tooltip with BLACK text — the author/date head was
   grey (#9ca3af) and hard to read once the broad light rule flipped the portal bg.
   !important beats themes.css's broad [data-theme="light"] div rules. */
[data-theme="light"] .cell-comment-tooltip-portal {
    background: #ffffff !important;
    color: #111827 !important;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18) !important;
}
[data-theme="light"] .cell-comment-tooltip-head,
[data-theme="light"] .cell-comment-tooltip-body {
    color: #111827 !important;
}

.cell-comment-tooltip-portal.visible {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.cell-comment-tooltip-portal .cell-comment-tooltip-head {
    font-size: 10.5px;
    color: #9ca3af;
    margin-bottom: 4px;
    letter-spacing: 0.2px;
}

.cell-comment-tooltip-portal .cell-comment-tooltip-body {
    white-space: pre-wrap;
    word-break: break-word;
}

/* Stack of comment cards inside one tooltip. Each card has its own
   header (meta + chips) and body. A thin divider sits between cards. */
.cct-list {
    display: flex;
    flex-direction: column;
    gap: 0;
}

.cct-card {
    padding: 4px 0;
}

.cct-card.solved {
    opacity: 0.72;
}

.cct-divider {
    height: 1px;
    background: rgba(255, 255, 255, 0.10);
    margin: 4px 0;
}

/* Inline chat-bubble icon used in the tooltip card meta line, before
   the author name. Reuses .cce-flag-icon's shape but adds spacing +
   slight vertical alignment tweaks for the dark tooltip context. */
.cct-flag-icon {
    margin-right: 4px;
    vertical-align: -1px;
}

/* Multi-count badge: when a cell has >1 comments the bubble grows to
   fit the count next to the glyph (e.g. "!3" or "✓2"). */
.cell-comment-badge.multi {
    width: auto;
    min-width: 22px;
    padding: 0 4px;
    font-size: 10px;
    letter-spacing: 0.2px;
}

/* Light-theme pin: the badge text (the "!" glyph plus the count digit on
   multi badges) must stay white on every colored background, because the
   table cell sits on a white sheet in light theme and the badge would
   otherwise pick up the cell's dark inherited color through any rule we
   haven't anticipated. !important on every variant keeps it locked. */
[data-theme="light"] .cell-comment-badge,
[data-theme="light"] .cell-comment-badge.flag-low,
[data-theme="light"] .cell-comment-badge.flag-medium,
[data-theme="light"] .cell-comment-badge.flag-high,
[data-theme="light"] .cell-comment-badge.solved,
[data-theme="light"] .cell-comment-badge.multi {
    color: #ffffff !important;
}

/* Tooltip header: meta text on the left, action chips on the right.
   Google-Sheets-style — a thin divider separates the header from the
   body so the buttons read as part of the title strip, not the comment. */
.cell-comment-tooltip-portal .cct-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-bottom: 5px;
    margin-bottom: 5px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}

.cell-comment-tooltip-portal .cct-header .cell-comment-tooltip-head {
    /* Reset bottom margin since the header row owns the spacing now. */
    margin-bottom: 0;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cct-actions {
    display: inline-flex;
    gap: 3px;
    flex-shrink: 0;
}

/* Compact icon chips — 22×22 with a single glyph each. Buttons hide
   themselves via inline display:none when an action isn't allowed
   (e.g. Clear is hidden for non-author / non-super_admin; Solve for
   already-solved comments). */
.cct-btn {
    background: rgba(255, 255, 255, 0.10);
    color: #f9fafb;
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 4px;
    padding: 0;
    width: 22px;
    height: 22px;
    font-size: 13px;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.12s, border-color 0.12s, transform 0.1s;
}

.cct-btn:hover {
    background: rgba(255, 255, 255, 0.20);
    border-color: rgba(255, 255, 255, 0.32);
    transform: translateY(-1px);
}

.cct-solve { color: #86efac; background: rgba(34, 197, 94, 0.16); border-color: rgba(34, 197, 94, 0.34); }
.cct-solve:hover { background: rgba(34, 197, 94, 0.32); border-color: rgba(34, 197, 94, 0.55); }

.cct-clear { color: #fca5a5; background: rgba(239, 68, 68, 0.16); border-color: rgba(239, 68, 68, 0.34); font-size: 16px; }
.cct-clear:hover { background: rgba(239, 68, 68, 0.30); border-color: rgba(239, 68, 68, 0.55); }

.cct-edit { color: #f9fafb; }

/* Inline confirm popover floating above the clicked Solve / Clear chip.
   Lives inside .cct-header so JS can position it relative to the
   tooltip's own bounds (tip and pop share an offset parent). */
.cell-comment-tooltip-portal .cct-confirm-pop {
    position: absolute;
    background: #111827;
    color: #f9fafb;
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 6px;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.45);
    padding: 5px 6px 5px 9px;
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    white-space: nowrap;
    z-index: 5;
}

.cct-confirm-pop[hidden] { display: none; }

.cct-confirm-text {
    font-weight: 600;
}

.cct-confirm-yes,
.cct-confirm-no {
    background: rgba(255, 255, 255, 0.12);
    color: #f9fafb;
    border: 1px solid rgba(255, 255, 255, 0.20);
    border-radius: 4px;
    padding: 1px 8px;
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    line-height: 1.3;
}

.cct-confirm-yes { background: rgba(34, 197, 94, 0.30); border-color: rgba(34, 197, 94, 0.55); color: #ecfdf5; }
.cct-confirm-yes:hover { background: rgba(34, 197, 94, 0.50); }

.cct-confirm-no { background: rgba(239, 68, 68, 0.22); border-color: rgba(239, 68, 68, 0.50); color: #fef2f2; }
.cct-confirm-no:hover { background: rgba(239, 68, 68, 0.42); }

/* ============================================
   CELL COMMENT EDITOR — dropdown popover for add/edit
   ============================================ */

/* The wrapper exists only to scope the panel; it must not paint any
   background of its own. In light theme a stray rule was filling it
   white and creating a full-screen overlay — explicit values + a
   defensive transparent fill keep it click-through and invisible in
   every theme. */
.cell-comment-editor-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 2100;
    display: none;
    pointer-events: none;
    background: transparent !important;
    box-shadow: none !important;
    border: 0 !important;
}

.cell-comment-editor-overlay.visible {
    display: block;
}

.cell-comment-editor-panel {
    position: fixed; /* concrete left/top set inline by CellCommentEditor.open */
    pointer-events: auto;
    background: var(--bg-secondary, #fff);
    color: var(--text-primary, #111827);
    border: 1px solid var(--border-color, #e5e7eb);
    border-radius: 10px;
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.32);
    width: 320px;
    max-width: 95vw;
    padding: 10px 12px;
    animation: fadeIn 0.12s ease;
}

/* Light theme: the panel is a <div>, so the global
   `[data-theme="light"] div { background-color: inherit }` in themes.css
   overrides its background and it inherits the transparent editor overlay
   → a see-through bubble. Pin an opaque Harbor-white card with a soft
   shadow so the comment editor reads solid on the light dashboard. */
[data-theme="light"] .cell-comment-editor-panel {
    background: #ffffff !important;
    color: #102033 !important;
    border-color: #d6e2ea !important;
    box-shadow: 0 14px 38px rgba(23, 45, 64, 0.18) !important;
}
[data-theme="light"] .cell-comment-editor-panel .cce-title { color: #102033 !important; }
[data-theme="light"] .cell-comment-editor-panel .cce-meta { color: #536579 !important; }
[data-theme="light"] .cell-comment-editor-panel .cce-flag-radio { border-color: #d6e2ea !important; }
[data-theme="light"] .cell-comment-editor-panel .cce-text { border-color: #d6e2ea !important; }

.cce-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}

.cce-title {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 0.85rem;
    font-weight: 600;
}

/* Flag picker — inline LOW / MED / HIGH radios with chat-bubble icons.
   Three labels side-by-side; clicking the label or its hidden radio
   selects the flag. The native radio carries state for keyboard A11y. */
.cce-flag-radios {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-left: auto;
    margin-right: 8px;
}

.cce-flag-radio {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 6px 2px 4px;
    border: 1px solid var(--border-color, #d1d5db);
    border-radius: 6px;
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.4px;
    color: var(--text-muted, #6b7280);
    cursor: pointer;
    user-select: none;
    transition: border-color 0.12s, background 0.12s, color 0.12s;
}

.cce-flag-radio:hover {
    border-color: var(--text-muted, #6b7280);
}

.cce-flag-radio.selected {
    color: var(--text-primary, #111827);
}

.cce-flag-radio[data-flag="low"].selected    { border-color: #3b82f6; background: rgba(59, 130, 246, 0.10); }
.cce-flag-radio[data-flag="medium"].selected { border-color: #f97316; background: rgba(249, 115, 22, 0.10); }
.cce-flag-radio[data-flag="high"].selected   { border-color: #dc2626; background: rgba(220, 38, 38, 0.10); }

/* Hide the native radio dot but keep it in the layout for A11y +
   keyboard focus. The label + chat icon are the visible affordance. */
.cce-flag-radio input[type="radio"] {
    appearance: none;
    -webkit-appearance: none;
    width: 0;
    height: 0;
    margin: 0;
    padding: 0;
    border: 0;
    outline: none;
    pointer-events: none;
    position: absolute;
}

.cce-flag-radio-label {
    line-height: 1;
}

/* Mini chat-bubble preview — the same shape the cell badge will show
   when the comment is saved with this flag. Tail color matches the bg
   of the bubble via per-flag rules below. */
.cce-flag-icon {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    border-radius: 3px 3px 3px 1px;
    color: #fff;
    font-weight: 800;
    font-size: 9.5px;
    line-height: 1;
    flex-shrink: 0;
}

.cce-flag-icon::after {
    content: '';
    position: absolute;
    bottom: -2px;
    left: 1px;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 3px 3px 0 0;
    border-color: currentColor transparent transparent transparent;
}

/* Per-flag fill — tail uses currentColor (set on the icon itself)
   so the bubble and tail always match. */
.cce-flag-icon.flag-low    { background: #3b82f6; color-scheme: light; }
.cce-flag-icon.flag-low::after    { border-top-color: #3b82f6; }
.cce-flag-icon.flag-medium { background: #f97316; }
.cce-flag-icon.flag-medium::after { border-top-color: #f97316; }
.cce-flag-icon.flag-high   { background: #dc2626; }
.cce-flag-icon.flag-high::after   { border-top-color: #dc2626; }

/* The "!" glyph inside the icon needs to render white over the colored
   background, but the bubble's color shorthand on .flag-* sets text
   color implicitly. Force white so the glyph stays readable. */
.cce-flag-icon { color: #fff !important; }

.cce-close {
    background: none;
    border: none;
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    color: var(--text-muted, #6b7280);
    padding: 2px 6px;
}

.cce-close:hover {
    color: var(--text-primary, #111827);
}

.cce-text {
    width: 100%;
    min-height: 84px;
    resize: vertical;
    font-family: inherit;
    font-size: 12.5px;
    line-height: 1.4;
    padding: 8px 10px;
    border: 1px solid var(--border-color, #d1d5db);
    border-radius: 6px;
    background: var(--bg-tertiary, #f9fafb);
    color: var(--text-primary, #111827);
    outline: none;
    box-sizing: border-box;
}

.cce-text:focus {
    border-color: var(--accent-orange, #f97316);
    box-shadow: 0 0 0 2px rgba(249, 115, 22, 0.18);
}

.cce-meta {
    margin-top: 6px;
    font-size: 0.65rem;
    color: var(--text-muted, #9ca3af);
    letter-spacing: 0.2px;
}

.cce-footer {
    margin-top: 10px;
    display: flex;
    justify-content: flex-end;
    gap: 6px;
}

/* Brief flash applied by NotificationCenter.viewCellComment so the user
   can spot which cell a pending-comment notification is anchored to. */
@keyframes cellCommentFlash {
    0%   { box-shadow: inset 0 0 0 3px rgba(249,115,22,0.85); }
    100% { box-shadow: inset 0 0 0 3px rgba(249,115,22,0); }
}

.cell-comment-flash {
    animation: cellCommentFlash 1.6s ease-out;
}

/* Cell-comment notification card variant — slightly distinct accent so
   it's visually parsable next to unload / service tasks. */
.notif-item.cell-comment-task {
    border-left: 3px solid var(--accent-orange, #f97316);
}

/* Ribbon Favorites Display - Main display in ribbon */
.ribbon-favorites {
    display: flex;
    gap: 0.25rem;
    margin-left: 0.3rem;
    padding: 0.15rem;
    background: rgba(0, 0, 0, 0.2);
    border-radius: var(--radius-sm);
}

.ribbon-favorite-color {
    width: 24px;
    height: 24px;
    border-radius: 4px;
    cursor: pointer;
    border: 2px solid rgba(255,255,255,0.2);
    transition: all 0.15s;
    position: relative;
}

.ribbon-favorite-color:hover {
    transform: scale(1.15);
    border-color: white;
    z-index: 5;
}

.ribbon-favorite-color.empty {
    border-style: dashed;
    border-color: rgba(255,255,255,0.3);
    background: transparent;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8rem;
    color: rgba(255,255,255,0.4);
}

.ribbon-favorite-color.empty:hover {
    border-color: var(--accent-orange);
    color: var(--accent-orange);
}

/* Light theme: the empty favourite slots are drawn white for the dark ribbon,
   which is invisible on a light one. Grey the dashed ring and the + glyph, and
   give the filled swatches a grey ring too so they still read as buttons.
   Dark theme keeps the white treatment above. */
[data-theme="light"] .ribbon-favorite-color.empty {
    border-color: rgba(71, 85, 105, 0.45);
    color: #64748b;
}
[data-theme="light"] .ribbon-favorite-color {
    border-color: rgba(71, 85, 105, 0.3);
}
[data-theme="light"] .ribbon-favorite-color:hover {
    border-color: #475569;
}

.ribbon-favorite-color .remove-fav {
    position: absolute;
    top: -5px;
    right: -5px;
    width: 14px;
    height: 14px;
    background: var(--accent-red);
    border: none;
    border-radius: 50%;
    color: white;
    font-size: 0.55rem;
    cursor: pointer;
    display: none;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

.ribbon-favorite-color:hover .remove-fav {
    display: flex;
}

/* ============================================
   ZOOMED TABLE STYLES
   ============================================ */

.excel-table.zoomed {
    transform-origin: top left;
}

/* ============================================
   CONNECTED USERS — green dot + status row
   ============================================
   Augments the existing .user-avatar / .user-item styles with a small
   "currently editing" indicator (Google-Sheets-style green dot in the
   bottom-right of the avatar) and a status string in the dropdown row. */

.user-avatar .user-editing-dot {
    position: absolute;
    bottom: -1px;
    right: -1px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #22c55e;
    border: 2px solid var(--bg-secondary);
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15);
}

.more-users-dropdown .user-item .user-status {
    margin-left: auto;
    font-size: 0.65rem;
    color: var(--text-muted);
    text-transform: none;
    letter-spacing: 0;
    white-space: nowrap;
}

.more-users-dropdown .user-item.user-item-empty {
    color: var(--text-muted);
    font-style: italic;
    justify-content: center;
}

/* ===========================================================================
   GRID SELECTION / HOVER — single authoritative look (loads LAST in the last
   CSS file). ONE clean style, IDENTICAL in BOTH themes (the grid is white in
   both): a light teal-blue border + a soft translucent fill, so BLACK cell text
   stays readable — never the old dark navy. The doubled `.excel-table.excel-table`
   is a deliberate specificity boost so this block authoritatively overrides the
   older per-theme selection/hover rules earlier in this file (and in table.css /
   themes.css) without having to delete them. Yellow warn cells (.cell-warn) and
   the row-# / status columns are never given a blue fill.
   Owner 2026-06-24: replaced the earlier "remove all feedback" block with this.
   =========================================================================== */
/* Row hover — barely-there tint. OPAQUE (not rgba): the grid cell bg is white in
   both themes, but a translucent fill would composite over the DARK page behind
   the cell in dark theme and read as a dark, unreadable block. Opaque light-blue
   keeps it identical and readable in both themes. */
.excel-table.excel-table tbody tr:hover td:not(.cell-warn):not(:first-child):not(.col-status) {
  background: #eef6f9 !important;
  box-shadow: none !important;
}
/* Selected ROW — light GREEN, so whole-row selection reads apart from the blue
   cell/range selection at a glance. Opaque hex (never rgba) for the same
   dark-theme compositing reason as the hover rule above. */
.excel-table.excel-table tbody tr.selected td:not(.cell-warn):not(:first-child):not(.col-status) {
  /* Deeper than the focus crosshair (#eef8f0): both are green, so the
     deliberate act (selecting a row) has to read stronger than the passive
     guide that merely follows the cursor. */
  background: #d4ecd7 !important;
  box-shadow: none !important;
}
/* Selected row block OUTLINE (rectangle around the selection) */
.excel-table.excel-table tbody tr.selected td:first-child:not(.cell-warn) { border-left: 2px solid #2e7d32 !important; }
.excel-table.excel-table tbody tr.selected td:last-child:not(.cell-warn)  { border-right: 2px solid #2e7d32 !important; }
.excel-table.excel-table tbody tr.selected.sel-block-top td:not(.cell-warn)    { border-top: 2px solid #2e7d32 !important; }
.excel-table.excel-table tbody tr.selected.sel-block-bottom td:not(.cell-warn) { border-bottom: 2px solid #2e7d32 !important; }
/* Selected cell / range — soft fill. The OUTLINE is drawn by the ::after
   overlay below, not by `border`: this table is border-collapse:collapse, so a
   cell only owns its right and bottom edges; its opaque background then paints
   over the top and left edges owned by the neighbours, which is why the old
   2px border showed on two sides only. An overlay is immune to collapsing.
   Do NOT re-add `border` here — a border AND a shadow together is what caused
   the heavy dark-blue frame regression noted at the top of this file. */
.excel-table.excel-table td.selected-cell:not(.cell-warn):not(.col-status),
.excel-table.excel-table tbody tr td.cell-selected:not(.cell-warn):not(.col-status) {
  background: #d9eaf0 !important;
  box-shadow: none !important;
  /* Hold the border at the NORMAL grid line. Three older rules still set a 2px
     coloured border on every selected cell (enhancements.css ~:99 and ~:230,
     themes.css ~:1813); with the border removed from this block they came back
     to life and boxed EVERY cell in a range, drawing lines INSIDE the block.
     Excel draws one outline around the whole range — that outline is the
     ::after overlay below, on perimeter edges only. */
  border: 1px solid #d6e2ea !important;
  position: relative;
  z-index: 2;
}
/* The ACTIVE cell (where the selection was anchored) is never filled — Excel
   and Google Sheets both leave it clear so you can see where you started. */
.excel-table.excel-table tbody tr td.cell-active:not(.cell-warn):not(.col-status) {
  background: var(--row-white) !important;
}
/* Range outline. Each selected cell draws an edge ONLY where its orthogonal
   neighbour is not also selected (classes set by
   SelectionManager.applyCellSelectionEdges), so touching cells merge into one
   block instead of each drawing its own box. */
.excel-table.excel-table tbody tr td.cell-selected::after,
.excel-table.excel-table td.selected-cell::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 3;
  border: 0 solid #0f7ea2;
}
.excel-table.excel-table tbody tr td.cell-selected.sel-e-t::after { border-top-width: 2px; }
.excel-table.excel-table tbody tr td.cell-selected.sel-e-r::after { border-right-width: 2px; }
.excel-table.excel-table tbody tr td.cell-selected.sel-e-b::after { border-bottom-width: 2px; }
.excel-table.excel-table tbody tr td.cell-selected.sel-e-l::after { border-left-width: 2px; }
/* A lone focused cell (no range) still gets a full box. */
.excel-table.excel-table td.selected-cell:not(.cell-selected)::after { border-width: 2px; }
/* While dragging a range, don't let the browser select text inside the inputs. */
body.grid-range-dragging, body.grid-range-dragging .excel-table input {
  user-select: none !important;
}
/* FOCUS MODE — a light GREEN wash down the focused row and column.
   Green on purpose: the focused row is almost always the row under the
   pointer, and the blue-grey hover tint (#eef6f9) is so close to a blue focus
   tint that the row highlight looked like it was not working at all.
   NEEDS !important: the light theme sets `.excel-table td { background:#fff }`
   and the zebra stripe `tr:nth-child(2n) td` BOTH with !important, so a plain
   declaration here can never win no matter its specificity.
   The :not() guards keep the intended layering, since this block sits later in
   the file and out-specifies the selection rules above:
     user-painted colours (inline !important)  >  selection  >  focus  >  zebra
   Excluding .cell-selected / .selected-cell / tr.selected is what stops the
   crosshair from washing over an active selection. A colour someone painted on
   a row is an INLINE !important style, which still beats everything here. */
.excel-table.excel-table tbody tr:not(.selected) td.focus-row:not(.cell-warn):not(:first-child):not(.col-status):not(.cell-selected):not(.selected-cell),
.excel-table.excel-table tbody tr:not(.selected) td.focus-col:not(.cell-warn):not(:first-child):not(.col-status):not(.cell-selected):not(.selected-cell) {
  background: #caead8 !important;
}
/* The row-number cell of the focused row gets a slightly stronger tint so the
   crosshair is readable even against the sticky # column chrome. */
.excel-table.excel-table tbody tr td.focus-row:first-child:not(.cell-warn) {
  background: #b3ddc6 !important;
  color: var(--text-primary) !important;
}
.excel-table.excel-table thead th.focus-col-head {
  box-shadow: inset 0 -3px 0 0 #2e7d32;
}
.excel-table.excel-table td.selected-cell input,
.excel-table.excel-table tbody tr td.cell-selected input { background: transparent !important; }
/* Row-number (#) cell of hovered/selected rows — keep its sticky chrome, never
   a blue fill (the row outline's left border still wraps it). */
.excel-table.excel-table tbody tr:hover td:first-child:not(.cell-warn),
.excel-table.excel-table tbody tr.selected td:first-child:not(.cell-warn) {
  background: var(--bg-tertiary) !important;
  color: var(--text-muted) !important;
}
/* cell-warn (yellow ASKED / MISSING) must also beat the nth-child(even) ZEBRA
   striping: that rule ([0,3,3] dark / [0,4,3] light) out-specifies the base
   .cell-warn rule, so on GREY (even) rows the yellow was being lost. Re-assert
   with matching specificity (doubled .excel-table) in this last-loading block so
   the yellow shows on BOTH white and grey rows, in BOTH themes. */
.excel-table.excel-table tbody tr td.cell-warn,
[data-theme="light"] .excel-table.excel-table tbody tr td.cell-warn {
  background: #fbff00 !important;
}

/* Carrier column always bold so it stands out on the register. Uses the cell
   selector (not an inline style) so it survives row bold/unbold toggles. */
.excel-table td[data-col="carrier"] input { font-weight: 700; }

/* ---------------------------------------------------------------------------
   Colour picker: native RGB input beside the hex field (2026-08).
   --------------------------------------------------------------------------- */
/* css/main.css:163 has a GLOBAL `input[type="color"] { position:absolute;
   width:100%; height:100%; opacity:0 }` for its own custom colour buttons. That
   selector is (0,1,1) and beats a bare `.cp-native-color` (0,1,0) whatever the
   load order, so this input rendered as an INVISIBLE sheet stretched over the
   whole picker panel — which is why a personalised colour could never be
   picked. Scoping by element+class wins the specificity fight. */
.custom-color-row input[type="color"].cp-native-color {
  position: static;
  opacity: 1;
  width: 34px;
  height: 30px;
}

.cp-native-color {
  width: 34px;
  height: 30px;
  padding: 0;
  border: 1px solid var(--border-color, #cbd5e1);
  border-radius: 5px;
  background: none;
  cursor: pointer;
  flex: none;
}
.cp-native-color::-webkit-color-swatch-wrapper { padding: 2px; }
.cp-native-color::-webkit-color-swatch { border: none; border-radius: 3px; }

/* Ribbon checkbox (Focus mode) — matches the ribbon's small-control sizing. */
.ribbon-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--text-secondary, #64748b);
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
}
.ribbon-toggle input { cursor: pointer; margin: 0; accent-color: #0f7ea2; }
.ribbon-toggle:hover { color: var(--text-primary, #0f172a); }

/* ===========================================================================
   CUSTOMS SCAN FLAG — Shipments Register, CONTAINER column only (2026-08-11)
   ---------------------------------------------------------------------------
   The flag is painted as a background-IMAGE layer, never a background-color,
   and it is addressed through the #tableBody ID. Both are deliberate:

   · cell_colors / row colours are written as INLINE `background-color …
     !important` (DashboardData._applyRowFormatting, TableManager.applyCellColor).
     An inline !important colour cannot be overridden from a stylesheet — and it
     must not be, it is the user's own colour. A gradient background-image
     composites ON TOP of it, so the flag never reads, writes or clobbers
     cell_colors, and lifting the flag exposes the stored colour again untouched.

   · The grid hover / row-selection / range-selection block earlier in this file
     uses the `background` SHORTHAND with !important, which RESETS
     background-image. Its specificity is (0,6,3); an ID beats any number of
     classes, so #tableBody td.<class> (1,1,1) keeps the flag visible while the
     row is hovered, selected, or inside a drag range.

   The grid cell is white with dark text in BOTH themes (see the block above),
   so one opaque amber is legible in light and dark — no per-theme variant.
   =========================================================================== */
#tableBody td.customs-scan-flagged {
  background-image: linear-gradient(#ffd43b, #ffd43b) !important;
  /* Thin amber rim so the flag reads as deliberate next to the neon #fbff00
     `.cell-warn` yellow used by PHYTO / Freight / Release. */
  box-shadow: inset 0 0 0 1px #b8860b !important;
}
/* IN FLIGHT — striped, never solid: the solid yellow is only ever painted from
   the server's answer. Declared after the flag rule so it wins on a cell that
   is being released (same specificity, later wins). */
#tableBody td.customs-scan-busy {
  background-image: repeating-linear-gradient(45deg, #ffe9a8 0 6px, #fff7dc 6px 12px) !important;
  box-shadow: inset 0 0 0 1px #d9b45a !important;
}

/* Context-menu items that are present for history but not actionable
   (already selected / already released). */
.context-menu-item.cs-disabled {
  opacity: 0.45;
  cursor: default;
}
.context-menu-item.cs-disabled:hover {
  background: transparent !important;
  color: inherit !important;
}
/* Keyboard focus ring — scoped to the customs-scan items, which are the only
   context-menu items that carry a tabindex. */
.context-menu-item.cs-item:focus-visible {
  outline: 2px solid #0f7ea2;
  outline-offset: -2px;
}

/* ===========================================================================
   SHIPMENTS REGISTER → EXCEL BUTTON (2026-08-12)
   ---------------------------------------------------------------------------
   Green, white text, sitting immediately left of the JARVIS button in the tab
   bar.

   WHY THE GREEN IS RE-DECLARED HERE rather than reused. The existing green
   Excel button is styled as `.cp-root #cpExportBtn` in css/cargo-planner.css —
   every one of those rules is scoped to `.cp-root`, which only exists inside
   the Cargo Planner pane. A button in the tab bar is not a descendant, so not
   one of them would match and the button would fall through to themes.css's
   `[data-theme="light"] button { background:#fff !important }`. Same hue
   (#15803d = 5.02:1 against white, hover #166534 = 7.13:1), declared where it
   can actually apply.

   WHY THE THEME SELECTORS ARE SPELLED OUT. themes.css sets button colours with
   `!important` per theme, so a plain `#id { background: … }` loses in light
   mode. This mirrors the pattern already used for #btnExportStock in
   pages/position-log.html, which hit the same wall.

   POSITIONING — CHANGED 2026-08-12 WHEN THE TOOLS MENU LANDED. The standalone
   button used to claim `margin-left:auto` so it travelled to the right edge
   with JARVIS. It is now an item inside the Tools menu, and the menu belongs
   next to the Rows badge, so the auto-margin goes BACK to the JARVIS trigger
   (which is where css/jarvis-fab.css declares it in the first place — the
   override below only ever existed to take it away). If the human keeps the
   old button in the markup during the changeover it now simply sits beside the
   Tools trigger instead of fighting it for the free space.
   =========================================================================== */
.page-tabs #registerExportBtn {
  margin-left: 0.4rem;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  flex: 0 0 auto;
  padding: 0.3rem 0.7rem;
  border-radius: 6px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
/* Hands the free space back to the FAB so it returns to the far right. Spelled
   out rather than deleted: this selector is (0,2,0) and jarvis-fab.css's own
   `.jarvis-fab-trigger` is (0,1,0), so merely removing the rule would leave
   the answer depending on which file happens to load last. */
.page-tabs .jarvis-fab-trigger { margin-left: auto; }

/* The green is declared ONCE, for the old button and the Tools trigger
   together — two reports sharing one hue must not be able to drift apart. */
#registerExportBtn,
.page-tabs #registerToolsBtn,
[data-theme="light"] .page-tabs #registerExportBtn,
[data-theme="light"] .page-tabs #registerToolsBtn,
[data-theme="dark"] .page-tabs #registerExportBtn,
[data-theme="dark"] .page-tabs #registerToolsBtn {
  background: #15803d !important;
  border: 1px solid #15803d !important;
  color: #ffffff !important;
}
#registerExportBtn > *,
.page-tabs #registerToolsBtn > *,
[data-theme="light"] .page-tabs #registerExportBtn > *,
[data-theme="light"] .page-tabs #registerToolsBtn > * { color: #ffffff !important; }

#registerExportBtn:hover:not(:disabled),
.page-tabs #registerToolsBtn:hover:not(:disabled),
[data-theme="light"] .page-tabs #registerExportBtn:hover:not(:disabled),
[data-theme="light"] .page-tabs #registerToolsBtn:hover:not(:disabled),
[data-theme="dark"] .page-tabs #registerExportBtn:hover:not(:disabled),
[data-theme="dark"] .page-tabs #registerToolsBtn:hover:not(:disabled) {
  background: #166534 !important;
  border-color: #166534 !important;
}
.page-tabs #registerExportBtn:focus-visible,
.page-tabs #registerToolsBtn:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: -3px;
}
/* In-flight: the label already says "Exporting…", so this only needs to read
   as not-clickable. Explicit colours, never opacity — an opacity wash over a
   white-on-green button drops the text contrast below AA in light theme. */
.page-tabs #registerExportBtn:disabled {
  background: #3f6b4f !important;
  border-color: #3f6b4f !important;
  color: #e8f0ea !important;
  cursor: default;
}

/* ===========================================================================
   SHIPMENTS REGISTER → TOOLS DROPDOWN (2026-08-12)
   ---------------------------------------------------------------------------
   "Tools ▾" sits IMMEDIATELY RIGHT OF THE ROWS BADGE, not at the right edge:
   it is a property of the register the badge is counting, so it reads as part
   of that group. JARVIS keeps the far right (see the margin note above).

   WHY THE WRAPPER EXISTS AT ALL. .page-tabs is the flex row, so the trigger
   cannot be both a flex item and the containing block for an absolutely
   positioned panel without the panel inheriting the row's alignment. The
   wrapper is the flex item and carries position:relative; the trigger and the
   panel live inside it, and the panel is therefore anchored to the trigger no
   matter how the row reflows at narrow widths.

   CLIPPING — CHECKED, NONE. .page-tabs and .page-tabs-container both leave
   `overflow` at its initial `visible` (css/navigation.css:425 and :459), and no
   ancestor between them and <body> sets one. `body { overflow-x: hidden }`
   (css/main.css:64) does not clip either: with <html> still `visible` the body's
   overflow propagates to the viewport and the body box itself computes back to
   `visible`. So the panel overhangs the tab bar freely and needs no portal.

   Z-INDEX 1300 is chosen against the two things it can overlap: the top nav and
   its user dropdown top out at 1200 (css/navigation.css:256) and the modals in
   this file start at 2000. The menu must beat the nav and lose to the modals.
   =========================================================================== */
.page-tabs .register-tools {
  position: relative;   /* containing block for the panel */
  flex: 0 0 auto;
  display: inline-flex;
  margin-left: 0.4rem;  /* hugs the Rows badge — deliberately NOT auto */
}
/* The reports are register-scoped, so the button is hidden on the panes they do
   not describe (see TOOLS_PANES in js/data.js). This rule is what makes that
   work: `display` above is an AUTHOR declaration and beats the browser's own
   `[hidden] { display: none }`, so setting the attribute alone left the button
   on screen. Same reason the menu carries its own [hidden] rule below. */
.page-tabs .register-tools[hidden] { display: none; }

.page-tabs #registerToolsBtn {
  display: inline-flex;
  align-items: center;
  /* Asymmetric: tighter on the caret side so the arrow reads as sitting on the
     button's edge, which is how the caret was asked for. */
  padding: 0.3rem 0.55rem 0.3rem 0.7rem;
  border-radius: 6px;
  font-family: inherit;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

/* The divider lives on the LABEL, not on the caret. It has to: the caret flips
   180° when the menu opens, and a border on the rotating element would swing
   round to the wrong side with it. */
.page-tabs #registerToolsBtn .register-tools-label {
  padding-right: 0.45rem;
  border-right: 1px solid rgba(255, 255, 255, 0.4);
  line-height: 1.35;
}

.page-tabs #registerToolsBtn .register-tools-caret {
  display: inline-flex;      /* transform is ignored on a non-replaced inline box */
  align-items: center;
  justify-content: center;
  width: 0.85rem;
  font-size: 0.62rem;
  line-height: 1;
  transition: transform 0.15s ease;
}
/* Fixed width above + transform here: the open/closed states occupy exactly the
   same box, so nothing on the tab bar moves when the menu is toggled. */
.page-tabs #registerToolsBtn[aria-expanded="true"] .register-tools-caret {
  transform: rotate(180deg);
}

/* In-flight pulse. The trigger's label is never rewritten (a wider caption
   would shove the JARVIS button sideways mid-click), so the only signal that a
   report is building is this — plus the toast. */
.page-tabs #registerToolsBtn.is-busy { animation: registerToolsPulse 1.1s ease-in-out infinite; }
@keyframes registerToolsPulse {
  0%, 100% { background: #15803d !important; }
  50%      { background: #1f9c4d !important; }
}

/* ── The panel ─────────────────────────────────────────────────────────────
   `hidden` is the ONLY switch: the JS sets menu.hidden and the [hidden] rule
   below (one specificity step up, same file) wins over the display:block. A
   class-based open state on top of the attribute is how a menu ends up visible
   while aria says it is closed. */
.page-tabs .register-tools-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 1300;
  min-width: 232px;
  padding: 0.3rem 0;
  display: block;
  background: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.4);
  animation: registerToolsIn 0.14s ease;
}
.page-tabs .register-tools-menu[hidden] { display: none; }

@keyframes registerToolsIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}

.page-tabs .register-tools-item {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.55rem;
  text-align: left;
  padding: 0.55rem 0.85rem;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 0.72rem;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 0.12s ease, color 0.12s ease;
}
/* :focus AND NOT :focus-visible, deliberately. The arrow-key handler moves
   between items by calling .focus() from script, and a programmatic focus does
   not reliably put the browser into the "keyboard modality" that
   :focus-visible depends on — the item would take focus with nothing on screen
   to say so, which is the whole point of the arrow keys. Plain :focus is safe
   here precisely because these items are NEVER focused by pointer: a mouse
   open leaves focus on the trigger (verified), and activating an item hands
   focus straight back to it. */
.page-tabs .register-tools-item:hover,
.page-tabs .register-tools-item:focus {
  background: var(--bg-hover);
  color: var(--text-primary);
}
/* The highlight above plus an inset rule on the leading edge. Inset, because a
   ring drawn OUTSIDE the item would be clipped by the panel's own rounded
   corners on the first and last row. */
.page-tabs .register-tools-item:focus {
  outline: none;
  box-shadow: inset 3px 0 0 0 var(--accent-green);
}
.page-tabs .register-tools-item:disabled {
  color: var(--text-muted);
  cursor: default;
}
.page-tabs .register-tools-item:disabled:hover { background: transparent; }

.page-tabs .register-tools-item .register-tools-icon {
  width: 1rem;
  flex: 0 0 auto;
  text-align: center;
  opacity: 0.85;
}

/* ── Light theme ───────────────────────────────────────────────────────────
   Everything below needs !important, and not out of habit. themes.css:936 sets
   `[data-theme="light"] button { background:#fff !important; color:#102033
   !important; border:1px solid #b9cedb !important }` — the menu items ARE
   buttons, so without this each one renders as a white boxed button inside the
   panel with a visible border, three stacked rectangles instead of a list.
   The panel itself is a plain div and only has to out-specify themes.css:919
   `[data-theme="light"] div { background-color: inherit }`, which the two-class
   selector already does; it is given an explicit white anyway so it separates
   from the white tab bar behind it by border and shadow alone. */
[data-theme="light"] .page-tabs .register-tools-menu {
  background: #ffffff !important;
  border-color: #d6e2ea !important;
  box-shadow: 0 12px 28px rgba(23, 45, 64, 0.16) !important;
}
[data-theme="light"] .page-tabs .register-tools-item {
  background: transparent !important;
  border: 0 !important;
  color: #33465a !important;
}
[data-theme="light"] .page-tabs .register-tools-item:hover:not(:disabled),
[data-theme="light"] .page-tabs .register-tools-item:focus {
  background: #e6f3f8 !important;
  color: #0a5989 !important;
}
[data-theme="light"] .page-tabs .register-tools-item:focus {
  box-shadow: inset 3px 0 0 0 #15803d !important;
}
[data-theme="light"] .page-tabs .register-tools-item:disabled {
  color: #7c8c9b !important;
  background: transparent !important;
}
