/* ROI calculator (roi-calculator.php). Loaded after styles.css through $pageStylesheets.
   Ported from the approved design (pages.css section G). State hooks set by calculator.js
   on [data-roi-calculator]:
     data-distribution-source  quote | custom | quantity | unpriced | unavailable
     data-result               "dashes" while a figure cannot be used, so the result shows no number
     data-invalid              present while the result card explains what to correct */

/* Head: the lead's first line sits level with the H1's cap height (kicker 12px + 24px gap) */
.roi-head { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); }
.roi-head .lead { margin-top: 0; }
.roi-head .caption { margin-top: var(--space-3); max-width: 36em; }
@media (min-width: 1080px) {
  .roi-head { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); column-gap: clamp(48px, 6vw, 96px); align-items: start; }
  .roi-head__copy { padding-top: 44px; }
}

/* Form card and result card */
.roi-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); padding-bottom: var(--section-pad); }
@media (min-width: 1080px) {
  .roi-grid { grid-template-columns: minmax(0, 7fr) minmax(0, 4.6fr); gap: clamp(24px, 3vw, 40px); align-items: start; }
  /* Sticky 16px below the header, as designed. calculator.js sets --roi-card-h (card height) and
     --roi-card-lead (card top to the "Estimated ROI" label): a card taller than the window is pinned
     by its bottom edge instead, but never so high that the ROI label and figure go under the header. */
  .roi-result {
    position: sticky;
    top: max(calc(var(--header-h) + 16px - var(--roi-card-lead, 0px)), min(calc(var(--header-h) + 16px), calc(100vh - var(--roi-card-h, 0px) - 16px)));
  }
}
.roi-form { padding: clamp(20px, 3vw, 36px); box-shadow: var(--shadow-print); }
.roi-form__top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); }
.roi-form__intro { margin-top: var(--space-3); }
/* Each option's radio covers the full track height (48px), so the touch target is at least 44px */
.roi-mode .segmented__option input { top: -3px; height: calc(100% + 6px); }
.roi-fields { display: grid; gap: 0; margin-top: var(--space-4); }
.roi-set { padding-block: var(--space-5); border-top: 1px solid var(--rule); }
.roi-set legend { float: left; width: 100%; margin-bottom: var(--space-4); font-size: var(--fs-micro); font-weight: 600; letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--accent-text); }
.roi-set legend + * { clear: both; }
.roi-set__intro { margin: calc(-1 * var(--space-2)) 0 var(--space-4); font-size: var(--fs-small); color: var(--text-muted); }
.roi-set__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
@media (min-width: 620px) { .roi-set__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; } }
.roi-set > .caption { margin-top: var(--space-3); }
/* The three percentages are number fields; the bespoke fields show no native steppers in any engine
   (Firefox and Safari draw them at all times). Arrow keys still step the value. */
.roi-fields input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.roi-fields input[type="number"]::-webkit-inner-spin-button,
.roi-fields input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

/* Distribution cost: Quote rate (green-50) or the visitor's own figure (neutral paper).
   A typed figure is a legitimate choice, not an error: terracotta tag only, never error pink. */
.roi-distribution { margin-bottom: var(--space-4); padding: var(--space-4); border-radius: var(--radius-m); background: var(--green-50); box-shadow: inset 0 0 0 1px rgba(18, 53, 46, 0.1); }
[data-roi-calculator]:not([data-distribution-source="quote"]) .roi-distribution { background: var(--paper-200); box-shadow: inset 0 0 0 1px rgba(18, 53, 46, 0.14); }
.roi-distribution__label { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.roi-distribution .tag .icon { width: 13px; height: 13px; stroke-width: 2.4; }
.roi-distribution .input-affix { max-width: 16rem; }
.roi-distribution__basis { display: grid; gap: 4px; font-size: var(--fs-caption); line-height: 1.5; color: var(--text); }
.roi-distribution__text { display: grid; gap: 4px; }
.roi-distribution__basis strong { color: var(--text-strong); }
/* The label wraps before the figure when a large Quote cost does not fit the panel (320px) */
.roi-distribution__use { justify-self: start; max-width: 100%; margin-top: 8px; padding-block: 10px; white-space: normal; text-align: center; line-height: calc(1em + 4px); }
.roi-distribution__use [data-quote-cost] { white-space: nowrap; }
/* The button itself is the hit target, so a press on the price text activates it in every engine (WebKit drops a
   click when the pressed text changes under the pointer). */
.roi-distribution__use span { pointer-events: none; }
.roi-distribution [data-quote-quantity] { white-space: nowrap; }

.roi-spend { max-width: 22rem; }
.roi-actions { display: flex; justify-content: flex-end; padding-top: var(--space-4); border-top: 1px solid var(--rule); }

/* Result card: the page's only green surface. "Breakdown" lands it 16px below the header through
   the shared html scroll-padding-top (a scroll-margin here would add the offset twice). */
.roi-result { border-radius: var(--radius-l); background: var(--green-900); color: var(--on-inverse); box-shadow: var(--shadow-print); }
.roi-result__inner { padding: clamp(22px, 2.6vw, 32px); }
.roi-result__top { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.roi-result__top .kicker { color: var(--on-inverse-muted); }
.roi-result__flag { padding: 4px 10px; border: 1px solid var(--rule-inverse); border-radius: var(--radius-pill); font-size: 0.75rem; font-weight: 600; color: var(--on-inverse-muted); }
.roi-result__label { margin-top: var(--space-4); font-size: var(--fs-small); color: var(--on-inverse-muted); }
.roi-result__value { display: block; font-family: var(--font-display); font-weight: 340; font-size: clamp(3.5rem, 2.6rem + 3.4vw, 5.5rem); line-height: 0.95; letter-spacing: -0.04em; color: var(--on-inverse); font-variant-numeric: lining-nums tabular-nums; white-space: nowrap; } /* calculator.js sets a smaller size when a figure is too long for the card */
/* While a figure is invalid the result shows dashes and says why (no silently clamped numbers) */
.roi-result__check { display: none; margin-top: var(--space-3); padding: 10px 12px; border-radius: var(--radius-m); background: rgba(247, 242, 232, 0.1); font-size: var(--fs-small); font-weight: 600; color: var(--on-inverse); }
[data-roi-calculator][data-invalid] .roi-result__check, .roi-result__check--static { display: flex; gap: 8px; align-items: flex-start; }
.roi-result__check .icon { width: 18px; height: 18px; margin-top: 1px; color: var(--on-inverse-accent); flex: none; }
[data-roi-calculator][data-result="dashes"] .roi-result__value, [data-roi-calculator][data-result="dashes"] .roi-rows dd { color: var(--on-inverse-muted); }
.roi-result__explain { margin-top: var(--space-3); font-size: var(--fs-caption); color: var(--on-inverse-muted); }
.roi-rows { display: grid; grid-template-columns: minmax(0, 1fr); margin-top: var(--space-4); }
.roi-rows > div { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); padding-block: 9px; border-top: 1px solid var(--rule-inverse); font-size: var(--fs-small); }
.roi-rows dt { flex: 1 1 0; color: var(--on-inverse-muted); }
/* A figure too long for the row wraps inside it rather than leaving the card */
.roi-rows dd { min-width: 0; font-weight: 600; color: var(--on-inverse); font-variant-numeric: lining-nums tabular-nums; text-align: right; overflow-wrap: break-word; }
.roi-rows > .roi-rows__total { border-top-color: rgba(247, 242, 232, 0.5); }
.roi-rows__total dt { color: var(--on-inverse); font-weight: 600; }
.roi-rows__total dd { font-family: var(--font-display); font-weight: 400; font-size: 1.5rem; }
.roi-result__note { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--rule-inverse); font-size: var(--fs-caption); color: var(--on-inverse-muted); }
/* Short laptop screens (1366x768, 1280x720): a slightly tighter card, so the default estimate
   fits below the header without being pinned (the designed sizes apply from 820px tall). */
@media (min-width: 1080px) and (max-height: 819px) {
  .roi-result__inner { padding: 24px 28px; }
  .roi-result__label { margin-top: var(--space-3); }
  .roi-result__value { font-size: clamp(3.5rem, 1.6rem + 3.4vw, 4.5rem); }
  .roi-result__explain, .roi-result__check { margin-top: var(--space-2); }
  .roi-rows { margin-top: var(--space-3); }
  .roi-rows > div { padding-block: 6px; }
  .roi-result__note { margin-top: var(--space-3); padding-top: var(--space-3); }
  /* While every figure is a dash the ROI definition is not needed; the note takes its place */
  [data-roi-calculator][data-invalid] .roi-result__explain { display: none; }
}

/* Live result strip (below 1080px): sticky inside the form card, never fixed to the viewport.
   It fades out while the full result card is in view and keeps its place, so nothing moves. */
.roi-strip { display: none; }
@media (max-width: 1079px) {
  .roi-strip {
    position: sticky;
    top: calc(var(--header-h) + 8px);
    z-index: 5;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: 56px;
    margin: var(--space-4) calc(-1 * clamp(8px, 1.5vw, 16px)) 0;
    padding: 8px 8px 8px 16px;
    border-radius: var(--radius-m);
    background: var(--green-900);
    color: var(--on-inverse);
    box-shadow: 0 12px 24px -16px rgba(18, 53, 46, 0.6);
    /* visibility switches at the end of the fade out and at the start of the fade in */
    transition: opacity var(--dur-fast) var(--ease-out), visibility var(--dur-fast) var(--ease-out);
  }
  .roi-strip.is-concealed { visibility: hidden; opacity: 0; }
  /* A focused field or button scrolls clear of the strip with its label and its focus ring whole
     (the shared html scroll-padding-top already clears the header). calculator.js keeps
     --roi-strip-h at the strip's measured height (0 while it is faded out), and moves a field
     the strip still covers in engines that ignore scroll-margin when focus moves (WebKit). */
  .roi-fields :is(input, button) { scroll-margin-top: calc(var(--roi-strip-h, 72px) + 40px); }
}
.roi-strip__figs { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 14px; flex: 1 1 auto; min-width: 0; font-size: var(--fs-caption); color: var(--on-inverse-muted); }
.roi-strip__figs > span { white-space: nowrap; }
.roi-strip__figs strong { font-family: var(--font-display); font-weight: 400; font-size: 1.375rem; line-height: 1.1; color: var(--on-inverse); font-variant-numeric: lining-nums tabular-nums; overflow-wrap: break-word; }
.roi-strip a { --btn-bg: var(--paper-50); --btn-fg: var(--green-950); --btn-bg-hover: var(--paper-200); flex: none; padding: 0 14px; }
.roi-strip a .icon { width: 16px; height: 16px; }
/* Below 430px the Breakdown button is icon-only (as the planner's result-bar button), so each
   figure keeps its label on one line (labels are bound with non-breaking spaces in the markup and
   each label-and-figure pair never wraps) and the strip stays two short lines at most. The strip
   is aria-hidden; the full results card carries the figures. */
@media (max-width: 429px) {
  .roi-strip { gap: var(--space-2); padding-left: 14px; }
  .roi-strip a { width: 44px; padding: 0; }
  .roi-strip__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
@media (max-width: 374px) {
  .roi-distribution__label { flex-wrap: wrap; row-gap: 6px; }
  .roi-distribution__label .field__label { white-space: nowrap; }
}

/* Without JavaScript nothing recalculates: no mode switch, its explanation or the strip */
.no-js .roi-mode, .no-js .roi-strip, .no-js [data-simple-assumptions] { display: none; }

/* Forced colours drop backgrounds and shadows, so the panels keep a visible edge */
@media (forced-colors: active) {
  .roi-distribution, .roi-result, .roi-strip, .roi-result__check { border: 1px solid CanvasText; }
}

/* The calculation */
.roi-formula { padding-block: var(--section-pad); background: var(--surface-alt); }
.roi-formula__steps { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-6); }
@media (min-width: 900px) { .roi-formula__steps { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(24px, 4vw, 64px); } }
.roi-formula__steps span { font-family: var(--font-display); font-style: italic; font-size: var(--fs-display-m); color: var(--accent-text); }
.roi-formula__steps h3 { margin-top: var(--space-2); }
.roi-formula__steps p { margin-top: var(--space-3); max-width: 28em; }

/* Questions */
.roi-faq { padding-block: var(--section-pad); }
.roi-faq__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-7); }
@media (min-width: 1080px) { .roi-faq__grid { grid-template-columns: minmax(0, 4fr) minmax(0, 7fr); column-gap: clamp(48px, 7vw, 120px); } }
.roi-faq .lead { margin-top: var(--space-4); max-width: 24em; }

/* End band on paper-200 (the result card stays the only green surface) */
.roi-cta { padding-block: clamp(56px, 6vw, 88px); background: var(--surface-alt); }
.roi-cta__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); }
@media (min-width: 1080px) { .roi-cta__grid { grid-template-columns: minmax(0, 7fr) minmax(0, 4.4fr); column-gap: clamp(48px, 6vw, 112px); align-items: end; } }
/* Kickers are terracotta on paper (DESIGN-SPEC §2 component table); the body-text rule below must not darken it */
.roi-cta .kicker { margin-bottom: var(--space-4); color: var(--accent-text); }
.roi-cta p { color: var(--text); max-width: 32em; }
.roi-cta__actions { margin-top: var(--space-5); }
