/* Factory Web -- black & white minimalist (2026-08-24).

   Replaces the earlier "entropy field" synthesis (colored plasma blobs,
   fractal-noise grain, drifting motes) at Thiago's explicit direction:
   "layout preto, preto e branco minimalista" -- and, in his own words, a
   quality bar of "modelo Apple e Vercel... nivel fino de startup que
   acabou de pegar 2 mi de funding": crisp, restrained, premium, not a
   product demo. Concretely that means: no animated background, no color
   used for its own sake, tight 1px hairline borders instead of glow/blur,
   generous whitespace, and every color in this file resolving to black,
   white, or a step of gray -- including status colors, which lean on the
   text label every badge already carries (RUNNING/COMPLETED/etc) rather
   than hue for meaning.

   Both themes below are literally black/white, just inverted -- light is
   white-on-near-black-text with a black accent, dark is black-on-near-
   white-text with a white accent. The toggle mechanism itself (factory.js,
   the [data-theme] attribute) is unchanged.

   Kept from the previous system, recolored rather than removed: the
   bracket-frame corners (--frame-ink, .container/.table-card/etc), the
   self-drawing lemniscate brand mark, and the small "always computing"
   pulse-infinity indicator -- all three were already just borders/strokes,
   not color statements, so they carry the new palette cleanly. */

:root {
  color-scheme: light;

  /* -- surfaces & ink -- */
  --bg: #ffffff;
  --surface: rgba(10, 10, 10, 0.03);
  --surface-solid: #ffffff;
  --surface-alt: rgba(10, 10, 10, 0.045);
  --text: #0a0a0a;
  --text-secondary: #4d4d4d;
  --muted: #8a8a8a;
  --border: rgba(10, 10, 10, 0.10);
  --border-strong: rgba(10, 10, 10, 0.22);
  --gridline: #e8e8e8;

  /* -- brand / accent: pure black-on-white -- */
  --accent: #0a0a0a;
  --accent-strong: #000000;
  --accent-text: #ffffff;
  --accent-wash: rgba(10, 10, 10, 0.08);

  /* -- status: grayscale steps, distinguished by weight/label, not hue -- */
  --good: #1f1f1f;
  --good-wash: rgba(10, 10, 10, 0.06);
  --warning: #454545;
  --warning-wash: rgba(10, 10, 10, 0.09);
  --serious: #303030;
  --critical: #0a0a0a;
  --critical-wash: rgba(10, 10, 10, 0.12);

  /* -- categorical chart series: gray ramp, darkest to lightest -- */
  --series-2: #2b2b2b;
  --series-3: #464646;
  --series-4: #616161;
  --series-5: #7c7c7c;
  --series-6: #979797;
  --series-7: #b2b2b2;
  --series-8: #cdcdcd;
  --chart-surface: rgba(10, 10, 10, 0.03);
  --chart-track: var(--surface-alt);

  --shadow-sm: 0 1px 2px rgba(10, 10, 10, 0.05);
  --shadow-md: 0 8px 20px rgba(10, 10, 10, 0.06), 0 1px 2px rgba(10, 10, 10, 0.04);
  --shadow-lg: 0 20px 44px rgba(10, 10, 10, 0.10), 0 2px 6px rgba(10, 10, 10, 0.05);

  --radius-sm: 8px;
  --radius-md: 16px;
  --radius-lg: 22px;
  --radius-pill: 999px;

  --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", system-ui, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-loop: cubic-bezier(0.65, 0, 0.35, 1);

  /* -- bracket-frame recipe, overridden per scale where it's applied
     (.container / .table-card etc. / .stat) -- */
  --frame-ink: var(--border-strong);
  --fr: 12px;
  --fr-radius: 3px;

  /* -- brand-mark gradient: monochrome, black to mid-gray -- */
  --brand-grad-1: var(--accent);
  --brand-grad-2: #6b6b6b;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #000000;
    --surface: rgba(255, 255, 255, 0.045);
    --surface-solid: #0a0a0a;
    --surface-alt: rgba(255, 255, 255, 0.065);
    --text: #f5f5f5;
    --text-secondary: #b3b3b3;
    --muted: #7a7a7a;
    --border: rgba(255, 255, 255, 0.12);
    --border-strong: rgba(255, 255, 255, 0.24);
    --gridline: #262626;

    --accent: #f5f5f5;
    --accent-strong: #ffffff;
    --accent-text: #0a0a0a;
    --accent-wash: rgba(245, 245, 245, 0.10);

    --good: #e5e5e5;
    --good-wash: rgba(245, 245, 245, 0.08);
    --warning: #bdbdbd;
    --warning-wash: rgba(245, 245, 245, 0.10);
    --serious: #d0d0d0;
    --critical: #ffffff;
    --critical-wash: rgba(245, 245, 245, 0.14);

    --series-2: #e5e5e5;
    --series-3: #cccccc;
    --series-4: #b3b3b3;
    --series-5: #999999;
    --series-6: #808080;
    --series-7: #666666;
    --series-8: #4d4d4d;
    --chart-surface: rgba(255, 255, 255, 0.04);

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
    --shadow-md: 0 8px 20px rgba(0, 0, 0, 0.55), 0 1px 2px rgba(0, 0, 0, 0.35);
    --shadow-lg: 0 20px 44px rgba(0, 0, 0, 0.65), 0 2px 6px rgba(0, 0, 0, 0.4);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #000000;
  --surface: rgba(255, 255, 255, 0.045);
  --surface-solid: #0a0a0a;
  --surface-alt: rgba(255, 255, 255, 0.065);
  --text: #f5f5f5;
  --text-secondary: #b3b3b3;
  --muted: #7a7a7a;
  --border: rgba(255, 255, 255, 0.12);
  --border-strong: rgba(255, 255, 255, 0.24);
  --gridline: #262626;

  --accent: #f5f5f5;
  --accent-strong: #ffffff;
  --accent-text: #0a0a0a;
  --accent-wash: rgba(245, 245, 245, 0.10);

  --good: #e5e5e5;
  --good-wash: rgba(245, 245, 245, 0.08);
  --warning: #bdbdbd;
  --warning-wash: rgba(245, 245, 245, 0.10);
  --serious: #d0d0d0;
  --critical: #ffffff;
  --critical-wash: rgba(245, 245, 245, 0.14);

  --series-2: #e5e5e5;
  --series-3: #cccccc;
  --series-4: #b3b3b3;
  --series-5: #999999;
  --series-6: #808080;
  --series-7: #666666;
  --series-8: #4d4d4d;
  --chart-surface: rgba(255, 255, 255, 0.04);

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow-md: 0 8px 20px rgba(0, 0, 0, 0.55), 0 1px 2px rgba(0, 0, 0, 0.35);
  --shadow-lg: 0 20px 44px rgba(0, 0, 0, 0.65), 0 2px 6px rgba(0, 0, 0, 0.4);
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--text);
  line-height: 1.5;
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  transition: background-color 0.3s var(--ease), color 0.3s var(--ease);
  position: relative;
}

a {
  color: var(--accent);
  text-decoration: none;
  transition: color 0.15s var(--ease), opacity 0.15s var(--ease);
}
a:hover { color: var(--accent-strong); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
  .pulse-infinity path,
  .brand-mark .loop-path, .brand-mark .loop-core,
  .lobe-pulse {
    animation: none !important;
  }
  .brand-mark .loop-path { stroke-dashoffset: 0; }
  .brand-mark .loop-core { opacity: 0.9; }
  .lobe-pulse { display: none; }
}

/* ---------------------------------------------------------------------- */
/* Header                                                                   */
/* ---------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  /* ACIMA do drawer (21) e do overlay (20), de propósito. O drawer é
     `position: fixed; top: 0` e cobre a faixa do cabeçalho -- com o header
     em z-index 10 ele cobria o próprio botão que o fecha, e o menu abria sem
     ter como fechar (Thiago, 2026-08-29: "quando clica não tem como
     desclicar"). O padding-top do drawer já reserva a altura do cabeçalho,
     então subir o header não esconde item nenhum: só devolve o clique ao X. */
  z-index: 22;
  background: var(--bg);
  background: color-mix(in srgb, var(--bg) 70%, transparent);
  backdrop-filter: saturate(180%) blur(16px);
  -webkit-backdrop-filter: saturate(180%) blur(16px);
  border-bottom: 1px solid var(--border);
}

.site-header-inner {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0.85rem clamp(1rem, 3vw, 1.75rem);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--text);
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: -0.01em;
}
.brand:hover { color: var(--text); opacity: 0.75; }

/* Genesis rebrand (2026-08-26): "Genesis" is the outward product name,
   "Factory Cauteloso" stays visible underneath as the accurate technical/
   internal system name -- same pairing pattern as a product shown next to
   its parent platform, not a rename of the codebase/repo. */
.brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}
.brand-name {
  font-size: 0.95rem;
  font-weight: 650;
  letter-spacing: -0.01em;
}
.brand-sub {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.03em;
  color: var(--muted);
}
@media (max-width: 480px) {
  .brand-sub { display: none; }
}

/* The brand mark (from #16, developed further than #18's simpler dashed
   trace): a lemniscate drawn with one continuous gradient stroke -- O(n)=N
   folded back into itself, the brief's own image. It draws itself in on
   load, then the crossing point at the centre carries a slow, permanent
   pulse: the loop never stops, because the whole point of the mark is
   "infinite". Gradient stops are entropy's own accent + bloom-3 tokens, so
   the wordmark reads as part of the field's palette, not a second brand. */
.brand-mark {
  width: 26px;
  height: 16px;
  overflow: visible;
  flex: none;
}
.brand-mark .loop-path {
  fill: none;
  stroke: url(#loopGradient);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-dasharray: 132;
  stroke-dashoffset: 132;
  animation: draw-loop 1.4s var(--ease-loop) 0.1s forwards, trace-loop 5.5s linear 1.6s infinite;
}
.brand-mark .loop-core {
  fill: var(--brand-grad-2);
  opacity: 0;
  animation: core-in 0.4s var(--ease) 1.3s forwards, core-pulse 2.2s ease-in-out 1.6s infinite;
}
@keyframes draw-loop { to { stroke-dashoffset: 0; } }
@keyframes trace-loop { 0% { filter: drop-shadow(0 0 0 transparent); } 50% { filter: drop-shadow(0 0 3px var(--accent-wash)); } 100% { filter: drop-shadow(0 0 0 transparent); } }
@keyframes core-in { to { opacity: 1; } }
@keyframes core-pulse { 0%, 100% { r: 2; opacity: 0.9; } 50% { r: 3.1; opacity: 0.5; } }

/* Small quiet "always computing" indicator elsewhere on the page (dashboard
   health line, metrics timestamp) -- a plainer traced lemniscate, kept
   distinct from the header wordmark above. */
@keyframes infinity-trace {
  to { stroke-dashoffset: -180; }
}

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface-alt);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background-color 0.15s var(--ease), color 0.15s var(--ease), border-color 0.15s var(--ease), transform 0.1s var(--ease);
}
.theme-toggle:hover { color: var(--text); border-color: var(--border-strong); }
.theme-toggle:active { transform: scale(0.94); }
.theme-toggle .icon { width: 17px; height: 17px; }
.theme-toggle .icon-sun { display: none; }
.theme-toggle .icon-moon { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .icon-sun { display: block; }
  :root:not([data-theme="light"]) .theme-toggle .icon-moon { display: none; }
}
:root[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }
:root[data-theme="light"] .theme-toggle .icon-sun { display: none; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: block; }

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

/* ---------------------------------------------------------------------- */
/* Hamburger nav -- checkbox-driven drawer, no JS required to open/close.  */
/* #nav-toggle is a hidden-but-focusable sibling of .header-actions (the   */
/* toggle button lives inside it), .nav-overlay and #nav-drawer, so every  */
/* one of `:checked ~ ...` selectors below reaches its target without any  */
/* script running. factory.js only adds Escape-to-close and aria-expanded  */
/* sync on top -- both already work by clicking the toggle, a link, or the */
/* overlay with JS disabled. */
/* ---------------------------------------------------------------------- */

.nav-toggle-input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

.nav-toggle-btn {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface-alt);
  cursor: pointer;
  transition: background-color 0.15s var(--ease), border-color 0.15s var(--ease), transform 0.1s var(--ease);
}
.nav-toggle-btn:hover { border-color: var(--border-strong); }
.nav-toggle-btn:active { transform: scale(0.94); }

.nav-toggle-bar {
  width: 16px;
  height: 1.6px;
  border-radius: 1px;
  background: var(--text-secondary);
  transition: transform 0.25s var(--ease), opacity 0.2s var(--ease);
}

#nav-toggle:focus-visible ~ .header-actions .nav-toggle-btn {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Hamburger -> X, driven purely by the checkbox's :checked state. */
#nav-toggle:checked ~ .header-actions .nav-toggle-bar:nth-child(1) {
  transform: translateY(5.6px) rotate(45deg);
}
#nav-toggle:checked ~ .header-actions .nav-toggle-bar:nth-child(2) {
  opacity: 0;
}
#nav-toggle:checked ~ .header-actions .nav-toggle-bar:nth-child(3) {
  transform: translateY(-5.6px) rotate(-45deg);
}

.nav-overlay {
  position: fixed;
  inset: 0;
  z-index: 20;
  background: transparent;
  opacity: 0;
  pointer-events: none;
  cursor: default;
  transition: opacity 0.28s var(--ease);
}
#nav-toggle:checked ~ .nav-overlay {
  opacity: 1;
  pointer-events: auto;
}

/* Apple-style full-bleed dropdown panel: spans the viewport width just
   below the header, fades + slides down a few px, rather than a fixed-width
   side drawer. Row layout (items spread across, centered) on wide
   viewports; collapses to a full-width stacked list on narrow ones -- same
   two-tier responsive behavior apple.com's nav uses. */
.nav-drawer {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 21;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: calc(0.85rem + 34px + 1.25rem) max(1.25rem, calc((100% - 980px) / 2)) 1.5rem;
  background: rgba(15, 14, 22, 0.82);
  backdrop-filter: blur(20px) saturate(1.6);
  -webkit-backdrop-filter: blur(20px) saturate(1.6);
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition: opacity 0.28s var(--ease), transform 0.28s var(--ease);
}
#nav-toggle:checked ~ .nav-drawer {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

@media (min-width: 720px) {
  .nav-drawer {
    flex-direction: row;
    /* `wrap` não é enfeite: são 19 itens numa linha só, e flex-row NÃO quebra
       por padrão -- os últimos vazavam para fora da tela e sumiam sem aviso.
       Foi assim que o Maestro (16º da lista) desapareceu do menu enquanto o
       link continuava lá no HTML (Thiago, 2026-08-29: "sumiu a aba maestro").
       Item novo no fim da nav não pode empurrar o anterior para fora. */
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.25rem 2.5rem;
    padding-top: calc(0.85rem + 34px + 1rem);
    padding-bottom: 1.25rem;
  }
}

/* Altura máxima + rolagem pelo mesmo motivo, no eixo que sobrou: em tela
   baixa (ou com a lista crescendo) a coluna passava do rodapé e os últimos
   itens ficavam inalcançáveis. Rolar é feio; sumir é bug. */
.nav-drawer {
  max-height: 100vh;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.nav-drawer a {
  padding: 0.75rem 0.6rem;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-size: 0.98rem;
  font-weight: 500;
  text-align: center;
  transition: background-color 0.12s var(--ease), color 0.12s var(--ease);
}
.nav-drawer a:hover { background: var(--surface); color: var(--text); }
.nav-drawer a[aria-current="page"] { color: var(--accent); }

@media (prefers-reduced-motion: reduce) {
  .nav-overlay, .nav-drawer, .nav-toggle-bar {
    transition: none !important;
  }
}

/* ---------------------------------------------------------------------- */
/* Layout                                                                   */
/* ---------------------------------------------------------------------- */

.container {
  position: relative;
  z-index: 1;
  max-width: 1180px;
  margin: 0 auto;
  padding: clamp(1.25rem, 3vw, 2.25rem) clamp(1rem, 3vw, 1.75rem) 4rem;
}

.page-head {
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 2.5rem;
}

.eyebrow {
  margin: 0 0 0.3rem;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

.entropy-caption {
  font-family: var(--font-mono);
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  color: var(--muted);
  opacity: 0.8;
}

.page-title {
  margin: 0;
  font-size: clamp(1.9rem, 3.4vw, 2.75rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
}

.page-title.job-id {
  font-family: var(--font-mono);
  font-size: clamp(1.15rem, 2vw, 1.45rem);
  font-weight: 600;
  word-break: break-all;
}

.back-link { margin: 0 0 1rem; font-size: 0.88rem; }
.back-link a { color: var(--text-secondary); }
.back-link a:hover { color: var(--text); }

section { margin-bottom: 3.5rem; }

.section-title {
  margin: 0 0 1rem;
  font-size: 1.1rem;
  font-weight: 650;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

/* ---------------------------------------------------------------------- */
/* Recursion -- shared bracket-frame system (from #17), the merge's         */
/* secondary signature. One recipe (--fr / --fr-radius / --frame-ink),      */
/* reused at three nested scales: page -> section -> tile. Zoom into a stat */
/* tile's corner and it is the same bracket geometry as the frame around    */
/* the whole page, just smaller -- self-similarity as the actual mechanism, */
/* not a decoration. Replaces #18's own card treatment (organic "breathing" */
/* border-radius drift + a separate nested-ring glyph): two corner borders  */
/* read clearly against the entropy field behind them, where another        */
/* independently-animating layer would start to compete with it.           */
/* ---------------------------------------------------------------------- */

.container,
.stat,
.table-card,
.chart-card,
.auth-card,
.empty {
  position: relative;
}

.container::before,
.container::after,
.stat::before,
.stat::after,
.table-card::before,
.table-card::after,
.chart-card::before,
.chart-card::after,
.auth-card::before,
.auth-card::after,
.empty::before,
.empty::after {
  content: "";
  position: absolute;
  z-index: 1;
  width: var(--fr);
  height: var(--fr);
  pointer-events: none;
  transition: border-color 0.18s var(--ease);
}
.container::before,
.stat::before,
.table-card::before,
.chart-card::before,
.auth-card::before,
.empty::before {
  top: 0;
  left: 0;
  border-top: 1.5px solid var(--frame-ink);
  border-left: 1.5px solid var(--frame-ink);
  border-top-left-radius: var(--fr-radius);
}
.container::after,
.stat::after,
.table-card::after,
.chart-card::after,
.auth-card::after,
.empty::after {
  bottom: 0;
  right: 0;
  border-bottom: 1.5px solid var(--frame-ink);
  border-right: 1.5px solid var(--frame-ink);
  border-bottom-right-radius: var(--fr-radius);
}

/* scale 1 of 3 -- page */
.container { --fr: 26px; --fr-radius: 0px; --frame-ink: var(--border-strong); }

/* scale 2 of 3 -- section (tables, chart cards, auth card, empty state) */
.table-card,
.chart-card,
.auth-card,
.empty { --fr: 14px; --fr-radius: 3px; --frame-ink: var(--border-strong); }

/* scale 3 of 3 -- tile (stat cards). Status color, which #18 carried in a
   separate top strip, now lives directly in the bracket ink -- the frame
   is the thing that carries meaning, not just geometry. */
.stat { --fr: 8px; --fr-radius: 2px; --frame-ink: var(--border); }
.stat:hover { --frame-ink: var(--border-strong); }
.stat-accent { --frame-ink: var(--accent); }
.stat-accent .stat-value { color: var(--accent); }
.stat-good { --frame-ink: var(--good); }
.stat-good .stat-value { color: var(--good); }
.stat-warning { --frame-ink: var(--warning); }
.stat-warning .stat-value { color: var(--warning); }
.stat-critical { --frame-ink: var(--critical); }
.stat-critical .stat-value { color: var(--critical); }

/* ---------------------------------------------------------------------- */
/* Health badge                                                            */
/* ---------------------------------------------------------------------- */

.status-line { display: flex; align-items: center; gap: 0.6rem; }

.health {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  padding: 0.45rem 1rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  background: var(--surface);
  backdrop-filter: blur(8px);
}
.health .dot { width: 7px; height: 7px; border-radius: 50%; }
.health-healthy { color: var(--good); }
.health-healthy .dot { background: var(--good); box-shadow: 0 0 0 3px var(--good-wash); }
.health-degraded { color: var(--critical); }
.health-degraded .dot { background: var(--critical); box-shadow: 0 0 0 3px var(--critical-wash); }

/* "Always computing" indicator -- a small traced lemniscate placed next to
   live/refreshing regions (dashboard health line, metrics timestamp). Not
   tied to the actual network request (this app has no client JS fetch loop
   by design), it is atmospheric: the system is always in motion. */
.pulse-infinity {
  width: 20px;
  height: 13px;
  overflow: visible;
  flex: none;
  opacity: 0.7;
}
.pulse-infinity path {
  fill: none;
  stroke: var(--muted);
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-dasharray: 4.5 3.5;
  animation: infinity-trace 11s linear infinite;
}

/* ---------------------------------------------------------------------- */
/* Stat grid                                                                */
/* ---------------------------------------------------------------------- */

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 0.75rem;
  margin: 0 0 3rem;
}

.stat {
  background: var(--surface);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1.1rem 1.1rem 0.95rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  transition: background-color 0.18s var(--ease), border-color 0.18s var(--ease);
}
.stat:hover {
  background: var(--surface-alt);
  border-color: var(--border-strong);
}

.stat-value {
  font-size: 2.1rem;
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.stat-label {
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* Status color lives in the bracket-frame ink (--frame-ink), set per
   .stat-accent/.stat-good/.stat-warning/.stat-critical above, alongside the
   .stat-value color rules. No separate top strip needed. */

/* ---------------------------------------------------------------------- */
/* Infinity -- figure-eight job summary, two lobes of one curve (from #16). */
/* The single strongest layout idea across all three PRs: the dashboard's   */
/* job counts are grouped into two lobes -- "in flight" and "resolved" --   */
/* on either side of a waist, the same crossing point the wordmark draws.   */
/* A thin dashed lemniscate threads behind both lobes with a small dot      */
/* travelling the full loop: work entering on the left, exiting resolved    */
/* on the right, endlessly. The tiles inside each lobe are plain .stat      */
/* elements, so they carry the same bracket-frame + glass surface as        */
/* every other tile on the page -- this is a layout accent, not a second    */
/* card system.                                                             */
/* ---------------------------------------------------------------------- */

.infinity-summary {
  position: relative;
  margin: 0 0 3rem;
  padding: 2.75rem 0 1.25rem;
}
.infinity-summary-curve {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}
.infinity-summary-curve .lobe-line {
  fill: none;
  stroke: var(--border-strong);
  stroke-width: 1.5;
  stroke-dasharray: 3 6;
}
.infinity-summary-curve .lobe-pulse {
  fill: var(--accent);
  filter: drop-shadow(0 0 4px var(--accent-wash));
}

.lobe-grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(0.75rem, 2.5vw, 2.5rem);
  align-items: stretch;
}

.lobe {
  background: var(--surface);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 1.3rem 1.3rem 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  transition: border-color 0.18s var(--ease), background-color 0.18s var(--ease);
}
.lobe:hover { border-color: var(--border-strong); }

.lobe-label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.lobe-label .lobe-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex: none; }
.lobe-right .lobe-label .lobe-dot { background: var(--good); }

.lobe-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 0.6rem;
}

/* ---------------------------------------------------------------------- */
/* Tables                                                                   */
/* ---------------------------------------------------------------------- */

.table-card {
  background: var(--surface);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

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

table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.86rem;
}

table.data th,
table.data td {
  padding: 0.65rem 0.9rem;
  text-align: left;
  vertical-align: top;
  overflow-wrap: anywhere;
  border-bottom: 1px solid var(--gridline);
}

table.data tbody tr { transition: background-color 0.12s var(--ease); }
table.data tbody tr:hover { background: var(--surface-alt); }
table.data tbody tr:last-child td { border-bottom: none; }

table.data thead th {
  background: var(--surface-alt);
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.num { font-variant-numeric: tabular-nums; color: var(--text-secondary); }

table.meta th {
  width: 12rem;
  color: var(--muted);
  font-weight: 500;
  font-size: 0.82rem;
}
table.meta td { font-size: 0.88rem; }
.meta-card { margin-top: 0.25rem; }

.job-link { font-family: var(--font-mono); font-size: 0.85rem; }

code {
  font-family: var(--font-mono);
  font-size: 0.85em;
  background: var(--surface-alt);
  padding: 0.1rem 0.4rem;
  border-radius: 4px;
}

/* ---------------------------------------------------------------------- */
/* Status pills & process badges                                           */
/* ---------------------------------------------------------------------- */

.status {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.25rem 0.7rem;
  border-radius: var(--radius-pill);
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
}
.status .dot { width: 6px; height: 6px; border-radius: 50%; flex: none; }

.status-running { background: var(--accent-wash); color: var(--accent); }
.status-running .dot { background: var(--accent); animation: dot-pulse 2.3s ease-in-out infinite; }

.status-waiting,
.status-waiting_approval,
.status-prepared { background: var(--surface-alt); color: var(--text-secondary); }
.status-waiting .dot,
.status-waiting_approval .dot,
.status-prepared .dot { background: var(--muted); }

.status-completed { background: var(--good-wash); color: var(--good); }
.status-completed .dot { background: var(--good); }

.status-failed { background: var(--critical-wash); color: var(--critical); }
.status-failed .dot { background: var(--critical); }

.status-stalled { background: var(--warning-wash); color: var(--warning); }
.status-stalled .dot { background: var(--warning); }

.status-validating,
.status-rework { background: var(--accent-wash); color: var(--accent); }
.status-validating .dot,
.status-rework .dot { background: var(--accent); animation: dot-pulse 2.3s ease-in-out infinite; }

.status-aberta { background: var(--surface-alt); color: var(--muted); }
.status-aberta .dot { background: var(--muted); }

@keyframes dot-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--accent-wash); }
  50% { box-shadow: 0 0 0 4px var(--accent-wash); }
}

.proc {
  font-size: 0.78rem;
  font-weight: 500;
}
.proc-alive { color: var(--good); }
.proc-down { color: var(--muted); }

.error-cell { color: var(--critical); font-size: 0.85rem; }

/* ---------------------------------------------------------------------- */
/* Empty states & alerts                                                   */
/* ---------------------------------------------------------------------- */

.empty {
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 2.75rem 1.5rem 2.25rem;
  text-align: center;
  font-size: 0.9rem;
  background: var(--surface);
}

.alert {
  border-radius: var(--radius-sm);
  padding: 0.65rem 0.9rem;
  font-size: 0.87rem;
  margin: 0 0 1.25rem;
  border: 1px solid transparent;
}
.alert-good { background: var(--good-wash); color: var(--good); border-color: var(--good-wash); }
.alert-critical { background: var(--critical-wash); color: var(--critical); border-color: var(--critical-wash); }

/* ---------------------------------------------------------------------- */
/* Forms & buttons                                                         */
/* ---------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 0.55rem 1.1rem;
  font-size: 0.88rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: transform 0.1s var(--ease), box-shadow 0.15s var(--ease), background-color 0.15s var(--ease), opacity 0.15s var(--ease);
}
.btn:hover { opacity: 0.92; }
.btn:active { transform: scale(0.98); }

.btn-primary {
  background: var(--accent);
  color: var(--accent-text);
  border-radius: var(--radius-pill);
  padding: 0.7rem 1.6rem;
}
.btn-primary:hover { background: var(--accent-strong); opacity: 1; }

/* Outlined rather than a second filled color -- monochrome palette has no
   hue to spare for "this one's different/riskier", so the distinction from
   .btn-primary is border-vs-fill instead (execution-mode step-up uses
   this). */
.btn-warning {
  background: transparent;
  border: 1.5px solid var(--text);
  color: var(--text);
}
.btn-warning:hover { background: var(--surface-alt); opacity: 1; }

.auth-shell {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: center;
  padding: 2.5rem 0 1rem;
}

.auth-card {
  width: 100%;
  max-width: 380px;
  background: var(--surface-alt);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 2rem 2rem 2.25rem;
}
.auth-card .page-title { margin-bottom: 1.25rem; }

.admin-form {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.admin-form label {
  color: var(--text-secondary);
  font-size: 0.82rem;
  font-weight: 500;
  margin-top: 0.75rem;
}
.admin-form label:first-child { margin-top: 0; }

.admin-form input,
.admin-form textarea {
  background: var(--surface-solid);
  border: 1px solid var(--border);
  border-radius: 9px;
  color: var(--text);
  padding: 0.6rem 0.75rem;
  font-size: 0.95rem;
  font-family: inherit;
  resize: vertical;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}
.admin-form input:hover,
.admin-form textarea:hover { border-color: var(--border-strong); }
.admin-form input:focus,
.admin-form textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-wash);
}

.admin-form .btn { margin-top: 1.4rem; width: 100%; }

/* ---------------------------------------------------------------------- */
/* Charts -- hand-rolled inline SVG, no charting library.                  */
/* ---------------------------------------------------------------------- */

.chart-card {
  background: var(--surface);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1.1rem 1.25rem 1.25rem;
}

.chart-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1rem;
  margin: 0 0 3rem;
}

.chart-title {
  margin: 0 0 0.9rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-secondary);
}

.bar-rows { display: flex; flex-direction: column; gap: 0.55rem; }

.bar-row {
  display: grid;
  grid-template-columns: minmax(72px, 30%) 1fr auto;
  align-items: center;
  gap: 0.6rem;
}

.bar-row-label {
  font-size: 0.8rem;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bar-row-track {
  background: var(--chart-track);
  border-radius: 4px;
  height: 14px;
  overflow: hidden;
}

.bar-row-track svg {
  display: block;
  width: 100%;
  height: 100%;
}

.bar-row-value {
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  min-width: 2.2rem;
  text-align: right;
}

.donut-wrap {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  flex-wrap: wrap;
}

.donut-wrap svg { flex: none; }

.donut-legend {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  font-size: 0.82rem;
}

.donut-legend-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--text-secondary);
}

.donut-legend-swatch {
  width: 9px;
  height: 9px;
  border-radius: 3px;
  flex: none;
}

.donut-legend-value {
  color: var(--text);
  font-variant-numeric: tabular-nums;
  margin-left: auto;
  padding-left: 0.75rem;
}

.chart-empty {
  color: var(--muted);
  font-size: 0.85rem;
  padding: 1.5rem 0;
  text-align: center;
}

.chart-unavailable {
  color: var(--muted);
  font-size: 0.82rem;
  padding: 0.5rem 0;
}

/* ---------------------------------------------------------------------- */
/* Metrics panel                                                           */
/* ---------------------------------------------------------------------- */

.stat-sm .stat-value { font-size: 1.5rem; }

.machine-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }

.section-note {
  margin: -0.5rem 0 1rem;
  color: var(--muted);
  font-size: 0.82rem;
}

.online-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; margin-right: 0.4rem; }
.online-dot.is-online { background: var(--good); box-shadow: 0 0 0 3px var(--good-wash); }
.online-dot.is-offline { background: var(--muted); }

/* ---------------------------------------------------------------------- */
/* Chat (Admin V2 Phase 2)                                                  */
/* ---------------------------------------------------------------------- */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.chat-note {
  color: var(--text-secondary);
  font-size: 0.88rem;
  max-width: 62ch;
  margin: -0.5rem 0 1.25rem;
}

.chat-card {
  position: relative;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  backdrop-filter: blur(8px);
  padding: 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}

.chat-log {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  min-height: 8rem;
  max-height: 32rem;
  overflow-y: auto;
  padding-right: 0.25rem;
}

/* Redesign (2026-08-26): "meu chat de execução tem que ser idêntico aqui,
   até design" -- Thiago wants both chat surfaces to read like Claude
   Code's own interface, not an iMessage-style bubble thread. That means a
   flat, full-width transcript: a small role label above each turn, a
   thin left accent bar instead of a colored pill, monospace for code/
   tool-call content and sans for prose, real markdown rendering (see
   chat_markdown.js), and tool invocations as their own collapsible
   blocks. Reuses the site's existing tokens throughout (--surface,
   --accent, --font-mono, --border, ...) -- no new palette. */

.chat-bubble {
  max-width: 100%;
  width: 100%;
  padding: 0 0 0 1rem;
  font-size: 0.98rem;
  line-height: 1.6;
  word-break: break-word;
  border-left: 2px solid var(--border);
}

.chat-bubble::before {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: 0.3rem;
}

.chat-bubble-user {
  border-left-color: var(--border-strong);
  color: var(--text);
}
.chat-bubble-user::before {
  content: "Você";
  color: var(--muted);
}

.chat-bubble-assistant {
  border-left-color: var(--accent);
  color: var(--text);
}
.chat-bubble-assistant::before {
  content: "Claude";
  color: var(--accent);
}
/* Sandbox chats (/sandbox/<username>) talk to other self-hosted models, not
   Claude -- the label comes from the server/JS via data-role-label instead
   of being hardcoded. Attribute selector wins on specificity over the
   plain-class rule above regardless of source order. */
.chat-bubble-assistant[data-role-label]::before {
  content: attr(data-role-label);
}

/* ---- Markdown-lite rendering (chat_markdown.js) ------------------------ */

.chat-md-p { margin: 0 0 0.75rem; white-space: pre-wrap; }
.chat-md-p:last-child { margin-bottom: 0; }

.chat-md-heading {
  margin: 0.9rem 0 0.4rem;
  font-weight: 650;
  line-height: 1.3;
}
.chat-md-heading:first-child { margin-top: 0; }

.chat-md-list {
  margin: 0 0 0.75rem;
  padding-left: 1.3rem;
}
.chat-md-list li { margin: 0.2rem 0; }

.chat-inline-code {
  font-family: var(--font-mono);
  font-size: 0.88em;
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.05rem 0.35rem;
}

.chat-md-code {
  margin: 0 0 0.75rem;
  padding: 0.75rem 0.9rem;
  border-radius: var(--radius-sm);
  background: var(--surface-alt);
  border: 1px solid var(--border);
  overflow-x: auto;
}
.chat-md-code code {
  font-family: var(--font-mono);
  font-size: 0.86rem;
  line-height: 1.5;
  white-space: pre;
  background: none;
  border: none;
  padding: 0;
}

/* ---- Tool-call blocks -- Claude Code-style collapsible invocations ---- */

.chat-tool-call {
  margin: 0.5rem 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-alt);
  font-family: var(--font-mono);
  font-size: 0.85rem;
}

.chat-tool-call-summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0.7rem;
  cursor: pointer;
  color: var(--text-secondary);
  list-style: none;
}
.chat-tool-call-summary::-webkit-details-marker { display: none; }

.chat-tool-call-icon {
  color: var(--muted);
  transition: transform 0.12s var(--ease);
  flex-shrink: 0;
}
.chat-tool-call[open] .chat-tool-call-icon { transform: rotate(90deg); }

.chat-tool-call-name {
  font-weight: 650;
  color: var(--text);
  flex-shrink: 0;
}

.chat-tool-call-preview {
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.chat-tool-call-body {
  margin: 0;
  padding: 0.6rem 0.7rem;
  border-top: 1px solid var(--border);
  color: var(--text-secondary);
  overflow-x: auto;
  white-space: pre;
}

/* Legacy name-only marker (pre-2026-08-26 history) -- kept for old
   stored sessions that never got the richer [TOOL_CALL] marker. */
.chat-tool-tag {
  display: inline-block;
  margin: 0.35rem 0;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--muted);
  font-size: 0.78rem;
  font-family: var(--font-mono);
  letter-spacing: 0.01em;
}

/* ---- "Thinking" indicator ---------------------------------------------- */

.chat-thinking {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--muted);
  padding: 0.15rem 0;
}

.chat-thinking-dot {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: currentColor;
  animation: chat-thinking-pulse 1.1s ease-in-out infinite;
}
.chat-thinking-dot:nth-child(2) { animation-delay: 0.15s; }
.chat-thinking-dot:nth-child(3) { animation-delay: 0.3s; }

.chat-thinking-caption {
  font-size: 0.82rem;
  font-family: var(--font-mono);
}

@keyframes chat-thinking-pulse {
  0%, 80%, 100% { opacity: 0.25; transform: scale(0.85); }
  40% { opacity: 1; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .chat-thinking-dot { animation: none; opacity: 0.6; }
}

@media (max-width: 640px) {
  .chat-bubble {
    font-size: 1rem;
  }
  .chat-log {
    max-height: 60vh;
  }
}

.chat-form {
  display: flex;
  gap: 0.6rem;
  align-items: flex-end;
}

.chat-form textarea {
  flex: 1;
  resize: vertical;
  min-height: 2.6rem;
  max-height: 10rem;
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface-alt);
  color: var(--text);
  font-family: inherit;
  font-size: 0.92rem;
}

.chat-form textarea:focus {
  outline: none;
  border-color: var(--accent);
}

.chat-form .btn { flex-shrink: 0; }

/* ---------------------------------------------------------------------- */
/* Execution-mode chat                                                     */
/* ---------------------------------------------------------------------- */

.chat-card-exec {
  border-color: var(--warning);
  box-shadow: 0 0 0 1px var(--warning-wash);
}

.chat-bubble-exec-blocked {
  border-left-color: var(--critical);
  background: var(--critical-wash);
  color: var(--critical);
  padding-top: 0.4rem;
  padding-bottom: 0.4rem;
}
.chat-bubble-exec-blocked::before {
  content: "Bloqueado";
  color: var(--critical);
}

.chat-exec-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  margin: 0 0 1rem;
  font-size: 0.85rem;
}

/* ---------------------------------------------------------------------- */
/* Immersive full-page chat (execution mode) -- Thiago's ask: the whole    */
/* page is the conversation, not a boxed card floating in the dashboard    */
/* chrome. Forced onto the dark (black/white) token set regardless of the  */
/* light/dark toggle.                                                       */
/* ---------------------------------------------------------------------- */

body:has(main.chat-immersive) {
  display: flex;
  flex-direction: column;
  /* 100vh on mobile includes the address bar's reserved space, which isn't
     actually visible -- the layout ends up taller than the real viewport,
     pushing the message input down below what's on screen (worse once the
     on-screen keyboard opens). 100dvh tracks the real visible viewport on
     browsers that support it; the 100vh line above is the fallback for
     ones that don't. Real bug reported live, 2026-08-21. */
  min-height: 100vh;
  min-height: 100dvh;
}
body:has(main.chat-immersive) .site-header { flex-shrink: 0; }

main.chat-immersive {
  /* Force the dark token set for this page regardless of the site's
     light/dark toggle -- bubbles, borders and accent colors below all key
     off these same custom properties, so without this override a
     light-themed visitor would get a black page with light-mode (i.e.
     invisible/mismatched) bubble colors. */
  color-scheme: dark;
  --surface: rgba(255, 255, 255, 0.045);
  --surface-alt: rgba(255, 255, 255, 0.065);
  --text: #f5f5f5;
  --text-secondary: #b3b3b3;
  --muted: #7a7a7a;
  --border: rgba(255, 255, 255, 0.12);
  --accent: #f5f5f5;
  --accent-strong: #ffffff;
  --accent-text: #0a0a0a;
  --critical: #ffffff;
  --critical-wash: rgba(245, 245, 245, 0.14);

  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: #000000;
  color: var(--text);
  max-width: 780px;
  width: 100%;
  margin: 0 auto;
  padding: 1rem clamp(1rem, 3vw, 1.5rem) clamp(1rem, 3vw, 1.5rem);
}

.chat-immersive .chat-exec-toolbar {
  color: var(--text-secondary);
  flex-shrink: 0;
}
.chat-immersive .back-link { margin: 0; }
.chat-immersive .back-link a { color: var(--muted); }
.chat-immersive .back-link a:hover { color: var(--text); }

.chat-immersive .chat-card {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: transparent;
  border: none;
  backdrop-filter: none;
  padding: 0;
}

.chat-immersive .chat-log {
  flex: 1;
  max-height: none;
  min-height: 0;
  padding: 0.5rem 0.25rem;
}

.chat-immersive .chat-form {
  flex-shrink: 0;
  align-items: center;
  padding-top: 0.5rem;
}

.chat-immersive .chat-form textarea {
  background: var(--surface-alt);
  border-color: var(--border);
  color: var(--text);
  border-radius: 20px;
  padding: 0.7rem 1.1rem;
  resize: none;
}

.chat-send-btn {
  flex-shrink: 0;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  border: none;
  background: var(--accent);
  color: var(--accent-text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform 0.12s var(--ease), opacity 0.12s var(--ease);
}
.chat-send-btn svg { width: 1.2rem; height: 1.2rem; }
.chat-send-btn:hover { transform: scale(1.06); }
.chat-send-btn:disabled { opacity: 0.5; cursor: default; transform: none; }

.chat-exec-toolbar-label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--muted);
}

#chat-session-picker {
  font-size: 0.85rem;
  padding: 0.3rem 0.5rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  max-width: 22rem;
}

.chat-exec-continuous-badge {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  color: var(--success, var(--accent));
  font-weight: 600;
}

.chat-exec-toolbar-dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 20%, transparent);
}

.chat-turn-status {
  font-size: 0.78rem;
  color: var(--muted);
  margin-top: 0.25rem;
}

/* ---------------------------------------------------------------------- */
/* RafaCodex (2026-08-26) -- Thiago's direção visual explícita pro painel:
   "não preto; branco metálico com tons de azul". É uma identidade própria,
   fixa (não segue dark mode como o resto do site) pra distinguir claramente
   a superfície do RafaCodex das outras telas de execução. Reaproveita os
   MESMOS componentes .chat-card/.chat-log/.chat-exec-* (nenhuma classe
   nova de layout) só redefinindo os tokens de cor localmente -- mesmo
   princípio já documentado acima ("Reuses the site's existing tokens
   throughout... no new palette"), aplicado a uma segunda paleta em vez de
   inventar CSS de componente novo. */
.theme-rafacodex {
  --bg: #f2f5f8;
  --surface: #ffffff;
  --surface-solid: #ffffff;
  --surface-alt: #eef3fc;
  --text: #16202e;
  --text-secondary: #5c7085;
  --muted: #5c7085;
  --border: #d7e0ea;
  --border-strong: #b7c6da;
  --accent: #2f5fd6;
  --accent-strong: #24499f;
  --accent-text: #ffffff;
  --accent-wash: rgba(47, 95, 214, 0.08);
  --shadow-sm: 0 1px 3px rgba(30, 64, 140, 0.08);
  --shadow-md: 0 8px 20px rgba(30, 64, 140, 0.08), 0 1px 2px rgba(30, 64, 140, 0.05);
  --shadow-lg: 0 20px 44px rgba(30, 64, 140, 0.12), 0 2px 6px rgba(30, 64, 140, 0.06);
  background: var(--bg);
  color: var(--text);
}

/* Card de preview/confirmação (ação de execução aguardando aprovação humana)
   -- precisa se destacar do resto do transcript, é o momento mais importante
   da tela. Reaproveita .chat-bubble como base (já é o bloco de turno) com um
   modificador; aplicar via JS/servidor quando o turno for desse tipo. */
.theme-rafacodex .chat-bubble.is-confirm {
  border-left-width: 2px;
  border-left-color: var(--accent);
  background: var(--accent-wash);
  border-radius: var(--radius-sm);
  padding: 0.75rem 1rem;
}

/* ---------------------------------------------------------------------- */
/* Repo guide -- live-read "comece por aqui" sections                      */
/* ---------------------------------------------------------------------- */

.repo-guide-card { padding: 1.25rem 1.5rem; }

.repo-guide-section { font-size: 0.92rem; line-height: 1.6; color: var(--text); }
.repo-guide-section p { margin: 0 0 0.9rem; }
.repo-guide-section p:last-child { margin-bottom: 0; }
.repo-guide-section ul { margin: 0 0 0.9rem; padding-left: 1.3rem; }
.repo-guide-section li { margin: 0 0 0.4rem; }
.repo-guide-section li:last-child { margin-bottom: 0; }
.repo-guide-section strong { font-weight: 650; }
.repo-guide-section a { color: var(--accent); }
.repo-guide-subhead { color: var(--text-secondary); text-transform: uppercase; font-size: 0.76rem; letter-spacing: 0.05em; }

/* ---------------------------------------------------------------------- */
/* Responsive                                                              */
/* ---------------------------------------------------------------------- */

@media (max-width: 640px) {
  .site-header-inner { padding: 0.7rem 1rem; }
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
  table.meta th { width: 8rem; }
  .auth-card { padding: 1.5rem 1.25rem 1.75rem; }
  .bar-row { grid-template-columns: minmax(60px, 38%) 1fr auto; }
  .container { --fr: 16px; }
  .lobe-grid { grid-template-columns: 1fr; }
  .lobe-left, .lobe-right { border-radius: var(--radius-lg); }
  .infinity-summary-curve { display: none; }
  .infinity-summary { padding-top: 0.5rem; }
  .lobe-stats { grid-template-columns: repeat(2, 1fr); }
}

/* ---------------------------------------------------------------------- */
/* Kanban board                                                            */
/* ---------------------------------------------------------------------- */
/* Read-only, derived-from-real-data board (mybagcenter-site#29 + multi-tab
   extension -- see kanban.py's module docstring). Tab switching and the
   priority/category filters are JS enhancements (factory.js); with JS
   disabled every tab panel and every card simply stays visible/unfiltered
   -- still fully correct data, just not tabbed/filtered, matching this
   file's existing "additive, never load-bearing" JS convention. */

.kanban-tabbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 1rem 0 1.5rem;
}
.kanban-tab-btn {
  font: inherit;
  cursor: pointer;
  background: var(--surface-alt);
  color: var(--text-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.45rem 1rem;
  font-weight: 650;
  font-size: 0.85rem;
  transition: background-color 0.15s var(--ease), color 0.15s var(--ease), border-color 0.15s var(--ease);
}
.kanban-tab-btn:hover { border-color: var(--border-strong); }
.kanban-tab-btn.is-active { background: var(--accent); color: var(--accent-text); border-color: var(--accent); }
.kanban-tab-count {
  display: inline-block;
  margin-left: 0.4rem;
  opacity: 0.8;
  font-variant-numeric: tabular-nums;
}

.kanban-tab-panel { margin-bottom: 2rem; }
.kanban-tab-panel[hidden] { display: none; }

.kanban-tab-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.kanban-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin: 0.75rem 0 1.25rem;
}
.kanban-filter-field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.78rem;
  color: var(--text-secondary);
  font-weight: 600;
}
.kanban-filter {
  font: inherit;
  padding: 0.4rem 0.6rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface-solid);
  color: var(--text);
}

.kanban-board {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  align-items: start;
}

.kanban-column {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  backdrop-filter: blur(6px);
  min-width: 0;
}
.kanban-column-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
}
.kanban-column-head h3 {
  margin: 0;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
}
.kanban-column-count {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--muted);
  background: var(--surface-alt);
  border-radius: var(--radius-pill);
  padding: 0.1rem 0.55rem;
  font-size: 0.8rem;
}
.kanban-column[data-column="doing"] .kanban-column-count { color: var(--accent); }
.kanban-column[data-column="done"] .kanban-column-count { color: var(--good); }

.kanban-column-body {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 0.85rem;
  max-height: 70vh;
  overflow-y: auto;
}
.kanban-empty { margin: 0.5rem 0; padding: 1rem 0.5rem; }

.kanban-card {
  display: block;
  background: var(--surface-solid);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.75rem 0.85rem;
  text-decoration: none;
  color: inherit;
  box-shadow: var(--shadow-sm);
  transition: transform 0.12s var(--ease), box-shadow 0.12s var(--ease), border-color 0.12s var(--ease);
}
.kanban-card:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); border-color: var(--border-strong); }
.kanban-card-failed { border-color: var(--critical); }
.kanban-card[hidden] { display: none; }

.kanban-card-top { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.35rem; }
.kanban-card-issue { font-family: var(--font-mono); font-size: 0.75rem; color: var(--muted); }

.kanban-priority {
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  padding: 0.1rem 0.4rem;
  border-radius: var(--radius-pill);
  background: var(--surface-alt);
  color: var(--text-secondary);
}
.kanban-priority-p0 { background: var(--critical-wash); color: var(--critical); }
.kanban-priority-p1 { background: var(--warning-wash); color: var(--warning); }
.kanban-priority-p2 { background: var(--accent-wash); color: var(--accent); }
.kanban-priority-p3 { background: var(--good-wash); color: var(--good); }

.kanban-card-title { margin: 0 0 0.3rem; font-weight: 650; font-size: 0.92rem; line-height: 1.3; }
.kanban-card-desc { margin: 0 0 0.5rem; font-size: 0.82rem; color: var(--text-secondary); line-height: 1.4; }

.kanban-card-meta { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 0.5rem; }
.kanban-card-category,
.kanban-card-agent {
  font-size: 0.72rem;
  color: var(--text-secondary);
  background: var(--surface-alt);
  border-radius: var(--radius-sm);
  padding: 0.12rem 0.45rem;
}

.kanban-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.kanban-card-date { font-size: 0.72rem; color: var(--muted); font-variant-numeric: tabular-nums; }

@media (max-width: 900px) {
  .kanban-board { grid-template-columns: 1fr; }
  .kanban-column-body { max-height: none; overflow-y: visible; }
}

/* ---- AS-IS/TO-BE project vision page (generic) -----------------------
   Originated on /admin/james (mesh vision, 2026-08-26); renamed from
   .james-* to .vision-* the same day so /admin/projetos (project pages,
   starting with SANDBOX) can reuse it without a name that only makes
   sense for the first page it appeared on. ---- */
.vision-section { margin-top: 2.5rem; }

.vision-tag {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.2rem 0.6rem;
  border-radius: var(--radius-sm);
  display: inline-block;
  margin-bottom: 0.6rem;
  border: 1px solid var(--border);
}

.vision-tag--as-is { background: var(--surface-alt); color: var(--muted); }
.vision-tag--to-be { background: var(--accent-wash); color: var(--accent-strong); border-color: var(--accent-strong); }

.vision-panel {
  background: var(--surface-solid);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1.5rem 1.75rem;
  box-shadow: var(--shadow-sm);
}

.vision-panel p { max-width: 68ch; }
.vision-panel p + p { margin-top: 0.9rem; }

.vision-diagram {
  margin-top: 1.25rem;
  padding: 1.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.25rem;
}

.vision-hub {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  text-align: center;
  padding: 0.9rem 1.4rem;
  border-radius: var(--radius-pill);
  background: var(--accent-strong);
  color: var(--accent-text);
  line-height: 1.35;
}

.vision-hub--mesh { background: var(--accent-strong); }
.vision-hub-sub { font-size: 0.7rem; opacity: 0.75; }

.vision-spokes {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem;
}

.vision-node {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  padding: 0.45rem 0.8rem;
  border-radius: var(--radius-sm);
  background: var(--surface-solid);
  border: 1px solid var(--border-strong);
}

.vision-node em { font-style: normal; color: var(--muted); display: block; font-size: 0.7rem; margin-top: 0.15rem; }
.vision-node--dim { opacity: 0.55; border-style: dashed; }
.vision-node--new { border-color: var(--good); color: var(--good); }

.vision-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  margin-top: 1.25rem;
}

.vision-table thead th {
  text-align: left;
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 500;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--border);
}

.vision-table tbody td {
  padding: 0.6rem 0.4rem;
  border-bottom: 1px solid var(--border);
}

.vision-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  padding: 0.18rem 0.55rem 0.18rem 0.45rem;
  border-radius: var(--radius-pill);
}

.vision-pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; }
.vision-pill--hub { background: var(--surface-alt); color: var(--muted); }
.vision-pill--hub::before { background: var(--muted); }
.vision-pill--none { background: var(--warning-wash); color: var(--warning); }
.vision-pill--none::before { background: var(--warning); }
.vision-pill--live { background: var(--good-wash); color: var(--good); }
.vision-pill--live::before { background: var(--good); }

.vision-gap-list { list-style: none; margin: 1.25rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.8rem; }

.vision-gap-item {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.9rem;
  align-items: start;
  background: var(--surface-solid);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.9rem 1.1rem;
}

.vision-gap-item strong { display: block; font-size: 0.95rem; margin-bottom: 0.15rem; }
.vision-detail { color: var(--text-secondary); font-size: 0.88rem; max-width: 60ch; }

.vision-badge {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
  padding: 0.2rem 0.5rem;
  border-radius: var(--radius-sm);
  align-self: center;
}

.vision-badge--blocked { background: var(--warning-wash); color: var(--warning); }
.vision-badge--todo { background: var(--surface-alt); color: var(--muted); border: 1px solid var(--border); }

@media (max-width: 640px) {
  .vision-gap-item { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------- */
/* Genesis -- public landing page (2026-08-26).                            */
/*                                                                          */
/* Same monochrome black/white/gray system as the rest of factory.css --   */
/* no new hues are introduced here. Apple/Vercel/Linear/Stripe-minimal per */
/* Thiago's brief: large confident type in the existing --font-sans stack, */
/* --font-mono reserved for technical labels (the pairing this file        */
/* already used for .entropy-caption/.vision-node), generous whitespace,    */
/* motion that explains a causal chain rather than decorating the page.    */
/* Every visual on this page reuses REAL product vocabulary rather than    */
/* invented UI: the .status-* pills are the exact classes the live job     */
/* dashboard renders, .online-dot is the exact class the metrics panel     */
/* renders -- "product as protagonist" without needing screenshots.        */
/* ---------------------------------------------------------------------- */

.main--genesis { max-width: 1180px; }

.genesis-page {
  display: flex;
  flex-direction: column;
}

.genesis-eyebrow {
  margin: 0 0 1.1rem;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--muted);
}

.genesis-h2 {
  margin: 0 0 1.1rem;
  font-size: clamp(1.65rem, 3.4vw, 2.4rem);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.015em;
  text-wrap: balance;
  max-width: 22ch;
}

.genesis-body {
  margin: 0;
  max-width: 62ch;
  font-size: 1.02rem;
  line-height: 1.65;
  color: var(--text-secondary);
}

/* ---- hero ---- */

.genesis-hero {
  padding: clamp(2.5rem, 8vw, 6rem) 0 clamp(3rem, 7vw, 5rem);
}

.genesis-h1 {
  margin: 0 0 1.5rem;
  font-size: clamp(2.75rem, 7vw, 5.5rem);
  font-weight: 700;
  line-height: 0.98;
  letter-spacing: -0.03em;
  text-wrap: balance;
}

.genesis-lede {
  margin: 0 0 2.25rem;
  max-width: 46ch;
  font-size: clamp(1.05rem, 1.6vw, 1.25rem);
  line-height: 1.6;
  color: var(--text-secondary);
}

.genesis-cta-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1.75rem;
  margin-bottom: clamp(3.5rem, 8vw, 6rem);
}

.genesis-cta-secondary {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--text-secondary);
  font-weight: 600;
  font-size: 0.95rem;
}
.genesis-cta-secondary svg { width: 15px; height: 15px; transition: transform 0.15s var(--ease); }
.genesis-cta-secondary:hover { color: var(--text); }
.genesis-cta-secondary:hover svg { transform: translate(1px, -1px); }

/* Causal flow diagram: intenção -> issue -> agente -> código -> testes ->
   deploy. Pure CSS -- each connector owns one travelling dot, staggered by
   --i so the motion reads left-to-right as one continuous causal chain
   rather than six things blinking independently. */
.genesis-flow {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0;
  padding: 1.75rem clamp(1rem, 3vw, 2rem);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.genesis-flow-node {
  flex: none;
  padding: 0.55rem 0.95rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  background: var(--surface-solid);
}
.genesis-flow-label {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--text-secondary);
  white-space: nowrap;
}
.genesis-flow-node--accent { border-color: var(--accent); }
.genesis-flow-node--accent .genesis-flow-label { color: var(--accent); }
.genesis-flow-node--good { border-color: var(--good); }
.genesis-flow-node--good .genesis-flow-label { color: var(--good); }

.genesis-flow-link {
  position: relative;
  flex: 1 1 28px;
  min-width: 20px;
  height: 1px;
  background: var(--border-strong);
  margin: 0 0.15rem;
}
.genesis-flow-dot {
  position: absolute;
  top: 50%;
  left: 0;
  width: 5px;
  height: 5px;
  margin-top: -2.5px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-wash);
  animation: genesis-flow-travel 3.6s var(--ease-loop) infinite;
  animation-delay: calc(var(--i) * 0.4s);
}
@keyframes genesis-flow-travel {
  0% { left: 0; opacity: 0; }
  8% { opacity: 1; }
  46% { left: 100%; opacity: 1; }
  54% { opacity: 0; }
  100% { left: 100%; opacity: 0; }
}

@media (max-width: 720px) {
  .genesis-flow { flex-direction: column; align-items: stretch; gap: 0.6rem; }
  .genesis-flow-node { text-align: center; }
  .genesis-flow-link { width: 1px; height: 22px; margin: 0 auto; }
  .genesis-flow-dot { top: 0; left: 50%; margin-top: 0; margin-left: -2.5px; }
  @keyframes genesis-flow-travel {
    0% { top: 0; opacity: 0; }
    8% { opacity: 1; }
    46% { top: 100%; opacity: 1; }
    54% { opacity: 0; }
    100% { top: 100%; opacity: 0; }
  }
}

/* ---- shared section rhythm ---- */

.genesis-section {
  padding: clamp(2.5rem, 6vw, 4rem) 0;
  border-top: 1px solid var(--gridline);
}

/* ---- Factory: real status-pill pipeline ---- */

.genesis-pipeline {
  margin-top: 2rem;
  padding: 1.75rem clamp(1rem, 3vw, 2rem) 2rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}
.genesis-pipeline-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
}
.genesis-pipeline-row--terminal { margin-top: 0.9rem; }
.genesis-pipeline-arrow {
  color: var(--muted);
  font-size: 0.95rem;
}
.genesis-pipeline-branch {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0.9rem 0 0 1.4rem;
}
.genesis-pipeline-branch-arrow {
  color: var(--muted);
  font-size: 1.1rem;
  transform: scaleX(-1);
}
.genesis-pipeline-row--terminal .genesis-pipeline-branch-arrow { transform: none; }
.genesis-pipeline-branch-note {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  color: var(--muted);
}

/* ---- Infraestrutura: hub + real nodes ---- */

.genesis-mesh {
  margin-top: 2rem;
  padding: 2rem clamp(1rem, 3vw, 2rem);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.5rem;
}
.genesis-mesh-hub {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  padding: 0.9rem 1.6rem;
  border-radius: var(--radius-pill);
  background: var(--accent-strong);
  color: var(--accent-text);
}
.genesis-mesh-hub-label {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 600;
}
.genesis-mesh-hub-sub {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  opacity: 0.75;
}
.genesis-mesh-spokes {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.9rem;
}
.genesis-mesh-node {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  padding: 0.7rem 1.3rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--surface-solid);
}
.genesis-mesh-node .online-dot { margin: 0 0 0.3rem; }
.genesis-mesh-node-name {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 600;
}
.genesis-mesh-node-detail {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--muted);
}

/* ---- Filosofia ---- */

.genesis-quote-lead {
  margin: 0 0 2.5rem;
  max-width: 30ch;
  font-size: clamp(1.4rem, 2.6vw, 1.9rem);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

.genesis-principles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1.5rem 2rem;
  margin-bottom: 2rem;
}
.genesis-principle {
  padding-top: 0.9rem;
  border-top: 1px solid var(--border-strong);
}
.genesis-principle-num {
  margin: 0 0 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.genesis-principle-name {
  margin: 0 0 0.4rem;
  font-size: 1.02rem;
  font-weight: 650;
}
.genesis-principle-text {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--text-secondary);
}

.genesis-caption {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--muted);
}

/* ---- closing ---- */

.genesis-cta {
  padding: clamp(3rem, 7vw, 4.5rem) 0 clamp(1.5rem, 3vw, 2rem);
  text-align: center;
}
.genesis-cta-line {
  margin: 0 0 0.4rem;
  font-size: 1.05rem;
  font-weight: 600;
}
.genesis-cta-sub {
  margin: 0;
  font-size: 0.85rem;
  color: var(--muted);
}
.genesis-cta-sub code {
  font-size: 0.85em;
}

@media (prefers-reduced-motion: reduce) {
  .genesis-flow-dot {
    animation: none !important;
    opacity: 0.9;
  }
}


/* ---- Self-hosted design editor ---- */
.design-page { max-width: none; padding-left: 1rem; padding-right: 1rem; }
.design-frame { width: 100%; height: calc(100vh - 150px); min-height: 680px; border: 1px solid var(--border); border-radius: var(--radius-md); background: white; }
.sandbox-tabs { display: flex; gap: .5rem; margin-bottom: 1rem; }
.sandbox-tabs a { padding: .5rem 1rem; border: 1px solid var(--border); border-radius: var(--radius-pill); }
.sandbox-tabs a[aria-current="page"] { background: var(--accent); color: var(--accent-text); }

/* Maestro cockpit: one-click universe switching, responsive to narrow terminals. */
.maestro-grid { display:grid; grid-template-columns:minmax(12rem, 18rem) minmax(0, 1fr); gap:1rem; align-items:start; }
.maestro-sidebar, .session-card { border:1px solid var(--border); border-radius:var(--radius-md); background:var(--surface); }
.maestro-sidebar { padding:1rem; display:grid; gap:.45rem; position:sticky; top:1rem; }
.maestro-sidebar h2 { margin:.1rem 0 .5rem; }
.maestro-sidebar a { padding:.65rem .75rem; border-radius:var(--radius-sm); color:var(--text-muted); text-decoration:none; }
.maestro-sidebar a:hover, .maestro-sidebar .maestro-nav-active { color:var(--text); background:var(--surface-raised); }
.section-heading, .session-card-head { display:flex; align-items:center; justify-content:space-between; gap:.75rem; }
.session-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(16rem,1fr)); gap:1rem; }
.session-card { padding:1rem; min-width:0; }
.session-card p { color:var(--text-muted); font-size:.9rem; }
.session-preview { white-space:pre-wrap; overflow-wrap:anywhere; max-height:5rem; overflow:hidden; }
.status-dot { width:.6rem; height:.6rem; border-radius:50%; background:var(--brand-grad-2); flex:0 0 auto; }
.session-status { margin-left:auto; font-size:.75rem; color:var(--text-muted); }
@media (max-width: 700px) {
  .maestro-grid { grid-template-columns:1fr; }
  .maestro-sidebar { position:static; display:flex; overflow-x:auto; gap:.35rem; }
  .maestro-sidebar h2 { display:none; }
  .maestro-sidebar a { white-space:nowrap; }
  .session-grid { grid-template-columns:1fr; }
}

/* ── Campo de senha com revelar ─────────────────────────────────────────
   Thiago (2026-08-28): "design tem que ser padrão apple e vercel de login.
   Não está. O olhinho não literal, mas pra ver a senha e conferir."

   O emoji 👁 era literal demais -- num formulário Apple/Vercel o controle de
   revelar é texto discreto ou ícone traçado, no tom secundário, dentro do
   próprio campo. Aqui é a palavra: menos ruído visual que um ícone e diz
   exatamente o que faz, o que também resolve leitor de tela sem aria extra.

   Usa os tokens que já existem no arquivo; não introduz cor nova. */
.senha-campo {
  position: relative;
  display: block;
}

.senha-campo input {
  width: 100%;
  padding-right: 4.25rem;   /* espaço do botão, para o texto nunca passar por baixo */
}

.senha-revelar {
  position: absolute;
  top: 50%;
  right: 0.7rem;
  transform: translateY(-50%);
  background: none;
  border: 0;
  padding: 0.2rem 0.35rem;
  font: inherit;
  font-size: 0.78rem;
  letter-spacing: 0.01em;
  color: var(--muted);
  cursor: pointer;
  border-radius: 4px;
  transition: color 0.15s var(--ease, ease);
}

.senha-revelar:hover { color: var(--text); }

/* Foco visível de propósito: quem navega por teclado precisa enxergar onde
   está, e um controle dentro do campo é fácil de perder. */
.senha-revelar:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  color: var(--text);
}

/* ---- Estado do agente, junto do campo de escrever (Maestro) -------------
   Thiago (2026-08-28), usando a tela: "isso tem que ficar embaixo, tipo no
   chat do Claude no app [...] aqui pode ser aquele símbolo do infinito
   carregando". Fica entre o fio da conversa e o campo -- onde a vista já
   está quando se espera resposta, e não num canto do topo.

   Sem cor nova: `--muted` para o texto, `--accent` só quando está
   trabalhando, que é o único estado em que a espera é normal. */
.maestro-estado {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.1rem 0.55rem;
  font-size: 0.82rem;
  color: var(--muted);
  min-height: 1.9rem;   /* reserva o espaço: a linha não pode empurrar o
                           campo de escrever para baixo quando o estado muda */
}
.maestro-estado .pulse-infinity { width: 30px; height: auto; }
.maestro-estado[data-estado="trabalhando"] { color: var(--accent); }

/* Os dois estados que pedem AÇÃO de gente, não paciência. Continuam sóbrios
   -- o objetivo é a pessoa reparar, não a tela gritar. */
.maestro-estado[data-estado="aguardando-humano"],
.maestro-estado[data-estado="entrada-pendente"] { color: var(--text); }
.maestro-estado[data-estado="aguardando-humano"] .chat-exec-toolbar-dot,
.maestro-estado[data-estado="entrada-pendente"] .chat-exec-toolbar-dot {
  background: var(--accent);
}

/* Trabalhando: só o infinito, no centro. Pedido do Thiago depois de ver a
   primeira versão no ar -- a animação já diz "está acontecendo", e a frase ao
   lado repetia o que o desenho mostra. Os outros estados continuam com texto:
   símbolo mudo não serve para "parado esperando permissão". */
.maestro-estado[data-estado="trabalhando"] { justify-content: center; }
.maestro-estado[data-estado="trabalhando"] .pulse-infinity { width: 38px; }

/* ---- Composer no padrão WhatsApp (Maestro) ------------------------------
   Thiago (2026-08-28), usando a tela: "tem que ser padrão WhatsApp, quando eu
   escrevo começa a sumir, e no whats não é botão enviar, é aquele ícone de
   aviãozinho de papel". */
.chat-form #chat-input {
  resize: none;          /* a altura é o JS que decide (maestro.js) */
  overflow-y: hidden;
  line-height: 1.45;
}

/* Botão redondo só com o ícone. Fica alinhado embaixo para não subir junto
   quando o campo cresce -- no WhatsApp o avião não sai do lugar. */
.btn-enviar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: flex-end;
  width: 2.4rem;
  height: 2.4rem;
  padding: 0;
  border-radius: 999px;
  flex-shrink: 0;
}
.btn-enviar svg {
  width: 1.05rem;
  height: 1.05rem;
  fill: currentColor;
  /* leve deslocamento: o desenho do avião é opticamente pesado à esquerda */
  margin-left: 1px;
}

/* Hora também nas mensagens de quem escreve. A regra do assistente já usava
   `data-role-label`; a do usuário tinha "Você" fixo no CSS e por isso não
   tinha como carregar o horário junto. Thiago: "o seu tem horário, mas o meu
   não, legal seria se o meu tivesse". */
.chat-bubble-user[data-role-label]::before {
  content: attr(data-role-label);
  color: var(--muted);
}

/* ---- Permissão pendente (Maestro) ---------------------------------------
   Mostra por inteiro o que o agente está pedindo. Sóbrio de propósito: é
   informação para ler, não alarme para reagir -- e o texto do comando é a
   parte que importa, não a moldura. */
.permissao-pendente {
  border: 1px solid var(--border);
  border-left: 2px solid var(--accent);
  border-radius: 8px;
  padding: 0.8rem 0.9rem;
  margin: 0 0 0.75rem;
  background: var(--surface);
}
.permissao-titulo {
  margin: 0 0 0.5rem;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text);
}
.permissao-pedido {
  margin: 0 0 0.6rem;
  padding: 0.55rem 0.7rem;
  background: var(--surface-2, var(--bg));
  border-radius: 6px;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 11rem;
  overflow-y: auto;   /* comando longo rola aqui, não estica a página */
  color: var(--text);
}
.permissao-opcoes { margin: 0 0 0.5rem; padding-left: 0; list-style: none; }
.permissao-opcoes li {
  font-size: 0.84rem;
  color: var(--muted);
  padding: 0.12rem 0;
}
.permissao-opcoes kbd {
  font-family: var(--font-mono);
  font-size: 0.74rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.05rem 0.35rem;
  margin-right: 0.35rem;
  color: var(--text);
}

/* Preserva as quebras de linha da mensagem.
   Thiago (2026-08-28): "quebra em linhas as tuas mensagens [...] eu gosto de
   quebra de linhas, fica mais legível e eu entendo melhor".
   As quebras SEMPRE estiveram lá -- o HTML é que colapsa espaço em branco por
   padrão, então um texto com parágrafos chegava como um bloco só. */
.chat-bubble { white-space: pre-wrap; }

/* A atividade ao vivo, ao lado do infinito. Monoespaçada porque é a mesma
   linha do terminal e o número muda a cada segundo -- fonte proporcional
   faria o texto dançar. */
.maestro-atividade {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  color: var(--accent);
  opacity: 0.85;
  font-variant-numeric: tabular-nums;
}
/* Recebeu e ainda não respondeu: o estado que substitui o "Ocioso" mentiroso.
   Tom de quem está devendo resposta, não de alarme. */
.maestro-estado[data-estado="sua-vez-dele"] { color: var(--accent); }

/* ---- Bolhas distinguíveis à distância (Maestro) -------------------------
   Thiago (2026-08-28): "no GPT minhas mensagens ficam num balão azul e o
   Claude um balão cinza. É isso que está faltando."

   Reverte, para ESTA tela, a escolha anterior de transcrição plana estilo
   Claude Code. O motivo é o uso real: ele conversa com nove agentes por aqui,
   e precisa achar a própria fala rolando rápido. Barra fina à esquerda exige
   ler para saber de quem é; fundo se distingue de relance.

   Sem cor nova: os mesmos tokens do resto do site. */
.chat-card-exec .chat-bubble {
  padding: 0.6rem 0.8rem;
  border-radius: 12px;
  border-left: none;
  margin-bottom: 0.55rem;
  max-width: 82%;
}
.chat-card-exec .chat-bubble-user {
  background: var(--accent-soft, color-mix(in srgb, var(--accent) 14%, transparent));
  margin-left: auto;              /* a própria fala encosta à direita */
  border-bottom-right-radius: 4px;
}
.chat-card-exec .chat-bubble-assistant {
  background: var(--surface);
  border: 1px solid var(--border);
  border-bottom-left-radius: 4px;
}

/* ---------------------------------------------------------------------- */
/* Botões de permissão e blocos de terminal (/admin/agentes).             */
/*                                                                        */
/* Thiago (2026-08-29): "pode ser uma linha por vez: verde sim, vermelho   */
/* não" e "tudo na web".                                                   */
/*                                                                        */
/* Sem JavaScript: cada botão é um submit de <form>. A CSP servida é       */
/* `script-src 'self'` e já matou três telas deste projeto em silêncio --  */
/* a que não depende de script não tem como quebrar assim.                 */
/* ---------------------------------------------------------------------- */

.permissao-acoes {
  display: flex;
  flex-wrap: wrap;      /* comando longo não empurra botão para fora da tela */
  gap: 0.5rem;
  margin: 0 0 0.5rem;
}

.botao-permissao {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35rem;
  padding: 0.45rem 0.8rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--surface-alt);
  color: var(--text);
  font-size: 0.86rem;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
}
.botao-permissao:hover { border-color: var(--text); }

/* A COR NUNCA É A ÚNICA DISTINÇÃO: o rótulo diz "Sim"/"Não"/"Política" em
   texto, e o texto da própria opção vem junto. Quem não separa verde de
   vermelho continua conseguindo decidir. */
.botao-sim {
  border-color: #1a7f37;
  background: color-mix(in srgb, #1a7f37 12%, transparent);
  color: #116329;
}
.botao-nao {
  border-color: #cf222e;
  background: color-mix(in srgb, #cf222e 12%, transparent);
  color: #a40e26;
}
/* "Yes, and don't ask again" muda a política do agente, não responde à
   pergunta -- então não pode parecer o botão de aprovar. Fica neutro. */
.botao-politica { opacity: 0.85; }

:root:not([data-theme="light"]) .botao-sim,
:root[data-theme="dark"] .botao-sim { color: #4ac26b; border-color: #2ea043; }
:root:not([data-theme="light"]) .botao-nao,
:root[data-theme="dark"] .botao-nao { color: #ff7b72; border-color: #da3633; }

.botao-permissao-texto { font-weight: 400; opacity: 0.85; }

.terminal-bloco {
  border: 1px solid var(--border);
  border-radius: 8px;
  margin: 0 0 0.5rem;
  background: var(--surface);
}
.terminal-bloco > summary {
  cursor: pointer;
  padding: 0.55rem 0.8rem;
  font-size: 0.9rem;
  font-weight: 600;
}

/* O terminal é escuro nos dois temas, de propósito: é a reprodução de uma
   tela de terminal, e ela não muda de cor conforme o tema do site. Cores
   fixas aqui são a exceção justificada, não descuido. */
.terminal-saida {
  margin: 0;
  padding: 0.7rem 0.9rem;
  background: #0b0b0f;
  color: #d7d7e0;
  border-top: 1px solid var(--border);
  border-radius: 0 0 8px 8px;
  font-family: var(--font-mono);
  font-size: 0.74rem;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 22rem;
  overflow: auto;
}
