/* Visual language applied to the daily surfaces (hq#20, hq#71).

   The tokens already ship in shared/contracts/ui/design-tokens.css. This layer
   only *binds* them to the screens a user touches every day — chat list,
   conversation + composer, search, Actions, Settings — so the daily path stops
   carrying its own dark-first palette.

   Rules of this file:
   - no new palette and no new shell: every colour, radius, font size and
     duration below is a token that already exists in the canonical contract;
   - no new components: only selectors that already exist on the daily surfaces;
   - loaded last (after css/chat-list-surface.css) so it wins over the legacy
     dark-first declarations in css/main.css without editing them.

   Measured before/after contrast is listed in visual-language-review.html. */

/* ---------------------------------------------------------------------------
   1. Search surface.

   Was hardcoded dark (#252536 / #1e1e2e / #2f2f44 / #888) with no light-theme
   counterpart, so in the light theme the panel stayed a dark island and its
   muted label (#888 on #2f2f44) sat at 3.68:1. Now it follows the theme.
   ------------------------------------------------------------------------ */
.search-panel {
    background: var(--color-bg-surface);
    border-color: var(--color-border-subtle);
    color: var(--color-text-primary);
}

.search-panel--chat {
    background: color-mix(in srgb, var(--color-bg-surface) 98%, transparent);
}

.search-panel-header input {
    background: var(--color-bg-input);
    border-color: var(--color-border);
    color: var(--color-text-primary);
    font-family: var(--font-sans);
    font-size: var(--font-size-section);
}

.search-panel-header input::placeholder {
    color: var(--color-text-muted);
}

.search-panel-header input:focus {
    border-color: var(--color-accent);
    box-shadow: var(--focus-ring);
}

.search-panel-icon-btn,
.search-panel-close {
    border-color: var(--color-border);
    color: var(--color-text-secondary);
    background: transparent;
}

.search-panel-icon-btn:hover,
.search-panel-close:hover {
    background: var(--color-bg-hover);
    color: var(--color-text-primary);
}

.search-panel-icon-btn:disabled,
.search-panel-icon-btn:disabled:hover {
    color: var(--color-text-muted);
    background: transparent;
}

.search-result-position {
    color: var(--color-text-secondary);
    font-family: var(--font-mono);
    font-variant-numeric: var(--font-variant-data);
}

.search-panel-chip,
.search-scope-btn {
    background: var(--color-bg-muted);
    border-color: var(--color-border);
    color: var(--color-text-secondary);
    font-family: var(--font-sans);
    font-size: var(--font-size-meta);
}

.search-panel-chip:hover,
.search-scope-btn:hover {
    border-color: var(--color-accent);
    color: var(--color-text-primary);
}

.search-scope-btn.active {
    background: var(--color-bg-selected);
    border-color: var(--color-accent);
    color: var(--color-text-primary);
}

.search-panel-popover {
    background: var(--color-bg-surface-raised);
    border-color: var(--color-border);
    box-shadow: var(--shadow-lg);
}

.search-panel-popover-title,
.search-scope-label,
.search-chat-options-empty {
    color: var(--color-text-muted);
    font-family: var(--font-sans);
    font-size: var(--font-size-micro);
}

.search-chat-option {
    background: var(--color-bg-muted);
    color: var(--color-text-primary);
    font-family: var(--font-sans);
    font-size: var(--font-size-meta);
}

.search-chat-option:hover {
    background: var(--color-bg-hover);
}

.search-chat-option input {
    accent-color: var(--color-accent);
}

.search-panel-filters input,
.search-panel-filters select {
    background: var(--color-bg-input);
    border-color: var(--color-border);
    color: var(--color-text-primary);
    font-family: var(--font-sans);
    font-size: var(--font-size-meta);
}

.search-panel-filters input:focus,
.search-panel-filters select:focus {
    border-color: var(--color-accent);
    box-shadow: var(--focus-ring);
}

.search-results {
    border-top-color: var(--color-border-subtle);
}

.search-result-count {
    color: var(--color-text-muted);
    border-bottom-color: var(--color-border-subtle);
    font-family: var(--font-sans);
    font-size: var(--font-size-meta);
}

.search-result-item {
    border-bottom-color: var(--color-border-subtle);
}

.search-result-item:hover {
    background: var(--color-bg-hover);
}

.search-result-item.active {
    background: var(--color-bg-selected);
}

.search-result-chat {
    background: var(--color-bg-selected);
    border-color: var(--color-border-strong);
    color: var(--color-accent);
    font-family: var(--font-sans);
    font-size: var(--font-size-micro);
}

.search-result-sender {
    color: var(--color-accent);
    font-family: var(--font-sans);
    font-size: var(--font-size-meta);
    font-weight: var(--font-weight-strong);
}

.search-result-date {
    color: var(--color-text-muted);
    font-family: var(--font-mono);
    font-size: var(--font-size-micro);
    font-variant-numeric: var(--font-variant-data);
}

.search-result-content {
    color: var(--color-text-secondary);
    font-family: var(--font-sans);
    font-size: var(--font-size-meta);
}

.search-result-content mark {
    background: var(--color-accent-soft);
    color: var(--color-text-primary);
}

/* Search states. "Nothing to search", "still searching", "search failed" and
   "no matches" used to share one grey line, so an error looked like an empty
   result set. They now differ by role, by colour and by wording. */
.search-results-empty {
    color: var(--color-text-secondary);
    font-family: var(--font-sans);
    font-size: var(--font-size-section);
}

.search-results-empty.is-empty,
.search-results-empty.is-loading {
    color: var(--color-text-muted);
}

.search-results-empty.is-error {
    color: var(--color-danger);
    font-weight: var(--font-weight-medium);
}

/* ---------------------------------------------------------------------------
   2. Conversation.

   The sent bubble was #667eea with a white label — 3.66:1 in both themes.
   --color-accent-action is the token the contract provides for a filled
   primary action carrying a light label (4.79:1 dark, 5.43:1 light).
   ------------------------------------------------------------------------ */
.message.sent .message-bubble {
    background: var(--color-accent-action);
    color: var(--color-text-inverse);
}

.message.received .message-bubble {
    background: var(--color-bg-muted);
    color: var(--color-text-primary);
}

.message-sender {
    color: var(--color-text-muted);
    font-family: var(--font-sans);
    font-size: var(--font-size-micro);
}

.message-time {
    color: var(--color-text-muted);
    font-family: var(--font-mono);
    font-size: var(--font-size-micro);
    font-variant-numeric: var(--font-variant-data);
}

/* Delivery status. The four states are now told apart by shape as well as by
   colour: read = double tick, sent = filled dot, sending = hollow ring,
   status unknown = dashed ring. Every state also carries an aria-label. */
.message-status-indicator.is-sent,
.chat-last-status.is-sent {
    color: var(--color-text-muted);
}

.message-status-indicator.is-unread,
.chat-last-status.is-unread {
    color: var(--color-accent);
}

.message-status-indicator.is-read,
.chat-last-status.is-read {
    color: var(--color-success);
}

.message-status-indicator.is-pending,
.chat-last-status.is-pending {
    color: var(--color-text-secondary);
}

.message-status-indicator.is-syncing,
.chat-last-status.is-syncing {
    color: var(--color-text-muted);
}

.message-status-indicator.is-pending .message-status-pulse,
.chat-last-status.is-pending .message-status-pulse {
    box-sizing: border-box;
    width: 9px;
    height: 9px;
    background: transparent;
    border: 1.6px solid currentColor;
}

.message-status-indicator.is-syncing .message-status-pulse,
.chat-last-status.is-syncing .message-status-pulse {
    box-sizing: border-box;
    width: 9px;
    height: 9px;
    background: transparent;
    border: 1.6px dashed currentColor;
}

/* ---------------------------------------------------------------------------
   3. Presence.

   "Online" was #4caf50 (2.71:1 on the light surface) and "offline" was #aaa /
   #666 (3.14:1 on the dark surface). Both now use the contract's success and
   muted tokens, and the online/offline wording stays as the non-colour cue.
   ------------------------------------------------------------------------ */
.member-status.online {
    color: var(--color-success);
}

.member-status.offline {
    color: var(--color-text-muted);
}

.users-list-status.online {
    color: var(--color-success);
}

.users-list-status.offline {
    color: var(--color-text-muted);
}

.online-dot {
    background-color: var(--color-success);
    box-shadow: 0 0 4px var(--color-success);
}

.offline-dot {
    background-color: var(--color-text-muted);
}

.avatar-online::after {
    background: var(--color-success);
    border-color: var(--color-bg-surface);
}

/* ---------------------------------------------------------------------------
   4. Chat list state badge (blocked chats).

   Was rgba(255, 179, 126, …) on #ffcfab — 1.39:1 on the light surface, so the
   badge disappeared in the light theme.
   ------------------------------------------------------------------------ */
.chat-list-state-badge {
    background: var(--color-warning-container);
    color: var(--color-warning);
    font-family: var(--font-sans);
    font-size: var(--font-size-micro);
}

.chat-item-blocked {
    border-color: color-mix(in srgb, var(--color-warning) 32%, var(--color-border-subtle));
}

/* ---------------------------------------------------------------------------
   5. Density floor.

   The web client has no density switcher yet (hq#251 owns it), so the shipped
   comfortable row stays exactly as it is. When the switcher lands, the compact
   variant tightens the row down to the contract floor --density-row-min-height,
   which is 44 px in compact and therefore still a safe tap target.
   ------------------------------------------------------------------------ */
[data-density='compact'] .chat-item {
    min-height: var(--density-row-min-height);
    padding: var(--density-row-padding-y) var(--density-row-padding-x);
}

/* ---------------------------------------------------------------------------
   6. Media frame.

   --color-bg-media is a light surface in .theme-light (canonical contract).
   The video frames themselves keep their own dark background, but the letterbox
   behind a contained video followed the token and turned light. A camera frame
   is media, not canvas: it stays on the dark media surface in both themes.

   --media-frame-surface is not a new colour: it is the canonical dark
   --color-bg-media value (#080c14), pinned here because the light theme value
   of that token is a light canvas.
   ------------------------------------------------------------------------ */
:root {
    --media-frame-surface: #080c14;
}

.call-helper-participant-video,
.call-voice-tile.is-fullscreen .call-voice-tile-media,
.call-voice-tile:fullscreen .call-voice-tile-video,
.call-voice-tile:-webkit-full-screen .call-voice-tile-video,
.call-voice-tile.is-fullscreen .call-voice-tile-video {
    background: var(--media-frame-surface);
}

/* Personal is one quiet workspace, rather than a card above a second toolbar. */
.chat-header.is-personal {
    min-height: 72px;
    margin: 0;
    padding: 14px 20px 6px;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: transparent;
}
.chat-header.is-personal .chat-header-info {
    gap: 12px;
    padding: 0;
    min-width: 0;
    background: transparent;
    cursor: default;
}
.chat-header.is-personal .chat-header-avatar {
    width: 38px;
    height: 38px;
    flex: 0 0 38px;
    border-radius: 12px;
    background: color-mix(in srgb, var(--color-accent) 14%, var(--color-bg-surface));
    color: var(--color-accent);
    box-shadow: none;
}
.chat-header.is-personal .chat-header-avatar .ui-icon { width: 21px; height: 21px; }
.chat-header.is-personal .chat-header-name { font-size: 16px; font-weight: 600; line-height: 1.4; }
.chat-header.is-personal .chat-header-status {
    margin-top: 2px;
    color: var(--color-text-muted);
    font-size: 12px;
    font-weight: 400;
    line-height: 1.4;
}
.chat-header.is-personal .chat-header-actions { gap: 6px; flex: 0 0 auto; }
.chat-header.is-personal #searchBtn {
    min-width: 44px;
    min-height: 44px;
    padding: 10px;
    border: 0;
    border-radius: 10px;
    box-shadow: none;
    background: transparent;
    color: var(--color-text-muted);
}
.chat-header.is-personal #searchBtn:hover { background: var(--color-bg-hover); color: var(--color-text-primary); }
.chat-header.is-personal #searchBtn .chat-header-action-label { display: none; }
.chat-header.is-personal + .chat-sections { padding: 8px 20px 13px; }
@media (max-width: 520px) {
    .chat-header.is-personal { padding: 10px 12px 4px; min-height: 64px; gap: 8px; }
    .chat-header.is-personal .chat-header-info { flex: 1; gap: 9px; }
    .chat-header.is-personal .chat-header-info > div:last-child { min-width: 0; }
    .chat-header.is-personal .chat-header-status { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .chat-header.is-personal + .chat-sections { padding-inline: 12px; }
}
