/* Deep Field view styles: dashboard. Companion to deep-field.css (tokens/components live there).
   Owned by the dashboard view(s); keep everything token-driven, flat, AA in both themes.

   Contents:
   - .df-dash ............ full-bleed wrapper (cancels .app-main padding so the
                           hero band runs edge-to-edge; margins mirror the
                           .app-main padding at each breakpoint)
   - .df-acc / .df-seg ... element-level derived-accent plumbing. The view sets
                           BOTH themes' roles as custom properties inline
                           (--acc-*-l / --acc-*-d, --seg-l / --seg-d from
                           App.accent.deriveAccent); these rules pick the -l or
                           -d set per theme so a theme flip needs no re-render.
   - .an-panel / .an-two . analytics panels (chart, donuts, stacked claim bars)
   - chart / donut / stacked-bar classes ported from the approved prototype
   - .df-reconsent ....... flat re-consent banner
   - small helpers: quiet notes, syncing label, skeleton chart block, legacy
     card treatment */

/* ===== Full-bleed wrapper: cancel .app-main padding around the view ===== */
.df-dash {
  margin: calc(-1 * var(--space-6)) calc(-1 * var(--space-5)) 0;
}
@media (min-width: 900px) {
  .df-dash { margin: calc(-1 * var(--space-8)) calc(-1 * var(--space-8)) 0; }
}
@media (max-width: 480px) {
  .df-dash { margin: calc(-1 * var(--space-4)) calc(-1 * var(--space-3)) 0; }
}

/* Impact grid fade during the impact-view swap (bound in JS, styled here) */
.df-dash .impact-grid { transition: opacity 150ms ease-out; }
@media (prefers-reduced-motion: reduce) {
  .df-dash .impact-grid { transition: none; }
}

/* ===== Derived-accent plumbing (theme-scoped custom-property re-mapping) ===== */
.df-acc {
  --acc-num: var(--acc-num-l);
  --acc-fill: var(--acc-fill-l);
  --acc-soft: var(--acc-soft-l);
}
.df-seg { --seg: var(--seg-l); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .df-acc {
    --acc-num: var(--acc-num-d);
    --acc-fill: var(--acc-fill-d);
    --acc-soft: var(--acc-soft-d);
  }
  :root:not([data-theme="light"]) .df-seg { --seg: var(--seg-d); }
}
:root[data-theme="dark"] .df-acc {
  --acc-num: var(--acc-num-d);
  --acc-fill: var(--acc-fill-d);
  --acc-soft: var(--acc-soft-d);
}
:root[data-theme="dark"] .df-seg { --seg: var(--seg-d); }

/* Impact wallet cards with a DB-derived accent. Specificity note: these tie
   the core theme-scoped .impact-number/.impact-icon rules at (0,3,0) and win
   by source order (this sheet loads after deep-field.css). */
.impact-card.df-acc .impact-number { color: var(--acc-num); }
.impact-card.df-acc .impact-icon { background: var(--acc-soft); color: var(--acc-num); }
.impact-card.df-acc .impact-bar-fill { background: var(--acc-fill); }

/* Donut slices + colour-dot legend marks */
circle.df-seg { stroke: var(--seg); }
.donut-leg-dot.df-seg { background: var(--seg); }

/* ===== Impact wallet extras ===== */
.df-impact-empty {
  grid-column: 1 / -1;
  font-size: 14px;
  color: var(--ink-62);
}
.impact-card.df-legacy { opacity: 0.65; }
.impact-card-legacy-badge {
  font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--ink-62); margin-left: 6px;
}
.df-impact-icon-img { width: 19px; height: 19px; object-fit: contain; display: block; }
/* Emoji/text icons sit on the soft accent chip */
.impact-card.df-acc .impact-icon { font-size: 17px; line-height: 1; }

/* Charity partner logo: fills the 34x34 icon slot as a fixed-size white tile
   so any partner artwork (usually built for light backgrounds) stays legible
   in BOTH themes and never shifts layout. object-fit keeps aspect ratio;
   box-sizing keeps the padding inside the fixed box. */
.df-impact-logo-img {
  box-sizing: border-box;
  width: 34px; height: 34px;
  object-fit: contain;
  background: var(--white);
  border-radius: 9px;
  padding: 3px;
  display: block;
}

/* ===== Analytics panels (chart, donut, claim funnel) ===== */
.an-panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 18px 20px;
}
.an-panel-head {
  display: flex; align-items: baseline; justify-content: space-between;
  flex-wrap: wrap; gap: 10px; margin-bottom: 14px;
}
.an-panel-title { font-weight: 800; font-size: 16px; letter-spacing: -0.01em; margin: 0; color: var(--text); }
.an-panel-note { color: var(--ink-62); font-size: 13px; font-weight: 500; }
.an-two { display: grid; gap: 14px; grid-template-columns: 1fr; margin-top: 14px; }
@media (min-width: 900px) {
  /* Equal-height panels (owner-directed 2026-07-10): the default grid
     stretch keeps the donut panel as tall as the bars panel. */
  .an-two { grid-template-columns: 1.5fr 1fr; }
}
.df-quiet-note { color: var(--ink-62); font-size: 13px; font-weight: 500; margin: 4px 0 0; }

/* Cumulative line chart (theme-aware via CSS fill/stroke; colours by class,
   never by attribute) */
.an-chart-wrap { width: 100%; overflow: hidden; }
.an-chart { display: block; width: 100%; height: auto; }
.an-chart text { font-family: inherit; }
.an-chart-grid line { stroke: var(--border); }
.an-chart-axis { fill: var(--ink-62); }
.chart-area-direct { fill: var(--num-green); fill-opacity: 0.12; }
.chart-line-direct { stroke: var(--num-green); }
.chart-line-network { stroke: var(--num-teal); }
.chart-end-direct, .chart-lbl-direct { fill: var(--num-green); }
.chart-end-network, .chart-lbl-network { fill: var(--num-teal); }
.chart-end-direct, .chart-end-network { stroke: var(--panel); stroke-width: 2; }
.an-legend { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 8px; }
.an-legend-item { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 600; color: var(--text); }
.an-swatch { width: 14px; height: 14px; border-radius: 4px; flex: none; }

/* DEF-043: "From reminder to gesture" line chart + clickable (toggle) legend. */
.an-line { fill: none; stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.an-line.df-seg { stroke: var(--seg); }
.an-line.an-line--unchosen { stroke: var(--track-bar); stroke-dasharray: 5 4; }
.an-line-dot { stroke: none; }
.an-line-dot.df-seg { fill: var(--seg); }
.an-line-dot.an-line--unchosen { fill: var(--track-bar); }
.an-line-group.is-hidden { display: none; }
.an-legend-toggle {
  appearance: none; background: none; border: 0; padding: 2px 4px;
  font: inherit; color: inherit; cursor: pointer; border-radius: 6px;
}
.an-legend-toggle:hover { background: var(--inset); }
.an-legend-toggle:focus-visible { outline: 2px solid var(--num-teal); outline-offset: 1px; }
.an-legend-toggle.is-hidden { opacity: 0.42; }
.sw-green { background: var(--num-green); }
.sw-teal { background: var(--num-teal); }

/* Donut — ring thickness ~1/3 of diameter; 2px gaps show the --bg ring behind */
/* Legend sits UNDER the ring (owner-directed 2026-07-10). */
.donut-wrap { display: flex; flex-direction: column; align-items: center; gap: 18px; }
.donut-svg { width: 172px; height: 172px; flex: none; }
.donut-svg text { font-family: inherit; }
.donut-seg, .donut-gap { fill: none; stroke-width: 28; }
.donut-gap { stroke: var(--bg); }
.donut-hole-num { fill: var(--text); font-weight: 900; font-size: 36px; letter-spacing: -0.02em; }
.donut-hole-label { fill: var(--ink-62); font-weight: 600; font-size: 12px; }
.donut-legend { width: 100%; display: flex; flex-direction: column; gap: 10px; }
.donut-leg-row { display: flex; align-items: center; gap: 9px; font-size: 13px; }
.donut-leg-dot { width: 11px; height: 11px; border-radius: 3px; flex: none; }
/* The NAME breaks at spaces, never mid-word, and the VALUE can shrink.
   Previously the name carried `overflow-wrap: anywhere` while the value was an
   unshrinkable flex item holding a long phrase ("9 gestures for Plastic Bank —
   Remove 25 plastic bottles"). The value starved the name to near-zero width
   and `anywhere` then broke it one letter per line, rendering "Plastic Bank"
   as a vertical column of characters. */
.donut-leg-name { font-weight: 700; color: var(--text); flex: 1 1 auto; min-width: 5.5em; overflow-wrap: break-word; }
.donut-leg-val { font-weight: 700; color: var(--text); min-width: 0; overflow-wrap: break-word; }
.donut-leg-pct { color: var(--ink-62); font-weight: 600; margin-left: 6px; min-width: 34px; text-align: right; }

/* Gesture-allowance donut ("polo") segment colours. Fixed semantic pairs drawn
   from the AA-verified --num-* set: each token flips per theme and is designed
   as AA body text, so as ring fills it clears the 3:1 non-text-contrast bar in
   both themes. The 2px --bg gaps separate adjacent arcs and every legend row
   carries label + count + %, so colour is never the only signal (WCAG 1.4.1).
     Plan     Green→Lime     Rollover Teal→Cyan
     Boost    Amber→Gold     Used     Burgundy→Blush */
circle.df-bal-plan     { stroke: var(--num-green);    }
circle.df-bal-rollover { stroke: var(--num-teal);     }
circle.df-bal-boost    { stroke: var(--num-amber);    }
circle.df-bal-used     { stroke: var(--num-burgundy); }
.donut-leg-dot.df-bal-plan     { background: var(--num-green);    }
.donut-leg-dot.df-bal-rollover { background: var(--num-teal);     }
.donut-leg-dot.df-bal-boost    { background: var(--num-amber);    }
.donut-leg-dot.df-bal-used     { background: var(--num-burgundy); }

/* Month-scoped gestures-by-cause donut: the unfilled remainder of the
   allowance capacity renders as a muted track arc (same recessive role as
   the progress-track token; comfortably distinct from the accent arcs in
   both themes, and never the only signal — the centre carries "N of M"). */
circle.df-track { stroke: var(--track-bar); }

/* "From reminder to gesture" — summary line + stacked daily bars.
   Bar segments take the per-cause derived accent through the same --seg
   custom-property plumbing as the donut slices (never hardcoded hex); the
   legend chip variant maps --seg onto the shared .an-swatch shape. Text
   stays in ink/text tokens. */
.df-claim-summary { font-size: 13px; font-weight: 500; color: var(--ink-62); margin: 0 0 12px; }
.df-claim-summary b { font-weight: 800; font-size: 14px; color: var(--text); }
.df-bar-seg { fill: var(--seg); }
.an-swatch.df-seg { background: var(--seg); }
/* Unchosen remainder of a day's sent cohort: same recessive track token as
   the month donut's unfilled capacity arc. The legend chip gets a hairline
   border so a 12-14% alpha fill still reads as a chip in both themes. */
.df-bar-seg.df-unchosen { fill: var(--track-bar); }
.an-swatch.df-unchosen { background: var(--track-bar); border: 1px solid var(--border); }

/* ===== Re-consent banner (flat, Amber-ruled) ===== */
.df-reconsent {
  display: flex; align-items: flex-start; gap: 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-left: 4px solid var(--num-amber);
  border-radius: var(--radius);
  padding: 16px 18px;
  margin-top: 22px;
}
.df-reconsent-icon { width: 20px; height: 20px; flex: none; margin-top: 2px; color: var(--num-amber); }
.df-reconsent-body { flex: 1; min-width: 0; }
.df-reconsent-body strong { color: var(--text); font-size: 15px; }
.df-reconsent-body p { color: var(--ink-62); font-size: 14px; margin: 4px 0 0; }
.df-reconsent .btn { white-space: nowrap; }
@media (max-width: 560px) {
  .df-reconsent { flex-wrap: wrap; }
  .df-reconsent .btn { margin-left: 32px; }
}

/* ===== "This month" surfaces alignment =====
   The funnel "This month" grid and the analytics strip stack as the dashboard's
   two period-stat rows. Match the strip's inner gutter (global 18px 20px) to
   the funnel cells' 16px content inset so the first strip metric lines up
   vertically with the first funnel metric, and put both section heads on one
   rhythm. Presentation only — no metrics added or removed. */
#dashboard-analytics-strip { padding-left: 16px; padding-right: 16px; }

/* ===== Headline band (proof-of-success layout, owner-directed 2026-07-10) =====
   The Teal band leads the page as its hero statement: four headline numbers,
   larger numerals than the in-section strip it replaced, generous padding. */
/* ===== Analytics-window selector (owner-directed 2026-07-10): a date input
   above the ledger that scopes the period-sensitive tables and graphs ===== */
.dash-window-row {
  display: flex; align-items: center; justify-content: flex-end; gap: 10px;
  flex-wrap: wrap; margin: 0 0 14px;
}
.dash-window-label { font-size: 13px; font-weight: 600; color: var(--ink-62); }
.dash-window-input {
  font-family: inherit; font-size: 14px; font-weight: 600; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  padding: 8px 12px;
}
.dash-window-input:focus-visible { outline: 2px solid var(--num-teal); outline-offset: 2px; }
/* "Gestures Remaining": current-billing-period figure pinned to the LEFT of the
   window row (margin-right:auto), on the same top line as the date control. It
   does not react to the date filter, so it reads as a standing figure separate
   from the window-scoped stats (owner, snag row 29). */
.dash-remaining { display: inline-flex; align-items: baseline; gap: 8px; margin-right: auto; }
.dash-remaining-value { font-size: 20px; font-weight: 800; color: var(--text); line-height: 1; }
.dash-remaining-label { font-size: 13px; font-weight: 600; color: var(--ink-62); }
@media (max-width: 560px) {
  .dash-remaining { margin-right: 0; width: 100%; }
}

/* ===== Ledger layout (owner-picked design "D · The Ledger", 2026-07-10):
   totals rail + auditable per-cause table. Replaces the Teal headline band
   (.headline-strip rules below retained for git-history context) and the
   impact wallet cards. Token-driven, flat, AA in both themes. ===== */
.ledger-grid { display: grid; grid-template-columns: 250px 1fr; gap: 14px; }
@media (max-width: 899px) { .ledger-grid { grid-template-columns: 1fr; } }
/* The rail wears the bold Teal band treatment (constant in both themes,
   same proven pair as the retired .analytics-strip: Lime lead numeral +
   paper text on Teal) — the page's colour anchor, esp. in light mode. */
.ledger-rail {
  background: var(--teal); border: 1px solid var(--teal);
  border-radius: var(--radius); padding: 20px;
  /* Stretch to the ledger panel's height (owner-directed 2026-07-10, "for
     balance"); the stat rows spread down the full teal band. */
  display: flex; flex-direction: column; justify-content: space-between;
}
/* The lead block absorbs the rail's spare height and centres its numeral +
   label both ways (owner-directed 2026-07-10); the stat rows keep the
   bottom of the band. */
.rail-lead {
  padding-bottom: 14px; flex: 1;
  display: flex; flex-direction: column; justify-content: center; align-items: center;
  text-align: center;
}
.rail-lead b { display: block; font-size: 44px; font-weight: 900; letter-spacing: -0.02em; line-height: 1; color: var(--lime); }
.rail-lead span { color: rgba(250,250,250,0.78); font-size: 12px; font-weight: 600; }
.rail-row { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; padding: 12px 0; border-top: 1px solid rgba(250,250,250,0.16); }
/* STACKED ROWS — the ones carrying a breakdown and/or the direct/referral
   split. `.rail-row` is a two-item horizontal flex (numeral | label), which is
   right for the funnel rows and wrong the moment DEF-056 added a third and
   fourth child: without this the numeral, the label AND the breakdown were
   squeezed into three narrow columns and every one of them wrapped down the
   page. The lead block escaped it only because it is flex-direction: column.

   Scoped to a modifier the renderer adds when it actually emits one of those
   children, so rows with neither keep exactly the layout they had. The
   sub-items take a full basis so each lands on its own line. */
.rail-row--stacked { flex-wrap: wrap; }
.rail-row--stacked .rail-breakdown,
.rail-row--stacked .rail-split { flex-basis: 100%; }
.rail-row .rail-breakdown {
  color: rgba(250,250,250,0.62); font-size: 11.5px; font-weight: 500; line-height: 1.5;
}
/* A flex item defaults to min-width:auto, so the breakdown's longest word set
   its floor and pushed the whole rail 436px wide inside a 248px column — the
   text escaped the teal band entirely. min-width:0 lets it shrink; the wrap
   rules let it break rather than demand the space. */
.ledger-rail, .rail-stat, .rail-lead { min-width: 0; }
.rail-breakdown { max-width: 100%; overflow-wrap: anywhere; }
.rail-row b { font-size: 20px; font-weight: 900; color: var(--paper); }
.rail-row span { color: rgba(250,250,250,0.78); font-size: 12px; font-weight: 600; }

/* ===== The direct/referral split (owner ruling 2026-07-31) =====
   A DERIVATION of the figure above it, never a competitor to it. The headline
   stays the number the customer reads first, so these two lines are quieter in
   every dimension: smaller, lighter weight, no Lime.

   The `b` override is load-bearing. Both .rail-lead b (44px Lime) and
   .rail-row b (20px paper) are sized for a headline numeral, and the split's
   numerals sit inside those blocks. Scoped two classes deep so this wins on
   specificity rather than on source order. */
.rail-split { display: block; flex-basis: 100%; margin-top: 10px; }
.rail-lead .rail-split { text-align: center; }
.rail-split .rail-split-row {
  display: block;
  font-size: 12px; font-weight: 500; line-height: 1.6;
  color: rgba(250,250,250,0.78);
}
.rail-split .rail-split-row b {
  display: inline; font-size: 13px; font-weight: 700;
  color: var(--paper); letter-spacing: 0;
}
.ledger-panel .impact-toggle { margin: 2px 0 8px; }
.ledger-note { margin: 0 0 12px; font-size: 12.5px; font-weight: 500; color: var(--ink-62); }
/* Grid items default to min-width:auto, so the table's 560px min-content
   would widen the whole grid past narrow viewports instead of letting
   .ledger-wrap scroll — min-width:0 restores the intended inner scroll. */
.ledger-grid > * { min-width: 0; }
.ledger-wrap { overflow-x: auto; }
.ledger-table { width: 100%; border-collapse: collapse; min-width: 560px; }
.ledger-table th {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em;
  /* ink-62, not ink-40: the a11y gate holds header text to AA 4.5:1 */
  color: var(--ink-62); text-align: left; padding: 0 12px 10px;
  border-bottom: 1px solid var(--border-14);
}
.ledger-table th.num, .ledger-table td.num { text-align: right; }
.ledger-table td { padding: 14px 12px; border-bottom: 1px solid var(--border); font-size: 14px; vertical-align: middle; color: var(--text); }
.ledger-cause { font-weight: 700; }
.ledger-cause-name { display: inline-block; }
.ledger-cause-name small { display: block; color: var(--ink-62); font-weight: 500; font-size: 12px; }
.ledger-table td.num b { font-size: 17px; font-weight: 900; }
/* Units numerals wear the cause's AA-derived accent (same plumbing as the
   retired wallet-card numerals) — identity + life in light mode. */
.ledger-units.df-acc { color: var(--acc-num); }
.ledger-trend { width: 118px; }
.ledger-spark { display: block; width: 110px; height: 26px; }
.ledger-spark polyline { stroke: var(--seg); }
.ledger-spark circle { fill: var(--seg); }
.ledger-legacy { display: inline-block; vertical-align: 1px; margin-left: 7px; padding: 2px 8px; border-radius: 9999px; background: var(--chip-none-bg); color: var(--ink-62); font-size: 10.5px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
.ledger-empty { color: var(--ink-62); font-weight: 500; }
.ledger-totals td { border-bottom: 0; border-top: 1px solid var(--border-14); font-weight: 700; color: var(--ink-62); font-size: 12.5px; }

.headline-strip { padding: 26px 24px; gap: 18px 28px; }
.headline-strip .analytics-stat { flex: 1 1 160px; min-width: 140px; }
.headline-strip .analytics-value { font-size: 40px; line-height: 1.05; }
.headline-strip .analytics-label { margin-top: 7px; font-size: 13px; font-weight: 600; }
@media (max-width: 719px) {
  .headline-strip { padding: 20px 18px; }
  .headline-strip .analytics-value { font-size: 32px; }
}
#dashboard-funnel-section .section-head,
#dashboard-section-analytics .section-head { margin-bottom: 12px; }

/* ===== Small helpers ===== */
.df-syncing-label { font-size: 14px; color: var(--ink-62); margin: 0 0 12px; }
.df-skel-chart { height: 220px; margin-bottom: var(--space-3); }

/* The direct/referral split, in the My Impact panel rather than the rail:
   one line with the width to stay one line. */
.ledger-split { margin: -4px 0 12px; }
.ledger-split b { color: var(--text); font-weight: 800; }
