/* ============================================================================
   LDS portal — design tokens (Portal Reboot R1, 2026-05-31)
   Single source of truth. Matches lds_brand.py (deck/docx side).
   Everything else (components.css, page styles) references these.
   ========================================================================== */
:root {
  /* Brand */
  --c-forest:    #1F4D3C;
  --c-forest-d:  #123328;
  --c-moss:      #97BC62;
  --c-sage:      #C8D4CE;
  --c-cream:     #F7F4EC;
  --c-paper:     #FFFFFF;
  --c-ink:       #1A1A1A;
  --c-ink-soft:  #55605A;
  --c-gold:      #C4993A;
  --c-warn:      #C0553C;

  /* Soft tints — for icon circles, alert backgrounds */
  --c-cream-soft: #FBF9F2;       /* icon circle default */
  --c-moss-soft:  #E8F0DC;       /* "ok" pill, low-emphasis success */
  --c-warn-soft:  #FBECE6;       /* "warn" pill, gentle */
  --c-gold-soft:  #F6EBCF;       /* "highlight" pill */

  /* Radii — softer than the legacy 4-8px */
  --r-xs:  6px;        /* form inputs, micro-pills */
  --r-sm:  10px;       /* small chips */
  --r-md:  14px;       /* cards, buttons */
  --r-lg:  20px;       /* hero, big surfaces */
  --r-pill: 9999px;    /* fully rounded */

  /* Spacing — 4px scale */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 24px;
  --s-6: 32px;
  --s-7: 48px;
  --s-8: 64px;
  --s-9: 96px;

  /* Type — match lds_brand.py.
     Fraunces is the brand display serif (loaded via Google Fonts on every
     portal page); Georgia is the offline fallback. Listing Fraunces first
     makes the token honest — the hero title now matches the panel headings,
     which already force Fraunces in styles.css. */
  --f-head:  "Fraunces", Georgia, "Iowan Old Style", "Apple Garamond", "Baskerville", serif;
  --f-body:  "Manrope", Calibri, system-ui, -apple-system, "Segoe UI", sans-serif;

  --t-eyebrow:   10px / 1.2  var(--f-body);  /* MOSS, uppercase, +0.12em letter-spacing */
  --t-body:      14px / 1.55 var(--f-body);
  --t-body-lg:   16px / 1.55 var(--f-body);
  --t-h3:        18px / 1.25 var(--f-head);
  --t-h2:        22px / 1.2  var(--f-head);
  --t-h1:        32px / 1.1  var(--f-head);
  --t-hero:      48px / 1.05 var(--f-head);
  --t-stat:      40px / 1.0  var(--f-head);
  --t-stat-lg:   56px / 1.0  var(--f-head);

  /* Shadows — almost invisible, only on lifted surfaces */
  --shadow-1: 0 1px 2px rgba(20, 35, 26, 0.04), 0 1px 1px rgba(20, 35, 26, 0.02);
  --shadow-2: 0 6px 16px rgba(20, 35, 26, 0.06), 0 2px 4px rgba(20, 35, 26, 0.03);

  /* Borders */
  --border-hairline: 1px solid var(--c-sage);

  /* Motion */
  --motion-fast: 120ms cubic-bezier(0.2, 0.8, 0.2, 1);
  --motion-base: 200ms cubic-bezier(0.2, 0.8, 0.2, 1);
  --motion-slow: 550ms cubic-bezier(0.2, 0.8, 0.2, 1);  /* FLIP re-order, line trace */
  --ease-out-soft: cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* ============================================================================
   Iconography helpers — Lucide sprite at /styles/icons.svg
   Usage: <svg class="lds-icon"><use href="/styles/icons.svg#icon-zap"></use></svg>
   stroke-width 1.5 per the brand brief (Lucide ships at 2).
   ========================================================================== */
.lds-icon {
  width: 20px;
  height: 20px;
  flex: 0 0 auto;
  stroke-width: 1.5;
  vertical-align: middle;
}
.lds-icon--18 { width: 18px; height: 18px; }  /* list items, secondary inline */
.lds-icon--16 { width: 16px; height: 16px; }  /* micro pills, status badges */
.lds-icon--24 { width: 24px; height: 24px; }  /* hero accent only */

/* Containment — stat-card icon circle (32px, cream-soft, forest stroke) */
.lds-icon-circle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--r-pill);
  background: var(--c-cream-soft);
  color: var(--c-forest);
  flex: 0 0 auto;
}
/* Alert variant — 24px, warn-soft, warn stroke */
.lds-icon-circle--alert {
  width: 24px;
  height: 24px;
  background: var(--c-warn-soft);
  color: var(--c-warn);
}

/* ============================================================================
   Product shield helper — Levant (OnDark canonical) at /styles/shields/
   Usage: <svg class="lds-shield"><use href="/styles/shields/Lantern_Shield_OnDark.svg#shield"/></svg>
   ========================================================================== */
.lds-shield {
  width: 48px;          /* hero placement */
  height: 48px;
  flex: 0 0 auto;
}
.lds-shield--inline { width: 32px; height: 32px; }  /* household header / breadcrumb */
@media (max-width: 640px) {
  .lds-shield { width: 40px; height: 40px; }        /* hero on mobile */
}

/* ============================================================================
   Visual Refresh R3 (2026-06-20) — semantic + status + data-viz + density.

   WHY: the live portal (styles.css + portal.js) historically hard-coded a
   teal/amber/beige palette (#0f766e, #d97706, #fbfaf7 ...) that diverged from
   the forest-green brand. This layer makes forest-green the single source of
   truth: the semantic aliases below let legacy `var(--accent)` / `var(--muted)`
   usages resolve to brand tokens, and the status + viz tokens give one place
   for every state colour so the JS can't drift again.

   ACCESSIBILITY CONTRACT:
   - Status colours are tuned so the *-ink text meets WCAG AA (≥4.5:1) on its
     own *-bg. Verified pairings noted inline.
   - Status is NEVER colour-alone: every status chip / risk card / trend marker
     must also carry an icon + word in the markup (the renderer enforces this).
   - Data-viz hues differ in *lightness* as well as hue, so series stay
     distinguishable in greyscale / for colour-blind advisers; secondary series
     also use dash patterns in the SVG.
   ========================================================================== */
:root {
  /* --- Semantic aliases — retire the legacy teal accent for forest-green --- */
  --accent:        var(--c-forest);     /* primary action / links / chart elec */
  --accent-strong: var(--c-forest-d);   /* hover / pressed */
  --accent-soft:   var(--c-moss-soft);  /* selected-chip wash, low-emphasis */
  --on-accent:     var(--c-paper);      /* text/icons on an accent surface */
  --ink:           var(--c-ink);
  --muted:         var(--c-ink-soft);
  --panel:         var(--c-paper);
  --panel-soft:    var(--c-cream-soft); /* nested cards, gene rows, notes */
  --border:        var(--c-sage);
  --border-strong: #AEBFB6;             /* table header rule, a step past sage */
  --shadow:        var(--shadow-1);     /* legacy single-name shadow alias */

  /* --- Status system — text meets AA on its paired soft background --------- */
  /* OK / steady — forest-derived green (#1B5E43 on #E8F0DC ≈ 6.4:1) */
  --status-ok-ink:        #1B5E43;
  --status-ok-bg:         var(--c-moss-soft);
  --status-ok-border:     #7FB069;
  /* WATCH / amber — darkened so it passes AA (#8A4B16 on #FBEBD2 ≈ 5.6:1) */
  --status-watch-ink:     #8A4B16;
  --status-watch-bg:      #FBEBD2;
  --status-watch-border:  #D9943B;
  /* ALERT / call now — warm red (#A23320 on #FBECE6 ≈ 6.1:1) */
  --status-alert-ink:     #A23320;
  --status-alert-bg:      var(--c-warn-soft);
  --status-alert-border:  var(--c-warn);
  /* INFO / loading — forest on a cool tint (#1F4D3C on #EAF1EE ≈ 8.0:1) */
  --status-info-ink:      var(--c-forest);
  --status-info-bg:       #EAF1EE;
  --status-info-border:   #9DBBAE;
  /* NEUTRAL — quiet grey (#55605A on #EEF0EC ≈ 6.0:1) */
  --status-neutral-ink:   var(--c-ink-soft);
  --status-neutral-bg:    #EEF0EC;
  --status-neutral-border: var(--c-sage);

  /* --- Data-viz palette — brand-anchored, greyscale-distinguishable -------- */
  --viz-elec:        var(--c-forest);   /* electricity — primary series */
  --viz-elec-fill:   rgba(31, 77, 60, 0.12);
  --viz-gas:         var(--c-gold);     /* gas */
  --viz-gas-fill:    rgba(196, 153, 58, 0.12);
  --viz-export:      #6B8E5A;           /* export — also dashed in the SVG */
  --viz-export-fill: rgba(107, 142, 90, 0.12);
  --viz-carbon:      var(--c-ink-soft); /* carbon */
  /* Measured INDOOR temperature, against --viz-outdoor-temp's cool blue. Warm vs
     cool rather than two hues of one family: "inside" and "outside" are opposites,
     and the pairing has to survive greyscale and a protanopic reader. */
  --viz-indoor-temp: #C07A5E;
  --viz-grid:        #E4E9E5;           /* gridlines */
  --viz-axis:        #8A958F;           /* axis labels / ticks */

  /* --- Density — comfortable by default; body.is-compact tightens the rhythm.
     Independent of the volunteer/detailed CONTENT toggle (§3 density toggle). --- */
  --density-row-pad:  0.7rem 0.75rem;   /* table/list cell padding */
  --density-card-gap: 16px;             /* household grid gap */
  --density-card-pad: 18px;             /* household card padding */
  --density-card-min: 238px;            /* household card min-height */
}

/* ============================================================================
   Elevation layer (2026-08-16) — surfaces, hairlines, shadows, easing.

   WHY THESE ARE HERE AND NOT IN portal-v3.css: they used to be declared inside
   `.pv3{...}`, so they only resolved for a document whose <body> carried that
   class. A page that linked the stylesheet but forgot the class rendered with
   transparent borders, no shadows and no page background — broken, but silently,
   because every rule still applied and only the var() lookups failed.

   That was survivable while one page used the system. It is not survivable now
   that every page is adopting it. Declared on :root, a missing `pv3` class costs
   you the body canvas and nothing else, which is a visible, diagnosable failure.
   ========================================================================== */
:root {
  --paper:       #FFFFFF;   /* card surface */
  --page-1:      #F6F2E9;   /* page canvas, top of the gradient */
  --page-2:      #EFEADD;   /* page canvas, foot of the gradient */
  --hair:        rgba(31, 77, 60, 0.12);   /* forest at 12% — card borders */
  --hair-soft:   rgba(31, 77, 60, 0.07);   /* forest at 7% — inner rules */
  --keel:        linear-gradient(90deg, var(--c-gold), #E4C97F 60%, transparent);
  --shadow-card: 0 1px 2px rgba(20, 35, 26, 0.04), 0 10px 30px rgba(20, 35, 26, 0.07);
  --shadow-lift: 0 2px 6px rgba(20, 35, 26, 0.06), 0 22px 48px rgba(20, 35, 26, 0.12);
  --ease:        cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* Compact density: tighter rhythm so an adviser fits more households on screen. */
body.is-compact {
  --density-row-pad:  0.5rem 0.6rem;
  --density-card-gap: var(--s-3);
  --density-card-pad: 13px;
  --density-card-min: 188px;
}
