/* ===========================================================
   Arqia · Validação Contratual — design system
   Type: Montserrat (Galano Grotesque when licensed)
   Palette: docs/reference/brand/STYLE-GUIDE.md
   Accessibility: every text token clears WCAG AA 4.5:1 on both
   white and Alice blue. Vivid brand colors (--*-ico) are fills
   and dots only, never text: they fail AA as text. Guarded by
   billing_validation/tests/web/test_color_contrast.py
   =========================================================== */
/* The UA sheet's `[hidden]{display:none}` is beaten on origin by ANY author
   rule that sets `display`. Two in this file do it on elements that carry
   the attribute: `.rl-sec` (display:flex) and `.st` (display:inline-flex),
   so a family heading the Regras filter hid stayed on the page, and the
   status badge a termo replaces with its live stage list stayed beside it.
   `!important` is what the UA rule needed all along. Global on purpose, and
   at the top on purpose: it is a reset, not part of any component. */
[hidden]{display:none!important}

:root{
  /* The page ground: the login screen's gradient (templates/registration/
     login.html), with every stop taken a quarter of the way to white. The login
     page is one card on an empty field and carries the full tint; these pages
     are dense, and at full strength the lavender competes with the white
     panels sitting on it. Same shape and hue, gently lifted.
     Cards stay --surface white, so the tint reads as depth behind them. */
  --bg:radial-gradient(135% 90% at 50% -10%, #F2EDFB 0%, #F8F6FD 46%, #FCFBFE 100%);
  --surface:#fff; --sunken:#E9F0F3;

  /* text ramp — all three pass AA on white AND on Alice blue */
  --ink:#3D2F7F; --sec:#5A4E92; --ter:#6E639F;

  /* non-text only: borders, dividers, decorative glyphs */
  --icon-muted:#8E88A3;
  --line:rgba(61,47,127,.12); --line-2:rgba(61,47,127,.07);

  --accent:#662DFF; --accent-soft:#F1ECFE; --accent-soft-2:#E6DBFD;
  --expanded:#FBFAFF;

  /* status: -ico is the vivid brand color (dot/icon), the base is the label */
  --ok:#0B6B41;   --ok-ico:#0AE587;   --ok-bg:#E8FBF3;
  --warn:#7A5B00; --warn-ico:#FFC700; --warn-bg:#FFF6DC;
  --bad:#D90A66;  --bad-ico:#FF0033;  --bad-bg:#FFF2F6;
  /* Body text on --bad-bg. The --bad label colour is tuned for chips at 10.5px
     and goes muddy in a paragraph, so the callout that says a ceiling takes
     effect immediately gets its own darker ink. In :root rather than inline so
     test_color_contrast.py can see it: that test only reads custom properties. */
  --bad-ink:#8A2050;
  --neu:#5F5A70;  --neu-ico:#8E88A3;  --neu-bg:#F1F2F5;
  /* Two verdicts that are neighbours of ok/bad but must not be mistaken for
     them at a glance. "Aprovado com ressalva" is an approval a person forced,
     so it reads green, but a deeper teal green than the engine's own mint:
     side by side in the distribution bar the two greens must be tellable
     apart, which is the whole reason the verdict got a chip of its own.
     "Bloqueado" outranks "Reprovado" and is the only verdict no analyst can
     clear from the quote page, so it takes a heavier wine red than the hot
     crimson a rejection uses. */
  --ressalva:#0F6A54; --ressalva-ico:#18B88A; --ressalva-bg:#E6F7F1;
  --bloqueio:#7A0B2E; --bloqueio-ico:#A80B2E; --bloqueio-bg:#FBE9EE;

  /* gradient #1 — logo and hero decoration ONLY (its red end is 3.96:1) */
  --grad-brand:linear-gradient(90deg,#FF0033 0%,#D90A66 35%,#662DFF 100%);
  /* hero fill — gradient #1 MIRRORED so text (left-aligned) sits on the indigo/rose
     end (5.02:1+, AA-safe for small text); the red end lands far-right under the
     ring motif, where no text goes. */
  --grad-hero:linear-gradient(90deg,#662DFF 0%,#D90A66 65%,#FF0033 100%);
  /* gradient #2 — nav bar; white text is safe end to end (5.02 → 10.99) */
  --grad-nav:linear-gradient(90deg,#D90A66 0%,#3D2F7F 100%);

  /* Nav bar height. A token because the top-right ring set centres on the
     corner of the CONTENT area, which is this value down from the viewport
     top: with 72px written in two places they drift and the ring goes
     off-centre. */
  --bar-h:72px;
  --r:16px;
  /* A three-stop elevation ramp: a contact shadow that pins the card's edge,
     a mid layer that gives it height, and a wide ambient one that lifts it off
     the page. The card and the page are both pure white, so with the grey
     title bar gone this token is the only thing that makes a card a card.
     Two of the five stops carry a NEGATIVE y offset: with light coming
     straight down the top edge got nothing, so a card read as sitting on the
     page rather than above it. They stay weaker than their downward twins,
     because an upward shadow at equal strength stops looking like depth and
     starts looking like a glow.
     Tinted with the brand indigo rather than black: a neutral shadow on this
     background reads as dirty grey. Used by .panel, .tile and .banner, so
     every card on every page moves together. */
  --shadow:0 -1px 2px rgba(61,47,127,.02),0 -8px 22px -10px rgba(61,47,127,.04),0 1px 2px rgba(61,47,127,.03),0 6px 16px -4px rgba(61,47,127,.04),0 20px 44px -16px rgba(61,47,127,.065);
}
*{box-sizing:border-box}
html,body{margin:0}
/* Always reserve the scrollbar gutter so centered content (main{margin:0 auto})
   doesn't shift horizontally between pages that scroll and pages that don't. */
html{scrollbar-gutter:stable}
body{
  font-family:"Galano Grotesque","Montserrat",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  /* The login page's ground, applied to the authenticated pages too. It is
     `fixed` because these pages are long and a radial gradient anchored to the
     document would stretch with the content: the tint has to stay where the
     login page puts it, at the top of the VIEWPORT. */
  background:var(--bg);background-attachment:fixed;
  color:var(--ink);font-size:14px;line-height:1.47;letter-spacing:-.008em;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
}
a{color:inherit;text-decoration:none}
.mono{font-variant-numeric:tabular-nums;font-feature-settings:"tnum"}
.sp{flex:1}
/* Tertiary text ramp as a utility class, not just the --ter variable: used
   wherever a caption or count needs to read as muted rather than inherit
   whatever colour rule its parent happens to carry (e.g. .kpi .d.up/.down
   green/red, .bc-row .ct's bold ink). */
.ter{color:var(--ter)}

/* ---- top bar ---- */
.bar{position:sticky;top:0;z-index:10;display:flex;align-items:center;gap:38px;padding:0 40px;height:var(--bar-h);
  background:var(--grad-nav);
  border-bottom:1px solid rgba(255,255,255,.10)}
.logo-img{height:32px;display:block}
/* Brand rings watermark behind every authenticated page, one set tucked into
   the top-right corner and one into the bottom-left, so the page is framed on
   its diagonal rather than weighted to one side. Both bleed off their corner:
   a ring set fully inside the viewport reads as a logo someone forgot to
   place, one that runs off the edge reads as texture.
   Fixed to the viewport rather than the document so they behave as a backdrop
   and do not drift as you scroll a long list. z-index 0 keeps them under the
   content; the nav bar is z-index 10 and covers the top of the upper set.
   Opacity is the one knob worth turning if they read too strong or too faint. */
/* The ring set's CENTRE sits exactly on the viewport corner, so the arcs
   radiate out of it. The graphic is square, so that means offsetting it by
   half its own width on both axes: the offsets are derived from --ring-size
   with calc() rather than typed as literals, because a hand-tuned pair drifts
   off-centre the moment the size changes and the effect only works while the
   centre is exactly on the corner. Exactly one quadrant is on screen.
   The two sets do NOT share a vertical anchor. The bottom-left one centres on
   the viewport corner; the top-right one centres --bar-h lower, on the corner
   of the content area, because the nav bar is opaque and a set centred on the
   viewport corner would have its whole upper quadrant swallowed by chrome. */
.page-rings{position:fixed;--ring-size:620px;width:var(--ring-size);opacity:.12;
  pointer-events:none;z-index:0;user-select:none}
.page-rings.tr{top:calc(var(--bar-h) - var(--ring-size) / 2);right:calc(var(--ring-size) / -2)}
.page-rings.bl{bottom:calc(var(--ring-size) / -2);left:calc(var(--ring-size) / -2)}
/* The watermark is position:fixed at z-index 0, so the page content needs its
   own stacking context to sit above it rather than under. */
main{position:relative;z-index:1}
.tabs{display:flex;gap:28px;height:100%}
/* All tabs are solid white: on --grad-nav's rose end even .9-alpha white is only
   4.22:1 (below AA), so neither colour-alpha nor element opacity can dim an inactive
   tab and stay legible. The active state is carried by weight + the underline. */
.tabs a{display:flex;align-items:center;height:100%;font-weight:500;color:#fff;font-size:14px;position:relative;transition:font-weight .18s ease}
.tabs a.on{font-weight:700}
.tabs a.on::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;background:#fff;border-radius:2px}
.tabs a:hover{color:#fff}
.tabs .n{margin-left:6px;background:var(--bad);color:#fff;font-size:10.5px;font-weight:700;min-width:16px;height:16px;padding:0 4px;border-radius:999px;display:grid;place-items:center;align-self:center}
.usr{display:flex;align-items:center;gap:9px;color:rgba(255,255,255,.72);font-size:13px;font-weight:500;transition:transform .18s ease}
.av{width:28px;height:28px;border-radius:50%;background:rgba(255,255,255,.16);color:#fff;display:grid;place-items:center;font-weight:600;font-size:11px;
  transition:transform .25s cubic-bezier(.34,1.4,.5,1)}
.usr:hover .av{transform:scale(1.08)}

/* ---- page header ---- */
main{max-width:1360px;margin:0 auto;padding:40px 40px 76px}
/* Positioned and raised so the "?" popover can escape it. The panels below
   are later in the DOM and animate their own opacity, which gives each one a
   stacking context that painted over a popover anchored in a static header.
   Safe against the sticky nav: `main` is itself a stacking context at
   z-index 1, so nothing inside it can rise above `.bar` at 10. */
.head{display:flex;align-items:flex-end;gap:13px;margin-bottom:32px;
  position:relative;z-index:60}
.head h1{margin:0;font-size:30px;font-weight:700;letter-spacing:-.03em;line-height:1.05}
.head .sub{color:var(--ter);font-size:15px;font-weight:500;margin-bottom:4px}
.back{display:inline-flex;align-items:center;gap:6px;color:var(--sec);font-weight:500;font-size:13.5px;margin-bottom:14px;transition:color .18s ease,transform .18s ease}
.back:hover{color:var(--accent);transform:translateX(-2px)}
.section-label{font-size:12px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--ter);margin:0 0 12px}

/* ---- hero (showcase surfaces only: overview, kpis, login) ---- */
.hero-showcase{position:relative;overflow:hidden;border-radius:var(--r);padding:34px 36px;margin-bottom:32px;
  background:var(--grad-hero);color:#fff}
.hero-showcase h1{margin:0;font-size:30px;font-weight:700;letter-spacing:-.03em;color:#fff}
.hero-showcase .sub{display:block;color:#fff;font-size:15px;font-weight:500;margin-top:6px}
.hero-showcase .rings{position:absolute;right:-58px;top:-86px;width:280px;opacity:.5;pointer-events:none}

/* ---- login (no nav bar here — centered card on a soft brand wash) ---- */
.login-view{min-height:100vh;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:44px 20px}
.login-stack{width:100%;max-width:428px;display:flex;flex-direction:column;align-items:center}
.login-mark{width:150px;height:auto;margin-bottom:26px}
.login-card{position:relative;overflow:hidden;width:100%;background:#fff;border-radius:22px;
  padding:38px 34px 34px;border:1px solid rgba(61,47,127,.05);
  box-shadow:0 1px 2px rgba(61,47,127,.06), 0 24px 60px -20px rgba(61,47,127,.24)}
.login-rings{position:absolute;right:-72px;top:-88px;width:212px;opacity:.14;pointer-events:none}
.login-title{position:relative;margin:0;font-size:26px;font-weight:800;letter-spacing:-.02em;color:var(--ink)}
.login-sub{position:relative;margin:6px 0 26px;font-size:14px;line-height:1.5;color:var(--sec)}
.login-form{position:relative;display:flex;flex-direction:column}
.login-label{font-size:11px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--ter);margin:0 0 7px}
.login-input{width:100%;padding:13px 14px;font-family:inherit;font-size:14px;color:var(--ink);background:#fff;
  border:1px solid var(--line);border-radius:12px;margin-bottom:18px;transition:border-color .16s ease,box-shadow .16s ease}
.login-input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.login-hint{margin:-8px 0 20px;font-size:12px;color:var(--ter)}
.login-error{margin:-8px 0 20px;font-size:12px;font-weight:600;color:var(--bad)}
.login-btn{display:block;width:100%;text-align:center;border:0;border-radius:12px;padding:14px;cursor:pointer;
  font-family:inherit;font-size:14px;font-weight:700;letter-spacing:.01em;color:#fff;
  background:linear-gradient(90deg,#D90A66 0%,#662DFF 100%);box-shadow:0 8px 20px -8px rgba(102,45,255,.5);
  transition:transform .18s cubic-bezier(.34,1.4,.5,1),filter .18s ease,box-shadow .18s ease}
.login-btn:hover{transform:translateY(-1px);filter:brightness(1.05);box-shadow:0 12px 26px -8px rgba(102,45,255,.55)}
.login-btn:active{transform:scale(.99)}
.login-secure{position:relative;display:flex;align-items:flex-start;gap:9px;margin-top:20px;padding-top:18px;
  border-top:1px solid var(--line);font-size:12.5px;line-height:1.45;color:var(--sec)}
.login-secure svg{flex:none;margin-top:1px;color:var(--accent)}
.login-note{position:relative;margin:18px 0 0;font-size:12px;color:var(--ter);text-align:center}
@media (prefers-reduced-motion:reduce){.login-btn{transition:none}}
@media (max-width:480px){.login-card{padding:30px 22px}.login-mark{width:132px}}

/* ---- buttons / controls ---- */
.linkbtn{color:var(--accent);font-weight:500;font-size:14px;padding:9px 6px;transition:color .18s ease}
.btn{background:var(--accent);color:#fff;border:0;border-radius:11px;padding:10px 17px;font-weight:600;font-size:14px;cursor:pointer;font-family:inherit;letter-spacing:-.01em;
  transition:filter .2s ease,transform .25s cubic-bezier(.34,1.4,.5,1),box-shadow .2s ease}
.head .btn,.head .linkbtn{margin-left:12px}
.btn:hover{transform:translateY(-1px);filter:brightness(1.07);box-shadow:0 6px 18px rgba(94,46,230,.28)}
.btn:active{transform:scale(.97)}
.btn.ghost{background:var(--surface);color:var(--ink);border:1px solid var(--line);box-shadow:none}
.btn.ghost:hover{border-color:var(--accent-soft-2);color:var(--accent);box-shadow:none}
.search{position:relative;width:300px}
.search input{width:100%;padding:10px 13px 10px 36px;border:1px solid var(--line);border-radius:11px;font-family:inherit;font-size:14px;background:var(--surface);letter-spacing:-.01em}
.search input::placeholder{color:var(--icon-muted)}
.search input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 4px var(--accent-soft)}
.search svg{position:absolute;left:12px;top:50%;transform:translateY(-50%);color:var(--icon-muted)}
.filterbtn{display:inline-flex;align-items:center;gap:7px;background:var(--surface);border:1px solid var(--line);border-radius:11px;padding:9px 14px;font-weight:500;color:var(--ink);font-size:13.5px;cursor:pointer;transition:border-color .18s ease,color .18s ease}
.filterbtn:hover{border-color:var(--accent-soft-2);color:var(--accent)}
.chip{display:inline-flex;align-items:center;gap:7px;background:var(--accent-soft);color:var(--accent);padding:7px 12px;border-radius:999px;font-size:12.5px;font-weight:600;transition:transform .18s ease}
.chip:hover{transform:translateY(-1px)}.chip .x{opacity:.55;font-weight:700;cursor:pointer}
.toolbar{display:flex;align-items:center;gap:14px;margin-bottom:18px}
/* The CRM reference adds a labelled selector beside search, status and
   dates. Allow wrapping so each control stays readable at narrower widths. */
.quotes-toolbar{flex-wrap:wrap}
/* The search takes the slack and gets a floor wide enough for its
   placeholder to read as a whole sentence: truncated to "Buscar empresa" it
   understates what the box does (it also matches quote name and number). */
.quotes-toolbar .search{width:auto;flex:1 1 268px;min-width:268px}
/* The two selects are sized by their longest option, which leaves the
   Conteúdo one much wider than it needs to be once the date chip is on the
   row. Truncating the option text there costs nothing — the selected value
   still reads, and the full text is one click away. */
.quotes-toolbar select.filterbtn{max-width:190px;text-overflow:ellipsis}
/* The dates and the two buttons keep their size; the search is the only
   thing that gives. A squashed date field is unreadable, an "Filtr…" button
   is broken, but a narrower search box is merely narrower. */
.quotes-toolbar .daterange,
.quotes-toolbar .btn{flex:0 0 auto}
@media(max-width:1080px){
  /* Past the point where shrinking the search would leave it unusable,
     wrapping is the better failure. */
  .quotes-toolbar{flex-wrap:wrap}
  .quotes-toolbar .search{flex-basis:100%}
}
/* The date pair as a single chip, bordered and sized like `.filterbtn`
   beside it, so a range reads as one filter rather than two loose fields.
   The native inputs keep their own dd/mm/aaaa affordance, so no label is
   needed; `min-width:0` lets them shrink with the chip instead of forcing
   the toolbar wider than the panel. */
.daterange{display:inline-flex;align-items:center;gap:4px;background:var(--surface);
  border:1px solid var(--line);border-radius:11px;padding:8px 11px;
  transition:border-color .18s ease}
.daterange:focus-within{border-color:var(--accent);box-shadow:0 0 0 4px var(--accent-soft)}
.daterange input{min-width:0;width:122px;border:0;background:transparent;padding:0;
  font-family:inherit;font-size:13.5px;color:var(--ink)}
.daterange input:focus{outline:none}
/* An empty date input renders its placeholder in the same ink as a filled
   one, so an unset range would read as a set one. */
.daterange input:not(:valid){color:var(--icon-muted)}
.daterange-sep{color:var(--icon-muted);font-size:13px}

/* segmented control */
.seg{display:flex;background:#EDEDF0;border-radius:10px;padding:2px;gap:2px;position:relative}
.seg a{padding:7px 15px;font-weight:500;font-size:13px;color:var(--sec);border-radius:8px;letter-spacing:-.01em;position:relative;z-index:1;transition:color .2s ease}
.seg a.on{color:var(--ink);font-weight:600}
.seg-ind{position:absolute;top:2px;height:calc(100% - 4px);left:0;width:0;background:#fff;border-radius:8px;z-index:0;
  box-shadow:0 1px 3px rgba(0,0,0,.10),0 1px 1px rgba(0,0,0,.04);
  transition:transform .42s cubic-bezier(.34,1.45,.5,1),width .42s cubic-bezier(.34,1.45,.5,1)}

/* KPI head: the range label sits under the title and CRM/Motor tabs sit right.
   The CRM reference sits immediately left of the tabs; periods have their own row.
   Both control rows reserve their height. The custom date form stays beside
   the period strip; on narrow screens they scroll sideways rather than wrapping.
   The sliding indicator is positioned
   along one axis and a second row would leave it pointing at the wrong pill.
   Layout rules are scoped so no other page's .head or .seg moves. */
.head-kpis{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,900px);grid-template-rows:42px 42px;min-height:136px;margin-bottom:8px;align-items:start;align-content:start;column-gap:24px;row-gap:16px}
.head-kpis .head-title{grid-column:1;grid-row:1 / span 2;min-width:0}
.head-kpis .head-title .exe-meta{margin:0;line-height:1.45}
.head-kpis .kpis-all-dates{flex:0 0 auto;line-height:normal;text-decoration:none;white-space:nowrap}
.head-kpis .kpis-all-dates.on{box-shadow:0 0 0 2px var(--surface),0 0 0 4px var(--accent-soft-2)}
.head-kpis .kpis-all-dates:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.quote-action-row .all-dates-button{flex:0 0 auto;line-height:normal;text-decoration:none;white-space:nowrap}
.quote-action-row .all-dates-button.on{box-shadow:0 0 0 2px var(--surface),0 0 0 4px var(--accent-soft-2)}
.quote-action-row .all-dates-button:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.kpis-head-controls{grid-column:2;display:flex;flex-wrap:nowrap;align-items:center;justify-content:flex-end;gap:13px;min-height:42px;overflow-x:auto}
.head-kpis .quotes-subtabs{margin:0;flex:0 0 auto;width:max-content}
.kpis-filters{grid-column:2;display:flex;flex-wrap:nowrap;align-items:center;justify-content:flex-end;gap:12px;margin:0;min-height:42px;overflow-x:auto}
.kpis-filters .range-row{flex:0 0 auto;flex-wrap:nowrap;gap:8px;margin:0}
.kpis-filters .range-field input{width:130px;min-width:0;padding-inline:7px}
.kpis-filters .seg-periodo{flex:0 0 auto}
.kpis-filters .seg-periodo a{padding-inline:12px}
.kpis-head-controls,.kpis-filters{scrollbar-width:none;justify-content:safe flex-end}
.kpis-head-controls::-webkit-scrollbar,.kpis-filters::-webkit-scrollbar{display:none}
.head-kpis .crm-reference-form{align-items:center;flex-wrap:nowrap;flex:0 0 auto;margin:0}
.crm-reference-form{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 14px 4px 0}
.head-title{display:flex;flex-direction:column;gap:5px}
.head-title .sub{margin-bottom:0}
.seg-periodo{overflow-x:auto;max-width:100%;scrollbar-width:none}
.seg-periodo::-webkit-scrollbar{display:none}
.seg-periodo a{white-space:nowrap}
@media(max-width:1200px){
  .head-kpis{grid-template-columns:minmax(0,1fr);grid-template-rows:136px 42px 42px}
  .head-kpis .head-title{grid-row:auto}
  .kpis-head-controls,.kpis-filters{grid-column:1}
  .kpis-head-controls,.kpis-filters{justify-content:flex-start}
}
@media(max-width:480px){
  .head-kpis{grid-template-rows:144px 42px 42px}
}
/* Renovações and Cotações both reuse the KPI period control, but on the KPI
   page the row is anchored by the page title beside it. On these two the
   title lives a row above, so the strip needs its own left-hand label or it
   reads as floating in an empty band. Named for the control, not for either
   page: two pages render it, so a `renewal-` prefix would have the Cotações
   header styled by rules named after a tab it has nothing to do with. */
.window-head-text{display:flex;flex-direction:column;gap:2px}
.window-head-label{color:var(--ter);font-size:11.5px;font-weight:700;
  letter-spacing:.04em;text-transform:uppercase}
.window-head-range{color:var(--ink);font-size:14px;font-weight:600}
/* Tighter top margin on Renovações: its label row and the sub-tabs above it
   belong together. */
.renewal-horizon{margin-top:-14px;margin-bottom:22px}
/* Cotações sits between the distribution bar and the toolbar, both of which
   bring their own spacing, so it only needs to match the toolbar's gap. */
.quotes-window{margin-bottom:18px}

/* KPI custom range: the date form that "Personalizado" opens. It is inserted
   into a head that was already on screen, so it slides out of the pill strip
   instead of blinking into existence. The fields arrive just behind the row
   itself, which is what makes it read as one control opening rather than
   three elements landing together. */
@keyframes rangeIn{from{opacity:0;transform:translateX(14px)}
  to{opacity:1;transform:none}}
.range-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  margin:0 14px 4px 0;
  animation:rangeIn .34s cubic-bezier(.22,1,.36,1) both}
.crm-reference-form,.range-row>*,.crm-reference-form>*{animation:rangeIn .34s cubic-bezier(.22,1,.36,1) both}
.range-row>*:nth-child(1),.crm-reference-form>*:nth-child(1){animation-delay:.04s}
.range-row>*:nth-child(2),.crm-reference-form>*:nth-child(2){animation-delay:.08s}
.range-row>*:nth-child(3),.crm-reference-form>*:nth-child(3){animation-delay:.12s}
/* Leaving is the same motion run backwards, and faster: an exit the eye has
   to wait for is an exit that feels stuck. app.js adds the class and holds
   the swap back for exactly this long before replacing the markup. */
@keyframes rangeOut{from{opacity:1;transform:none}
  to{opacity:0;transform:translateX(14px)}}
.range-row.range-leaving,.crm-reference-form.range-leaving{animation:rangeOut .18s ease-in both}
.range-row.range-leaving>*,.crm-reference-form.range-leaving>*{animation:none}
form.range-stable:not(.range-leaving),form.range-stable:not(.range-leaving)>*{animation:none}
@media(prefers-reduced-motion:reduce){
  .range-row,.range-row>*,.range-row.range-leaving,.crm-reference-form,.crm-reference-form>*,.crm-reference-form.range-leaving{animation:none}
}
.range-field{display:flex;align-items:center;gap:8px;
  font-size:13px;font-weight:500;color:var(--sec)}
.range-field input{font-family:inherit;font-size:13px;color:var(--ink);
  background:var(--surface);border:1px solid var(--line);border-radius:9px;
  padding:7px 10px;letter-spacing:-.01em}
.range-field input:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px var(--accent-soft)}
.range-apply{background:var(--accent);color:#fff;border:0;border-radius:9px;
  padding:8px 15px;font-family:inherit;font-weight:600;font-size:13px;
  letter-spacing:-.01em;cursor:pointer;transition:filter .2s ease}
.range-apply:hover{filter:brightness(1.07)}
.range-apply:active{transform:scale(.97)}
/* Says which window is on screen when the typed one could not be used. */
.range-warn{margin:-18px 0 26px;padding:9px 13px;border-radius:10px;
  background:var(--warn-bg);color:var(--warn);font-size:12.5px;font-weight:500;
  animation:fadeUp .3s cubic-bezier(.22,1,.36,1) .1s both}
@media(prefers-reduced-motion:reduce){.range-warn{animation:none}}

/* switcher fetch-swap: dims the swapped region while its request is in flight */
.swap-loading{opacity:.55;pointer-events:none;transition:opacity .15s ease}
/* Tabs keep their own header and geometry while only the body is loading. */
[data-swap-content]{position:relative}
.tab-waiting > :not(.head):not([data-tab-loading]){visibility:hidden;pointer-events:none}
[data-tab-loading]{position:absolute;left:0;right:0;bottom:0;overflow:hidden;pointer-events:none;animation:tabLoadingIn .14s ease-out both}
.tab-skeleton-band{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:24px;margin-bottom:26px}
.tab-skeleton-stat{height:68px}
.tab-skeleton-toolbar{height:42px;margin-bottom:20px}
.tab-skeleton-row{height:54px;margin-bottom:10px}
.tab-skeleton-card{height:230px}
.tab-skeleton-label{width:160px;height:16px;margin:22px 0 16px}
.tab-skeleton-rule{height:100px;margin-bottom:14px}
.tab-error{display:flex;align-items:center;gap:16px;padding:14px 18px;margin-bottom:18px;background:var(--warn-bg);border-radius:10px;font-size:13px}
@keyframes tabLoadingIn{from{opacity:.35}to{opacity:1}}
@keyframes tabContentIn{from{opacity:.4;transform:translateY(3px)}to{opacity:1;transform:none}}
/* One body transition, not an ancestor fade multiplied by a 550ms panel fade. */
[data-swap-content].swap-tab :is(.panel,.summary,.toolbar,.banner,.reveal,.alert,.tile,.kpi,tbody tr.clickable){animation:none!important;opacity:1}
[data-swap-content].swap-tab > :not(.head):not([data-tab-loading]){animation:tabContentIn .32s cubic-bezier(.22,1,.36,1) both!important}
/* The status distribution is already sized by the response. Its page-load
   reveal hides it for 500ms after the surrounding tab has arrived. Let the
   body transition carry the complete bar, with no second entrance. */
[data-swap-content].swap-tab .distbar{animation:none;clip-path:none}
@media(prefers-reduced-motion:reduce){
  [data-tab-loading],[data-swap-content].swap-tab > :not(.head):not([data-tab-loading]){animation:none!important}
  [data-tab-loading] .skel::after{animation:none}
}
/* A swapped region is not a page load, but it is still new content, so it
   should arrive rather than appear. Durations are left exactly as designed —
   overriding them is what made a switch feel snappy instead of smooth. What
   goes is the wait before the containers arrive: on load, a panel is blank
   for 240ms before it fades, which is fine after a navigation and reads as
   a flicker after a 40ms fetch. The containers now start immediately and
   fade over their own unchanged .55s, and everything inside them — bars,
   lines, donuts, sparklines — keeps its own timing untouched, so the motion
   within a card is identical to a fresh load. */
[data-swap-content].swapped :is(.summary,.toolbar,.panel,.banner,.reveal,
  .alert,.tile,.kpi,tbody tr.clickable){animation-delay:0s!important}
/* The head is the exception: the title and the tab bar are the same before
   and after, so animating them announces a reload that did not happen. */
[data-swap-content].swapped .head{opacity:1!important;animation:none!important}
/* Moving between SCREENS through the menu. The per-element entrance is the
   page-LOAD animation: panels fading up from nothing on a stagger, `.head`
   at .02s, `.summary` at .10s, `.toolbar` at .18s, `.panel` at .24s. Playing
   that over a screen that is already in place is what reads as the page
   loading a second time, so the elements arrive already visible...  */
[data-swap-content].swap-screen :is(.head,.summary,.toolbar,.panel,
  .banner,.reveal,.alert,.tile,.kpi,.quotes-tab-content){
  opacity:1!important;animation:none!important}
/* ...and the REGION carries the motion instead, as one piece. Suppressing
   the stagger without this left the swap a hard cut with no motion at all.
   It starts at .35 rather than 0 on purpose: from 0 the screen goes blank
   first, which is the very flash both halves of this exist to remove. Short
   enough (.18s) that it never delays reading, and it cannot be mistaken for
   a second load because nothing ever disappears. */
[data-swap-content].swap-in{animation:swapScreenIn .18s ease-out both}
@keyframes swapScreenIn{from{opacity:.35;transform:translateY(4px)}
  to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){
  [data-swap-content].swap-in{animation:none}}

/* ---- summary / distribution bar ---- */
.summary{margin-bottom:22px}
.summary .n{font-size:44px;font-weight:700;letter-spacing:-.035em;line-height:1}
.summary .cap{color:var(--ter);font-size:14px;font-weight:500;margin:9px 0 0}
.distbar{display:flex;height:10px;border-radius:999px;overflow:hidden;background:var(--neu-bg);width:100%;box-shadow:inset 0 0 0 1px rgba(20,20,30,.04)}
.distbar span{display:block;height:100%;transition:filter .2s ease}
.distbar:hover span{filter:saturate(1.15)}
.legend{display:flex;gap:28px;margin-top:18px;flex-wrap:wrap}
.legend .it{display:flex;align-items:center;gap:9px;font-size:13.5px;color:var(--sec);font-weight:500}
.legend .it .dot{width:8px;height:8px;border-radius:50%}
.legend .it b{color:var(--ink);font-weight:600}

/* ---- panel / table ---- */
.panel{background:var(--surface);border-radius:var(--r);box-shadow:var(--shadow);overflow:hidden}
.panel.pad{padding:22px 24px}
table{width:100%;border-collapse:collapse}
thead th{text-align:left;padding:14px 22px;font-size:12px;font-weight:600;color:var(--ter);border-bottom:1px solid var(--line-2)}
tbody td{padding:16px 22px;border-bottom:1px solid var(--line-2);vertical-align:middle}
tbody tr:last-child td{border-bottom:0}
tbody tr.clickable{cursor:pointer;transition:background .15s ease}
tbody tr.clickable:hover{background:#FAFAFC}
.fname{font-weight:600;font-size:14.5px;letter-spacing:-.01em}
.sub-cnpj{color:var(--ter);font-size:12.5px;margin-top:3px;font-weight:500;letter-spacing:0}
.type,.when{color:var(--sec);font-size:13.5px}
.motivo{color:var(--ter);font-size:12px;margin-top:6px;font-weight:500;max-width:240px}
.valor{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.flag{display:inline-flex;vertical-align:-1px;margin-right:7px;color:var(--bad)}
tbody tr.risk td:first-child{box-shadow:inset 3px 0 0 var(--bad)}
.chev{color:var(--icon-muted);font-size:19px;text-align:right;width:26px;transition:color .18s ease,transform .18s ease}
tbody tr.clickable:hover .chev{color:var(--accent);transform:translateX(3px)}
.pag{display:flex;align-items:center;gap:20px;padding:16px 22px;color:var(--sec);font-size:13.5px;border-top:1px solid var(--line-2)}
.pag a{color:var(--accent);font-weight:500}.pag a.off{color:var(--ter)}

/* ---- Cotações: Renovações ------------------------------------------- */
.quotes-head{flex-wrap:wrap}
.quotes-head .quotes-subtabs{margin:0}
.quotes-subtabs{display:flex;gap:6px;margin:0 0 18px;padding:4px;background:var(--neu-bg);border-radius:11px;width:max-content;max-width:100%}
.quotes-subtabs a{padding:7px 12px;border-radius:8px;color:var(--sec);font-size:13px;font-weight:600;white-space:nowrap}
.quotes-subtabs .seg-ind{top:4px;height:calc(100% - 8px)}
.quotes-subtabs a.on{background:transparent;color:var(--ink);box-shadow:none}
.quote-submit{display:flex;align-items:center;gap:14px;margin:0 0 18px}
.quote-action-row{display:flex;align-items:center;gap:10px;margin-bottom:18px;flex-wrap:wrap}
.quote-action-row .quote-submit{flex:1;min-width:320px;margin:0}
.quote-action-row .quote-submit-controls{max-width:none;min-width:0}
.quote-action-row .range-field{flex:none;white-space:nowrap}
.quote-action-row .filterbtn{max-width:210px;text-overflow:ellipsis}
@media(max-width:640px){.quote-action-row .quote-submit{flex-basis:100%;min-width:0}.quote-action-row .range-field{flex-wrap:wrap;white-space:normal}}
.quote-submit label{flex:none;color:var(--sec);font-size:13px;font-weight:600}
.quote-submit-controls{display:flex;align-items:center;gap:10px;flex:1;max-width:720px}
.quote-submit input{min-width:0;flex:1;padding:10px 13px;border:1px solid var(--line);
  border-radius:8px;background:var(--surface);color:var(--ink);font:inherit;
  font-size:14px;letter-spacing:0}
.quote-submit input:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 4px var(--accent-soft)}
@media(max-width:640px){.quote-submit{align-items:stretch;flex-direction:column;gap:7px}
  .quote-submit-controls{max-width:none}.quote-submit-controls .btn{flex:none}}
[data-swap-content].swapped .quotes-tab-content,.kpis-tab-view.swapped > :not(.head-kpis){animation:fadeUp .18s ease-out both}
@media(prefers-reduced-motion:reduce){[data-swap-content].swapped .quotes-tab-content,.kpis-tab-view.swapped > :not(.head-kpis){animation:none}.quotes-subtabs .seg-ind{transition:none}}
@media(max-width:640px){.quotes-head{align-items:flex-start}.quotes-head .sp{display:none}.quotes-head .quotes-subtabs{flex-basis:100%}}
.renewal-period{margin:0 0 26px}
.renewal-period-head{display:flex;align-items:center;gap:16px;margin:0 0 10px}
.renewal-period-head h2{margin:0;font-size:16px;letter-spacing:-.015em}
.renewal-kpis{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-left:auto;color:var(--sec);font-size:12.5px;font-weight:600}
.renewal-kpis span{padding-left:14px;border-left:1px solid var(--line)}
.renewal-kpis span:first-child{padding-left:0;border-left:0}
.renewal-table-wrap{overflow-x:auto}
.renewal-table-wrap table{min-width:900px}
.renewal-contact{display:flex;flex-wrap:wrap;align-items:baseline;gap:3px 9px;min-width:180px;color:var(--sec);font-size:12.5px}
.renewal-contact .fname{width:100%;color:var(--ink)}
.renewal-contact a{color:var(--accent);overflow-wrap:anywhere}
.renewal-contact-source{color:var(--ter);font-size:11.5px;font-weight:600}
.renewal-conflict{display:inline-block;margin-top:5px;padding:2px 7px;border-radius:999px;background:var(--warn-bg);color:var(--warn);font-size:10.5px;font-weight:700}
.renewal-period.no-forecast{opacity:.84}
.renewal-period.no-forecast:hover{opacity:1}
/* Sections outside the chosen window ("Vencem depois da janela", "Já
   encerrados"). Their contracts are fully calculated, so they are not dimmed
   the way the no-forecast list is; they are set apart by a rule above the
   heading, which says "past the edge of what you asked for" without saying
   "less certain". */
.renewal-outside{padding-top:22px;border-top:1px dashed var(--line)}
.renewal-outside .renewal-period-head h2{color:var(--sec)}
/* The month heading names itself; "Este mês" is a qualifier in front of it,
   set quieter so the calendar month stays the thing being read. */
.renewal-month-of{margin-left:9px;color:var(--ter);font-size:12.5px;
  font-weight:600;letter-spacing:0;text-transform:lowercase}
/* Contrato column. It held four stacked provenance lines and wrapped to ten
   rows at table width; the provenance now lives on the cell's title, leaving
   the type name and one meta line. min-width stops the type name shredding
   into one word per line. */
.renewal-contract{min-width:190px}
/* Seven columns of real content overran the panel and clipped the Situação
   pill off the right edge. The status text is the longest string in the row
   ("Renova automaticamente"), so it is the one allowed to wrap. */
/* The status label is short now ("Renova" / "Encerra", full wording on the
   chip's title), so it no longer has to wrap to fit its column. */
.renewal-table .st{white-space:nowrap}
/* The chevron was clipping against the panel edge, which left a 26px
   target partly unclickable. The row itself now navigates, so this is the
   visible affordance and the keyboard target rather than the only way in. */
.renewal-table .chev{width:34px;padding-right:4px}
.renewal-table .chev a{display:inline-block;padding:2px 4px}
/* Why a row has no date, in the column where its date would have been. */
.renewal-missing{display:inline-block;padding:3px 9px;border-radius:999px;
  background:var(--warn-bg);color:var(--warn);font-size:11px;font-weight:700;
  white-space:nowrap;cursor:help}
.renewal-type{color:var(--ink);line-height:1.3}
.renewal-basis{margin-top:3px;color:var(--ter);font-size:11.5px;font-weight:600;
  white-space:nowrap;cursor:help}
.renewal-basis-tag{display:inline-block;margin-top:5px;padding:2px 7px;
  border-radius:999px;background:var(--sunken);color:var(--sec);font-size:10.5px;
  font-weight:700;white-space:nowrap}
/* Year/month toggles. A row of small targets rather than a select: the counts
   are the point, and an analyst picks "março e abril" by seeing where the
   contracts are. Years read heavier than their months so the two granularities
   are distinguishable at a glance. */
.renewal-chips{display:flex;flex-wrap:wrap;gap:7px;margin:0 0 24px}
.rc{display:inline-flex;align-items:center;gap:7px;padding:6px 11px;
  border:1px solid var(--line);border-radius:999px;background:var(--surface);
  color:var(--sec);font-size:12.5px;font-weight:600;text-transform:capitalize;
  transition:border-color .18s ease,color .18s ease,background .18s ease}
.rc:hover{border-color:var(--accent);color:var(--accent)}
.rc.on{background:var(--accent-soft);border-color:var(--accent-soft-2);
  color:var(--accent)}
.rc-year{font-weight:700;letter-spacing:.01em;text-transform:none;
  background:var(--sunken)}
.rc-year.on{background:var(--accent-soft)}
.rc-n{font-variant-numeric:tabular-nums;color:var(--ter);font-size:11px;
  font-weight:700}
.rc.on .rc-n{color:var(--accent)}
/* The year owns its months: one heading, then the month sections under it.
   Without this a twelve-month window repeats "de 2027" twelve times. */
.renewal-year{margin:0 0 30px}
.renewal-year-head{display:flex;align-items:center;gap:16px;margin:0 0 14px;
  padding-bottom:9px;border-bottom:1px solid var(--line)}
.renewal-year-head h2{margin:0;font-size:21px;font-weight:700;
  letter-spacing:-.025em}
.renewal-year .renewal-period{margin:0 0 22px}
.renewal-year .renewal-period-head h3{margin:0;font-size:15px;
  letter-spacing:-.015em;text-transform:capitalize}
/* The empty state is followed by real sections ("Vencem depois da janela"),
   so it needs the same bottom margin a year group carries. Without it the card
   sits against the next heading and reads as part of it. */
.renewal-empty{padding:34px 22px;margin:0 0 30px;text-align:center}
.renewal-empty p{margin:0;color:var(--sec);font-size:14px}
.renewal-empty-hint{margin-top:7px !important;color:var(--ter) !important;
  font-size:12.5px !important}
@media(max-width:720px){
  .quotes-subtabs{width:100%;overflow-x:auto}
  .renewal-period-head{display:block}
  .renewal-kpis{margin:8px 0 0}
  .renewal-contact{align-items:flex-start;flex-direction:column;gap:2px}
  .renewal-contact .fname{width:auto}
}

/* ---- Cotações: Produtos --------------------------------------------- */
.products-table-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
.products-table{min-width:850px}
.products-summary{min-width:230px;color:var(--sec);font-size:13px}
.products-summary .sub-cnpj{max-width:310px;overflow-wrap:anywhere}
.products-missing{display:inline-flex;padding:4px 8px;border-radius:999px;
  background:var(--warn-bg);color:var(--warn);font-size:11.5px;font-weight:700}
.products-blocked{margin-top:5px;color:var(--bad);font-size:11.5px;font-weight:700}
.products-action{width:1%;white-space:nowrap;text-align:right}
.products-toggle{display:inline-flex;align-items:center;gap:7px;padding:6px 9px;border:1px solid var(--line);
  border-radius:8px;background:var(--surface);color:var(--sec);font:inherit;font-size:12px;font-weight:700;cursor:pointer}
.products-toggle:hover{border-color:var(--accent);color:var(--accent)}
.products-toggle:focus-visible{outline:none;box-shadow:0 0 0 3px var(--accent-soft)}
.products-chevron{display:inline-block;color:var(--icon-muted);font-size:15px;line-height:1;transition:transform .18s ease}
.products-chevron.is-expanded{transform:rotate(180deg)}
.products-details>td{padding:0 22px 18px;background:var(--sunken);vertical-align:top}
.products-details-table{min-width:760px;margin-top:14px;background:var(--surface)}
.products-details-table thead th,.products-details-table tbody td{padding:10px 12px;font-size:12px}
.products-details-table tbody td{color:var(--sec)}
.products-details .products-missing{margin-top:14px}
@media(max-width:720px){
  .products-table{min-width:760px}
  .products-summary{min-width:210px}
  .products-details>td{padding:0 14px 14px}
  .products-details-table{min-width:700px}
}

/* ---- status pill ---- */
.st{display:inline-flex;align-items:center;gap:7px;padding:5px 11px;border-radius:999px;font-size:12.5px;font-weight:600;letter-spacing:-.01em}
.st .dot{width:6px;height:6px;border-radius:50%}
.st.ok{background:var(--ok-bg);color:var(--ok)} .st.ok .dot{background:var(--ok-ico)}
.st.warn{background:var(--warn-bg);color:var(--warn)} .st.warn .dot{background:var(--warn-ico)}
.st.bad{background:var(--bad-bg);color:var(--bad)} .st.bad .dot{background:var(--bad-ico)}
.st.neu{background:var(--neu-bg);color:var(--neu)} .st.neu .dot{background:var(--neu-ico)}
.st.ressalva{background:var(--ressalva-bg);color:var(--ressalva)} .st.ressalva .dot{background:var(--ressalva-ico)}
.st.bloqueio{background:var(--bloqueio-bg);color:var(--bloqueio)} .st.bloqueio .dot{background:var(--bloqueio-ico)}

/* ---- KPI band (single panel, internal dividers) ---- */
.kpis{display:flex}
.kpi{flex:1;padding:21px 24px;border-left:1px solid var(--line-2);display:flex;flex-direction:column}
.kpi:first-child{border-left:0}
.kpi .l{color:var(--sec);font-size:13px;font-weight:500}
.kpi .top{display:flex;align-items:flex-end;justify-content:space-between;gap:10px;margin-top:9px}
.kpi .v{font-size:29px;font-weight:700;letter-spacing:-.03em;line-height:.95}
.kpi .d{display:inline-flex;align-items:center;gap:4px;font-size:12.5px;font-weight:600;margin-top:9px}
.kpi .d.up{color:var(--ok)} .kpi .d.down{color:var(--bad)} .kpi .d.flat{color:var(--ter)}
.kpi .sub{color:var(--ter);font-size:11.5px;font-weight:500;margin-top:7px;line-height:1.35}
/* per-KPI sparkline */
.spark{width:72px;height:26px;flex:none;overflow:visible;display:block}
.spark .a{opacity:0;animation:fadeUp .6s ease .75s forwards}
.spark .l{fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:1;stroke-dashoffset:1;animation:draw 1.25s cubic-bezier(.22,1,.36,1) .45s forwards}
.spark .pt{opacity:0;animation:fadeUp .4s ease 1.35s forwards}
.spark.up .l{stroke:var(--ok)} .spark.up .a{fill:rgba(31,164,99,.10)} .spark.up .pt{fill:var(--ok)}
.spark.down .l{stroke:var(--accent)} .spark.down .a{fill:rgba(94,46,230,.10)} .spark.down .pt{fill:var(--accent)}

/* ---- bar chart (execuções por dia) ---- */
.chart{display:flex;align-items:flex-end;gap:6px;height:200px;padding-top:8px}
.chart .col{flex:1;display:flex;flex-direction:column-reverse;height:100%;justify-content:flex-start;gap:2px;
  transform:scaleY(0);transform-origin:bottom;animation:growY .8s cubic-bezier(.22,1,.36,1) forwards}
.chart .col .seg-bar{width:100%;border-radius:3px}
.chart .col .seg-bar.approved{background:var(--ok-ico)}
.chart .col .seg-bar.pending{background:var(--warn-ico)}
.chart .col .seg-bar.rejected{background:var(--bad-ico)}
.chart .col .seg-bar.other{background:var(--neu-ico)}
.legend .it .dot.approved{background:var(--ok-ico)}
.legend .it .dot.pending{background:var(--warn-ico)}
.legend .it .dot.rejected{background:var(--bad-ico)}
.legend .it .dot.other{background:var(--neu-ico)}
.chart-x{display:flex;gap:6px;margin-top:10px}
/* min-width:0 is load-bearing: a flex item defaults to min-width:auto, so a
   span holding a date would refuse to shrink below its text while the empty
   spans collapsed, and the strip stopped lining up with the columns above it.
   The dates now sit on the same track as the bars and overflow the empty
   neighbours, which is why they must not wrap. */
.chart-x span{flex:1;min-width:0;text-align:center;font-size:11px;color:var(--ter);font-weight:500;white-space:nowrap;overflow:visible}

/* ---- top failing rules (horizontal bars) ---- */
.rule-row{display:grid;grid-template-columns:1fr 46px;align-items:center;gap:14px;padding:11px 0;border-bottom:1px solid var(--line-2)}
.rule-row:last-child{border-bottom:0}
.rule-row .name{font-size:13.5px;font-weight:600}
.rule-row .track{height:10px;border-radius:999px;background:var(--neu-bg);margin-top:8px;overflow:hidden}
.rule-row .fill{height:100%;background:var(--bad);border-radius:999px;width:0;animation:growX .9s cubic-bezier(.22,1,.36,1) forwards}
.rule-row .cnt{text-align:right;font-weight:700;font-variant-numeric:tabular-nums;font-size:15px}

/* ---- alerts ---- */
.alert{display:flex;gap:14px;padding:18px 22px;border-bottom:1px solid var(--line-2);align-items:flex-start;transition:background .15s ease}
.alert:last-child{border-bottom:0}
.alert:hover{background:#FAFAFC}
.alert.unread{box-shadow:inset 3px 0 0 var(--accent)}
.alert .ic{width:22px;display:grid;place-items:center;flex:none;margin-top:1px}
.alert .ic svg{width:20px;height:20px}
.alert .ic.crit{color:var(--bad)}
.alert .ic.warn{color:var(--warn)}
.alert .ic.info{color:var(--accent)}
.alert .body{flex:1;min-width:0}
.alert .t{font-weight:600;font-size:14.5px;letter-spacing:-.01em}
.alert.unread .t::after{content:"";display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--accent);margin-left:8px;vertical-align:middle}
.alert .m{color:var(--sec);font-size:13px;margin-top:4px}
.alert .meta{color:var(--ter);font-size:12.5px;margin-top:7px;font-weight:500}
.alert .when{color:var(--ter);font-size:12.5px;font-weight:500;white-space:nowrap;margin-left:8px}
.ack{background:none;border:1px solid var(--line);color:var(--sec);border-radius:9px;padding:7px 12px;font-size:12.5px;font-weight:600;cursor:pointer;font-family:inherit;white-space:nowrap;transition:border-color .18s,color .18s}
.ack:hover{border-color:var(--accent-soft-2);color:var(--accent)}

/* ---- home: value-at-risk hero + mini stats ---- */
.hero-risk .n{font-size:46px;font-weight:700;letter-spacing:-.035em;line-height:1}
.hero-risk .cap{color:var(--ter);font-size:14px;font-weight:500;margin:10px 0 0}
.atmini{display:flex;gap:26px;margin-top:18px;flex-wrap:wrap}
.atmini .it{font-size:13.5px;color:var(--sec);font-weight:500;display:flex;gap:8px;align-items:center}
.atmini .it .dot{width:8px;height:8px;border-radius:50%}
.atmini .it b{color:var(--ink);font-weight:700}
/* EXPERIMENT (revert this commit to restore): the grey title bar is gone from
   every card head across the dashboard, leaving the rule alone to separate the
   title from the body. Kept in one commit so the whole look flips back at once. */
.panel-head{display:flex;align-items:center;gap:10px;padding:16px 22px;
  border-bottom:1px solid var(--line-2)}
/* Body of a panel that has a head bar. `.panel.pad` cannot serve: it pads the
   card itself, which would inset the bar too. */
.panel-body{padding:22px 24px;flex:1}
.panel-head .ttl{font-size:14px;font-weight:700;letter-spacing:-.01em}
.panel-head .cnt{background:var(--bad-bg);color:var(--bad);font-size:12px;font-weight:700;padding:1px 9px;border-radius:999px}
.panel-head a{margin-left:auto;color:var(--accent);font-weight:500;font-size:13px}
/* Muted qualifier beside a panel title, for what the panel's own figure
   cannot say: a ring drawn from a partial sweep is green either way. */
.panel-head .qual{margin-left:auto;color:var(--sec);font-size:12.5px;font-weight:500}
/* A search form living in a panel head: pushed right like the head's other
   trailing elements, and without the standalone toolbar's bottom margin,
   which would otherwise shove the head's own border down. */
/* A search form living in a panel head. Placement comes from a `.sp` spacer
   in the markup, not from an auto margin here: `.panel-head a` already sets
   margin-left:auto for trailing links, and the Limpar link sits INSIDE this
   form, so an auto margin on the form competes with a rule doing the same job
   one level down. Only the standalone toolbar's bottom margin is cancelled,
   which would otherwise shove the head's border away from its text. */
.panel-head .toolbar{margin-bottom:0}
/* Undo `.panel-head a{margin-left:auto;color:var(--accent);font-weight:500;
   font-size:13px}` for the buttons inside that form: that rule exists to push
   a lone trailing link to the far right of a head and to read as a quiet text
   link there, and applied to the "Limpar" `<a class="btn ghost">` it both
   tears Limpar away from Buscar AND repaints it in accent purple at the wrong
   weight and size instead of `.btn.ghost`'s `--ink`/600/14px, so it stops
   matching the "Buscar" button beside it. */
.panel-head .toolbar a{margin-left:0;color:var(--ink);font-weight:600;font-size:14px}
.panel-head .search{width:260px}
.panel-head .search input{padding-left:13px}
/* The screened base's size, stated once under the ring now that the ring's
   centre carries the percentage instead. */
.type-legend .row.tot{color:var(--sec);font-weight:600;margin-bottom:6px;cursor:default}
.type-legend .row.tot:hover{background:transparent}
/* activity feed */
.feed-item{display:flex;align-items:center;gap:13px;padding:13px 0;border-bottom:1px solid var(--line-2);font-size:13.5px}
.feed-item:last-child{border-bottom:0}
.feed-item .tm{color:var(--ter);font-size:12.5px;width:58px;flex:none;font-variant-numeric:tabular-nums}
.feed-item .nm{flex:1;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.statline{display:flex;gap:30px;margin-top:20px;flex-wrap:wrap}
.statline .s .v{font-size:24px;font-weight:700;letter-spacing:-.02em}
.statline .s .l{color:var(--sec);font-size:12.5px;font-weight:500;margin-top:3px}
/* line / area chart */
.linechart svg{display:block;width:100%;height:auto;overflow:visible}
.linechart .area{transform-origin:bottom;transform:scaleY(0);animation:growY 1s cubic-bezier(.22,1,.36,1) .35s forwards}
.linechart .line{fill:none;stroke:var(--accent);stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:1;stroke-dashoffset:1;animation:draw 1.5s cubic-bezier(.22,1,.36,1) .3s forwards}
.linechart .dot{fill:var(--accent);opacity:0;animation:fadeUp .4s ease forwards;animation-delay:1.4s}
.linechart-x{display:flex;justify-content:space-between;margin-top:8px;font-size:11px;color:var(--ter);font-weight:500}
@keyframes draw{to{stroke-dashoffset:0}}

/* ---- bento grid ---- */
.bento{display:grid;grid-template-columns:repeat(4,1fr);grid-auto-rows:152px;gap:18px}
.tile{background:var(--surface);border-radius:var(--r);box-shadow:var(--shadow);padding:22px 24px;overflow:hidden;display:flex;flex-direction:column;min-width:0;position:relative;
  opacity:0;animation:fadeUp .55s cubic-bezier(.22,1,.36,1) forwards}
.tile.flush{padding:0}
.tile .section-label{margin:0 0 14px}
.tile-num{font-size:40px;font-weight:700;letter-spacing:-.03em;line-height:1}
.tile-num.lg{font-size:46px}
.tile-lbl{color:var(--sec);font-size:13px;font-weight:500;margin-top:auto;padding-top:10px}
.tile .d{display:inline-flex;align-items:center;gap:4px;font-size:12.5px;font-weight:600;margin-top:8px}
.tile .d.up{color:var(--ok)}.tile .d.down{color:var(--bad)}
.tile:nth-child(1){animation-delay:.04s}.tile:nth-child(2){animation-delay:.09s}
.tile:nth-child(3){animation-delay:.14s}.tile:nth-child(4){animation-delay:.19s}
.tile:nth-child(5){animation-delay:.24s}.tile:nth-child(6){animation-delay:.29s}
.tile:nth-child(7){animation-delay:.34s}.tile:nth-child(8){animation-delay:.39s}
.tile:nth-child(9){animation-delay:.44s}.tile:nth-child(10){animation-delay:.49s}
.tile.scroll{overflow-y:auto}
@media(max-width:980px){.bento{grid-template-columns:1fr 1fr}.tile{grid-column:auto!important;grid-row:auto!important;min-height:150px}}

/* ---- open stat band (not boxed) ---- */
.stats-open{display:flex;border-top:1px solid var(--line);border-bottom:1px solid var(--line);margin-bottom:30px}
.stats-open .st-item{flex:1;padding:18px 26px;border-left:1px solid var(--line-2)}
.stats-open .st-item:first-child{border-left:0;padding-left:2px}
.stats-open .l{color:var(--sec);font-size:12.5px;font-weight:500}
.stats-open .v{font-size:27px;font-weight:700;letter-spacing:-.025em;margin-top:7px;line-height:1}
.stats-open .d{display:inline-flex;gap:4px;font-size:12.5px;font-weight:600;margin-top:8px}
.stats-open .d.up{color:var(--ok)}.stats-open .d.down{color:var(--bad)}.stats-open .d.flat{color:var(--ter)}
.stats-open .sub{color:var(--ter);font-size:11px;font-weight:500;margin-top:7px;line-height:1.35}

/* ---- skeleton loading ---- */
.skel{position:relative;overflow:hidden;background:#E9E9EE;border-radius:8px}
.skel::after{content:"";position:absolute;inset:0;transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.65),transparent);animation:shimmer 1.3s infinite}
.sk-line{height:14px;border-radius:6px}
@keyframes shimmer{100%{transform:translateX(100%)}}
body.loading #view{display:none}
body:not(.loading) #skeleton{display:none}

/* ---- hero donut (pizza) ---- */
.hero-flex{display:flex;align-items:center;justify-content:space-between;gap:48px;flex-wrap:wrap}
.donut-block{display:flex;align-items:center;gap:28px}
.donut{width:138px;height:138px;flex:none;transform-origin:center;animation:popIn .6s cubic-bezier(.34,1.4,.5,1) .25s both}
@keyframes popIn{from{opacity:0;transform:scale(.85)}to{opacity:1;transform:none}}
.dleg{display:flex;flex-direction:column;gap:13px}
.dleg .it{display:flex;align-items:center;gap:10px;font-size:13.5px;color:var(--sec);font-weight:500}
.dleg .it b{color:var(--ink);font-weight:700;min-width:12px}
.dleg .it .dot{width:9px;height:9px;border-radius:50%}
.resumo-row{display:flex;align-items:center;gap:48px;flex-wrap:wrap}
.resumo-dist{flex:1;min-width:300px}
.resumo-row .statline{margin:0!important;flex:none}
/* waffle / unit chart */
.waffle{display:grid;grid-template-columns:repeat(4,28px);gap:7px;flex:none}
.waffle span{width:28px;height:28px;border-radius:7px;animation:popIn .4s cubic-bezier(.34,1.4,.5,1) both}
.waffle span:nth-child(1){animation-delay:.22s}.waffle span:nth-child(2){animation-delay:.27s}
.waffle span:nth-child(3){animation-delay:.32s}.waffle span:nth-child(4){animation-delay:.37s}
.waffle span:nth-child(5){animation-delay:.42s}.waffle span:nth-child(6){animation-delay:.47s}
.waffle span:nth-child(7){animation-delay:.52s}.waffle span:nth-child(8){animation-delay:.57s}
/* nested mini-cards inside a panel */
/* minmax(0,1fr) rather than 1fr: .mini .v is white-space:nowrap, so a long
   value like "R$ 42.269,30" sets a min-content floor that a plain 1fr track
   cannot go below. That widened the currency column, and aspect-ratio:1 then
   made that card taller than its neighbours. */
.mini-cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;margin-top:20px;align-items:start}
.mini{background:#F3F3F8;border-radius:14px;padding:20px;aspect-ratio:1;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;gap:12px}
.mini .l{color:var(--sec);font-size:13px;font-weight:600;order:-1}
.mini .v{font-size:38px;font-weight:700;letter-spacing:-.03em;line-height:1;white-space:nowrap}
.mini .v.cur{font-size:27px}
/* hero breakdown (clean counts, horizontal; number beside the bullet) */
.hbreak{display:flex;flex-direction:row;gap:38px;flex-wrap:wrap}
.hb{display:flex;flex-direction:row;align-items:center;gap:10px}
.hb .dot{width:9px;height:9px;border-radius:50%;flex:none}
.hb .v{font-size:25px;font-weight:700;letter-spacing:-.02em;line-height:1}
.hb .lab{color:var(--sec);font-size:14px;font-weight:500}
/* A hero break that carries a value under its label and links to the filtered
   Cotações list. .hb lays its children out in a row, so stacking the label
   over the amount needs one column wrapper rather than a second flex child. */
.hb-txt{display:flex;flex-direction:column;gap:3px}
.hb .amt{color:var(--ter);font-size:12.5px;font-weight:600;font-variant-numeric:tabular-nums}
a.hb{color:inherit;text-decoration:none}
a.hb:hover .lab{color:var(--ink)}
/* feed that fills available height */
.feed{flex:1;display:flex;flex-direction:column;justify-content:space-between}
/* donut composition (por tipo de documento) */
.donut-wrap{display:flex;flex-direction:column;align-items:center}
.donut-c{position:relative;width:152px;height:152px;animation:popIn .6s cubic-bezier(.34,1.4,.5,1) .3s both}
.donut-c svg{width:152px;height:152px;transform:rotate(-90deg);display:block}
.donut-c circle{fill:none;stroke-width:15}
.donut-c .ctr{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center}
.donut-c .ctr .n{font-size:32px;font-weight:700;letter-spacing:-.03em;line-height:1}
.donut-c .ctr .t{color:var(--ter);font-size:11px;font-weight:600;margin-top:3px;text-transform:uppercase;letter-spacing:.04em}
.type-legend{display:flex;flex-direction:column;margin-top:20px;width:100%}
.type-legend .row{display:flex;align-items:center;gap:11px;padding:9px 0;border-bottom:1px solid var(--line-2);font-size:13.5px;
  opacity:0;animation:fadeUp .5s cubic-bezier(.22,1,.36,1) forwards}
.type-legend .row:last-child{border-bottom:0}
.type-legend .row:nth-child(1){animation-delay:.45s}.type-legend .row:nth-child(2){animation-delay:.51s}
.type-legend .row:nth-child(3){animation-delay:.57s}.type-legend .row:nth-child(4){animation-delay:.63s}
.type-legend .row:nth-child(5){animation-delay:.69s}.type-legend .row:nth-child(6){animation-delay:.75s}
.type-legend .dot{width:10px;height:10px;border-radius:50%;flex:none}
.type-legend .row.z{cursor:default}
.type-legend .row.z .nm,.type-legend .row.z .ct,.type-legend .row.z .dot{opacity:.5}
.type-legend .row.z:hover{background:transparent}
.type-legend .nm{flex:1;font-weight:500}
.type-legend .ct{font-weight:700;font-variant-numeric:tabular-nums}
.type-legend .pc{color:var(--ter);font-size:12px;width:40px;text-align:right;font-variant-numeric:tabular-nums}
/* compliance data-source rows */
/* The sources list is taller than the donut beside it, so it would set the
   row's height and leave the triagens card padded out with white. Absolutely
   positioning the list takes it out of the height calculation: the row is
   sized by the donut card, and the list scrolls inside whatever that leaves.
   The panel must be a flex column for .body-scroll's flex:1 to mean anything. */
.grid-2>.panel{display:flex;flex-direction:column}
.body-scroll{position:relative;flex:1;min-height:220px;padding:0}
/* overflow-y:scroll, not auto: macOS hides overlay scrollbars until you
   already scrolled, which is exactly when the affordance is no longer needed.
   Styling the track keeps a visible rail, so the card says up front that it
   holds more than it shows. */
.body-scroll>.inner{position:absolute;inset:0;overflow-y:scroll;padding:4px 24px 12px;
  scrollbar-width:thin;scrollbar-color:#D6D6DE transparent}
.body-scroll>.inner::-webkit-scrollbar{width:10px}
.body-scroll>.inner::-webkit-scrollbar-track{background:var(--neu-bg);border-radius:999px;
  margin:6px 0}
.body-scroll>.inner::-webkit-scrollbar-thumb{background:#C9C9D4;border-radius:999px;
  border:3px solid transparent;background-clip:content-box}
.body-scroll>.inner::-webkit-scrollbar-thumb:hover{background:var(--ter);
  border:3px solid transparent;background-clip:content-box}
/* A fade under the last visible row: the rail says "scrollable", this says
   "the list continues here". pointer-events:none so it never eats a click. */
.body-scroll::after{content:"";position:absolute;left:0;right:12px;bottom:0;height:26px;
  background:linear-gradient(to top,var(--surface),rgba(255,255,255,0));pointer-events:none}
.source-row{display:flex;align-items:flex-start;gap:14px;padding:16px 0;border-bottom:1px solid var(--line-2)}
.source-row:last-child{border-bottom:0}
.source-row .info{flex:1;min-width:0}
.source-row .nm{font-weight:600;font-size:13.5px}
.source-row .meta{color:var(--ter);font-size:12px;margin-top:4px}

/* ---- detail page ---- */
.dhead{display:flex;align-items:flex-start;gap:14px;margin-bottom:26px}
.dhead h1{margin:0;font-size:26px;font-weight:700;letter-spacing:-.025em}
.dhead .meta-cnpj{color:var(--ter);font-size:14px;margin-top:5px;font-weight:500}
.banner{border-radius:var(--r);box-shadow:var(--shadow);background:var(--surface);padding:22px 24px;margin-bottom:26px;position:relative;overflow:hidden}
.banner::before{content:"";position:absolute;left:0;top:0;bottom:0;width:4px}
.banner.bad::before{background:var(--bad)} .banner.ok::before{background:var(--ok)} .banner.warn::before{background:var(--warn)}
.banner .verdict{display:flex;align-items:center;gap:12px}
.banner .verdict h2{margin:0;font-size:18px;font-weight:700;letter-spacing:-.02em}
.banner .just{color:var(--sec);font-size:14px;margin-top:10px}
.banner ul{margin:12px 0 0;padding:0;list-style:none}
.banner li{display:flex;align-items:flex-start;gap:9px;padding:6px 0;color:var(--ink);font-size:13.5px}
.banner li::before{content:"›";color:var(--bad);font-weight:700;margin-top:-1px}
.grid-2{display:grid;grid-template-columns:1.5fr 1fr;gap:22px;align-items:stretch}
.grid-2>.panel{display:flex;flex-direction:column}
.grid-2-even{display:grid;grid-template-columns:1fr 1fr;gap:22px;align-items:stretch}
.grid-2-even>.panel{display:flex;flex-direction:column}
.block{margin-bottom:24px}
.kv{display:grid;grid-template-columns:auto 1fr;gap:11px 18px}
.kv dt{color:var(--sec);font-size:13px;font-weight:500}
.kv dd{margin:0;font-weight:600;font-size:13.5px;text-align:right}
.rules td{padding:13px 22px;font-size:13.5px}
.rules .rn{font-weight:600}
.rules .rmsg{color:var(--ter);font-size:12px;margin-top:3px}
.stage{display:flex;align-items:center;gap:12px;padding:11px 0;border-bottom:1px solid var(--line-2);font-size:13.5px}
.stage:last-child{border-bottom:0}
.stage .ck{width:20px;height:20px;border-radius:50%;display:grid;place-items:center;flex:none;font-size:11px;font-weight:700}
.stage .ck.ok{background:var(--ok-bg);color:var(--ok)}
.stage .ck.bad{background:var(--bad-bg);color:var(--bad)}
.stage .nm{flex:1}.stage .dur{color:var(--ter);font-size:12.5px;font-variant-numeric:tabular-nums}

/* ---- bold ranking bars (full-width, color-forward) ---- */
.bc{display:flex;flex-direction:column}
.bc-row{padding:9px 0;border-radius:8px;transition:background .15s ease;cursor:default}
.bc-row:hover{background:#FAFAFC}
.bc-row .top{display:flex;justify-content:space-between;gap:14px;align-items:baseline;margin-bottom:9px}
.bc-row .nm{font-size:13.5px;font-weight:600}
.bc-row .ct{font-size:15px;font-weight:700;font-variant-numeric:tabular-nums;flex:none}
/* "54 sozinha": context beside the count, never the headline number. */
.bc-row .ct .of{margin-left:6px;font-size:11.5px;font-weight:500;color:var(--ter)}
/* A zero here is the finding, not a missing value: this rule fires often and
   releases nothing when fixed. Worth reading differently from a number. */
.bc-row .ct .of.none{color:var(--warn);font-style:italic}
.card-note{margin:0 0 10px;font-size:12px;color:var(--ter);line-height:1.45}
.card-note b{font-weight:600;color:var(--sec)}
.bc-track{position:relative;height:12px;background:#F1F1F5;border-radius:999px;overflow:hidden}
.bc-fill{display:block;height:100%;border-radius:999px;width:0;animation:growX .95s cubic-bezier(.22,1,.36,1) forwards;transition:filter .18s ease}
.bc-row:hover .bc-fill{filter:brightness(1.06) saturate(1.08)}
.bc-fill.tone-bad{background:var(--bad)}
.bc-fill.tone-ok{background:var(--ok-ico)}
.bc-fill.tone-neutral{background:var(--neu-ico)}
.bc-fill.tone-warn{background:var(--warn-ico)}
/* The decision-reasons card colours each bar by the decision it records, so
   it needs the caveat green the pill and the distribution slices already
   use. Not a rule severity, which is why it is absent from _SEVERITY_TONE. */
.bc-fill.tone-ressalva{background:var(--ressalva-ico)}

/* ---- stacked time-composition bar ---- */
.timebar{display:flex;height:32px;border-radius:11px;overflow:hidden;background:#F1F1F5;margin-top:6px;
  box-shadow:inset 0 0 0 1px rgba(20,20,30,.04);clip-path:inset(0 100% 0 0);animation:barReveal 1s cubic-bezier(.22,1,.36,1) .35s forwards}
.timebar span{display:block;height:100%;cursor:pointer;transition:filter .18s ease}
.timebar:hover span{filter:saturate(.7) brightness(1.05)}
.timebar span:hover{filter:saturate(1.18) brightness(1.06)!important}
.timeleg{display:flex;flex-direction:column;margin-top:20px}
.timeleg .it{display:flex;align-items:center;gap:11px;font-size:13.5px;padding:12px 0;border-bottom:1px solid var(--line-2);
  opacity:0;animation:fadeUp .5s cubic-bezier(.22,1,.36,1) forwards}
.timeleg .it:last-child{border-bottom:0}
.timeleg .it:nth-child(1){animation-delay:.5s}.timeleg .it:nth-child(2){animation-delay:.56s}
.timeleg .it:nth-child(3){animation-delay:.62s}.timeleg .it:nth-child(4){animation-delay:.68s}
.timeleg .it:nth-child(5){animation-delay:.74s}.timeleg .it:nth-child(6){animation-delay:.8s}
.timeleg .it .dot{width:10px;height:10px;border-radius:50%;flex:none}
.timeleg .it .nm{flex:1;color:var(--sec);font-weight:500}
.timeleg .it b{font-weight:700;font-variant-numeric:tabular-nums}

/* ---- "em breve" placeholder states (real layout + stand-in values) ---- */
.ph{color:var(--ter)!important}
.eb-badge{background:var(--neu-bg);color:var(--neu);font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;padding:4px 11px;border-radius:999px;white-space:nowrap}
.summary .topline{display:flex;align-items:center;gap:14px}
.eb-headrow{display:flex;align-items:center;gap:12px;margin-bottom:16px}
.eb-headrow .section-label{margin:0}
.panel-head .eb-badge{margin-left:auto}
.card-head .eb-badge{margin-left:auto}
.st.placeholder{background:var(--neu-bg);color:var(--neu)} .st.placeholder .dot{background:var(--neu)}
.feed-head{display:flex;align-items:center;gap:13px;padding-bottom:11px;border-bottom:1px solid var(--line);font-size:12px;font-weight:600;color:var(--ter)}
.feed-head .tm{width:58px;flex:none}.feed-head .nm{flex:1}
/* neutral placeholder marks for charts */
.ph-bar{background:var(--neu-bg)!important}
.ph-track .fill{background:var(--neu-bg)!important}
.ph-line{stroke:var(--icon-muted)!important;stroke-dasharray:4 4!important;opacity:.5}

/* ===== interactive: tooltip + hover states ===== */
.tip{position:fixed;z-index:60;pointer-events:none;left:0;top:0;
  background:#16161A;color:#fff;border-radius:11px;padding:10px 13px;font-size:12.5px;font-weight:500;
  box-shadow:0 10px 30px rgba(20,20,30,.22),0 2px 6px rgba(20,20,30,.14);
  opacity:0;transform:translateY(5px) scale(.97);transform-origin:bottom left;
  transition:opacity .14s ease,transform .18s cubic-bezier(.34,1.4,.5,1);white-space:nowrap}
.tip.on{opacity:1;transform:none}
.tip .tt{font-weight:700;font-size:12.5px;margin-bottom:6px;letter-spacing:-.01em}
.tip .rr{display:flex;align-items:center;gap:16px;justify-content:space-between;margin-top:4px;font-size:12px;color:rgba(255,255,255,.78)}
.tip .rr .nm{display:flex;align-items:center;gap:7px}
.tip .rr .dot{width:7px;height:7px;border-radius:50%;flex:none}
.tip .rr b{color:#fff;font-weight:700;font-variant-numeric:tabular-nums}
.tip .big{font-size:18px;font-weight:700;letter-spacing:-.02em}

/* daily chart hover */
.chart .col{transition:opacity .2s ease,filter .2s ease;cursor:pointer}
.chart.dim .col:not(.hot){opacity:.3;filter:saturate(.55)}
.chart.dim .col.hot{filter:saturate(1.12)}

/* donut hover */
.donut-c circle{transition:opacity .22s ease,stroke-width .22s cubic-bezier(.34,1.4,.5,1)}
.donut-c.dim circle:not(.hot){opacity:.26}
.donut-c circle.hot{stroke-width:19}
.type-legend .row{cursor:pointer;border-radius:8px;transition:background .15s ease}
.type-legend .row:hover{background:#FAFAFC}

/* rule-row hover */
.rule-row{cursor:default;border-radius:8px;transition:background .15s ease}
.rule-row:hover{background:#FAFAFC}
.rule-row .fill{transition:filter .18s ease}
.rule-row:hover .fill{filter:brightness(1.08) saturate(1.1)}

/* line chart hover */
.linechart{position:relative}
.lc-pts circle{cursor:pointer}
.lc-hot{fill:#fff;stroke:var(--accent);stroke-width:3;opacity:0;transition:opacity .15s ease}
.lc-hot.on{opacity:1}
.lc-guide{stroke:var(--line);stroke-width:1;stroke-dasharray:3 3;opacity:0;transition:opacity .15s ease}
.lc-guide.on{opacity:1}

/* ===== motion ===== */
@keyframes fadeUp{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
@keyframes barReveal{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}
@keyframes growY{to{transform:scaleY(1)}}
@keyframes growX{to{width:var(--w,100%)}}
/* Same motion as growX under a second name, so the severity panes can restart
   it on a switch: only a change of animation-name restarts an animation, a
   change of duration on the same name does not. See .sev-pane below. */
@keyframes growXIn{from{width:0}to{width:var(--w,100%)}}
.head{opacity:0;animation:fadeUp .55s cubic-bezier(.22,1,.36,1) .02s forwards}
.summary{opacity:0;animation:fadeUp .55s cubic-bezier(.22,1,.36,1) .10s forwards}
.toolbar{opacity:0;animation:fadeUp .55s cubic-bezier(.22,1,.36,1) .18s forwards}
.reveal{opacity:0;animation:fadeUp .55s cubic-bezier(.22,1,.36,1) forwards}
.panel:not(.no-anim){opacity:0;animation:fadeUp .55s cubic-bezier(.22,1,.36,1) .24s forwards}
.banner{opacity:0;animation:fadeUp .55s cubic-bezier(.22,1,.36,1) .12s forwards}
.distbar{clip-path:inset(0 100% 0 0);animation:barReveal 1.05s cubic-bezier(.22,1,.36,1) .5s forwards}
.d-1{animation-delay:.10s!important}.d-2{animation-delay:.18s!important}.d-3{animation-delay:.26s!important}
.d-4{animation-delay:.34s!important}.d-5{animation-delay:.42s!important}
/* staggered children */
tbody tr.clickable{opacity:0;animation:fadeUp .5s cubic-bezier(.22,1,.36,1) forwards}
tbody tr:nth-child(1){animation-delay:.30s}tbody tr:nth-child(2){animation-delay:.34s}
tbody tr:nth-child(3){animation-delay:.38s}tbody tr:nth-child(4){animation-delay:.42s}
tbody tr:nth-child(5){animation-delay:.46s}tbody tr:nth-child(6){animation-delay:.50s}
tbody tr:nth-child(7){animation-delay:.54s}tbody tr:nth-child(8){animation-delay:.58s}
.kpi:nth-child(1){animation-delay:.05s}.kpi:nth-child(2){animation-delay:.12s}
.kpi:nth-child(3){animation-delay:.19s}.kpi:nth-child(4){animation-delay:.26s}.kpi:nth-child(5){animation-delay:.33s}
.chart .col:nth-child(n){animation-delay:calc(.4s + (var(--i,0) * .03s))}
.alert{opacity:0;animation:fadeUp .5s cubic-bezier(.22,1,.36,1) forwards}
.alert:nth-child(1){animation-delay:.30s}.alert:nth-child(2){animation-delay:.36s}
.alert:nth-child(3){animation-delay:.42s}.alert:nth-child(4){animation-delay:.48s}
.alert:nth-child(5){animation-delay:.54s}.alert:nth-child(6){animation-delay:.60s}
.rule-row .fill{animation-delay:.5s}
@media (prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important}
  .head,.summary,.toolbar,.panel,.banner,tbody tr,.alert,.reveal,.tile{opacity:1!important}
  .distbar{clip-path:none!important}.chart .col{transform:none!important}.rule-row .fill{width:var(--w)!important}
  .linechart .area{transform:none!important}.linechart .line{stroke-dashoffset:0!important}.linechart .dot{opacity:1!important}
  .spark .l{stroke-dashoffset:0!important}.spark .a,.spark .pt{opacity:1!important}
  .type-legend .row{opacity:1!important}
  .bc-fill{width:var(--w)!important}.timebar{clip-path:none!important}.timeleg .it{opacity:1!important}
}

/* ---- Execução page -------------------------------------------------
   Rows separated by a hairline and whitespace rather than a box each:
   a card per problem plus a strip plus a pill stated the severity three
   times and read as clutter. The dot and the word are one signal.
   Warning uses no coloured outline on purpose: --warn-ico on white is
   invisible at 1px. -------------------------------------------------- */
.exe-meta{font-size:12px;color:var(--ter);margin:-10px 0 14px}
/* Partial re-judge notice. Sits between the page meta and the verdict,
   because it qualifies everything below it: a run that only re-judged the
   rules inherited the rest, and the laudo must say so before it shows a
   finding nobody re-checked. */
.exe-inherited{font-size:12px;color:var(--sec);background:var(--neu-bg);
  border:1px solid var(--line-2);border-radius:10px;padding:10px 14px;
  margin:0 0 14px;max-width:720px}

.exe-verdict{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:4px}

.exe-panel{border:1px solid var(--line);border-radius:14px;overflow:hidden;margin-bottom:8px;background:var(--surface)}
.exe-head{display:flex;align-items:center;gap:12px;padding:11px 16px;background:var(--neu-bg);border-bottom:1px solid var(--line-2);font-size:12px;font-weight:600;color:var(--sec)}
.exe-count{margin-left:auto;font-weight:500;color:var(--ter)}
.exe-quiet .exe-head{background:var(--surface)}

.exe-row{border-bottom:1px solid var(--line-2)}
.exe-row:last-child{border-bottom:0}
.exe-row>summary{display:flex;gap:12px;align-items:flex-start;padding:15px 16px;cursor:pointer;list-style:none}
.exe-row>summary::-webkit-details-marker{display:none}
.exe-row>summary:hover{background:var(--accent-soft)}
.exe-row.static{display:flex;gap:12px;align-items:flex-start;padding:15px 16px}
/* A termo row whose whole surface opens its analysis. Same box as a summary
   so the two kinds of row line up, but an <a>, which is what it behaves as:
   middle-click, copy-link and keyboard focus all work without JS. The
   non-link twin is the same rule so a termo with no run keeps the layout. */
.exe-row>.exe-open{display:flex;gap:12px;align-items:flex-start;padding:15px 16px;
  text-decoration:none;color:inherit}
a.exe-open:hover{background:var(--accent-soft)}
/* Indented past the dot's column so the action reads as belonging to the row
   above it, and kept out of the anchor: the button spends money. */
/* One row per termo, wrapping: "Analisar de novo" and the decision label sit
   side by side, and the form the label opens takes the line below them. A
   wrapping flex row, exactly as it was before the decision form existed:
   only .blk-form's flex-basis:100% is new, and it is what pushes the form
   onto its own line at full width instead of into a sliver beside them. */
.exe-row-act{padding:0 16px 14px 36px;display:flex;flex-wrap:wrap;
  align-items:center;gap:10px}
.exe-row-act form{margin:0}
.exe-row-act > .blk-form{flex:1 0 100%;padding:0}
.exe-dot{width:8px;height:8px;border-radius:50%;margin-top:6px;flex:none;background:var(--neu-ico)}
.exe-dot.ok{background:var(--ok-ico)}.exe-dot.warn{background:var(--warn-ico)}
.exe-dot.bad{background:var(--bad-ico)}.exe-dot.neu{background:var(--neu-ico)}
.exe-dot.ressalva{background:var(--ressalva-ico)}.exe-dot.bloqueio{background:var(--bloqueio-ico)}
.exe-body{flex:1;display:flex;flex-direction:column;gap:3px}
.exe-title{font-size:14px;font-weight:600;line-height:1.4}
.exe-why{font-size:12.5px;color:var(--sec);line-height:1.5}
.exe-sev{font-size:9.5px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;flex:none;padding-top:4px;color:var(--neu)}
.exe-sev.bad{color:var(--bad)}.exe-sev.warn{color:var(--warn)}
.exe-chev{color:var(--icon-muted);flex:none;padding-top:2px;transition:transform .15s ease}
.exe-row[open]>summary .exe-chev{transform:rotate(90deg)}

/* The expanded region is more of the same row, not a different surface. A
   slab of grey behind it read as a hole in the page, so it stays white and
   a rail in the dot's column marks how far the disclosure reaches. */
.exe-det{position:relative;padding:2px 16px 18px 40px;background:var(--surface)}
.exe-det::before{content:"";position:absolute;left:19px;top:0;bottom:18px;
  width:2px;border-radius:2px;background:var(--line)}
.exe-dl{display:grid;grid-template-columns:120px 1fr;gap:7px 14px;font-size:12.5px;margin:0}
.exe-dl dt{color:var(--ter)}
.exe-dl dd{margin:0}
.miss{color:var(--bad);font-weight:600}
.exe-quote{background:var(--neu-bg);border:1px solid var(--line-2);border-radius:9px;padding:10px 12px;font-size:12px;color:var(--sec);line-height:1.6;margin-top:10px}
/* A decision citing a catalogue motivo stores "motivo\ndetalhe". HTML
   collapses that newline, so the two run together into one sentence that
   reads as neither. Its own class rather than white-space on .exe-quote:
   that class also carries rule evidence quoted out of the OCR, which is full
   of layout newlines and is meant to reflow as a paragraph. */
.exe-quote-decision{white-space:pre-line}
.exe-audit{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:10.5px;color:var(--ter);margin-top:12px}
/* One quiet link per finding, to the criterion that raised it. Sits beside
   the audit line rather than in the row's summary: the collapsed row is a
   verdict to scan, this is an action for someone already reading detail. */
/* The plain-language expansion of a restrictive list, inside a finding's
   own detail. Reads as explanation, not as evidence, so it is set apart
   from `.exe-quote` (which carries text lifted from the document). */
.exe-source-note{font-size:12.5px;line-height:1.5;color:var(--sec);background:var(--sunken);border-radius:8px;padding:10px 12px;margin:0 0 10px}
.exe-crit-link{display:inline-block;font-size:11.5px;font-weight:500;color:var(--accent);margin-top:10px}
.exe-crit-link:hover{text-decoration:underline}
/* One entry per line, the rule named on the left and what it found on the
   right. Reading down a single column of names is how you find the one you
   want; stacking name over message doubled the height and made the
   messages the thing you scanned. The bucket's colour is already on the
   row you opened, so it is not repeated per entry. */
.exe-list{list-style:none;padding:0;margin:2px 0 0}
.exe-list li{display:grid;grid-template-columns:minmax(0,22em) minmax(0,1fr);
  gap:3px 26px;align-items:baseline;padding:9px 0;
  border-top:1px solid var(--line-2);font-size:12.5px}
.exe-list b{font-weight:600;line-height:1.4}
.exe-list span{color:var(--ter);font-size:11.5px;line-height:1.5}
/* Below this the two columns would each be too narrow to hold a phrase, so
   the message goes back under its name. */
@media (max-width:820px){.exe-list li{grid-template-columns:1fr}}

.exe-slices{display:flex;gap:3px;flex:1;margin-left:auto;max-width:200px}
.exe-slices i{height:5px;flex:1;border-radius:3px;background:var(--neu-ico)}
.exe-slices i.ok{background:var(--ok-ico)}.exe-slices i.bad{background:var(--bad-ico)}
.exe-slices i.warn{background:var(--warn-ico)}.exe-slices i.neu{background:var(--neu-ico)}

.exe-kv{display:grid;grid-template-columns:1fr 1fr;gap:0 26px;padding:4px 16px 12px}
.exe-k{display:flex;justify-content:space-between;gap:14px;padding:9px 0;border-bottom:1px solid var(--line-2);font-size:12.5px}
.exe-k span:first-child{color:var(--ter)}
.exe-k span:last-child{text-align:right;font-weight:500}
@media (max-width:720px){.exe-kv{grid-template-columns:1fr}}

.exe-table{width:100%;border-collapse:collapse;font-size:12.5px}
.exe-table th{text-align:left;font-size:9.5px;text-transform:uppercase;letter-spacing:.07em;color:var(--ter);padding:11px 16px;font-weight:700;background:var(--neu-bg)}
.exe-table td{padding:11px 16px;border-top:1px solid var(--line-2)}

.exe-clause{padding:13px 16px;border-top:1px solid var(--line-2)}
.exe-clause:first-child{border-top:0}

/* Processamento: one row while nothing is broken, the whole trail once
   something is. A stacked time bar and eleven full-width legend rows spent
   half a screen to say "it ran"; on a healthy run this is diagnostics nobody
   reads, and on a failed one the row itself has to name the stage. */
.exe-grid2{display:grid;grid-template-columns:repeat(2,1fr);gap:0 26px}
.exe-grid2 .it{display:flex;align-items:center;gap:10px;font-size:12.5px;padding:9px 0;
  border-bottom:1px solid var(--line-2)}
.exe-grid2 .sw{width:9px;height:9px;border-radius:50%;flex:none;background:var(--accent)}
.exe-grid2 .sw.bad{background:var(--bad-ico)}
.exe-grid2 .sw.neu,.exe-grid2 .sw.off{background:var(--neu-ico)}
.exe-grid2 .nm{flex:1;color:var(--sec);font-weight:500}
.exe-grid2 b{font-weight:700;font-variant-numeric:tabular-nums;font-size:11.5px}
.exe-grid2 b.bad{color:var(--bad)}
.exe-grid2 b.off{color:var(--ter);font-weight:500;font-variant-numeric:normal}
@media (max-width:720px){.exe-grid2{grid-template-columns:1fr}}

/* Everything the analyst can already read in the contract, one click away.
   It is the last row OF the Resumo panel, not a pill floating between two
   panels: the page then has one interaction idiom, a row with a dot and a
   chevron, instead of a different one per section. */
.exe-row.inset{border-top:1px solid var(--line-2)}
/* Full-bleed content: the panels inside carry their own borders, so the
   rail would run underneath them instead of beside them. */
.exe-det.wide{padding:14px 16px}
.exe-det.wide::before{display:none}
.exe-det.wide .exe-panel:last-child{margin-bottom:0}

/* The live stage checklist. Its right column ends in a status chip, so the
   16px the other .exe-det variants use left those chips almost touching the
   panel border while every other right-aligned chip on the page sits ~32px
   in. Widened both sides so the two columns breathe and the right edge
   lines up with the rest of the page. */
.exe-det.progress{padding-right:32px}
/* The run page drops the rail (.wide), so there is no 40px gutter holding
   the left edge off the border the way the cotação page's nesting does.
   Match the right inset there so the checklist sits evenly inside its own
   section instead of hugging both borders. */
.exe-det.wide.progress{padding:16px 32px 20px}
.exe-det.progress .exe-grid2{column-gap:40px}

/* ---- page rhythm ------------------------------------------------------
   The page used to be six identical section-label + panel pairs, so nothing
   outranked anything. A section is now one closed object whose title lives
   in its own header bar, which is the idiom the field groups already used;
   the verdict section borrows the blocker colour on that bar alone, and the
   section that never has findings is dimmed until hovered. ------------- */
/* The page title uses the shared .head treatment (30px h1 + 15px sub), so
   this page ranks like every other one. .exe-meta sits under it, which is
   what its negative top margin was always sized for. */
.exe-hero{border:1px solid var(--line);border-radius:14px;overflow:hidden;margin-bottom:14px;
  background:var(--surface)}
.exe-hero-top{padding:19px 22px 17px;background:var(--neu-bg)}
/* Bold, but at the page title's own size and tracking: what read as
   shouting was 27px at 800, not the weight by itself. */
.exe-hero-word{font-size:24px;font-weight:700;letter-spacing:-.015em;line-height:1;color:var(--neu)}
.exe-hero-why{font-size:13px;font-weight:500;color:var(--sec);margin-top:8px;max-width:640px}
.exe-hero.bad{border-color:rgba(217,10,102,.22)}
.exe-hero.bad .exe-hero-top{background:var(--bad-bg)}
.exe-hero.bad .exe-hero-word{color:var(--bad)}
.exe-hero.warn{border-color:rgba(255,199,0,.4)}
.exe-hero.warn .exe-hero-top{background:var(--warn-bg)}
.exe-hero.warn .exe-hero-word{color:var(--warn)}
.exe-hero.ok{border-color:rgba(11,107,65,.22)}
.exe-hero.ok .exe-hero-top{background:var(--ok-bg)}
.exe-hero.ok .exe-hero-word{color:var(--ok)}
.exe-hero.ressalva{border-color:rgba(15,106,84,.22)}
.exe-hero.ressalva .exe-hero-top{background:var(--ressalva-bg)}
.exe-hero.ressalva .exe-hero-word{color:var(--ressalva)}
.exe-hero.bloqueio{border-color:rgba(122,11,46,.26)}
.exe-hero.bloqueio .exe-hero-top{background:var(--bloqueio-bg)}
.exe-hero.bloqueio .exe-hero-word{color:var(--bloqueio)}

/* Names what a Fast Flow's cross-document check matched against, so an
   analyst can disagree with the automatic search. --ter, not --muted:
   that token name does not exist in this stylesheet's :root (see the
   text ramp above), and --ter is what every other muted label already
   uses (.exe-dl dt, .exe-list span). */
.mother-termo{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap;margin-top:10px;font-size:13px}
.mother-termo .mt-label{color:var(--ter)}
.mother-termo .mt-quote{font-weight:600}
.mother-termo .mt-file{color:var(--ter);word-break:break-all}
.mother-termo .mt-warn{color:var(--warn);font-style:italic}
.exe-hero-body{background:var(--surface)}
.exe-hero-label{font-size:9.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ter);padding:14px 22px 3px}
/* A numbered pendência: the count is a position in a to-do list, not a
   severity, so the ring colour carries the severity instead. */
.exe-num{width:20px;height:20px;border-radius:50%;flex:none;margin-top:1px;
  display:flex;align-items:center;justify-content:center;
  font-size:10px;font-weight:800;border:1.5px solid var(--neu-ico);color:var(--neu)}
.exe-num.bad{border-color:var(--bad);color:var(--bad)}
.exe-num.warn{border-color:var(--warn-ico);color:var(--warn)}
.exe-row.pend>summary{padding:12px 22px}
.exe-row.pend .exe-det{padding-left:56px;padding-right:22px}
.exe-hero-acts{display:flex;flex-wrap:wrap;align-items:center;gap:9px;
  padding:14px 22px;border-top:1px solid var(--line-2)}
.exe-hero-acts form{margin:0}
/* The action row holding the decision toggle. "Reprocessar análise" and the
   decision label sit side by side, and the form the label opens takes the
   line below them: it is a column of selects and a textarea, and squeezed
   into the space left beside a button it renders as a sliver. The row keeps
   the plain flex layout every .exe-hero-acts has; flex-basis:100% on the
   form is the whole of what makes it wrap. The row already supplies the
   22px gutter, so the form drops its own or the fields would sit indented
   from the label that opened them. */
.exe-hero-acts.dec-row > .blk-form{flex:1 0 100%;padding:0 0 4px}
.exe-btn{display:inline-flex;align-items:center;background:var(--surface);color:var(--accent);
  border:1px solid var(--accent-soft-2);border-radius:10px;padding:9px 15px;
  font-family:inherit;font-size:12.5px;font-weight:600;cursor:pointer;
  transition:background .15s ease}
.exe-btn:hover{background:var(--accent-soft)}
/* Anchored to the page header, so opening the contract is in the same place
   on every run instead of moving with whatever the hero happens to list. */
.exe-btn.top{margin-left:auto;flex:none;white-space:nowrap;text-decoration:none}
/* The first one absorbs the free space; the rest only need separating. */
.exe-btn.top+.exe-btn.top{margin-left:8px}

.exe-section{border:1px solid var(--line);border-radius:14px;overflow:hidden;
  margin-bottom:14px;background:var(--surface)}
/* EXPERIMENT (revert this commit to restore the grey): the section bars lose
   their neutral fill along with every other card head on the dashboard. The
   colour on this page still belongs to the verdict, so nothing else changes. */
.exe-sec-head{display:flex;align-items:center;gap:12px;padding:13px 16px;
  border-bottom:1px solid var(--line-2)}
.exe-sec-head h2{font-size:13.5px;font-weight:700;letter-spacing:-.012em;margin:0;color:var(--ink)}
/* The count is pushed right by its own margin, or by the strip when a
   section has one: either way the right edge of the bar is where it sits. */
.exe-sec-head .c{margin-left:auto;font-size:11.5px;font-weight:600;
  color:var(--ter);text-align:right;flex:none}
.exe-sec-head .exe-slices~.c{margin-left:0}
.exe-section.lead-bad{border-color:rgba(217,10,102,.22)}
.exe-section.lead-bad .exe-sec-head{background:var(--bad-bg);border-bottom-color:rgba(217,10,102,.14)}
.exe-section.lead-bad .exe-sec-head h2{color:var(--bad)}
.exe-section.quiet{opacity:.74;transition:opacity .2s ease}
.exe-section.quiet:hover,.exe-section.quiet:focus-within{opacity:1}
/* ---- optional side-by-side contract ---------------------------------- */
.exe-layout.split{display:grid;grid-template-columns:minmax(0,1fr) minmax(420px,560px);
  gap:18px;align-items:start}
.exe-layout.split .exe-main{min-width:0}
.exe-pdf{position:sticky;top:88px;border:1px solid var(--line);border-radius:14px;
  overflow:hidden;background:var(--surface)}
.exe-pdf-bar{display:flex;align-items:center;gap:12px;padding:11px 14px;background:var(--sunken);
  border-bottom:1px solid var(--line-2);font-size:11.5px;font-weight:600;color:var(--sec)}
.exe-pdf-bar span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.exe-pdf-bar a{flex:none;color:var(--accent);font-size:11px;font-weight:600}
.exe-pdf-frame{display:block;width:100%;height:calc(100vh - 170px);min-height:420px;border:0}
.exe-pdf-fallback{padding:24px;font-size:12.5px;color:var(--sec);text-align:center}
.exe-pdf-fallback a{display:block;margin-top:8px;color:var(--accent);font-weight:600}
@media (max-width:1080px){
  .exe-layout.split{grid-template-columns:1fr}
  .exe-pdf{position:static}
  .exe-pdf-frame{height:70vh}
}

/* ---- Cotação page ----------------------------------------------------
   Shares every .exe-* idiom with the Execução page one level down: same
   hero, same section bars, same rows. Only the facts strip is new. It
   replaces four tiles that rendered their values at title size, so a
   quote number wrapped mid-token and the tallest tile set the height of
   all four. ---------------------------------------------------------- */
.qf{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  border:1px solid var(--line);border-radius:14px;background:var(--surface);
  overflow:hidden;margin:0 0 14px}
.qf .it{padding:12px 16px;border-left:1px solid var(--line-2);min-width:0}
.qf .it:first-child{border-left:0}
.qf .l{font-size:9.5px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--ter)}
.qf .v{font-size:14px;font-weight:600;margin-top:4px;line-height:1.35;
  overflow-wrap:anywhere;font-variant-numeric:tabular-nums}
.qf .s{font-size:11px;font-weight:500;color:var(--ter);margin-top:2px}
.qf .s.bad{color:var(--bad);font-weight:600}
@media (max-width:820px){.qf{grid-template-columns:repeat(2,minmax(0,1fr))}
  .qf .it:nth-child(3){border-left:0}}
@media (max-width:560px){.qf{grid-template-columns:1fr}
  .qf .it{border-left:0;border-top:1px solid var(--line-2)}
  .qf .it:first-child{border-top:0}}
/* The caption that states what the motivo counts cover. Sits between the
   toolbar and the table, so it reads as a note on the selector above it
   rather than as a heading for the rows below. */
.qf-motivo-note{margin:-4px 0 12px}

/* The reason under the "Não analisado" and "Sem contrato na pasta" chips.
   Same tertiary tone as the
   `.sub-cnpj` line it borrows, capped in width so the longest of the eleven
   labels widens the Situação column by nothing. */
.qf-motivo{max-width:210px;line-height:1.35}

/* The "termo esperado" marker on a row title. A real badge (own background,
   own padding), not inline text riding on .exe-title: nested there its
   flex/padding rules were inert and it read as part of the filename. A
   soft accent fill, never --bad-ico/--warn-ico/etc: those are vivid fills
   meant for small dots, not text, and fail AA contrast used as one. */
.qf-badge{display:inline-block;background:var(--accent-soft);color:var(--ter);
  font-size:9.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  padding:2px 7px;border-radius:999px;vertical-align:middle}

/* A code, not a word: the h1's -.03em tracking is tuned for names and
   closes up letter pairs that have to be read one character at a time. */
.head h1.mono-title{letter-spacing:-.01em;font-variant-numeric:tabular-nums}
/* The status chip sits at the right edge of a row's summary. Scoped to the
   summary on purpose: .exe-clause on the Execução page also puts a .st
   inside an .exe-row, and a descendant selector would shove it right. */
.exe-row>summary>.st{margin-left:auto;flex:none;align-self:center}

/* Verdict distribution on the Cotações list. The bar covers only the
   quotes that were judged: the never-analysed ones are the ingestion
   backlog, stated above it in words, and folding them in would reduce
   every real verdict to a sliver. */
.qdist{margin:0 0 24px}
.qdist .legend{margin-top:12px;gap:22px}
.qdist .legend .it{font-size:12.5px}

/* Company compliance block: same hero shell, one reason per row. Scoped by
   the blk- prefix itself rather than an .exe-hero.blk ancestor, because the
   Compliance page reuses the same release form (.blk-form) outside any
   hero, and it needs the same styling there. */
/* Horizontal padding matches .exe-hero-label / .exe-hero-acts (22px): the
   reason rows and the release form used to sit flush against the panel's
   own edges while every sibling in the same hero kept its 22px margin. */
.blk-row { display: flex; gap: 10px; align-items: flex-start; padding: 8px 22px; }
.blk-row .exe-sub { display: block; font-size: 12px; opacity: .75; }
.blk-form { margin-top: 14px; padding: 0 22px 18px; display: flex; flex-direction: column; gap: 8px; }
.blk-label { font-size: 12px; opacity: .8; }
.blk-form textarea { width: 100%; max-width: 100%; padding: 8px; border-radius: 6px;
  border: 1px solid rgba(0,0,0,.15); font: inherit; font-size: 13px; }
.blk-form .exe-btn { align-self: flex-start; }
/* Two decisions on one contract are a choice, not a sequence, so they sit
   side by side. Without the wrapper .blk-form's column direction stacks them,
   which reads as "approve, then reject". flex-start keeps the pair hugging
   the left edge instead of stretching to the form's width. */
.blk-acts { display: flex; gap: 8px; align-items: center; align-self: flex-start; }
.blk-select { padding: 7px 8px; border-radius: 6px; border: 1px solid rgba(0,0,0,.15);
  font: inherit; font-size: 13px; background: #fff; max-width: 100%; }
.blk-check { display: flex; gap: 6px; align-items: center; font-size: 12px; opacity: .8; }
/* The decision form ships closed. Deciding by hand is the exception, so on a
   cotacao with a dozen termos an open form on every row buried the list under
   selects and textareas nobody asked for.

   A checkbox and its label rather than a <details>, because the label has to
   sit beside the rerun button while the form spans the row below it, and a
   <details> keeps its content in a single box (a ::details-content
   pseudo-element in current browsers) that placed itself in the grid and
   left the form nowhere to go. This is the same JS-free toggle the Criterios
   severity tabs use, and the label keeps it operable by keyboard. */
.dec-toggle { position: absolute; width: 1px; height: 1px; padding: 0;
  margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap;
  border: 0; }
.dec-summary { cursor: pointer; font-size: 12.5px; font-weight: 600;
  color: var(--accent); }
/* Non-breaking space, not a plain one: a trailing space in generated content
   collapses, and the open marker rendered as "-Decidir". */
.dec-summary::before { content: "+\00a0"; font-weight: 700; }
.dec-toggle:checked ~ .dec-summary::before { content: "\2212\00a0"; }
.dec-summary:hover { text-decoration: underline; }
.dec-toggle:focus-visible ~ .dec-summary { outline: 2px solid var(--accent-soft-2);
  outline-offset: 2px; border-radius: 4px; }
/* Closed is the default state, so the form stays hidden until its own
   checkbox is checked. The general sibling combinator, because the label
   sits between the two in the row. */
.dec-toggle ~ .blk-form { display: none; }
.dec-toggle:checked ~ .blk-form { display: flex; }

/* Small caps label distinguishing the verdict hero from the compliance
   block hero above it on a blocked quote's page: the two must never read
   as restating the same word. */
.exe-hero-kicker { font-size: 10.5px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ter); margin-bottom: 6px; }

/* Explanatory text inside a section body, under its own exe-sec-head bar.
   .exe-meta's negative top margin is sized for sitting right under the page
   .head; reusing it here pulled the paragraph up into the header box. */
.exe-sec-note { font-size: 12px; color: var(--ter); padding: 10px 16px 2px; }

/* ---- compliance: donut slices and source chips ---- */
/* The unfilled remainder of the ring, so a single full slice still reads
   as a proportion. Always drawn, always beneath the real arcs. */
.donut-c circle.seg-track{stroke:var(--neu-bg)}
/* Arcs and legend dots take the vivid -ico tokens, not the base ones: per the
   palette note at the top of this file the base colour is for LABEL TEXT and
   the -ico variant is the graphic. Using --ok on the ring is what made the
   donut read as a dull bottle green. */
.donut-c circle.seg-ok{stroke:var(--ok-ico)}
.donut-c circle.seg-warn{stroke:var(--warn-ico)}
.donut-c circle.seg-bad{stroke:var(--bad-ico)}
.donut-c circle.seg-neu{stroke:var(--neu-ico)}
.type-legend .dot-ok{background:var(--ok-ico)}
.type-legend .dot-warn{background:var(--warn-ico)}
.type-legend .dot-bad{background:var(--bad-ico)}
.type-legend .dot-neu{background:var(--neu-ico)}
.source-row .st.neutral{background:var(--neu-bg);color:var(--neu)}

/* ---- compliance: history feed ---- */
.hist-row{display:flex;gap:16px;padding:14px 20px;border-bottom:1px solid var(--line-2)}
.hist-row:last-of-type{border-bottom:0}
.hist-row .when{flex:none;width:52px;color:var(--ter);font-size:11.5px;font-weight:600;
  font-variant-numeric:tabular-nums;line-height:1.45;padding-top:1px}
.hist-row .body{flex:1;min-width:0}
.hist-row .line{font-size:13px;line-height:1.5}
.hist-row .just{font-size:12.5px;color:var(--sec);font-style:italic;margin-top:6px;
  border-left:2.5px solid var(--line);padding-left:11px;max-width:62ch}

/* ---- KPI page: card titles, headline pair, breakdown extras ---- */
.card-head{display:flex;align-items:center;gap:9px;padding:11px 20px;
  border-bottom:1px solid var(--line-2);font-size:11.5px;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;color:var(--sec);flex:none}
.card-head .r{margin-left:auto;font-size:11px;font-weight:500;letter-spacing:0;
  text-transform:none;color:var(--ter)}
/* seg-card: the segmented control reused inside a title bar instead of a
   page head, so it needs a smaller footprint than .seg's default 7px 15px.
   It switches four server-rendered panes through hidden radio inputs (no
   JavaScript, no page reload), so it styles <label> rather than the
   <a>+.seg-ind pill the period control at the top of the page still uses:
   the checked label just gets the white pill directly. */
.card-head .seg-card{text-transform:none;letter-spacing:normal}
.seg-card label{display:inline-block;padding:4.5px 10px;font-weight:500;font-size:11.5px;
  color:var(--sec);border-radius:8px;letter-spacing:-.01em;cursor:pointer;
  transition:color .2s ease,background .2s ease}
/* The radios sit at .panel level and the labels inside .card-head, so they
   are not adjacent siblings: `input:checked + label` matches nothing here and
   left the control with no visible selection. Each pair is addressed the same
   way the panes are, through the general sibling combinator. */
#rule-sev-blocker:checked ~ .card-head label[for="rule-sev-blocker"],
#rule-sev-warning:checked ~ .card-head label[for="rule-sev-warning"],
#rule-sev-info:checked ~ .card-head label[for="rule-sev-info"],
#rule-sev-all:checked ~ .card-head label[for="rule-sev-all"]{
  background:#fff;color:var(--ink);font-weight:600;
  box-shadow:0 1px 3px rgba(0,0,0,.10),0 1px 1px rgba(0,0,0,.04)}
/* Keyboard focus has to be visible on the label, since the radio it belongs
   to is the visually hidden element that actually receives focus. */
.sev-radio:focus-visible ~ .card-head label[for]{outline:2px solid var(--accent-soft-2);
  outline-offset:1px}
/* Visually hidden but still focusable/clickable-by-label, and in the tab
   order: display:none would drop the radios from keyboard navigation. */
.sev-radio{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.sev-count{display:none}
#rule-sev-blocker:checked ~ .card-head .sev-count-blocker,
#rule-sev-warning:checked ~ .card-head .sev-count-warning,
#rule-sev-info:checked ~ .card-head .sev-count-info,
#rule-sev-all:checked ~ .card-head .sev-count-all{display:block}
/* All four panes stack in the same grid cell, so the cell is as tall as the
   tallest of them and the card keeps one height whether the selected tab
   holds eight rules or one. Switching severities can then never move the
   page under the pointer. This is deliberately structural: the earlier
   min-height was a hand-computed row count, and every arithmetic guess at
   the height of a row was wrong by a few pixels, which is exactly what a
   fixed card height cannot tolerate.
   visibility rather than display, because a display:none pane contributes
   no height to the cell — and visibility:hidden also keeps the inactive
   panes out of the accessibility tree, which is what display gave us. */
.sev-panes{display:grid;flex:1}
.sev-pane{grid-area:1/1;visibility:hidden}
/* The animation is declared here, on the checked rule, rather than on
   .sev-pane: all four panes exist from page load, so one declared on the
   pane itself would have run and finished long before you touched the tabs.
   Adding it as the selector starts matching is what makes it play on each
   switch — and removing it as the selector stops matching is what lets it
   play again when you come back to a pane. Shorter than the .55s a panel
   gets on load: this is content moving inside a card that never moved. */
#rule-sev-blocker:checked ~ .card-body .sev-pane-blocker,
#rule-sev-warning:checked ~ .card-body .sev-pane-warning,
#rule-sev-info:checked ~ .card-body .sev-pane-info,
#rule-sev-all:checked ~ .card-body .sev-pane-all{visibility:visible;
  animation:fadeUp .34s cubic-bezier(.22,1,.36,1)}
/* And the bars refill with the pane. growXIn rather than the growX the base
   rule already ran: swapping the name is what restarts it, and swapping back
   on deselect is what arms it for the next visit. Held back .08s so the pane
   is on its way in before the bars start moving. */
#rule-sev-blocker:checked ~ .card-body .sev-pane-blocker .bc-fill,
#rule-sev-warning:checked ~ .card-body .sev-pane-warning .bc-fill,
#rule-sev-info:checked ~ .card-body .sev-pane-info .bc-fill,
#rule-sev-all:checked ~ .card-body .sev-pane-all .bc-fill{
  animation:growXIn .8s cubic-bezier(.22,1,.36,1) .08s forwards}
/* A rule name is held to one line so it cannot wrap in the narrow
   two-column layout and grow its own pane past the others. The full text
   stays available through the title attribute. */
/* The rules card above carries no bottom margin, having been the last thing
   on the page until this one followed it, so the gap belongs to this card.
   24px is the rhythm every other block on the page keeps. */
.dr-card{margin-top:24px}
.sev-pane .bc-row .nm,.dr-card .bc-row .nm{flex:1;min-width:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* A reason is analyst-typed free text up to 300 characters, so the guard
   above matters more here than on the rule names it was written for: one
   long reason would otherwise wrap to five lines and tower over the card
   beside it. The full text stays in the title attribute. */
.card-body{padding:18px 22px 20px;flex:1;display:flex;flex-direction:column;min-height:0}

/* headline pair: number, caption, bar pinned to the floor, legend. margin-top:auto
   is what makes both cards agree on where the bar sits, whatever height the grid
   stretches them to. */
.hl-top{display:flex;align-items:baseline;gap:13px}
.hl-num{font-size:34px;font-weight:700;letter-spacing:-.03em;line-height:1}
.hl-cap{font-size:13px;color:var(--sec);font-weight:500;margin-top:7px;line-height:1.45}
.hl-bar{margin-top:auto}

/* The average tick rides inside .bc-track. Ink at partial alpha, not white:
   white vanishes on the empty #F1F1F5 portion of the track. */
.bc-mark{position:absolute;top:0;bottom:0;width:2px;background:rgba(61,47,127,.55);z-index:1}
.bc-note{display:flex;align-items:center;gap:7px;font-size:11px;color:var(--ter);font-weight:600;
  margin-top:14px;padding-top:11px;border-top:1px solid var(--line-2)}
.bc-note s{width:2px;height:11px;background:rgba(61,47,127,.55);text-decoration:none;display:block}
/* The group count reads as a footnote to the list, so it sits on the footer
   line at the card's bottom right rather than in the title bar. */
.bc-count{margin-left:auto;font-weight:600;color:var(--ter)}

/* Breakdown panel search + in-card pagination (JS, static/billing/app.js).
   No-JS fallback: rows past the fifth stay hidden and the search box, which
   would do nothing without a handler, stays hidden with them. The .bc-ready
   class (added by the initialiser once it binds a panel) lifts both. */
.bc-search{display:none;width:190px;margin-left:auto;flex:none}
.bc-search input{padding:7px 12px;font-size:12.5px}
.bc-row{display:none}
.bc .bc-row:nth-child(-n+5){display:block}
/* The two panels stretch to a shared height, but a page holding fewer rows
   than the other (4 canais against 5 executivos) left its pager floating in
   the middle. The list absorbs the slack so the pager and the legend sit on
   the floor of both cards, at the same height. */
[data-bc-panel] .bc{flex:1}
.bc-empty{padding:16px 0;font-size:13px;color:var(--ter);text-align:center}
.bc-pager{display:none;align-items:center;justify-content:center;gap:12px;
  margin-top:12px;padding-top:11px;border-top:1px solid var(--line-2)}
.bc-pg-btn{width:26px;height:26px;border:1px solid var(--line);border-radius:8px;
  background:var(--surface);color:var(--sec);cursor:pointer;font-size:14px;line-height:1;
  display:flex;align-items:center;justify-content:center;transition:border-color .18s ease,color .18s ease}
.bc-pg-btn:disabled{opacity:.35;cursor:default}
.bc-pg-btn:not(:disabled):hover{border-color:var(--accent-soft-2);color:var(--accent)}
.bc-pg-label{font-size:11.5px;color:var(--ter);font-weight:600;font-variant-numeric:tabular-nums}
.bc-ready .bc-search{display:block}
.bc-ready .bc-row{display:block}
.bc-ready .bc-pager{display:flex}

/* .kpis compacted: three .kpi columns give each ~186px, where the stock 29px .v
   wraps "US$ 0,00" onto two lines. */
.kpis.sm .kpi{padding:16px 18px}
.kpis.sm .l{font-size:12px}
.kpis.sm .v{font-size:22px}
.kpis.sm .sub{font-size:11px}

.rules-2{display:grid;grid-template-columns:1fr 1fr;gap:0 34px}

/* A baseline turns "no bar" into "zero that day" instead of a hole. */
.chart.axis{border-bottom:1px solid var(--line)}
.chart-none{height:200px;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:9px;border:1px dashed var(--line);border-radius:12px;background:#FCFCFD}
.chart-none .t{font-size:13.5px;font-weight:600;color:var(--sec)}
.chart-none .s{font-size:12px;color:var(--ter);font-weight:500}

/* Visão geral's "Precisa de atenção" panel, which is two tabs over the same
   findings: the queue keeps each document's worst one, so an INFO note has
   no other way onto this page. Same hidden-radio switch the Critérios card
   uses — no JS, and it survives the page being served without it. */
/* Visually hidden but still focusable and in the tab order: display:none
   would drop the radios out of keyboard navigation entirely. */
.atn-radio{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.atn-radio:focus-visible ~ .panel-head label[for]{outline:2px solid var(--accent-soft-2);
  outline-offset:1px}
/* The heading names the selected tab. Only one is ever in flow, so the head
   bar keeps its height and the tabs beside it never shift. */
.atn-ttl{display:none}
#atn-tab-fila:checked ~ .panel-head .atn-ttl-fila,
#atn-tab-info:checked ~ .panel-head .atn-ttl-info{display:inline}
/* "Ver todas" leads to Cotações filtered by verdict. There is no list of
   notes for it to lead to, so it belongs to the queue tab alone. */
#atn-tab-info:checked ~ .panel-head .atn-all{display:none}
/* Both panes share one grid cell, so the panel is as tall as the taller of
   them and switching tabs cannot move the page under the pointer. Same
   reasoning, and the same visibility-not-display choice, as .sev-pane. */
.atn-panes{display:grid}
.atn-pane{grid-area:1/1;visibility:hidden}
/* Declared on the checked rule rather than on .atn-pane: both panes exist
   from page load, so an animation on the pane itself would have finished
   before anyone touched the tabs. */
#atn-tab-fila:checked ~ .atn-panes .atn-pane-fila,
#atn-tab-info:checked ~ .atn-panes .atn-pane-info{visibility:visible;
  animation:fadeUp .34s cubic-bezier(.22,1,.36,1)}
/* The checked label gets the white pill. Scoped to .panel-head because the
   rule above it is scoped to .card-head: the radios sit at .panel level and
   the labels inside the head bar, so they are never adjacent siblings and
   `input:checked + label` matches nothing here. */
#atn-tab-fila:checked ~ .panel-head label[for="atn-tab-fila"],
#atn-tab-info:checked ~ .panel-head label[for="atn-tab-info"]{
  background:#fff;color:var(--ink);font-weight:600;
  box-shadow:0 1px 3px rgba(0,0,0,.10),0 1px 1px rgba(0,0,0,.04)}
/* The switch sits at the right edge of the bar, last in the head. "Ver
   todas" carries the auto margin that pushes the pair over (from
   `.panel-head a`), so hiding that link on the notes tab cannot slide the
   switch: the seg's own auto margin takes over at the same edge. */
.atn .panel-head .seg{margin-left:auto}
/* And the link gives up its own auto margin (from `.panel-head a`), or the
   two would each claim a share of the free space and strand "Ver todas" in
   the middle of the bar. Dropped, it stays with the heading it belongs to
   and the switch keeps the whole right edge. */
.atn .panel-head .atn-all{margin-left:0}

/* Shared empty state for a panel whose list came back with nothing. */
.empty-note{padding:26px 4px;text-align:center;color:var(--ter);font-size:13.5px;font-weight:500}

/* Feed rows became links to their run. The row keeps its own layout; only the
   anchor defaults need neutralising. */
a.feed-item{color:inherit;text-decoration:none;transition:background .15s ease}
a.feed-item:hover{background:#FAFAFC}

/* Critérios page (Regras tab). Reuses .panel/.card-head/.card-body/.seg/.head/
   .mono/.ph/.btn/.chip rather than redefining them; only the vocabulary-specific
   pieces (chips per criticality, the per-rule drawer form) are new here. */
.num{text-align:right}
.btn-primary{box-shadow:0 10px 24px -8px rgba(102,45,255,.45)}

.crit-histcap{color:var(--ter);font-size:13px;font-weight:500;margin:0 0 14px}
/* Sits at the right end of the type bar, above the table rather than inside
   its header, where it read as a column heading for the rows beneath it. */
.crit-histbtn{margin-left:auto;padding:8px 14px;font-size:13px;text-decoration:none}
.crit-reason{color:var(--ter);font-size:13px;max-width:280px;display:block;margin-top:4px}
/* One line per attribute the decision moved: stacked, not comma-joined,
   because a decision that changed the criticidade, o limite e o texto reads
   as three facts and a run-on sentence hides the last two. */
.crit-change{display:block}
.crit-change+.crit-change{margin-top:4px}

.crit-table thead th:last-child,.crit-table tbody td:last-child{text-align:right}
.crit-row:hover{background:#FAFAFC}

.crit-name{font-weight:600;color:var(--ink)}

.crit-chip{display:inline-flex;align-items:center;padding:4px 10px;border-radius:999px;
  font-size:12px;font-weight:600}
.crit-chip-obrigatorio{background:var(--bad-bg);color:var(--bad)}
.crit-chip-desejavel{background:var(--warn-bg);color:var(--warn)}
.crit-chip-informativo{background:var(--accent-soft);color:var(--accent)}
.crit-chip-nao_exigido{background:var(--neu-bg);color:var(--neu)}
/* What a motivo was ruled to mean now lives in .fx-st-*, on the Fontes tab's
   own row. These four chips were the deleted table's, and the enumerated
   chip guard cannot see them: it walks `Criticality`, and blocker/warning/
   info/pendente are not members of it. */
/* Critérios page: the same tone vocabulary the Compliance page uses
   (ok/warn/bad/neutral), applied to the shared .chip pill so a source this
   page calls healthy is never a source the Compliance page calls down. */
.chip-ok{background:var(--ok-bg);color:var(--ok)}
.chip-warn{background:var(--warn-bg);color:var(--warn)}
.chip-bad{background:var(--bad-bg);color:var(--bad)}
.chip-neutral{background:var(--neu-bg);color:var(--neu)}

/* The two Fontes tables, their inline editor, their radio pills and their
   per-column widths lived here. The tab now renders .rl-* rows with a drawer
   (see "Configurações: aba Fontes" below), so every one of those rules lost
   its only consumer and went with the markup. */
.crit-pill-obrigatorio input:checked+span{background:var(--bad-bg);color:var(--bad)}
.crit-pill-desejavel input:checked+span{background:var(--warn-bg);color:var(--warn)}
.crit-pill-informativo input:checked+span{background:var(--accent-soft);color:var(--accent)}
.crit-pill-nao_exigido input:checked+span{background:var(--neu-bg);color:var(--neu)}
.crit-hist{margin:16px 0 0;padding-top:14px;border-top:1px dashed var(--line)}

/* ---------- Critérios: empty history ---------- */
.crit-empty{padding:46px 24px;text-align:center}
.crit-empty-mark{width:46px;height:46px;margin:0 auto 15px;border-radius:50%;
  border:2px dashed rgba(61,47,127,.22)}
.crit-empty b{display:block;font-size:14.5px;color:var(--ink);margin-bottom:7px}
.crit-empty p{margin:0 auto;max-width:44ch;color:var(--ter);font-size:13px;line-height:1.6}

/* ---------- Critérios: rule anchors (Regras tab) ---------- */
/* One per document type a rule spans, not just the row's first type: a
   deep link from a laudo finding must resolve to the exact rule it names.
   Zero footprint so it never disturbs the row's own layout. */
.rl-anchor{position:absolute;width:0;height:0;overflow:hidden}

/* ---------- Configurações: help popover + Regras tab filter bar --------- */
/* Hover/focus help. Focusable so it is reachable without a mouse, and it
   stays open while the pointer is inside the panel. */
.rl-help{position:relative;z-index:61;display:inline-flex;align-items:center;justify-content:center;
  width:22px;height:22px;margin-left:11px;border-radius:50%;border:1px solid var(--line);
  color:var(--ter);font-size:12.5px;font-weight:700;cursor:help;flex:none;align-self:center}
.rl-help:hover,.rl-help:focus{border-color:var(--accent);color:var(--accent);outline:none}
.rl-pop{position:absolute;top:30px;left:-8px;width:430px;max-width:78vw;z-index:200;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--shadow);padding:16px 18px;opacity:0;visibility:hidden;
  transform:translateY(-4px);transition:opacity .18s ease,transform .18s ease,visibility .18s;
  text-align:left;font-weight:400;cursor:auto}
.rl-help:hover .rl-pop,.rl-help:focus .rl-pop,.rl-pop:hover{opacity:1;visibility:visible;transform:none}
.rl-pop b{display:block;font-size:13.5px;color:var(--ink);margin-bottom:10px;letter-spacing:-.01em}
.rl-pop dl{margin:0}
.rl-pop dt{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;
  color:var(--sec);margin-top:11px}
.rl-pop dt:first-of-type{margin-top:0}
.rl-pop dd{margin:3px 0 0;font-size:12.5px;color:var(--ter);line-height:1.5}
.rl-pop dd i{font-style:normal;font-weight:600;color:var(--sec)}
.rl-pop dd b{display:inline;font-size:inherit;color:var(--ink);margin:0}
.rl-bar{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin:0 0 20px}
.rl-search{flex:1;min-width:230px;border:1px solid var(--line);border-radius:10px;padding:10px 14px;
  font:inherit;font-size:13.5px;color:var(--ink);background:var(--surface)}
.rl-search:focus{outline:2px solid var(--accent);outline-offset:-1px}
.rl-sel{border:1px solid var(--line);border-radius:10px;padding:10px 12px;font:inherit;font-size:13px;
  color:var(--ink);background:var(--surface);max-width:190px}
/* A <select> sizes itself to its widest option, and the document-type names
   here run to "Termo de Adesão — Equipamentos locados". Unbounded, that one
   control ate ~490px and pushed the effect filter onto a second row. The cap
   keeps the bar on one line; the full name is still readable once open. */
.rl-count{font-size:12.5px;color:var(--ter);margin:0 0 14px}
/* The way out of an isolated criterion. Sits inline in the tally line, so
   it is styled as text with an underline rather than as another button
   competing with the filter bar right above it. */
.rl-showall{font:inherit;color:var(--accent);background:none;border:0;padding:0;text-decoration:underline;cursor:pointer}
.rl-showall:hover{color:var(--ink)}

/* ---------- Critérios: Regras tab (rule-first reading) ---------- */
/* Four levels, each a different kind of object: the family heading sits on
   the page background, the field is a card with its own head, and the rules
   inside it are a table. The heading is un-boxed on purpose — the card head
   is also a labelled bar, and two bars would compete. */
.rl-sec{display:flex;align-items:baseline;gap:12px;margin:34px 0 12px;
  font-size:19px;font-weight:700;letter-spacing:-.02em;color:var(--ink)}
.rl-sec:first-child{margin-top:6px}
.rl-sec em{font-style:normal;margin-left:auto;font-size:12.5px;font-weight:500;
  color:var(--ter)}
/* Each field is its own card inside the family: the strip is that card's head
   and the rules under it are its list, so one subject can be read without the
   neighbouring subjects running into it. */
.rl-field{margin-bottom:10px}
.rl-field:last-child{margin-bottom:0}
.rl-fh{display:flex;align-items:center;gap:9px;padding:13px 18px 11px;
  font-size:13.5px;font-weight:700;color:var(--ink);letter-spacing:-.01em;
  border-bottom:1px solid var(--line-2)}
.rl-fh em{font-style:normal;font-size:11.5px;color:var(--ter);font-weight:500}
/* The rows are a table, so the heading reuses their exact widths and gap. */
.rl-cols{display:flex;align-items:center;gap:16px;padding:9px 18px;
  border-bottom:1px solid var(--line-2);font-size:11.5px;font-weight:600;
  color:var(--ter);letter-spacing:.01em}
.rl-cols .rl-txt{flex:1}
.rl-cols .rl-n,.rl-cols .rl-st{justify-content:flex-end}
.rl-chev-sp{flex:none;width:18px}
.rl-list .card-body{padding:0}
.rl-row{position:relative;border-bottom:1px solid var(--line-2)}
.rl-row:last-child{border-bottom:0}
/* Neutral, not accent: the expanded ground is a violet off-white, so a violet
   hover read as "this row is already open". */
.rl-row:hover{background:#F6F6F8}
.rl-row.open{background:var(--surface)}
.rl-row-off .rl-main{opacity:.55}
.rl-row-off .rl-name{text-decoration:line-through;text-decoration-thickness:1px}
.crit-chip-off{background:var(--line-2);color:var(--ter)}
.rl-retired{display:block;margin-top:9px;font-size:12.5px;color:var(--ter);line-height:1.5}
.rl-main{display:flex;align-items:center;gap:16px;padding:11px 18px;cursor:pointer}
.rl-txt{flex:1;min-width:0}
.rl-name{margin:0 0 3px;font-size:14.5px;font-weight:600;color:var(--ink);
  line-height:1.3}
.rl-sub{margin:0;font-size:12.5px;color:var(--ter)}
.rl-sub b{color:var(--sec);font-weight:600}
/* The count is the reason an analyst opened the page, so it is the one thing
   on the row that is allowed to be loud. Zero goes quiet instead of red. */
.rl-n{flex:none;width:132px;display:flex;align-items:baseline;
  justify-content:flex-end;gap:6px}
.rl-n b{font-size:19px;font-weight:700;line-height:1;color:var(--bad)}
.rl-n span{font-size:12px;color:var(--ter);white-space:nowrap}
.rl-n-zero b{color:var(--icon-muted);font-weight:600}
.rl-st{flex:none;width:118px;display:flex;justify-content:flex-end}
/* The row itself is the control, so all that is left is a direction mark. */
.rl-chev{flex:none;width:18px;text-align:center;font-size:19px;line-height:1;
  color:var(--icon-muted);
  transition:transform .3s cubic-bezier(.4,0,.2,1),color .18s ease;
  transform:rotate(90deg)}
.rl-row.open .rl-chev{transform:rotate(-90deg);color:var(--accent)}
.rl-main:hover .rl-chev{color:var(--accent)}
/* Neutral, not accent: the expanded ground is already violet, so a violet
   hover read as "this row is already open". */
.rl-row:hover{background:#F6F6F8}
.rl-row.open:hover{background:transparent}

/* ---------- Critérios: Regras tab, read-only drawer (spec sheet) ---------- */
/* Height morph: a 0fr -> 1fr grid row animates to the drawer's natural
   height without measuring it, so nothing re-renders and nothing blinks.
   The border-top only exists while open; at 0fr it would still paint 1px. */
.rl-dw{display:grid;grid-template-rows:0fr;
  transition:grid-template-rows .3s cubic-bezier(.4,0,.2,1)}
.rl-row.open .rl-dw{grid-template-rows:1fr}
.rl-dr{overflow:hidden;min-height:0;background:var(--expanded);padding:0 20px;
  transition:padding .3s cubic-bezier(.4,0,.2,1)}
.rl-row.open .rl-dr{padding:18px 20px 20px;border-top:1px solid var(--line);
  box-shadow:inset 0 8px 12px -12px rgba(61,47,127,.16)}
/* Every row is the same three columns, so the labels line up down the whole
   sheet and Phase 2's per-row edit toggle drops into the third without
   shifting anything. The hairline between rows is what separates them; the
   sheet needs no fills. */
.rl-spec{display:grid}
.rl-r{display:grid;grid-template-columns:118px minmax(0,1fr) auto;gap:22px;
  padding:13px 0;border-top:1px solid var(--line-2);align-items:start}
.rl-r:first-child{border-top:0;padding-top:2px}
.rl-rk{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ter);padding-top:2px}
/* Prose, not a stack: the derived sentence carries inline <b>, and a flex
   column would make every bold span its own line and break the sentence at
   the wrong points. Anything that genuinely stacks says so below. */
.rl-rv{font-size:13px;color:var(--sec);line-height:1.6;min-width:0}
.rl-rv b{color:var(--ink);font-weight:600}
.rl-ra{display:flex;justify-content:flex-end}
@media (max-width:760px){
  .rl-r{grid-template-columns:1fr auto;gap:4px 12px}
  .rl-rk{grid-column:1}.rl-ra{grid-column:2;grid-row:1}
  .rl-rv{grid-column:1/-1}}
.rl-rv>.rl-unread,.rl-rv>.rl-hl,.rl-rv>.rl-dead,.rl-rv>.rl-why{display:block}
.rl-rv>.rl-unread+.rl-unread,.rl-rv>.rl-dead,.rl-rv>.rl-why{margin-top:6px}
.rl-unread{color:var(--bad-ink)}
.rl-unread b{color:var(--bad)}
.rl-hl{color:var(--ink)}
.rl-hl .ok{color:var(--ok)}
.rl-hl .bad{color:var(--bad)}
.rl-hl .skip{color:var(--neu)}
.rl-dead{color:var(--bad)}
.rl-dead b{color:var(--bad)}
.rl-dead-soft{color:var(--warn)}
.rl-why{color:var(--ter);font-style:italic}
.rl-rv-note{display:block;margin-bottom:5px;color:var(--ter);font-size:11.5px}
/* The stacked proportion bar the legend below it describes in words. Reading
   "402 passou · 75 reprovou" as a shape is what makes a lopsided rule visible
   at a glance instead of arithmetic the analyst has to do. */
.rl-hb{display:flex;height:7px;border-radius:4px;overflow:hidden;
  background:var(--line-2);margin-bottom:9px}
.rl-hb i{display:block;height:100%}
.rl-hb .ok{background:var(--ok-ico)}
.rl-hb .bad{background:var(--bad)}
.rl-hb .skip{background:var(--icon-muted)}
.rl-ev{display:flex;align-items:center;gap:10px;margin-top:4px}
/* Wider than the mock's 132px because the real document-type names run to
   "Termo de Adesão de Conectividade (Serviços Arqia)", where 132px wrapped
   them to three lines and dragged the bar out of alignment with its row. */
.rl-ev-t{width:210px;flex:none;color:var(--ink);font-weight:500;line-height:1.35}
.rl-ev-bar{flex:1;max-width:210px;height:6px;border-radius:999px;background:var(--sunken);
  overflow:hidden}
.rl-ev-bar i{display:block;height:100%;border-radius:999px;
  background:var(--bad-ico)}
.rl-ev-n{width:80px;flex:none;color:var(--ter)}
.rl-ev-p{width:42px;flex:none;text-align:right;color:var(--ink);font-weight:600}
.rl-ev-read{margin:9px 0 0;font-size:12.5px;color:var(--sec);line-height:1.5}
.rl-ev-read b{color:var(--bad);font-weight:700}
/* The quote chips under one type's bar. Links, because the whole point is
   that the analyst can open the contracts the rate is made of. */
.rl-ev-q{margin:8px 0 2px;display:flex;gap:7px;flex-wrap:wrap;padding-left:220px}
.rl-ev-q a,.rl-ev-q .rl-ev-more{font-size:11.5px;font-weight:600;padding:4px 10px;
  border-radius:999px;border:1px solid var(--line);color:var(--sec);
  background:var(--surface);text-decoration:none;white-space:nowrap}
.rl-ev-q a:hover{border-color:var(--accent);color:var(--accent)}
.rl-ev-q .rl-ev-more{border-style:dashed;color:var(--ter)}
/* One rule's own decision trail, inside the "Origem" row's disclosure. */
.rl-hist{display:flex;flex-direction:column;gap:10px}
/* NOT `.rl-hb`: that is the health proportion bar (height:7px, a flex row
   of three coloured slivers). Reusing it here rendered each decision as a
   7px stripe. */
.rl-he{display:flex;flex-direction:column;gap:2px;padding-left:11px;
  border-left:2px solid var(--line)}
.rl-he-w{font-size:11.5px;color:var(--ter)}
.rl-he-c{font-size:12.5px;color:var(--ink)}
.rl-he-r{font-size:12.5px;color:var(--sec);font-style:italic}
.rl-tt{display:inline-flex;align-items:center;margin:0 6px 6px 0;padding:4px 10px;
  border-radius:999px;font-size:12px;background:var(--accent-soft);
  color:var(--accent)}
.rl-said{color:var(--ink);font-style:italic}
.rl-said-note{display:block;margin-top:4px;font-size:12.5px;color:var(--ter)}

/* ---------- Critérios: Regras tab, drawer row editors (Phase 2 Task 8) ---------- */
/* The `editar` toggle on each editable row's third column; the row's own
   editor panel below it stays `hidden` until Task 9's JS flips it. */
.rl-edit{font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  color:var(--accent);background:none;border:0;padding:3px 8px;border-radius:7px;
  cursor:pointer;font-family:inherit}
.rl-edit:hover{background:var(--accent-soft)}
/* Section headers inside a row's own editor: a step label (uppercase,
   ruled above) for a whole block, a quieter sub-step label for a nested
   group inside it (numbers under criticidade, exceptions under either). */
.rl-lab{display:block;font-size:11px;font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:var(--sec);margin:20px 0 11px;
  padding-top:15px;border-top:1px solid var(--line)}
.rl-commit>.rl-lab:first-of-type{margin-top:16px}
.rl-lab-sub{display:block;margin:12px 0 7px;font-size:11px;font-weight:600;
  letter-spacing:.05em;text-transform:uppercase;color:var(--ter)}
.rl-lab-sub:first-child{margin-top:0}
/* Criticidade / a labelled row that holds a control. */
.rl-pol{display:flex;align-items:center;gap:14px;padding:0;flex-wrap:wrap}
.rl-pol>span:first-child{font-size:13px;color:var(--sec);min-width:150px}
.rl-pills{display:flex;gap:6px;flex-wrap:wrap}
.rl-p{position:relative;font-size:12px;font-weight:600;padding:6px 12px;
  border-radius:8px;border:1px solid var(--line);color:var(--ter);
  background:var(--surface);cursor:pointer;user-select:none}
.rl-p input{position:absolute;inset:0;margin:0;opacity:0;cursor:pointer}
.rl-p.on.obrigatorio,.rl-p:has(input:checked).obrigatorio{
  background:var(--bad-bg);border-color:var(--bad);color:var(--bad)}
.rl-p.on.desejavel,.rl-p:has(input:checked).desejavel{
  background:var(--warn-bg);border-color:var(--warn);color:var(--warn)}
.rl-p.on.informativo,.rl-p:has(input:checked).informativo{
  background:var(--accent-soft);border-color:var(--accent);color:var(--accent)}
.rl-p.on.nao_exigido,.rl-p:has(input:checked).nao_exigido{
  background:var(--neu-bg);border-color:var(--neu);color:var(--neu)}
/* One diverging type: its own name, its (locked) pills, and the note that
   it keeps its own stance. Phase 3 wires the pills live and the remove;
   here they are read-only, which is why there is no `.rl-x`. */
/* A grid, not a wrapping flex row: with flex, a long document type name
   ("Termo de Adesão de Licença de Uso de Software (Plataforma Starlink)")
   pushed the "x" onto a line of its own, where it read as a stray glyph
   rather than that row's control. Three columns keep it beside its pills. */
.rl-exc{display:grid;grid-template-columns:minmax(150px,1fr) auto auto;
  align-items:center;gap:12px;padding:9px 0;
  border-bottom:1px solid var(--line-2)}
.rl-exc:first-child{padding-top:0}
.rl-exc>span:first-child{font-size:13px;color:var(--ink);font-weight:600;
  line-height:1.35}
/* The pills in an exception row are real radios now, so they take the same
   pointer as every other choosable pill. They were `cursor:default` while
   the row was a locked read-only display. */
.rl-exc .rl-p{cursor:pointer}
.rl-exc .rl-en{font-size:11.5px;color:var(--ter)}
/* A type that follows the general criticality is not an exception, so it
   stays out of the list until "+ um tipo" reveals it: a rule spanning
   twelve types would otherwise open as twelve rows of pills. */
.rl-exc-off{display:none}
.rl-x{margin-left:auto;color:var(--ter);cursor:pointer;font-size:17px;
  line-height:1;padding:0 6px;border:0;background:transparent;font-family:inherit}
.rl-x:hover{color:var(--bad)}
.rl-add{margin:12px 0 4px;font-size:12.5px;color:var(--accent);cursor:pointer;
  background:transparent;font-weight:600;display:inline-block;border:0;
  padding:0;font-family:inherit}
/* Air between the exception list and the locked Campo / Tipo de checagem
   block that follows it, which otherwise butts straight up against the
   "+ um tipo" button and reads as part of the same control. */
.rl-add + .rl-dl-lock{margin-top:16px;padding-top:14px;
  border-top:1px solid var(--line-2)}
.rl-add:hover{text-decoration:underline}
/* The types this policy applies to, and the types it cannot (no row to
   tick). Each is a `.rl-pol` row so it shares the label column with the
   criticidade control above it. */
.rl-types-edit{display:flex;flex-direction:column;gap:2px}
.rl-off{color:var(--ter);font-size:11.5px;font-style:italic}
.rl-selbar{display:flex;align-items:center;gap:10px;margin-bottom:9px}
.rl-selbar .rl-lab-sub{margin-right:auto}
.rl-params{display:flex;gap:12px;margin-top:0;flex-wrap:wrap}
.rl-par{display:flex;flex-direction:column;gap:5px}
.rl-par span{font-size:11px;font-weight:600;color:var(--ter);
  text-transform:uppercase;letter-spacing:.05em}
.rl-in{border:1px solid var(--line);border-radius:9px;padding:8px 11px;
  font:inherit;font-size:13px;color:var(--ink);background:var(--surface);
  width:130px}
.rl-ta{width:100%;margin-top:0;border:1px solid var(--line);border-radius:10px;
  padding:10px 13px;font:inherit;font-size:13px;color:var(--ink);
  background:var(--surface);resize:vertical}
.rl-hint{font-size:11.5px;color:var(--ter);margin:8px 0 0;font-style:normal}
.rl-say{font-size:13px;color:var(--sec);line-height:1.6;margin:0 0 9px}
.rl-say b{color:var(--ink);font-weight:600}
.rl-say-exc{padding-left:12px;border-left:2px solid var(--warn);color:var(--ter)}
.rl-ed-err{margin-top:6px;color:var(--bad);font-size:12.5px}
.rl-dl{display:grid;grid-template-columns:auto 1fr;gap:5px 14px;margin:0;
  font-size:12.5px}
.rl-dl dt{color:var(--ter);font-weight:600}
.rl-dl dd{margin:0;color:var(--sec)}
.rl-dl-lock{margin-bottom:16px;padding-bottom:14px;
  border-bottom:1px solid var(--line-2);gap:8px 14px}
.rl-dl-lock dd{color:var(--ink);font-weight:600}
.rl-lock{display:inline-block;margin-left:8px;font-size:11px;font-weight:500;color:var(--ter);
  font-style:italic}
.rl-lock-btn{font-style:normal;color:var(--accent);background:none;border:0;padding:0;
  cursor:pointer;font-family:inherit;text-decoration:underline}
.rl-lock-form{display:inline}
.rl-note-ext{font-size:12.5px;color:var(--warn);margin:0;line-height:1.5}
.rl-note-ext i{font-style:italic}
.rl-commit{margin-top:18px;padding-top:16px;border-top:1px solid var(--line)}
.rl-eff{margin-top:20px;padding:13px 16px;border-radius:10px;font-size:13px;
  line-height:1.5;border:1px solid var(--line);background:var(--neu-bg);
  color:var(--ter)}
.rl-eff:empty{display:none}
.rl-eff.quiet{background:var(--surface);border-color:var(--line);color:var(--ter)}
.rl-eff.ok{background:var(--ok-bg);border-color:rgba(11,107,65,.28);color:var(--ok)}
.rl-eff.warn{background:var(--warn-bg);border-color:rgba(122,91,0,.32);color:var(--warn)}
.rl-acts{margin-top:14px;display:flex;align-items:center;justify-content:flex-end;
  gap:12px;flex-wrap:wrap}
.rl-link{font-size:13px;font-weight:600;padding:7px 15px;border-radius:10px;
  background:var(--surface);color:var(--ink);border:1px solid var(--line);
  cursor:pointer;font-family:inherit;transition:background .15s}
.rl-link:hover{background:var(--sunken)}
.rl-link-sm{font-size:12px;padding:4px 11px;margin-top:8px}

/* Creation wizard: opens the field-heading "+ regra em outro campo" button,
   Campo and Checagem steps. Ported verbatim from tmp/settings-mock/index.html. */
.rl-fadd{font-size:13px;font-weight:600;color:#fff;background:var(--accent);border:0;
  padding:8px 16px;border-radius:10px;cursor:pointer;font-family:inherit;letter-spacing:-.01em;
  transition:filter .2s ease,transform .25s cubic-bezier(.34,1.4,.5,1),box-shadow .2s ease}
.rl-fadd:hover{transform:translateY(-1px);filter:brightness(1.07);box-shadow:0 6px 18px rgba(94,46,230,.28)}
.rl-fadd:active{transform:scale(.97)}
.rl-sec .rl-fadd{margin-left:0}
.rl-fw{display:grid;grid-template-rows:0fr;transition:grid-template-rows .3s cubic-bezier(.4,0,.2,1)}
.rl-fw.open{grid-template-rows:1fr}
.rl-form{overflow:hidden;min-height:0;background:var(--expanded);border:1px solid transparent;
  border-radius:var(--r);margin:0;padding:0 20px;box-shadow:var(--shadow);
  transition:padding .3s cubic-bezier(.4,0,.2,1),margin .3s cubic-bezier(.4,0,.2,1),border-color .3s ease}
.rl-fw.open .rl-form{padding:18px 20px;margin:0 0 14px;border-color:var(--line)}
.rl-fsel{width:100%;max-width:420px;background:var(--surface)}
.rl-steps{display:flex;list-style:none;margin:0 0 18px;padding:0 0 14px;gap:6px;
  border-bottom:1px solid var(--line);flex-wrap:wrap}
.rl-steps li{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--ter);
  padding:5px 12px 5px 6px;border-radius:999px}
.rl-steps li b{display:inline-flex;align-items:center;justify-content:center;width:21px;height:21px;
  border-radius:50%;background:var(--line-2);color:var(--ter);font-size:11.5px;font-weight:700}
.rl-steps li.on{color:var(--ink);font-weight:600}
.rl-steps li.on b{background:var(--accent);color:#fff}
.rl-steps li.done{color:var(--sec);cursor:pointer}
.rl-steps li.done b{background:var(--ok-bg);color:var(--ok)}
.rl-steps li.done:hover{background:var(--accent-soft)}
.rl-about{font-size:12.5px;color:var(--sec);margin:0 0 18px;padding:0 0 14px;
  border-bottom:1px solid var(--line-2);line-height:1.5}
.rl-about b{color:var(--ink);font-weight:600}
.rl-empty{padding:22px;text-align:center;color:var(--ter);font-size:13px}
.rl-picks{display:flex;gap:7px;flex-wrap:wrap}
.rl-pk{font-size:12px;font-weight:600;padding:6px 12px;border-radius:999px;border:1px solid var(--line);
  background:var(--surface);color:var(--sec);cursor:pointer;user-select:none;display:inline-block}
.rl-pk:hover{border-color:var(--accent);color:var(--accent)}
.rl-pk.on{background:var(--accent);border-color:var(--accent);color:#fff}
.rl-pk-new{border-style:dashed;color:var(--ok);border-color:rgba(11,107,65,.35)}
.rl-pk-new:hover{background:var(--ok-bg);border-color:var(--ok);color:var(--ok)}
.rl-cen{margin-top:12px;border:1px solid var(--line);border-radius:10px;padding:12px 14px;
  background:var(--surface)}
.rl-cen-r{display:flex;align-items:center;gap:11px;padding:4px 0;font-size:12.5px;color:var(--sec)}
.rl-cen-t{width:118px;flex:none}
.rl-cen-b{flex:1;max-width:190px;height:6px;border-radius:3px;overflow:hidden;display:flex;
  background:var(--line-2)}
.rl-cen-b i{display:block;height:100%}
.rl-cen-b .fill{background:var(--ok-ico)}
.rl-cen-b .empty{background:var(--warn-ico)}
.rl-cen-b .abs{background:var(--icon-muted)}
.rl-cen-n{font-size:11.5px;color:var(--ter);white-space:nowrap}
.rl-cen-leg{margin-top:8px;font-size:11.5px;color:var(--ter)}
.rl-cen-leg i{display:inline-block;width:8px;height:8px;border-radius:2px;margin:0 4px 0 10px}
.rl-cen-leg i:first-child{margin-left:0}
/* The legend's own swatches. The colours live on `.rl-cen-b .fill` etc.,
   scoped to the bar, so the legend rendered three invisible squares and
   the labels named colours nothing on screen actually showed. */
.rl-cen-leg .fill{background:var(--ok-ico)}
.rl-cen-leg .empty{background:var(--warn-ico)}
.rl-cen-leg .abs{background:var(--icon-muted)}
.rl-block{margin-top:12px;padding:12px 14px;border-radius:10px;background:var(--bad-bg);
  border:1px solid rgba(217,10,102,.3);color:var(--bad-ink);font-size:12.5px;line-height:1.55}
/* A completed step's rail entry has no click handler: the wizard is walked
   through its own pills and links, not by clicking back into the rail. This
   modifier strips the pointer cursor and hover feedback the base
   .rl-steps li.done rule carries, so the rail does not look like a live
   control it is not. .rl-picks.rl-inert has no user left (every pick step
   is wired), but stays available for a future read-only pick list. */
.rl-picks.rl-inert .rl-pk{cursor:default}
.rl-picks.rl-inert .rl-pk:hover{border-color:var(--line);color:var(--sec)}
.rl-steps.rl-inert li.done{cursor:default}
.rl-steps.rl-inert li.done:hover{background:none}
.rl-block b{color:var(--bad)}
.rl-ext{margin-top:18px;padding:14px 0 0;border-top:1px solid var(--line-2)}
.rl-ext p{margin:0 0 8px;font-size:12.5px;color:var(--warn);line-height:1.5}

/* A disclosure, not a permanent dump: "Onde vale" on a rule spanning seven
   document types printed four rows of chips and pushed every section below
   it off the screen. Closed it is one line; open it is the same chips. */
.rl-tech{margin-top:10px}
.rl-tech summary{display:inline-flex;align-items:center;gap:6px;font-size:12px;
  font-weight:600;color:var(--sec);cursor:pointer;list-style:none;
  border:1px solid var(--line);border-radius:8px;padding:6px 12px;
  background:var(--surface);width:max-content;
  transition:border-color .18s ease,color .18s ease}
.rl-tech summary::-webkit-details-marker{display:none}
.rl-tech summary::after{content:"\203A";font-size:14px;line-height:1;
  color:var(--icon-muted);transform:rotate(90deg);
  transition:transform .25s cubic-bezier(.4,0,.2,1),color .18s ease}
.rl-tech[open] summary::after{transform:rotate(-90deg)}
.rl-tech summary:hover{border-color:var(--accent);color:var(--accent)}
.rl-tech summary:hover::after{color:var(--accent)}
.rl-tech>*:not(summary){margin-top:11px}
.rl-off-say{display:block;margin-top:5px;color:var(--ter)}
/* The chips inside the disclosure above. Distinct from `.rl-types-edit`,
   which is the tick list the editor renders. */
.rl-types{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}
/* A floor under the step body so the box does not resize on every step,
   which made the Continuar button jump under the cursor between steps. */
.rl-step-body{min-height:132px}
.rl-step-body>.rl-lab:first-child{margin-top:0;padding-top:0;border-top:0}

/* ---------- Configurações: aba Fontes ---------- */
/* Structure is borrowed from the Regras tab (.rl-sec, .rl-field, .rl-list,
   .rl-row, .rl-main, .rl-txt, .rl-n, .rl-st, .rl-chev, .rl-dw, .rl-dr,
   .rl-spec, .rl-r, .rl-edit, .rl-pills, .rl-p, .rl-commit, .rl-lab, .rl-ta,
   .rl-acts, .rl-link) and is NOT restyled here: Regras already decides how
   those look, and a second opinion is how two tabs drift apart. */
.fx-card{margin-bottom:10px}
/* The register's name carries a marker when it matches by name rather than
   by CNPJ, because that is why its findings are capped. */
.fx-badge{margin-left:9px;font-size:10.5px;font-weight:600;color:var(--ter);
  background:var(--neu-bg);padding:3px 9px;border-radius:999px;
  white-space:nowrap;letter-spacing:0;text-transform:none}
.fx-pend{color:var(--accent)}
/* The decision cell: what the motivo does today, and nothing else. */
.fx-dec{display:flex;justify-content:flex-end}
.fx-st{font-size:11px;font-weight:700;padding:4px 10px;border-radius:8px;
  white-space:nowrap}
.fx-st-blocker{background:var(--bad-bg);color:var(--bad)}
.fx-st-warning{background:var(--warn-bg);color:var(--warn)}
.fx-st-info{background:var(--neu-bg);color:var(--neu)}
.fx-st-sem{background:var(--bad);color:#fff}
/* A row whose second half is still open. Only the chevron's colour says so:
   the missing half changes nothing today, and the row is not the place to
   answer the question anyway. */
.fx-row-pending .rl-chev{color:var(--accent)}
.fx-flag{color:var(--accent);font-weight:600}
.fx-undec{color:var(--accent)}
.rl-rv-note{display:block;margin-bottom:8px;font-size:11.5px;color:var(--ter)}
/* What the sanction means in practice. Reads as reference, not as a control:
   no weight, no colour, just the paragraph an analyst needs before deciding. */
.fx-meaning{color:var(--sec);line-height:1.65}
/* What the save will do, stated. It borrowed .rl-eff.quiet — white fill, thin
   border, full width, directly above the textarea — and read as a second
   input. A tinted panel with no border and a standing label cannot be
   mistaken for a field. */
.fx-eff{border:0;background:var(--accent-soft);color:var(--ink);
  padding:12px 16px 13px;line-height:1.55;font-weight:500}
.fx-eff:empty{display:none}
.fx-eff::before{content:"Ao salvar";display:block;margin-bottom:4px;
  font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--accent)}
/* Registers that never matched anybody: a list, not a queue. */
.fx-quiet{padding:16px 18px 6px}
.fx-qhead{font-size:12.5px;font-weight:500;color:var(--ter);line-height:1.5}
.fx-qtable{width:100%;border-collapse:collapse;margin-top:12px}
.fx-qtable th{text-align:left;font-size:10.5px;font-weight:700;
  letter-spacing:.05em;text-transform:uppercase;color:var(--ter);
  padding:8px 12px;border-bottom:1px solid var(--line)}
.fx-qtable td{padding:12px;border-top:1px solid var(--line-2);font-size:13px}
.fx-qtable th:first-child,.fx-qtable td:first-child{padding-left:0}
.fx-qname{font-weight:600;letter-spacing:-.01em;color:var(--ink)}

/* Empty state for the reason list on Configurações. The KPI card that used
   to share the .dr- family now renders as a bar card (.dr-card), so this is
   all that is left of it. */
.dr-empty { padding: 0 22px 18px; font-size: 13px; opacity: .7; }
.rsn-row { display: grid; grid-template-columns: 1fr auto auto auto auto; gap: 12px;
  align-items: center; padding: 9px 22px; font-size: 13px;
  border-top: 1px solid rgba(0,0,0,.06); }
.rsn-row.off .rsn-text { opacity: .5; text-decoration: line-through; }
.rsn-kind, .rsn-usage, .rsn-who { font-size: 11px; opacity: .7;
  font-variant-numeric: tabular-nums; }
.rsn-intro { margin: 0; padding: 0 22px 14px; font-size: 12px; opacity: .8; }
.cost-badge { font-size: 10px; color: var(--muted); border: 1px solid var(--line-2); border-radius: 4px; padding: 2px 5px; }
.cost-details { position: relative; margin-top: 6px; font-size: 11px; }
.cost-details summary { cursor: pointer; width: fit-content; }
.cost-details-panel { position: absolute; bottom: calc(100% + 8px); left: 0; z-index: 10; width: 300px; max-width: 70vw; padding: 12px; border: 1px solid var(--line-2); border-radius: 8px; background: var(--surface, #fff); box-shadow: 0 4px 16px #0002; }
.cost-details-panel p { margin: 0; }
.cost-details-panel p + p { margin-top: 8px; }
