/**
 * Component Library - Reusable UI Components
 * Purpose: Standardized, accessible, and consistent UI components
 * 
 * This file contains:
 * - Button components and variants
 * - Form controls (inputs, selects, textareas)
 * - Card components
 * - Modal/Dialog components
 * - Alert/Notification components
 * - Loading states
 * - Navigation components
 * 
 * Dependencies: design-system.css
 * 
 * Last Updated: October 19, 2025
 */

/* ========================================================================
   BUTTON COMPONENTS
   ======================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--spacing-2);
  font-family: inherit;
  font-weight: var(--font-medium);
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  vertical-align: middle;
  user-select: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: all var(--transition-fast) var(--ease-out);
  border-radius: var(--radius-lg);
  
  /* Accessibility */
  position: relative;
  overflow: hidden;
}

.btn:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
  box-shadow: var(--focus-ring-shadow);
}

.btn:disabled {
  opacity: var(--opacity-60);
  cursor: not-allowed;
  pointer-events: none;
}

/* Button Sizes */
.btn-xs {
  padding: var(--spacing-1-5) var(--spacing-3);
  font-size: var(--text-xs);
  min-height: 32px;
}

.btn-sm {
  padding: var(--spacing-2) var(--spacing-4);
  font-size: var(--text-sm);
  min-height: 36px;
}

.btn-md {
  padding: var(--spacing-2-5) var(--spacing-5);
  font-size: var(--text-sm);
  min-height: 44px; /* 44px: o 40px antigo ficava 1px abaixo do alvo de toque */
}

.btn-lg {
  padding: var(--spacing-3) var(--spacing-6);
  font-size: var(--text-base);
  min-height: var(--touch-target-min);
}

.btn-xl {
  padding: var(--spacing-4) var(--spacing-8);
  font-size: var(--text-lg);
  min-height: var(--touch-target-recommended);
}

/* Ensure minimum touch targets on mobile */
@media (hover: none) and (pointer: coarse) {
  .btn,
  .btn-xs,
  .btn-sm {
    min-height: var(--touch-target-min);
    min-width: var(--touch-target-min);
    padding: var(--spacing-2-5) var(--spacing-4);
  }
}

/* Material Icons in Buttons - Proper Sizing */
.btn .material-icons {
  font-size: inherit;
  line-height: 1;
}

.btn-xs .material-icons {
  font-size: 1rem; /* 16px */
}

.btn-sm .material-icons {
  font-size: 1.125rem; /* 18px */
}

.btn-md .material-icons,
.btn-lg .material-icons {
  font-size: 1.25rem; /* 20px */
}

.btn-xl .material-icons {
  font-size: 1.5rem; /* 24px */
}

/* Button Variants */
.btn-primary {
  /* oliva da marca: 5.7:1 com branco (WCAG AA) */
  background-color: var(--color-primary-600);
  color: white;
  border-color: var(--color-primary-600);
}

.btn-primary:hover:not(:disabled) {
  background-color: var(--color-primary-700);
  border-color: var(--color-primary-700);
  box-shadow: var(--shadow-hover);
  transform: translateY(-1px);
}

.btn-primary:active:not(:disabled) {
  background-color: var(--color-primary-800);
  box-shadow: var(--shadow-active);
  transform: translateY(0);
}

.btn-secondary {
  background-color: var(--color-secondary-600);
  color: white;
  border-color: var(--color-secondary-600);
}

.btn-secondary:hover:not(:disabled) {
  background-color: var(--color-secondary-700);
  border-color: var(--color-secondary-700);
  box-shadow: var(--shadow-hover);
  transform: translateY(-1px);
}

.btn-success {
  background-color: var(--color-success);
  color: white;
  border-color: var(--color-success);
}

.btn-success:hover:not(:disabled) {
  background-color: var(--color-success-dark);
  border-color: var(--color-success-dark);
  box-shadow: var(--shadow-hover);
  transform: translateY(-1px);
}

.btn-danger {
  background-color: var(--color-error);
  color: white;
  border-color: var(--color-error);
}

.btn-danger:hover:not(:disabled) {
  background-color: var(--color-error-dark);
  border-color: var(--color-error-dark);
  box-shadow: var(--shadow-hover);
  transform: translateY(-1px);
}

.btn-warning {
  background-color: var(--color-warning);
  color: white;
  border-color: var(--color-warning);
}

.btn-warning:hover:not(:disabled) {
  background-color: var(--color-warning-dark);
  border-color: var(--color-warning-dark);
  box-shadow: var(--shadow-hover);
  transform: translateY(-1px);
}

/* Muted (cinza sólido) — ações secundárias como Close */
.btn-muted {
  background-color: var(--color-neutral-200);
  color: var(--color-neutral-700);
  border-color: var(--color-neutral-200);
}

.btn-muted:hover:not(:disabled) {
  background-color: var(--color-neutral-300);
  border-color: var(--color-neutral-300);
}

/* Outline Variants */
.btn-outline {
  background-color: transparent;
  color: var(--color-neutral-700);
  border-color: var(--color-neutral-300);
}

.btn-outline:hover:not(:disabled) {
  background-color: var(--color-neutral-50);
  border-color: var(--color-neutral-400);
}

.btn-outline-primary {
  background-color: transparent;
  color: var(--color-primary);
  border-color: var(--color-primary);
}

.btn-outline-primary:hover:not(:disabled) {
  background-color: var(--color-primary-50);
  color: var(--color-primary-700);
  border-color: var(--color-primary-700);
}

/* Ghost Variants (no border) */
.btn-ghost {
  background-color: transparent;
  color: var(--color-neutral-700);
  border-color: transparent;
}

.btn-ghost:hover:not(:disabled) {
  background-color: var(--color-neutral-100);
}

.btn-ghost-primary {
  background-color: transparent;
  color: var(--color-primary);
  border-color: transparent;
}

.btn-ghost-primary:hover:not(:disabled) {
  background-color: var(--color-primary-50);
  color: var(--color-primary-700);
}

.btn-ghost-secondary {
  background-color: transparent;
  color: var(--color-secondary-600);
  border-color: transparent;
}

.btn-ghost-secondary:hover:not(:disabled) {
  background-color: var(--color-secondary-50);
  color: var(--color-secondary-700);
}

.btn-ghost-success {
  background-color: transparent;
  color: var(--color-success);
  border-color: transparent;
}

.btn-ghost-success:hover:not(:disabled) {
  background-color: var(--color-success-light);
  color: var(--color-success-dark);
}

.btn-ghost-danger {
  background-color: transparent;
  color: var(--color-error);
  border-color: transparent;
}

.btn-ghost-danger:hover:not(:disabled) {
  background-color: var(--color-error-light);
  color: var(--color-error-dark);
}

/* Icon Button */
.btn-icon {
  padding: var(--spacing-2);
  aspect-ratio: 1;
  border-radius: var(--radius-full);
}

.btn-icon .material-icons {
  font-size: 1.25rem;
  margin: 0;
}

/* Loading State */
.btn.loading {
  position: relative;
  color: transparent;
  pointer-events: none;
}

.btn.loading::after {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  top: 50%;
  left: 50%;
  margin-left: -8px;
  margin-top: -8px;
  border: 2px solid currentColor;
  border-radius: 50%;
  border-top-color: transparent;
  animation: spin 0.6s linear infinite;
}

/* Ripple Effect */
.btn-ripple::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.5);
  width: 100px;
  height: 100px;
  margin-top: -50px;
  margin-left: -50px;
  top: 50%;
  left: 50%;
  animation: ripple 0.6s;
  opacity: 0;
  pointer-events: none;
}

.btn-ripple:active::after {
  animation: ripple 0.6s;
}

/* ========================================================================
   FORM COMPONENTS
   ======================================================================== */

/* Base Input Styles */
.input,
.textarea,
.select {
  width: 100%;
  padding: var(--spacing-2-5) var(--spacing-4);
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: var(--font-normal);
  line-height: var(--leading-normal);
  color: var(--color-neutral-800);
  background-color: white;
  border: 1px solid var(--color-neutral-300);
  border-radius: var(--radius-lg);
  transition: all var(--transition-fast) var(--ease-out);
  appearance: none;
}

.input:hover:not(:disabled):not(:focus),
.textarea:hover:not(:disabled):not(:focus),
.select:hover:not(:disabled):not(:focus) {
  border-color: var(--color-neutral-400);
}

.input:focus,
.textarea:focus,
.select:focus {
  outline: none;
  border-color: var(--color-primary-600);
  box-shadow: 0 0 0 3px rgba(92, 107, 74, 0.14);
}

.input:disabled,
.textarea:disabled,
.select:disabled {
  background-color: var(--color-neutral-50);
  color: var(--color-neutral-400);
  cursor: not-allowed;
  opacity: var(--opacity-60);
}

/* Input Sizes */
.input-sm {
  padding: var(--spacing-2) var(--spacing-3);
  font-size: var(--text-xs);
}

.input-md {
  padding: var(--spacing-2-5) var(--spacing-4);
  font-size: var(--text-sm);
}

.input-lg {
  padding: var(--spacing-3) var(--spacing-5);
  font-size: var(--text-base);
}

/* Input States */
.input.error,
.textarea.error,
.select.error {
  border-color: var(--color-error);
}

.input.error:focus,
.textarea.error:focus,
.select.error:focus {
  box-shadow: 0 0 0 3px rgba(176, 67, 59, 0.14);
}

.input.success,
.textarea.success,
.select.success {
  border-color: var(--color-success);
}

.input.success:focus,
.textarea.success:focus,
.select.success:focus {
  box-shadow: 0 0 0 3px rgba(74, 124, 89, 0.14);
}

/* Textarea Specific */
.textarea {
  min-height: 100px;
  resize: vertical;
}

/* Select Specific */
.select {
  padding-right: var(--spacing-10);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%237e786c' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3E%3C/svg%3E");
  background-position: right var(--spacing-2-5) center;
  background-repeat: no-repeat;
  background-size: 1.25rem 1.25rem;
  cursor: pointer;
}

/* Label */
.label {
  display: block;
  margin-bottom: var(--spacing-2);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--color-neutral-700);
}

.label-required::after {
  content: ' *';
  color: var(--color-error);
}

/* Helper Text */
.helper-text {
  display: block;
  margin-top: var(--spacing-1-5);
  font-size: var(--text-xs);
  color: var(--color-neutral-500);
}

.helper-text.error {
  /* error-dark: o red-500 puro ficava em 3.76:1 sobre branco */
  color: var(--color-error-dark);
}

.helper-text.success {
  color: var(--color-success);
}

/* Input Group (Icon + Input) */
.input-group {
  position: relative;
  display: flex;
  align-items: center;
}

.input-group-icon-left {
  position: absolute;
  left: var(--spacing-3);
  color: var(--color-neutral-400);
  pointer-events: none;
}

.input-group .input.has-icon-left {
  padding-left: var(--spacing-10);
}

.input-group-icon-right {
  position: absolute;
  right: var(--spacing-3);
  color: var(--color-neutral-400);
}

.input-group .input.has-icon-right {
  padding-right: var(--spacing-10);
}

/* Checkbox & Radio */
.checkbox,
.radio {
  width: 1rem;
  height: 1rem;
  border: 1px solid var(--color-neutral-300);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.radio {
  border-radius: var(--radius-full);
}

.checkbox:checked,
.radio:checked {
  background-color: var(--color-primary);
  border-color: var(--color-primary);
}

.checkbox:focus-visible,
.radio:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

/* ========================================================================
   CARD COMPONENTS
   ======================================================================== */

.card {
  background-color: white;
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
  border: 1px solid var(--color-neutral-100);
  padding: var(--spacing-6);
  transition: all var(--transition-base) var(--ease-out);
}

.card:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--color-neutral-200);
}

.card-interactive {
  cursor: pointer;
}

.card-interactive:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

.card-interactive:active {
  transform: translateY(0);
  box-shadow: var(--shadow);
}

/* Card Header */
.card-header {
  display: flex;
  align-items: center;
  gap: var(--spacing-3);
  padding-bottom: var(--spacing-4);
  margin-bottom: var(--spacing-4);
  border-bottom: 1px solid var(--color-neutral-200);
}

.card-header-title {
  flex: 1;
  font-size: var(--text-xl);
  font-weight: var(--font-semibold);
  color: var(--color-neutral-900);
}

.card-header-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--radius-lg);
  background-color: var(--color-primary-50);
  color: var(--color-primary);
}

/* Card Body */
.card-body {
  font-size: var(--text-sm);
  color: var(--color-neutral-600);
}

/* Card Footer */
.card-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--spacing-3);
  padding-top: var(--spacing-4);
  margin-top: var(--spacing-4);
  border-top: 1px solid var(--color-neutral-100);
}

/* Card Variants */
.card-flat {
  box-shadow: none;
  border: 1px solid var(--color-neutral-200);
}

.card-elevated {
  box-shadow: var(--shadow-md);
}

.card-elevated:hover {
  box-shadow: var(--shadow-lg);
}

/* Status Accent (borda esquerda)
   O estado do workflow (draft/linked/active) é o primeiro sinal que o
   concierge precisa escanear — uma borda esquerda de 4px carrega isso
   sem adicionar ruído ao rodapé do card. A regra :hover gêmea mantém o
   accent quando a utility Tailwind hover:border-blue-300 repinta todas
   as bordas no hover (este arquivo carrega depois do Tailwind). */
.card-accent-draft { border-left: 4px solid var(--color-warning-400); }
.card-accent-draft:hover { border-left-color: var(--color-warning-400); }

.card-accent-linked { border-left: 4px solid var(--color-info); }
.card-accent-linked:hover { border-left-color: var(--color-info); }

.card-accent-active { border-left: 4px solid var(--color-success); }
.card-accent-active:hover { border-left-color: var(--color-success); }

.card-accent-archived { border-left: 4px solid var(--color-neutral-400); }
.card-accent-archived:hover { border-left-color: var(--color-neutral-400); }

.card-accent-deleted { border-left: 4px solid var(--color-error); }
.card-accent-deleted:hover { border-left-color: var(--color-error); }

.card-accent-pending { border-left: 4px solid var(--color-info-400); }
.card-accent-pending:hover { border-left-color: var(--color-info-400); }

.card-accent-published { border-left: 4px solid #7a5c8e; }
.card-accent-published:hover { border-left-color: #7a5c8e; }

/* ========================================================================
   CHIP / TAG (padrão único de tags e badges)
   Todas as tags do app (status, fonte de dados, conceitos, sync)
   usam este componente + tone dos tokens do design-system.
   ======================================================================== */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 10px;
  border-radius: 9999px;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
}

.chip .material-icons {
  font-size: 14px;
}

.chip--info    { background-color: var(--chip-info-bg);    color: var(--chip-info-fg); }
.chip--success { background-color: var(--chip-success-bg); color: var(--chip-success-fg); }
.chip--warning { background-color: var(--chip-warning-bg); color: var(--chip-warning-fg); }
.chip--danger  { background-color: var(--chip-danger-bg);  color: var(--chip-danger-fg); }
.chip--neutral { background-color: var(--chip-neutral-bg); color: var(--chip-neutral-fg); }
.chip--accent  { background-color: var(--chip-accent-bg);  color: var(--chip-accent-fg); }

/* ========================================================================
   SECTION HEADING (padrão único de título de seção)
   As seções do app usavam duas convenções (text-xl+border vs text-2xl
   sem border) com ícones em cores variadas. Um componente.
   ======================================================================== */

.section-heading {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  font-size: 1.0625rem; /* 17px — título quieto entre card e conteúdo */
  font-weight: var(--font-semibold);
  letter-spacing: -0.01em;
  color: var(--color-neutral-900);
  margin-bottom: var(--spacing-4);
  padding-bottom: var(--spacing-3);
  border-bottom: 1px solid var(--color-neutral-100);
}

.section-heading .material-icons {
  font-size: 20px;
  color: var(--color-primary-600);
}

.section-heading--plain {
  border-bottom: none;
  padding-bottom: 0;
}

/* ========================================================================
   EMPTY STATE (padrão único de estado vazio)
   Variante BEM (.empty-state__*) removida (ago/2026): o emptyStateManager
   e os templates usam o vocabulário hyphenated (.empty-state-icon etc.)
   — as duas convenções coexistiam no mesmo CSS. Definição única abaixo.
   ========================================================================
   ICON BUTTON (padrão único de botão de ícone nas ações dos cards)
   Antes cada card tinha botões próprios com paddings/tons variados.
   ======================================================================== */

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  flex-shrink: 0;
  border-radius: var(--radius-lg);
  background-color: var(--color-neutral-50);
  color: var(--color-neutral-600);
  border: 1px solid var(--color-neutral-200);
  cursor: pointer;
  transition: background-color var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
}

.icon-btn:hover {
  background-color: var(--color-neutral-100);
  color: var(--color-neutral-800);
}

.icon-btn .material-icons {
  font-size: 18px;
}

/* ========================================================================
   UTILITIES ARBITRARY (Tailwind 2 CDN não tem JIT)
   As classes text-[10px]...max-h-[80vh] usadas no markup nunca
   existiram no build CDN do Tailwind 2 — os tamanhos finos pretendidos
   (badges 11px, ícones 14px) nunca aplicaram e os elementos renderizavam
   com tamanhos herdados. Utilities equivalentes aqui.
   ======================================================================== */

.text-\[10px\] { font-size: 10px; }
.text-\[11px\] { font-size: 11px; }
.text-\[14px\] { font-size: 14px; }
.text-\[18px\] { font-size: 18px; }
.text-\[20px\] { font-size: 20px; }
.mt-\[1px\] { margin-top: 1px; }
.w-\[90\%\] { width: 90%; }
.max-w-\[150px\] { max-width: 150px; }
.max-h-\[95vh\] { max-height: 95vh; }
.max-h-\[80vh\] { max-height: 80vh; }

/* ========================================================================
   TOASTS (Toastify)
   Card branco com accent de cor por tipo — mesma linguagem visual dos
   cards de curadoria. Substitui o fundo escuro padrão do Toastify.
   ======================================================================== */

.toastify {
  background: #fff;
  color: var(--color-neutral-800);
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--color-neutral-200);
  border-radius: var(--radius-lg);
  padding: var(--spacing-3) var(--spacing-4);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  max-width: 360px;
}

.toastify .toast-content {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
}

.toastify .toast-content .material-icons {
  font-size: 18px;
  flex-shrink: 0;
}

.toastify.toast-success { border-left: 4px solid var(--color-success); }
.toastify.toast-success .material-icons { color: var(--color-success); }

.toastify.toast-error { border-left: 4px solid var(--color-error); }
.toastify.toast-error .material-icons { color: var(--color-error); }

.toastify.toast-info,
.toastify.toast-warning { border-left: 4px solid var(--color-warning); }
.toastify.toast-info .material-icons,
.toastify.toast-warning .material-icons { color: var(--color-warning); }

/* ========================================================================
   MODAL/DIALOG COMPONENTS
   ======================================================================== */

.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal-backdrop);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--spacing-4);
  background-color: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(4px);
  animation: fadeIn var(--transition-base) var(--ease-out);
}

.modal {
  position: relative;
  z-index: var(--z-modal);
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 32rem;
  max-height: 90vh;
  background-color: white;
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-2xl);
  overflow: hidden;
  animation: slideInUp var(--transition-base) var(--ease-out);
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--spacing-6);
  border-bottom: 1px solid var(--color-neutral-200);
}

.modal-title {
  font-size: var(--text-xl);
  font-weight: var(--font-semibold);
  color: var(--color-neutral-900);
}

.modal-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border: none;
  background-color: transparent;
  color: var(--color-neutral-500);
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.modal-close:hover {
  background-color: var(--color-neutral-100);
  color: var(--color-neutral-700);
}

.modal-body {
  flex: 1;
  padding: var(--spacing-6);
  overflow-y: auto;
}

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--spacing-3);
  padding: var(--spacing-6);
  border-top: 1px solid var(--color-neutral-200);
}

/* Modal Sizes */
.modal-sm { max-width: 24rem; }
.modal-md { max-width: 32rem; }
.modal-lg { max-width: 48rem; }
.modal-xl { max-width: 64rem; }
.modal-full { max-width: calc(100% - var(--spacing-8)); }

/* ========================================================================
   ALERT/NOTIFICATION COMPONENTS
   ======================================================================== */

.alert {
  display: flex;
  gap: var(--spacing-3);
  align-items: flex-start;
  padding: var(--spacing-4);
  border-radius: var(--radius-lg);
  margin-bottom: var(--spacing-4);
  border: 1px solid;
  animation: slideInDown var(--transition-base) var(--ease-out);
}

.alert-icon {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
}

.alert-content {
  flex: 1;
}

.alert-title {
  font-weight: var(--font-semibold);
  margin-bottom: var(--spacing-1);
}

.alert-description {
  font-size: var(--text-sm);
}

.alert-close {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: inherit;
  opacity: var(--opacity-60);
  transition: opacity var(--transition-fast);
}

.alert-close:hover {
  opacity: var(--opacity-100);
}

/* Alert Variants — bordas no tom do tema (ago/2026): os hex do Tailwind
   antigo (#6ee7b7/#fcd34d/#fca5a5) eram os únicos pontos neon do sistema */
.alert-info {
  background-color: var(--color-info-light);
  border-color: var(--color-primary-300);
  color: var(--color-info-dark);
}

.alert-success {
  background-color: var(--color-success-light);
  border-color: var(--color-success-400);
  color: var(--color-success-dark);
}

.alert-warning {
  background-color: var(--color-warning-light);
  border-color: var(--color-warning-400);
  color: var(--color-warning-dark);
}

.alert-error {
  background-color: var(--color-error-light);
  border-color: #d39891; /* tom de borda tijolo (border-red-300) */
  color: var(--color-error-dark);
}

/* ========================================================================
   LOADING STATES
   ======================================================================== */

/* Spinner */
.spinner {
  display: inline-block;
  width: 1rem;
  height: 1rem;
  border: 2px solid var(--color-neutral-200);
  border-radius: 50%;
  border-top-color: var(--color-primary);
  animation: spin 0.6s linear infinite;
}

.spinner-sm { width: 0.75rem; height: 0.75rem; }
.spinner-md { width: 1rem; height: 1rem; }
.spinner-lg { width: 1.5rem; height: 1.5rem; }
.spinner-xl { width: 2rem; height: 2rem; }

/* Skeleton Loader */
.skeleton {
  background: linear-gradient(
    90deg,
    var(--color-neutral-100) 25%,
    var(--color-neutral-200) 50%,
    var(--color-neutral-100) 75%
  );
  background-size: 200% 100%;
  animation: skeleton 1.5s ease-in-out infinite;
  border-radius: var(--radius);
}

.skeleton-text {
  height: 1rem;
  margin-bottom: var(--spacing-2);
}

.skeleton-text:last-child {
  width: 80%;
}

.skeleton-circle {
  border-radius: var(--radius-full);
  aspect-ratio: 1;
}

.skeleton-rect {
  border-radius: var(--radius-lg);
}

/* Progress Bar */
.progress {
  height: 0.5rem;
  background-color: var(--color-neutral-200);
  border-radius: var(--radius-full);
  overflow: hidden;
}

.progress-bar {
  height: 100%;
  background-color: var(--color-primary);
  border-radius: var(--radius-full);
  transition: width var(--transition-base) var(--ease-out);
}

.progress-bar-animated {
  position: relative;
  overflow: hidden;
}

.progress-bar-animated::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(255, 255, 255, 0.3),
    transparent
  );
  animation: progress 1.5s ease-in-out infinite;
}

/* Loading Overlay */
.loading-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal-backdrop);
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(4px);
  animation: fadeIn var(--transition-fast);
}

.loading-overlay-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--spacing-4);
  padding: var(--spacing-8);
  background-color: white;
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-xl);
}

.loading-overlay-spinner {
  width: 3rem;
  height: 3rem;
  border: 3px solid var(--color-neutral-200);
  border-radius: 50%;
  border-top-color: var(--color-primary);
  animation: spin 0.8s linear infinite;
}

.loading-overlay-text {
  font-weight: var(--font-medium);
  color: var(--color-neutral-700);
}

/* ========================================================================
   BADGE COMPONENTS
   ======================================================================== */

/* Variantes .badge-* removidas — dead CSS (zero uso em HTML/JS).
   O padrão único é .chip chip--{tone}. Ago/2026. */

/* ========================================================================
   EMPTY STATE COMPONENTS
   ======================================================================== */

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--spacing-16) var(--spacing-8);
}

.empty-state-icon {
  font-size: 4rem;
  color: var(--color-neutral-300);
  margin-bottom: var(--spacing-4);
}

.empty-state-title {
  font-size: var(--text-xl);
  font-weight: var(--font-semibold);
  color: var(--color-neutral-700);
  margin-bottom: var(--spacing-2);
}

.empty-state-description {
  font-size: var(--text-sm);
  color: var(--color-neutral-500);
  margin-bottom: var(--spacing-6);
  max-width: 28rem;
}

.empty-state-action {
  margin-top: var(--spacing-4);
}

/* ========================================================================
   TOOLTIP COMPONENT
   ======================================================================== */

.tooltip {
  position: absolute;
  z-index: var(--z-tooltip);
  padding: var(--spacing-2) var(--spacing-3);
  font-size: var(--text-xs);
  font-weight: var(--font-medium);
  color: white;
  background-color: var(--color-neutral-900);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--transition-fast);
}

.tooltip.show {
  opacity: 1;
}

.tooltip-arrow {
  position: absolute;
  width: 0.5rem;
  height: 0.5rem;
  background-color: var(--color-neutral-900);
  transform: rotate(45deg);
}

/* ========================================================================
   DIVIDER
   ======================================================================== */

.divider {
  height: 1px;
  background-color: var(--color-neutral-200);
  border: none;
  margin: var(--spacing-6) 0;
}

.divider-vertical {
  width: 1px;
  height: auto;
  align-self: stretch;
  margin: 0 var(--spacing-6);
}

.divider-text {
  display: flex;
  align-items: center;
  gap: var(--spacing-4);
  font-size: var(--text-sm);
  color: var(--color-neutral-500);
  margin: var(--spacing-6) 0;
}

.divider-text::before,
.divider-text::after {
  content: '';
  flex: 1;
  height: 1px;
  background-color: var(--color-neutral-200);
}

/* ========================================================================
   FIXED BOTTOM TOOLBAR COMPONENT
   ======================================================================== */

.toolbar-fixed-bottom {
  display: block; /* Ensure it has a display value when not hidden */
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: var(--z-fixed);
  background-color: white;
  border-top: 2px solid var(--color-primary);
  box-shadow: var(--shadow-xl);
  padding: var(--spacing-4);
}

.toolbar-container {
  max-width: 1280px; /* 7xl */
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-4);
}

.toolbar-info {
  flex: 1;
  font-size: var(--text-sm);
  color: var(--color-neutral-600);
}

.toolbar-info-title {
  font-weight: var(--font-semibold);
}

.toolbar-actions {
  display: flex;
  gap: var(--spacing-2);
  align-items: center;
}

/* Responsive behavior: UMA linha no mobile — Cancel | Save lado a
   lado. O título "Edit Restaurant" não ocupa mais linha própria: o
   contexto do modo já vive no header (mobile-nav-title) e na rota */
@media (max-width: 640px) {
  .toolbar-fixed-bottom {
    padding: 0.5rem 0.75rem;
    padding-bottom: calc(0.5rem + env(safe-area-inset-bottom, 0px));
  }

  .toolbar-container {
    flex-direction: row;
    align-items: center;
    gap: 0.75rem;
  }

  .toolbar-info {
    display: none;
  }

  .toolbar-actions {
    flex: 1;
    gap: 0.75rem;
  }

  .toolbar-actions .btn {
    flex: 1;
  }
}

/* ========================================================================
   CURATION EDITOR MODAL — REMOVIDO (ago/2026)
   O editor por áreas é INLINE (#concepts-section) desde o redesign;
   o modal #curation-editor-modal não existe no DOM (zero referências).
   O bloco tinha até propriedades CSS inválidas (ring:/ring-color:).
   ======================================================================== */

/* ========================================================================
   TAB NAVIGATION COMPONENTS
   ======================================================================== */

.view-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-1);
  padding: var(--spacing-3) var(--spacing-1);
  font-size: var(--text-sm);
  border-bottom: 2px solid transparent;
  font-weight: var(--font-medium);
  color: var(--color-neutral-600);
  background: transparent;
  cursor: pointer;
  transition: all var(--transition-fast) var(--ease-out);
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}

.view-tab:hover:not(.active) {
  color: var(--color-neutral-900);
  border-bottom-color: var(--color-neutral-300);
}

.view-tab.active {
  color: var(--color-primary-600);
  border-bottom-color: var(--color-primary-600);
}

.view-tab:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
  border-radius: var(--radius-sm);
}

.view-tab .material-icons {
  font-size: 1rem;
  vertical-align: middle;
}

/* Tab content areas */
.view-content {
  animation: fadeIn var(--transition-base) var(--ease-out);
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Responsive tabs */
@media (max-width: 768px) {
  .view-tab {
    padding: var(--spacing-3) var(--spacing-2);
    font-size: var(--font-size-sm);
  }
}

/* ========================================================================
   PALETA "CONCIERGE" — COMPONENTES NOVOS (ago/2026)
   ======================================================================== */

/* Painel de seção — substitui a sopa de utilities
   (bg-white rounded-xl shadow-md border-gray-100 hover:shadow-lg)
   que o index.html repetia em cada section. Sombra em tinta quente,
   raio 16px e borda de pedra: o card senta quieto na mesa limestone. */
.panel {
  background: var(--color-surface);
  border: 1px solid var(--color-neutral-200);
  border-radius: var(--radius-2xl);
  box-shadow:
    0 1px 2px rgba(26, 24, 23, 0.04),
    0 8px 24px rgba(26, 24, 23, 0.05);
  transition: box-shadow var(--transition-base) var(--ease-out);
}

.panel:hover {
  box-shadow:
    0 2px 4px rgba(26, 24, 23, 0.05),
    0 14px 34px rgba(26, 24, 23, 0.07);
}

/* Logo da top bar — 48px mobile, 67px em >=640px. O 58px original
   (auditoria, ponto 15) inflava o header sticky junto com o wordmark
   centrado; 48px devolve ~10px de viewport ao editor no mobile.
   Tailwind 2 CDN não tem utilitários arbitrários, então a altura
   exata vive aqui. */
.brand-logo {
  height: 48px;
  width: auto;
}

@media (min-width: 640px) {
  .brand-logo {
    height: 67px;
  }
}

/* Wordmark do header — serif de exibição, como o capture/ usa para
   nomes próprios. Acompanha o logo sem competir com ele. */
.brand-wordmark {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.75rem;
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--color-neutral-900);
}

/* Nome de restaurante nos cards — a assinatura do app: serif de
   exibição (Cormorant Garamond) como verbete de menu; no hover do
   card (grupo) escurece para o oliva da marca. */
.card-restaurant-name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.375rem;
  line-height: 1.25;
  letter-spacing: -0.005em;
  color: var(--color-neutral-900);
  transition: color var(--transition-fast) var(--ease-out);
}

.group:hover .card-restaurant-name {
  color: var(--color-primary-600);
}

/* Badge do tipo no topo dos cards — círculo PERFEITO com o ícone
   centrado de verdade. Antes era um div com p-2 + span inline-block:
   o line-height 1.5 herdado do body criava um strut de baseline de 6px
   embaixo do ícone — círculo oval (34×40) e glifo fora do centro.
   Flex + width/height explícitos eliminam o strut. */
.card-type-badge {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;   /* 36px */
  height: 2.25rem;
  border-radius: 9999px;
  background: rgba(255, 255, 255, 0.9);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  box-shadow: var(--shadow-sm);
}

.card-type-badge .material-icons {
  display: block;
  font-size: 1.125rem;
  line-height: 1;
}

/* Botão de editar dos cards (entity/curation) — era bg-blue-600 sólido
   ("azul berrante"). Oliva-tintado, quieto, no padrão dos icon-btns. */
.card-edit-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 2.5rem;
  width: 100%;
  gap: 0.375rem;
  border-radius: var(--radius-lg);
  background: var(--color-primary-100);
  color: var(--color-primary-800);
  border: 1px solid var(--color-primary-200);
  cursor: pointer;
  transition: background-color var(--transition-fast) var(--ease-out),
    color var(--transition-fast) var(--ease-out),
    border-color var(--transition-fast) var(--ease-out);
}

.card-edit-btn:hover {
  background: var(--color-primary-200);
  border-color: var(--color-primary-300);
}

/* Botão de vínculo do card de curation — View Entity (linkado) ou
   Link Entity (solto), no MESMO espaço e linguagem quieta. */
.card-link-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 2.5rem;
  width: 100%;
  gap: 0.375rem;
  border-radius: var(--radius-lg);
  background: var(--color-neutral-100);
  color: var(--color-neutral-700);
  border: 1px solid var(--color-neutral-200);
  font-size: 0.75rem;
  font-weight: var(--font-medium);
  cursor: pointer;
  transition: background-color var(--transition-fast) var(--ease-out),
    color var(--transition-fast) var(--ease-out),
    border-color var(--transition-fast) var(--ease-out);
}

.card-link-btn:hover {
  background: var(--color-primary-50);
  border-color: var(--color-primary-200);
  color: var(--color-primary-700);
}

/* Véu de hover dos cards — antes um gradiente Tailwind de blue-50/30
   (grupo hover). Agora um tom de oliva a 8%, sutil como o do capture.
   z-index 2: acima do conteúdo (z-1) e do véu OG (z-0), como sempre foi. */
.card-veil {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(to top, transparent, transparent);
  transition: background var(--transition-base) var(--ease-out);
}

.group:hover .card-veil {
  background: linear-gradient(to top, rgba(111, 130, 86, 0.08), transparent);
}

/* Véu de imagem OG — degradê suave com a foto do site do restaurante
   (resolvida em real-time pelo ogImageModule via /api/v3/og-image).
   A máscara é HORIZONTAL: transparente na esquerda (onde mora o texto)
   e vai ganhando opacidade para a direita — a foto não compete com
   nome/localização. O ::before é um wash branco de reforço no topo. */
.card-og-veil {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  opacity: 0;
  transition: opacity 700ms var(--ease-out);
  -webkit-mask-image: linear-gradient(
    to right,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0) 25%,
    rgba(0, 0, 0, 0.65) 55%,
    rgba(0, 0, 0, 1) 100%
  );
  mask-image: linear-gradient(
    to right,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0) 25%,
    rgba(0, 0, 0, 0.65) 55%,
    rgba(0, 0, 0, 1) 100%
  );
}

.card-og-veil::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0.82),
    rgba(255, 255, 255, 0.45) 35%,
    rgba(255, 255, 255, 0) 75%
  );
}

.card-og-veil--visible {
  opacity: 0.38;
}

/* Véu de imagem já conhecida (mapa quente/cache): sem transição — o
   herói do modal re-aplicava o fade de 700ms a cada abertura */
.card-og-veil--instant {
  transition: none;
}

/* Conteúdo do card acima do véu OG (z-0) e abaixo do véu de hover (z-2) */
.entity-card-main {
  position: relative;
  z-index: 1;
}

/* Estabilização mobile: cards rolam no eixo VERTICAL nativo — o pan
   horizontal bloqueado evita o back-swipe acidental do browser sobre
   os cards (o app não tem gestos horizontais próprios) */
.restaurant-card,
[data-entity-id],
.review-card {
  touch-action: pan-y;
}

/* Badge "novo" (padrão newBadge do feedmine): criado/atualizado nas
   últimas 24h — chip discreto sob o badge do tipo, tom aço */
.card-new-badge {
  margin-top: 0.375rem;
  text-align: center;
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--chip-info-fg);
  background: var(--chip-info-bg);
  border-radius: var(--radius-full);
  padding: 0.125rem 0.5rem;
}

/* Véu de FALLBACK — princípio feedmine "cards resolvidos antes de
   aparecer": card sem imagem nunca fica branco vazio; ganha um
   gradiente suave no TOM DO STATUS (placeholder de categoria, como o
   contentTypePlaceholder do feedmine). Gradiente diagonal: presença
   no canto superior direito, dissolve na esquerda (texto). */
.card-og-veil--fallback {
  opacity: 1;
  background-image: linear-gradient(
    135deg,
    var(--og-fallback-a, rgba(126, 120, 108, 0.15)),
    var(--og-fallback-b, rgba(126, 120, 108, 0.02))
  );
  -webkit-mask-image: linear-gradient(
    to bottom left,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0) 40%,
    rgba(0, 0, 0, 0.6) 68%,
    rgba(0, 0, 0, 0.85) 100%
  );
  mask-image: linear-gradient(
    to bottom left,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0) 40%,
    rgba(0, 0, 0, 0.6) 68%,
    rgba(0, 0, 0, 0.85) 100%
  );
}

/* Ícone fantasma do tipo no véu de fallback (padrão
   contentTypePlaceholderImage do feedmine): só visível no fallback,
   posicionado no canto de maior presença da máscara diagonal. */
.card-og-veil__icon {
  display: none;
}
.card-og-veil--fallback .card-og-veil__icon {
  display: block;
  position: absolute;
  top: 10px;
  right: 12px;
  font-size: 56px;
  line-height: 1;
  color: var(--og-fallback-fg, #7e786c);
  opacity: 0.14;
}

/* Tons do fallback por status (mesmo mapeamento semântico do tema:
   draft=bronze, linked=aço, active=garrafa, archived=pedra,
   deleted=tijolo) */
/* Fallback do véu: NEUTRO (pedra) para todos os status — o estado do
   workflow já vive na borda (card-accent-*) e no chip; o fallback da
   imagem é conteúdo, não status. Uma cor só, mais calmo. */
.card-og-veil--fallback {
  --og-fallback-a: rgba(126, 120, 108, 0.13); /* pedra */
  --og-fallback-b: rgba(126, 120, 108, 0.02);
  --og-fallback-fg: #8a8377;
}

/* Menu "⋯" dos cards (source/sync + Delete) — nível operacional
   secundário; posicionado fixo via JS sob o botão */
.card-more-menu {
  position: fixed;
  z-index: 1060;
  min-width: 12rem;
  background: #fff;
  border: 1px solid var(--color-border, #e5e7eb);
  border-radius: 0.75rem;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  padding: 0.375rem;
}

.card-more-menu__item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.5rem 0.625rem;
  font-size: 0.8125rem;
  border-radius: 0.5rem;
  border: none;
  background: none;
  cursor: pointer;
  color: var(--color-text-primary, #111827);
  text-align: left;
}

.card-more-menu__info {
  color: var(--color-text-secondary, #6b7280);
  cursor: default;
}

.card-more-menu__info .material-icons {
  font-size: 1rem;
}

.card-more-menu__danger {
  color: var(--color-error, #b0433b);
}

.card-more-menu__danger:hover {
  background: var(--color-error-light, #f6e2df);
}

.card-more-menu__item:hover:not(.card-more-menu__info) {
  background: var(--color-bg-secondary, #f3f4f6);
}

/* Item ATUAL no menu de status (check à esquerda) */
.card-more-menu__current {
  color: var(--color-primary-700);
  font-weight: var(--font-semibold);
}

/* Read-state do feedmine: cards arquivados/deletados ficam atenuados
   (opacity 0.78) e voltam ao hover — escaneabilidade da lista sem
   perder o conteúdo. */
.card-accent-archived,
.card-accent-deleted {
  opacity: 0.78;
}
.card-accent-archived:hover,
.card-accent-deleted:hover {
  opacity: 1;
}

/* ===================================================================
   EDITOR POR ÁREAS (UX: Identity / Curation / Concepts / Source material)
   ===================================================================
   Mobile: uma coluna, accordions na ordem natural do fluxo.
   Desktop (≥1024px): 2 colunas — editorial (Curation+Concepts) à
   esquerda, contexto factual (Identity+Sources) à direita — e uma
   faixa de âncoras sticky sob o header. */

/* O style.css legado dá overflow:hidden + ripple ::after às sections —
   o overflow quebra o sticky das âncoras do editor; aqui o editor pede
   overflow visível e sem ripple */
#concepts-section {
  overflow: visible;
}

#concepts-section::after {
  display: none;
}

.editor-grid {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

/* No mobile as colunas somem e as áreas viram itens diretos (a ordem
   visual é controlada pelos .editor-area--* abaixo) */
.editor-col-main,
.editor-col-context {
  display: contents;
}

.editor-area {
  scroll-margin-top: 8rem;
}

/* Ferramentas automatizadas (fotos, transcrição, extração) ficam ACIMA
   das listas grandes — a lista de conceitos é a última área do fluxo */
.editor-area--identity { order: 1; }
.editor-area--sources { order: 2; }
.editor-area--curation { order: 3; }
.editor-area--concepts { order: 4; }

.editor-section-heading {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-sans, 'DM Sans', sans-serif);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-text-secondary, #6b7280);
  padding-bottom: 0.5rem;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--color-border, #e5e7eb);
}

.editor-section-heading > .material-icons {
  font-size: 1rem;
  color: var(--color-primary, #6f8256);
}

/* Botão do accordion (mobile) — desktop esconde, mas o estado
   colapsado sobrevive à rotação */
.editor-section-toggle {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  min-height: 44px; /* touch target mínimo */
  border: none;
  background: transparent;
  border-radius: 0.375rem;
  color: var(--color-text-secondary, #6b7280);
  cursor: pointer;
}

.editor-section-toggle:hover {
  background: var(--color-bg-secondary, #f3f4f6);
}

.editor-section-toggle .material-icons {
  transition: transform 0.2s ease;
}

.editor-area.is-collapsed .editor-section-toggle .material-icons {
  transform: rotate(180deg);
}

.editor-area.is-collapsed .editor-section-body {
  display: none;
}

/* Faixa de âncoras do editor (desktop apenas) */
#edit-section-nav {
  display: none;
  align-items: center;
  gap: 0.25rem;
  padding: 0.25rem 0 0.5rem;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--color-border, #e5e7eb);
  position: sticky;
  top: 4.25rem;
  background: var(--color-bg-primary, #ffffff);
  z-index: 30;
}

.edit-nav-link {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--color-text-secondary, #6b7280);
  padding: 0.375rem 0.625rem;
  border-radius: 0.375rem;
  text-decoration: none;
  white-space: nowrap;
}

.edit-nav-link:hover {
  color: var(--color-text-primary, #111827);
  background: var(--color-bg-secondary, #f3f4f6);
}

@media (min-width: 1024px) {
  #edit-section-nav {
    display: flex;
  }

  .editor-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.62fr) minmax(0, 1fr);
    gap: 1.5rem;
    align-items: start;
  }

  .editor-col-main {
    display: block;
    grid-column: 1;
    grid-row: 1;
  }

  .editor-col-context {
    display: block;
    grid-column: 2;
    grid-row: 1;
  }

  .editor-section-toggle {
    display: none;
  }

  /* Estado colapsado no mobile não pode esconder conteúdo no desktop */
  .editor-area.is-collapsed .editor-section-body {
    display: block;
  }
}

/* Contador de palavras da descrição (o limite de verdade é por
   palavras; bronze quando estoura) */
.description-word-count {
  margin-left: 0.5rem;
  font-size: 0.75rem;
  font-weight: 500;
  /* neutral-500 (AA): o text-tertiary/neutral-400 antigo ficava em
     ~2.6:1 sobre branco — ilegível no contador */
  color: var(--color-neutral-500, #6f6a64);
}

.description-word-count--over {
  color: var(--color-warning, #9a5b1f);
  font-weight: 700;
}

/* ===================================================================
   FILTROS DA COLEÇÃO (Search + Status visíveis; refinamentos em
   bottom sheet com chips)
   =================================================================== */

.filters-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
}

.filters-bar__search {
  flex: 1 1 14rem;
  min-width: 0;
}

.filters-bar__status {
  flex: 0 0 auto;
  min-width: 8rem;
}

.filters-toggle {
  flex: 0 0 auto;
}

.filters-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.25rem;
  height: 1.25rem;
  padding: 0 0.25rem;
  margin-left: 0.25rem;
  border-radius: 999px;
  background: var(--color-primary, #6f8256);
  color: #fff;
  font-size: 0.6875rem;
  font-weight: 700;
}

.filters-sheet-label {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-text-secondary, #6b7280);
  margin-bottom: 0.25rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.filters-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin-bottom: 1rem;
}

.filters-chips:empty {
  display: none;
}

.filters-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-info, #3d5a80);
  background: var(--color-info-light, #e3eaf2);
  border: 1px solid transparent;
  padding: 0.25rem 0.5rem 0.25rem 0.625rem;
  border-radius: 999px;
  cursor: pointer;
}

.filters-chip:hover {
  border-color: var(--color-info, #3d5a80);
}

.filters-chip .material-icons {
  font-size: 0.875rem;
}

/* Saved views (auditoria UX, ponto 20): presets de escopo para operação
   em volume — chips neutros que marcam o ativo com oliva (a cor da ação
   principal), nunca um arco-íris de estados. */
.saved-views {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
}

.saved-view-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-text-secondary, #6b7280);
  background: transparent;
  border: 1px solid var(--color-border, #e5e7eb);
  padding: 0.25rem 0.625rem;
  border-radius: 999px;
  cursor: pointer;
  transition:
    color var(--transition-fast) var(--ease-out),
    border-color var(--transition-fast) var(--ease-out),
    background-color var(--transition-fast) var(--ease-out);
}

.saved-view-chip:hover {
  border-color: var(--color-text-secondary, #6b7280);
}

.saved-view-chip:focus-visible {
  outline: 2px solid var(--color-primary-500, #6f8256);
  outline-offset: 2px;
}

.saved-view-chip.is-active {
  color: #fff;
  background: var(--color-primary, #6f8256);
  border-color: var(--color-primary, #6f8256);
}

/* Onboarding pós-auth (auditoria UX, ponto 22): faixa de boas-vindas da
   primeira entrada — papel limestone com fio oliva à esquerda; some
   para sempre no dismiss. Não é wizard: só nomes de verbos. */
.onboarding-welcome {
  margin-bottom: 1.5rem;
  background: var(--color-bg-secondary, #faf8f4);
  border: 1px solid var(--color-border, #e5e7eb);
  border-left: 3px solid var(--color-primary, #6f8256);
  border-radius: 0.75rem;
  padding: 1rem 1.25rem;
}

.onboarding-welcome__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1.5rem;
}

.onboarding-welcome__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.125rem;
  color: var(--color-neutral-900);
  margin-bottom: 0.125rem;
}

.onboarding-welcome__text {
  font-size: 0.875rem;
  color: var(--color-text-secondary, #6b7280);
  max-width: 52ch;
}

.onboarding-welcome__actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
}

/* Entrada de nova curadoria por plataforma: "+ New Curation" no header
   (desktop); o FAB flutuante fica só no mobile, onde corresponde ao
   ambiente de uso (gravou/fotografou no restaurante) */
#new-curation-btn {
  display: none;
}

/* FAB sempre visível: escondê-lo por largura (ou ponteiro) tirou o
   gravador de aparelhos touch com viewport >=641px — bisect em prod
   (2026-08-16) apontou essa regra como o pepino. O botão desktop
   #new-curation-btn fica oculto (base display:none) e o FAB é a
   entrada única de gravação em qualquer tela. */

/* Variante desktop do bottom sheet de filtros: painel flutuante no
   canto inferior direito, não folha de tela cheia */
@media (min-width: 1024px) {
  .bottom-sheet {
    left: auto;
    right: 1.5rem;
    bottom: 1.5rem;
    width: 24rem;
    max-height: 70vh;
    border-radius: var(--radius-xl, 1rem);
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.14);
  }
}

/* ══════════════════════════════════════════════════════════════════
   Detalhes (modais de review/entity) — a linguagem dos cards levada
   às páginas de detalhe: véu OG no herói (mesmo pipeline do
   ogImageModule), painéis brancos sobre limestone, eyebrows com
   ícones, ações reais (maps/tel/mailto). Classes usadas por
   uiManager.handleViewReviewDetails e entityModule.showEntityDetails.
   ══════════════════════════════════════════════════════════════════ */
.detail-sheet {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

/* Herói: o véu OG vira a faixa de abertura do modal. Máscara invertida
   (visível em cima, dissolve em baixo) + scrim discreto para os fatos
   (rating/preço/cuisine) legíveis sobre a imagem. */
.detail-hero {
  position: relative;
  /* Herói generoso (2026-08-16): a foto é a estrela do modal — antes o
     banner mínimo de 7.5rem + máscaras fazia a imagem parecer ruído */
  min-height: clamp(11rem, 34vh, 16rem);
  border-radius: var(--radius-lg, 0.5rem);
  overflow: hidden;
  background-color: var(--color-primary-50, #f1f3ec);
  display: flex;
  align-items: flex-end;
}

.detail-hero .card-og-veil {
  /* Foto PLENA no herói: sem máscara de fade e sem o wash branco dos
     cards — a imagem cobre o banner inteiro, nítida. O véu degradê
     continua só nos cards da lista. */
  -webkit-mask-image: none;
  mask-image: none;
  opacity: 1;
  transition: opacity 240ms var(--ease-out);
}

.detail-hero .card-og-veil::before {
  /* o wash branco de legibilidade dos cards não pertence ao herói */
  background: none;
}

.detail-hero .card-og-veil--visible {
  opacity: 1;
}

/* Fallback do herói (sem imagem): pedra com o ícone do tipo CENTRADO —
   presença calma no banner grande em vez do canto decorado dos cards */
.detail-hero .card-og-veil--fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  background-image: radial-gradient(
    ellipse 80% 60% at 50% 40%,
    rgba(126, 120, 108, 0.12),
    rgba(126, 120, 108, 0.03)
  );
  -webkit-mask-image: none;
  mask-image: none;
}

.detail-hero .card-og-veil--fallback .card-og-veil__icon {
  position: static;
  font-size: 4.5rem;
  opacity: 0.16;
}

.detail-hero__facts {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  width: 100%;
  padding: 2rem 1.25rem 1rem;
  background: linear-gradient(to top, rgba(38, 33, 26, 0.72) 0%, rgba(38, 33, 26, 0.25) 55%, rgba(38, 33, 26, 0) 100%);
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}

/* Meta (review): mesma faixa de fatos, sem imagem — tom de papel */
.detail-hero__facts--meta {
  position: static;
  background: none;
  color: inherit;
  padding: 0;
  width: auto;
}

.detail-hero__rating {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: var(--text-base, 1rem);
}
.detail-hero__rating .material-icons {
  color: #ffd97a;
  font-size: 1.125rem;
}

.detail-hero__price {
  font-size: var(--text-base, 1rem);
  font-weight: 600;
  letter-spacing: 0.05em;
}

/* Faixa de fotos da review */
.detail-photos {
  display: flex;
  gap: 0.5rem;
  overflow-x: auto;
  padding-bottom: 0.25rem;
}
.detail-photos__img {
  height: 7rem;
  border-radius: var(--radius-md, 0.375rem);
  object-fit: cover;
  border: 1px solid var(--color-neutral-300, #d9d2c6);
  flex-shrink: 0;
}

/* Painel: seção branca sobre o limestone do modal */
.detail-panel {
  background: #fff;
  border: 1px solid var(--color-neutral-300, #d9d2c6);
  border-radius: var(--radius-lg, 0.5rem);
  padding: 1rem 1.125rem;
}
.detail-panel--dim {
  background: transparent;
  border-style: dashed;
}
.detail-panel--notes {
  padding: 0.875rem 1rem;
}

/* Eyebrow: rótulo de seção com ícone — a hierarquia do modal */
.detail-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin: 0 0 0.5rem;
  font-size: var(--text-xs, 0.75rem);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-neutral-500, #6f6a64);
}
.detail-eyebrow .material-icons {
  font-size: 1rem;
  color: var(--color-primary-600, #5c6b4a);
}

.detail-text {
  margin: 0 0 0.25rem;
  font-size: var(--text-sm, 0.875rem);
  color: var(--color-neutral-800, #2e2b26);
  line-height: 1.5;
}
.detail-sub {
  margin: 0;
  font-size: var(--text-xs, 0.75rem);
  color: var(--color-neutral-500, #6f6a64);
}
.detail-coords {
  margin: 0.5rem 0 0;
  font-size: var(--text-xs, 0.75rem);
  color: var(--color-neutral-400, #a9a193);
  font-variant-numeric: tabular-nums;
}
.detail-actions {
  margin-top: 0.625rem;
}

/* Links de contato reais (tel/mailto/site) */
.detail-links {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
}
.detail-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  width: fit-content;
  font-size: var(--text-sm, 0.875rem);
  color: var(--color-primary-700, #4a573c);
  text-decoration: none;
}
.detail-link:hover {
  text-decoration: underline;
}
.detail-link .material-icons {
  font-size: 1.125rem;
  color: var(--color-primary-600, #5c6b4a);
}

/* Transcrição */
.detail-transcript {
  background: var(--color-bg, #f5f2ec);
  border: 1px solid var(--color-neutral-300, #d9d2c6);
  border-radius: var(--radius-md, 0.375rem);
  padding: 0.875rem 1rem;
  font-size: var(--text-sm, 0.875rem);
  color: var(--color-neutral-600, #5f5a4f);
  line-height: 1.6;
  white-space: pre-wrap;
}
.detail-toggle {
  margin-top: 0.5rem;
  font-size: var(--text-xs, 0.75rem);
  font-weight: 600;
  color: var(--color-primary-600, #5c6b4a);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.detail-toggle:hover {
  text-decoration: underline;
}

/* Notas (públicas/privadas) */
.detail-note {
  border-radius: var(--radius-md, 0.375rem);
  padding: 0.75rem 0.875rem;
  font-size: var(--text-sm, 0.875rem);
  line-height: 1.6;
  white-space: pre-wrap;
}
.detail-note--public {
  background: #fdf6e7;
  border: 1px solid #f0e3c0;
  color: #5c4f2d;
}
.detail-note--private {
  background: var(--color-bg, #f5f2ec);
  border: 1px solid var(--color-neutral-300, #d9d2c6);
  color: var(--color-neutral-600, #5f5a4f);
}

/* Curadoria vinculada (entity): linhas clicáveis */
.detail-curation-list {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
}
.detail-curation-row {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  width: 100%;
  text-align: left;
  background: var(--color-bg, #f5f2ec);
  border: 1px solid var(--color-neutral-300, #d9d2c6);
  border-radius: var(--radius-md, 0.375rem);
  padding: 0.625rem 0.75rem;
  cursor: pointer;
}
.detail-curation-row:hover {
  border-color: var(--color-primary-300, #afb996);
}
.detail-curation-row__name {
  display: block;
  font-size: var(--text-sm, 0.875rem);
  font-weight: 600;
  color: var(--color-neutral-800, #2e2b26);
}
.detail-curation-row__curator {
  display: block;
  font-size: var(--text-xs, 0.75rem);
  color: var(--color-neutral-500, #6f6a64);
}
.detail-curation-row__go {
  margin-left: auto;
  font-size: 1.125rem;
  color: var(--color-neutral-400, #a9a193);
}

/* Metadata dim (entity) */
.detail-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.375rem;
  font-size: var(--text-xs, 0.75rem);
  color: var(--color-neutral-500, #6f6a64);
}
.detail-meta__dot {
  color: var(--color-neutral-300, #d9d2c6);
}
.detail-meta__id {
  font-variant-numeric: tabular-nums;
}

/* Rodapé de ações do card em VIDRO FOSCO (pedido do usuário, padrão
   feedmine): o véu OG do card passa por trás desfocado — substitui o
   banner branco sólido dos botões inferiores */
.card-footer-glass {
  background: rgba(255, 255, 255, 0.72);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

/* Paginação: mobile EMPILHA (resumo em cima, controles embaixo) em
   vez de apertar tudo numa linha — o flex-row quebrava em 2-3 linhas
   de texto no aparelho */
@media (max-width: 640px) {
  .pagination-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.5rem;
  }
}

/* ===================================================================
   REDESIGN COLEÇÃO (ago/2026)
   ===================================================================
   Tela "My Collection" como experiência mobile intencional:
   header compacto, cabeçalho editorial, tabs full-width, controles
   densos e cards horizontais com thumbnail explícita (a foto deixa
   de ser fundo). Escala de espaçamento: 4/8/12/16/24/32 (tokens
   --spacing-*). Identidade: mesa limestone + oliva funcional +
   Cormorant para nomes/títulos.

   Convenção de override: as regras abaixo vêm DEPOIS dos blocos
   legados deste arquivo e vencem empates de especificidade; IDs são
   usados onde o JS reescreve as classes (ex.: #view-sync-activity).
   =================================================================== */

/* ── Header ──
   Mobile: [logo Lotier] [Collector centrado] [sync][avatar ▼].
   O wordmark sai do fluxo e centraliza de verdade (transform) —
   o flex space-between alinharia pelo texto, não pela marca. */

.header-bar {
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-neutral-200);
  margin-bottom: var(--spacing-3);
  margin-left: -1rem;
  margin-right: -1rem;
  /* padding vertical ZERO de propósito: o style.css legado dá
     padding 1.5rem/2rem ao elemento `header` — a classe vence o
     elemento e devolve a altura compacta ao mobile E ao desktop */
  padding: 0 1rem;
}

.header-bar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-3);
  padding-top: calc(var(--spacing-1) + var(--safe-area-inset-top));
  padding-bottom: var(--spacing-1);
}

/* Slots laterais com a MESMA largura (flex: 1 1 0), e não com largura
   ditada pelo conteúdo. São duas consequências, as duas pedidas:

   1. O wordmark fica no centro EXATO do container (= centro da viewport,
      porque #app é mx-auto e o padding do header é simétrico). Com
      `flex-shrink: 0` + space-between, o título era centralizado no vão
      ENTRE os slots, o que o deslocava em (largura_esq − largura_dir) / 2.
   2. O título não se move mais enquanto o resto carrega: #sync-status-header
      e #user-profile-header são preenchidos por JS depois do login
      (curatorProfile.js, syncStatusModule.js), e antes disso mediam 0px —
      era isso que jogava o título para a direita e o fazia "pular" quando
      sync/avatar apareciam. Agora a largura do slot independe do conteúdo. */
.header-bar__brand {
  display: flex;
  align-items: center;
  flex: 1 1 0;
  min-width: 0;
}

.header-bar__actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--spacing-1);
  flex: 1 1 0;
  min-width: 0;
}

/* Logo menor no mobile (48→30px) devolve ~20px de viewport */
.header-bar .brand-logo {
  height: 30px;
}

/* Wordmark centralizado só no mobile; desktop = à esquerda junto
   do logo (estrutura original preservada). Especificidade de duas
   classes vence o bloco legado do mobile-enhancements.css, que
   ESCONDIA o wordmark abaixo de 400px — no redesign ele permanece
   (é o título central do header pedido); trunca com ellipsis em vez
   de competir com sync/perfil. */
@media (max-width: 639px) {
  .header-bar__inner {
    position: relative;
  }

  .header-bar__inner .brand-wordmark {
    display: block;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    max-width: 38%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 1.25rem;
  }

  /* Sync: só ícone (o SyncStatusModule já esconde o texto no mobile —
     aqui o ícone compacta e o alvo de toque continua ≥32px) */
  #sync-status-header .material-icons {
    font-size: 1.25rem;
  }

  #sync-status-header button {
    padding: 0.25rem 0.375rem;
    min-height: 2rem;
  }

  /* Avatar 32px + chevron quieto; botão com menos gordura vertical */
  #user-profile-header #user-profile-button {
    padding: 0.125rem 0.25rem;
    gap: 0.125rem;
  }

  #user-profile-header #user-profile-button img,
  #user-profile-header #user-profile-button .avatar-fallback {
    width: 2rem !important;
    height: 2rem !important;
    font-size: 0.75rem !important;
  }

  #user-profile-header #user-profile-button .material-icons {
    font-size: 1.25rem;
    margin-left: 0;
  }
}

/* Telas muito estreitas: wordmark um passo menor para nunca encostar
   no cluster da direita (testado em 320px) */
@media (max-width: 359px) {
  .header-bar__inner .brand-wordmark {
    font-size: 1.125rem;
  }
}

/* Desktop: header volta às margens do container */
@media (min-width: 640px) {
  .header-bar {
    margin-left: 0;
    margin-right: 0;
    padding-left: 0;
    padding-right: 0;
    /* width: auto neutraliza o `width: calc(100% + 2rem)` do bloco legado
       `header` em style.css:963. Aquele bloco está em @media (max-width: 640px)
       — INCLUSIVO — e este em (min-width: 640px): os dois casam em exatamente
       640px de viewport. Zerar só margin/padding deixava a barra 32px mais
       larga que o container, ancorada à esquerda, e o wordmark saía 16px à
       direita do centro da viewport nesse único ponto (medido no Chrome). */
    width: auto;
  }

  .header-bar__inner {
    padding-top: var(--spacing-2);
    padding-bottom: var(--spacing-2);
  }

  .header-bar .brand-logo {
    height: 67px;
  }

  #user-profile-header #user-profile-button {
    gap: var(--spacing-2);
  }
}

/* ── Cabeçalho editorial da seção ── */

.page-head {
  display: flex;
  align-items: center;
  gap: var(--spacing-3);
  margin-bottom: var(--spacing-4);
}

.page-head__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  flex-shrink: 0;
  border-radius: 9999px;
  background: var(--color-primary-50);
  border: 1px solid var(--color-primary-100);
  color: var(--color-primary-700);
}

.page-head__icon .material-icons {
  display: block;
  font-size: 1.375rem;
  line-height: 1;
}

.page-head__text {
  flex: 1;
  min-width: 0;
}

.page-head__title {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--color-neutral-900);
}

.page-head__subtitle {
  font-size: var(--text-xs);
  color: var(--color-neutral-500);
  margin-top: 0.125rem;
}

/* Subtítulo some em telas extremamente estreitas (≤430px) */
@media (max-width: 430px) {
  .page-head__subtitle {
    display: none;
  }
}

/* Pill de sync em atividade — estilizada por ID porque o JS
   (updateSyncActivityIndicator) RESETA as classes a cada update */
/* Overlay independente, fora do fluxo: fixo no canto inferior esquerdo
   (o FAB ocupa o direito) e com max-width que respeita a área do FAB.
   O posicionamento fica no seletor de ID DE PROPÓSITO — updateSyncActivityIndicator()
   (uiManager.js:534) faz `className = ''` a cada atualização e recria só as
   utilitárias de cor/espaçamento, então qualquer classe de posição seria
   apagada no primeiro sync; a regra de ID sobrevive ao wipe.
   pointer-events: none porque é puramente informativo e não deve capturar
   cliques do conteúdo por baixo. */
#view-sync-activity {
  font-size: var(--text-xs);
  padding: 0.25rem 0.625rem;
  border-radius: var(--radius-full);
  position: fixed;
  left: 1rem;
  bottom: calc(1rem + var(--safe-area-inset-bottom, 0px));
  z-index: 45;
  max-width: calc(100vw - 6.5rem);
  box-shadow: var(--shadow-md);
  pointer-events: none;
}

/* ── Painel da coleção ── */

.collection-panel {
  padding: var(--spacing-3);
  margin-bottom: var(--spacing-6);
}

@media (min-width: 640px) {
  .collection-panel {
    padding: var(--spacing-5);
  }
}

/* ── Tabs: área inteira clicável, underline oliva na ativa ── */

.view-tabs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--spacing-1);
  border-bottom: 1px solid var(--color-neutral-200);
  margin-bottom: var(--spacing-3);
}

.view-tabs .view-tab {
  justify-content: center;
  height: 2.75rem; /* 44px — alvo de toque */
  padding: 0;
  gap: 0.375rem;
  margin-bottom: -1px; /* underline sobre a linha da nav */
  border-bottom-width: 2px;
  font-size: var(--text-sm);
}

.view-tabs .view-tab.active {
  color: var(--color-primary-700);
  font-weight: var(--font-semibold);
}

.view-tabs .view-tab .material-icons {
  font-size: 1.0625rem;
}

/* Linha de estados loading/vazio (spans gerenciados pelo uiManager —
   ficam ocultos quando a paginação mostra a contagem) */
.view-counts {
  margin-bottom: var(--spacing-2);
  font-size: var(--text-xs);
  color: var(--color-neutral-500);
}

/* ── Barra de filtros: search + status lado a lado ── */

.collection-filters {
  margin-bottom: var(--spacing-2);
}

.filters-bar {
  gap: var(--spacing-2);
}

.filters-bar__search {
  flex: 1 1 10rem;
}

.filters-bar__status {
  min-width: 7.25rem;
}

/* Altura consistente e raio de input (44px mobile / 40px desktop) */
.filters-bar .input,
.filters-bar .select {
  height: 2.75rem;
  border-radius: var(--radius-input);
  border-color: var(--color-neutral-200);
  font-size: var(--text-sm);
}

@media (min-width: 640px) {
  .filters-bar .input,
  .filters-bar .select {
    height: 2.5rem;
  }
}

/* Search — a lupinha foi REMOVIDA (ago/2026): ficava por cima do
   placeholder em algumas larguras; o campo limpo lê melhor */
.search-field {
  position: relative;
}

.search-field__input::placeholder {
  color: var(--color-neutral-400);
}

/* Botão Filters compacto com contador discreto */
.filters-bar .filters-toggle {
  height: 2.75rem;
  padding: 0 0.75rem;
  border-radius: var(--radius-input);
  font-size: var(--text-sm);
  gap: 0.375rem;
}

@media (min-width: 640px) {
  .filters-bar .filters-toggle {
    height: 2.5rem;
  }
}

/* ── Saved views: chips com ícone, scroll horizontal ── */

.saved-views {
  flex-wrap: nowrap;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  gap: var(--spacing-2);
  padding: 0.125rem 0; /* respiro para o focus ring */
}

.saved-views::-webkit-scrollbar {
  display: none;
}

.saved-view-chip {
  flex: 0 0 auto;
  height: 2.375rem; /* 38px */
  padding: 0 0.75rem;
  gap: 0.375rem;
  font-size: 0.8125rem;
  white-space: nowrap;
  background: var(--color-surface);
}

/* Duas classes vencem o seletor [type="button"] do bloco mobile
   (min-height/padding 44px globais) — mesma especificidade perderia
   por ordem de carregamento */
.saved-views .saved-view-chip {
  min-height: 2.375rem; /* 38px */
  padding: 0 0.75rem;
}

.saved-view-chip .material-icons {
  font-size: 1rem;
  color: var(--color-neutral-400);
  transition: color var(--transition-fast) var(--ease-out);
}

.saved-view-chip:hover .material-icons {
  color: var(--color-neutral-600);
}

/* Estado selecionado: oliva-soft (tom claro), não bloco sólido —
   "selected state claro" do redesign; o oliva sólido anterior
   competia com o botão Edit por atenção */
.saved-view-chip.is-active {
  color: var(--color-primary-800);
  background: var(--color-primary-50);
  border-color: var(--color-primary-300);
}

.saved-view-chip.is-active .material-icons {
  color: var(--color-primary-700);
}

/* ── Grade da coleção: 1 → 2 → 3 (+4 para entities em telas largas) ── */

.collection-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--spacing-3);
}

@media (min-width: 768px) {
  .collection-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1280px) {
  .collection-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 1536px) {
  .collection-grid--entities {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* ── Paginação compacta ── */

.collection-pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-2);
  padding: var(--spacing-2) var(--spacing-3);
  margin-bottom: var(--spacing-3);
  background: var(--color-neutral-50);
  border: 1px solid var(--color-neutral-200);
  border-radius: var(--radius-input);
  font-size: var(--text-xs);
  color: var(--color-neutral-600);
}

.collection-pagination__summary {
  white-space: nowrap;
}

.collection-pagination__summary strong {
  font-weight: var(--font-semibold);
  color: var(--color-neutral-800);
}

.collection-pagination__controls {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin-left: auto;
}

.collection-pagination__page {
  font-weight: var(--font-medium);
  color: var(--color-neutral-700);
  white-space: nowrap;
  padding: 0 0.125rem;
}

.collection-pagination__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem; /* 32px — compacto; touch target ok (espaçamento ao redor) */
  height: 2rem;
  min-width: 2rem; /* vence o min-width 44px global do mobile */
  min-height: 2rem; /* vence o min-height 44px global do mobile */
  padding: 0;
  border-radius: var(--radius-input);
  border: 1px solid var(--color-neutral-200);
  background: var(--color-surface);
  color: var(--color-neutral-700);
  cursor: pointer;
  transition: background-color var(--transition-fast) var(--ease-out),
    border-color var(--transition-fast) var(--ease-out);
}

.collection-pagination__btn:hover:not(:disabled) {
  background: var(--color-neutral-100);
  border-color: var(--color-neutral-300);
}

.collection-pagination__btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.collection-pagination__btn:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

.collection-pagination__btn .material-icons {
  font-size: 1.125rem;
}

/* ── Card da coleção ──
   Horizontal: thumbnail explícita à esquerda (foto como OBJETO,
   não mais como fundo), info editorial no meio, rodapé de ações.
   A foto não compete mais com o texto — a legibilidade não depende
   de máscaras. */

.collection-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border: 1px solid var(--color-neutral-200);
  border-radius: var(--radius-card);
  box-shadow: 0 1px 2px rgba(26, 24, 23, 0.04);
  overflow: hidden;
  transition: box-shadow var(--transition-base) var(--ease-out),
    border-color var(--transition-base) var(--ease-out);
}

.collection-card:hover {
  border-color: var(--color-neutral-300);
  box-shadow: 0 4px 14px rgba(26, 24, 23, 0.07);
}

/* Área foto + info */
.collection-card__main {
  display: flex;
  align-items: stretch;
  gap: var(--spacing-3);
  padding: var(--spacing-3);
  flex: 1;
  min-width: 0;
}

/* Thumbnail explícita: 110px mobile, 96px em telas muito estreitas,
   150px ≥640. object-fit: cover + fallback de gradiente pedra com
   ícone do tipo (card nunca fica com mídia vazia). */
.collection-card__media {
  position: relative;
  flex: 0 0 6.875rem;
  align-self: stretch;
  min-height: 6.875rem;
  border-radius: var(--radius-card-inner);
  overflow: hidden;
  background: var(--color-neutral-100);
}

@media (max-width: 359px) {
  .collection-card__media {
    flex-basis: 6rem;
    min-height: 6rem;
  }
}

@media (min-width: 640px) {
  .collection-card__media {
    flex-basis: 9.375rem;
    min-height: 9.375rem;
  }
}

.collection-card__thumb {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 500ms var(--ease-out);
}

.collection-card__thumb.is-loaded {
  opacity: 1;
}

/* Imagem já conhecida (mapa quente/cache): sem transição de 500ms —
   o fade sobre blob reutilizado virava piscada a cada re-render */
.collection-card__thumb.is-loaded--instant {
  transition: none;
}

.collection-card__thumb-fallback {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Placeholder oficial (ago/2026): imagem da marca em vez do gradiente
     pedra + ícone do tipo — cobre TODA ausência de imagem no card. O
     img real da foto (ogImageModule) cobre este fundo quando carrega. */
  background-image: url('../images/placeholder_card.jpeg');
  background-size: cover;
  background-position: center;
  color: var(--color-neutral-400);
  transition: opacity 300ms var(--ease-out);
}

/* O ícone do tipo virou decoração inerte — o placeholder oficial
   substitui o glyph; mantido no DOM por compatibilidade dos testes */
.collection-card__thumb-fallback .material-icons {
  font-size: 2rem;
  opacity: 0;
}

.collection-card__thumb.is-loaded ~ .collection-card__thumb-fallback {
  opacity: 0;
}

/* Corpo: nome serif + badges + metadata */
.collection-card__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
}

.collection-card__title-row {
  display: flex;
  align-items: flex-start;
  gap: var(--spacing-2);
}

.collection-card__title-row .card-restaurant-name {
  flex: 1;
  min-width: 0;
  margin: 0;
  padding: 0;
  font-size: 1.25rem;
}

.collection-card__badges {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  flex-shrink: 0;
}

/* Badge do tipo menor e assentado no branco do card */
.collection-card .card-type-badge {
  width: 2rem;
  height: 2rem;
  background: var(--color-neutral-50);
  border: 1px solid var(--color-neutral-200);
  box-shadow: none;
}

.collection-card .card-type-badge .material-icons {
  font-size: 1rem;
}

/* Badge de source (▣ Excel Import Script) — tom neutro, ícone do
   SourceUtils. Fonte única de origem visível no card. */
.collection-source-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  align-self: flex-start;
  font-size: 0.6875rem;
  font-weight: var(--font-semibold);
  color: var(--chip-neutral-fg);
  background: var(--chip-neutral-bg);
  border-radius: var(--radius-full);
  padding: 0.1875rem 0.5rem;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.collection-source-badge .material-icons {
  font-size: 0.8125rem;
  flex-shrink: 0;
}

.collection-card__meta {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  margin-top: 0.125rem;
}

.collection-card__address {
  display: flex;
  align-items: flex-start;
  gap: 0.375rem;
  font-size: var(--text-xs);
  line-height: 1.4;
  color: var(--color-neutral-500);
}

.collection-card__address .material-icons {
  font-size: 0.875rem;
  margin-top: 1px;
  flex-shrink: 0;
}

.collection-card__website {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  align-self: flex-start;
  font-size: var(--text-xs);
  font-weight: var(--font-medium);
  color: var(--color-primary-700);
  max-width: 100%;
}

.collection-card__website:hover {
  text-decoration: underline;
  color: var(--color-primary-800);
}

.collection-card__website .material-icons {
  font-size: 0.875rem;
  flex-shrink: 0;
}

/* Chips de status/sync no rodapé (só estados que pedem atenção) */
.collection-card__status {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem;
  min-width: 0;
}

/* Tag de status é um BOTÃO (menu de workflow: draft/active/archived/
   deleted) — visual de chip, affordance de clique */
.collection-card__status-chip {
  cursor: pointer;
  transition: box-shadow var(--transition-fast) var(--ease-out),
    filter var(--transition-fast) var(--ease-out);
}

.collection-card__status-chip:hover {
  filter: brightness(0.96);
  box-shadow: 0 0 0 2px var(--color-primary-100);
}

.collection-card__status-chip:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

/* Rodapé: chips à esquerda, ações à direita com hierarquia
   (Edit = oliva-soft primário; View/Link = neutro; ⋯ overflow) */
.collection-card__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spacing-2);
  padding: var(--spacing-2) var(--spacing-3);
  border-top: 1px solid var(--color-neutral-100);
  background: var(--color-neutral-50);
}

.collection-card__actions {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin-left: auto;
  flex: 1 1 12rem;
}

.collection-card__actions .card-link-btn,
.collection-card__actions .card-edit-btn {
  height: 2.25rem; /* 36px */
  min-height: 2.25rem; /* vence o min-height 44px global do mobile */
  min-width: 0;
  padding: 0 0.5rem;
  flex: 1 1 0;
  border-radius: var(--radius-input);
  font-size: 0.75rem;
  gap: 0.25rem;
}

.collection-card__actions .card-edit-btn {
  background: var(--color-primary-100);
  border-color: var(--color-primary-200);
  color: var(--color-primary-800);
}

.collection-card__actions .card-edit-btn:hover {
  background: var(--color-primary-200);
  border-color: var(--color-primary-300);
}

.collection-card__actions .btn-more-curation {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  min-width: 2.25rem; /* vence o min-width 44px global do mobile */
  min-height: 2.25rem; /* vence o min-height 44px global do mobile */
  padding: 0;
  flex: 0 0 auto;
  border-radius: var(--radius-input);
  background: transparent;
  border: 1px solid transparent;
  color: var(--color-neutral-500);
  cursor: pointer;
  transition: background-color var(--transition-fast) var(--ease-out),
    color var(--transition-fast) var(--ease-out),
    border-color var(--transition-fast) var(--ease-out);
}

.collection-card__actions .btn-more-curation:hover {
  background: var(--color-neutral-100);
  border-color: var(--color-neutral-200);
  color: var(--color-neutral-700);
}

.collection-card__actions .btn-more-curation:focus-visible,
.collection-card__actions .card-link-btn:focus-visible,
.collection-card__actions .card-edit-btn:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

/* Subtitle (curador/cuisine) dentro do novo corpo */
.collection-card__subtitle {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  align-self: flex-start;
  font-size: 0.6875rem;
  font-weight: var(--font-medium);
  color: var(--color-neutral-500);
  background: var(--color-neutral-50);
  border: 1px solid var(--color-neutral-200);
  border-radius: var(--radius-full);
  padding: 0.125rem 0.5rem;
  max-width: 100%;
}

.collection-card__subtitle .material-icons {
  font-size: 0.8125rem;
}

/* Nome do restaurante é o único alvo de clique do card de curation
   (ver detalhes) — affordance discreta no hover */
.collection-card__name-link {
  display: inline;
  border: none;
  background: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  border-radius: var(--radius-sm);
}

/* Botão de TEXTO — não pode herdar o min-height/padding 44px
   globais do mobile ([type="button"] tem mesma especificidade e
   carrega depois; o prefixo h3 desempata) */
h3 .collection-card__name-link {
  min-height: 0;
  min-width: 0;
  padding: 0;
}

.collection-card__name-link:hover {
  color: var(--color-primary-600);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.collection-card__name-link:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: 2px;
}

/* Truncamento dos labels internos (source badge, chip de curador) */
.collection-source-badge__label,
.collection-card__subtitle-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

/* Links de endereço dentro do meta: clamp precisa de min-width 0 */
.collection-card__address > a,
.collection-card__address > span:last-child {
  min-width: 0;
  flex: 1;
}

.collection-card__address a {
  color: inherit;
  text-decoration: none;
}

.collection-card__address a:hover {
  text-decoration: underline;
}

/* Rating/preço no meta (cards de entity; removido nas curadoria) */
.collection-card__rating {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  align-self: flex-start;
  font-size: var(--text-xs);
  color: var(--color-warning);
}

.collection-card__rating .material-icons {
  font-size: 0.875rem;
}

.collection-card__rating-value {
  font-weight: var(--font-semibold);
}

.collection-card__rating-price {
  color: var(--color-neutral-500);
}

/* ── Card de review órfã (createReviewCard, uiManager) ── */

.collection-card__review-row {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  font-size: var(--text-xs);
  color: var(--color-neutral-500);
}

.collection-card__concepts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}

.collection-card__concepts-more {
  font-size: var(--text-xs);
  color: var(--color-neutral-600);
  background: var(--color-neutral-100);
  border: 1px solid var(--color-neutral-200);
  border-radius: var(--radius-md);
  padding: 0.0625rem 0.375rem;
}

.collection-card__transcript {
  font-size: var(--text-xs);
  color: var(--color-neutral-600);
  font-style: italic;
  border-left: 2px solid var(--color-neutral-200);
  padding-left: var(--spacing-2);
  line-height: 1.45;
}

.collection-card__curator {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  font-size: var(--text-xs);
  color: var(--color-neutral-500);
  margin-top: auto;
}

.collection-card__curator .material-icons {
  font-size: 0.875rem;
}

/* Mídia fantasma da review (curadoria órfã): MESMO placeholder oficial
   do fallback padrão — identidade única para toda ausência de imagem */
.collection-card__media--note .collection-card__thumb-fallback {
  background-image: url('../images/placeholder_card.jpeg');
  background-size: cover;
  background-position: center;
  color: var(--color-primary-600);
}

/* Card inteiro clicável (entidades) — cursor comunica a affordance */
.collection-card--clickable {
  cursor: pointer;
}

/* ── Galeria ranqueada do entity details (API v2 do collector) ──
   Faixa horizontal de thumbs; clique troca a foto do herói. */

.detail-gallery__strip {
  display: flex;
  gap: var(--spacing-2);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding: 0.125rem 0.25rem 0.375rem;
  scroll-snap-type: x proximity;
}

.detail-gallery__strip::-webkit-scrollbar {
  display: none;
}

.detail-gallery__thumb {
  position: relative;
  flex: 0 0 auto;
  width: 5rem; /* 80px — thumbs maiores para o herói novo */
  height: 5rem;
  min-width: 5rem;
  min-height: 5rem;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-lg, 0.5rem);
  border: 1px solid var(--color-neutral-200);
  background: var(--color-neutral-100);
  color: var(--color-neutral-400);
  cursor: pointer;
  overflow: hidden;
  scroll-snap-align: start;
  transition: border-color var(--transition-fast) var(--ease-out),
    box-shadow var(--transition-fast) var(--ease-out),
    transform var(--transition-fast) var(--ease-out);
}

.detail-gallery__thumb-placeholder {
  font-size: 1.5rem;
}

.detail-gallery__thumb:hover:not(:disabled) {
  border-color: var(--color-neutral-400);
  transform: translateY(-1px);
}

.detail-gallery__thumb:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

.detail-gallery__thumb:disabled {
  opacity: 0.4;
  cursor: default;
}

.detail-gallery__thumb.is-active {
  border-color: var(--color-primary-500);
  box-shadow: 0 0 0 2px var(--color-primary-100);
}

.detail-gallery__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Viewer modal (sheets sem hero — ex.: detalhes da review) */
.detail-gallery__viewer-img {
  width: 100%;
  max-height: 70vh;
  object-fit: contain;
  border-radius: var(--radius-input);
  display: block;
}

/* ── Picker de imagem do editor de entity (data.image_rank) ── */

.entity-image-picker {
  padding: var(--spacing-3) 0;
  border-top: 1px solid var(--color-neutral-100);
  margin-top: var(--spacing-3);
}

.entity-image-picker__hint {
  font-size: var(--text-xs);
  color: var(--color-neutral-500);
  margin-bottom: var(--spacing-2);
}

.entity-image-picker__status {
  font-size: var(--text-xs);
  color: var(--color-primary-700);
  margin-top: var(--spacing-2);
  min-height: 1rem;
}

.entity-image-picker__status:empty {
  display: none;
}

/* ── Skeleton na shell do card (sem layout shift) ── */
.skeleton-block {
  background: var(--color-neutral-200);
  border-radius: var(--radius-sm);
}

.skeleton-line {
  height: 0.75rem;
}

.skeleton-card .collection-card__media {
  border: none;
}

.skeleton-card .collection-card__body {
  justify-content: center;
  gap: 0.5rem;
}
