/* ============================================================================
   Cards, chart cards, KPI cards, grid layouts
   ========================================================================== */

.card {
    background: var(--surface);
    border: var(--border-width) solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
}
.card-header {
    padding: var(--space-7) var(--space-9);
    border-bottom: var(--border-width) solid var(--border-subtle);
    font-weight: var(--weight-semibold);
    font-size: var(--text-md);
    color: var(--text);
}
.card-body { padding: var(--space-9); }
/* Density variants, so a compact card is a class rather than an inline padding override. */
.card-body-sm { padding: var(--space-3) var(--space-5); }
.card-body-lg { padding: var(--space-16); }
.card-body-flush { padding: 0; }

/* A card body that holds several distinct sub-topics: each gets a title, and every section after
   the first is separated by a rule so the groups don't run together. */
.card-section + .card-section {
    margin-top: var(--space-12);
    padding-top: var(--space-10);
    border-top: var(--border-width) solid var(--border-subtle);
}
.section-title {
    font-size: var(--text-lg);
    font-weight: var(--weight-semibold);
    color: var(--text);
    margin-bottom: var(--space-6);
}
.section-title i { color: var(--text-muted); margin-right: var(--space-3); }
.section-title .text-muted { font-weight: var(--weight-normal); }
/* One step below .section-title: the heading inside a card body that groups a few rows. */
.subhead {
    font-size: var(--text-lg);
    font-weight: var(--weight-semibold);
    color: var(--text);
    margin-bottom: var(--space-6);
}

.card-hover { transition: box-shadow var(--transition-slow), transform var(--transition); }
.card-hover:hover {
    box-shadow: var(--shadow-md);
    transform: translateY(-1px);
}
/* A bordered block inside a card body: settings rows, provider entries, result groups. */
.panel-box {
    border: var(--border-width) solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--space-6) var(--space-8);
    margin-bottom: var(--space-6);
}

/* Chart cards */
.chart-card {
    display: flex;
    flex-direction: column;
    max-width: 600px;
    max-height: 400px;
}
.chart-card-full { max-width: none; max-height: none; }
.chart-card-full .chart-card-body { overflow: visible; }
.chart-card-full .chart-card-body svg { max-height: none; }
.chart-card-header {
    padding: var(--space-5) var(--space-8);
    border-bottom: var(--border-width) solid var(--border-subtle);
    font-weight: var(--weight-semibold);
    font-size: var(--text-base);
    color: var(--text);
}
.chart-card-body {
    padding: var(--space-6) var(--space-8);
    overflow: hidden;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
}
/* SVGs inside chart cards must stay within bounds */
.chart-card-body svg {
    display: block;
    width: 100%;
    max-width: 100%;
    max-height: 280px;
    flex-shrink: 1;
    overflow: hidden;
}

/* KPI cards */
.kpi-grid {
    display: grid;
    grid-template-columns: repeat(5, minmax(100px, 1fr));
    gap: var(--space-6);
    margin-bottom: var(--space-10);
    max-width: 640px;
}
.kpi-card {
    background: var(--surface);
    border: var(--border-width) solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-6) var(--space-7);
}
.kpi-label {
    font-size: var(--text-2xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    color: var(--text-muted);
}
.kpi-value {
    font-size: var(--text-3xl);
    font-weight: var(--weight-bold);
    color: var(--text);
    margin-top: var(--space-1);
    line-height: var(--leading-none);
}
.kpi-trend {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-top: var(--space-3);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
}
.kpi-trend.trend-good    { color: var(--success); }
.kpi-trend.trend-bad     { color: var(--danger-on-soft); }
.kpi-trend.trend-neutral { color: var(--brand); }
.kpi-trend.trend-flat    { color: var(--text-muted); }
/* A single oversized figure, used as a page's headline number. */
.stat-hero {
    font-size: var(--text-6xl);
    font-weight: var(--weight-bold);
    line-height: var(--leading-none);
}

/* Grid layouts */
.grid-2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-8); margin-bottom: var(--space-10); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-8); margin-bottom: var(--space-10); }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-8); margin-bottom: var(--space-10); }
.grid-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--space-8); }

/* === Card tone variants ====================================================
   A card that carries a status: an info panel, a failure panel, a risk-graded
   analysis panel. Previously each of these set border-color and header colours
   inline, which is how five different reds got into the application. */
.card-info { border-color: var(--info); }
.card-info > .card-header { background: var(--info-soft); color: var(--info-on-soft); }
.card-danger { border-color: var(--danger); }
.card-danger > .card-header { color: var(--danger-on-soft); }
.card-success { border-color: var(--success); }
.card-success > .card-header { background: var(--success-soft); color: var(--success-on-soft); }
.card-sunken { background: var(--surface-alt); }

/* A left accent stripe, for a card that is a signal rather than a container. */
.card-accent-warning { border-left: var(--border-accent) solid var(--warning); }
.card-accent-danger { border-left: var(--border-accent) solid var(--danger); }
.card-accent-info { border-left: var(--border-accent) solid var(--info); }
/* The fourth stripe carries no urgency, and it exists so a set of cards can say "this one is the
   plain case" in the same language the other three use. A card with no stripe at all cannot: it
   reads as a card nobody classified, which is the state a kind badge is drawn to rule out. */
.card-accent-neutral { border-left: var(--border-accent) solid var(--border-strong); }

/* Risk-graded analysis card: the two grades the commit detail page renders. */
.card-risk-high { border-color: var(--danger); }
.card-risk-high > .card-header { background: var(--danger-soft); color: var(--danger-on-soft); }
.card-risk-normal { border-color: var(--warning); }
.card-risk-normal > .card-header { background: var(--warning-soft); color: var(--warning-on-soft); }

/* A quiet inset well for prose inside a card (ticket summaries, PR judgments). */
.prose-well {
    padding: var(--space-6);
    background: var(--surface-alt);
    border-radius: var(--radius-md);
}

/* A rule between two stacked groups inside one card body. */
.section-divider {
    margin-top: var(--space-12);
    padding-top: var(--space-12);
    border-top: var(--border-width) solid var(--border);
}
/* A row in a plain stacked list inside a card body. */
.divided-row {
    padding: var(--space-5) 0;
    border-bottom: var(--border-width) solid var(--border-subtle);
}
.divided-row:last-child { border-bottom: none; }

/* The label above a small group of fields — one step below .subhead. */
.field-group-title {
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    margin: 0 0 var(--space-4);
    color: var(--text-body);
}

/* Big grey ordinal in a ranked list. */
.rank-numeral {
    font-size: var(--text-xl);
    font-weight: var(--weight-bold);
    color: var(--text-subtle);
    width: var(--space-14);
    text-align: center;
}

/* A second card-header further down the same card, ruled off from what precedes it. */
.card-header-divided { border-top: var(--border-width) solid var(--border-subtle); }

/* Buttons under a card's content. Three sites were carrying `flex gap-3 flex-wrap` as raw utilities,
   which makes the spacing between two actions a utility decision rather than a design one.

   align-items: flex-end is copied from .form-row and is what lets one class serve all three: the
   third site holds a select beside its button and was reaching for `items-end` on top of the other
   three utilities. Not .filter-bar, which is two rules away in the buttons sheet and carries a top
   margin for sitting above a table. */
.card-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--space-6);
    margin-top: var(--space-8);
}

/* A screenshot on a card. Bounded in height rather than in width, because the thing being looked at
   is almost always a window capture that is wider than it is tall, and one sized to the column would
   push the caption and the thread below the fold. The full image is one click away, so this is a
   thumbnail and is allowed to be one. */
.attachment-shot {
    display: block;
    max-width: 100%;
    max-height: 14rem;
    width: auto;
    border: var(--border-width) solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface-sunken);
    margin-bottom: var(--space-4);
}
