/*
 * Stylesheet for the whole panel. The only asset public_html/ is allowed to serve
 * besides index.php and webhook.php (see CLAUDE.md's structural rule).
 *
 * No external request of any kind: no CDN, no remote font, no @import of anything
 * off this origin. Content-Security-Policy in App\Http\Response has no
 * 'unsafe-inline', so this file is also the ONLY place any screen in this panel
 * may declare style — no template may carry a style="" attribute, ever.
 */

:root {
    --color-bg: #f4f5f7;
    --color-surface: #ffffff;
    --color-border: #d7dbe0;
    --color-text: #1f2430;
    --color-text-muted: #5b6472;
    --color-primary: #1d5b8f;
    --color-primary-hover: #164a75;
    --color-danger: #9b2c2c;
    --color-danger-bg: #fbe9e9;
    --radius: 6px;
    --font-body: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    /* For identifiers only. A UUID is read by comparing it to another one, character
     * by character — a job proportional glyphs actively obstruct. Local faces only,
     * like every other asset here: no font is ever fetched off this origin. */
    --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
    /* Series colours for the evolution screen. Eight, because funnel_stage is opaque
     * text (rule 8) and the number of stages is whatever the Hub decides — the ninth
     * series reuses the first colour rather than rendering invisible. Chosen dark
     * enough to read as a 2px stroke on white, and far enough apart in hue AND
     * lightness that the chart survives being printed or read without colour. */
    --chart-0: #1d5b8f;
    --chart-1: #b4590a;
    --chart-2: #2c7a52;
    --chart-3: #77389b;
    --chart-4: #9b2c2c;
    --chart-5: #0d6b76;
    --chart-6: #6a6a12;
    --chart-7: #8a4168;
    --chart-grid: #e6e9ee;
}

* {
    box-sizing: border-box;
}

html,
body {
    margin: 0;
    padding: 0;
    height: 100%;
}

/* Every screen is one column exactly as tall as the viewport: whatever sits at the
 * top (the app header) takes what it needs, and the screen below it takes the rest.
 * This is the top of the chain that lets .table-wrap be "the space that is left"
 * instead of a hand-measured height — see the comment there. */
body {
    background: var(--color-bg);
    color: var(--color-text);
    font-family: var(--font-body);
    font-size: 16px;
    line-height: 1.5;
    display: flex;
    flex-direction: column;
}

h1 {
    font-size: 1.375rem;
    margin: 0 0 1.25rem;
    color: var(--color-text);
}

p {
    margin: 0 0 1rem;
}

/* ----------------------------------------------------------------- login screen */

.login-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
}

.login-form {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 2rem;
    width: 100%;
    max-width: 22rem;
    display: flex;
    flex-direction: column;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

.login-form label {
    font-size: 0.875rem;
    font-weight: 600;
    margin: 0.75rem 0 0.25rem;
}

.login-form input[type="text"],
.login-form input[type="password"] {
    font: inherit;
    padding: 0.5rem 0.625rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    color: var(--color-text);
}

.login-form input[type="text"]:focus,
.login-form input[type="password"]:focus {
    outline: 2px solid var(--color-primary);
    outline-offset: 1px;
}

.login-form button {
    margin-top: 1.5rem;
    font: inherit;
    font-weight: 600;
    padding: 0.625rem 1rem;
    border: none;
    border-radius: var(--radius);
    background: var(--color-primary);
    color: #ffffff;
    cursor: pointer;
}

.login-form button:hover {
    background: var(--color-primary-hover);
}

.login-form__error {
    background: var(--color-danger-bg);
    color: var(--color-danger);
    border-radius: var(--radius);
    padding: 0.625rem 0.75rem;
    font-size: 0.9375rem;
    margin: 0 0 0.5rem;
}

/* ------------------------------------------------------------------ app screens */

.app-header {
    flex: none;
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-border);
    padding: 0.875rem 1.5rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.logout-form button {
    font: inherit;
    padding: 0.375rem 0.875rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    color: var(--color-text);
    cursor: pointer;
}

.logout-form button:hover {
    background: var(--color-bg);
}

/* ---------------------------------------------------------------- error screens */

/* These pages carry the app header now, so the panel is recognisable from a stale
 * bookmark instead of looking like a stray server error page — hence `flex: 1`
 * against the body column rather than a 100vh that would push the text below the
 * header it now sits under. */
.error-page {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 1.5rem;
    color: var(--color-text-muted);
}

.error-page__back {
    color: var(--color-primary);
    text-decoration: none;
}

.error-page__back:hover {
    text-decoration: underline;
}

/* ------------------------------------------------------------------ leads screen
 *
 * Density is the requirement, not a taste: the stakeholder opens this to sweep the
 * list, find who to approach and fire off the conversation. Small type, tight rows,
 * a sticky header, and the two contact buttons always in the same place on every
 * line so the eye never has to hunt for them.
 *
 * No style="" anywhere in app/Views/leads.php — the CSP has no unsafe-inline, so
 * every rule below has to reach the markup through a class. No @import, no font, no
 * image: the page shows 258 real people, and any third-party request would tell the
 * third party that someone is looking at them.
 */

.leads {
    padding: 1rem 1.25rem 1.25rem;
    max-width: 110rem;
    margin: 0 auto;
    width: 100%;
    flex: 1;
    display: flex;
    flex-direction: column;
    /* min-height: 0 is load-bearing, not defensive. A flex item's automatic minimum
     * size is its content, so without this the 50-row table would refuse to shrink,
     * push this column past the viewport, and give the page its own scrollbar next to
     * the table's — two bars for one list. */
    min-height: 0;
}

/* ------- counter strip: the population, never the filtered slice */

.counters {
    flex: none;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1.75rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 0.75rem 1rem;
    margin-bottom: 0.75rem;
}

.counter {
    display: flex;
    align-items: baseline;
    gap: 0.375rem;
}

.counter__value {
    font-size: 1.125rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.counter--lead .counter__value {
    font-size: 1.5rem;
    color: var(--color-primary);
}

.counter__label {
    font-size: 0.8125rem;
    color: var(--color-text-muted);
}

.counters__stages {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
    margin-left: auto;
}

.stage-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.125rem 0.5rem;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    background: var(--color-bg);
    color: var(--color-text-muted);
    text-decoration: none;
    font-size: 0.75rem;
    letter-spacing: 0.01em;
}

.stage-chip:hover {
    border-color: var(--color-primary);
    color: var(--color-primary);
}

.stage-chip--on {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: #ffffff;
}

.stage-chip__count {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* ------- filter bar: one POST form, filters and search together */

.filters {
    flex: none;
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 0.5rem 0.75rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 0.75rem 1rem;
    margin-bottom: 0.75rem;
}

.filters__field {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
}

.filters__field--wide {
    flex: 1 1 18rem;
}

.filters label {
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-muted);
}

.filters input,
.filters select {
    font: inherit;
    font-size: 0.875rem;
    padding: 0.3125rem 0.5rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    color: var(--color-text);
}

.filters input:focus,
.filters select:focus {
    outline: 2px solid var(--color-primary);
    outline-offset: 1px;
}

.filters__actions {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.filters__actions button {
    font: inherit;
    font-size: 0.875rem;
    font-weight: 600;
    padding: 0.375rem 1.125rem;
    border: none;
    border-radius: var(--radius);
    background: var(--color-primary);
    color: #ffffff;
    cursor: pointer;
}

.filters__actions button:hover {
    background: var(--color-primary-hover);
}

.filters__reset {
    font-size: 0.8125rem;
    color: var(--color-text-muted);
}

/* ------- result count and pagination */

.results-bar {
    flex: none;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 1rem;
    margin: 0 0 0.5rem;
}

.results-count {
    margin: 0;
    font-size: 0.875rem;
    color: var(--color-text-muted);
}

.results-count strong {
    font-size: 1.0625rem;
    color: var(--color-text);
    font-variant-numeric: tabular-nums;
}

/* Secondary next to the result count: this is a side door, not the thing the
   screen is for. It exports the slice the number beside it counts. */
.export-link {
    /* Hugs the result count instead of floating in the middle of the bar: it exports
       that number, and space-between alone would centre it between count and pager. */
    margin-right: auto;
    padding: 0.1875rem 0.625rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--color-text-muted);
    text-decoration: none;
    white-space: nowrap;
}

.export-link:hover {
    color: var(--color-text);
    border-color: var(--color-text-muted);
}

.pager {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.8125rem;
}

.pager__link {
    padding: 0.1875rem 0.5rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    text-decoration: none;
    color: var(--color-primary);
    white-space: nowrap;
}

.pager__link:hover {
    background: var(--color-bg);
}

.pager__link--off {
    color: var(--color-border);
    background: var(--color-bg);
}

.pager__position {
    color: var(--color-text-muted);
    white-space: nowrap;
}

/* ------- the table itself */

/* The table scrolls INSIDE this box rather than with the page, and the box is
 * whatever height the flex column above it has left over. That is what makes
 * `position: sticky` on the header row actually engage: sticky resolves against its
 * nearest scrolling ancestor, and a wrapper that only scrolls horizontally (no
 * height cap) never scrolls vertically, so the header silently never sticks. Losing
 * the column headers at row 40 of a 50-row page is exactly the friction this screen
 * cannot afford — and keeping the counter strip, the filter bar and the pager pinned
 * above the box means none of them has to be scrolled back to either.
 *
 * The height comes from `flex: 1` against html/body/.leads, NOT from a calc() against
 * the viewport. A calc() has to encode how tall the frame above happens to be today,
 * and the number it encoded was 15rem against a frame that really occupies ~284px —
 * so the page grew ~92px of scroll of its own on top of the table's, and every edit
 * to the counter strip or the filter bar silently moved the error again. Flex asks
 * the browser instead of guessing.
 *
 * min-height caps how far the box may be squeezed on a short window: past that the
 * page scrolls, which is the right trade — a table box shorter than a few rows is
 * not a table anyone can read. */
.table-wrap {
    flex: 1;
    min-height: 6rem;
    overflow: auto;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
}

.leads-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.8125rem;
    line-height: 1.35;
}

.leads-table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--color-bg);
    /* inset shadow, not border-bottom: with border-collapse: collapse a sticky
     * header's own border scrolls away with the cells it was collapsed into. */
    box-shadow: inset 0 -1px 0 var(--color-border);
    text-align: left;
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-muted);
    padding: 0.4375rem 0.625rem;
    white-space: nowrap;
}

.leads-table th.th-sortable a {
    color: inherit;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
}

.leads-table th.th-sortable a:hover {
    color: var(--color-primary);
}

.leads-table th.th-sortable--on {
    color: var(--color-primary);
}

.th-sortable__arrow {
    font-size: 0.625rem;
}

.leads-table tbody td {
    padding: 0.3125rem 0.625rem;
    border-bottom: 1px solid var(--color-bg);
    vertical-align: middle;
    white-space: nowrap;
}

.leads-table tbody tr:nth-child(even) {
    background: #fafbfc;
}

.leads-table tbody tr:hover {
    background: #eef4fa;
}

.leads-table td.num {
    font-variant-numeric: tabular-nums;
}

.leads-table td[data-column="name"] {
    font-weight: 600;
    max-width: 16rem;
    overflow: hidden;
    text-overflow: ellipsis;
}

.leads-table td[data-column="email"],
.leads-table td[data-column="referrer"] {
    max-width: 15rem;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--color-text-muted);
}

.leads-table td[data-column="stage"] {
    font-size: 0.6875rem;
    letter-spacing: 0.02em;
    color: var(--color-text-muted);
}

/* ------- contact buttons: the point of the whole screen */

.contact {
    display: flex;
    gap: 0.25rem;
}

.btn {
    display: inline-block;
    padding: 0.125rem 0.5rem;
    border-radius: var(--radius);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-decoration: none;
    white-space: nowrap;
    border: 1px solid transparent;
}

.btn--wa {
    background: #0f7a4b;
    color: #ffffff;
}

.btn--wa:hover {
    background: #0b5f3a;
}

.btn--mail {
    background: var(--color-surface);
    border-color: var(--color-border);
    color: var(--color-primary);
}

.btn--mail:hover {
    background: var(--color-bg);
}

/* Phone-less is a third of the base and a normal state (rule 9) — the button stays
 * in place, visibly unavailable, instead of vanishing and shifting the column. */
.btn--off {
    background: var(--color-bg);
    border-color: var(--color-border);
    color: #a6adb7;
    cursor: not-allowed;
}

/* ------- empty state: never a blank rectangle */

.empty-state {
    margin: 0;
    padding: 2rem 1.25rem;
    text-align: center;
    color: var(--color-text-muted);
    font-size: 0.9375rem;
}

/* ------- header additions for the app screens */

.app-header__brand {
    font-weight: 700;
}

.app-header__nav {
    margin-right: auto;
    padding-left: 1.25rem;
}

.app-header__here {
    font-size: 0.875rem;
    color: var(--color-primary);
    font-weight: 600;
}

.app-header__link {
    font-size: 0.875rem;
    color: var(--color-text-muted);
    text-decoration: none;
}

.app-header__link:hover {
    color: var(--color-primary);
}

/* ------- the name cell opens the detail screen */

/* Inherits colour and weight from the cell: the whole first column is the way in,
 * so painting it link-blue would make the table look like a page of links instead
 * of a table.
 *
 * The affordance is permanent, and that is the fix for a real problem: PRD §4.1
 * says "clicar numa linha abre o registro", in practice only the name cell is
 * clickable, and with the underline appearing on hover only, nothing on the screen
 * said so. A reader who never happens to hover over the first column never finds
 * the detail screen at all.
 *
 * A DOTTED underline, in the muted text colour, is what says so permanently. The
 * first thing tried was a solid hairline in --color-border, and on screen it was
 * invisible against both row backgrounds at 100% — an affordance nobody can see is
 * the bug it was meant to fix. Dotted reads as "there is more behind this" without
 * looking like body-text emphasis, it is drawn rather than laid out so the row
 * height is unchanged (31.84px before and after) and the table keeps its density,
 * and it leaves the colour alone. Hover then promotes it to the primary colour and
 * a solid line, which is what confirms the target under the cursor. */
.lead-link {
    color: inherit;
    text-decoration: underline dotted;
    text-decoration-color: var(--color-text-muted);
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}

.lead-link:hover {
    color: var(--color-primary);
    text-decoration-style: solid;
    text-decoration-color: currentColor;
}

/* ----------------------------------------------------------- detail screen */

/* Unlike .leads, this screen scrolls with the page: the record is a fixed number of
 * fields, not a list that grows, so there is nothing to keep pinned above a scroll
 * box and no sticky header to make work. */
.lead {
    padding: 1rem 1.25rem 2rem;
    max-width: 90rem;
    margin: 0 auto;
    width: 100%;
}

.lead__back {
    display: inline-block;
    font-size: 0.8125rem;
    color: var(--color-primary);
    text-decoration: none;
    margin-bottom: 0.75rem;
}

.lead__back:hover {
    text-decoration: underline;
}

.lead__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 0.875rem 1.125rem;
    margin-bottom: 0.75rem;
}

.lead__name {
    font-size: 1.25rem;
    margin: 0;
    /* A name is free text from the Hub and can be long; it wraps rather than pushing
     * the contact buttons off the card. */
    overflow-wrap: anywhere;
}

.lead__sub {
    margin: 0.125rem 0 0;
    font-size: 0.8125rem;
    color: var(--color-text-muted);
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    overflow-wrap: anywhere;
}

.lead__stage {
    font-size: 0.6875rem;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 0 0.375rem;
    align-self: center;
}

.lead__actions {
    display: flex;
    gap: 0.375rem;
    align-items: center;
}

/* Multi-column flow, not a grid. The cards have very different heights — eight
 * fields in one, three in another — and a grid puts each row's cards on the same
 * baseline, so a short card leaves a hole as tall as the tallest one next to it.
 * Columns let each card start where the previous one ended, which is what "ferramenta
 * densa" means here: information per pixel, not a tidy matrix with air in it. The
 * column width is a minimum, so the count follows the window with no media query. */
.lead__grid {
    columns: 21rem;
    column-gap: 0.75rem;
}

.card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 0.75rem 1rem 0.875rem;
    /* Without this a card is free to be split across two columns, with its title in
     * one and half its fields in the next. */
    break-inside: avoid;
    margin-bottom: 0.75rem;
}

.card__title {
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-text-muted);
    margin: 0 0 0.5rem;
    padding-bottom: 0.375rem;
    border-bottom: 1px solid var(--color-bg);
}

.card__note {
    margin: -0.25rem 0 0.5rem;
    font-size: 0.6875rem;
    color: var(--color-text-muted);
}

/* Label left, value right, one row per field, hairline between: the densest shape
 * that still lets the eye run down either column on its own. */
.field {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    padding: 0.1875rem 0;
    border-bottom: 1px solid var(--color-bg);
    font-size: 0.8125rem;
}

.field:last-child {
    border-bottom: 0;
}

.field__label {
    color: var(--color-text-muted);
    white-space: nowrap;
}

.field__value {
    text-align: right;
    font-variant-numeric: tabular-nums;
    /* An id, an e-mail or a hostile name has no spaces to break on; without this the
     * value would widen the card and give the page a horizontal scrollbar. */
    overflow-wrap: anywhere;
}

/* The identifiers, which were the two worst lines on this page: 36 characters of
 * body text, right-aligned, broken across two lines with a ragged left edge — and
 * the first of them sits at the top of the first card, so the eye landed on it
 * before anything the reader can act on.
 *
 * Three changes, one cause each.
 *
 * Monospace, because a UUID is only ever read by comparing it to another one,
 * character by character, and proportional glyphs obstruct exactly that.
 *
 * At 0.6875rem an id measures ~218px, and the min-width reserves the 14rem it
 * needs, so the value never has to break — on these rows it is the LABEL that
 * yields instead. That is the whole trade: an id split in half is unreadable,
 * "ID de quem indicou" split after a word is not. min() keeps the floor from ever
 * exceeding the card and giving the page a horizontal scrollbar on a narrow window.
 *
 * Muted, because an id is the field you verify once you already know which record
 * you are on — never the field you scan for. Demoting it costs nothing: legibility
 * here is per character, and monospace at this size has more of it, not less. */
.field__value[data-field="id"],
.field__value[data-field="referred_by_user_id"],
.field__value[data-field="referrer_influencer_id"] {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    color: var(--color-text-muted);
}

/* ------------------------------------------------------------ evolution screen */

/* Two stacked cards, one per series, in the space the app header leaves. The scroll
 * lives here rather than on <body> so the header stays put, same as .table-wrap. */
.charts {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 1.25rem 1.5rem 2rem;
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.chart {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 1rem 1.25rem 1.125rem;
}

.chart__header {
    margin-bottom: 0.75rem;
}

.chart__title {
    font-size: 0.9375rem;
    font-weight: 700;
    margin: 0 0 0.25rem;
}

/* The sentence that says what KIND of statement the chart below is. It is not a
 * caption and not a footnote: PRD §4.6 requires the distinction between the two
 * halves to be visible on the screen, so it sits above the plot, at reading width,
 * with the load-bearing clause in full colour while the rest stays muted. */
.chart__nature {
    font-size: 0.8125rem;
    line-height: 1.45;
    color: var(--color-text-muted);
    margin: 0 0 0.375rem;
    max-width: 74ch;
}

.chart__nature strong {
    color: var(--color-text);
    font-weight: 600;
}

.chart__meta {
    margin: 0;
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
}

/* Scales with the column and keeps its ratio: the SVG carries no
 * preserveAspectRatio="none", so the tick text scales instead of being stretched. */
.chart__plot {
    display: block;
    width: 100%;
    height: auto;
}

.chart__gridline {
    stroke: var(--chart-grid);
    stroke-width: 1;
}

.chart__axis {
    stroke: var(--color-border);
    stroke-width: 1;
}

/* SVG text takes fill, not color, and inherits neither from the page. */
.chart__tick {
    font-family: var(--font-body);
    font-size: 9px;
    fill: var(--color-text-muted);
}

.chart__tick--y {
    text-anchor: end;
    dominant-baseline: middle;
}

.chart__tick--middle {
    text-anchor: middle;
}

/* The first and last bottom labels anchor inward. Centred, half of "24/08/2026"
 * would hang past the viewBox and be clipped to "24/08/20" — which reads as a
 * corrupted date, not as an overflow. */
.chart__tick--start {
    text-anchor: start;
}

.chart__tick--end {
    text-anchor: end;
}

/* fill: none is structural, not decoration — without it a polyline paints itself as
 * a filled blob between its first and last point. It lives here because the CSP has
 * no 'unsafe-inline' and no template in this project may carry a style attribute. */
.chart__line {
    fill: none;
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
}

/* A run of one point, which a polyline cannot draw at all. The ring in the surface
 * colour keeps two markers that land on top of each other readable as two. */
.chart__marker {
    stroke: var(--color-surface);
    stroke-width: 1.5;
}

.chart__point-label {
    font-family: var(--font-body);
    font-size: 9px;
    fill: var(--color-text-muted);
}

/* Legend and readout in one: the series name next to the last measured value, which
 * on a one-point chart is the only number there is. */
.chart-legend {
    list-style: none;
    margin: 0.625rem 0 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1.25rem;
}

/* Says WHAT the numbers to its right are — last week, or last photograph. Without
 * it "Cadastros 73" reads as a total. */
.chart-legend__caption {
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-text-muted);
    align-self: center;
}

.chart-legend__item {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    font-size: 0.75rem;
}

.chart-legend__swatch {
    width: 0.625rem;
    height: 0.625rem;
    border-radius: 2px;
    flex: none;
}

.chart-legend__name {
    color: var(--color-text-muted);
}

.chart-legend__value {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* "coleta iniciada em ... — ainda nao ha serie para desenhar". Marked as a note and
 * not as a warning on purpose: nothing is wrong, the series is simply young. */
.chart__note {
    margin: 0.625rem 0 0;
    padding-left: 0.625rem;
    border-left: 2px solid var(--color-primary);
    font-size: 0.75rem;
    color: var(--color-text-muted);
}

/* Shown INSTEAD of a plot, never next to an empty frame: a rectangle with no words
 * in it is read as a screen that failed to render. */
.chart__empty {
    margin: 0.5rem 0 0;
    padding: 1.5rem 1.25rem;
    background: var(--color-bg);
    border: 1px dashed var(--color-border);
    border-radius: var(--radius);
    font-size: 0.8125rem;
    color: var(--color-text-muted);
    text-align: center;
}

.chart__series--0 .chart__line {
    stroke: var(--chart-0);
}

.chart__series--0 .chart__marker {
    fill: var(--chart-0);
}

.chart-legend__item--0 .chart-legend__swatch {
    background: var(--chart-0);
}

.chart__series--1 .chart__line {
    stroke: var(--chart-1);
}

.chart__series--1 .chart__marker {
    fill: var(--chart-1);
}

.chart-legend__item--1 .chart-legend__swatch {
    background: var(--chart-1);
}

.chart__series--2 .chart__line {
    stroke: var(--chart-2);
}

.chart__series--2 .chart__marker {
    fill: var(--chart-2);
}

.chart-legend__item--2 .chart-legend__swatch {
    background: var(--chart-2);
}

.chart__series--3 .chart__line {
    stroke: var(--chart-3);
}

.chart__series--3 .chart__marker {
    fill: var(--chart-3);
}

.chart-legend__item--3 .chart-legend__swatch {
    background: var(--chart-3);
}

.chart__series--4 .chart__line {
    stroke: var(--chart-4);
}

.chart__series--4 .chart__marker {
    fill: var(--chart-4);
}

.chart-legend__item--4 .chart-legend__swatch {
    background: var(--chart-4);
}

.chart__series--5 .chart__line {
    stroke: var(--chart-5);
}

.chart__series--5 .chart__marker {
    fill: var(--chart-5);
}

.chart-legend__item--5 .chart-legend__swatch {
    background: var(--chart-5);
}

.chart__series--6 .chart__line {
    stroke: var(--chart-6);
}

.chart__series--6 .chart__marker {
    fill: var(--chart-6);
}

.chart-legend__item--6 .chart-legend__swatch {
    background: var(--chart-6);
}

.chart__series--7 .chart__line {
    stroke: var(--chart-7);
}

.chart__series--7 .chart__marker {
    fill: var(--chart-7);
}

.chart-legend__item--7 .chart-legend__swatch {
    background: var(--chart-7);
}


/* ----------------------------------------------------------------- status screen
 *
 * A dense instrument panel, not a dashboard: the reader opens this because
 * something looks wrong, or to confirm the night's run happened. So the numbers are
 * tabular and small, the words that qualify them are right next to them, and
 * nothing here is a decorative gauge.
 *
 * Colour carries no meaning on its own. Every state prints its name in words, and
 * the tint behind it only speeds up finding it again — a panel read on a bad screen,
 * printed, or by someone who does not separate red from green must lose nothing.
 */

.status {
    padding: 1rem 1.25rem 2rem;
    max-width: 110rem;
    margin: 0 auto;
    width: 100%;
}

.status-cards,
.status-latest {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
}

.status-card {
    flex: 1 1 16rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 0.75rem 0.875rem;
}

.status-card--wide {
    flex: 2 1 26rem;
}

.status-card--run {
    flex: 1 1 24rem;
}

.status-card__title {
    margin: 0;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-text-muted);
}

.status-card__lead {
    margin: 0.25rem 0 0;
    font-size: 1.5rem;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
}

/* "não medida ainda" and "não configurado" are absences, and an absence set in the
 * same weight as a headcount reads as a value. It is still full size: it is the
 * answer, just not a number. */
.status-card__lead--muted {
    font-size: 1.125rem;
    color: var(--color-text-muted);
}

.status-card__lead--state {
    font-size: 1.125rem;
}

.status-card__versus {
    color: var(--color-text-muted);
    padding: 0 0.15rem;
}

.status-card__figure {
    margin: 0.25rem 0 0;
    font-size: 0.875rem;
    font-variant-numeric: tabular-nums;
}

.status-card__note {
    margin: 0.35rem 0 0;
    font-size: 0.75rem;
    line-height: 1.4;
    color: var(--color-text-muted);
}

.status-card__note code {
    font-family: var(--font-mono);
    font-size: 0.7rem;
}

.status-card[data-divergence="over"] {
    border-color: var(--color-danger);
    background: var(--color-danger-bg);
}

.status-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.25rem;
    margin: 0.6rem 0 0;
}

.status-facts__item {
    display: flex;
    flex-direction: column;
}

.status-facts dt {
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-muted);
}

.status-facts dd {
    margin: 0;
    font-size: 1rem;
    font-variant-numeric: tabular-nums;
}

.status-runs__title,
.status-legend__title {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-text-muted);
    margin: 1.25rem 0 0.4rem;
}

/* This table is as tall as it needs to be, unlike the leads table: twenty rows is
 * the whole history the screen shows, and pinning it to the viewport would put a
 * second scrollbar around a list that usually fits. .table-wrap's flex: 1 does
 * nothing here because .status is not a flex column. */
.status .table-wrap {
    max-height: 32rem;
}

.runs-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.8125rem;
    line-height: 1.35;
}

.runs-table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--color-bg);
    box-shadow: inset 0 -1px 0 var(--color-border);
    text-align: left;
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--color-text-muted);
    padding: 0.4rem 0.5rem;
    white-space: nowrap;
}

.runs-table tbody td {
    padding: 0.35rem 0.5rem;
    border-top: 1px solid var(--color-border);
    vertical-align: top;
}

.runs-table tbody tr:nth-child(even) {
    background: #fbfbfc;
}

.runs-table td.num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.runs-table td.mono {
    font-family: var(--font-mono);
    font-size: 0.75rem;
}

/* The one cell that may be long: sync_runs.error is a formatted sentence with up to
 * ten reasons in it, printed as-is. It wraps instead of stretching the table. */
.runs-table__error {
    min-width: 18rem;
    font-size: 0.75rem;
    color: var(--color-text-muted);
    word-break: break-word;
}

/* Never zero. A discard count above zero is the silent source failure PRD §8 is
 * about, and it has to be findable by eye in a wall of digits. */
.is-warning {
    color: var(--color-danger);
    font-weight: 600;
}

.run-state {
    display: inline-block;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    font-size: 0.75rem;
    white-space: nowrap;
    border: 1px solid var(--color-border);
    background: var(--color-bg);
}

.run-state--live {
    border-color: #1d5b8f;
    background: #e7f0f8;
    color: #14456d;
}

.run-state--paused {
    border-color: #b4590a;
    background: #fbf0e4;
    color: #85420a;
}

.run-state--stalled,
.run-state--abandoned {
    border-color: #6a6a12;
    background: #f6f6e6;
    color: #55550f;
}

.run-state--success {
    border-color: #2c7a52;
    background: #e9f4ee;
    color: #1f5b3c;
}

.run-state--warning,
.run-state--failed,
.run-state--unknown {
    border-color: var(--color-danger);
    background: var(--color-danger-bg);
    color: var(--color-danger);
}

.status-legend__list {
    margin: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr));
    gap: 0.5rem 1.25rem;
}

.status-legend__item {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.status-legend__item dt {
    font-weight: 400;
}

.status-legend__item dd {
    margin: 0;
    font-size: 0.75rem;
    line-height: 1.4;
    color: var(--color-text-muted);
}

.status-legend__note {
    margin: 0.75rem 0 0;
    font-size: 0.75rem;
    color: var(--color-text-muted);
}

.status-empty {
    margin: 0;
    padding: 1rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    color: var(--color-text-muted);
}

/* ---------------------------------------------------------- configuration screen
 *
 * One field, and the paragraphs that make it safe to change. Same instrument-panel
 * language as the status screen — surface card, uppercase micro-labels, tabular
 * numerals — but laid out narrow: this is a page you READ before you type, and a
 * measure of 60rem is where the sentences stop being a wall.
 *
 * The field itself is deliberately oversized against everything else on the page.
 * There is exactly one input in the whole panel that changes what every other
 * screen shows, and it should look like it.
 */

/* The field and the caveats side by side, wrapping to one column when the window is
 * narrow. Stacked, the caveats sit below the fold on a laptop and the page reads as a
 * form with a footnote; abreast, the whole screen is one thing to read. */
.settings {
    padding: 1rem 1.25rem 2rem;
    max-width: 76rem;
    /* Not centred, unlike .leads and .status. Those two are as wide as the panel gets,
     * so on any real window their auto margins are zero and they read as left-aligned;
     * this screen is narrow, and centring it would float two small cards away from the
     * header brand they belong under. */
    margin: 0;
    width: 100%;
    overflow-y: auto;
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 0.75rem;
}

.settings-card {
    flex: 2 1 32rem;
}

.settings-aside {
    flex: 1 1 20rem;
}

.settings-card,
.settings-aside {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 1rem 1.125rem;
}

.settings-aside {
    background: none;
    border-style: dashed;
}

.settings-card__title,
.settings-aside__title {
    margin: 0;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-text-muted);
}

.settings-card__lead {
    margin: 0.5rem 0 0;
    font-size: 0.9375rem;
    max-width: 44rem;
}

.settings-card__note {
    margin: 0.875rem 0 0;
    font-size: 0.8125rem;
    color: var(--color-text-muted);
}

/* The saved confirmation and the rejection notice. Both carry their meaning in
 * words — the tint only helps find them again on the second visit. */
.settings-notice {
    margin: 0.75rem 0 0;
    padding: 0.5rem 0.75rem;
    border-radius: var(--radius);
    border: 1px solid var(--color-border);
    font-size: 0.875rem;
}

.settings-notice--ok {
    border-color: #b7d4c3;
    background: #eef7f1;
}

.settings-notice--error {
    border-color: var(--color-danger);
    background: var(--color-danger-bg);
    color: var(--color-danger);
}

.settings-form {
    margin-top: 1rem;
}

.settings-form__label {
    display: block;
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-muted);
}

.settings-form__row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.25rem;
}

/* Wide enough for three digits and the spinner, and no wider: a box sized for a
 * sentence invites one to be typed into it. */
.settings-form__input {
    font: inherit;
    font-size: 1.375rem;
    font-variant-numeric: tabular-nums;
    width: 7rem;
    padding: 0.25rem 0.5rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    color: var(--color-text);
}

.settings-form__input:focus {
    outline: 2px solid var(--color-primary);
    outline-offset: 1px;
}

.settings-form__input[aria-invalid="true"] {
    border-color: var(--color-danger);
}

.settings-form__submit {
    font: inherit;
    font-size: 0.875rem;
    font-weight: 600;
    padding: 0.5rem 1.25rem;
    border: none;
    border-radius: var(--radius);
    background: var(--color-primary);
    color: #ffffff;
    cursor: pointer;
}

.settings-form__submit:hover {
    background: var(--color-primary-hover);
}

.settings-form__hint {
    margin: 0.375rem 0 0;
    font-size: 0.75rem;
    color: var(--color-text-muted);
}

.settings-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.25rem;
    margin: 1rem 0 0;
    padding-top: 0.75rem;
    border-top: 1px solid var(--color-border);
}

.settings-facts__item {
    display: flex;
    flex-direction: column;
}

.settings-facts dt {
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-muted);
}

.settings-facts dd {
    margin: 0;
    font-size: 0.9375rem;
    font-variant-numeric: tabular-nums;
}

.settings-aside__list {
    margin: 0.5rem 0 0;
    padding-left: 1.125rem;
    font-size: 0.8125rem;
    line-height: 1.5;
    color: var(--color-text-muted);
}

.settings-aside__list li + li {
    margin-top: 0.3125rem;
}

.settings-aside__list code {
    font-family: var(--font-mono);
    font-size: 0.75rem;
}
