/* ============================================================================
   personas_analytics — internal dashboard styles
   NTT DATA palette, shared with the runs index (report_server.py _INDEX_HTML).
   No build step: plain CSS, mobile-friendly, soft shadows, rounded cards.
   ----------------------------------------------------------------------------
   DESIGN SYSTEM (Phase 1 — transversal base; consumed by every dashboard
   screen and the upcoming screens). Sections in this file, in order:

     1. Tokens .......... brand palette + semantic status colors (vars).
     2. Buttons ......... .btn-primary (the single ACTION-blue CTA), .btn-secondary,
                          .btn-ghost (destructive, error-toned — NEVER the action color),
                          .btn-danger (alias of the destructive ghost).
     3. Badges .......... semantic STATUS pills: .badge-success / -warning /
                          -error / -neutral. Colors outside the brand palette
                          are deliberate, justified semantic exceptions.
     4. Chips ........... neutral CATEGORY pill (.chip): rule/near-white surface,
                          navy/muted text, uniform height, tabular numbers.
                          The action color is NOT used for category chips — it is
                          reserved for the primary CTA, the active nav item and row hover.
     5. Empty/loading/error state .... .empty-state component (icon + title +
                          muted text + optional CTA) used inside a card. Mirrors
                          the `empty_state()` Jinja macro in _components.html.
     6. Utilities ....... .tnum (tabular-nums), focus ring, 24px hit targets.

   BRAND ACTION COLOR (2026 NTT DATA rebrand): the action color is NTT Future
   Blue #0072BC (hover Future Blue 150 #005B96), NOT the previous amber. Every
   CTA / active nav item / row hover / focus ring now renders blue. The legacy
   `--amber*` tokens are kept ONLY as backward-compatible ALIASES of the new
   `--action*` tokens so the ~40 existing rules need no edits; they no longer
   carry any yellow. Prefer the `--action*` tokens in new code.

   ACCESSIBILITY: status badge/chip text colors are picked to clear WCAG AA
   (>= 4.5:1) on their own tinted surfaces. Future Blue #0072BC clears AA as
   text on white (≈ 4.6:1), so it is safe both as the CTA surface (white text on
   blue) and, where needed, as foreground. The alert state uses Future Blue 150
   (#005B96) text on a pale-blue surface (#E6F1F8) — no yellow anywhere.
   ========================================================================== */

/* ── 1. Tokens — NTT DATA palette + semantic status colors ────────────────── */
:root {
  /* Brand palette (non-negotiable). */
  --navy:       #070F26;                  /* Smart Navy                         */

  /* ACTION color — NTT Future Blue. This is the single brand accent for CTAs,
     the active nav item, row/card hover washes and the focus glow. */
  --action:       #0072BC;                /* Future Blue — primary action       */
  --action-hover: #005B96;                /* Future Blue 150 — button hover      */
  --action-pale:  rgba(0, 114, 188, .10); /* row hover + active-nav wash         */
  --action-glow:  rgba(0, 114, 188, .30); /* focus ring                         */

  /* Legacy aliases — kept so the ~40 existing `var(--amber*)` rules keep working
     without per-rule edits. These now resolve to the BLUE action color above;
     despite the name, NO yellow is rendered. Do not use in new code. */
  --amber:      var(--action);
  --amber-pale: var(--action-pale);
  --amber-glow: var(--action-glow);

  --bg:         #F4F5F8;
  --card:       #FFFFFF;
  --muted:      #6B7280;
  --rule:       #E9EAED;

  /* Semantic status colors (justified exceptions to the brand palette — used
     only to communicate state, never as decoration). Foreground tokens are
     AA-legible on their paired *-bg tints below. */
  --danger:        #991b1b;               /* error text (red-800)               */
  --danger-bg:     #FEF2F2;               /* error surface (red-50)             */
  --success:       #166534;               /* success text (green-800)           */
  --success-bg:    #F0FDF4;               /* success surface (green-50)         */
  /* ALERT / "incomplete" / "running" state. The previous amber alert tone
     (dark-amber text on amber-100) is replaced by a neutral blue that is NOT the
     action blue: Future Blue 150 text (#005B96) on a pale-blue surface
     (#E6F1F8). #005B96 on #E6F1F8 clears WCAG AA for normal text (≈ 6.7:1).
     No yellow remains. */
  --warning:       #005B96;               /* alert text — Future Blue 150       */
  --warning-bg:    #E6F1F8;               /* alert surface — pale blue          */
  --neutral-fg:    #4B5563;               /* neutral status text (gray-600)     */
  --neutral-bg:    #F3F4F6;               /* neutral surface (gray-100)         */

  /* Chip (neutral category) surface — near-white, distinct from --bg cards. */
  --chip-bg:       #F3F4F6;
  --chip-border:   var(--rule);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--navy);
  min-height: 100vh;
  line-height: 1.5;
}

a { color: inherit; }

/*
  Visible focus ring for keyboard navigation (DESIGN_REVIEW #24). Applies to
  EVERY actionable control: buttons, links (incl. nav + shortcuts), form inputs,
  selects, checkboxes, and any element opted into keyboard interaction
  (clickable table rows carry [tabindex] / [role="button"]). The action-glow
  (Future Blue) outline is brand-consistent and meets the non-text-contrast
  requirement.
*/
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible,
[role="button"]:focus-visible {
  outline: 3px solid var(--amber-glow);
  outline-offset: 2px;
}

/* ── Header / nav ─────────────────────────────────────────────────────────── */
header {
  background: var(--navy);
  color: #fff;
  padding: 0 40px;
  min-height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  border-bottom: 3px solid var(--amber);
}

.header-brand { display: flex; align-items: center; gap: 14px; text-decoration: none; }
.header-brand .logo-mark {
  width: 36px; height: 36px;
  background: var(--action); border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  font-size: 18px; font-weight: 900; color: #fff;   /* white on Future Blue (navy-on-blue would fail AA) */
  letter-spacing: -1px; flex-shrink: 0;
}
.header-brand h1 { font-size: 16px; font-weight: 700; letter-spacing: -.2px; color: #fff; }
.header-brand .sub {
  font-size: 11px; color: rgba(255, 255, 255, .5); margin-top: 1px;
  letter-spacing: .2px; text-transform: uppercase;
}

.main-nav { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.main-nav a {
  font-size: 13px; font-weight: 600; color: rgba(255, 255, 255, .65);
  text-decoration: none; padding: 8px 14px; border-radius: 6px;
  transition: color .15s, background .15s;
}
.main-nav a:hover { color: #fff; background: rgba(255, 255, 255, .08); }
.main-nav a.active { color: #fff; background: var(--action); }  /* white on Future Blue */
.main-nav a.logout { color: rgba(255, 255, 255, .5); }
.main-nav a.logout:hover { color: #fff; }

/* ── Layout ───────────────────────────────────────────────────────────────── */
main { max-width: 1040px; margin: 0 auto; padding: 36px 24px; }

.page-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 24px;
}
.page-head h2 { font-size: 22px; font-weight: 800; letter-spacing: -.4px; }
.page-head p.lead { font-size: 13px; color: var(--muted); margin-top: 4px; }

.section-title {
  font-size: 11px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: 2px;
  margin: 28px 0 18px; display: flex; align-items: center; gap: 8px;
}
.section-title::after { content: ''; flex: 1; height: 1px; background: var(--rule); }

/* ── 2. Buttons (DESIGN_REVIEW #6) ────────────────────────────────────────────
   ONE primary button, used identically everywhere (home, lists, forms, /run):
     .btn-primary   Future Blue surface, WHITE text — the single CTA / active
                    action. Hover darkens to Future Blue 150 (--action-hover).
     .btn-secondary white surface, navy text, rule border, action-blue border on
                    hover — non-primary actions (Editar, Cancelar, Atualizar).
     .btn-ghost     transparent, navy text, rule border — low-emphasis neutral
                    actions (Voltar, Cancelar, Clonar). NEVER the action color.
     .btn-danger    DESTRUCTIVE action (Excluir): transparent with error-toned
                    (red) text + border, red wash on hover. NEVER the action
                    color. This is the canonical destructive button;
                    `.btn-ghost.is-danger` aliases it for templates that prefer
                    the ghost naming.
   All buttons share a min-height so even `.btn-sm` per-row actions stay >= 24px
   tall (DESIGN_REVIEW #24). Same padding/radius/weight across variants. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font-size: 13px; font-weight: 700; letter-spacing: .2px;
  padding: 9px 18px; border-radius: 8px; border: 1.5px solid transparent;
  cursor: pointer; text-decoration: none; transition: all .15s;
  font-family: inherit; line-height: 1;
  min-height: 38px;                            /* comfortable target; >= 24px even when shrunk */
}
/* White-on-Future-Blue clears AA (white on #0072BC ≈ 4.6:1). Hover darkens the
   surface to Future Blue 150 instead of relying on amber-toned shadow alone. */
.btn-primary { background: var(--action); color: #fff; }
.btn-primary:hover { background: var(--action-hover); box-shadow: 0 6px 18px var(--action-glow); transform: translateY(-1px); }
.btn-secondary { background: var(--card); color: var(--navy); border-color: var(--rule); }
.btn-secondary:hover { border-color: var(--action); }
.btn-ghost { background: transparent; color: var(--navy); border-color: var(--rule); }
.btn-ghost:hover { border-color: var(--navy); }
/* Destructive: error-toned, never brand amber. */
.btn-danger,
.btn-ghost.is-danger { background: transparent; color: var(--danger); border-color: rgba(153, 27, 27, .3); }
.btn-danger:hover,
.btn-ghost.is-danger:hover { background: var(--danger-bg); border-color: var(--danger); }
/* Compact row actions still keep a >= 24px clickable target. */
.btn-sm { padding: 6px 12px; font-size: 12px; min-height: 30px; }
/* Prominent CTA modifiers (DESIGN_REVIEW #4): larger type/padding for a single
   dominant action, and full-width when the button owns its card. Reusable across
   screens; on /run the submit pairs both so it reads as THE action. */
.btn-lg { padding: 13px 24px; font-size: 15px; min-height: 48px; }
.btn-block { display: flex; width: 100%; }
.btn:disabled { opacity: .5; cursor: not-allowed; transform: none; box-shadow: none; }

/* ── Cards ────────────────────────────────────────────────────────────────── */
.card {
  background: var(--card); border-radius: 12px; padding: 22px 26px;
  border: 1.5px solid var(--rule);
  box-shadow: 0 1px 3px rgba(8, 15, 39, .06), 0 1px 2px rgba(8, 15, 39, .04);
}

.card-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
}
.shortcut {
  display: block; background: var(--card); border-radius: 12px; padding: 24px;
  text-decoration: none; color: inherit; border: 1.5px solid var(--rule);
  box-shadow: 0 1px 3px rgba(8, 15, 39, .06);
  transition: border-color .18s, box-shadow .18s, transform .12s;
}
.shortcut:hover {
  border-color: var(--amber); transform: translateY(-2px);
  box-shadow: 0 6px 24px var(--amber-glow), 0 1px 3px rgba(8, 15, 39, .06);
}
/* DESIGN_REVIEW #20: home shortcut icons are a single monochrome line-icon set
   (inline SVG, no icon library / no build step). They inherit the card's navy
   via currentColor and are aria-hidden in the markup — purely decorative, since
   each card's <h3> carries the meaning. Sober and consistent across the grid,
   replacing the prior multicolor emojis. */
.shortcut .ico { margin-bottom: 12px; line-height: 0; color: var(--navy); }
.shortcut .ico svg { width: 28px; height: 28px; display: block; }
.shortcut h3 { font-size: 16px; font-weight: 800; margin-bottom: 6px; }
.shortcut p { font-size: 12px; color: var(--muted); line-height: 1.5; }
/* Count badge on shortcut cards: NEUTRAL surface (DESIGN_REVIEW #3). Amber is
   reserved for the primary CTA / active nav / row hover, so a count (data, not
   action) must not borrow the brand color. */
.shortcut .count {
  display: inline-block; margin-top: 12px; font-size: 12px; font-weight: 700;
  color: var(--navy); background: var(--chip-bg); border: 1px solid var(--rule);
  padding: 3px 10px; border-radius: 8px;
  font-variant-numeric: tabular-nums;
}
/* Action affordance for shortcut cards whose footer is an ACTION (e.g. "Iniciar
   agora", "Ver resultados"), not DATA (DESIGN_REVIEW #9/#43). Rendered as a
   navy link with a trailing arrow instead of a chip, so it never reads as a
   second amber CTA competing with the single primary button on the home. The
   arrow nudges right on card hover to reinforce the affordance. */
.shortcut .go {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 12px;
  font-size: 12px; font-weight: 700; color: var(--navy);
}
.shortcut .go .arrow { font-weight: 700; transition: transform .15s; }
.shortcut:hover .go .arrow { transform: translateX(3px); }

/* ── Tables ───────────────────────────────────────────────────────────────── */
.table-wrap {
  background: var(--card); border-radius: 12px; border: 1.5px solid var(--rule);
  box-shadow: 0 1px 3px rgba(8, 15, 39, .06); overflow-x: auto;
}
table { width: 100%; border-collapse: collapse; font-size: 13px; }
thead th {
  text-align: left; font-size: 11px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .8px;
  padding: 14px 18px; border-bottom: 1.5px solid var(--rule); white-space: nowrap;
}
tbody td { padding: 14px 18px; border-bottom: 1px solid var(--rule); vertical-align: middle; }
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--amber-pale); }
td .strong { font-weight: 700; }
td .sub { font-size: 12px; color: var(--muted); }
.row-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
/* DESIGN_REVIEW #18: per-row actions on one horizontal line, with the
   destructive action set apart by a thin rule so "Excluir" never sits flush
   against "Editar"/"Clonar". Secondary actions stay grouped on the left. */
.row-actions--split { align-items: center; flex-wrap: nowrap; }
.row-actions-sep {
  width: 1px; align-self: stretch; min-height: 22px;
  background: var(--rule); margin: 0 2px;
}
@media (max-width: 640px) {
  /* Narrow screens: allow wrapping and drop the divider's stretch so the row
     never overflows the cell. */
  .row-actions--split { flex-wrap: wrap; }
  .row-actions-sep { display: none; }
}

/* ── 3. Chips — neutral CATEGORY pill (DESIGN_REVIEW #3/#5) ───────────────────
   The default chip is NEUTRAL (rule/near-white surface, navy/muted text). The
   action color is not a chip color — category data (outcome, archetype,
   scenario, FullStory signals, counts) must not borrow the brand action color.
   Chips share
   one height (min-height 22px), an 8px radius and consistent padding so the
   personas/experiments lists read as one system. Numbers like "×3" use
   tabular-nums so weights align. `.chip-muted` is kept as an explicit alias of
   the neutral default (templates pair `.chip .chip-muted`). */
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  min-height: 22px;
  padding: 3px 10px; border-radius: 8px; font-size: 11px; font-weight: 700;
  background: var(--chip-bg); color: var(--navy); letter-spacing: .2px;
  border: 1px solid var(--chip-border);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;          /* align "×3" / "×8" weights      */
}
.chip-muted { background: var(--chip-bg); color: var(--muted); border-color: var(--rule); }
/*
  Semantic outcome chip: the inline `color`/`border-color` come from
  `outcome_colors` (set per-row in the template). Here we only define the soft
  surface: a near-white background tinted slightly toward the semantic hue via
  color-mix, so the dark hue text stays AA-legible. The brand action color is
  intentionally NOT used here — it is reserved for CTAs and the active nav state.
*/
.chip-outcome {
  background: #fff;                                          /* fallback for browsers without color-mix support */
  background: color-mix(in srgb, currentColor 8%, #ffffff);
  border: 1px solid;            /* border-color provided inline */
  font-weight: 700;
}
.chip-list { display: flex; gap: 6px; flex-wrap: wrap; }

/* ── 4. Badges — semantic STATUS pill (DESIGN_REVIEW #4/#8) ───────────────────
   Reusable status indicators with a fixed meaning. Use these (NOT chips) to
   communicate state: a run's success, an incomplete/alert condition, an error,
   or a neutral/unknown state. Colors are semantic exceptions to the brand
   palette and are AA-legible on their tinted surfaces.

     .badge-success  green  — completed / converted / healthy.
     .badge-warning  Future Blue 150 (#005B96) on pale blue (#E6F1F8) — ALERT /
                              incomplete / needs review. A neutral non-yellow
                              alert tone, kept distinct from the brand action
                              blue (#0072BC) which signals action, not state.
     .badge-error    red    — failed / destructive outcome / hard error.
     .badge-neutral  gray   — undefined / informational / "no data".

   Shares the chip geometry so badges and chips line up in the same row. */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  min-height: 22px;
  padding: 3px 10px; border-radius: 8px; font-size: 11px; font-weight: 700;
  letter-spacing: .2px; white-space: nowrap;
  border: 1px solid transparent;
  font-variant-numeric: tabular-nums;
}
.badge-success { background: var(--success-bg); color: var(--success); border-color: rgba(22, 101, 52, .25); }
.badge-warning { background: var(--warning-bg); color: var(--warning); border-color: rgba(0, 91, 150, .25); }
.badge-error   { background: var(--danger-bg);  color: var(--danger);  border-color: rgba(153, 27, 27, .25); }
.badge-neutral { background: var(--neutral-bg); color: var(--neutral-fg); border-color: var(--rule); }

/* ── Forms ────────────────────────────────────────────────────────────────── */
.form-card {
  background: var(--card); border-radius: 12px; padding: 28px 32px;
  border: 1.5px solid var(--rule); box-shadow: 0 1px 3px rgba(8, 15, 39, .06);
}
.field-group {
  margin-bottom: 28px;
  /* No fieldset border/padding (the section title carries the grouping), so the
     legend never sits flush against a border edge. */
  border: 0; padding: 0; min-width: 0;
}
/* DESIGN_REVIEW #21: the section legend appeared clipped/flush against the
   fieldset edge. A native <legend> is positioned by the UA and can clip its
   text; forcing block layout with explicit width + zero inset lets the
   uppercase label render in full without being cut. */
.field-group > legend,
.field-group > .group-title {
  font-size: 11px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: 1.5px;
  margin: 0 0 16px; padding: 0; border: 0;
  display: block; float: none; width: 100%; max-width: 100%;
  overflow: visible; white-space: normal; line-height: 1.4;
}
.field-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px 20px;
}
.field { display: flex; flex-direction: column; gap: 6px; }
.field.full { grid-column: 1 / -1; }
.field label { font-size: 12px; font-weight: 600; color: var(--navy); }
.field .hint { font-size: 11px; color: var(--muted); }
/* Required-field marker (DESIGN_REVIEW #16): a visible asterisk next to the
   label of a mandatory control. aria-hidden in the markup so screen readers get
   the requirement from the input's aria-required, not a spoken "asterisk".
   Error-toned for affordance; never brand amber (amber = action, not state). */
.field label .req { color: var(--danger); margin-left: 2px; font-weight: 700; }
.field input,
.field select,
.field textarea {
  font-family: inherit; font-size: 14px; color: var(--navy);
  width: 100%;                                /* full-width controls keep columns uniform */
  padding: 10px 12px; border: 1.5px solid var(--rule); border-radius: 8px;
  background: #fff; transition: border-color .15s;
}
.field input:focus,
.field select:focus,
.field textarea:focus { border-color: var(--amber); }
.field textarea { resize: vertical; min-height: 72px; }

.dual-input { display: flex; align-items: center; gap: 8px; }
.dual-input input { width: 100%; }
.dual-input span { font-size: 12px; color: var(--muted); flex-shrink: 0; }

/* ── Persona form layout (scoped) ─────────────────────────────────────────────
   The persona form packs many short controls into a dense grid. These rules
   keep the columns from pinching on wide screens and make every control align
   on a common baseline so single-column fields, selects and min–max dual-inputs
   sit on the same row height. Scoped to `.persona-form` so the shared
   experiment/run screens that reuse `.field`/`.field-grid` are untouched. */
.persona-form .field-grid {
  /* Roomier minimum so a 4-up row never squeezes a number+spinner too tight;
     gracefully collapses to 2 and then 1 column on narrower viewports. */
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 18px 20px;
  align-items: start;                         /* cells size to content, hints push down only their own field */
}
/* Uniform control height across text/number inputs and selects so adjacent
   fields line up on the base regardless of native widget rendering. The
   intentional friction hitboxes live in the POC site, not in this dashboard,
   so a consistent box-model here is purely cosmetic. */
.persona-form .field input,
.persona-form .field select {
  height: 42px;
}
.persona-form .field textarea { height: auto; }
/* The dual-input wrapper must match the height of a single control so a
   min–max field aligns with the plain field beside it. */
.persona-form .dual-input { height: 42px; }
.persona-form .dual-input input { height: 100%; }

.form-actions {
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap;
  margin-top: 24px; padding-top: 24px; border-top: 1px solid var(--rule);
}

/* ── Persona checklist (experiment form) ──────────────────────────────────── */
.persona-pick { display: flex; flex-direction: column; gap: 10px; }
.persona-row {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 16px; border: 1.5px solid var(--rule); border-radius: 8px;
  transition: border-color .15s, background .15s;
}
.persona-row:hover { border-color: var(--amber); background: var(--amber-pale); }
/* Checkbox sized to a >= 24px hit target (DESIGN_REVIEW #24). */
.persona-row input[type="checkbox"] { width: 24px; height: 24px; accent-color: var(--navy); flex-shrink: 0; }
.persona-row .meta { flex: 1; min-width: 0; }
.persona-row .meta .strong { font-weight: 700; }
.persona-row .meta .sub { font-size: 12px; color: var(--muted); }
.persona-row .weight-field { display: flex; align-items: center; gap: 8px; }
.persona-row .weight-field label { font-size: 12px; color: var(--muted); }
.persona-row .weight-field input { width: 72px; }

/* DESIGN_REVIEW #11: an unchecked persona's row is dimmed and its (disabled)
   weight input is muted, reinforcing "weight only counts for checked personas".
   The row stops reacting to hover so it does not read as actionable amber. */
.persona-row.is-disabled { opacity: .65; }
.persona-row.is-disabled:hover { border-color: var(--rule); background: transparent; }
.persona-row .weight-field input:disabled {
  background: var(--neutral-bg); color: var(--muted);
  border-color: var(--rule); cursor: not-allowed;
}

/* Helper text spacing without inline styles (DESIGN_REVIEW: no inline style). */
.hint-spaced { margin-top: 12px; }

/* DESIGN_REVIEW #12: live "X personas · Y sessões" summary under the picker. */
.persona-summary {
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--rule);
  font-size: 13px; font-weight: 600; color: var(--navy);
}
.persona-summary .tnum { font-weight: 700; }

/* DESIGN_REVIEW #14: read-only persona id shown in the edit header. Muted,
   monospace (it is a technical key with underscores), and clearly non-editable
   — it carries no name= and is disabled, so it is never submitted. */
.form-id-line { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.form-id-label {
  font-size: 10px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: 1px;
}
.form-id-value {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 12px; color: var(--muted);
  background: var(--neutral-bg); border: 1px solid var(--rule); border-radius: 6px;
  padding: 4px 10px; width: auto; min-width: 0; cursor: default;
}

/* ── Rich profile (read-only "Como esta persona foi construída") ───────────────
   Display-only section in the persona form rendering the persona's `profile`
   dict. Discreet, on-brand styling reusing the existing tokens (no new palette):
   a card grid with a soft neutral surface, navy block titles, key→value
   definition lists, trait chips (the shared `.chip`) and a highlighted
   tone-of-voice quote. Scoped under `.profile-*` so it never touches the
   editable Identity/Cognitive/Behavior fields. */
.profile-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
}
.profile-card {
  background: var(--neutral-bg); border: 1px solid var(--rule);
  border-radius: 10px; padding: 16px 18px;
}
.profile-card-title {
  font-size: 11px; font-weight: 700; color: var(--navy);
  text-transform: uppercase; letter-spacing: 1px; margin-bottom: 12px;
}
/* Key → value pairs: muted uppercase term, navy definition; tight vertical
   rhythm so a card with several keys stays compact. */
.profile-dl { display: flex; flex-direction: column; gap: 10px; margin: 0; }
.profile-dl dt {
  font-size: 10px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .8px; margin-bottom: 2px;
}
.profile-dl dd { margin: 0; font-size: 13px; color: var(--navy); word-break: break-word; }
.profile-list { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 3px; }
.profile-list li { font-size: 13px; color: var(--navy); }

/* Trait chips reuse the neutral `.chip`; just give the row some breathing room. */
.profile-traits { margin-bottom: 12px; }

/* Tone-of-voice: a small label above a quoted sentence, accented with the
   brand action color on the left edge so it reads as a highlighted excerpt. */
.profile-tone {
  border-left: 3px solid var(--action); background: var(--card);
  border-radius: 0 8px 8px 0; padding: 10px 14px;
}
.profile-tone-label {
  display: block; font-size: 10px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .8px; margin-bottom: 4px;
}
.profile-tone-quote { font-size: 14px; font-style: italic; color: var(--navy); line-height: 1.5; }

/* Discreet note when no detailed profile exists. */
.profile-empty { margin-bottom: 28px; }

/* ── Alerts ───────────────────────────────────────────────────────────────── */
.alert {
  border-radius: 8px; padding: 12px 16px; font-size: 13px; font-weight: 600;
  margin-bottom: 20px; border: 1.5px solid transparent;
}
.alert-error { background: var(--danger-bg); color: var(--danger); border-color: rgba(153, 27, 27, .3); }
.alert-success { background: rgba(22, 101, 52, .08); color: var(--success); border-color: rgba(22, 101, 52, .3); }
/* Neutral/informational alert (e.g. the Azure provider note on /config). Muted
   navy on the soft brand-pale wash — reads as guidance, not error/success. The
   inline <code> keeps the monospace env-var name legible against the wash. */
.alert-info { background: var(--amber-pale); color: var(--navy); border-color: var(--rule); font-weight: 600; }
.alert-info code { font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; font-size: 12px; }

/* ── 5. Empty / loading / error state (DESIGN_REVIEW #8/#17) ──────────────────
   ONE reusable state component for "nothing here yet", "working…" and "it
   failed" — always rendered inside a card and the standard header, never as a
   bare page. Structure: icon + title (navy) + message (muted) + optional CTA.
   Mirrored by the `empty_state()` Jinja macro in dashboard/_components.html so
   later phases can drop a consistent block with one call.

   Variants (add alongside `.empty-state`):
     (default)              neutral "empty" — icon + title + message + CTA.
     .empty-state.is-loading swaps the icon for the shared .spinner.
     .empty-state.is-error   title turns error-red; pair with an error icon/CTA.

   `.empty` is kept as a backward-compatible alias of the default state so the
   existing personas/experiments/run templates keep rendering unchanged. */
.empty,
.empty-state { text-align: center; padding: 64px 20px; color: var(--muted); }
.empty .empty-icon,
.empty-state .empty-icon { font-size: 44px; margin-bottom: 14px; opacity: .6; line-height: 1; }
.empty h3,
.empty-state h3 { font-size: 16px; font-weight: 700; color: var(--navy); margin-bottom: 8px; }
.empty p,
.empty-state p { font-size: 13px; line-height: 1.6; }
/* Optional call-to-action sits below the message with breathing room. */
.empty-state .empty-cta { margin-top: 18px; }
/* Error variant: only the title shifts to the semantic error color. */
.empty-state.is-error h3 { color: var(--danger); }
/* Loading variant: the spinner replaces the static icon (icon slot hidden). */
.empty-state.is-loading .empty-icon { display: none; }
.empty-state.is-loading .spinner { margin-bottom: 16px; }

/* ── Login ────────────────────────────────────────────────────────────────── */
.login-shell {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 24px; background:
    radial-gradient(circle at 20% 20%, rgba(0, 114, 188, .18), transparent 45%),
    var(--navy);
}
.login-card {
  width: 100%; max-width: 380px; background: var(--card); border-radius: 16px;
  padding: 36px 32px; box-shadow: 0 24px 64px rgba(0, 0, 0, .35);
}
.login-card .brand { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
.login-card .brand .logo-mark {
  width: 40px; height: 40px; background: var(--action); border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; font-weight: 900; color: #fff; letter-spacing: -1px;  /* white on Future Blue */
}
.login-card .brand h1 { font-size: 18px; font-weight: 800; }
.login-card .brand .sub {
  font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 1px;
}
.login-card p.intro { font-size: 13px; color: var(--muted); margin: 14px 0 24px; }
.login-card .field { margin-bottom: 16px; }
.login-card .btn-primary { width: 100%; padding: 12px; }

/* ── Run execution screen ─────────────────────────────────────────────────── */
.run-grid { display: grid; grid-template-columns: 1fr; gap: 24px; }
@media (min-width: 820px) { .run-grid { grid-template-columns: 1.1fr .9fr; } }

/* Vertical rhythm between the run form fields, moved off inline styles
   (DESIGN_REVIEW: no inline style). The last field before the submit gets extra
   breathing room so the prominent CTA stands apart. */
.run-form .field { margin-bottom: 18px; }
.run-form .field:last-of-type { margin-bottom: 24px; }
/* The status-panel heading sits flush with the card top (no leading margin). */
.run-grid .section-title { margin-top: 0; }

/* Result CTA (revealed on success) spans the panel and sits below the status. */
.run-result-link { margin-top: 18px; }

/* The status panel has FOUR visually distinct, on-brand states (DESIGN_REVIEW
   #7). The JS (dashboard.js _setStatus) toggles is-idle / is-running / is-done /
   is-error on this element; the rules below give each a tinted surface, border
   and accent drawn ONLY from the Phase-1 semantic tokens (idle neutral, running
   alert-blue, done success-green, error red). No new palette. */
.run-status {
  display: flex; flex-direction: column; gap: 14px;
  min-height: 180px; justify-content: center; text-align: center;
  padding: 24px; border-radius: 10px;
  border: 1.5px solid var(--rule); background: var(--neutral-bg);
  transition: background .18s, border-color .18s;
}
.run-status .status-icon { font-size: 36px; }
.run-status .status-msg { font-size: 14px; font-weight: 600; color: var(--navy); }
.run-status .status-detail { font-size: 12px; color: var(--muted); }

/* Idle — neutral/waiting: muted surface, dimmed icon. */
.run-status.is-idle { background: var(--neutral-bg); border-color: var(--rule); }
.run-status.is-idle .status-icon { opacity: .5; }

/* Running — in progress: neutral pale-blue alert surface (the --warning token,
   now Future Blue 150 on pale blue — NOT the brand action blue, which signals
   the CTA) plus the shared spinner. */
.run-status.is-running { background: var(--warning-bg); border-color: rgba(0, 91, 150, .25); }
.run-status.is-running .status-msg { color: var(--warning); }

/* Done — success: green surface + accent, success-toned message. */
.run-status.is-done { background: var(--success-bg); border-color: rgba(22, 101, 52, .25); }
.run-status.is-done .status-msg { color: var(--success); }

/* Error — failure: red surface + accent, error-toned message. */
.run-status.is-error { background: var(--danger-bg); border-color: rgba(153, 27, 27, .25); }
.run-status.is-error .status-msg { color: var(--danger); }

/* Per-step progress bar (revealed by the run controller while a job runs). */
.progress-wrap { margin-top: 14px; }
.progress {
  height: 8px; border-radius: 999px; overflow: hidden;
  background: var(--action-pale);
}
.progress-bar {
  height: 100%; width: 0; border-radius: 999px;
  background: var(--action); transition: width .35s ease;
}
.progress-step {
  margin-top: 8px; font-size: 12px; font-weight: 600; color: var(--muted);
  text-align: center;
}

/* Spinner shown while a job is running. The track + head use the action tokens,
   so the spinner renders in Future Blue (via the --amber* aliases). */
.spinner {
  width: 36px; height: 36px; margin: 0 auto; border-radius: 50%;
  border: 4px solid var(--action-pale); border-top-color: var(--action);
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2.4s; } }

/* ── 6. Utilities ─────────────────────────────────────────────────────────── */
.muted { color: var(--muted); }
/* Tabular figures so KPIs and weight columns align digit-by-digit
   (DESIGN_REVIEW #19). `.tnum` is the canonical utility; `.mono` is kept as an
   alias already used by existing templates. */
.tnum,
.mono { font-variant-numeric: tabular-nums; }
.nowrap { white-space: nowrap; }
.hidden { display: none !important; }
.stack { display: flex; flex-direction: column; gap: 8px; }
.inline-form { display: inline; }

/* ── Runs index — run cards (Phase 2; DESIGN_REVIEW #15/#19/#78) ───────────────
   The runs index (dashboard/runs.html) needs a clickable card with a fixed
   4-KPI grid and an outcome badge row. These rules only add the layout the
   shared `.card`/`.badge`/`.chip`/`.tnum` primitives don't cover; all colors,
   the amber-pale hover and the focus ring come from the existing design-system
   tokens above — no new palette is introduced. */
.page-head-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

.run-list { display: flex; flex-direction: column; gap: 14px; }

/* The whole card is an <a> (keyboard-focusable, single click target #78). Hover
   reuses the same amber border + amber-glow lift as the home shortcuts. */
.run-card {
  display: block; background: var(--card); border-radius: 12px;
  padding: 22px 26px; text-decoration: none; color: inherit;
  border: 1.5px solid var(--rule);
  box-shadow: 0 1px 3px rgba(8, 15, 39, .06), 0 1px 2px rgba(8, 15, 39, .04);
  transition: border-color .18s, box-shadow .18s, transform .12s;
}
.run-card:hover {
  border-color: var(--amber); transform: translateY(-1px);
  box-shadow: 0 6px 24px var(--amber-glow), 0 1px 3px rgba(8, 15, 39, .06);
}

.run-card-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 18px;
}
.run-card-title { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.run-id { font-size: 14px; font-weight: 700; color: var(--navy); letter-spacing: -.1px; }
.run-card-meta {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  justify-content: flex-end;
}
.run-ts { font-size: 11px; color: var(--muted); }

/* ONE standardized 4-KPI grid for every card (complete or incomplete). On
   narrow viewports it folds to 2 columns rather than squeezing. */
.run-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 18px; }
@media (max-width: 560px) { .run-kpis { grid-template-columns: repeat(2, 1fr); } }
.kpi {
  display: flex; flex-direction: column; gap: 5px;
  background: var(--bg); padding: 14px 16px; border-radius: 8px;
  border-left: 3px solid var(--amber);
}
.kpi-v { font-size: 24px; font-weight: 800; color: var(--navy); line-height: 1; }
.kpi-l { font-size: 10px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .8px; }

.run-outcomes { display: flex; gap: 7px; flex-wrap: wrap; align-items: center; }
.run-state-note { font-size: 12px; color: var(--muted); line-height: 1.5; }

.run-card-foot {
  margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--rule);
  display: flex; align-items: center; gap: 8px;
}
.run-foot-action { font-size: 12px; font-weight: 600; color: var(--muted); }
.run-foot-arrow { margin-left: auto; font-size: 16px; color: var(--amber); font-weight: 700; }

/* Report-missing echo of the run id sits below the empty state inside the card. */
.report-missing-id {
  margin-top: 12px; text-align: center; font-size: 12px;
  display: flex; gap: 8px; align-items: center; justify-content: center;
}

@media (max-width: 600px) {
  header { padding: 12px 20px; }
  main { padding: 24px 16px; }
  .form-card { padding: 22px 18px; }
}

/* ── Persona chat (LLM creation/edition) ─────────────────────────────────── */
.persona-chat { display: flex; flex-direction: column; padding-bottom: 14px; }

.chat-log {
  display: flex; flex-direction: column; gap: 12px;
  height: 48vh; min-height: 280px; overflow-y: auto;
  padding: 8px 4px; margin-bottom: 14px;
  border-bottom: 1px solid var(--rule);
}

/* Message rows: avatar + bubble, aligned by speaker. */
.chat-msg { display: flex; gap: 10px; align-items: flex-end; max-width: 82%; }
.chat-msg-user { align-self: flex-end; flex-direction: row-reverse; }
.chat-msg-assistant { align-self: flex-start; }
.chat-avatar {
  flex: 0 0 28px; width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 12px; font-weight: 800; color: #fff; user-select: none;
}
.chat-msg-user .chat-avatar { background: var(--action); }
.chat-msg-assistant .chat-avatar { background: var(--navy); }
.chat-bubble {
  padding: 10px 14px; border-radius: 14px;
  font-size: 14px; line-height: 1.5; white-space: pre-wrap; word-break: break-word;
}
.chat-msg-user .chat-bubble {
  background: var(--action); color: #fff; border-bottom-right-radius: 4px;
}
.chat-msg-assistant .chat-bubble {
  background: var(--neutral-bg); color: var(--navy); border-bottom-left-radius: 4px;
}

/* "Thinking…" indicator (three pulsing dots) shown while a turn is in flight. */
.chat-typing { display: flex; gap: 4px; padding: 4px 2px; }
.chat-typing span {
  width: 7px; height: 7px; border-radius: 50%; background: var(--muted);
  animation: chat-bounce 1.2s infinite ease-in-out both;
}
.chat-typing span:nth-child(2) { animation-delay: .15s; }
.chat-typing span:nth-child(3) { animation-delay: .3s; }
@keyframes chat-bounce {
  0%, 80%, 100% { opacity: .3; transform: translateY(0); }
  40% { opacity: 1; transform: translateY(-4px); }
}

/* Composer: textarea grows; the send button stays put; the advanced link sits
   on its own line beneath, so it never collides with the button. */
.chat-composer { display: flex; gap: 10px; align-items: flex-end; }
.chat-composer textarea {
  flex: 1; resize: none; min-height: 46px; max-height: 160px; line-height: 1.4;
}
.chat-composer .btn { flex: 0 0 auto; }

.chat-advanced-link { margin-top: 10px; text-align: right; }
.chat-advanced-link a { font-size: 12px; color: var(--muted); text-decoration: none; }
.chat-advanced-link a:hover { color: var(--action); text-decoration: underline; }

/* Persona review card revealed when the chat emits a persona. */
.persona-review {
  margin-top: 16px; padding: 16px 18px;
  background: var(--neutral-bg); border: 1px solid var(--rule); border-radius: 10px;
}
.persona-review h3 { margin: 0 0 10px; font-size: 15px; }
.persona-summary {
  display: grid; grid-template-columns: max-content 1fr; gap: 8px 18px;
  margin: 0 0 16px; font-size: 13px;
}
.persona-summary dt { font-weight: 700; color: var(--muted); }
.persona-summary dd { margin: 0; color: var(--navy); word-break: break-word; }
