/* ═══════════════════════════════════════════════════════════
   /analytics — archive analytics dashboard (EVE-3461)

   Loaded after webapp.css and before airy.css, matching contacts.css
   and assistant.css. Every colour is a token: this page has to read
   correctly in both themes, and a hardcoded hex would only look right
   in one of them.
   ═══════════════════════════════════════════════════════════ */

/* .stat-card's label/value/delta are inline spans in webapp.css, which only
   happens to stack on pages whose value is wide enough to wrap. Make the stack
   explicit — otherwise a short number renders as "PEOPLE 18" on one line while
   a long one wraps, and the four tiles do not share a baseline. Scoped to this
   page so the AdminApp dashboard's own tiles are untouched. */
.analytics-page .stat-card {
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
}

.analytics-page .stat-card .label,
.analytics-page .stat-card .value,
.analytics-page .stat-card .delta {
    display: block;
}

.analytics-page .stat-card .value {
    line-height: 1.15;
}

.analytics-page .analytics-section {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.analytics-section__head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1.5rem;
}

.analytics-section__title {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--color-text-primary);
}

.analytics-section__sub {
    margin: 0.25rem 0 0;
    font-size: 0.82rem;
    color: var(--color-text-secondary);
    max-width: 46ch;
    line-height: 1.4;
}

.analytics-section__empty {
    margin: 0;
    font-size: 0.88rem;
}

/* The attachment tile is the one stat allowed to come back missing.
   Muted so an em dash never reads as a real measured value. */
.analytics-value--unavailable {
    color: var(--color-text-secondary) !important;
}

.analytics-note {
    display: flex;
    align-items: flex-start;
    gap: 0.65rem;
    font-size: 0.86rem;
    line-height: 1.5;
}

/* ── Ranked contact list ─────────────────────────────────────
   A bar list rather than a chart: the WebApp ships no charting
   library, and for a top-10 ranking a proportional bar is more
   legible than a pie anyway. Widths come from the component.
   ─────────────────────────────────────────────────────────── */

.contact-rank {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
}

.contact-rank__row {
    display: grid;
    grid-template-columns: 1.75rem minmax(0, 15rem) 1fr auto;
    align-items: center;
    gap: 1rem;
    padding: 0.7rem 0.25rem;
    border-bottom: 1px solid var(--color-border);
    transition: background-color 200ms ease;
}

.contact-rank__row:last-child {
    border-bottom: 0;
}

@media (prefers-reduced-motion: no-preference) {
    .contact-rank__row:hover {
        background-color: var(--color-surface-muted, rgba(127, 127, 127, 0.06));
    }
}

.contact-rank__pos {
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--color-text-secondary);
    font-variant-numeric: tabular-nums;
}

.contact-rank__who {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.contact-rank__name {
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--color-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.contact-rank__email {
    font-size: 0.76rem;
    color: var(--color-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.contact-rank__bar {
    display: block;
    height: 0.5rem;
    border-radius: 999px;
    background-color: var(--color-border);
    overflow: hidden;
}

.contact-rank__fill {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--color-brand-accent), var(--color-brand-deep));
}

.contact-rank__count {
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--color-text-primary);
    font-variant-numeric: tabular-nums;
}

/* ── Longest-running correspondent ──────────────────────────── */

.analytics-longest {
    display: flex;
    align-items: center;
    gap: 1.15rem;
}

.analytics-longest__avatar {
    display: grid;
    place-items: center;
    width: 3.25rem;
    height: 3.25rem;
    flex: 0 0 auto;
    border-radius: 999px;
    background-color: var(--color-border);
    color: var(--color-brand-deep);
    font-size: 1.4rem;
}

.analytics-longest__body {
    min-width: 0;
}

.analytics-longest__name {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--color-text-primary);
}

.analytics-longest__email,
.analytics-longest__meta {
    margin: 0.15rem 0 0;
    font-size: 0.82rem;
    color: var(--color-text-secondary);
}

/* ── Plan teaser ────────────────────────────────────────────── */

.analytics-upsell {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    padding: 1.15rem 1.35rem;
    border: 1px dashed var(--color-border);
    border-radius: var(--radius-card, 24px);
}

.analytics-upsell__title {
    margin: 0;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--color-text-primary);
}

.analytics-upsell__body {
    margin: 0.3rem 0 0;
    font-size: 0.83rem;
    color: var(--color-text-secondary);
    max-width: 52ch;
    line-height: 1.45;
}

.analytics-upsell .btn {
    flex: 0 0 auto;
}

.analytics-footnote {
    margin: 0;
    font-size: 0.76rem;
    color: var(--color-text-secondary);
}

/* ---------------------------------------------------------------------------
   EVE-3467 (Phase 2): volume chart, arrival rhythm, domain badge, thread cards.

   Bars are CSS, not a charting library: the WebApp deliberately ships none
   (ApexCharts is AdminApp-only), and these shapes are simple enough that pulling
   one in would cost more than it explains. Every bar carries its number in a
   title and a visually-hidden span, so the chart is not the only way to read it.
   --------------------------------------------------------------------------- */

.analytics-page .volume-chart {
    display: flex;
    align-items: flex-end;
    gap: 3px;
    height: 160px;
    margin: 0;
    padding: 0;
    list-style: none;
    overflow-x: auto;
}

.analytics-page .volume-chart__col {
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    min-width: 18px;
    height: 100%;
}

/* No min-height here: ColumnHeight already floors a quiet-but-nonzero period to 4%
   and returns 0% only for a true zero. A floor in CSS would override that and draw a
   bar over a year that had no mail at all. */
.analytics-page .volume-chart__bar {
    width: 100%;
    max-width: 34px;
    border-radius: 3px 3px 0 0;
    background: linear-gradient(180deg, var(--color-brand-accent), var(--color-brand-deep));
}

.analytics-page .volume-chart__label {
    margin-top: 6px;
    font-size: 0.68rem;
    line-height: 1;
    color: var(--color-text-secondary);
    white-space: nowrap;
}

.analytics-page .rhythm {
    display: flex;
    flex-wrap: wrap;
    gap: 28px;
}

.analytics-page .rhythm__group {
    flex: 1 1 260px;
    min-width: 0;
}

.analytics-page .rhythm__caption {
    margin: 0 0 10px;
    font-size: 0.82rem;
    color: var(--color-text-secondary);
}

.analytics-page .rhythm__caption strong {
    color: var(--color-text-primary);
    font-weight: 600;
}

.analytics-page .rhythm__bars {
    display: flex;
    align-items: flex-end;
    gap: 4px;
    height: 96px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.analytics-page .rhythm__bars--hours {
    gap: 2px;
}

.analytics-page .rhythm__bar {
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    min-width: 0;
    height: 100%;
}

/* No min-height, for the same reason as .volume-chart__bar: an hour that genuinely
   received no mail must render nothing rather than a 2px stub. */
.analytics-page .rhythm__fill {
    width: 100%;
    max-width: 26px;
    border-radius: 3px 3px 0 0;
    background: var(--color-border);
}

/* The peak is the answer the caption states in words; colouring it is what ties
   the sentence to the chart. */
.analytics-page .rhythm__bar--peak .rhythm__fill {
    background: var(--color-brand-primary);
}

.analytics-page .rhythm__tick {
    margin-top: 5px;
    font-size: 0.66rem;
    line-height: 1;
    color: var(--color-text-secondary);
}

/* .contact-rank__name is nowrap + ellipsis, so a domain longer than about
   thirteen characters swallowed the badge whole — and the row then reads as an
   outside party, the one thing the badge exists to prevent. Let the domain text
   take the ellipsis and keep the badge at its natural width. */
.analytics-page .contact-rank__name:has(.domain-badge) {
    display: flex;
    align-items: center;
    min-width: 0;
}

.analytics-page .domain-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.analytics-page .domain-badge {
    flex: 0 0 auto;
    margin-left: 8px;
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--color-border);
    color: var(--color-brand-primary-strong);
    font-size: 0.68rem;
    font-weight: 600;
    white-space: nowrap;
}

.analytics-page .thread-cards {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
}

.analytics-page .thread-card {
    flex: 1 1 260px;
    min-width: 0;
    padding: 16px 18px;
    border: 1px solid var(--color-border);
    border-radius: 12px;
    background: var(--color-surface-muted);
}

.analytics-page .thread-card__label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-brand-primary-strong);
}

.analytics-page .thread-card__subject {
    /* Subjects run long and arrive from mail we did not write; clamping keeps one
       pathological subject from setting the height of the whole row. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin: 8px 0 6px;
    font-size: 0.98rem;
    font-weight: 600;
    line-height: 1.35;
    color: var(--color-text-primary);
    overflow-wrap: anywhere;
}

.analytics-page .thread-card__meta {
    margin: 0;
    font-size: 0.82rem;
    color: var(--color-text-secondary);
}

/* ═══════════════════════════════════════════════════════════
   "On this day" — home page (EVE-3487)

   Lives here rather than in webapp.css because it is part of the
   analytics feature, and analytics.css is already registered in
   App.razor. Scoped to .on-this-day so nothing here can reach the
   other .home-panel cards it sits beside.

   The panel reuses .home-panel and .home-panel__head wholesale — the
   card idiom already on this page — so only the rows inside it are
   new. Every colour is a token: the home page is the first thing a
   user sees in either theme, and a hardcoded hex only reads correctly
   in one of them.
   ═══════════════════════════════════════════════════════════ */

.on-this-day {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

/* The UTC label. Deliberately quiet — it answers a question rather than
   asking one, and it must never compete with the heading beside it. */
.on-this-day__tz {
    flex: 0 0 auto;
    padding: 2px 8px;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    color: var(--color-text-secondary);
}

.on-this-day__year + .on-this-day__year {
    margin-top: 0.25rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--color-border);
}

.on-this-day__year-head {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin: 0 0 0.5rem;
}

.on-this-day__year-label {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--color-brand-primary-strong);
}

.on-this-day__year-ago {
    font-size: 0.78rem;
    color: var(--color-text-secondary);
}

.on-this-day__list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.on-this-day__row {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    /* min-width:0 on the row as well as the children: without it a long subject
       makes the flex item refuse to shrink and the sender is pushed out of the
       card entirely rather than truncating. */
    min-width: 0;
    padding: 6px 8px;
    border-radius: 8px;
    color: var(--color-text-primary);
    text-decoration: none;
}

.on-this-day__row:hover,
.on-this-day__row:focus-visible {
    background: var(--color-surface-muted);
}

.on-this-day__subject {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    font-size: 0.92rem;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The sender is the secondary fact, so it yields first — but not below a
   readable width, or it truncates to two characters next to a short subject. */
.on-this-day__from {
    flex: 0 1 38%;
    min-width: 0;
    overflow: hidden;
    font-size: 0.82rem;
    color: var(--color-text-secondary);
    text-align: right;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.on-this-day__more {
    margin: 0.4rem 0 0 8px;
    font-size: 0.8rem;
    color: var(--color-text-secondary);
}

/* Below the two-column breakpoint the sender stacks under the subject rather
   than sharing the line: at 360px a right-aligned address and a subject on one
   row leaves neither legible. */
@media (max-width: 640px) {
    .on-this-day__row {
        flex-direction: column;
        gap: 2px;
    }

    .on-this-day__from {
        flex: 0 0 auto;
        max-width: 100%;
        text-align: left;
    }
}
