/* ===========================================================================
   Leadline Station — Design System
   ===========================================================================
   "Clean & human, light & warm." Warm paper, coral + amber accents, soft
   edges, an editorial serif voice (Fraunces) over a humanist UI grotesque
   (Hanken Grotesk), and the brand mark (four signals converging on one lead).
   Hand-built components — deliberately NOT a component-library look.

   HOW THIS FILE IS ORGANIZED
     1. Tokens ............. every design decision as a CSS variable (:root)
     2. Base / reset ....... document defaults + typographic primitives
     3. Brand .............. the logo lockup + the mark (icon)
     4. Components ......... auth · shell · page head · stats · controls ·
                             cards & tables · timeline · empty · settings · misc
     5. Responsive ......... the single mobile breakpoint

   RULES OF THE ROAD
     · Style THROUGH tokens, never hardcode a hex/size/radius in a component.
     · Type comes from the scale (--text-*) and the two family tokens only.
     · Full written spec + rationale lives in /docs/DESIGN.md. Keep them in sync.
   =========================================================================== */

:root {
  /* ---- Color · surfaces ---------------------------------------------------
     Warm, paper-biased neutrals — never a pure grey. Light → dark by depth. */
  --paper:      #FBF8F4;   /* app background            */
  --surface:    #FFFFFF;   /* raised cards, inputs      */
  --surface-2:  #FDFBF6;   /* insets, table head, code  */
  --line:       #ECE3D6;   /* borders / dividers        */
  --line-soft:  #F3ECE1;   /* hairline dividers         */

  /* ---- Color · ink (text) --- warm charcoal, stepped down in emphasis ----- */
  --ink:        #211C17;   /* primary text / headings   */
  --ink-soft:   #6B6053;   /* secondary text / labels   */
  --ink-mute:   #9C9082;   /* meta, captions, muted     */
  --ink-faint:  #A09484;   /* timestamps, faintest      */

  /* ---- Color · brand + semantic accents ----------------------------------
     The three base tones ARE the logo's (see /assets/logo.svg) — the mark and the
     product are painted from one palette, and the lockup literally reads its fills
     from these tokens, so it can't drift. Coral is THE accent; spend boldness here.
     Amber warms; green/violet are semantic (known / anonymous), not decoration.
     `-deep` = hover/pressed, `-ink` = text ON the tint (AA on its own tint). */
  --coral:      #F85D5E;   --coral-deep: #E4484A;   --coral-ink:  #A93A3B;
  --coral-tint: #FFF0EF;
  --coral-soft: #FDD2D2;   /* data-viz fills: chart area + data bars             */
  --amber:      #FFB062;   --amber-tint: #FFF1E2;   --amber-ink:  #A05E0B;  /* text/glyph on amber-tint */
  --green:      #00AF83;   --green-tint: #E2F5EF;
  --violet:     #6D5BD0;   --violet-tint:#EEEBFB;
  --teal:       #159C8E;   --teal-tint:  #E1F3F1;
  --rose:       #E8688E;   --rose-tint:  #FCE7ED;   --rose-deep:  #D94E78;

  /* ---- Typography · families ---------------------------------------------
     display = Fraunces (editorial serif, optical-sized). Headings, wordmark,
     stat numbers. sans = Hanken Grotesk, the whole UI. mono for code/keys. */
  --font-display: "Fraunces", Georgia, "Times New Roman", serif;
  --font-sans:    "Hanken Grotesk", ui-sans-serif, system-ui, -apple-system,
                  "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono:    ui-monospace, "SFMono-Regular", "JetBrains Mono", Menlo,
                  Consolas, monospace;

  /* ---- Typography · scale (rem @ 16px root, px noted) ---------------------
     One scale for the whole product. Reach for a step; never a raw px value. */
  --text-2xs:  0.6875rem;  /* 11 — micro caps / removable tag glyphs   */
  --text-xs:   0.75rem;    /* 12 — uppercase labels, timestamps        */
  --text-sm:   0.8125rem;  /* 13 — hints, chips, dense meta            */
  --text-base: 0.9375rem;  /* 15 — body, table cells, inputs           */
  --text-md:   1rem;       /* 16 — emphasised body / list titles       */
  --text-lg:   1.1875rem;  /* 19 — card / section headings (h3)        */
  --text-xl:   1.375rem;   /* 22 — sub-heads, identity name            */
  --text-2xl:  1.625rem;   /* 26 — auth headline                       */
  --text-3xl:  1.875rem;   /* 30 — page title, stat value              */
  --text-4xl:  2.5rem;     /* 40 — reserved: marketing / hero          */

  /* ---- Typography · weights · line-height · tracking ---------------------- */
  --fw-regular:  400;
  --fw-medium:   500;
  --fw-semibold: 600;
  --fw-bold:     700;
  --lh-tight:  1.08;   /* display headings      */
  --lh-snug:   1.28;   /* sub-heads, tight text */
  --lh-normal: 1.5;    /* body                  */
  --trk-tight: -0.02em;  /* large display        */
  --trk-snug:  -0.01em;  /* medium display       */
  --trk-label:  0.06em;  /* uppercase micro-caps */

  /* ---- Space scale (4px base) --------------------------------------------- */
  --space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px;
  --space-5: 20px; --space-6: 24px; --space-8: 32px; --space-10: 40px;
  --gap: var(--space-5);

  /* ---- Radius ------------------------------------------------------------- */
  --r-sm: 10px;  --r: 14px;  --r-lg: 22px;  --r-pill: 999px;

  /* ---- Elevation (warm-tinted shadows, never neutral black) --------------- */
  --shadow-sm: 0 1px 2px rgba(58, 42, 24, .06), 0 1px 1px rgba(58, 42, 24, .04);
  --shadow:    0 6px 20px -8px rgba(72, 50, 28, .18), 0 2px 6px -2px rgba(72, 50, 28, .08);
  --shadow-lg: 0 24px 60px -18px rgba(72, 50, 28, .30);

  /* ---- Motion ------------------------------------------------------------- */
  --ease: cubic-bezier(.2, .6, .2, 1);
  --dur-fast: .14s;
  --dur:      .2s;

  /* ---- Focus ring (keyboard) ---------------------------------------------- */
  --ring: 0 0 0 4px var(--coral-tint);
}

/* ============================ 2 · BASE / RESET ============================ */
* { box-sizing: border-box; }
html { font-size: 100%; -webkit-text-size-adjust: 100%; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--lh-normal);
  color: var(--ink);
  background: var(--paper);
  /* Crisp, warm rendering + Fraunces optical sizing tied to font-size. */
  font-optical-sizing: auto;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
a { color: inherit; text-decoration: none; }
button { font-family: inherit; }
/* Headings carry no intrinsic spacing: every heading in this app sits in a flex/grid row that
   owns its rhythm, so the UA's `margin: 1em 0` only ever pushed a title off its icon's centre
   (that was the flow inspector's misaligned title, and the palette's oversized header). */
h1, h2, h3, h4, h5, h6 { margin: 0; }
::selection { background: var(--coral-tint); }
/* Every icon in the app is an inline <svg> wrapped in a <span> (`h('span', { html: icon(x) })`).
   An inline span is a line box: the svg sits ON the baseline, so the descender gap hangs below it
   and the span's centre lands BELOW the svg's — which tips the icon up, off the centre of whatever
   flex row (nav item, button, badge) is trying to centre it. Making the wrapper a flex box removes
   the baseline from the equation, so the svg IS the box and centring works everywhere. */
span:has(> svg) { display: inline-flex; align-items: center; }

/* Typographic primitives — the display voice, applied once, reused everywhere.
   Every serif heading in the app is one of these; optical sizing + tight
   tracking give large sizes editorial contrast, small sizes a sturdier cut. */
.u-display {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  letter-spacing: var(--trk-tight);
  text-wrap: balance;
}
/* Uppercase micro-label (stat keys, table headers, captured-field caption). */
.u-eyebrow {
  font-size: var(--text-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--trk-label);
  text-transform: uppercase;
  color: var(--ink-mute);
}
/* Line up digits in any column of numbers. */
.num, .u-tnum { font-variant-numeric: tabular-nums; }

/* Visible keyboard focus everywhere (mouse clicks stay clean via :focus-visible). */
:focus-visible {
  outline: 2px solid var(--coral);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Respect reduced-motion: kill transitions + the loading spin. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* ========================= 3 · BRAND · LOGO + MOTIF ======================= */
/* The lockup. Markup lives in ONE place (public/js/components/logo.js) and is inlined,
   so the wordmark inherits `color` and the three shapes are painted from the palette
   tokens above. Callers size it with --logo-w; never restyle its innards. */
.logo {
  display: inline-block;
  line-height: 0;              /* no baseline gap under the svg */
  color: var(--ink);           /* the wordmark paints with currentColor */
}
.logo svg, .logo img {
  display: block;
  width: var(--logo-w, 160px);
  height: auto;
}

/* The mark — the lockup's icon on its own: four signals converging on one lead. The very
   artwork the favicon and app icons ship (public/assets/icon.svg), so the tab, the home
   screen and the empty states are literally the same shape. Size it with --mark-w. */
.mark {
  display: block;
  line-height: 0;
  flex: none;
  /* the art is square: the BOX is square too, so `margin: 0 auto` can centre it */
  width: var(--mark-w, 26px);
  height: var(--mark-w, 26px);
}
.mark svg { display: block; width: 100%; height: 100%; }

/* ============================ 4 · AUTH / LOGIN =========================== */
.auth {
  min-height: 100vh;
  display: grid; place-items: center;
  padding: var(--space-6);
  background:
    radial-gradient(1200px 500px at 20% -10%, var(--coral-tint), transparent 60%),
    radial-gradient(900px 500px at 110% 10%, var(--amber-tint), transparent 55%),
    var(--paper);
}
.auth-card {
  width: 100%; max-width: 400px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  padding: 40px 34px 30px;
}
.auth-brand { display: flex; align-items: center; margin-bottom: var(--space-6); --logo-w: 172px; }
.auth h1 {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--text-2xl);
  line-height: var(--lh-tight);
  letter-spacing: var(--trk-tight);
  margin: 0 0 4px;
}
.auth .sub { color: var(--ink-soft); margin: 0 0 var(--space-6); font-size: var(--text-base); }

/* ============================== APP SHELL =============================== */
.shell { display: grid; grid-template-columns: 244px 1fr; min-height: 100vh; }

.sidebar {
  background: linear-gradient(180deg, var(--surface-2), var(--paper));
  border-right: 1px solid var(--line);
  padding: 22px 16px;
  display: flex; flex-direction: column; gap: 6px;
  position: sticky; top: 0; height: 100vh;
}
.sidebar .brand { display: flex; align-items: center; padding: 4px 12px 24px; --logo-w: 148px; }
.nav-item {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 12px; border-radius: var(--r-sm);
  color: var(--ink-soft); font-weight: var(--fw-medium); font-size: var(--text-base);
  cursor: pointer; transition: background var(--dur-fast), color var(--dur-fast);
}
.nav-item svg { width: 18px; height: 18px; opacity: .8; }
.nav-item:hover { background: var(--line-soft); color: var(--ink); }
.nav-item.active { background: var(--coral-tint); color: var(--coral-ink); }
.nav-item.active svg { opacity: 1; }
.sidebar .spacer { flex: 1; }
.sidebar .who { padding: 10px 12px; border-top: 1px solid var(--line); font-size: var(--text-sm); color: var(--ink-mute); }
.sidebar .who b { display: block; color: var(--ink); font-weight: var(--fw-semibold); }
.sidebar .brand .mark { display: none; }   /* the mark only shows in the collapsed rail */
/* the lockup links home — display:contents so logo/mark stay direct flex children of .brand
   and every existing .brand rule (incl. the flow-focus collapse) matches unchanged */
.sidebar .brand-link { display: contents; }
.sidebar .brand-link .logo, .sidebar .brand-link .mark { cursor: pointer; }

/* Editor "focus": the flow editor collapses the nav to an icon rail (body.flow-focus, set by
   app.js route()) so the inspector drawer gets the horizontal room the condition builder needs.
   Desktop only — under 860px the sidebar is already a horizontal bar (RESPONSIVE §5). */
@media (min-width: 861px) {
  body.flow-focus .shell { grid-template-columns: 68px 1fr; }
  body.flow-focus .sidebar { padding: 22px 12px; }
  body.flow-focus .sidebar .brand { justify-content: center; padding: 4px 0 22px; --mark-w: 30px; }
  body.flow-focus .sidebar .brand .logo { display: none; }
  body.flow-focus .sidebar .brand .mark { display: block; }
  /* font-size:0 collapses the label text node; the icon is an SVG sized in px, so it stays */
  body.flow-focus .nav-item { gap: 0; justify-content: center; padding: 11px 0; font-size: 0; }
  body.flow-focus .sidebar .who { display: none; }
}

.main { min-width: 0; padding: 30px 38px 60px; }

/* ---- page header --------------------------------------------------------- */
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-5); margin-bottom: var(--space-6); flex-wrap: wrap; }
.page-head h1 {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--text-3xl);
  line-height: var(--lh-tight);
  letter-spacing: var(--trk-tight);
  text-wrap: balance;
  margin: 0;
}
.page-head .lede { color: var(--ink-soft); margin: 6px 0 0; font-size: var(--text-base); max-width: 60ch; }
.head-actions { display: flex; gap: 10px; align-items: center; }

/* ---- stat tiles ---------------------------------------------------------- */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: var(--space-6); }
.stat {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  padding: 16px 18px; box-shadow: var(--shadow-sm);
}
.stat .k {
  font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--trk-label);
  color: var(--ink-mute); font-weight: var(--fw-semibold);
}
.stat .v {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  letter-spacing: var(--trk-tight);
  font-variant-numeric: tabular-nums;
  margin-top: 4px;
}
.stat.accent .v { color: var(--coral); }

/* ============================ CONTROLS ==================================== */
.field { margin-bottom: 15px; }
.field label { display: block; font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--ink-soft); margin-bottom: 6px; }
.input, .textarea {
  width: 100%; padding: 11px 13px; font-size: var(--text-base); color: var(--ink);
  background: var(--surface); border: 1.5px solid var(--line);
  border-radius: var(--r-sm); outline: none; transition: border-color var(--dur-fast), box-shadow var(--dur-fast);
  font-family: inherit;
}
.textarea { resize: vertical; min-height: 120px; font-family: var(--font-mono); font-size: var(--text-sm); }
.input:focus, .textarea:focus { border-color: var(--coral); box-shadow: var(--ring); }

.btn {
  display: inline-flex; align-items: center; gap: 8px; justify-content: center;
  padding: 10px 16px; border-radius: var(--r-sm); font-size: var(--text-base); font-weight: var(--fw-semibold);
  border: 1.5px solid transparent; cursor: pointer;
  transition: transform .06s var(--ease), background var(--dur-fast), border-color var(--dur-fast);
  background: var(--surface); color: var(--ink); border-color: var(--line);
}
.btn:active { transform: translateY(1px); }
.btn svg { width: 16px; height: 16px; }
.btn-primary { background: var(--coral); color: #fff; border-color: var(--coral); box-shadow: 0 6px 16px -6px rgba(255,107,74,.6); }
.btn-primary:hover { background: var(--coral-deep); border-color: var(--coral-deep); }
.btn-ghost { background: transparent; border-color: var(--line); }
.btn-ghost:hover { background: var(--line-soft); }
.btn-block { width: 100%; }
.btn:disabled { opacity: .55; cursor: not-allowed; }
/* Destrutivo: rose é o hue de perigo (o mesmo que o estado de falha da linha do tempo usa). Ghost
   por padrão — um "Excluir" discreto em texto rose numa barra de editor; `.is-strong` é o commit
   sólido e pesado dentro de um diálogo de confirmação, o gêmeo rose do .btn-primary. */
.btn-danger { color: var(--rose); }
.btn-danger:hover { background: var(--rose-tint); border-color: var(--rose-tint); color: var(--rose); }
.btn-danger.is-strong { background: var(--rose); border-color: var(--rose); color: #fff; box-shadow: 0 6px 16px -6px rgba(232,104,142,.55); }
.btn-danger.is-strong:hover { background: var(--rose-deep); border-color: var(--rose-deep); color: #fff; }

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: var(--r-pill); font-size: var(--text-xs); font-weight: var(--fw-semibold);
  background: var(--line-soft); color: var(--ink-soft);
}
.chip.anon  { background: var(--violet-tint); color: var(--violet); }
.chip.known { background: var(--green-tint);  color: var(--green); }
.chip.amber { background: var(--amber-tint);  color: var(--amber-ink); }
/* Product chip: tinted in the product's own configured accent (--pc), derived from that one
   colour so any configured hue reads correctly in light + dark (mix toward --ink for text). */
.chip.product {
  background: color-mix(in srgb, var(--pc, var(--ink-mute)) 14%, transparent);
  color: color-mix(in srgb, var(--pc, var(--ink-mute)) 78%, var(--ink));
}

/* ---- search ------------------------------------------------------------- */
.search { position: relative; display: inline-flex; }
.search svg { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); width: 17px; height: 17px; color: var(--ink-mute); pointer-events: none; transition: color var(--dur-fast); }
.search input {
  width: 280px; padding: 10px 14px 10px 38px; font-size: var(--text-base); font-family: inherit;
  color: var(--ink); background: var(--surface); border: 1.5px solid var(--line);
  border-radius: var(--r-pill); outline: none; transition: border-color var(--dur-fast), box-shadow var(--dur-fast), background var(--dur-fast);
  -webkit-appearance: none; appearance: none;
}
.search input::placeholder { color: var(--ink-mute); }
.search input:hover { border-color: #E0D4C2; }
.search input:focus { border-color: var(--coral); background: var(--surface); box-shadow: var(--ring); }
.search:focus-within svg { color: var(--coral); }
.search input::-webkit-search-decoration,
.search input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.search input::-ms-clear { display: none; }

/* ============================ CARD / TABLE =============================== */
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); box-shadow: var(--shadow-sm); overflow: hidden;
}
.card-pad { padding: 22px; }

table.leads { width: 100%; border-collapse: collapse; }
table.leads th {
  text-align: left; font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--trk-label);
  color: var(--ink-mute); font-weight: var(--fw-semibold); padding: 13px 18px; border-bottom: 1px solid var(--line);
  background: var(--surface-2);
}
table.leads td { padding: 14px 18px; border-bottom: 1px solid var(--line-soft); font-size: var(--text-base); vertical-align: middle; }
table.leads tr:last-child td { border-bottom: none; }
table.leads tbody tr { cursor: pointer; transition: background var(--dur-fast); }
table.leads tbody tr:hover { background: var(--coral-tint); }
.lead-name { display: flex; align-items: center; gap: 11px; }
.avatar {
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  display: grid; place-items: center; font-weight: var(--fw-bold); font-size: var(--text-sm); color: #fff;
  background: linear-gradient(135deg, var(--coral), var(--amber));
}
.lead-name .txt b { font-weight: var(--fw-semibold); }
.lead-name .txt small { display: block; color: var(--ink-mute); font-size: var(--text-xs); }
.muted { color: var(--ink-mute); }

/* ============================ TIMELINE ================================== */
.detail-grid { display: grid; grid-template-columns: 320px 1fr; gap: 26px; align-items: start; }

.identity-card .head { display: flex; align-items: center; gap: 14px; padding: 22px; border-bottom: 1px solid var(--line-soft); }
.identity-card .avatar { width: 48px; height: 48px; font-size: var(--text-md); }
.identity-card h2 {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-snug);
  letter-spacing: var(--trk-snug);
  margin: 0;
}
.identity-card .head small { color: var(--ink-mute); }
.kv { padding: 8px 22px 20px; }
.kv .row { display: flex; justify-content: space-between; gap: 14px; padding: 9px 0; border-bottom: 1px dashed var(--line-soft); font-size: var(--text-base); }
.kv .row:last-child { border-bottom: none; }
.kv .row .k { color: var(--ink-mute); }
.kv .row .v { font-weight: var(--fw-semibold); text-align: right; word-break: break-word; }

/* ---- Comunicações: os dois interruptores da ficha (migration 034) -----------
   O estado normal é "pode receber", então ele é o discreto: a linha só ganha cor quando alguém
   está BLOQUEADO — é a informação que muda o que você pode fazer com o lead, e é ela que precisa
   saltar numa tela cheia de dados. Mesma lógica do "Canal (revenda)" do bloco do Blaster. */
.consent-list { display: flex; flex-direction: column; gap: 6px; padding: 2px 22px 18px; }
.consent-row {
  display: flex; align-items: center; gap: 11px; width: 100%; text-align: left;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface-2); color: var(--ink); font-family: inherit; cursor: pointer;
}
.consent-row:hover { border-color: var(--coral-soft); }
.consent-row:disabled { opacity: .55; cursor: default; }
.consent-ico { display: inline-flex; color: var(--green); flex: none; }
.consent-ico svg { width: 16px; height: 16px; }
.consent-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.consent-text strong { font-size: var(--text-base); font-weight: var(--fw-semibold); }
.consent-text small { color: var(--ink-mute); font-size: var(--text-xs); }
.consent-switch {
  position: relative; flex: none; width: 34px; height: 19px; border-radius: var(--r-pill);
  background: var(--green); transition: background .15s ease;
}
.consent-knob {
  position: absolute; top: 2px; left: 17px; width: 15px; height: 15px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 2px rgba(72, 50, 28, .3); transition: left .15s ease;
}
.consent-row.off { background: var(--amber-tint); border-color: var(--amber); }
.consent-row.off .consent-ico { color: var(--amber-ink); }
.consent-row.off .consent-text strong { color: var(--amber-ink); }
.consent-row.off .consent-text small { color: var(--amber-ink); opacity: .85; }
.consent-row.off .consent-switch { background: var(--ink-mute); }
.consent-row.off .consent-knob { left: 2px; }

/* ---- timeline: o cabeçalho (título · seletor de tipos · contador) ----------
   O seletor precisa da linha inteira, então o cabeçalho quebra em duas quando
   ela não cabe — o contador acompanha o seletor, nunca o título: os dois falam
   do mesmo conjunto, e separá-los faria "18 atividades" parecer o total da
   ficha e não o do filtro. */
.tl-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.tl-head-tools { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.tl-head-tools .scope-trigger { max-width: 260px; }

.timeline { position: relative; padding: 6px 0 6px 4px; }
/* left = centro de TODA bolinha, não 15: o item flui dentro do padding-left:4px
   da timeline (logo o ponto centra em 4 + 6 + 10 = 20), mas esta linha é
   posicionada a partir da borda da timeline, sem esse 4px — por isso ela corria
   4px à esquerda dos pontos. left:19 (+ width/2) crava o centro em 20. Todos os
   tipos de ponto centram em 20 (identify: 4+3+13; page/out: 4+6+10). */
.timeline::before {
  content: ""; position: absolute; left: 19px; top: 10px; bottom: 10px; width: 2px;
  background: linear-gradient(var(--line), var(--line-soft));
}
.tl-item { position: relative; padding: 4px 0 22px 46px; }
.tl-dot {
  position: absolute; left: 6px; top: 3px; width: 20px; height: 20px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--line); z-index: 1;
}
.tl-item.pageview .tl-dot { border-color: var(--amber); }
.tl-item.pageview .tl-dot::after { content: ""; position: absolute; inset: 4px; border-radius: 50%; background: var(--amber); }
.tl-item.custom .tl-dot { border-color: var(--violet); }
.tl-item.custom .tl-dot::after { content: ""; position: absolute; inset: 4px; border-radius: 50%; background: var(--violet); }
.tl-item.identify .tl-dot {
  border-color: var(--coral); left: 3px; top: 0; width: 26px; height: 26px;
  box-shadow: 0 0 0 4px var(--coral-tint);
}
.tl-item.identify .tl-dot::after { content: ""; position: absolute; inset: 5px; border-radius: 50%; background: var(--coral); }

/* ---- timeline: o que NÓS fizemos (e-mail, WhatsApp, passo de fluxo) --------
   A ficha passou a misturar duas histórias: o que o lead fez no site e o que a
   casa fez com ele. Elas se distinguem pela FORMA do ponto — disco colorido
   para o lead, ícone em tinta neutra para nós — e não por mais uma cor: verde e
   violeta são semânticos aqui e coral é o acento (§6.3), então o eixo livre era
   este. O ponto neutro também recua um degrau na hierarquia, que é onde ele
   deve estar: numa ficha de lead, o que a pessoa fez vem primeiro.
   `.fail` é a única exceção — falha é estado, e estado este sistema pinta. */
.tl-item.out .tl-dot {
  display: flex; align-items: center; justify-content: center;
  border-color: var(--line); background: var(--surface-2); color: var(--ink-mute);
}
/* svg as a BLOCK, não inline: um <svg> inline carrega o espaço de descida da
   linha de texto, e era ele que empurrava todo glifo um pixel para cima dentro
   do círculo (o "torto"). Zerado o line-height + block, o glifo centra de fato;
   13px lê limpo no interior de 16px sem inflar o ponto. */
.tl-glyph { display: flex; line-height: 0; }
.tl-glyph svg { display: block; width: 13px; height: 13px; }
.tl-item.out .tl-title { color: var(--ink-soft); font-weight: var(--fw-medium); }
.tl-item.out.fail .tl-dot { border-color: var(--rose); background: var(--rose-tint); color: var(--rose); }
.tl-item.out.fail .tl-title { color: var(--rose); }

.tl-row { display: flex; justify-content: space-between; gap: 14px; }
.tl-main { min-width: 0; }   /* let a long page label truncate instead of shoving the time out */
.tl-title { font-weight: var(--fw-semibold); font-size: var(--text-base); }
.tl-item.identify .tl-title { color: var(--coral-ink); }
.tl-meta { color: var(--ink-mute); font-size: var(--text-sm); margin-top: 2px; }
.tl-time { flex: 0 0 auto; color: var(--ink-faint); font-size: var(--text-xs); white-space: nowrap; }
.tl-utm { margin-top: 6px; display: flex; gap: 6px; flex-wrap: wrap; }

/* ---- timeline: o formulário por trás de um envio --------------------------
   Duas afirmações diferentes, dois desenhos diferentes — nunca a mesma forma:
   quando temos os VALORES é uma lista chave→valor, encostada numa régua coral
   (a tinta da conversão, a mesma do ponto do identify); quando temos só as
   CHAVES é uma fileira de etiquetas neutras, e o rótulo diz "sem valores".
   Se as duas fossem chips, "Subdomínio" leria como algo que alguém digitou. */
.tl-fields { margin-top: 8px; }
.tl-fields .u-eyebrow { margin-bottom: 5px; }
.tl-vals {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 3px 14px;
  border-left: 2px solid var(--coral-tint); padding-left: 11px;
}
.tl-vals .k { color: var(--ink-mute); font-size: var(--text-sm); }
.tl-vals .v { font-size: var(--text-sm); font-weight: var(--fw-semibold); word-break: break-word; }
.tl-keys { display: flex; gap: 6px; flex-wrap: wrap; }
.tl-more { margin-top: 5px; color: var(--ink-faint); font-size: var(--text-xs); }
.chip-form svg { width: 12px; height: 12px; opacity: .75; }

/* ---- page reference: the software-wide way to cite a page (label + open) --- */
.pageref { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; min-width: 0; vertical-align: middle; }
.pageref-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pageref-open {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: var(--r-sm); color: var(--ink-faint);
  transition: color var(--dur-fast), background var(--dur-fast);
}
.pageref-open:hover, .pageref-open:focus-visible { color: var(--coral-ink); background: var(--coral-tint); outline: none; }
.pageref-open svg { width: 13px; height: 13px; }

/* ---- a Fraunces section heading used inside cards (timeline title etc.) --- */
.card-title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-snug);
  letter-spacing: var(--trk-snug);
  margin: 0;
}

/* ============================ EMPTY STATE =============================== */
.empty { text-align: center; padding: 60px 30px; }
.empty .mark { margin: 0 auto 18px; --mark-w: 46px; }
.empty h3 {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  letter-spacing: var(--trk-snug);
  text-wrap: balance;
  margin: 0 0 6px;
}
.empty p { color: var(--ink-soft); max-width: 440px; margin: 0 auto 18px; }
.snippet-box {
  background: #2A241D; color: #F5EEE2; border-radius: var(--r-sm);
  padding: 14px 16px; font-family: var(--font-mono); font-size: var(--text-sm);
  text-align: left; overflow-x: auto; position: relative;
}
.snippet-box .tok { color: var(--amber); }

/* ============================ SETTINGS ================================== */
.settings-page { max-width: 1140px; }
.settings-hero { margin-bottom: 18px; }
/* Masonry via CSS multicol: cards pack top-to-bottom, column-to-column, with
   uneven heights instead of a grid's ragged aligned rows. Buildless, no JS. */
.settings-masonry { columns: 2; column-gap: 18px; }
.settings-masonry > .card { break-inside: avoid; margin-bottom: 18px; }

.setting-block { margin-bottom: 22px; }
.setting-block h3 {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-snug);
  letter-spacing: var(--trk-snug);
  margin: 0 0 4px;
}
.setting-block p.hint { color: var(--ink-soft); font-size: var(--text-sm); margin: 0 0 14px; }
.key-row { display: flex; gap: 10px; align-items: center; }
.key-row code { flex: 1; font-family: var(--font-mono); font-size: var(--text-sm); background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 10px 12px; }
.domain-tags { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.domain-tag { display: inline-flex; align-items: center; gap: 8px; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-pill); padding: 5px 6px 5px 12px; font-size: var(--text-sm); }
.domain-tag button { border: none; background: var(--line-soft); width: 20px; height: 20px; border-radius: 50%; cursor: pointer; color: var(--ink-soft); font-size: var(--text-sm); line-height: 1; }
.domain-tag button:hover { background: var(--coral-tint); color: var(--coral-ink); }

/* ---- Team / users ---- */
.user-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 20px; }
.user-list:empty { margin-bottom: 0; }
.user-row {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface-2);
}
.user-row .user-id { flex: 1; min-width: 0; }
.user-row .user-id b { display: block; font-weight: var(--fw-semibold); font-size: var(--text-base); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-row .user-id small { color: var(--ink-mute); font-size: var(--text-xs); }
.user-row .user-meta { display: flex; gap: 6px; align-items: center; }
.role-badge {
  font-size: var(--text-2xs); font-weight: var(--fw-semibold); padding: 3px 9px; border-radius: var(--r-pill);
  background: var(--line-soft); color: var(--ink-soft); white-space: nowrap;
}
.role-badge.is-owner { background: var(--amber-tint, var(--coral-tint)); color: var(--coral-ink); }
.role-badge.is-you { background: var(--coral); color: #fff; }
.icon-btn {
  border: none; background: transparent; cursor: pointer; color: var(--ink-mute);
  width: 32px; height: 32px; border-radius: var(--r-sm); display: grid; place-items: center; flex: none;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.icon-btn svg { width: 17px; height: 17px; }
.icon-btn:hover { background: var(--coral-tint); color: var(--coral-deep); }
.user-add-fields { display: flex; flex-wrap: wrap; gap: 10px; }
.user-add-fields .input { flex: 1; min-width: 180px; }

/* ============================ MISC ===================================== */
.toast {
  position: fixed; bottom: 24px; left: 50%; transform: translate(-50%, 20px);
  background: var(--ink); color: #fff; padding: 12px 20px; border-radius: var(--r-pill);
  font-size: var(--text-base); font-weight: var(--fw-medium); box-shadow: var(--shadow-lg);
  opacity: 0; pointer-events: none; transition: opacity var(--dur), transform var(--dur); z-index: 100;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
.toast.err { background: var(--coral-deep); }

.spinner { width: 28px; height: 28px; border: 3px solid var(--line); border-top-color: var(--coral); border-radius: 50%; animation: spin .7s linear infinite; margin: 60px auto; }
@keyframes spin { to { transform: rotate(360deg); } }

.back-link { display: inline-flex; align-items: center; gap: 6px; color: var(--ink-soft); font-size: var(--text-sm); font-weight: var(--fw-semibold); margin-bottom: 14px; cursor: pointer; }
.back-link:hover { color: var(--coral-ink); }
.error-text { color: var(--coral-deep); font-size: var(--text-sm); margin-top: 8px; min-height: 18px; }

/* ============================ DASHBOARD ================================= */
/* The analytics surface. Same warm cards + serif numbers as the rest of the app;
   one coral accent carries every data mark (charts, funnel, bars). Green/violet stay
   reserved for lead state, so KPI deltas are neutral — direction is a glyph, not a hue. */

/* ---- period control (defaults to the current month; steps to earlier months) ---- */
.period { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; justify-content: flex-end; }

/* ---- resolved-range caption + live badge ---- */
/* ---- dashboard scope filter (domain / product) — custom favicon dropdown --- */
/* A pill trigger that reads as a sibling of the date picker (same height, border weight
   and radius), carrying the selected domain's live favicon. When a scope is active
   (not "all") it takes the coral-tint "active" look — the same cue used by .date-trigger.active
   — so a narrowed dashboard is obvious at a glance. The panel is a curated favicon tree. */
.period-scope { margin-right: auto; position: relative; }   /* far left; date controls stay right */

.scope-trigger {
  display: inline-flex; align-items: center; gap: 8px;
  height: 36px; max-width: 260px; padding: 0 10px 0 7px;
  border: 1.5px solid var(--line); border-radius: var(--r-pill);
  background: var(--surface); color: var(--ink);
  font-family: inherit; font-size: var(--text-sm); font-weight: var(--fw-semibold);
  cursor: pointer;
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast), box-shadow var(--dur-fast);
}
.scope-trigger:hover { background: var(--line-soft); }
.scope-trigger:focus-visible { outline: none; border-color: var(--coral); box-shadow: var(--ring); }
.scope-trigger.active { background: var(--coral-tint); color: var(--coral-ink); border-color: var(--coral-tint); }
.scope-trigger.active:hover { filter: brightness(0.98); }
.scope-trigger-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.scope-caret { display: inline-flex; margin-left: 2px; color: var(--ink-mute); transition: transform var(--dur-fast) var(--ease); }
.scope-caret svg { width: 15px; height: 15px; }
.scope-trigger.active .scope-caret { color: var(--coral-ink); }
/* generic dropdown behaviour marker (components/dropdown.js) — shared by the dashboard
   scope selector and the leads filter pills; the open state is keyed on `.dd.open`. */
.dd { position: relative; }
.dd.open .scope-caret { transform: rotate(180deg); }
/* leading glyph for the non-favicon pills (Período / Origem) */
.scope-lead-icon { display: inline-flex; flex: none; width: 20px; height: 20px; align-items: center; justify-content: center; color: var(--ink-mute); }
.scope-lead-icon svg { width: 16px; height: 16px; }
.scope-trigger.active .scope-lead-icon { color: var(--coral-ink); }

/* favicon "app-icon" tile: monogram placeholder, real favicon crossfades in on load */
.fav {
  position: relative; flex: none; width: 20px; height: 20px;
  border-radius: 6px; overflow: hidden;
  background: var(--surface-2); border: 1px solid var(--line-soft);
  display: grid; place-items: center;
}
.fav-mono { font-family: var(--font-sans); font-size: 10px; font-weight: var(--fw-bold); line-height: 1; color: var(--ink-soft); transition: opacity var(--dur-fast); }
.fav-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; padding: 2px; background: #fff; opacity: 0; transition: opacity var(--dur-fast); }
.fav.has-img .fav-img { opacity: 1; }
.fav.has-img .fav-mono { opacity: 0; }
.scope-globe { display: inline-flex; flex: none; width: 20px; height: 20px; align-items: center; justify-content: center; color: var(--ink-mute); }
.scope-globe svg { width: 17px; height: 17px; }
.scope-trigger.active .scope-globe { color: var(--coral-ink); }
/* a product's identity dot (its configured colour) — a product spans several domains,
   so a single colour reads truer than any one domain's favicon */
.scope-dot { flex: none; width: 20px; height: 20px; border-radius: 50%; background: var(--pc, var(--ink-mute)); box-shadow: inset 0 0 0 1px rgba(33, 28, 23, .12); }

/* panel */
.scope-panel {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 40;
  min-width: 250px; max-width: min(320px, 90vw); max-height: min(60vh, 420px); overflow-y: auto;
  padding: 6px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  box-shadow: var(--shadow-lg);
  /* CLOSED = `display: none`, not `visibility: hidden`. A hidden-but-laid-out panel still occupies
     its 250px inside the scroll box it sits in, and in a narrow container (the 380px flow
     inspector) that phantom width alone gave the drawer a horizontal scrollbar with nothing open.
     `allow-discrete` + @starting-style keep the fade/rise on open. */
  display: none;
  opacity: 0; transform: translateY(-4px) scale(.98); transform-origin: top left;
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease),
              display var(--dur-fast) allow-discrete;
}
.dd.open .scope-panel { display: block; opacity: 1; transform: none; }
@starting-style { .dd.open .scope-panel { opacity: 0; transform: translateY(-4px) scale(.98); } }

.scope-opt {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; border: none; border-radius: var(--r-sm);
  background: transparent; color: var(--ink); font-family: inherit;
  font-size: var(--text-base); font-weight: var(--fw-medium); text-align: left; cursor: pointer;
  transition: background var(--dur-fast);
}
.scope-opt:hover, .scope-opt:focus-visible { background: var(--surface-2); outline: none; }
.scope-opt.sel { background: var(--coral-tint); color: var(--coral-ink); }
.scope-opt.sel:hover { background: var(--coral-tint); }
/* Multi-seleção: só o CHECK marca. Num menu de escolha única a tinta coral aponta a linha
   escolhida entre muitas; num de várias, o estado normal é quase tudo marcado — tingir todas
   inverte a figura e o fundo, e quem passa a saltar aos olhos é justamente o que está
   DESmarcado. O check já responde "este está ligado?"; a tinta só somaria ruído. */
.scope-multi .scope-opt.sel { background: transparent; color: var(--ink); }
.scope-multi .scope-opt.sel:hover, .scope-multi .scope-opt.sel:focus-visible { background: var(--surface-2); }
.scope-multi .scope-opt.sel .scope-opt-hint { color: var(--ink-mute); }
.scope-opt-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.scope-all .scope-opt-label, .scope-dom .scope-opt-label { font-weight: var(--fw-semibold); }
.scope-check { display: inline-flex; flex: none; color: var(--coral-ink); }
.scope-check svg { width: 16px; height: 16px; }
/* per-option count (e.g. how many leads a channel holds), trailing + muted */
.scope-opt-hint { flex: none; color: var(--ink-mute); font-size: var(--text-xs); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; }
.scope-opt.sel .scope-opt-hint { color: var(--coral-ink); }

/* Site / broken-out subdomains nested under their domain, joined by a hairline rail */
.scope-sub { position: relative; padding-left: 42px; font-size: var(--text-sm); color: var(--ink-soft); }
.scope-sub::before { content: ''; position: absolute; left: 26px; top: 0; bottom: 0; width: 1.5px; background: var(--line); }
.scope-sub.sel { color: var(--coral-ink); }

.scope-grouplabel { padding: 9px 10px 4px; font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--trk-label); color: var(--ink-mute); font-weight: var(--fw-semibold); }
.scope-sep { height: 1px; background: var(--line-soft); margin: 6px 8px; }

/* ---- leads filter bar ---------------------------------------------------- */
/* A row of dropdown pills (Período · Origem · Produto/Domínio) reusing the scope
   selector's trigger/panel primitives, sitting between the stat row and the table. */
.filters { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: var(--space-5); }
.filter-clear {
  border: none; background: transparent; color: var(--ink-soft); font-family: inherit;
  font-size: var(--text-sm); font-weight: var(--fw-semibold); cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px; padding: 8px 10px; border-radius: var(--r-pill);
  transition: background var(--dur-fast), color var(--dur-fast);
}
.filter-clear:hover { background: var(--line-soft); color: var(--ink); }
.filter-clear svg { width: 15px; height: 15px; }
.filters-count { margin-left: auto; color: var(--ink-mute); font-size: var(--text-sm); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ---- pagination (A paginação — TODA listagem, docs/DESIGN.md §9) --------
   Uma só, desenhada por components/pager.js: a faixa à esquerda ("51–100 de 2.899"),
   a navegação à direita, a nota de teto embaixo ocupando a linha inteira. Nasceu na base
   de leads e vale para as outras nove listagens sem uma linha de CSS por tela. */
.pager {
  display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  margin-top: 16px;
}
.pager-range { color: var(--ink-mute); font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.pager-nav { display: flex; align-items: center; gap: 4px; margin-left: auto; }
.pager-btn, .pager-page {
  min-width: 34px; height: 34px; padding: 0 8px; border-radius: var(--r-sm);
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-soft);
  font-family: inherit; font-size: var(--text-sm); font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
}
.pager-btn:hover:not(:disabled), .pager-page:hover:not(.on) { background: var(--line-soft); color: var(--ink); }
.pager-btn:disabled { opacity: .45; cursor: default; }
.pager-btn svg { width: 16px; height: 16px; }
.pager-page.on { background: var(--coral); border-color: var(--coral); color: #fff; }
.pager-gap { padding: 0 4px; color: var(--ink-mute); }
/* Nota de TETO: o servidor cortou o conjunto. Âmbar (atenção), nunca vermelho — não é erro,
   é um limite declarado. Quebra a linha do flex para ficar abaixo da faixa e da navegação. */
.pager-capped {
  flex-basis: 100%; margin: 0; display: flex; align-items: center; gap: 7px;
  color: var(--amber-ink); font-size: var(--text-sm);
}
.pager-capped svg { width: 14px; height: 14px; flex: none; }

/* ---- spam quarantine: toggle chip + row recovery ------------------------- */
.quarantine-toggle {
  border: 1px solid var(--line); background: transparent; color: var(--ink-soft); font-family: inherit;
  font-size: var(--text-sm); font-weight: var(--fw-semibold); cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px; border-radius: var(--r-pill);
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
}
.quarantine-toggle:hover { background: var(--line-soft); color: var(--ink); }
.quarantine-toggle svg { width: 15px; height: 15px; }
.quarantine-toggle.on { background: var(--coral); border-color: var(--coral); color: #fff; }
.lead-reasons { color: var(--ink-mute); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
.btn-recover {
  border: 1px solid var(--line); background: transparent; color: var(--ink-soft); font-family: inherit;
  font-size: var(--text-sm); font-weight: var(--fw-semibold); cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; border-radius: var(--r-pill);
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
}
.btn-recover:hover { background: var(--coral); border-color: var(--coral); color: #fff; }
.btn-recover svg { width: 15px; height: 15px; }

/* ---- dashboard date picker — presets + month + custom span --------------- */
/* A sibling of the scope control: same pill trigger + dropdown-panel pattern, held to
   the right of the period bar. Rolls the old preset chips and month stepper into one
   menu and adds a De/Até custom span. Reuses .scope-sep / .scope-grouplabel / .scope-check
   / .scope-caret so both dropdowns read as one family. */
.period-date { position: relative; }

.date-trigger {
  display: inline-flex; align-items: center; gap: 8px;
  height: 36px; max-width: 260px; padding: 0 10px 0 11px;
  border: 1.5px solid var(--line); border-radius: var(--r-pill);
  background: var(--surface); color: var(--ink);
  font-family: inherit; font-size: var(--text-sm); font-weight: var(--fw-semibold);
  cursor: pointer;
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast), box-shadow var(--dur-fast);
}
.date-trigger:hover { background: var(--line-soft); }
.date-trigger:focus-visible { outline: none; border-color: var(--coral); box-shadow: var(--ring); }
.date-trigger.active { background: var(--coral-tint); color: var(--coral-ink); border-color: var(--coral-tint); }
.date-trigger.active:hover { filter: brightness(0.98); }
.date-ico { display: inline-flex; flex: none; color: var(--ink-mute); }
.date-ico svg { width: 16px; height: 16px; }
.date-trigger.active .date-ico { color: var(--coral-ink); }
.date-trigger-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.period-date.open .scope-caret { transform: rotate(180deg); }

.date-panel {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 40;
  width: 300px; max-width: 92vw; max-height: min(72vh, 560px); overflow-y: auto;
  padding: 6px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  box-shadow: var(--shadow-lg);
  opacity: 0; visibility: hidden; transform: translateY(-4px) scale(.98); transform-origin: top right;
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.period-date.open .date-panel { opacity: 1; visibility: visible; transform: none; pointer-events: auto; }

.date-opt {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; border: none; border-radius: var(--r-sm);
  background: transparent; color: var(--ink); font-family: inherit;
  font-size: var(--text-base); font-weight: var(--fw-medium); text-align: left; cursor: pointer;
  transition: background var(--dur-fast);
}
.date-opt:hover, .date-opt:focus-visible { background: var(--surface-2); outline: none; }
.date-opt.sel { background: var(--coral-tint); color: var(--coral-ink); }
.date-opt.sel:hover { background: var(--coral-tint); }
.date-opt-label { flex: 1; min-width: 0; }

.date-monthpick { padding: 2px 8px 4px; }
.date-custom { padding: 2px 8px 6px; }
.date-fields { display: flex; gap: 8px; }
.date-field { display: flex; flex-direction: column; gap: 5px; flex: 1; min-width: 0; }
.date-field > span { font-size: var(--text-xs); font-weight: var(--fw-semibold); color: var(--ink-soft); }
.date-input {
  width: 100%; box-sizing: border-box;
  border: 1.5px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink);
  font-family: inherit; font-size: var(--text-sm); font-weight: var(--fw-medium);
  padding: 7px 9px;
  transition: border-color var(--dur-fast), box-shadow var(--dur-fast);
}
.date-input:focus-visible { outline: none; border-color: var(--coral); box-shadow: var(--ring); }
.date-err { margin-top: 7px; font-size: var(--text-xs); font-weight: var(--fw-medium); color: var(--coral-ink); }
.date-err:empty { display: none; }
.date-apply { margin-top: 10px; }

/* ---- products editor (settings) ----------------------------------------- */
.product-item { border: 1.5px solid var(--line); border-radius: var(--r-sm); padding: 14px; margin-bottom: 12px; }
.product-item-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.product-item-head .input { flex: 1; }

/* ---- product colour picker (settings) ----------------------------------- */
.product-color { display: flex; align-items: center; gap: 12px; margin-top: 12px; }
.product-color .u-eyebrow { color: var(--ink-mute); }
.swatch-row { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.swatch {
  position: relative; width: 26px; height: 26px; padding: 0; flex: none;
  border: 1.5px solid rgba(33, 28, 23, .10); border-radius: 50%;
  background: var(--sw, var(--surface-2)); cursor: pointer;
  display: grid; place-items: center; color: #fff;
  transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast);
}
.swatch:hover { transform: scale(1.08); }
.swatch:focus-visible { outline: none; box-shadow: var(--ring); }
.swatch.sel { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--sw); }
.swatch-check { display: inline-flex; }
.swatch-check svg { width: 15px; height: 15px; filter: drop-shadow(0 1px 1px rgba(0,0,0,.25)); }
/* the custom (advanced) swatch: a dashed "＋" tile until a custom colour is chosen */
.swatch-custom { background: var(--surface); border-style: dashed; border-color: var(--line); color: var(--ink-mute); }
.swatch-custom:hover { border-color: var(--ink-mute); }
.swatch-custom.sel { border-style: solid; border-color: rgba(33, 28, 23, .10); color: #fff; }
.swatch-plus { display: inline-flex; }
.swatch-plus svg { width: 15px; height: 15px; }
.color-native {
  width: 26px; height: 26px; padding: 0; cursor: pointer; background: none;
  border: 1.5px solid var(--line); border-radius: 50%; overflow: hidden;
}
.color-native::-webkit-color-swatch-wrapper { padding: 0; }
.color-native::-webkit-color-swatch { border: none; border-radius: 50%; }
.color-native::-moz-color-swatch { border: none; border-radius: 50%; }

/* ---- product interest (leads list/detail) + cross-product matrix --------- */
.lead-products { display: flex; flex-wrap: wrap; gap: 5px; }
/* the cross-product card is a standalone row under the grid pairs; its spacing comes
   from the one `.dash-body` rhythm below, like every other block the page stacks. */
/* diagonal (a product's own total) tinted per-product via inline background; the
   fallback keeps the old coral wash if a product has no colour. */
.cp-matrix td.cp-diag { background: var(--coral-tint); color: var(--ink); font-weight: var(--fw-semibold); }
.cp-matrix th:first-child, .cp-matrix td:first-child { text-align: left; white-space: nowrap; }
.cp-dot { color: var(--ink-faint); }
/* product colour key: a small dot that ties each row/column to its product colour */
.cp-th { display: inline-flex; align-items: center; gap: 7px; }
.cp-key { flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--pc, var(--ink-mute)); box-shadow: inset 0 0 0 1px rgba(33, 28, 23, .12); }

.dash-caption { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: var(--text-sm); color: var(--ink-soft); margin-bottom: var(--space-5); }
.dash-caption-sep { color: var(--ink-faint); }
.dash-live { display: inline-flex; align-items: center; gap: 6px; color: var(--coral-ink); font-weight: var(--fw-semibold); }
.dash-live i { width: 7px; height: 7px; border-radius: 50%; background: var(--coral); box-shadow: 0 0 0 3px var(--coral-tint); animation: livepulse 1.8s var(--ease) infinite; }
@keyframes livepulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

/* ---- KPI delta (neutral: glyph shows direction, never green/red) ---- */
.stat-delta { margin-top: 8px; font-size: var(--text-xs); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; display: inline-flex; align-items: center; gap: 4px; color: var(--ink-mute); }
.stat-delta.up, .stat-delta.down { color: var(--ink-soft); }
.stat-delta.flat { color: var(--ink-faint); }

/* ---- card head (title + control on one row) ---- */
.card-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }

/* ---- segmented metric toggle (single axis: one series at a time) ---- */
.seg { display: inline-flex; gap: 2px; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-pill); padding: 3px; }
.seg-btn { border: none; background: transparent; font-family: inherit; padding: 6px 13px; border-radius: var(--r-pill); font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--ink-soft); cursor: pointer; transition: background var(--dur-fast), color var(--dur-fast); }
.seg-btn:hover { color: var(--ink); }
.seg-btn.active { background: var(--surface); color: var(--coral-ink); box-shadow: var(--shadow-sm); }

/* ---- toggle chip: an INDEPENDENT on/off ------------------------------------
   O irmão solto do `.seg`, e a diferença é semântica, não decorativa: um segmentado promete
   "escolha UMA"; isto aqui liga e desliga cada uma por conta. Quando duas condições que se
   acumulam (modo escuro + imagens bloqueadas) são desenhadas dentro de um `.seg`, a forma
   mente sobre o que o clique faz. Ligado = tinta coral, a mesma marca de "engatado" do
   .nav-item ativo e do .scope-trigger filtrando. */
.toggle-chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 13px; border-radius: var(--r-pill);
  background: var(--surface); border: 1px solid var(--line);
  font-family: inherit; font-size: var(--text-sm); font-weight: var(--fw-semibold);
  color: var(--ink-soft); cursor: pointer;
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
}
.toggle-chip:hover { background: var(--line-soft); color: var(--ink); }
.toggle-chip:focus-visible { outline: none; border-color: var(--coral); box-shadow: var(--ring); }
.toggle-chip svg { width: 14px; height: 14px; }
.toggle-chip.on { background: var(--coral-tint); border-color: var(--coral-soft); color: var(--coral-ink); }
.toggle-chip.on:hover { filter: brightness(0.98); }

/* ---- trend chart ---- */
.chart-host { position: relative; margin-top: 4px; }
.chart { position: relative; }
.chart-svg { width: 100%; height: auto; display: block; overflow: visible; font-family: var(--font-sans); }
.chart-line { fill: none; stroke: var(--coral); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart-dot { fill: var(--coral); }
.chart-grid { stroke: var(--line-soft); stroke-width: 1; }
.chart-grid-base { stroke: var(--line); }
.chart-axis { fill: var(--ink-mute); font-size: 10px; font-variant-numeric: tabular-nums; }
.chart-cross { stroke: var(--ink-mute); stroke-width: 1; stroke-dasharray: 3 3; opacity: .5; transition: opacity var(--dur-fast); }
.chart-focus { fill: var(--coral); stroke: var(--surface); stroke-width: 2.5; transition: opacity var(--dur-fast); }
.chart-hit { cursor: crosshair; }
.chart-empty { padding: 48px 0; text-align: center; color: var(--ink-mute); font-size: var(--text-sm); }
.chart-tip {
  position: absolute; top: 4px; transform: translateX(-50%);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-sm);
  box-shadow: var(--shadow); padding: 9px 11px; pointer-events: none; z-index: 5;
  white-space: nowrap; transition: opacity var(--dur-fast); min-width: 132px;
}
.chart-tip-day { font-size: var(--text-xs); font-weight: var(--fw-semibold); color: var(--ink-soft); margin-bottom: 5px; }
.chart-tip-row { display: flex; align-items: center; justify-content: space-between; gap: 18px; font-size: var(--text-sm); color: var(--ink-mute); padding: 1px 0; }
.chart-tip-row b { color: var(--ink); font-weight: var(--fw-semibold); }

/* ---- funnel = the dashboard's summary row (visita → visitante → lead) --------
   The steps ARE the stat tiles (`.stat`, same recipe), so the summary is drawn once;
   what the funnel adds lives in the GUTTER — the relation between two steps. No
   magnitude bar: at 641.107 → 18.012 one shared scale draws the last step, the one
   that matters, as a nub (docs/DESIGN.md §6, rules 8–9). */
.funnel { display: grid; grid-template-columns: 1fr auto 1fr auto 1fr; align-items: center; gap: 14px; }
.funnel-step { min-width: 0; }
.funnel-link { display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 116px; padding: 0 2px; text-align: center; }
.funnel-arrow { display: block; margin-bottom: 5px; }
.funnel-arrow path { fill: none; stroke: var(--ink-faint); stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
.funnel-link-v {
  font-family: var(--font-display); font-size: var(--text-xl); font-weight: var(--fw-semibold);
  line-height: var(--lh-tight); letter-spacing: var(--trk-snug); color: var(--ink-soft);
}
.funnel-link-k { font-size: var(--text-xs); color: var(--ink-mute); font-weight: var(--fw-medium); }
/* The conversion is the one link the page is about — it gets the accent, and only it. */
.funnel-link.is-key .funnel-arrow path { stroke: var(--coral); }
.funnel-link.is-key .funnel-link-v { color: var(--coral); }
.funnel-link.is-key .funnel-link-k { color: var(--coral-ink); }
.funnel-link .stat-delta { margin-top: 2px; }

/* ---- paired cards + breakdown tables ----
   Both cells of a pair must be the same KIND of content (two rankings), and they
   stretch so the row reads as a row: a short card beside a long one used to leave a
   gap of bare paper that reads as a rendering bug. A card with no partner spans. */
.dash-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: stretch; }
.dash-grid > :only-child { grid-column: 1 / -1; }
/* One vertical rhythm for every block the dashboard stacks. */
.dash-body > .card, .dash-body > .dash-grid { margin-top: 18px; }
.dash-cardhead { padding: 16px 18px; border-bottom: 1px solid var(--line); }
.dash-sub { color: var(--ink-mute); font-size: var(--text-sm); margin: 3px 0 0; }
.dash-empty { padding: 34px 18px; text-align: center; color: var(--ink-mute); font-size: var(--text-sm); }
.dash-tablewrap { overflow-x: auto; }

table.dash-table { width: 100%; border-collapse: collapse; }
.dash-table th { text-align: left; font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--trk-label); color: var(--ink-mute); font-weight: var(--fw-semibold); padding: 11px 18px; border-bottom: 1px solid var(--line); background: var(--surface-2); white-space: nowrap; }
.dash-table td { padding: 9px 18px; border-bottom: 1px solid var(--line-soft); font-size: var(--text-base); vertical-align: middle; }
.dash-table tr:last-child td { border-bottom: none; }
.dash-table .ta-r { text-align: right; }
.dash-table td.cell-bar { width: 44%; min-width: 130px; }
/* A breakdown table in a FULL-WIDTH card: the slack goes to the bar, not to the gap
   between the label and it. At 1fr the label column doubles and every row reads as a
   name marooned from its own value. */
.dash-card-wide .dash-table td.cell-bar { width: 60%; }
.dash-table .num { font-variant-numeric: tabular-nums; }
.dash-table .pageref { max-width: 280px; }
.dash-table .pageref-label { font-weight: var(--fw-medium); }
.dash-table .src { font-weight: var(--fw-medium); }
/* Page cell with a host eyebrow — shown only when a path is split across hosts. */
.pagecell { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.pagecell-host { font-size: var(--text-xs); font-weight: var(--fw-medium); letter-spacing: var(--trk-tight); color: var(--ink-mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }

/* ---- data bar (magnitude behind a table value) ---- */
.databar { position: relative; height: 26px; display: flex; align-items: center; border-radius: 8px; overflow: hidden; }
.databar-fill { position: absolute; left: 0; top: 0; bottom: 0; background: var(--coral-soft); border-radius: 8px; }
.databar-label { position: relative; padding: 0 10px; font-size: var(--text-sm); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; color: var(--ink); }

/* ============================ PÁGINAS ==================================== */
/* Sparkline — the one coral mark, no axis (trend recognition only). */
.spark { display: block; margin-left: auto; }
.spark-line { stroke: var(--coral); stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }
.spark-dot { fill: var(--coral); }

.pages-toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 12px 18px; border-bottom: 1px solid var(--line); background: var(--surface-2); }
.pages-toolbar .seg { margin-right: auto; }

/* Filter controls share the scope/leads pill family. The search collapses last. */
.pages-search { flex: 0 1 220px; min-width: 150px; }
.pages-search input { width: 100%; height: 36px; padding-top: 0; padding-bottom: 0; font-size: var(--text-sm); }

/* Pill toggle — same shape/states as .scope-trigger, coral when on (cf. .quarantine-toggle). */
.pages-apptoggle {
  display: inline-flex; align-items: center; gap: 6px;
  height: 36px; padding: 0 12px 0 8px; white-space: nowrap;
  border: 1.5px solid var(--line); border-radius: var(--r-pill);
  background: var(--surface); color: var(--ink-soft);
  font-family: inherit; font-size: var(--text-sm); font-weight: var(--fw-semibold);
  cursor: pointer; user-select: none;
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
}
.pages-apptoggle:hover { background: var(--line-soft); color: var(--ink); }
.pages-apptoggle.on { background: var(--coral-tint); color: var(--coral-ink); border-color: var(--coral-tint); }
.pages-apptoggle.on:hover { filter: brightness(0.98); }
.pages-apptoggle .scope-lead-icon { width: 18px; height: 18px; color: inherit; }
.pages-apptoggle .scope-lead-icon svg { width: 15px; height: 15px; }
/* The card head becomes a row so the export sits discreetly in the top-right corner. */
.pages-cardhead { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.pages-export { margin-top: -2px; }

/* Page-class chips — informational, not semantic state (green/violet stay reserved). */
.pages-class { font-size: var(--text-xs); text-transform: none; }
.pages-class.app { opacity: .65; }

/* Sortable headers + expandable rows. */
.pages-th { cursor: pointer; user-select: none; }
.pages-th:hover { color: var(--ink); }
.pages-th.sorted { color: var(--ink); }
.pages-row { cursor: pointer; }
.pages-row.open td { border-bottom: none; }
.pages-detail > td { padding: 0 18px 14px 34px; background: var(--surface-2); }
.pages-bychannel { max-width: 640px; }
.pages-bychannel th { background: transparent; }
.pages-bychannel td.cell-bar { width: 36%; min-width: 110px; }
.pages-sparkcell { width: 110px; }
.pages-table td.cell-bar { width: 24%; min-width: 120px; }

.pages-notes { margin-top: var(--space-4); display: flex; flex-direction: column; gap: 4px; }

/* ============================ 5 · RESPONSIVE ============================= */
/* The funnel strip needs three tiles AND two gutters side by side; below this it
   stacks and the vertical order carries the flow (so the arrow, which only points
   right, is dropped rather than rotated into a box it no longer fits). */
@media (max-width: 1040px) {
  .funnel { grid-template-columns: 1fr; gap: 10px; }
  .funnel-link { flex-direction: row; align-items: baseline; gap: 8px; min-width: 0; padding: 0 20px; text-align: left; }
  .funnel-arrow { display: none; }
  .funnel-link-v { font-size: var(--text-lg); }
  .funnel-link .stat-delta { margin-top: 0; }
}

@media (max-width: 860px) {
  .shell { grid-template-columns: 1fr; }
  .sidebar { position: static; height: auto; flex-direction: row; overflow-x: auto; align-items: center; }
  .sidebar .spacer, .sidebar .who { display: none; }
  .main { padding: 22px 18px 50px; }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .detail-grid { grid-template-columns: 1fr; }
  .search input { width: 180px; }
  .page-head h1 { font-size: var(--text-2xl); }
  .dash-grid { grid-template-columns: 1fr; }
  .period { justify-content: flex-start; }
  .dash-table .pageref { max-width: 190px; }
  .dash-table td.cell-bar { width: 38%; min-width: 108px; }
  .settings-masonry { columns: 1; }
}

/* --- Lead segments -------------------------------------------------------------
   The segments list reuses table.leads; the builder is a stack of OR-joined group
   cards, each holding AND-joined condition rows built from native controls styled
   through the tokens so they read as one family with the rest of the app. */
.seg-dot { flex: none; width: 10px; height: 10px; border-radius: 50%; background: var(--pc, var(--coral)); box-shadow: inset 0 0 0 1px rgba(33, 28, 23, .12); }
.seg-name { display: inline-flex; align-items: center; gap: 10px; }

.seg-editor { display: block; }
.seg-label { display: block; font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--ink-soft); margin-bottom: 8px; }
.seg-name-input { width: 100%; font-family: inherit; font-size: var(--text-lg); font-weight: var(--fw-semibold); color: var(--ink); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); padding: 12px 14px; transition: border-color var(--dur-fast), box-shadow var(--dur-fast); }
.seg-name-input:focus { outline: none; border-color: var(--coral); box-shadow: var(--ring); }

/* Live preview bar */
.seg-previewbar { display: flex; align-items: baseline; gap: 10px; margin: 18px 0 14px; padding: 14px 18px; background: var(--coral-tint); border: 1px solid var(--coral-soft); border-radius: var(--r); }
.seg-preview-lead { font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--coral-ink); }
.seg-count { font-family: var(--font-display); font-size: var(--text-2xl); font-weight: var(--fw-bold); color: var(--coral-ink); font-variant-numeric: tabular-nums; transition: opacity var(--dur-fast); }
.seg-count.loading { opacity: .45; }
.seg-count.invalid { color: var(--ink-mute); }
.seg-preview-hint { font-size: var(--text-sm); color: var(--ink-mute); }

/* Groups + OR/AND joins */
.seg-groups { display: flex; flex-direction: column; gap: 0; }
.seg-group { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); padding: 16px; box-shadow: var(--shadow-sm); }
.seg-or { display: flex; align-items: center; justify-content: center; margin: 12px 0; position: relative; }
.seg-or::before, .seg-or::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.seg-or span { padding: 3px 14px; margin: 0 12px; font-size: var(--text-xs); font-weight: var(--fw-bold); letter-spacing: var(--trk-label); color: var(--ink-soft); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-pill); }
.seg-conds { display: flex; flex-direction: column; gap: 8px; }
.seg-and { font-size: var(--text-2xs); font-weight: var(--fw-bold); letter-spacing: var(--trk-label); color: var(--ink-mute); padding-left: 4px; }
.seg-and-mini { font-size: var(--text-xs); color: var(--ink-mute); padding: 0 2px; }

/* A single condition row */
.seg-cond { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* Condition menus (field / operator / scope) — a custom dropdown that reuses the dashboard
   scope filter's popover (.scope-panel / .scope-opt via components/dropdown.js). The trigger
   is a button sized to match the builder's native inputs (.seg-value) so a row reads level. */
.seg-dd { position: relative; display: inline-flex; }
.seg-select {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: inherit; font-size: var(--text-sm); color: var(--ink); text-align: left;
  /* WHITE surface, not the old grey `surface-2` — a menu is a first-class field, sized and
     bordered like the text inputs it sits among (.seg-value) and finished like the dashboard's
     scope-filter pill (.scope-trigger). The grey box read as disabled/off-brand. */
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  padding: 8px 12px; min-height: 38px; cursor: pointer;
  transition: background var(--dur-fast), border-color var(--dur-fast), box-shadow var(--dur-fast);
}
.seg-select:hover { background: var(--surface-2); border-color: var(--coral-soft); }
.seg-select:focus-visible { outline: none; border-color: var(--coral); box-shadow: var(--ring); }
.seg-select-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.seg-select .scope-caret { margin-left: auto; }
.seg-dd .scope-panel { min-width: 210px; }
/* Never let a long option label force the row to scroll sideways: the trigger caps at its
   container and the label ellipses (min-width:0 lets it shrink inside the inline-flex trigger). */
.seg-select { max-width: 100%; }
.seg-select-label { min-width: 0; }
/* In the narrow flow inspector, the FIELD menu takes its own line — a long field name gets the
   full width to ellipsis into — and the operator + value flow beneath it, instead of a cramped
   3-up row that overflowed. (The wrapper is .seg-dd; :has() picks the one holding the field.) */
.flow-insp .seg-cond > .seg-dd:has(.seg-field) { flex: 1 1 100%; }
.flow-insp .seg-cond > .seg-dd:has(.seg-field) .seg-select { width: 100%; }

/* Combobox — the design-system dropdown you can ALSO type into (dropdown.js combobox()). The field
   reads like a text input (.seg-value's white/bordered look) with a caret; the popover is the same
   .scope-panel, sized to the field so it never overflows the narrow inspector. Replaces the native
   <datalist>, whose OS popup was off-brand — the "opções soltas". */
.combo { position: relative; }
.combo-field { display: flex; align-items: center; min-height: 38px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); transition: border-color var(--dur-fast), box-shadow var(--dur-fast); }
.combo-field:focus-within { border-color: var(--coral); box-shadow: var(--ring); }
.combo-input { flex: 1; min-width: 0; border: none; background: transparent; padding: 8px 12px; font-family: inherit; font-size: var(--text-sm); color: var(--ink); }
.combo-input::placeholder { color: var(--ink-mute); }
.combo-input:focus { outline: none; }
.combo-mono { font-family: var(--font-mono); }
.combo-caret { display: inline-flex; align-items: center; flex: none; align-self: stretch; padding: 0 10px; color: var(--ink-mute); background: transparent; border: none; cursor: pointer; }
.combo-caret svg { width: 15px; height: 15px; transition: transform var(--dur-fast) var(--ease); }
.combo.open .combo-caret svg { transform: rotate(180deg); }
.combo-panel { left: 0; min-width: 0; max-width: none; width: 100%; }
.combo-note { padding: 9px 11px; color: var(--ink-mute); font-size: var(--text-xs); line-height: 1.45; }

/* Searchable select (dropdown.js searchSelect()) — o mesmo gatilho `.scope-trigger` do resto do
   app, com a BUSCA dentro do pop-over. É o que substitui o `<datalist>` num campo de escolher-um:
   o gatilho mostra sempre a escolha real (rótulo + dica em ink-mute, os dois com reticências),
   em vez de um campo de texto que pode exibir meia digitação enquanto o app guarda outra coisa. */
.ss { position: relative; }
/* O padrão do `.scope-trigger` reserva 7px à esquerda para um glifo (favicon, relógio); aqui o
   rótulo é a primeira coisa, então ele ganha a folga simétrica — e a seta vai para a borda
   quando o gatilho ocupa a largura do campo. */
.ss-trigger { max-width: 100%; min-width: 0; padding: 0 9px 0 13px; }
.ss-trigger .scope-caret { margin-left: auto; padding-left: 4px; }
.ss-trigger .scope-trigger-label { flex: 0 1 auto; }
.ss-hint { flex: 0 4 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink-mute); font-weight: var(--fw-medium); }
.ss-hint:empty { display: none; }
.ss-trigger.ss-empty .scope-trigger-label { color: var(--ink-mute); font-weight: var(--fw-medium); }
.ss-panel { padding: 0; min-width: 260px; width: max-content; max-width: min(420px, 90vw); }
/* O campo de busca fica COLADO no topo e não rola junto: numa lista de 8 leads a diferença é
   pequena, mas é ele que se procura quando a lista não trouxe o que se queria. */
.ss-field {
  position: sticky; top: 0; z-index: 1; display: flex; align-items: center; gap: 8px;
  padding: 9px 11px; background: var(--surface);
  border-bottom: 1px solid var(--line); border-radius: var(--r) var(--r) 0 0;
}
.ss-glass { display: inline-flex; flex: none; color: var(--ink-mute); }
.ss-glass svg { width: 15px; height: 15px; }
.ss-input { flex: 1; min-width: 0; border: none; background: transparent; font-family: inherit; font-size: var(--text-sm); color: var(--ink); }
.ss-input:focus { outline: none; }
.ss-input::placeholder { color: var(--ink-mute); }
.ss-rows { padding: 6px; max-height: min(46vh, 320px); overflow-y: auto; }
/* A dica aqui é um e-mail, não uma contagem: pode ser longa, então ela ENCOLHE (o .scope-opt-hint
   padrão é `flex: none`, que empurraria a linha para fora do painel) — e encolhe MUITO antes do
   nome (shrink 4 contra 1). Quem identifica a pessoa na lista é o nome; um e-mail cortado ainda
   serve de desempate, um "João P…" não. */
.ss-rows .scope-opt-label { flex: 0 1 auto; }
.ss-opt-hint { flex: 1 4 auto; min-width: 42px; text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--fw-medium); font-variant-numeric: normal; }

.seg-field { font-weight: var(--fw-semibold); }
.seg-op { color: var(--ink-soft); }
.seg-value, .seg-chip-input, .seg-fieldkey { font-family: inherit; font-size: var(--text-sm); color: var(--ink); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); padding: 8px 10px; min-width: 140px; transition: border-color var(--dur-fast), box-shadow var(--dur-fast); }
.seg-value:focus { outline: none; border-color: var(--coral); box-shadow: var(--ring); }
/* a number field is sized for a number — the UA's default input width (~175px) reads as a
   half-empty box next to its unit */
.seg-value-num { min-width: 0; width: 104px; }
.seg-value-date { min-width: 150px; }
.seg-value-scope { min-width: 180px; }
.seg-fieldkey { min-width: 120px; font-style: italic; }
.seg-num-wrap { display: inline-flex; align-items: center; gap: 6px; }
.seg-num-suffix { font-size: var(--text-sm); color: var(--ink-mute); }
.seg-daterange { display: inline-flex; align-items: center; gap: 6px; }

/* Multi-value chips */
.seg-chips { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); padding: 5px 8px; min-width: 180px; }
.seg-chip { display: inline-flex; align-items: center; gap: 4px; }
.seg-chip-x, .seg-chip-x:hover { background: transparent; border: none; padding: 0; margin-left: 2px; cursor: pointer; color: currentColor; opacity: .6; display: inline-flex; }
.seg-chip-x:hover { opacity: 1; }
.seg-chip-x svg { width: 12px; height: 12px; }
.seg-chip-input { border: none; padding: 3px 2px; min-width: 90px; flex: 1; background: transparent; }
.seg-chip-input:focus { outline: none; box-shadow: none; }

/* O SELETOR DE SEGMENTOS (o público: "manda para estes, menos estes") — components/segment-picker.js.
   Reusa a caixa de fichas acima de propósito: é a mesma ideia de "vários itens escolhidos numa caixa
   só", e a exclusão só se distingue da inclusão pela cor da ficha (.chip.danger), que é o que faz as
   duas listas não serem confundidas de relance. */
.seg-picker { display: flex; width: 100%; min-height: 38px; }
.seg-picker-add {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: inherit; font-size: var(--text-xs); font-weight: var(--fw-semibold);
  color: var(--ink-soft); background: transparent; border: 1px dashed var(--line);
  border-radius: var(--r-pill); padding: 4px 10px; cursor: pointer;
  transition: border-color var(--dur-fast), color var(--dur-fast);
}
.seg-picker-add:hover { border-color: var(--coral); color: var(--coral); }
.seg-picker-add svg { width: 12px; height: 12px; }
.seg-picker-empty { font-size: var(--text-xs); color: var(--ink-mute); align-self: center; }
/* Um segmento que sumiu: a ficha se anuncia em vez de aparecer vazia. */
.chip-missing { background: var(--line-soft); color: var(--ink-mute); font-style: italic; }
/* O total do público, sob o par de listas. Zero é uma condição de atenção, não um erro — quase
   sempre significa que a exclusão comeu a inclusão inteira. */
.audience-count { margin-top: 8px; font-variant-numeric: tabular-nums; }
.audience-count.is-zero { color: var(--amber-ink); font-weight: var(--fw-semibold); }

/* Optional date window on activity conditions */
.seg-when { display: inline-flex; align-items: center; gap: 6px; padding: 4px 8px; background: var(--amber-tint); border: 1px solid var(--line-soft); border-radius: var(--r-pill); }
.seg-when-lead svg { width: 15px; height: 15px; color: var(--amber); }
.seg-when-add { display: inline-flex; align-items: center; gap: 5px; font-family: inherit; font-size: var(--text-xs); font-weight: var(--fw-semibold); color: var(--ink-soft); background: transparent; border: 1px dashed var(--line); border-radius: var(--r-pill); padding: 5px 10px; cursor: pointer; transition: border-color var(--dur-fast), color var(--dur-fast); }
.seg-when-add:hover { color: var(--coral-ink); border-color: var(--coral-soft); }
.seg-when-add svg { width: 14px; height: 14px; }

/* Row + group actions */
.seg-remove-cond, .seg-remove-group { background: transparent; border: none; color: var(--ink-mute); cursor: pointer; padding: 6px; border-radius: var(--r); display: inline-flex; transition: color var(--dur-fast), background var(--dur-fast); }
.seg-remove-cond { margin-left: auto; }
.seg-remove-cond:hover, .seg-remove-group:hover { color: var(--rose); background: var(--surface-2); }
.seg-remove-cond svg, .seg-remove-group svg { width: 16px; height: 16px; }
.seg-group-foot { display: flex; align-items: center; justify-content: space-between; margin-top: 12px; }
.seg-add-cond { display: inline-flex; align-items: center; gap: 6px; font-family: inherit; font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--coral-ink); background: transparent; border: none; cursor: pointer; padding: 4px 0; }
.seg-add-cond svg { width: 15px; height: 15px; }
.seg-add-group { margin-top: 14px; align-self: flex-start; }
.btn-danger { color: var(--rose); }
.btn-danger:hover { background: var(--rose-tint, var(--surface-2)); }
.btn-sm { padding: 6px 12px; font-size: var(--text-xs); }

/* Segment context banner on the leads list */
.seg-banner { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; padding: 11px 16px; background: var(--coral-tint); border: 1px solid var(--coral-soft); border-radius: var(--r); font-size: var(--text-sm); color: var(--ink); }
.seg-banner-lead svg { width: 17px; height: 17px; color: var(--coral-ink); display: block; }
.seg-banner b { font-weight: var(--fw-semibold); color: var(--coral-ink); }
.seg-banner-edit { margin-left: auto; color: var(--ink-soft); font-weight: var(--fw-semibold); }
.seg-banner-edit:hover { color: var(--coral-ink); }
.seg-banner-clear { display: inline-flex; align-items: center; gap: 4px; color: var(--ink-soft); font-weight: var(--fw-semibold); }
.seg-banner-clear:hover { color: var(--coral-ink); }
.seg-banner-clear svg { width: 13px; height: 13px; }

/* --- Automations: the flow editor ----------------------------------------------
   An automation is a FLOW — a graph a lead walks. The canvas is hand-built (see
   public/js/components/flow/): ONE transformed "world" carries pan+zoom for both
   the SVG edge layer and the absolutely-positioned node cards, so neither ever
   pays a per-element write.

   COLOUR DISCIPLINE (docs/DESIGN.md §7): the canvas keeps the one-accent rule. The
   node's icon badge is the only tinted surface, and it encodes ROLE, not identity:
     entry  → coral      (the accent — where a lead comes in; there is exactly one)
     logic  → amber      (a decision: condicional, esperar, teste A/B)
     action → neutral    (the work; the glyph carries the meaning, not a hue)
     exit   → ink-mute   (the flow ends)
   Edges are warm hairlines, coral only on hover/active. Green/violet stay reserved
   for lead state, and no product colour is borrowed here. ------------------------ */

.chip.danger { background: var(--rose-tint); color: var(--rose); }

/* small shared bits (list + activity log) */
.wh-ico svg { width: 18px; height: 18px; color: var(--coral-ink); display: block; }
.wh-lede { color: var(--ink-mute); font-size: var(--text-sm); margin: 6px 0 14px; }
.wh-empty { color: var(--ink-mute); font-size: var(--text-sm); }

/* list */
.auto-name { display: flex; align-items: center; gap: 9px; }
.auto-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--line); flex: none; }
.auto-dot.on { background: var(--green); box-shadow: 0 0 0 3px var(--green-tint); }

/* shared form primitives (used by the inspector) */
.auto-field { display: flex; flex-direction: column; gap: 7px; }
.auto-hint { color: var(--ink-mute); font-size: var(--text-xs); margin: 0; line-height: 1.45; }
.auto-notice { display: flex; align-items: flex-start; gap: 8px; padding: 10px 14px; background: var(--amber-tint); border-radius: var(--r); color: var(--amber-ink); font-size: var(--text-sm); line-height: 1.45; }
.auto-notice svg { width: 16px; height: 16px; flex: none; margin-top: 2px; }
.auto-scope { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.auto-scope-opt { display: flex; align-items: flex-start; gap: 10px; text-align: left; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--r); background: var(--surface); cursor: pointer; transition: border-color var(--dur-fast), background var(--dur-fast); }
.auto-scope-opt:hover { border-color: var(--coral-soft); }
.auto-scope-opt.sel { border-color: var(--coral); background: var(--coral-tint); }
.auto-scope-opt b { display: block; font-size: var(--text-sm); font-weight: var(--fw-semibold); margin-bottom: 2px; }
.auto-scope-desc { display: block; color: var(--ink-mute); font-size: var(--text-xs); line-height: 1.35; }
.auto-radio { width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--ink-mute); flex: none; margin-top: 1px; position: relative; }
.auto-radio.on { border-color: var(--coral); }
.auto-radio.on::after { content: ''; position: absolute; inset: 3px; border-radius: 50%; background: var(--coral); }

/* ---- editor chrome ---------------------------------------------------------- */
.flow-editor { display: flex; flex-direction: column; gap: 14px; }
.flow-head { align-items: center; margin-bottom: 0; }
.flow-head-main { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
.flow-name { width: 100%; max-width: 520px; }
.flow-dirty { width: 7px; height: 7px; border-radius: 50%; background: transparent; flex: none; transition: background var(--dur-fast); }
.flow-dirty.on { background: var(--amber); box-shadow: 0 0 0 3px var(--amber-tint); }
.flow-tabs { align-self: flex-start; }

/* ---- stage: canvas + inspector ---------------------------------------------- */
/* No transition on grid-template-columns: animating a track width relayouts the whole canvas on
   every frame (and the canvas is the most expensive thing on the page). The drawer just appears. */
.flow-stage { display: grid; grid-template-columns: minmax(0, 1fr) 0; gap: 0; }
.flow-stage:has(.flow-insp-wrap.open) { grid-template-columns: minmax(0, 1fr) clamp(400px, 30vw, 520px); gap: var(--space-4); }

/* ---- the canvas ------------------------------------------------------------- */
.flow-canvas {
  position: relative; overflow: hidden;
  height: clamp(460px, calc(100vh - 300px), 900px);
  background-color: var(--surface-2);
  background-image: radial-gradient(circle, var(--line) 1px, transparent 1px);
  border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  touch-action: none; cursor: grab;
}
.flow-canvas.panning { cursor: grabbing; }
.flow-canvas.linking { cursor: crosshair; }
.flow-world { position: absolute; inset: 0; transform-origin: 0 0; will-change: transform; }
.flow-nodes { position: absolute; inset: 0; }
/* The edge layer is canvas-sized but draws (and hit-tests) outside its box: overflow:visible means
   no clip, and an unclipped SVG child still receives pointer events. Same trick React Flow uses. */
.flow-edges { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }

/* edges: a fat invisible path gives a 2px line a generous grab area */
.flow-edge { fill: none; stroke: var(--ink-mute); stroke-width: 1.75; stroke-linecap: round; transition: stroke var(--dur-fast); }
.flow-edge.hot { stroke: var(--coral); stroke-width: 2.25; }
.flow-edge.ghost { stroke: var(--coral); stroke-dasharray: 5 5; }
.flow-edge-hit { fill: none; stroke: transparent; stroke-width: 22; pointer-events: stroke; }

.flow-edge-tools { position: absolute; display: flex; gap: 4px; transform: translate(-50%, -50%); opacity: 0; pointer-events: none; transition: opacity var(--dur-fast); }
.flow-edge-tools.show { opacity: 1; pointer-events: auto; }
.flow-edge-btn { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0; border-radius: 50%; border: 1px solid var(--line); background: var(--surface); color: var(--ink-soft); cursor: pointer; box-shadow: var(--shadow-sm); }
.flow-edge-btn:hover { border-color: var(--coral); color: var(--coral-ink); }
.flow-edge-cut:hover { border-color: var(--rose); color: var(--rose); }
.flow-edge-btn svg { width: 13px; height: 13px; }

/* ---- node card -------------------------------------------------------------- */
.flow-node {
  position: absolute; top: 0; left: 0;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  box-shadow: var(--shadow-sm); cursor: grab; user-select: none;
  transition: box-shadow var(--dur-fast), border-color var(--dur-fast);
}
.flow-node:hover { border-color: var(--coral-soft); box-shadow: var(--shadow); }
.flow-node.sel { border-color: var(--coral); box-shadow: var(--ring), var(--shadow); }
.flow-node.dragging { cursor: grabbing; box-shadow: var(--shadow-lg); }

.flow-node-head { display: flex; align-items: center; gap: 11px; padding: 14px 15px; height: 78px; box-sizing: border-box; }
.flow-node-text { min-width: 0; }
.flow-node-title { display: flex; align-items: center; gap: 6px; font-size: var(--text-base); font-weight: var(--fw-semibold); color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.flow-node-sub { font-size: var(--text-xs); color: var(--ink-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 2px; }
.flow-stub { font-size: var(--text-2xs); font-weight: var(--fw-semibold); color: var(--ink-mute); background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-pill); padding: 1px 6px; }

/* the badge is the ONE tinted surface on a card, and it encodes role (see header) */
.flow-badge { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; flex: none; border-radius: var(--r-sm); background: var(--surface-2); color: var(--ink-soft); }
.flow-badge svg { width: 18px; height: 18px; }
.role-entry .flow-badge, .flow-badge.role-entry { background: var(--coral-tint); color: var(--coral-ink); }
.role-logic .flow-badge, .flow-badge.role-logic { background: var(--amber-tint); color: var(--amber-ink); }
.role-action .flow-badge, .flow-badge.role-action { background: var(--surface-2); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
.role-exit .flow-badge, .flow-badge.role-exit { background: var(--surface-2); color: var(--ink-mute); }

/* labelled outputs: each branch is a pill on the bottom edge, anchored on its port,
   so a multi-way condition explains itself without a legend or a hover */
.flow-node-foot { display: flex; border-top: 1px solid var(--line-soft); height: 34px; box-sizing: border-box; }
.flow-pill { position: relative; display: flex; align-items: center; justify-content: center; min-width: 0; border-left: 1px solid var(--line-soft); }
.flow-pill:first-child { border-left: none; }
.flow-pill-label { font-size: var(--text-2xs); font-weight: var(--fw-semibold); letter-spacing: var(--trk-label); text-transform: uppercase; color: var(--ink-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 0 6px; }
.flow-pill.muted .flow-pill-label { color: var(--ink-mute); }

/* ---- ports ------------------------------------------------------------------ */
.flow-port { position: absolute; width: 11px; height: 11px; border-radius: 50%; background: var(--surface); border: 2px solid var(--ink-mute); box-sizing: border-box; }
.flow-port.in { top: -6px; left: 50%; transform: translateX(-50%); }
.flow-port.in.target { border-color: var(--coral); background: var(--coral); box-shadow: 0 0 0 5px var(--coral-tint); }
.flow-port.out { bottom: -6px; left: 50%; transform: translateX(-50%); cursor: crosshair; }
.flow-port.out.linked { background: var(--ink-mute); }
.flow-port.out:hover { border-color: var(--coral); box-shadow: 0 0 0 5px var(--coral-tint); }

/* the "+" that hangs under an unconnected output — the primary way to build a flow */
.flow-addnext { position: absolute; top: 16px; left: 50%; transform: translateX(-50%); display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0; border-radius: 50%; border: 1px dashed var(--line); background: var(--surface); color: var(--ink-soft); cursor: pointer; box-shadow: var(--shadow-sm); transition: border-color var(--dur-fast), color var(--dur-fast), background var(--dur-fast); }
.flow-addnext:hover { border-style: solid; border-color: var(--coral); color: var(--coral-ink); background: var(--coral-tint); }
.flow-addnext svg { width: 13px; height: 13px; }
.flow-addnext::before { content: ''; position: absolute; bottom: 22px; left: 50%; width: 1px; height: 10px; background: var(--line); }

/* ---- canvas toolbar --------------------------------------------------------- */
.flow-tools { position: absolute; right: 14px; bottom: 14px; display: flex; flex-direction: column; gap: 6px; z-index: 2; }
.flow-tool { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); color: var(--ink-soft); cursor: pointer; box-shadow: var(--shadow-sm); }
.flow-tool:hover { color: var(--coral-ink); border-color: var(--coral-soft); }
.flow-tool svg { width: 16px; height: 16px; }

/* ---- step palette (docked, not floating) ------------------------------------
   Clicking a "+" opens this DOCKED to the canvas's left edge. It was a floating
   popover first, and that was wrong twice over: the popover base class
   (.scope-panel) is invisible until an ancestor `.dd` opens — so it rendered as
   nothing — and once visible it had to be clamped inside a canvas barely taller
   than itself, landing far from the "+" that opened it. Docked, it is always in
   the same place, never covers the node being wired, and scrolls on its own
   (canvas.js stops `wheel` from bubbling, or the graph would zoom instead). */
.flow-picker {
  position: absolute; left: 0; top: 0; bottom: 0; z-index: 6;
  width: 288px; display: flex; flex-direction: column;
  background: var(--surface); border-right: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  animation: flow-picker-in var(--dur) var(--ease);
}
@keyframes flow-picker-in { from { transform: translateX(-8px); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .flow-picker { animation: none; } }

.flow-picker-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 14px 16px; border-bottom: 1px solid var(--line-soft); }
.flow-picker-head h4 { font-family: var(--font-display); font-size: var(--text-md); font-weight: var(--fw-semibold); color: var(--ink); }
.flow-picker-x { display: inline-flex; padding: 4px; border: none; background: transparent; color: var(--ink-mute); cursor: pointer; border-radius: var(--r-sm); }
.flow-picker-x:hover { color: var(--ink); background: var(--surface-2); }
.flow-picker-x svg { width: 15px; height: 15px; }

.flow-picker-list { flex: 1; overflow-y: auto; overscroll-behavior: contain; padding: 6px; }
.flow-pick { display: flex; align-items: flex-start; gap: 10px; width: 100%; text-align: left; }
.flow-pick-ico { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; flex: none; border-radius: var(--r-sm); background: var(--surface-2); color: var(--ink-soft); }
.flow-pick-ico svg { width: 14px; height: 14px; }
.flow-pick-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.flow-pick-hint { font-size: var(--text-xs); color: var(--ink-mute); white-space: normal; line-height: 1.35; }

/* ---- inspector drawer ------------------------------------------------------- */
.flow-insp-wrap { overflow: hidden; }
.flow-insp { display: flex; flex-direction: column; height: 100%; max-height: clamp(460px, calc(100vh - 300px), 900px); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow-sm); }
.flow-insp-head { display: flex; flex-direction: column; gap: 8px; padding: 16px 18px; border-bottom: 1px solid var(--line-soft); }
.flow-insp-id { display: flex; align-items: center; gap: 11px; min-width: 0; }
.flow-insp-head h3 { font-family: var(--font-display); font-size: var(--text-lg); font-weight: var(--fw-semibold); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.flow-insp-head p { font-size: var(--text-sm); color: var(--ink-mute); line-height: 1.45; }
.flow-insp-body { display: flex; flex-direction: column; gap: 16px; padding: 16px 18px; overflow-y: auto; flex: 1; }
.flow-insp-foot { padding: 12px 18px; border-top: 1px solid var(--line-soft); }
.flow-insp .auto-notice { margin: 0 18px; }
/* The choice cards go two-up on a full-width page (the trigger's own tab), but the drawer is
   380px: side by side, each description breaks into four ragged lines. Stack them here. */
.flow-insp .auto-scope { grid-template-columns: 1fr; }
.flow-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.flow-select { min-width: 150px; }
.flow-method { min-width: 92px; }
.flow-url, .flow-body { width: 100%; box-sizing: border-box; }
.flow-body { font-family: var(--font-mono); font-size: var(--text-sm); }
.flow-key { min-width: 130px; font-family: var(--font-mono); font-size: var(--text-sm); }
.flow-hint { font-size: var(--text-xs); color: var(--ink-mute); line-height: 1.45; }
.seg-op-static { color: var(--ink-mute); font-weight: var(--fw-semibold); white-space: nowrap; }

/* Ordinal list rows in the inspector (template {{vars}} and the repeat message rungs): an ordinal
   marker + one input that fills + a remove button that stays with the row. Distinct from the
   condition builder's bare .seg-cond, whose row is full of controls and parks its X far-right via
   margin-left:auto — here the row is a SINGLE input, so that same rule would (a) let the width:100%
   .flow-url wrap the input onto its own line, stranding the ordinal above and the X below, and
   (b) open a dead gap after the 140px vars input. The ordinal gets a fixed column so every input
   left-edge lines up, the input fills, and the X sits right after it. */
.flow-listrow { flex-wrap: nowrap; }
.flow-listrow .seg-op-static { flex: none; min-width: 32px; font-variant-numeric: tabular-nums; }
.flow-listrow .seg-value { flex: 1 1 auto; min-width: 0; width: auto; }
.flow-listrow .seg-remove-cond { flex: none; margin-left: 0; }

/* schedule trigger: the 1–31 day-of-month grid (the days a recurring flow fires on) */
.flow-days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.flow-day { display: inline-flex; align-items: center; justify-content: center; height: 34px; padding: 0; border: 1px solid var(--line); border-radius: var(--r); background: var(--surface); color: var(--ink-soft); font-size: var(--text-sm); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; cursor: pointer; transition: border-color var(--dur-fast), background var(--dur-fast), color var(--dur-fast); }
.flow-day:hover { border-color: var(--coral-soft); }
.flow-day.on { border-color: var(--coral); background: var(--coral-tint); color: var(--coral-ink); }

/* API list source: the "Testar conexão" result (discovered fields) */
.src-probe { margin: 8px 0 4px; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r); background: var(--surface-2); }
.src-probe .flow-var-chips { margin-top: 6px; }
/* O começo do corpo cru da resposta, quando o teste de conexão não conseguiu ler as linhas: é a
   única pista que resta, então precisa ser legível — monoespaçado, com rolagem própria (regra do
   §9: conteúdo largo rola dentro do seu container, a coluna nunca). */
.src-probe .src-raw {
  margin: 8px 0 0; padding: 8px 10px; max-height: 180px; overflow: auto;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink-soft);
  font: 400 11px/1.5 var(--font-mono); white-space: pre-wrap; word-break: break-word;
}

/* API list source: the phone-field map. ONE input per row (the response field), full width, with a
   trailing remove — same shape as .flow-listrow. No "procedência" column: it confused operators and,
   in the 380px drawer, its second min-width input wrapped every row into a cramped stack of two. */
.src-phones { display: flex; flex-direction: column; gap: 8px; margin-bottom: 4px; }
.src-phone-row { display: flex; align-items: center; gap: 8px; }
.src-phone-row .combo { flex: 1 1 auto; min-width: 0; }
.src-phone-row .seg-remove-cond { flex: none; margin-left: 0; }

/* repeat node: the send-window time inputs (sit inline, not stretched to the field min-width) */
.seg-value-time { min-width: 0; width: auto; flex: 0 0 auto; }

/* condition/split branch cards inside the inspector */
.flow-branch { border: 1px solid var(--line); border-radius: var(--r); padding: 12px; background: var(--surface-2); }
.flow-branch-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.flow-branch-n { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; flex: none; border-radius: 50%; background: var(--amber-tint); color: var(--amber-ink); font-size: var(--text-2xs); font-weight: var(--fw-bold); }
.flow-branch-name { flex: 1; min-width: 0; font-weight: var(--fw-semibold); }
.flow-add-branch { align-self: flex-start; }
.flow-split-row { align-items: center; }
.flow-branch .seg-group { background: var(--surface); box-shadow: none; }

/* the condition builder, tightened for the drawer */
.seg-compact .seg-group { padding: 12px; border-radius: var(--r); }
.seg-compact .seg-cond { gap: 6px; }
.seg-compact .seg-value, .seg-compact .seg-select { min-width: 96px; }

/* variable chips: click to copy a {{token}} — how data moves between steps */
.flow-vars { display: flex; flex-direction: column; gap: 6px; }
.flow-var-chips { display: flex; flex-wrap: wrap; gap: 5px; }
.flow-var { font-family: var(--font-mono); font-size: var(--text-2xs); background: var(--surface-2); border: 1px solid var(--line); color: var(--ink-soft); cursor: pointer; }
.flow-var:hover { border-color: var(--coral-soft); color: var(--coral-ink); background: var(--coral-tint); }

/* ---- activity log + runs ---------------------------------------------------- */
.auto-log-wrap { margin-top: 18px; }
.auto-log-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.auto-log-head > div:first-child { display: flex; align-items: center; gap: 8px; }
.auto-log-head h3 { font-family: var(--font-display); font-size: var(--text-lg); font-weight: var(--fw-semibold); }
.auto-log { display: flex; flex-direction: column; }
/* Resumo (métricas por período) */
.auto-stats { margin-bottom: 16px; }
.stat .stat-sub { font-size: var(--text-xs); margin-top: 4px; }
.auto-sum-extra { margin: 0 0 14px; font-size: var(--text-sm); }
.auto-sum-motivos { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: baseline; margin: 0 0 18px; font-size: var(--text-sm); }
.auto-sum-lbl { color: var(--ink-mute); font-weight: var(--fw-semibold); }
.auto-sum-motivo-n { font-variant-numeric: tabular-nums; font-weight: var(--fw-semibold); }
.auto-sum-table { padding: 0; overflow-x: auto; }
.auto-sum-table th.num, .auto-sum-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
@media (max-width: 720px) { .auto-stats { grid-template-columns: repeat(2, 1fr); } }
.auto-log-row { display: grid; grid-template-columns: 92px 150px 190px 1fr auto auto; align-items: center; gap: 10px; padding: 9px 2px; border-top: 1px solid var(--line-soft); font-size: var(--text-sm); }
.auto-log-row:first-child { border-top: none; }
.flow-run-row { grid-template-columns: 100px 200px 150px 1fr auto; }
.auto-log-event { color: var(--ink); font-weight: var(--fw-medium); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
a.auto-log-event:hover { color: var(--coral-ink); }
.auto-log-lead { font-family: var(--font-mono); font-size: var(--text-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.auto-log-msg { color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.auto-log-time { font-size: var(--text-xs); white-space: nowrap; color: var(--ink-faint); }
.flow-log-detail { background: transparent; border: none; color: var(--ink-mute); cursor: pointer; padding: 2px; display: inline-flex; }
.flow-log-detail:hover { color: var(--coral-ink); }
.flow-log-detail svg { width: 14px; height: 14px; }
.flow-log-pre { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--ink-soft); background: var(--surface-2); border: 1px solid var(--line-soft); border-radius: var(--r-sm); padding: 10px 12px; margin: 2px 0 8px; white-space: pre-wrap; word-break: break-word; max-height: 220px; overflow: auto; }

@media (max-width: 980px) {
  .flow-stage, .flow-stage:has(.flow-insp-wrap.open) { grid-template-columns: 1fr; }
  .flow-insp { max-height: 520px; margin-top: var(--space-4); }
}
@media (max-width: 640px) {
  .auto-scope { grid-template-columns: 1fr; }
  .auto-log-row, .flow-run-row { grid-template-columns: auto 1fr auto; }
  .auto-log-lead, .auto-log-msg { display: none; }
}

/* =============================================================================
   14. COMUNICAÇÕES — the e-mail composer
   -----------------------------------------------------------------------------
   Two surfaces live here and they must not be confused:

   • The DASHBOARD chrome (the funnel, the header card, the inspector) is the
     product's own design system — tokens, Fraunces, coral.
   • The PAPER (.mail-paper and everything inside it) is a rehearsal of an INBOX.
     It deliberately does NOT use the brand's type or colour: an e-mail renders in
     Gmail with Helvetica or Georgia at 16px, and a preview that shows Hanken
     Grotesk at 15px is a preview that lies. The paper is the one place in this
     codebase where a hard-coded px and a system font stack are correct — they are
     not styling, they are a simulation of the destination.
   ============================================================================= */

/* ---- list ------------------------------------------------------------------- */
.mail-row-name { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mail-row-subject { color: var(--ink-mute); font-size: var(--text-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- the creation funnel ---------------------------------------------------- */
/* ONE measure for the funnel, the way .settings-page takes one. Without it the page inherited
   .main's full width: on a wide screen the card grid laid seven 210px tracks for three cards, so
   the two groups ended at different x, and the 60ch lede floated in a 1600px field. This is a page
   for READING two questions and choosing — it is not a table, so it gets a measure. */
.mail-new { max-width: 1000px; }
/* Where am I? The funnel is two steps and used to say so only in the prose ("Primeiro:" / "Agora:").
   It's the .u-eyebrow primitive, not a new stepper component: two steps don't need a diagram, and
   the marker stays --ink-mute because the accent is already spoken for by the choice itself. */
.mail-step { display: block; margin-bottom: 7px; }
.mail-choices { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap); }
.mail-choice {
  display: flex; flex-direction: column; align-items: flex-start; gap: 10px; text-align: left;
  padding: 26px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm); cursor: pointer; font-family: inherit;
  transition: border-color var(--dur-fast), box-shadow var(--dur-fast), transform var(--dur-fast);
}
.mail-choice:hover { border-color: var(--coral-soft); box-shadow: var(--shadow); transform: translateY(-2px); }
.mail-choice-icon {
  display: inline-flex; align-items: center; justify-content: center; width: 38px; height: 38px;
  border-radius: var(--r-sm); background: var(--coral-tint); color: var(--coral-ink);
}
.mail-choice-icon svg { width: 19px; height: 19px; }
.mail-choice h3 { font-family: var(--font-display); font-size: var(--text-xl); font-weight: var(--fw-semibold); letter-spacing: var(--trk-snug); }
.mail-choice p { color: var(--ink-soft); font-size: var(--text-base); line-height: var(--lh-normal); }
/* A ficha do que a escolha É — o mesmo par chave/valor da ficha do lead (.kv): chave apagada,
   valor em texto, hairline tracejada. As duas fichas respondem as mesmas três perguntas na mesma
   ordem e com a MESMA coluna de chave, então elas alinham lado a lado e a comparação se lê na
   horizontal — que é a decisão que este passo pede.

   Aqui havia bullets com um check --green. Verde é SEMÂNTICO neste sistema ("lead conhecido", §2),
   e o §6 regra 3 diz para não gastá-lo como decoração: o check não significava nada, só somava um
   clichê de tabela de preço. A identidade vem do tipo (micro-caps + os degraus de tinta quente),
   como o §3 declara — não de um ícone colorido. */
/* margin-top:auto ancora a ficha no PISO do cartão. Sem isso ela seguia a descrição, que tem duas
   linhas num cartão e três no outro — as linhas caíam 22px fora de registro e a leitura horizontal,
   que é o motivo da ficha existir, ia embora. O grid já estica os dois à mesma altura, então o piso
   é a única régua que as duas compartilham. A coluna de chave é fixa pelo mesmo motivo. */
.mail-choice-spec { display: flex; flex-direction: column; width: 100%; margin: auto 0 0; }
.mail-choice-spec .row {
  display: grid; grid-template-columns: 62px 1fr; gap: 12px; align-items: baseline;
  padding: 8px 0; border-top: 1px dashed var(--line-soft);
}
.mail-choice-spec .row:first-child { border-top: none; }
/* dt herda o --ink-mute da .u-eyebrow — a mesma tinta que a chave da ficha do lead (.kv .k) usa. */
.mail-choice-spec dd { margin: 0; color: var(--ink-soft); font-size: var(--text-sm); line-height: var(--lh-normal); }

.mail-tpl-group { margin-top: var(--space-7); }
.mail-tpl-blurb { color: var(--ink-mute); font-size: var(--text-sm); line-height: var(--lh-normal); max-width: 68ch; margin: 6px 0 16px; }
.mail-tpls { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: var(--gap); }
.mail-tpl {
  display: flex; flex-direction: column; gap: 0; padding: 0; text-align: left; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); cursor: pointer;
  font-family: inherit; transition: border-color var(--dur-fast), box-shadow var(--dur-fast), transform var(--dur-fast);
}
.mail-tpl:hover { border-color: var(--coral-soft); box-shadow: var(--shadow); transform: translateY(-2px); }
.mail-tpl-meta { display: flex; flex-direction: column; gap: 3px; padding: 12px 14px 14px; }
.mail-tpl-meta b { font-size: var(--text-base); }
.mail-tpl-meta span { color: var(--ink-mute); font-size: var(--text-xs); line-height: 1.45; }

/* The thumbnail is a MINIATURE of the message, drawn FROM the block list, so it cannot
   misrepresent the layout. It also draws the difference the two groups exist to sell, and draws it
   the way the renderer does: a LETTER has no container (EmailHtml::renderPlain emits no wrapper, no
   padding, no ground), a CAMPAIGN is a card on a tinted ground.

   Colour is the accent rule, not a rendering: the coral belongs to the campaign's button — the one
   mark that says "this is marketing" — and to nothing else. A letter's link is text (§8), and an
   image placeholder is a placeholder, so it is warm neutral rather than the --coral-soft data-viz
   fill it used to borrow. Widths come from the real text (emails.js `lines`), which is what makes
   seven starters look like seven starters. */
.mail-tpl-thumb {
  height: 176px; padding: 12px; overflow: hidden; border-bottom: 1px solid var(--line-soft);
}
.mail-tpl-thumb.plain { background: var(--surface); padding: 14px 16px; }
.mail-tpl-thumb.visual { background: var(--paper); }

.mt-sheet { height: 100%; }
.mail-tpl-thumb.visual .mt-sheet {
  padding: 9px; border-radius: 5px; background: var(--surface); box-shadow: var(--shadow-sm);
}
/* The flow is a VIEWPORT onto the top of the message, and it fades where the message keeps going —
   the mask rides the content, not the sheet, so a campaign's card stays a whole card while its
   text runs off the foot. Nothing to toggle: a starter that fits never reaches the gradient, so
   the fade appears on exactly the ones that are still going. That the letters fit and the
   campaigns don't is not a layout accident — it is the difference the two groups are selling. */
.mt-flow {
  display: flex; flex-direction: column; gap: 9px; height: 100%; overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 20px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 20px), transparent);
}

/* Three gaps, and they have to stay far enough apart to be read as three: 3px between the lines of
   a paragraph, 7px between paragraphs, 9px between blocks. At 3/6/6 the whole letter came out as
   one mass of bars with no paragraphing — which is the one thing a letter's shape IS. */
.mt-line { display: block; height: 4px; border-radius: 2px; background: var(--line); }
.mt-text { display: flex; flex-direction: column; gap: 7px; }
.mt-p { display: flex; flex-direction: column; gap: 3px; }
.mt-head { display: block; height: 7px; border-radius: 2px; background: var(--ink-mute); }
.mt-li { display: flex; flex-direction: column; gap: 3px; position: relative; padding-left: 7px; }
.mt-li::before {
  content: ''; position: absolute; left: 0; top: 1px;
  width: 3px; height: 3px; border-radius: 50%; background: var(--ink-faint);
}
.mt-img {
  display: flex; align-items: center; justify-content: center; flex: none; height: 34px;
  border-radius: 3px; background: var(--surface-2); border: 1px solid var(--line-soft); color: var(--ink-faint);
}
.mt-img svg { width: 13px; height: 13px; }
.mt-btn { display: block; flex: none; height: 10px; width: 46%; border-radius: 5px; background: var(--coral); }
.mt-btn.center { margin: 0 auto; }
/* A letter's CTA. It has to read as a bit of emphasised TEXT — at --ink-soft it was the darkest
   thing in the letter and stole the eye the coral button is meant to have in the other group. */
.mt-link { display: block; flex: none; height: 4px; width: 32%; border-radius: 2px; background: var(--ink-mute); }
.mt-div { display: block; flex: none; height: 1px; background: var(--line); }
.mt-space { display: block; flex: none; height: 6px; }
/* A signature is text, so it is the same ink as text — only short. At --ink-faint it was darker
   than the body it signs off, which drew every letter as a sign-off with noise above it. */
.mt-sig { display: flex; flex-direction: column; gap: 3px; }
.mt-sig .mt-line:first-child { width: 38%; }
.mt-sig .mt-line:last-child { width: 24%; }
/* The footer just follows the message. It must NOT be pinned to the foot with margin-top:auto the
   way it used to be: that opened the void that made every letter read as a half-loaded skeleton,
   and under the fade it would now sit permanently in the gradient. A short letter simply ends
   early and leaves paper below it — which is what a short letter looks like. */
.mt-foot { display: flex; flex-direction: column; gap: 3px; }
.mt-foot .mt-line { height: 3px; background: var(--line-soft); }
.mt-foot .mt-line:last-child { width: 54%; }

/* ---- the composer page ------------------------------------------------------ */
.mail-editor { display: flex; flex-direction: column; gap: var(--gap); }
/* O cabeçalho do composer é o único que põe um CAMPO (o nome) no lugar do <h1> — e é por isso que o
   `align-items: flex-end` do .page-head não servia aqui: com uma pilha de três itens à esquerda, os
   botões alinhavam pelo RODAPÉ dela (as tags) e atravessavam a altura do input, mirando nada.
   Centralizados contra o bloco nome+tags eles têm um eixo. O margin-bottom sai porque o .mail-editor
   já é um flex column com gap — os dois somavam. */
.mail-editor .page-head { align-items: center; margin-bottom: 0; }
.mail-editor .page-head > div:first-child {
  flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
}
/* Um nome interno não precisa de 1000px, e esticado ele encostava nos botões. */
.mail-editor .seg-name-input { width: 100%; max-width: 520px; }
/* align-self: sem ele o inline-flex estica no column e a faixa clicável vai de ponta a ponta. */
.mail-editor > .back-link { align-self: flex-start; margin-bottom: 0; }
.mail-tags { display: flex; gap: 6px; }
.mail-header .card-title { margin-bottom: 16px; }
.mail-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 18px 20px; }
.mail-fields > .auto-field:first-child, .mail-fields > .auto-field:nth-child(2) { grid-column: span 2; }
/* O PÚBLICO de um disparo: "recebem" e "menos" lado a lado, atravessando a grade. Separados em
   colunas diferentes eles caem na diagonal e deixam de se ler como uma subtração. */
.mail-fields > .mail-audience { grid-column: span 2; }
.mail-audience-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 20px; align-items: start; }
.mail-audience-tag {
  display: block; margin-bottom: 6px;
  font-size: var(--text-xs); font-weight: var(--fw-semibold); letter-spacing: .02em;
  text-transform: uppercase; color: var(--ink-mute);
}
.mail-audience-tag.is-out { color: var(--rose); }
.mail-audience .audience-count { margin-top: 12px; }
@media (max-width: 900px) { .mail-audience-row { grid-template-columns: 1fr; gap: 14px; } }

.mail-subject { position: relative; display: flex; align-items: center; }
.mail-subject .input { padding-right: 62px; }
.mail-counter {
  position: absolute; right: 12px; color: var(--ink-faint); font-size: var(--text-xs);
  font-variant-numeric: tabular-nums; pointer-events: none;
}
.mail-counter.over { color: var(--coral-deep); font-weight: var(--fw-semibold); }
.btn.is-dirty { box-shadow: 0 0 0 3px var(--coral-tint); }

/* stage: the paper on the left, the block inspector on the right */
.mail-stage { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: var(--gap); align-items: start; }
.mail-canvas {
  padding: var(--space-6); border-radius: var(--r-lg); background: var(--surface-2);
  border: 1px solid var(--line); min-height: 520px;
}

/* ---- THE PAPER: a rehearsal of the inbox, not of the dashboard --------------- */
.mail-paper {
  --mail-accent: #F85D5E;
  --mail-ground: #FFFFFF;
  width: 100%; max-width: 600px; margin: 0 auto; box-sizing: border-box;
  font-family: -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  font-size: 16px; line-height: 26px; color: #2B2621;
}
.mail-paper.serif { font-family: Georgia, "Times New Roman", Times, serif; }

/* The LETTER. Everything here is a subtraction, and each one mirrors EmailHtml::renderPlain — if
   that renderer stops emitting something, this must stop showing it, or the paper goes back to
   lying. It rehearses a message someone typed in Gmail: no container (no max-width, no padding, no
   radius), Arial rather than the design system's stack, and plain black text at the client's own
   default, because the renderer emits no colour at all. The canvas around it supplies the air. */
.mail-paper.plain {
  max-width: none; background: #FFFFFF; padding: 0; border-radius: 0;
  font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; color: #000000;
}
.mail-paper.plain.serif { font-family: Georgia, "Times New Roman", Times, serif; }
/* Gmail's own link, not ours: a coral link is the tool signing work a person supposedly typed. */
.mail-paper.plain .mail-text a,
.mail-paper.plain .mail-btn-link { color: #1155CC; text-decoration: underline; }

.mail-paper.card {
  background: #FFFFFE; padding: 32px 30px; border-radius: 14px; border: 1px solid #ECE3D6;
  box-shadow: var(--shadow-sm);
}
.mail-stack { display: flex; flex-direction: column; }

.mail-block { position: relative; border-radius: var(--r-sm); padding: 2px; transition: box-shadow var(--dur-fast); }
.mail-block:hover { box-shadow: 0 0 0 1px var(--line); }
.mail-block.sel { box-shadow: 0 0 0 2px var(--coral); }
.mail-block-tag {
  position: absolute; top: -9px; left: 8px; z-index: 2; display: none; align-items: center; gap: 4px;
  padding: 1px 7px; border-radius: var(--r-pill); background: var(--coral); color: #fff;
  font-family: var(--font-sans); font-size: var(--text-2xs); font-weight: var(--fw-semibold);
  letter-spacing: var(--trk-label); text-transform: uppercase; line-height: 15px;
}
.mail-block-tag svg { width: 10px; height: 10px; }
.mail-block.sel .mail-block-tag { display: inline-flex; }
.mail-block-bar {
  position: absolute; top: 4px; right: 4px; z-index: 2; display: none; gap: 2px; padding: 3px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-sm); box-shadow: var(--shadow-sm);
}
.mail-block:hover .mail-block-bar, .mail-block.sel .mail-block-bar { display: flex; }
.mail-bbtn {
  display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px;
  border: none; border-radius: 6px; background: transparent; color: var(--ink-mute); cursor: pointer;
}
.mail-bbtn:hover:not(:disabled) { background: var(--coral-tint); color: var(--coral-deep); }
.mail-bbtn:disabled { opacity: .3; cursor: default; }
.mail-bbtn svg { width: 14px; height: 14px; }

/* the inline "+" between blocks */
.mail-insert { display: flex; align-items: center; gap: 6px; height: 12px; opacity: 0; transition: opacity var(--dur-fast); }
.mail-insert:hover, .mail-insert:focus-within, .mail-stack > .mail-insert:last-child { opacity: 1; }
.mail-insert-line { flex: 1; height: 1px; background: var(--coral-soft); }
.mail-insert-btn {
  display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; flex: none;
  border: 1px solid var(--coral-soft); border-radius: 50%; background: var(--surface); color: var(--coral-deep);
  cursor: pointer; padding: 0;
}
.mail-insert-btn:hover { background: var(--coral); border-color: var(--coral); color: #fff; }
.mail-insert-btn svg { width: 12px; height: 12px; }
.mail-palette .scope-panel { min-width: 270px; }
.mail-opt-icon { color: var(--ink-mute); display: inline-flex; }
.mail-opt-icon svg { width: 15px; height: 15px; }
.mail-empty-hint { color: var(--ink-mute); font-size: var(--text-sm); text-align: center; padding: 28px 0; font-family: var(--font-sans); }

/* block bodies, styled as the renderer will render them */
.mail-text { outline: none; }
.mail-text:focus { outline: none; }
.mail-text p { margin: 0 0 16px; }
.mail-text p:last-child { margin-bottom: 0; }
.mail-text h2 { font-size: 22px; line-height: 30px; font-weight: 700; margin: 0 0 12px; }
.mail-text h3 { font-size: 18px; line-height: 26px; font-weight: 700; margin: 0 0 10px; }
.mail-text ul, .mail-text ol { margin: 0 0 16px; padding-left: 22px; }
.mail-text li { margin-bottom: 6px; }
.mail-text a { color: var(--mail-accent); text-decoration: underline; }
.mail-text:empty::before { content: "Escreva aqui."; color: #9C9082; }

.mail-btn-wrap { padding: 4px 0 20px; }
.mail-btn {
  display: inline-block; padding: 14px 28px; border-radius: 10px;
  background: var(--mail-accent); color: #FFFFFE; font-size: 16px; font-weight: 700; line-height: 20px;
}
.mail-btn-link { color: var(--mail-accent); text-decoration: underline; }
.mail-btn.nolink, .mail-btn-link.nolink { opacity: .55; }
.mail-img { display: block; width: 100%; height: auto; border-radius: 4px; margin: 0 auto 20px; }
.mail-img-empty {
  display: flex; align-items: center; justify-content: center; gap: 8px; height: 120px; margin-bottom: 20px;
  border: 1px dashed #D8CDBC; border-radius: 6px; color: #9C9082;
  font-family: var(--font-sans); font-size: var(--text-sm);
}
.mail-img-empty svg { width: 18px; height: 18px; }
.mail-divider { height: 1px; background: #ECE3D6; margin: 8px 0 24px; }
.mail-spacer { background: repeating-linear-gradient(45deg, transparent, transparent 5px, #F7F2E9 5px, #F7F2E9 10px); }
.mail-sig { display: flex; flex-direction: column; }
.mail-sig b { font-weight: 400; }
.mail-sig span { font-size: 14px; line-height: 22px; color: #6B6053; }
.mail-sig i { font-style: normal; font-size: 14px; line-height: 22px; color: #6B6053; margin-top: 16px; }
.mail-footer { border-top: 1px solid #ECE3D6; padding-top: 24px; margin-top: 8px; }
.mail-footer p { font-size: 12px; line-height: 20px; color: #9C9082; margin: 0 0 6px; }
.mail-footer u { text-decoration: underline; }

/* ---- the same blocks, as a LETTER -------------------------------------------
   The mirror of EmailHtml's plain block methods. Everything above draws a card; a letter is what is
   left when you stop drawing one. Keep the two in step — the paper's whole job is to not lie. */
.mail-paper.plain .mail-text p,
.mail-paper.plain .mail-text ul,
.mail-paper.plain .mail-text ol { margin: 0 0 16px; }
/* Nobody types a 22px display heading into Gmail — they bold a line. */
.mail-paper.plain .mail-text h2,
.mail-paper.plain .mail-text h3 { font-size: 16px; line-height: 24px; font-weight: 700; margin: 0 0 16px; }
/* No pill: the CTA is a link on its own line (the composer already swaps in .mail-btn-link). */
.mail-paper.plain .mail-btn-wrap { padding: 0 0 16px; }
/* A typed signature is the person still talking: same size, no grey. */
.mail-paper.plain .mail-sig span,
.mail-paper.plain .mail-sig i { font-size: 16px; line-height: 24px; color: #000000; }
/* Size says "boilerplate"; a grey would be a colour to defend under forced dark mode, and a rule
   above it would rebuild the container this mode exists to avoid. */
.mail-paper.plain .mail-footer { border-top: none; padding-top: 0; margin-top: 24px; }
.mail-paper.plain .mail-footer p { font-size: 13px; line-height: 20px; color: #000000; margin: 0; }
/* It renders as a real <a> in the message, so it must read as one here. */
.mail-paper.plain .mail-footer u { color: #1155CC; }
.mail-paper.plain .mail-divider { background: none; border-top: 1px solid #CCCCCC; margin: 8px 0 16px; }

/* ---- the block inspector ---------------------------------------------------- */
.mail-insp {
  display: flex; flex-direction: column; gap: 16px; padding: 18px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm); position: sticky; top: var(--space-5);
}
.mail-insp-head { display: flex; flex-direction: column; gap: 8px; padding-bottom: 14px; border-bottom: 1px solid var(--line-soft); }
.mail-insp-id { display: flex; align-items: center; gap: 11px; }
.mail-insp-head h3 { font-family: var(--font-display); font-size: var(--text-lg); font-weight: var(--fw-semibold); }
.mail-insp-head p { font-size: var(--text-sm); color: var(--ink-mute); line-height: 1.45; }
.mail-badge {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; flex: none;
  border-radius: var(--r-sm); background: var(--surface-2); color: var(--ink-soft); box-shadow: inset 0 0 0 1px var(--line);
}
.mail-badge svg { width: 15px; height: 15px; }

.mail-toolbar { display: flex; align-items: center; gap: 2px; padding: 4px; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-sm); }
.mail-tbtn {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
  border: none; border-radius: 6px; background: transparent; color: var(--ink-soft); cursor: pointer;
}
.mail-tbtn:hover { background: var(--coral-tint); color: var(--coral-deep); }
.mail-tbtn svg { width: 15px; height: 15px; }
.mail-tsep { width: 1px; height: 18px; background: var(--line); margin: 0 3px; }
.mail-linkrow { display: flex; gap: 6px; }
.mail-linkinput { flex: 1; min-width: 0; }

.mail-rangerow { display: flex; align-items: center; gap: 10px; }
.mail-range { flex: 1; accent-color: var(--coral); }
.mail-rangev { color: var(--ink-mute); font-size: var(--text-sm); font-variant-numeric: tabular-nums; min-width: 46px; text-align: right; }

.mail-check {
  display: flex; align-items: center; gap: 9px; padding: 10px 12px; width: 100%; text-align: left;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-sm);
  color: var(--ink); font-family: inherit; font-size: var(--text-base); cursor: pointer;
}
.mail-check:hover { border-color: var(--coral-soft); }
.mail-check.on { background: var(--coral-tint); border-color: var(--coral-soft); color: var(--coral-ink); }
.mail-checkbox {
  display: inline-flex; align-items: center; justify-content: center; width: 17px; height: 17px; flex: none;
  border: 1px solid var(--line); border-radius: 5px; background: var(--surface); color: #fff;
}
.mail-check.on .mail-checkbox { background: var(--coral); border-color: var(--coral); }
.mail-checkbox svg { width: 11px; height: 11px; }

.mail-swatches { display: flex; gap: 7px; flex-wrap: wrap; }
.mail-swatch {
  width: 28px; height: 28px; border-radius: 50%; border: 2px solid transparent; cursor: pointer; padding: 0;
  background: var(--sw); box-shadow: inset 0 0 0 1px rgba(72, 50, 28, .12);
}
.mail-swatch.on { border-color: var(--ink); }

/* ---- dialog: o primitivo de modal ÚNICO (confirmação, e o que for estreito + bloqueante) ------
   Scrim + card centralizado, dos MESMOS tokens do modal de pré-visualização de e-mail. A a11y
   (role=dialog, aria-modal, foco preso, Esc, foco de volta) mora em components/confirm.js. z-index
   acima do mail-overlay (60) para uma confirmação poder cobrir a pré-visualização se preciso. */
.modal-overlay {
  position: fixed; inset: 0; z-index: 70; display: flex; align-items: center; justify-content: center;
  padding: var(--space-6); background: rgba(33, 28, 23, .5);
}
.modal-card {
  display: flex; flex-direction: column; gap: 14px; width: 100%; max-width: 420px;
  padding: 22px; background: var(--paper); border-radius: var(--r-lg); box-shadow: var(--shadow-lg);
}
.modal-head { display: flex; align-items: center; gap: 11px; }
.modal-icon { flex: none; display: inline-flex; width: 20px; height: 20px; color: var(--ink-soft); }
.modal-icon svg { width: 20px; height: 20px; }
.modal-confirm.is-danger .modal-icon { color: var(--rose); }
.modal-title { font-family: var(--font-display); font-size: var(--text-lg); font-weight: var(--fw-semibold); }
.modal-body { display: flex; flex-direction: column; gap: 12px; }
.modal-msg { font-size: var(--text-sm); color: var(--ink-soft); line-height: 1.5; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 2px; }

/* ---- preview: a real render, in a sandboxed frame --------------------------- */
.mail-overlay {
  position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center;
  padding: var(--space-6); background: rgba(33, 28, 23, .5);
}
.mail-modal {
  display: flex; flex-direction: column; gap: 12px; width: 100%; max-width: 900px; max-height: 92vh;
  padding: 18px; background: var(--paper); border-radius: var(--r-lg); box-shadow: var(--shadow-lg);
}
.mail-modal-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.mail-modal-head h3 { font-family: var(--font-display); font-size: var(--text-lg); font-weight: var(--fw-semibold); margin-right: auto; }
.mail-views .seg-btn { display: inline-flex; align-items: center; gap: 6px; }
.mail-views svg { width: 14px; height: 14px; }
.mail-sims { display: inline-flex; gap: 8px; flex-wrap: wrap; }

/* A linha do lead + assunto: uma régua só sob o cabeçalho, porque as duas respondem a mesma
   pergunta ("para esta pessoa, o que chega na caixa?"). O assunto ocupa o resto e corta com
   reticências — o que é fiel ao meio: é assim que a caixa de entrada o trata. */
.mail-meta { display: flex; align-items: center; gap: 10px; min-width: 0; }
.mail-meta-label { flex: none; }
.mail-meta .lead-ref { flex: 0 1 auto; min-width: 200px; max-width: 460px; }
.mail-subject { flex: 1; min-width: 0; font-size: var(--text-sm); color: var(--ink-soft); }
.mail-subject-line { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.mail-subject-line > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }

/* Os avisos: UMA lista de conferência, não N alarmes empilhados. Cada aviso numa faixa própria
   somava três blocos âmbar entre o cabeçalho e a mensagem — e repetir o ⚠ em cada linha fazia
   "três coisas a melhorar" parecer "três erros". A contagem vai no topo, com o único glifo. */
.mail-warns:empty { display: none; }
.mail-checklist {
  padding: 9px 12px; border-radius: var(--r-sm);
  background: var(--amber-tint); color: var(--amber-ink);
  font-size: var(--text-sm); line-height: 1.4;
}
.mail-checklist-head { display: flex; align-items: center; gap: 7px; font-weight: var(--fw-semibold); }
.mail-checklist-head svg { width: 14px; height: 14px; flex: none; }
/* Aviso único: sem contagem, e em peso normal — uma frase inteira em semibold âmbar grita. */
.mail-checklist.one .mail-checklist-head { align-items: flex-start; font-weight: var(--fw-medium); }
.mail-checklist.one .mail-checklist-head svg { margin-top: 3px; }
.mail-checklist-items { list-style: none; margin: 4px 0 0; padding: 0 0 0 21px; }
.mail-checklist-items li { position: relative; padding: 1px 0; }
.mail-checklist-items li::before { content: ''; position: absolute; left: -12px; top: .62em; width: 4px; height: 4px; border-radius: 50%; background: currentColor; opacity: .5; }

/* Envio de teste: um modal estreito — é um campo e um botão, não merece a largura da
   pré-visualização (que precisa caber um e-mail de 600px). */
.mail-modal-sm { max-width: 460px; }
.mail-modal-foot { display: flex; justify-content: flex-end; gap: 8px; }
.mail-test-body { display: flex; flex-direction: column; gap: 10px; }
.mail-test-body .seg-label { margin-bottom: 0; }
.mail-test-body .small { font-size: var(--text-xs); }
.mail-test-warn {
  padding: 7px 11px; border-radius: var(--r-sm);
  background: var(--amber-tint); color: var(--amber-ink); font-size: var(--text-sm);
}
.mail-test-result:empty { display: none; }
/* No modal do teste o seletor é um CAMPO de formulário, empilhado com o "Para" — então ele veste
   a forma de campo (retângulo arredondado, altura do .input), não a pílula de filtro que o mesmo
   gatilho usa numa barra de ferramentas. Mesma peça, duas roupas: o que muda é o contexto. */
.mail-test-body .lead-ref .scope-trigger {
  width: 100%; height: 44px; border-radius: var(--r-sm); padding: 0 10px 0 13px;
  font-size: var(--text-base); font-weight: var(--fw-medium);
}
.mail-test-body .lead-ref .scope-trigger:hover { background: var(--surface); border-color: var(--coral-soft); }
.mail-test-ok {
  display: flex; align-items: center; gap: 7px; padding: 8px 11px; border-radius: var(--r-sm);
  background: var(--green-tint); color: var(--green); font-size: var(--text-sm); line-height: 1.4;
}
.mail-test-ok svg { width: 15px; height: 15px; flex: none; }
.mail-test-err {
  padding: 8px 11px; border-radius: var(--r-sm);
  background: var(--coral-tint); color: var(--coral-ink); font-size: var(--text-sm); line-height: 1.4;
}
/* O texto cru do servidor ("535 5.7.8 …") é o que diz o que consertar — legível, não escondido. */
.mail-test-err .small { margin-top: 4px; color: var(--coral-ink); opacity: .85; word-break: break-word; }
.mail-frame-stage {
  flex: 1; min-height: 0; display: flex; justify-content: center; overflow: auto;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r); padding: 16px;
}
.mail-frame { width: 100%; max-width: 700px; height: 100%; min-height: 420px; border: none; background: #fff; border-radius: var(--r-sm); }
.mail-frame-stage.mobile .mail-frame { max-width: 390px; }
/* Dark mode and blocked images are FORCED on the frame, not asked of it: the Gmail app inverts
   whether the message consents or not, and Outlook blocks images by default. This is the only way
   to see what most recipients actually get. */
.mail-frame-stage.dark { background: #1B1714; }
.mail-frame-stage.dark .mail-frame { filter: invert(1) hue-rotate(180deg); background: #1B1714; }
.mail-frame-stage.noimg .mail-frame { filter: grayscale(1) opacity(.98); }
.mail-frame-stage.noimg.dark .mail-frame { filter: invert(1) hue-rotate(180deg) grayscale(1); }

/* ---- sender defaults, in Pixel & Config ------------------------------------- */
/* A plain stack, NOT .mail-fields: that grid spans its first two children across two columns, so
   reusing it in a one-column card silently pairs the remaining fields side by side. */
.mail-senderfields { display: flex; flex-direction: column; gap: 16px; }

/* A escolha que vai dentro de toda mensagem (o pixel) — mesma família do remetente/rodapé.
   Alinhado ao topo: o texto explica um trade-off e ocupa várias linhas, então centralizar
   deixaria a caixa flutuando no meio do parágrafo. */
.setting-check { display: flex; align-items: flex-start; gap: 10px; cursor: pointer; }
.setting-check input { accent-color: var(--coral); margin-top: 3px; flex: none; }
.setting-check b { font-size: var(--text-sm); }
.setting-check .auto-hint { margin-top: 3px; }

/* A abertura na lista de comunicações. Discreta de propósito: é um número aproximado ao lado de
   colunas que são exatas, e a tipografia não deve dar a ele autoridade que ele não tem. */
.mail-opens { font-variant-numeric: tabular-nums; font-size: var(--text-sm); cursor: help; }

/* ---- the flow's e-mail node picker ------------------------------------------ */
.flow-mailrow { display: flex; gap: 8px; flex-wrap: wrap; }

@media (max-width: 1100px) {
  .mail-stage { grid-template-columns: 1fr; }
  .mail-insp { position: static; }
}
@media (max-width: 760px) {
  .mail-choices { grid-template-columns: 1fr; }
  .mail-fields { grid-template-columns: 1fr; }
  .mail-fields > .auto-field:first-child, .mail-fields > .auto-field:nth-child(2) { grid-column: auto; }
}

/* ===================== LINK PÚBLICO DO LEAD (/s/<token>) ===================== */
/* No painel: a caixinha do link, no cabeçalho da ficha. */
.share-box { display: flex; flex-direction: column; gap: 6px; align-items: flex-end; }
.share-row { display: flex; gap: 8px; align-items: center; }
.share-row .input { width: 340px; max-width: 46vw; font-size: var(--text-xs); color: var(--ink-soft); }
.share-meta { display: flex; gap: 12px; align-items: center; font-size: var(--text-xs); }
.linklike {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-size: var(--text-xs); color: var(--ink-soft);
  text-decoration: underline; text-underline-offset: 2px;
}
.linklike:hover { color: var(--ink); }
.linklike.danger { color: var(--rose); }

/* Fora do painel: a página que a pessoa com o link vê. Sem sidebar, sem menu — só a ficha,
   com a marca no topo para dizer de onde ela veio. */
.public-page { max-width: 1100px; margin: 0 auto; padding: 34px 24px 60px; }
.public-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  margin-bottom: 26px; padding-bottom: 18px; border-bottom: 1px solid var(--line-soft);
}
.public-foot { margin-top: 26px; font-size: var(--text-xs); text-align: center; }

/* Descadastro (/u/<token>). Estreito de propósito: a página tem UM botão e nenhuma pergunta —
   ver o cabeçalho de views/unsubscribe.js para por que não há atrito aqui. */
.unsub-card { max-width: 440px; margin: 40px auto; text-align: center; }
.unsub-card h2 { margin-bottom: var(--space-3); }
.unsub-card .btn { margin-top: var(--space-5); }
.unsub-card .unsub-error { margin-top: var(--space-3); color: var(--coral); }
.unsub-card .small { margin-top: var(--space-4); font-size: var(--text-xs); }

@media (max-width: 900px) {
  .share-box { align-items: flex-start; }
  .share-row .input { width: 100%; max-width: none; }
}
