/* ============================================================================
   Project configurator on /pricing.html.

   Markup: src/_includes/partials/pricing-configurator.njk
   Logic:  assets/js/pricing-configurator.js

   Layout is an option list beside a summary that sticks to the viewport on
   desktop, so the total stays in view while the list is worked through.

   Each option row is its own grid rather than a table: a table would either
   scroll sideways at 320px or need the same stacked-block override the
   definition table in ecopi-components.css already carries. Because every row
   is a separate grid, the columns are given fixed widths — a content-sized
   control column would be 22px wide on a checkbox row and 116px on a stepper
   row, and the option names would no longer line up.

   No opacity is used to grey out an unselected row. Halving the opacity of
   muted body text puts it below the AA minimum, and tools/verify.js samples
   real pixels; the dash in the amount column carries that signal instead.
   ========================================================================= */

.ep-cfg {
  margin-top: var(--ep-space-6);
}

.ep-cfg__layout {
  display: grid;
  gap: var(--ep-space-6);
}

@media (min-width: 62em) {
  .ep-cfg__layout {
    grid-template-columns: minmax(0, 1fr) 21rem;
    align-items: start;
    gap: var(--ep-space-7);
  }
}

.ep-cfg__panels {
  display: grid;
  gap: var(--ep-space-5);
}

/* ---- Option group -------------------------------------------------------
   A <fieldset>, so the legend names the group for assistive technology. The
   legend is floated because a legend in normal flow is laid into the
   fieldset's own border, and this fieldset draws a card border instead. Every
   block that can follow it therefore clears the float. */

.ep-cfg__group {
  min-width: 0;                          /* fieldsets default to min-content */
  margin: 0;
  padding: var(--ep-space-5);
  border: 1px solid var(--ep-border);
  border-radius: var(--ep-radius-lg);
  background: var(--ep-bg-card);
}

.ep-cfg__legend {
  float: left;
  width: 100%;
  margin: 0;
  padding: 0;
  color: var(--ep-text);
  font-family: var(--ep-font-heading);
  font-size: var(--ep-h4);
  font-weight: 600;
  line-height: var(--ep-leading-snug);
}

.ep-cfg__caption,
.ep-cfg__rows,
.ep-cfg-scope {
  clear: both;
}

.ep-cfg__caption {
  margin: var(--ep-space-1) 0 var(--ep-space-4);
  color: var(--ep-text-secondary);       /* 7.19:1 on --ep-bg-card */
  font-size: var(--ep-text-sm);
}

/* ---- Scope: number of devices and duration ------------------------------ */

.ep-cfg-scope {
  display: grid;
  gap: var(--ep-space-5);
  margin-top: var(--ep-space-4);
}

@media (min-width: 48em) {
  .ep-cfg-scope {
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--ep-space-7);
    align-items: start;
  }
}

.ep-cfg-scope__label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--ep-space-3);
  margin-bottom: var(--ep-space-2);
  color: var(--ep-text);
  font-weight: 600;
}

.ep-cfg-scope__value {
  color: var(--ep-primary);              /* 6.41:1 on --ep-bg-card */
  font-size: var(--ep-h4);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.ep-cfg-scope__hint {
  margin: var(--ep-space-2) 0 0;
  color: var(--ep-text-secondary);
  font-size: var(--ep-text-sm);
}

/* The live discount-tier reading gets its own colour so it stands out from
   the static explanation above it — it is the one line on this page that
   changes as a direct consequence of dragging the slider, not of ticking a
   box. */
.ep-cfg-scope__hint--term strong {
  color: var(--ep-primary);              /* 6.41:1 on --ep-bg-card */
}

.ep-cfg-range {
  width: 100%;
  height: 2.5rem;                        /* WCAG 2.5.8 pointer target */
  margin: 0;
  accent-color: var(--ep-primary);
  cursor: pointer;
}

.ep-cfg-range-wrap {
  position: relative;
}

/* Waypoint dashes sitting on the track, at the exact percentage each year
   lands on the 1-48 range (see pricingOptions.js — the range does not start
   at 0, so a plain quarter-of-48 would visibly miss the thumb's real
   positions). A small ring rather than a plain bar, so it stays visible
   whether it happens to sit on the filled or the unfilled half of the
   track. `pointer-events: none` keeps it from ever stealing a drag from the
   input it overlays. */
.ep-cfg-range-dashes {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.ep-cfg-range-dashes__dash {
  position: absolute;
  top: 50%;
  left: 0;                               /* overridden per mark by an inline percentage */
  width: 0.5rem;
  height: 0.5rem;
  transform: translate(-50%, -50%);
  border: 2px solid var(--ep-primary);
  border-radius: 50%;
  background: var(--ep-bg-card);
}

/* The last mark always lands at 100% of the track, where centring the ring
   on that point would push half of it past the input's own edge — anchored
   to the edge instead, the same fix the label row below needs for the same
   reason. */
.ep-cfg-range-dashes__dash[data-ep-edge="end"] {
  left: auto;
  right: 0;
  transform: translate(50%, -50%);
}

/* Four years across the 1-48 range, each label under its own dash above.
   Decorative: the live reading further down is what a screen reader
   announces, so this row and the dashes on the track are both
   aria-hidden. */
.ep-cfg-ticks {
  position: relative;
  height: 2.5rem;
  margin-top: var(--ep-space-1);
}

.ep-cfg-ticks__mark {
  position: absolute;
  top: 0;
  left: 0;                               /* overridden per mark by an inline percentage */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.125rem;
  transform: translateX(-50%);
  font-size: var(--ep-text-xs);
  white-space: nowrap;
}

.ep-cfg-ticks__mark[data-ep-edge="end"] {
  left: auto;
  right: 0;
  align-items: flex-end;
  transform: none;
}

.ep-cfg-ticks__year {
  color: var(--ep-text-muted);           /* 5.28:1 on --ep-bg-card */
  font-weight: 600;
}

.ep-cfg-ticks__pct {
  color: var(--ep-accent);               /* 6.00:1 on --ep-bg-card */
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* ---- Column heading -----------------------------------------------------
   Names the two amount columns for sighted readers. Hidden from assistive
   technology because it labels nothing programmatically; each row carries its
   own visually-hidden labels instead. */

.ep-cfg-head {
  display: none;
}

@media (min-width: 48em) {
  .ep-cfg-head {
    display: grid;
    grid-template-columns: 7.75rem minmax(0, 1fr) 12rem;
    gap: var(--ep-space-4);
    padding-bottom: var(--ep-space-2);
    border-bottom: 1px solid var(--ep-border);
    color: var(--ep-text-muted);         /* 5.28:1 on --ep-bg-card */
    font-size: var(--ep-text-xs);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }

  .ep-cfg-head__label {
    grid-column: 1 / 3;
  }

  .ep-cfg-head__amounts {
    grid-column: 3;
    display: flex;
    justify-content: space-between;
    gap: var(--ep-space-4);
  }
}

/* Subtle grouping within a group's row list (e.g. "Power supply" and
   "Connectivity" inside Hardware) — a small label, not a second fieldset, so
   it reads as a hint about the rows below it rather than a new section of
   the page. The row above already ends in a border, so this only needs
   space, not a rule of its own. */
.ep-cfg-subsection {
  margin: var(--ep-space-4) 0 var(--ep-space-1);
  color: var(--ep-text-muted);           /* 5.28:1 on --ep-bg-card */
  font-size: var(--ep-text-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.ep-cfg-subsection:first-child {
  margin-top: 0;
}

/* ---- Option row --------------------------------------------------------- */

.ep-cfg-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas:
    "control text"
    "amounts amounts";
  gap: var(--ep-space-2) var(--ep-space-4);
  padding: var(--ep-space-4) 0;
  border-bottom: 1px solid var(--ep-border);
}

/* The browser's own `[hidden] { display: none }` rule is user-agent origin,
   so it loses to this file's own `display: grid` above at equal specificity
   — restated here so a forced-only row (e.g. the Y-cable below two solar
   panels) actually disappears instead of leaving an empty grid box. */
.ep-cfg-row[hidden] {
  display: none;
}

.ep-cfg-row:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}

/* A stepper is 116px wide, which on a 390px screen left the longest option
   names running over four lines. Below the breakpoint those rows put the name
   on its own full-width line and the stepper next to the amounts, where it
   reads as the quantity picker it is. Checkbox rows are only 24px of control
   and keep the name beside it. */
@media (max-width: 47.99em) {
  .ep-cfg-row:has(.ep-cfg-stepper) {
    grid-template-areas:
      "text text"
      "control amounts";
    align-items: center;
  }
}

@media (min-width: 48em) {
  .ep-cfg-row {
    grid-template-columns: 7.75rem minmax(0, 1fr) 12rem;
    grid-template-areas: "control text amounts";
    align-items: center;
  }
}

.ep-cfg-row__control {
  grid-area: control;
  display: flex;
  align-items: center;
}

.ep-cfg-row__text {
  grid-area: text;
  min-width: 0;
}

.ep-cfg-row__name {
  display: block;
  margin: 0;
  color: var(--ep-text);
  font-weight: 600;
  line-height: var(--ep-leading-snug);
}

/* Only a real control makes the name clickable. */
label.ep-cfg-row__name {
  cursor: pointer;
}

.ep-cfg-row__hint {
  margin: var(--ep-space-1) 0 0;
  color: var(--ep-text-secondary);       /* 7.19:1 on --ep-bg-card */
  font-size: var(--ep-text-sm);
  line-height: var(--ep-leading-snug);
}

.ep-cfg-row__amounts {
  grid-area: amounts;
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  gap: var(--ep-space-4);
  white-space: nowrap;
}

@media (min-width: 48em) {
  .ep-cfg-row__amounts {
    justify-content: space-between;
  }
}

.ep-cfg-row__unit {
  color: var(--ep-text-muted);           /* 5.28:1 on --ep-bg-card */
  font-size: var(--ep-text-sm);
  font-variant-numeric: tabular-nums;
}

.ep-cfg-row__line {
  color: var(--ep-text);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.ep-cfg-row__request {
  color: var(--ep-text-muted);
  font-size: var(--ep-text-sm);
  font-weight: 400;
}

/* Not selected: the amount column reads as a dash rather than a figure. */
.ep-cfg-row.is-off .ep-cfg-row__line {
  color: var(--ep-text-muted);
  font-weight: 400;
}

/* ---- Controls ----------------------------------------------------------- */

.ep-cfg-box {
  width: 1.5rem;
  height: 1.5rem;
  margin: 0;
  accent-color: var(--ep-primary);       /* radio rows, still drawn natively */
  cursor: pointer;
}

/* The checkbox is drawn here rather than left to the browser, for one reason:
   a row can be forced on by another row (LTE connectivity once the external
   antenna kit is picked, the data plan once LTE is), and a *native* checkbox
   in that state is painted grey by the browser no matter what accent-color
   says — which reads as "this one does not count" on rows that very much do,
   and made two ticks in the same list two different colours. Every tick is
   therefore the same teal whether the reader set it or another row did; only
   the cursor still says the control is locked. `disabled` continues to do the
   locking, so nothing about the interaction or what assistive technology
   announces changes. */
.ep-cfg-box[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  border: 2px solid var(--ep-border-strong);
  border-radius: var(--ep-radius-sm);
  background-color: var(--ep-bg-card);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 1rem 1rem;
}

/* The tick is an inline SVG data URI rather than a ::before pseudo-element,
   which an <input> is not allowed to have. currentColor is no use inside a
   data URI, so the stroke is the literal --ep-text-inverse (#FFFFFF). */
.ep-cfg-box[type="checkbox"]:checked {
  border-color: var(--ep-primary);
  background-color: var(--ep-primary);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='m3 8.5 3.2 3.2L13 5' stroke='%23FFFFFF' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

.ep-cfg-box[type="checkbox"]:not(:disabled):hover {
  border-color: var(--ep-primary);
}

/* Locked by another row, either forced on or ruled out. Only the cursor
   changes: see the note above on why the tick keeps its colour. */
.ep-cfg-box:disabled {
  cursor: not-allowed;
}

.ep-cfg-row:has(.ep-cfg-box:disabled) .ep-cfg-row__name {
  cursor: default;
}

.ep-cfg-row__note {
  margin: var(--ep-space-1) 0 0;
  color: var(--ep-text-secondary);       /* 7.19:1 on --ep-bg-card */
  font-size: var(--ep-text-sm);
  font-style: italic;
}

/* Dropdown for a row with several tiers (e.g. storage capacity), so adding a
   third or fourth tier later is a new <option>, not a new row. Native
   appearance is switched off so the arrow can be drawn with a token colour
   instead of baking a hex value into a background-image data URI. */
.ep-cfg-select-wrap {
  position: relative;
  display: inline-flex;
  width: 7.5rem;
}

.ep-cfg-select-wrap::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 0.9rem;
  width: 0.45rem;
  height: 0.45rem;
  border-right: 2px solid var(--ep-primary);
  border-bottom: 2px solid var(--ep-primary);
  transform: translateY(-65%) rotate(45deg);
  pointer-events: none;
}

.ep-cfg-select {
  width: 100%;
  height: 2.375rem;                      /* matches .ep-cfg-stepper */
  padding: 0 1.75rem 0 0.75rem;
  border: 1px solid var(--ep-border-strong);
  border-radius: var(--ep-radius-md);
  background: var(--ep-bg-card);
  color: var(--ep-text);
  font-weight: 700;
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  cursor: pointer;
}

/* Always-included rows: a mark where the control would be, so the option
   names keep a single left edge down the whole list. */
.ep-cfg-fixed {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  background: var(--ep-primary-faint);
  color: var(--ep-primary);
}

/* Stepper. Native number spinners are a couple of pixels tall on a phone,
   which is where a twenty-row list is most likely to be worked through. */
.ep-cfg-stepper {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid var(--ep-border-strong);
  border-radius: var(--ep-radius-md);
  background: var(--ep-bg-card);
}

.ep-cfg-stepper__btn {
  width: 2.375rem;
  min-height: 2.375rem;                  /* WCAG 2.5.8 pointer target */
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ep-primary);              /* 6.41:1 on --ep-bg-card */
  font-size: 1.125rem;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  transition: background var(--ep-duration-fast) var(--ep-ease);
}

.ep-cfg-stepper__btn:hover {
  background: var(--ep-primary-faint);
}

.ep-cfg-stepper__btn:first-child {
  border-radius: calc(var(--ep-radius-md) - 1px) 0 0 calc(var(--ep-radius-md) - 1px);
}

.ep-cfg-stepper__btn:last-child {
  border-radius: 0 calc(var(--ep-radius-md) - 1px) calc(var(--ep-radius-md) - 1px) 0;
}

.ep-cfg-stepper__input {
  width: 2.5rem;
  padding: 0;
  border: 0;
  border-inline: 1px solid var(--ep-border);
  background: transparent;
  color: var(--ep-text);
  text-align: center;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  -moz-appearance: textfield;
  appearance: textfield;
}

/* The − / + buttons replace the spinners, so showing both is redundant. */
.ep-cfg-stepper__input::-webkit-outer-spin-button,
.ep-cfg-stepper__input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* ---- Summary ------------------------------------------------------------ */

@media (min-width: 62em) {
  .ep-cfg__summary {
    position: sticky;
    top: calc(var(--ep-nav-h) + var(--ep-space-4));
  }
}

.ep-cfg-summary {
  padding: var(--ep-space-5);
  border: 1px solid var(--ep-border);
  border-radius: var(--ep-radius-lg);
  background: var(--ep-bg-card);
  box-shadow: var(--ep-shadow-md);
}

.ep-cfg-summary__heading {
  margin: 0 0 var(--ep-space-4);
  font-size: var(--ep-h4);
}

.ep-cfg-summary__list {
  margin: 0;
  padding: 0;
}

.ep-cfg-summary__item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--ep-space-3);
  padding: var(--ep-space-2) 0;
  border-bottom: 1px solid var(--ep-border);
}

.ep-cfg-summary__item dt {
  color: var(--ep-text-secondary);       /* 7.19:1 on --ep-bg-card */
  font-size: var(--ep-text-sm);
  font-weight: 400;
}

.ep-cfg-summary__item dd {
  margin: 0;
  color: var(--ep-text);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* The monthly rate is a breakdown of the line above it, not a fourth subtotal. */
.ep-cfg-summary__item--sub {
  padding-top: 0;
  padding-left: var(--ep-space-4);
}

.ep-cfg-summary__item--sub dt,
.ep-cfg-summary__item--sub dd {
  color: var(--ep-text-muted);           /* 5.28:1 on --ep-bg-card */
  font-size: var(--ep-text-sm);
  font-weight: 400;
}

.ep-cfg-summary__total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--ep-space-3);
  margin: var(--ep-space-4) 0 0;
}

.ep-cfg-summary__total-label {
  color: var(--ep-text);
  font-weight: 700;
}

.ep-cfg-summary__total-value {
  color: var(--ep-primary);              /* 6.41:1 on --ep-bg-card */
  font-size: clamp(1.5rem, 2.4vw, 2rem);
  font-weight: 700;
  line-height: var(--ep-leading-tight);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.ep-cfg-summary__per-unit {
  margin: var(--ep-space-1) 0 0;
  color: var(--ep-text-secondary);
  font-size: var(--ep-text-sm);
}

.ep-cfg-summary__note {
  margin: var(--ep-space-4) 0 0;
  padding: var(--ep-space-3) var(--ep-space-4);
  border-left: 3px solid var(--ep-primary-light);
  border-radius: 0 var(--ep-radius-sm) var(--ep-radius-sm) 0;
  background: var(--ep-primary-faint);
  color: var(--ep-text-secondary);
  font-size: var(--ep-text-sm);
}

.ep-cfg-summary__actions {
  display: grid;
  gap: var(--ep-space-2);
  margin-top: var(--ep-space-5);
}

.ep-cfg-summary__vat {
  margin: var(--ep-space-4) 0 0;
  color: var(--ep-text-muted);           /* 5.28:1 on --ep-bg-card */
  font-size: var(--ep-text-sm);
}
