/* Developer energy model.

   The page is a three part flow: one step of questions, a calculating screen, and a
   result. Everything structural is borrowed from the shipped tools, so this file only
   carries what the model needs on top of them. site-assess.css carries the staged form,
   assess-inputs.css the tiles and the text fields, assess-result.css the result plates,
   g.css the page chrome.

   What is here: the segmented control on the step and on the Gryd column, the build cost
   strip the result opens with, the three scenario columns with the clay house at the head
   of each, the gate that holds the Gryd figures back, and the calculating screen. */

.em-tool {
  --em-line: var(--stone-mid);
  --em-grey: var(--warm-grey);
  --em-ink: var(--red110);
  /* Text colours from the brand guide's contrast page (Brand Guidelines, page 20). On a
     light ground #872823 and #AC0000 are cleared for every size; the flare #FF5532 is
     cleared only for text over 14pt, and only on white. The page has no white: on its cream
     the flare reaches 2.95 to 1 and on the stone of the Gryd column 2.66, both under the 3
     to 1 large text floor. So the flare is never text here. It marks things instead: the
     strike through the system value, the energy line in the picture, focus rings and the
     buttons, and the figures that matter are set in #872823. */
  --em-flare-ink: #872823;
  --em-alert: #AC0000;
  --em-ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --em-ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
}

/* The brand guide clears white on the flare for text over 14pt only, so the tool's buttons
   carry their label at 19px. */
.em-tool .f-submit {
  background: var(--flare);
  color: #fff;
  font-size: 19px;
  line-height: 1.2;
  transition: transform 160ms var(--em-ease-out);
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
.em-tool .f-submit:active { transform: scale(0.97); }

/* The site assessment runs as a full bleed tool and hides the footer. This page shows the
   site chrome, so the footer comes back. */
body.sa-tool > footer.foot { display: block; }

/* ---- step one, the house ---- */

/* Step one is the site assessment's step one. The mast, the 620px column the questions
   stand in and the stage filling what is left of the viewport under it all come from that
   page, so the two tools open as one family. The stage height is set in script, the way
   the site assessment sets its own. */
.em-tool .sa-q { width: 100%; max-width: 620px; }

/* The mast is the page. The tool's own mast sets a title at the size of a label; this one
   is a heading, two balanced lines of it, with one short stand under it and enough air
   before the first field that the sentence is finished before the step arrives. */
.em-tool .sa-mast.em-mast { padding-bottom: clamp(88px, 7.6vw, 118px); }

/* 22ch breaks the title after "specifications,", which keeps the flared word on the second
   line with two words in front of it rather than alone. balance holds that if the copy
   changes under it. */
.em-tool .sa-mast.em-mast h1 {
  font-size: clamp(38px, 4.4vw, 62px);
  max-width: 22ch;
  margin-top: var(--label-gap);
  text-wrap: balance;
}

.em-tool .sa-mast.em-mast .stand {
  font-size: 18px;
  line-height: 1.55;
  max-width: 54ch;
  margin: 20px 0 0;
  color: var(--ink-soft);
  text-wrap: pretty;
}

/* A postcode the model cannot price is an answer the page does not have, so it is said
   under the field that set it rather than swallowed as a fallback on the result. */
.em-field-err { text-align: center; margin: 8px 0 0; }

/* The segmented control the council solar index uses, for the two answers that are a
   short list rather than free text. */
.em-seg {
  display: inline-flex;
  border: 1px solid var(--stone-mid);
  border-radius: 999px;
  overflow: hidden;
  background: transparent;
}
.em-seg button {
  font: inherit;
  font-size: 14px;
  line-height: 1;
  padding: 11px 18px;
  border: 0;
  border-left: 1px solid var(--stone-mid);
  background: transparent;
  color: var(--red110);
  cursor: pointer;
  white-space: nowrap;
}
.em-seg button:first-child { border-left: 0; }
.em-seg button[aria-checked="true"] {
  background: var(--red110);
  color: var(--paper);
  border-left-color: var(--red110);
}
.em-seg button[aria-checked="true"] + button { border-left-color: var(--stone-mid); }
.em-seg button:focus-visible { outline: 2px solid var(--flare); outline-offset: -2px; }

.em-q-seg { display: flex; justify-content: center; }

/* Matches the shipped :disabled weight, on aria rather than the attribute so the pill
   keeps its focus ring and still answers a screen reader. */
.f-submit[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }

/* The quiet basis line under the controls, so a wrong postcode is caught on the step that
   set it rather than on the result. */
.em-live {
  margin: 22px auto 0;
  max-width: 62ch;
  font-size: 13px;
  line-height: 1.55;
  color: var(--warm-grey);
  text-align: center;
  text-wrap: pretty;
}
.em-live b { font-weight: 500; color: var(--red110); }

/* The row carries four built forms, not the five the site's tile rule lays out, so the
   fifth column would sit empty and pull the row left of the stage. Four columns at the
   site assessment's own 108px width keep the row centred under the label. */
.sa-q [data-tile-group="type"].f-tiles {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  max-width: 492px;
}

/* Four built forms want a 2 by 2 block on a phone. The site's own tile rule packs five
   tiles into three columns, which strands the fourth here. */
@media (max-width: 720px) {
  .sa-q [data-tile-group="type"].f-tiles {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    max-width: 300px;
  }
}

/* ---- the result ---- */

/* The result is laid out with the site's own pieces and nothing else. The head is a site
   section head: eyebrow, one Borna headline with its closing phrase in the flare, and the
   house it was run on set on the right the way a project name is. The three columns carry
   no rules and no boxes; the Gryd column alone sits on a stone plate, and each bill has one
   hairline, over its total. */

.em-tool .ar-root { padding-top: 0; }

.em-rhead {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: 24px 48px;
}
.em-rhead .eyebrow { margin-bottom: var(--label-gap, 20px); }
.em-tool .em-headline {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(34px, 3.9vw, 52px);
  font-weight: 500;
  line-height: 1.04;
  letter-spacing: -0.012em;
  color: var(--red110);
  text-wrap: balance;
}
.em-flare { color: var(--em-flare-ink); }
/* Two lines on a wide screen, the claim and then the part in the flare. */
@media (min-width: 721px) { .em-headline .em-flare { display: block; } }

.em-house { text-align: right; padding-bottom: 6px; }
.em-house-name {
  margin: 0;
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 500;
  line-height: 1.15;
  color: var(--red110);
}
.em-house-meta {
  margin: 6px 0 0;
  font-size: 15px;
  line-height: 1.45;
  color: var(--warm-grey);
}

/* ---- the three columns ---- */

/* Six shared rows, one grid: the house, the name, the kit, the build cost, the tariff and
   the bill. Each column subgrids onto the same lines and puts every child on its own row
   by name, so a name that runs to two lines in one column cannot push its build cost below
   the others, the three totals end level, and the gate's card can sit over rows three to
   six of the Gryd column without moving anything. */
.em-columns {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: repeat(6, auto);
  column-gap: 20px;
  margin-top: 56px;
}
.em-col {
  display: grid;
  grid-row: span 6;
  grid-template-rows: subgrid;
  row-gap: 26px;
  min-width: 0;
  padding: 22px 22px 26px;
  border-radius: var(--radius-panel, 28px);
}
/* Every child names its column as well as its row. With the row alone, the card over rows
   three to six would push them into a second column rather than lie on top of them. */
.em-col > * { grid-column: 1; }
.em-col > .em-pic { grid-row: 1; }
.em-col > .em-name { grid-row: 2; }
.em-col > .em-kit { grid-row: 3; }
.em-col > .em-buildcell { grid-row: 4; }
.em-col > .em-tariff { grid-row: 5; }
.em-col > .em-billwrap { grid-row: 6; }
/* The Gryd column sits on the site's stone plate, the one column with a ground of its own. */
.em-col-lead {
  position: relative;
  background: var(--stonelight);
}

/* The houses come in one after another when the result lands, rising 8px. Backwards fill
   only, so once it has played nothing holds the column's opacity or position. */
.em-enter { animation: em-in 300ms var(--em-ease-out) backwards; }
@keyframes em-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}
@keyframes em-fade { from { opacity: 0; } to { opacity: 1; } }

/* ---- the house ---- */

.em-pic { margin: 0; }
.em-pic img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 18px;
}

.em-name { align-self: start; }
.em-name .em-kicker {
  display: block;
  margin-bottom: 6px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--warm-grey);
}
.em-name h4 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 500;
  line-height: 1.1;
  color: var(--red110);
  text-wrap: balance;
}

/* ---- the kit ---- */

/* The three clay icons the other tools use, one tile each. A house without the fitting
   keeps the tile, faded and greyed over None, so the gap reads as a gap. */
.em-kit {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
.em-kit li { display: grid; justify-items: start; align-content: start; }
.em-kit-tile {
  display: grid;
  place-items: center;
  width: 68px;
  height: 68px;
  margin-bottom: 10px;
  border-radius: 18px;
  background: var(--stonelight);
}
.em-col-lead .em-kit-tile { background: var(--paper); }
.em-kit-tile img { display: block; width: 54px; height: 54px; }
.em-kit .em-lab { margin-bottom: 3px; }
.em-kit-val { font-size: 15px; font-weight: 500; color: var(--red110); }
.em-kit .is-off .em-kit-tile { opacity: .55; }
.em-kit .is-off img { filter: grayscale(1); opacity: .3; }
.em-kit .is-off .em-kit-val { color: var(--warm-grey); font-weight: 400; }

/* ---- the labels every row shares ---- */

.em-lab {
  display: block;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--warm-grey);
}

/* ---- added to the build ---- */

.em-buildcell .em-lab { margin-bottom: 8px; }
.em-buildrow { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 14px; }
.em-build {
  font-family: var(--font-display);
  font-size: 44px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--red110);
  font-variant-numeric: tabular-nums;
}
.em-build.is-zero { color: var(--em-flare-ink); }
/* The system Gryd provides, struck through beside the nothing the developer pays for it. */
.em-was {
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 500;
  line-height: 1;
  color: var(--warm-grey);
  text-decoration: line-through;
  text-decoration-thickness: 2px;
  text-decoration-color: var(--flare);
  font-variant-numeric: tabular-nums;
}
.em-buildnote { margin: 10px 0 0; font-size: 13px; line-height: 1.4; color: var(--warm-grey); }
.em-col-lead .em-buildnote { color: var(--red110); }

/* ---- the tariff ---- */

.em-tariff { position: relative; }
.em-tariff .em-lab { margin-bottom: 10px; }
.em-controls { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }
.em-controls.is-locked { cursor: not-allowed; }
.em-controls.is-locked .em-seg button,
.em-controls.is-locked .em-switch { pointer-events: none; }

/* A fixed tariff is plain words on the line height of the control beside it. */
.em-fixed {
  display: inline-flex;
  align-items: center;
  min-height: 38px;
  font-size: 15px;
  color: var(--red110);
  white-space: nowrap;
}

.em-rates {
  display: flex;
  flex-direction: column;
  min-height: 32px;
  width: 100%;
  font-size: 11px;
  line-height: 16px;
  color: var(--warm-grey);
}
.em-rate { display: block; white-space: nowrap; }
.em-fixed + .em-rates { margin-top: -10px; margin-bottom: 10px; }
.em-col-lead .em-line .is-none { font-size: 13px; line-height: 1.5; }

/* The Gryd control: a soft track, no outline, and one dark pill that slides. */
#em-columns .em-seg {
  position: relative;
  display: inline-flex;
  border: 0;
  border-radius: 999px;
  overflow: visible;
  background: rgba(78, 37, 27, .06);
  transition: transform 160ms var(--em-ease-out);
}
#em-columns .em-seg:active { transform: scale(0.98); }
#em-columns .em-seg button {
  position: relative;
  z-index: 1;
  transition: color 220ms ease;
  padding: 12px 15px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--red110);
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
}
/* 44px to hit, though the pill draws at 38. */
#em-columns .em-seg button::after { content: ""; position: absolute; inset: -3px 0; }
#em-columns .em-seg button:focus-visible { outline: 2px solid var(--flare); outline-offset: 2px; }
#em-columns .em-seg.has-on button[aria-checked="true"] { background: transparent; color: #fff; }
.em-seg-on {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: var(--red110);
  pointer-events: none;
  transition: transform 340ms cubic-bezier(0.22, 1, 0.36, 1), width 340ms cubic-bezier(0.22, 1, 0.36, 1);
}
@media (hover: hover) and (pointer: fine) {
  #em-columns .em-seg button { transition: background-color 150ms ease, color 220ms ease; }
  #em-columns .em-seg button:hover { background: rgba(78, 37, 27, .06); }
}

/* Optimised charging, as a switch rather than a fourth tariff, because it is a way of
   running the pack on whichever tariff is chosen. It draws at 20px and takes 44 to hit,
   without moving the rows around it. */
.em-switch {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 12px 0;
  margin: -12px 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 14px;
  line-height: 20px;
  color: var(--red110);
  cursor: pointer;
  text-align: left;
  transition: opacity 200ms ease;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
}
.em-switch-track {
  position: relative;
  flex: none;
  width: 34px;
  height: 20px;
  border-radius: 999px;
  background: rgba(78, 37, 27, .18);
  transition: background-color 200ms ease, transform 160ms var(--em-ease-out);
}
.em-switch-track::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 2px rgba(78, 37, 27, .25);
  transition: transform 200ms var(--em-ease-in-out);
}
.em-switch:active .em-switch-track { transform: scale(0.94); }
.em-switch[aria-checked="true"] .em-switch-track { background: var(--red110); }
.em-switch[aria-checked="true"] .em-switch-track::after { transform: translateX(14px); }
.em-switch[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
.em-switch[aria-disabled="true"]:active .em-switch-track { transform: none; }
.em-switch:focus-visible { outline: 2px solid var(--flare); outline-offset: -6px; border-radius: 10px; }
/* The same switch, off and still, where there is no battery to run. */
.em-switch.is-none { cursor: default; color: var(--warm-grey); }
.em-switch.is-none .em-switch-track { background: transparent; box-shadow: inset 0 0 0 1px rgba(78, 37, 27, .16); }
.em-switch.is-none .em-switch-track::after { background: rgba(78, 37, 27, .16); box-shadow: none; }
.em-switch.is-none:active .em-switch-track { transform: none; }

/* The fetch and the missing prices are said under the switch, in the gap below the row,
   so a message never pushes the bill down. */
.em-say {
  position: absolute;
  left: 0;
  top: calc(100% + 4px);
  margin: 0;
  font-size: 13px;
  color: var(--warm-grey);
}
.em-say:empty { display: none; }
.em-say.is-warn { color: var(--em-alert); }

/* ---- the bill ---- */

/* Import, export, subscription and flex, then the year and how it stands against Part L.
   The same lines in every column, so a line one house does not have reads as none rather
   than as a gap. */
.em-bill { margin: 0; }
.em-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 6px 0;
  font-size: 15px;
}
.em-line dt { margin: 0; color: var(--red110); }
.em-line dd {
  margin: 0;
  color: var(--red110);
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.em-line dd.is-none { color: var(--warm-grey); }
.em-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-top: 10px;
  padding-top: 14px;
  border-top: 1px solid rgba(78, 37, 27, .14);
}
.em-total .em-lab { align-self: center; }
.em-total strong {
  font-family: var(--font-display);
  font-size: 36px;
  font-weight: 500;
  line-height: 1;
  color: var(--red110);
  font-variant-numeric: tabular-nums;
}
.em-col-lead .em-total strong { color: var(--em-flare-ink); }
.em-against {
  margin: 8px 0 0;
  text-align: right;
  font-size: 14px;
  font-weight: 500;
  color: var(--red110);
  font-variant-numeric: tabular-nums;
}
.em-col:first-child .em-against { color: var(--warm-grey); font-weight: 400; }
/* Keep the changing figures aligned while their tabular digits count. */
[data-fig] { display: inline-block; }
.em-against [data-fig], .em-against[data-fig] { display: block; }

.em-fee-tag {
  display: inline-block;
  margin-left: 8px;
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--red110);
  border: 1px solid currentColor;
  border-radius: 999px;
  padding: 2px 8px;
  white-space: nowrap;
  vertical-align: middle;
}

.em-notices { list-style: none; margin: 18px 0 0; padding: 0; display: grid; gap: 6px; }
.em-notices li { font-size: 13px; color: var(--warm-grey); }
.em-notices li.em-notice-stop { color: var(--em-alert); }

/* ---- after the columns ---- */

.em-acts { margin-top: 28px; display: flex; gap: 14px; flex-wrap: wrap; align-items: center; }
.em-tool .g-close { margin-top: 56px; padding: 52px 48px; }
.em-tool .g-close h2 { font-size: clamp(28px, 3.2vw, 40px); }
.em-tool .g-close p { margin-top: 14px; }

/* ---- what the model assumes ---- */

/* A native details element, shut when the result lands. It is the one place every stated
   assumption is written down, so it is quiet enough to ignore and plain enough to read. */
.em-assume { margin-top: 32px; padding-top: 16px; border-top: 1px solid var(--em-line); }
.em-assume summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 4px 0;
  cursor: pointer;
  list-style: none;
  color: var(--warm-grey);
}
.em-assume summary::-webkit-details-marker { display: none; }
.em-assume summary:focus-visible { outline: 2px solid var(--em-flare-ink); outline-offset: 3px; }
.em-assume-lab { font-size: 13px; font-weight: 600; letter-spacing: .01em; color: var(--em-ink); }
.em-assume-cue { flex: none; font-size: 12px; color: var(--warm-grey); }
.em-assume summary:hover .em-assume-cue { color: var(--em-flare-ink); }
.em-assume[open] .em-assume-cue { visibility: hidden; }
.em-assume-list { margin: 12px 0 0; padding: 0 0 4px 18px; display: grid; gap: 7px; }
.em-assume-list li { font-size: 13px; line-height: 1.5; color: var(--warm-grey); text-wrap: pretty; }

/* ---- the gate over the Gryd column ---- */

/* Everything under the Gryd name is covered: the kit, the build, the tariff and the bill.
   The blur is on from the first frame, and it clears one row after another when the
   details come back. */
.em-gated { transition: filter 360ms var(--em-ease-out), opacity 360ms var(--em-ease-out); }
.em-gated.is-blurred { filter: blur(7px); opacity: .5; user-select: none; pointer-events: none; }

/* The card sits over rows three to six of the Gryd column, in the middle of them, and rises
   8px into place once the houses have landed. It leaves faster than it came. */
.em-veil {
  grid-row: 3 / 7;
  grid-column: 1;
  align-self: center;
  position: relative;
  z-index: 3;
  margin: 0 -6px;
  opacity: 0;
  transform: translateY(8px) scale(0.98);
  transform-origin: 50% 0;
  transition: opacity 160ms var(--em-ease-out), transform 160ms var(--em-ease-out);
}
.em-veil.is-in {
  opacity: 1;
  transform: none;
  transition: opacity 280ms var(--em-ease-out), transform 280ms var(--em-ease-out);
}

.em-veil { text-align: center; padding: 20px 10px; }
.em-veil > p { margin: 12px auto 0; max-width: 24ch; font-size: 14px; line-height: 1.5; color: var(--red110); }
.em-veil .ar-btn { box-shadow: 0 4px 18px rgba(78, 37, 27, .12); }

html.em-dialog-open { overflow: hidden; }
.em-lead-dialog {
  --em-alert: #AC0000;
  width: min(520px, calc(100% - 32px));
  max-width: none;
  max-height: calc(100dvh - 32px);
  padding: 0;
  border: 0;
  border-radius: var(--modal-radius);
  background: var(--modal-plate);
  color: var(--modal-ink);
  box-shadow: var(--modal-shadow);
  font-family: var(--font-body, "DM Sans", sans-serif);
  overscroll-behavior: contain;
}
.em-lead-dialog::backdrop { background: var(--modal-scrim); }
.em-lead-dialog .dl-panel {
  width: 100%;
  max-height: none;
  padding: 60px 34px 30px;
  box-shadow: none;
}
.em-lead-dialog .dl-x { width: 44px; height: 44px; top: 12px; right: 14px; }
.em-ask { margin: 0; }
.em-ask h2 {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(26px, 5vw, 32px);
  font-weight: 500;
  line-height: 1.15;
}
.em-ask #em-lead-intro { margin: 12px 0 26px; font-size: 15px; line-height: 1.5; color: var(--modal-grey); }
.em-ask .hs-f { margin-bottom: 22px; }
.em-ask input { min-height: 44px; }
.em-ask input[aria-invalid="true"] { border-bottom-color: var(--em-alert); }
.em-ask input:focus-visible { outline: 2px solid var(--modal-flare); outline-offset: 4px; }
.em-ask .ar-btn { width: 100%; margin-top: 2px; }
.em-err { margin: 8px 0 0; font-size: 13px; color: var(--em-alert); }
.em-consent { margin: 14px 0 0; font-size: 12px; line-height: 1.5; color: var(--modal-grey); }
@media (max-width: 480px) {
  .em-lead-dialog .dl-panel { padding: 60px 24px 26px; }
}
.em-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.em-col-lead.is-busy .em-bill { opacity: .45; transition: opacity .2s ease; }

/* ---- the calculating screen ---- */

/* The language is the site's own loading cover: the same cream ground, the same short
   linear fade off it, and the flare the result's own figures are set in. */
.em-calc {
  position: fixed;
  inset: 0;
  z-index: 4000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 var(--gutter);
  background: var(--paper);
  opacity: 1;
  transition: opacity .2s linear;
  overscroll-behavior: contain;
  touch-action: none;
}
.em-calc.is-out { opacity: 0; pointer-events: none; }
.em-calc:focus { outline: none; }

/* The screen is a stage, not a section. Nothing under it scrolls into view while it is up,
   and the page keeps the offset it had so a changed house comes back where it was. */
html.em-calc-lock, html.em-calc-lock body { overflow: hidden; }

.em-calc-inner { width: 100%; max-width: 720px; }

.em-calc-line {
  margin: 18px 0 0;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(26px, 3.2vw, 36px);
  letter-spacing: -0.025em;
  line-height: 1.06;
  color: var(--red110);
  text-wrap: balance;
}

/* One hairline, the weight of the rules the result uses, filling once over the wait. */
.em-calc-track {
  margin-top: 32px;
  height: 2px;
  border-radius: 2px;
  background: var(--stone-mid);
  overflow: hidden;
}
.em-calc-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--flare-trail) 0%, var(--flare) 70%);
}
.em-calc-fill.is-running { transition: width 5000ms linear; }

/* ---- the year the screen draws ---- */

.em-calc-chart { margin: 26px 0 0; position: relative; }
.em-calc-plot { position: relative; height: 128px; }
.em-calc-chart svg { display: block; width: 100%; height: 100%; }

.em-calc-grid { stroke: var(--stonelight); stroke-width: 1; }
.em-calc-base { stroke: var(--stone-mid); stroke-width: 1; }
/* The scale runs from zero, so shading down to the axis states a real quantity. */
.em-calc-area { fill: var(--flare); opacity: .085; }
.em-calc-curve {
  fill: none;
  stroke: var(--flare);
  stroke-width: 1.8;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

/* One rect scaled from its left edge. Clipping the curve rather than dashing it keeps the
   reveal linear in x, so the head of the line sits under the counter's own progress
   however steep the curve happens to be there. */
.em-calc-wipe {
  transform-box: fill-box;
  transform-origin: left center;
  transform: scaleX(0);
}
.em-calc-wipe.is-running { transition: transform 5000ms linear; }

.em-calc-head {
  position: absolute;
  left: 0;
  top: 100%;
  width: 7px;
  height: 7px;
  margin: -3.5px 0 0 -3.5px;
  border-radius: 999px;
  background: var(--flare);
  opacity: 0;
  transition: opacity .3s ease;
}
.em-calc-head.is-on { opacity: 1; }

.em-calc-months {
  display: flex;
  margin-top: 8px;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--warm-grey);
}
.em-calc-months span { flex: 1; }

.em-calc-meta {
  margin-top: 18px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 18px;
}
.em-calc-tally { margin: 0; }
.em-calc-count {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(30px, 4vw, 44px);
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--red110);
  font-variant-numeric: tabular-nums;
}
.em-calc-count-lab {
  font-size: 14px;
  color: var(--warm-grey);
  margin-left: 9px;
}
.em-calc-season {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(22px, 3vw, 30px);
  letter-spacing: -0.025em;
  line-height: 1;
  color: var(--em-flare-ink);
  transition: opacity .28s ease;
}
.em-calc-season.is-turning { opacity: 0; transition: opacity .14s ease; }

.em-calc-source {
  margin: 14px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--warm-grey);
  max-width: 60ch;
}

/* The result heading takes focus when the screen stands down, so a keyboard or a screen
   reader lands on the answer rather than back at the top of the document. */
#em-result .ar-title:focus { outline: none; }
#em-result .ar-title:focus-visible { outline: 2px solid var(--flare); outline-offset: 4px; }

.em-error { color: var(--em-alert); font-size: 16px; padding: 24px 0; }
.em-tool[data-state="ready"] .em-error { display: none; }

.em-notices { list-style: none; margin: 20px 0 0; padding: 0; }
.em-notices:empty { display: none; }
.em-notices li {
  margin: 0 0 8px;
  padding: 10px 14px;
  border-left: 3px solid var(--em-alert);
  background: rgba(255, 85, 50, .06);
  font-size: 14px;
  line-height: 1.45;
  max-width: 78ch;
}
.em-notices li.em-notice-stop { font-weight: 600; }

/* The site has no visually hidden helper of its own, so the page carries one for the
   headings that label a region without needing to be read on screen. */
.em-tool .visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---- narrow ---- */

.em-summary { display: none; }

@media (max-width: 1040px) {
  .em-summary { display: block; max-width: 560px; margin: 28px auto 0; }
  .em-summary:empty { display: none; }
  .em-summary-title { margin: 0 0 16px; font: 500 20px/1.2 var(--font-display); color: var(--red110); }
  .em-summary-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
  .em-summary-col { min-width: 0; padding: 10px 6px 16px; text-align: center; }
  .em-summary-lead { background: var(--stonelight); border-radius: 18px; }
  .em-summary-col figure { margin: 0; }
  .em-summary-col img { display: block; width: 100%; height: auto; max-width: 120px; aspect-ratio: 1; object-fit: cover; border-radius: 12px; margin: 0 auto; }
  .em-summary-col h4 { margin: 8px 0 20px; font: 500 20px/1.2 var(--font-display); color: var(--red110); }
  .em-summary-col abbr { text-decoration: none; }
  .em-summary-col dl { display: grid; gap: 20px; margin: 0; }
  .em-summary-col dt { font-size: 11px; color: var(--warm-grey); }
  .em-summary-col dd { margin: 4px 0 0; font: 500 clamp(20px, 5.6vw, 26px)/1.2 var(--font-display); color: var(--red110); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
  .em-summary.is-locked .em-summary-lead dd { filter: blur(6px); user-select: none; }
  .em-summary [data-summary-unlock] { width: 100%; margin-top: 16px; min-height: 44px; justify-content: center; }
  .em-summary [data-summary-unlock][hidden] { display: none; }
  .em-summary-note { margin: 12px 0 0; font-size: 12px; line-height: 1.5; color: var(--warm-grey); text-align: center; }
  .em-summary-link { display: flex; min-height: 44px; align-items: center; justify-content: center; font-size: 13px; color: var(--red110); text-underline-offset: 3px; }
  .em-summary-bill:focus-visible { outline: 2px solid var(--flare); outline-offset: 4px; }
  #em-columns { scroll-margin-top: 90px; }
  .em-rhead { grid-template-columns: 1fr; }
  .em-house { text-align: left; }
  /* Stacked, there is no row to read across, so the shared grid stands down and each
     column closes over its own content. */
  .em-columns { grid-template-columns: 1fr; grid-template-rows: none; row-gap: 18px; margin-top: 36px; }
  .em-col { grid-row: auto; grid-template-rows: none; row-gap: 22px; padding: 18px 0 22px; }
  .em-col-lead { padding: 22px 18px 26px; }
  .em-pic img { max-width: 420px; }
  .em-build { font-size: 40px; }
  .em-total strong { font-size: 32px; }
}

@media (max-width: 760px) {
  .em-tool .g-close { padding: 40px 24px; }
}

@media (max-width: 720px) {
  .em-tool .sa-mast.em-mast { padding-bottom: 40px; }
  .em-tool .sa-mast.em-mast .stand { font-size: 16px; margin-top: 16px; }
  .em-tool .sa-q .sa-sec-head { font-size: 24px; }
  .em-tool .sa-q .q-sub { font-size: 14px; }
  .em-tool .sa-q .f-tiles { gap: 12px 20px; }
  .em-tool .sa-q .f-tile img { width: 76px; height: 76px; }
  .em-q-seg .em-seg { width: 100%; max-width: 350px; }
  .em-q-seg .em-seg button { flex: 1; min-width: 44px; min-height: 44px; padding: 12px 8px; }
}

@media (max-width: 1040px) {
  .em-rhead { gap: 20px; }
  .em-house-name { font-size: 21px; }
  .em-house-meta { font-size: 14px; }
  .em-columns { max-width: 560px; margin: 24px auto 0; row-gap: 28px; }
  /* In the stacked layout the illustration and name share a header. The costs stay full width,
     with the same reading order and the gate covering every Gryd detail. */
  .em-col { grid-template-columns: 104px minmax(0, 1fr); gap: 20px 16px; padding: 16px 0 24px; }
  .em-col > * { grid-column: 1 / -1; }
  .em-col > .em-pic { grid-column: 1; grid-row: 1; }
  .em-col > .em-name { grid-column: 2; grid-row: 1; align-self: center; }
  .em-col > .em-kit { grid-row: 2; }
  .em-col > .em-buildcell { grid-row: 3; }
  .em-col > .em-tariff { grid-row: 4; }
  .em-col > .em-billwrap { grid-row: 5; }
  .em-col > .em-veil { grid-row: 2 / 6; }
  .em-col-lead { padding: 20px 16px 24px; }
  .em-pic img { aspect-ratio: 1; border-radius: 14px; }
  .em-name h4 { font-size: 25px; text-wrap: pretty; }
  .em-name .em-kicker { font-size: 10px; }
  .em-kit { gap: 8px; }
  .em-kit-tile { width: 48px; height: 48px; border-radius: 12px; margin-bottom: 8px; }
  .em-kit-tile img { width: 40px; height: 40px; }
  .em-kit .em-lab { font-size: 10px; letter-spacing: .08em; }
  .em-kit-val { font-size: 14px; }
  .em-build { font-size: 34px; }
  .em-was { font-size: 23px; }
  .em-controls { align-items: stretch; }
  #em-columns .em-seg { display: flex; width: 100%; }
  #em-columns .em-seg button { flex: 1; min-height: 44px; padding: 12px 8px; }
  #em-columns .em-seg button::after { inset: 0; }
  .em-rate { white-space: normal; }
  .em-say { position: static; margin-top: 8px; }
  .em-line { font-size: 14px; }
  .em-line dd { min-width: 0; }
  .em-col-lead .em-line .is-none { max-width: 18ch; }
  .em-acts .f-ghost { min-height: 44px; }
  .em-tool .g-close { margin-top: 32px; padding: 28px 20px; }
  .em-tool .g-close .btn { white-space: normal; text-align: center; }
  .em-assume summary { min-height: 44px; align-items: center; }
}

@media (max-width: 720px) {
  .em-calc-inner { max-width: 360px; }
  .em-calc-track { margin-top: 26px; }
  .em-calc-plot { height: 108px; }
  .em-calc-meta { flex-direction: column; align-items: flex-start; gap: 8px; }
}

/* The wait still holds its five seconds and the year still reports at its quarters.
   Only the travel between the states is dropped. */
@media (prefers-reduced-motion: reduce) {
  .em-gated,
  .em-veil,
  .em-calc,
  .em-calc-fill,
  .em-calc-fill.is-running,
  .em-calc-wipe,
  .em-calc-wipe.is-running,
  .em-calc-head,
  .em-calc-season,
  .em-calc-season.is-turning { transition: none; }
  .ar-fig, .em-num { transition: none; }
  .em-switch-track::after, .em-seg-on, #em-columns .em-seg button { transition: none; }
  .em-enter { animation-name: em-fade; }
  .em-veil, .em-veil.is-in { transform: none; }
  #em-columns .em-seg:active, .em-switch:active .em-switch-track, .em-tool .f-submit:active { transform: none; }
}


/* The house tiles are radios, so their picked state is aria-checked. The shared tile
   rules in site-assess.css only know aria-pressed, which is why a picked tile lost its
   colour the moment the pointer left it. */
.sa-q .f-tile[aria-checked="true"] { color: var(--red110); }
.sa-q .f-tile[aria-checked="true"] img { filter: none; transform: translateY(-2px); }
.sa-q .f-tile[aria-checked="true"]::after { width: 26px; }
