/* ============================================================================
   components.css - shared UI components (T3 Phase 1.2b + Phase 2 + Phase 3+4, 2026-06-21..22)
   Extracted from base.html. Loaded after tokens.css + base.css.

    Organized by component family:
      - Header / nav (header, .spacer, .app-menu, .app-menu-*)
      - Destructive confirm (.confirm-destructive, .confirm-warning)
     - main + Layout primitives (.cols, .col)
     - Utility (.muted, .kv, .msg)
     - Buttons (.btn, .btn-primary, .btn-danger, .btn-ghost, .btn-secondary, .btn-sm, .btn-lg)
     - Form fields (.input, .textarea, .select)
     - Tables (table, th, td, .table-wrap)
     - Status indicators (.dot + variants)
     - Launch links (.launch)
     - Chips (.chip + per-domain variants + semantic variants)
     - Badges (.badge + variants)
     - NEED inline detail (.need, .need-detail, .need-field)
     - Cards (.card + variants)
     - Empty state (.empty-state -- generic; chat.css has its own .empty-state for chat-specific layout)
     - Skeleton loaders (.skeleton + variants)
     - Tooltips (.tooltip)
     - Modal (.modal, .modal-backdrop)
     - Toast (.toast + variants)
     - Divider (.divider, .divider-vertical)
     - Tabs (.tabs, .tabs-tab + active)
     - Auth page (.auth-page, .auth-hint, .auth-form, .auth-input, .auth-actions, .auth-footer)
     - Home (.home-cols, .home-tenant, .home-picker)
     - Admin shell (.admin-shell, .admin-sidebar, .admin-sidebar-brand, .admin-sidebar-footer, .admin-main, .admin-tabs)
     - Cut skeleton (.cut-skeleton)
     - Responsive breakpoints (@media)

   Every rule uses ONLY design tokens from tokens.css. No hardcoded colors.
   ============================================================================ */


/* =========================================================================
   Header / nav (consistent across home, admin, chat, login)
   ========================================================================= */
header {
  display: flex;
  align-items: stretch;
  /* T3 Phase 5.x (2026-06-24): gap dropped from var(--space-4)
     (16px) to 0. Leo: 'los espaciados que te menciono estan entre
     los iconos y las pestanas' -- the visible gap he was flagging
     was the 16px header gap PLUS the 12px session tab padding
     (28px total) between the home/menu dividers and the first/last
     tab text. The header gap was redundant since session tabs
     already carry their own internal padding for spacing. Dropping
     it to 0 leaves only the session tab padding (12px each side)
     as the breathing room between the home/menu buttons and the
     tabs. The spacer (flex:1) is the only flex child that benefits
     from extra gap, and it's invisible anyway -- setting gap to 0
     just lets the spacer absorb all the leftover horizontal space,
     which it already does. */
  gap: 0;
  /* T3 Phase 5.x (2026-06-24): vertical padding removed (was 8px
     top/bottom) so the tabs sit flush with the header's top/bottom
     edges. Horizontal padding restored to var(--space-2) on BOTH
     sides (8px each) for SYMMETRIC breathing room on the home and
     app-menu icons -- Leo: 'no, el objetivo es que sean simetricos
     no que ambos esten pegados a los bordes'. The previous flush-
     to-edge treatment (header padding 0 + .navtab-home padding 0 +
     flex-start) put the home icon's ink at ~2px from the viewport;
     mirroring that on the menu icon (justify-content:flex-end)
     matched the distance but felt claustrophobic with zero margin
      on either side. Restoring 8px on both sides gives both icons
      the same visual anchor (8px from their respective viewport
      edges) with a clean strip of empty space behind them. */
  padding: 0 var(--space-2);
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  flex-wrap: nowrap;
}
header .spacer { flex: 1; }
header a { font-size: var(--text-base); }
header select { font-size: var(--text-base); }

/* T3 Phase 5.4 (2026-06-23): the global app-menu (top-right corner
   dropdown). Replaces the deleted user-menu (T3 Phase 5.1) and the
   standalone "Cerrar sesión" link (T3 Phase 5.1). The trigger is a
   compact button: menu icon + user name + caret, anchored at the
   right edge of the header. The panel drops down with the admin
   section list (for admin) + the Cerrar-sesion item at the bottom.
   Same native-<details> pattern as the old user-menu: zero JS for
   the toggle, app-menu.js adds click-outside + Escape close. */
.app-menu {
  position: relative;
  margin: 0;
  /* Sit at the right edge of the header; the panel right-aligns
     itself to the trigger. */
  align-self: stretch;
  display: inline-flex;
  align-items: center;
}
.app-menu > .app-menu-toggle {
  list-style: none;
  cursor: pointer;
  /* T3 Phase 5.4.3 (2026-06-23): bigger icon-only trigger. Leo:
      'aumenta el tamano'. 48x48 square button with a 24x24 icon
      inside (close to the macOS toolbar icon aesthetic; the previous
      36x36 + 18 was too small next to the navtabs strip). No user
      name, no caret -- just the menu/X icon. */
  padding: 0;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-md);
  display: inline-flex;
  align-items: center;
  /* T3 Phase 5.x (2026-06-24): 8px margin top and bottom. Leo:
     'agregales 8px de margen superior e inferior a ambos botones'.
     The buttons stay 32x32 (height is fixed) but their outer box
     is now 48px tall (32 + 8 + 8). The header stretches to 48px
     to fit the taller outer boxes -- giving 8px of empty space
     above and below each button inside the header. The session
     tabs (32px, align-self: flex-end) stay anchored to the bottom
     and don't move with the button margin. */
  margin: 8px 0;
  /* T3 Phase 5.x (2026-06-24): justify-content reverted to center
     (was flex-start in the previous commit, which was the wrong
     fix). The spacing Leo flagged was BETWEEN the buttons and the
     session tabs (header gap + tab padding), NOT inside the button.
     Restored to center; the actual fix is in the header's gap rule. */
  justify-content: center;
  color: var(--color-fg);
  background: transparent;
  /* T3 Phase 5.x (2026-06-24): left-edge pseudo-element divider
     replaced by a box-shadow fade toward the bar center. Leo:
     'quita los divisores de ambos botones, y agregales un efecto
     de sombra que vaya hacia el centro de la barra. el color de
     la sombra que sea del color del fondo de la barra'. Mirror
     of the home button's right-side shadow -- short fade (4px to
     the LEFT, 6px blur), in var(--color-surface). Leo: 'que sea
     una sombra mucho mas corta para ambos'. */
  box-shadow: -4px 0 6px 0 var(--color-surface);
  border: 1px solid transparent;
  font-family: inherit;
  white-space: nowrap;
  /* T3 Phase 5.x (2026-06-24): z-index lifts the menu trigger above
     the .navtabs container for the same reason as the home button --
     keeps the left-side fade shadow visible above the navtabs surface.
     The menu trigger already has position: relative (added for the
     deleted ::after divider). z-index:1 is enough to put it above
     the navtabs without disrupting the rest of the stacking. */
  z-index: 1;
}
.app-menu > .app-menu-toggle::-webkit-details-marker { display: none; }
.app-menu > .app-menu-toggle:hover {
  background: var(--color-surface-raised);
}
.app-menu[open] > .app-menu-toggle {
  background: var(--color-surface-raised);
  /* The left-edge divider is now a pseudo-element (::after), not a
     border, so it stays at var(--color-border) regardless of the
     open state. border-color goes to full --color-border on the
     other 3 sides (top/right/bottom) as the open-state highlight. */
  border-color: var(--color-border);
}
/* T3 Phase 5.4.2 (2026-06-23): the trigger shows the menu icon
   (3 lines) when closed, and the X icon when open. Two <span>s in
   the markup, toggled by [open] on the parent <details>. The icons
   are absolute-centered in the trigger so the swap is seamless. */
.app-menu > .app-menu-toggle .app-menu-icon-closed,
.app-menu > .app-menu-toggle .app-menu-icon-open {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.app-menu[open] > .app-menu-toggle .app-menu-icon-closed { display: none; }
.app-menu:not([open]) > .app-menu-toggle .app-menu-icon-open { display: none; }
/* The caret indicator + .app-menu-caret rule are gone (T3 Phase
   5.4.1 removed the caret; T3 Phase 5.4.2 confirmed the removal).
   The closed/open icon swap above is the only open-state
   indicator on the trigger (in addition to the surface-raised bg
   + border). */
.app-menu-panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 240px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: var(--space-1);
  /* T3 Phase 5.7 (2026-06-23): the menu uses --z-popover (20) so
     it sits above sticky surfaces (the chathdr, the composer --
     both at --z-sticky 10) without being a full modal. The menu
     is a popover, not a modal: it doesn't block interaction with
     the rest of the page, but it should always render on top
     of sticky content. */
  z-index: var(--z-popover);
  /* Animate open/close. The native <details> toggle is instant; this
     hooks the visual fade. prefers-reduced-motion is honored globally
     in tokens.css. */
  animation: app-menu-slide 0.12s var(--ease-out);
}
@keyframes app-menu-slide {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}
.app-menu-meta {
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-xs);
  color: var(--color-fg-muted);
  border-bottom: 1px solid var(--color-border);
  margin-bottom: var(--space-1);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.app-menu-meta b {
  color: var(--color-fg);
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--text-sm);
  word-break: break-all;
}
.app-menu-section-label {
  padding: var(--space-2) var(--space-3) var(--space-1);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--color-fg-muted);
  font-weight: 600;
}
.app-menu-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.app-menu-item {
  display: block;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  color: var(--color-fg);
  text-decoration: none;
  background: transparent;
  border: 0;
  width: 100%;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
}
.app-menu-item:hover {
  background: var(--color-surface-raised);
  text-decoration: none;
}
.app-menu-divider {
  border: 0;
  border-top: 1px solid var(--color-border);
  margin: var(--space-1) 0;
}
.app-menu-item-danger { color: var(--color-danger); }
.app-menu-item-danger:hover { background: var(--color-danger-soft); }



/* =========================================================================
   Destructive confirm (admin tables). Wraps a destructive button in a
   details/summary pair with the class `confirm-destructive`: the button
   is the summary, an inline warning + the real destructive form appears
   on expand. Server-side only, no JS -- the native details toggle is
   enough. The summary keeps its .btn look; when open, it dims so the
   user knows they're already mid-confirm. The warning panel uses
   --color-danger-soft to make the destructiveness unmistakable.
   ========================================================================= */
.confirm-destructive {
  display: inline-block;
  margin-right: var(--space-1);
}
.confirm-destructive > summary {
  list-style: none;
  cursor: pointer;
}
.confirm-destructive > summary::-webkit-details-marker { display: none; }
.confirm-destructive[open] > summary {
  opacity: 0.45;
  cursor: default;
}
.confirm-warning {
  margin-top: var(--space-1);
  padding: var(--space-2) var(--space-3);
  background: var(--color-danger-soft);
  border: 1px solid var(--color-danger);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  max-width: 360px;
}
.confirm-warning p {
  margin: 0 0 var(--space-2);
  color: var(--color-fg);
}
.confirm-warning form { margin: 0; }
.confirm-warning button {
  font-size: var(--text-sm);
  padding: 4px 12px;
}


main {
  padding: var(--space-5);
  max-width: 1100px;
  /* T3 Phase 5.x (2026-06-24): body is now a column flex container.
     Without `margin: 0 auto` (which is needed in block layout to
     center the max-width box, but in a flex container absorbs the
     cross-axis free space and shrinks main to content width -- the
     trap that broke this in the previous step) main stretches to
     body width by default (align-items: stretch). On wide screens
     that puts the chatwrap flush LEFT instead of centered.
     `align-self: center` centers main on the cross axis (header
     stays stretched full-width via the parent's align-items:
     stretch default; only main opts out). The chatwrap inside is
     centered within main via its own align-self: center. */
  margin: 0;
  align-self: center;
  /* flex:1 / min-height:0 / column-flex: so the chatwrap child can
     shrink/grow to fill the remaining vertical space. */
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  /* On narrow viewports (body width < 1100px + main padding) main
     naturally fills the available width -- max-width no longer
     applies because body is narrower than max. On wide viewports
     main is capped at 1100px and centered via align-self: center
     (the extra horizontal space on body stays empty on both sides). */
  width: 100%;
}


/* =========================================================================
   Layout primitives
   ========================================================================= */
.cols { display: flex; gap: var(--space-5); align-items: flex-start; }
.col {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  flex: 1;
  min-width: 0; /* allow flex children to shrink so content can wrap */
}


/* =========================================================================
   Utility: .muted, .kv, .msg
   ========================================================================= */
.muted { color: var(--color-fg-muted); font-size: var(--text-sm); }
.kv { margin: var(--space-1) 0; }
.kv b {
  color: var(--color-fg-muted);
  font-weight: 600;
  margin-right: var(--space-2);
}
.msg {
  background: var(--color-surface);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-4);
  margin-bottom: var(--space-4);
  white-space: pre-wrap;
  font-size: var(--text-sm);
}


/* =========================================================================
   Buttons (replaces per-template button styling)
   ========================================================================= */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  background: var(--color-accent);
  border: 1px solid transparent;
  color: #fff;
  padding: 7px 14px;
  border-radius: var(--radius-md);
  cursor: pointer;
  font: inherit;
  font-size: var(--text-base);
  line-height: var(--leading-tight);
}
.btn:hover { filter: brightness(1.08); }
.btn:disabled {
  background: var(--color-border);
  color: var(--color-fg-muted);
  cursor: not-allowed;
}
.btn-primary { background: var(--color-accent); }
.btn-danger { background: var(--color-danger); }
.btn-ghost {
  background: var(--color-bg);
  border-color: var(--color-border);
  color: var(--color-fg);
}
.btn-ghost:hover { border-color: var(--color-accent); }

/* Icon-only button (square ghost button holding an SVG via the icon_* macros).
   Removes horizontal padding and the flex gap so the icon is centered on
   both axes and the button is square. Use aria-label on the wrapping element
   to keep the affordance accessible (screen readers will read the aria-label,
   not the SVG). */
.btn-icon {
  padding: 0;
  gap: 0;
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}


/* =========================================================================
   Form fields
   ========================================================================= */
.input, .textarea, .select {
  background: var(--color-bg);
  color: var(--color-fg);
  border: 1px solid var(--color-border);
  padding: 6px 10px;
  border-radius: var(--radius-md);
  font: inherit;
  font-size: var(--text-base);
}
.input:focus-visible, .textarea:focus-visible, .select:focus-visible {
  border-color: var(--color-accent);
}
.textarea { font-family: var(--font-mono); resize: vertical; min-height: 46px; }


/* =========================================================================
   Tables (admin + home report)
   ========================================================================= */
table { border-collapse: collapse; width: 100%; font-size: var(--text-base); }
th, td {
  text-align: left;
  padding: var(--space-1) var(--space-2);
  border-bottom: 1px solid var(--color-border);
}
th { color: var(--color-fg-muted); font-weight: 600; }
/* T1.3: row hover so the user can see which row is focused (tables
   like the NEEDs list + the API connections list are scan-heavy). */
tbody tr:hover { background: var(--color-surface-raised); }
.table-wrap { overflow-x: auto; } /* responsive: scrollable on mobile */


/* =========================================================================
   Semaforo + alert dot (state indicators)
   ========================================================================= */
.dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin-right: var(--space-2);
  vertical-align: middle;
}
.dot.green  { background: var(--color-success); }
.dot.yellow { background: var(--color-warning); }
.dot.red    { background: var(--color-danger); }


/* =========================================================================
   Launch links (home): styled like a flat list of buttons.
   ========================================================================= */
.launch {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  text-align: left;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  color: var(--color-fg);
  margin-bottom: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-md);
  cursor: pointer;
  font-size: var(--text-base);
  text-decoration: none;
}
.launch:hover { border-color: var(--color-accent); }


/* =========================================================================
   Chips (T1.8: collaborator grant in the admin table). Inline badges with
   a background tinted by domain. The chip-tenant variant uses the
   accent color (the tenant is the scope; the agent is what the
   collaborator can invoke).
   ========================================================================= */
.grant-row { margin: 2px 0; }
.chip {
  display: inline-block;
  padding: 1px 8px;
  margin: 1px 2px;
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  color: var(--color-fg);
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  white-space: nowrap;
}
.chip-tenant { background: var(--color-accent-soft); border-color: var(--color-accent); color: var(--color-accent); }
.chip-operator { background: var(--color-success-soft); border-color: var(--color-success); color: var(--color-success); }
.chip-advisor  { background: var(--color-warning-soft); border-color: var(--color-warning); color: var(--color-warning); }
.chip-marketing { background: rgba(168, 85, 247, 0.18); border-color: #a855f7; color: #c084fc; }
.chip-web      { background: var(--color-accent-soft); border-color: var(--color-accent); color: var(--color-accent); }


/* =========================================================================
   NEED detail (T1.9: each NEED row in the admin table is a <details>
   that expands inline to show the context + what_needed).
   ========================================================================= */
.need { width: 100%; }
.need > summary {
  cursor: pointer;
  padding: 4px 6px;
  border-radius: var(--radius-sm);
}
.need > summary:hover { background: var(--color-surface-raised); }
.need[open] > summary { margin-bottom: var(--space-2); }
/* T3 Phase 5.8 (2026-06-23): per-user cancelled-tokens dropdown
   on the /admin/usuarios page. Active tokens stay in the main
   table (the actionable surface); cancelled tokens live below
   in a collapsed <details> so the main view stays clean. The
   .caret span inside the summary is a CSS-only triangle that
   rotates when the dropdown is open (mirrors the native
   <details> behavior without needing a JS handler). */
.user-tokens-cancelled {
  margin-top: var(--space-2);
}
.user-tokens-cancelled > summary {
  cursor: pointer;
  padding: var(--space-1) var(--space-2);
  color: var(--color-fg-muted);
  font-size: var(--text-sm);
  border-radius: var(--radius-sm);
  list-style: none;          /* hide the default disclosure triangle */
  user-select: none;
}
.user-tokens-cancelled > summary:hover { color: var(--color-fg); }
.user-tokens-cancelled > summary::-webkit-details-marker { display: none; }
.user-tokens-cancelled > summary .caret {
  display: inline-block;
  width: 0;
  height: 0;
  margin-right: var(--space-1);
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  transition: transform var(--dur-hover) var(--ease-out);
  vertical-align: middle;
}
.user-tokens-cancelled[open] > summary .caret {
  transform: rotate(-180deg);
}
.user-tokens-cancelled[open] > summary { margin-bottom: var(--space-1); }
/* T3 Phase 5.8.2 (2026-06-23): per-tenant permissions dropdown
   on the /admin/usuarios user card. The summary carries the
   tenant name + the agent count so the admin can scan the
   full permission surface in a glance; the agent chips are
   inside, expanded on click. Same .caret chevron pattern as
   .user-tokens-cancelled (T3 Phase 5.8) -- different class
   so the two can be tuned independently (this is a primary
   surface; the other is history). */
.user-permissions { display: flex; flex-direction: column; gap: 2px; margin-top: var(--space-1); }
/* T3 Phase 5.8.3 (2026-06-23): per-section title inside the
   user card. Small + muted + uppercase + letter-spaced, the
   standard "section label" pattern used elsewhere in the
   design system (e.g. the .card legend). The .user-section-title-inline
   modifier removes the block-level margin + display so the
   title can sit inline in a <summary> (the cancelled-tokens
   dropdown). */
.user-section-title {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--color-fg-muted);
  margin: var(--space-3) 0 var(--space-2);
  font-weight: 600;
}
.user-section-title:first-child { margin-top: 0; }
.user-section-title-inline {
  display: inline;
  margin: 0;
  font-weight: 600;
}
.user-permissions-tenant > summary {
  cursor: pointer;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  list-style: none;
  user-select: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  width: fit-content;
}
.user-permissions-tenant > summary:hover { background: var(--color-surface-raised); }
.user-permissions-tenant > summary::-webkit-details-marker { display: none; }
.user-permissions-tenant > summary .caret {
  display: inline-block;
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  transition: transform var(--dur-hover) var(--ease-out);
}
.user-permissions-tenant[open] > summary .caret {
  transform: rotate(-180deg);
}
.user-permissions-agents {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-3) var(--space-2);
}
.need-detail {
  padding: var(--space-2) var(--space-3);
  background: var(--color-bg);
  border-left: 2px solid var(--color-accent);
  border-radius: var(--radius-sm);
  margin: var(--space-1) 0 var(--space-2);
}
.need-field { margin: 0 0 var(--space-2); }
.need-field b { color: var(--color-fg-muted); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.4px; display: block; margin-bottom: 2px; }
.need-field pre {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-2);
  font: var(--text-sm) / var(--leading-base) var(--font-body);
  color: var(--color-fg);
  white-space: pre-wrap;
  word-wrap: break-word;
  margin: 0;
  max-height: 200px;
  overflow-y: auto;
}
.need-meta { margin: var(--space-1) 0 0; font-size: var(--text-xs); }


/* =========================================================================
   Responsive breakpoints (CSS only, no JS)
   ========================================================================= */
@media (max-width: 900px) {
  .cols { flex-direction: column; }
  main { padding: var(--space-4); }
}
@media (max-width: 600px) {
  header { padding: var(--space-2) var(--space-3); }
  main { padding: var(--space-3); }
  h2 { font-size: var(--text-xs); }
  table { font-size: var(--text-sm); }
}


/* =========================================================================
   Button variants (T3 Phase 2, 2026-06-21). The base .btn class is the
   default medium size; size modifiers (sm, lg) and intent modifiers
   (primary, secondary, ghost, danger) compose freely.
   ========================================================================= */
.btn-sm {
  padding: 3px 9px;
  font-size: var(--text-sm);
}
.btn-lg {
  padding: 10px 20px;
  font-size: var(--text-md);
}
.btn-secondary {
  background: var(--color-accent-soft);
  color: var(--color-accent);
  border-color: var(--color-accent);
}
.btn-secondary:hover {
  filter: none;
  background: var(--color-accent);
  color: #fff;
}
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
}


/* =========================================================================
   Chips (Phase 2: semantic variants). The existing .chip-tenant /
   .chip-operator / .chip-advisor / .chip-marketing / .chip-web domain-
   tinted chips stay as-is (admin table renders those by domain). The new
   .chip-* variants are the design-system-v2 vocabulary for any new code
   that needs a status / category badge.
   ========================================================================= */
.chip-neutral { background: var(--color-surface-raised); border-color: var(--color-border); color: var(--color-fg-muted); }
.chip-accent  { background: var(--color-accent-soft);  border-color: var(--color-accent);  color: var(--color-accent); }
.chip-success { background: var(--color-success-soft); border-color: var(--color-success); color: var(--color-success); }
.chip-warning { background: var(--color-warning-soft); border-color: var(--color-warning); color: var(--color-warning); }
.chip-danger  { background: var(--color-danger-soft);  border-color: var(--color-danger);  color: var(--color-danger); }


/* =========================================================================
   Badge (Phase 2). Like .chip but tighter (counts / status indicators);
   the text is usually a short number or single token, never a sentence.
   ========================================================================= */
.badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 6px;
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: 600;
  background: var(--color-accent);
  color: #fff;
  line-height: 1;
}
.badge-neutral { background: var(--color-surface-raised); color: var(--color-fg-muted); border: 1px solid var(--color-border); }
.badge-success { background: var(--color-success); color: #fff; }
.badge-warning { background: var(--color-warning); color: #fff; }
.badge-danger  { background: var(--color-danger);  color: #fff; }


/* =========================================================================
   Card (Phase 2). The existing .col is the layout primitive (flex item
   inside .cols); .card is the standalone surface with title / body /
   footer slots. Use .card for grouped content blocks (NEEDs row, user
   summary, etc.); .col still wins inside a 2-column layout.
   ========================================================================= */
.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
}
.card-raised {
  background: var(--color-surface-raised);
}
.card-danger {
  background: var(--color-danger-soft);
  border-color: var(--color-danger);
}
/* Popover: floats a card above the page content, anchored to its
   nearest .popover-anchored parent (which provides the relative
   positioning context). Used by the per-user Editar <details>
   trigger in /admin/usuarios + /admin/conexiones + the legacy
   /admin (all-in-one) -- the form panel pops up under the pencil
   icon instead of expanding inline. Click the trigger again to
   close (native <details> behavior; no JS needed). */
.popover {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: var(--z-popover);
  min-width: 340px;
  max-height: 80vh;
  overflow-y: auto;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}
.popover-anchor {
  position: relative;
}

/* Modal: full-viewport dimmed scrim with a centered panel. Triggered
   by an Editar or Crear <details class="modal-trigger" name="user-modal">;
   the <details>'s name attribute makes the modals mutually exclusive
   (opening one auto-closes the others -- e.g. opening Crear while an
   Editar is open closes the Editar). The scrim is a child of the
   <details> -- when the <details> is open (native CSS-only toggle),
   the scrim + panel are rendered; when closed, they're hidden by the
   native <details> behavior.
   The close affordance is clicking the scrim (an inline onclick on
   the scrim closes the parent <details> when the click is on the
   scrim itself, not on the panel inside). No X button. */
.modal-trigger .modal-scrim {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  /* Dark page + rgba(0,0,0,0.6) reads as barely-dimmed; bump the
     opacity + add a slight backdrop blur so the modal is unmistakably
     "in focus" and the page behind is unmistakably "out of focus". */
  background: rgba(0, 0, 0, 0.78);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  display: flex;
  align-items: center;
  justify-content: center;
}
.modal-panel {
  position: relative;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  min-width: 380px;
  max-width: 560px;
  max-height: 85vh;
  overflow-y: auto;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--color-border);
}
.modal-header h3 {
  margin: 0;
  font-size: var(--text-md);
  font-weight: 600;
  /* The modal-header has only the title + the save icon (the X
     close button was removed -- the scrim's click-to-close is the
     single affordance). flex:1 makes the title expand to fill the
     remaining width and centers the text within its column;
     combined with justify-content: space-between on the header,
     the save icon stays pinned to the right edge. */
  flex: 1;
  text-align: center;
}
.modal-close {
  background: transparent;
  border: none;
  color: var(--color-fg-muted);
  padding: 0;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex: 0 0 auto;
}
.modal-close:hover { color: var(--color-fg); }
.modal-save {
  background: var(--color-accent);
  color: #fff;
  border: none;
  padding: 0;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex: 0 0 auto;
}
.modal-save:hover { filter: brightness(1.08); }
.modal-body { display: flex; flex-direction: column; gap: var(--space-2); }
.modal-footer {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
  display: flex;
  justify-content: flex-end;
}
.card-title {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--color-fg);
  margin: 0 0 var(--space-2);
}
/* T3 Phase 5.2 (2026-06-23): the home report card's title carries a
   tenant picker + the semaforo dot side-by-side. card-title-row
   switches the title to flex so the two elements align on one line
   without inheriting the global .card-title's block flow (which
   would stack them on separate lines). Used only by .card.home-report
   today, but the class lives on the design system so any future
   card with a title-level control can reuse it. */
.card-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}
.card-body {
  font-size: var(--text-base);
  color: var(--color-fg);
}
.card-footer {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
  display: flex;
  gap: var(--space-2);
}


/* =========================================================================
   Empty state (Phase 2). Centered placeholder for "no data yet" or "no
   results" surfaces. The chat surface uses its own .empty-state in
   chat.css (chat-specific layout); this one is the generic vocabulary.
   ========================================================================= */
.empty-state {
  text-align: center;
  padding: var(--space-7) var(--space-5);
  background: var(--color-surface);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-lg);
}
.empty-state-title {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--color-fg);
  margin: 0 0 var(--space-2);
}
.empty-state-body {
  color: var(--color-fg-muted);
  font-size: var(--text-sm);
  max-width: 480px;
  margin: 0 auto var(--space-4);
}
.empty-state-cta {
  display: inline-flex;
}

/* T3 Phase 4 optional: line-art SVG illustrations for empty states.
   Each illustration uses currentColor so it picks up the muted text
   color (--color-fg-muted via the empty-state-title's parent) and
   keeps the brand consistency. Size is bounded (80x80) so it never
   dominates the empty-state block. */
.empty-state-illustration {
  display: block;
  width: 80px;
  height: 80px;
  margin: 0 auto var(--space-3);
  color: var(--color-fg-muted);
  stroke: currentColor;
  fill: none;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.empty-state-illustration svg {
  width: 100%;
  height: 100%;
  display: block;
}


/* =========================================================================
   Skeleton (Phase 2 + 4). A shimmer placeholder used while async data is
   loading. Layout-aware: .skeleton-text spans the line; .skeleton-card
   keeps the card shape; .skeleton-circle is round (avatars). The shimmer
   is a gradient sweep animated over 1.5s; prefers-reduced-motion (in
   tokens.css) disables it cleanly.
   ========================================================================= */
.skeleton {
  display: block;
  background: linear-gradient(
    90deg,
    var(--color-surface-raised) 0%,
    var(--color-border) 50%,
    var(--color-surface-raised) 100%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-sm);
}
.skeleton-text {
  height: 12px;
  margin-bottom: var(--space-2);
}
.skeleton-text:last-child {
  width: 60%;
  margin-bottom: 0;
}
.skeleton-heading {
  height: 20px;
  width: 40%;
  margin-bottom: var(--space-3);
}
.skeleton-button {
  height: 32px;
  width: 120px;
  border-radius: var(--radius-md);
}
.skeleton-card {
  height: 96px;
  border-radius: var(--radius-lg);
}
.skeleton-circle {
  width: 32px;
  height: 32px;
  border-radius: 50%;
}
@keyframes skeleton-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}


/* =========================================================================
   Tooltip (Phase 2). CSS-only via :hover and :focus on a wrapper. Use:
     <span class="tooltip" data-tip="hint text">
       <button>...</button>
     </span>
   The trigger keeps its own styles; .tooltip just adds the bubble.
   ========================================================================= */
.tooltip {
  position: relative;
  display: inline-flex;
}
.tooltip:hover::after,
.tooltip:focus-within::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  background: var(--color-surface-raised);
  color: var(--color-fg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 4px 8px;
  font-size: var(--text-xs);
  white-space: nowrap;
  box-shadow: var(--shadow-md);
  z-index: var(--z-sticky);
  pointer-events: none;
}


/* =========================================================================
   Modal (Phase 2). Built on the native <dialog> element (browser-handled
   open/close, focus trap, Escape-to-close). Open via JS: dialog.showModal()
   or <dialog open>. The backdrop is dim; the dialog is centered with a
   card-like surface + large shadow.
   ========================================================================= */
dialog.modal {
  background: var(--color-surface);
  color: var(--color-fg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: 0;
  box-shadow: var(--shadow-lg);
  min-width: 360px;
  max-width: 560px;
  width: 90%;
}
dialog.modal::backdrop {
  background: rgba(0, 0, 0, 0.55);
}
.modal-header {
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--color-border);
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.modal-header h2 {
  margin: 0;
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--color-fg);
  text-transform: none;
  letter-spacing: 0;
}
.modal-close {
  margin-left: auto;
  background: transparent;
  border: 0;
  color: var(--color-fg-muted);
  cursor: pointer;
  font-size: var(--text-lg);
  padding: 0 4px;
  border-radius: var(--radius-sm);
  line-height: 1;
}
.modal-close:hover { color: var(--color-fg); }
.modal-body {
  padding: var(--space-5);
  font-size: var(--text-base);
  color: var(--color-fg);
}
.modal-footer {
  padding: var(--space-3) var(--space-5);
  border-top: 1px solid var(--color-border);
  display: flex;
  gap: var(--space-2);
  justify-content: flex-end;
}


/* =========================================================================
   Toast (Phase 2). A fixed bottom-right ephemeral notification. JS handles
   the lifecycle (mount, dismiss after N seconds, dismiss on click). The
   static rules below give the shape + variant colors; the slide-in /
   fade-out motion is a single keyframe pair.
   ========================================================================= */
.toast-stack {
  position: fixed;
  bottom: var(--space-5);
  right: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  z-index: var(--z-toast);
  pointer-events: none;
}
.toast {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-accent);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-sm);
  color: var(--color-fg);
  box-shadow: var(--shadow-md);
  min-width: 240px;
  max-width: 360px;
  pointer-events: auto;
  animation: toast-slide-in var(--dur-modal) var(--ease-out);
}
.toast-success { border-left-color: var(--color-success); }
.toast-warning { border-left-color: var(--color-warning); }
.toast-danger  { border-left-color: var(--color-danger); }
.toast-info    { border-left-color: var(--color-info); }
@keyframes toast-slide-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}


/* =========================================================================
   Divider (Phase 2). A more visible hr alternative for separating
   sections inside a card or between content blocks. Vertical variant
   for inline splits inside a flex row.
   ========================================================================= */
.divider {
  border: 0;
  border-top: 1px solid var(--color-border);
  margin: var(--space-3) 0;
}
.divider-vertical {
  width: 1px;
  align-self: stretch;
  background: var(--color-border);
  margin: 0 var(--space-2);
}


/* =========================================================================
   Tabs (Phase 2). A segmented control for top-level navigation between
   sibling views (e.g. /admin section switcher in Phase 3.3). The active
   tab gets aria-current="page" and .tabs-tab-active. Pure CSS + semantic
   HTML; no JS needed for the visual state.
   ========================================================================= */
.tabs {
  display: inline-flex;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 2px;
  gap: 2px;
}
.tabs-tab {
  display: inline-flex;
  align-items: center;
  padding: 4px 12px;
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  color: var(--color-fg-muted);
  text-decoration: none;
  background: transparent;
  border: 0;
  cursor: pointer;
  font-family: inherit;
}
.tabs-tab:hover { color: var(--color-fg); text-decoration: none; }
.tabs-tab-active {
  background: var(--color-surface-raised);
  color: var(--color-fg);
  font-weight: 500;
}


/* =========================================================================
   Cut skeleton (T3 Phase 4, 2026-06-22). When the admin clicks
   "Ejecutar corte" on /admin/pendientes, a .skeleton placeholder
   reveals below the form to show the work in progress. The
   shimmer animation honors prefers-reduced-motion (tokens.css
   disables transitions globally when that media query matches).
   ========================================================================= */
.cut-skeleton {
  margin-top: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.cut-skeleton[hidden] { display: none; }


/* =========================================================================
   Admin shell (T3 Phase 3.3, 2026-06-22). Persistent 200px sidebar on
   every /admin/* page with section nav (segmented control pattern) +
   the main area on the right. The shell sits on the same dark surface
   as the rest of the app; the sidebar carries a slight surface-raised
   background so the boundary is visible without a hard border.
   ========================================================================= */
.admin-shell {
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
  max-width: 1200px;
  margin: 0 auto;
  padding: var(--space-5);
}
.admin-sidebar {
  width: 200px;
  flex-shrink: 0;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-3);
  position: sticky;
  top: var(--space-4);
}
.admin-sidebar-brand {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--color-fg-muted);
  margin-bottom: var(--space-3);
  font-weight: 600;
}
.admin-sidebar .admin-tabs {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: 100%;
  background: transparent;
  border: 0;
  padding: 0;
  gap: 2px;
}
.admin-sidebar .tabs-tab {
  justify-content: flex-start;
  padding: 6px 10px;
  font-size: var(--text-sm);
}
.admin-sidebar-footer {
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
  font-size: var(--text-xs);
}
.admin-sidebar-footer a {
  color: var(--color-fg-muted);
  text-decoration: none;
}
.admin-sidebar-footer a:hover { color: var(--color-fg); text-decoration: underline; }
.admin-main {
  flex: 1;
  min-width: 0;
}
@media (max-width: 900px) {
  .admin-shell { flex-direction: column; }
  .admin-sidebar { width: 100%; position: static; }
  .admin-sidebar .admin-tabs { flex-direction: row; flex-wrap: wrap; }
}


/* =========================================================================
   Home page layout (T3 Phase 3.2, 2026-06-22). The launcher section
   groups agents under tenant chips; each tenant gets its own .home-tenant
   block. The .home-report section is the admin-only system monitoring
   card (semaforo + corte age + by-domain table + attention items).

   T3 Phase 5.6 (2026-06-23): the tenant picker is moved to a new
   .home-toolbar at the top of the page (visible to admin + collab).
   The picker filters BOTH the agents section AND the report section.

   T3 Phase 5.6.1 (2026-06-23): the toolbar is chrome-free (no
   background, no border, no padding) per Leo: 'no pongas color a
   la caja del tenant. hazlo tamaño titulo'. The select is styled
   as a page title (var(--text-md) + 600 weight) so the picker
   reads as a heading, not a form control. The semaforo dot
   moved back into the report card (T3 Phase 5.6 had it in the
   toolbar) -- one source of truth, next to the report data.

   The 2-column layout reuses .cols (Phase 1.2b) so the responsive
   collapse at <900px still works (launcher stacks above the report on
   mobile).
   ========================================================================= */
.home-toolbar {
  /* Chrome-free: no background, no border, no padding. The wrapper
     is a flex row that just spaces the picker from the 2-column
     grid below. Leo: 'no pongas color a la caja del tenant' --
     the picker should look like a page title, not a form
     control wrapped in a card. */
  display: flex;
  align-items: center;
  margin-bottom: var(--space-4);
}
.home-toolbar .home-picker {
  margin: 0;
}
/* T3 Phase 5.6.1: the picker is title-sized. var(--text-md) matches
   the .card-title size for visual consistency (the picker's
   semantic role is "which tenant's page is this?" -- a page
   heading, not a form input). T3 Phase 5.6.2: tenant names are
   rendered uppercase ("JHLEGACY", "FREELANCING") -- they read as
   page titles, and uppercase matches the per-tenant identity
   register used in admin surfaces. The underlying data is
   unchanged (select values stay lowercase; the URL ?tenant=X
     preserves the original id); the transformation is
     presentation-only. */
.home-tenant-select {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--color-fg);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  /* The native select chrome (background + border) varies across
     browsers; reset to none so the picker looks like a title, not
     a form control. The dropdown chevron still renders (the
     ::picker-icon pseudo), giving the affordance a clickable
     feel without a boxed background. */
  background: transparent;
  border: none;
  padding: 0;
  margin: 0;
  /* Native selects have a fixed line-height; override so the
     height matches the title baseline. */
  line-height: 1.3;
}
.home-cols {
  align-items: stretch;
}
.home-cols > .card {
  flex: 1;
  min-width: 0;
}
.home-tenant {
  margin-bottom: var(--space-4);
}
.home-tenant:last-child {
  margin-bottom: 0;
}
.home-picker {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}


/* =========================================================================
   Auth page layout (T3 Phase 3.1, 2026-06-22). The /login page is the
   only screen that needs a true viewport-centered card. .auth-page is
   a flex column that fills the remaining viewport height below the
   header and centers the card both vertically and horizontally. Other
   pages do not use this class; the normal .main padding + max-width
   layout is what they want.
   ========================================================================= */
.auth-page {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: calc(100vh - 60px); /* header height ~52px + breathing room */
  padding: var(--space-5) var(--space-3);
}
.auth-page > .card {
  width: 100%;
  max-width: 460px;
}
.auth-hint {
  margin: 0 0 var(--space-4);
  font-size: var(--text-sm);
}
.auth-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-3);
}
.auth-label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--color-fg-muted);
}
.auth-input {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}
.auth-actions {
  margin-top: var(--space-3);
  display: flex;
  justify-content: flex-start;
}
.auth-footer {
  margin: var(--space-4) 0 0;
  font-size: var(--text-xs);
}
/* T3 design pass (2026-06-22): "Mantener sesion iniciada" checkbox.
   Sits in the same row as the submit button (left side); the row is
   a flex with space-between so the button anchors to the right.
   Small text + muted color so the checkbox does not compete with the
   submit button. The native checkbox uses the system default styling. */
.auth-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-3);
}
.auth-remember {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  color: var(--color-fg-muted);
  cursor: pointer;
}
.auth-remember input[type="checkbox"] {
  margin: 0;
  cursor: pointer;
}


/* =========================================================================
   Styleguide layout primitives (Phase 2 + retired 2026-06-22).
   The /styleguide catalog page served as Leo's approval surface for
   the design system v2; once the macros + tokens were approved they
   became part of every page and the catalog had no role in the GUI.
   The route + template + demo JS + tests were deleted; the CSS that
   only fed the catalog goes too. If we ever need to spin up a new
   catalog (e.g. for a v3 design system) the history is here in git.
   ========================================================================= */


/* =========================================================================
   Global nav-tabs strip (T3 Phase 5 / 2026-06-23). The persistent
   navigation surface for chat sessions, rendered in the page header
   between the brand and the user menu. The first tab is always the
   home tab (icon-only, links to "/"). The remaining tabs are the
   open chat sessions, populated client-side by /static/js/navtabs.js
   from localStorage.

   Visual: a horizontal row of browser-style tabs with a bottom
   separator. The active tab has a brighter text + an accent-colored
   bottom border (the only "selected" indicator -- no background fill
   so the tabs blend with the header surface). The close button is
   an SVG X that becomes visible on hover. The home tab is square
   (icon-only) so it reads as a persistent anchor next to the wider
   session tabs.

   The strip scrolls horizontally on narrow viewports (overflow-x:
   auto) instead of wrapping, so the active tab stays visible while
   the inactive ones are reachable by scroll.
   ========================================================================= */
.navtabs {
  display: flex;
  align-items: stretch;
  flex: 1 1 auto;
  min-width: 0;
  gap: 2px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  /* T3 Phase 5.x (2026-06-24): changed from align-self:stretch to
     align-self:flex-end. With the previous header (align-items:stretch)
     and the 48px button heights setting the header height, the navtabs
     container stretched to 48px and each .navtab inside stretched too
     -- leaving ~17px of empty air above and below the text in every
     tab. Leo asked why so much air around the tab text (it was the
     header-stretch chain, not padding). Fix: stop the navtabs container
     from stretching to the full header height. flex-end anchors the
     container to the BOTTOM of the header (Leo: 'que esten pegadas
     abajo'), so the tabs sit flush with the header's bottom border
     line -- browser-style bottom-anchored tabs. The navtabs container
     now sizes to its content (text + min-height 32px on each tab) and
     the 48px header has empty space only above the navtabs container,
     not below it.
   T3 Phase 5.x (2026-06-24, follow-up): padding-left: 8px so the
     first session tab starts 8px further from the home button.
     Leo: 'que la posicion inicial de las pestanas empiecen 8 pixeles
     mas a la derecha'. Padding (not margin) keeps the scrollbar
     math correct -- padding is inside the content box, so the
     horizontal scroll behaves the same. */
  align-self: flex-end;
  padding-left: 8px;
}
.navtabs::-webkit-scrollbar { display: none; }
.navtab {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 0 var(--space-3);
  min-height: 32px;
  /* T3 Phase 5.x (2026-06-24): text color reverted to
     var(--color-fg-muted) (the original pre-9cd697a value).
     Leo's earlier ask ('haz que el color gris de cuando estan
     avtivadas sea el color por defecto') was about the BACKGROUND
     color, not the text color -- he clarified 'me refiero los
     colores del fondo. revierte los colores del texto'. The
     background change lives below (background: transparent ->
     var(--color-surface-raised) on the inactive default, and
     var(--color-surface-raised) -> var(--color-accent) on active). */
  color: var(--color-fg-muted);
  text-decoration: none;
  font-size: var(--text-sm);
  /* T3 Phase 5.x (2026-06-24): default background changed from
     transparent to var(--color-surface-raised) -- Leo: 'haz que el
     color gris de cuando estan avtivadas sea el color por defecto'.
     The gray surface-raised color (which used to be only on active
     tabs) is now the resting state for every session tab. All tabs
     read as 'on a surface' by default -- the visual cue for the
     active tab shifts from 'raised gray vs nothing' (presence/absence)
     to 'blue vs gray' (hue contrast, much more prominent). */
  background: var(--color-surface-raised);
  border: 0;
  border-bottom: 2px solid transparent;
  /* T3 Phase 5.x (2026-06-24): top corners rounded with
     var(--radius-md) to match the home button, app-menu trigger,
     modal panels, and other surfaces. The bottom corners stay
     square so the tab sits flush against the header's bottom border
     (no awkward gap between the tab's curve and the header line).
     Now that every tab has a surface-raised bg, the rounded top
     corners are visible on every tab, not just active. */
  border-top-left-radius: var(--radius-md);
  border-top-right-radius: var(--radius-md);
  cursor: pointer;
  white-space: nowrap;
  position: relative;
  flex: 0 0 auto;
  max-width: 220px;
}
.navtab:hover {
  color: var(--color-fg);
  text-decoration: none;
}
.navtab .navtab-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.navtab-active {
  /* T3 Phase 5.x (2026-06-24): text color reverted to
     var(--color-fg) (the original pre-9cd697a value). The text
     stays bright on the active tab; the visual cue for active
     now lives in the BACKGROUND (gray -> blue) per Leo's
     'me refiero los colores del fondo. revierte los colores del
     texto'. */
  color: var(--color-fg);
  /* T3 Phase 5.x (2026-06-24): active background changed from
     var(--color-surface-raised) (gray) to var(--color-accent)
     (blue) -- Leo: 'cuando esten activas sean del azul del borde
     inferior que tienen cuando estan activas actualmente'. The
     accent blue was previously only on the bottom border; now the
     active tab's full surface is that blue. The bottom border stays
     var(--color-accent) too (invisible against the same-color bg,
     but it ensures the active tab's blue extends cleanly to the
     header's bottom border line with no transparent gap). */
  background: var(--color-accent);
  border-bottom-color: var(--color-accent);
  /* font-weight 600 to make the active label read as 'this is the
     current page' without needing extra visual chrome. */
  font-weight: 600;
}
.navtab-home {
  /* T3 Phase 5.x (2026-06-24): padding dropped to 0 (was `0 var(--space-2)`,
     then `0 var(--space-2) 0 0`). Leo: 'hay otro margen del icono tal
     vez que sigue separando del borde' -- after dropping the header's
     left padding AND the cell's left padding, the icon's visible stroke
     was still being pushed inward by justify-content:center (the icon
     centered inside a 24px cell = 4px gap on each side of the icon).
     Dropping justify-content:center lets the icon hug the cell's left
     edge. Combined with header padding-left = 0, the icon now anchors
     to the viewport's left edge with only the SVG viewBox's natural
     stroke offset (~2px) before the visible ink begins. */
  padding: 0;
  max-width: none;
  /* T3 Phase 5.x (2026-06-24): the home button is now shaped like the
     app-menu trigger -- Leo: 'que el boton home sea igual el (me refiero
     a todo el boton, hover borde, etc, excepto el icono por supuesto)'.
     48x48 square with border-radius:var(--radius-md), background:transparent,
     and border:1px solid transparent (matching .app-menu-toggle's base
     border). On hover, background:var(--color-surface-raised) and
     border-color:var(--color-border) -- same hover treatment as the
     menu trigger. The icon stays left-aligned (justify-content:flex-start)
     per Leo's 'excepto el icono' qualifier; the icon's position is part
     of the icon's identity, not the button's chrome. */
  width: 32px;
  height: 32px;
  border: 1px solid transparent;
  border-bottom: 0; /* override .navtab's 2px transparent bottom border -- the home button is a square affordance, not a tab with an accent baseline */
  border-radius: var(--radius-md);
  /* T3 Phase 5.x (2026-06-24): 8px margin top and bottom. Mirrors
     the menu trigger's margin in the same commit. Header grows
     to 48px (button 32 + margins 16) -- the session tabs stay
     anchored to the bottom (align-self: flex-end, 32px tall),
     leaving 8px of header surface above and below each button. */
  margin: 8px 0;
  background: transparent;
  display: inline-flex;
  align-items: center;
  /* T3 Phase 5.x (2026-06-24): justify-content reverted to center
     (was flex-end in the previous commit, which was the wrong fix).
     Leo: 'los espaciados que te menciono estan entre los iconos y
     las pestanas' -- the spacing he was flagging was the gap BETWEEN
     the home/menu buttons and the session tabs (header gap +
     session tab padding), NOT inside the button. The previous commit
     moved the icons to the divider side, which solved a non-problem
     and broke the centered-icon look. Restored to center so the
     icons are back in the middle of their 48x48 buttons; the actual
     fix for the spacing between buttons and tabs lives in the
     header's gap rule (see header { gap: 0 } below). */
  justify-content: center;
  /* T3 Phase 5.x (2026-06-24): the home icon (and only the home
     icon) is the color the home button uses on hover (var(--color-fg)).
     Previously the icon inherited the muted color like every other
     inactive tab -- a status-quo read as "not active, not interesting".
     Bumping it to the hover color makes the home anchor read as a
     permanent call-to-action regardless of whether it's currently
     the active route (it never needs to feel "dim"). The active
     override below still escalates to pure white when on /. */
  color: var(--color-fg);
  /* T3 Phase 5.x (2026-06-24): right-edge pseudo-element divider
     replaced by a box-shadow fade toward the bar center. Leo:
     'quita los divisores de ambos botones, y agregales un efecto
     de sombra que vaya hacia el centro de la barra. el color de
     la sombra que sea del color del fondo de la barra'. Short
     fade (4px offset, 6px blur) -- Leo: 'que sea una sombra
     mucho mas corta para ambos'. The session tabs area
     (var(--color-surface-raised)) is slightly lighter than the
     bar surface, so the shadow reads as a soft fade FROM the
     bar's bg INTO the tabs area at the boundary. */
  box-shadow: 4px 0 6px 0 var(--color-surface);
  /* T3 Phase 5.x (2026-06-24): z-index lifts the home button above
     the .navtabs container so its box-shadow isn't covered. The
     home button is a DOM sibling that PRECEDES .navtabs in the
     header, so .navtabs would otherwise render on top of the
     shadow region (clipping the fade). */
  z-index: 1;
}
.navtab-home:hover {
  background: var(--color-surface-raised);
  /* The box-shadow stays in place on hover -- the fade is a
     structural feature of the button, not a state-dependent cue. */
}
/* T3 Phase 5.x (2026-06-24): Leo: 'cuando el boton home este
   activado el fondo sea azul'. When the user is on / (home
   active), the button bg matches the active session tab's accent
   blue (var(--color-accent)) -- the same color used for the
   active tab's bg. This makes the home button visually
   symmetrical with the rest of the active state: when / is the
   current page, the home button is blue, mirroring the active
   session tab's blue. Text stays #fff (was already in this
   rule) so it contrasts against the new blue bg. The border-color
   also goes to accent so the button reads as a unified blue
   affordance (no transparent border peeking through). */
.navtab-home.navtab-active {
  color: #fff;
  background: var(--color-accent);
  border-color: var(--color-accent);
}
/* T3 Phase 5.x (2026-06-24): the home tab slot wrapper. The home
   button lives OUTSIDE the .navtabs scrollable container (same as
   the app-menu trigger on the right) so it stays put when the
   session tabs scroll horizontally. The wrapper div exists only
   as a render target for navtabs.js#render(); display:contents
   removes the wrapper from the layout so the .navtab-home button
   itself is a direct flex child of <header> (no extra spacing, no
   flex item count change). display:contents has known accessibility
   caveats in older browsers, but the wrapper has no semantic meaning
   (no ARIA, no role) and contains exactly one link -- safe here. */
.navtab-home-slot { display: contents; }
.navtab-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  padding: 0;
  margin-left: var(--space-1);
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--color-fg-muted);
  cursor: pointer;
  flex: 0 0 auto;
  opacity: 0;
  transition: opacity var(--dur-hover) var(--ease-out),
              background var(--dur-hover) var(--ease-out);
}
.navtab:hover .navtab-close,
.navtab-close:focus-visible {
  opacity: 1;
}
.navtab-close:hover {
  background: var(--color-surface-raised);
  color: var(--color-fg);
}
@media (max-width: 600px) {
  .navtab-close { opacity: 1; }
  .navtab { padding: 0 var(--space-2); max-width: 160px; }
}
