/* HVAC, two seasons. The page is cut down the middle: heating on ink, cooling on porch yellow, and that
   seam runs from the header, which is the split page state in site.css, to the last row. Nothing with words crosses it. Every title and sentence sits
   whole on one side, or whole on lit, the third tone, which means "belongs to both": a slab lies across
   the seam for a row with no season, and a half-width panel holds the seasonless words of a split row.
   Each side carries its own art: heat rising on the ink, air moving across the yellow.
   Below 992 wide the seam turns horizontal: the same blocks stack and each keeps its ground. */

body {
  --seam: linear-gradient(90deg, var(--ink) 50%, var(--porch) 50%);
  --edge: max(var(--gutter), calc(50vw - 47rem));
  --read: 61ch; /* about 75 real characters of Source Sans 3, which runs narrower than its zero */
  --row-top: clamp(4.5rem, 8.5vw, 7.5rem);
  --under-head: clamp(1.25rem, 2.6vw, 2.25rem);
  --slab-pad: clamp(1.25rem, 3vw, 2.75rem);
  --stagger: clamp(3rem, 10vw, 9rem);
}

main { background: var(--seam); }
main section { background: transparent; }

/* The dark half. It carries the same roles as .night, but under its own name: the header watches .night,
   and half a row must not flip it. */
.heat {
  --ground: var(--ink);
  --fg: var(--porch);
  --fg-muted: var(--muted-night);
  --line: color-mix(in srgb, var(--porch) 24%, transparent);
  --press: var(--porch);
  --press-fg: var(--ink);
}
.heat, .lit { color: var(--fg); }
.heat::selection, .heat *::selection { background: var(--porch); color: var(--ink); }

/* The third tone: it means "both seasons". */
.lit {
  --ground: var(--lit);
  --fg: var(--ink);
  --fg-muted: var(--muted-porch);
  --line: color-mix(in srgb, var(--ink) 22%, transparent);
  --press: var(--ink);
  --press-fg: var(--porch);
  --dot-on: var(--ink);
  --dot-off: var(--mark-muted); /* 4.37:1 on lit, 3.74:1 against the ink dots */
}

/* ---------- Row kinds ---------- */
.row { position: relative; isolation: isolate; overflow-x: clip; padding-top: var(--row-top); }
.row.close-row { padding-bottom: var(--row-top); }

.title {
  font-family: var(--f-head);
  font-size: var(--t-xl);
  font-weight: var(--w-loud);
  letter-spacing: var(--track-xl);
  line-height: 1.02;
  font-variant-numeric: lining-nums proportional-nums;
}

.sides {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-top: var(--under-head);
}
.side {
  position: relative;
  isolation: isolate;
  min-width: 0;
  padding-inline: var(--edge) var(--slab-pad);

  & + .side { padding-inline: var(--slab-pad) var(--edge); }
  & > p { max-width: var(--read); }
}

.slab {
  margin-inline: var(--edge);
  margin-top: var(--under-head);
  padding: var(--slab-pad);
  background: var(--ground);

  .row > &:first-child { margin-top: 0; }
  & > .title { margin-bottom: clamp(0.75rem, 1.6vw, 1.25rem); }
}

/* A split row's opening: the title on one side, its seasonless words on a lit panel against the seam. */
.head { margin-top: 0; }
.panel {
  margin-inline-start: calc(var(--slab-pad) * -1);
  padding: var(--slab-pad);
  background: var(--ground);
  font-size: var(--t-m);
  line-height: 1.32;

  & p { max-width: var(--read); }
}
.head.flip {
  position: relative;

  & > .side { grid-column: 2; padding-inline: var(--slab-pad) var(--edge); }
  & .panel { margin-top: var(--under-head); }
}

/* ---------- Plates: line art in a tone of each side's own ground, masked so it fades before any words.
   The SVGs are plain strokes used as masks, so the color comes from the tokens. Each placement sets
   --art, --art-at, --art-size, --fade and --tone, and gives the pseudo-element its box and content. ---------- */
.hero-rest::before, .spend-row .side.heat::before, .inspect-row .head.flip::before, .permit-row .side.heat::before,
.ledger-sides .side + .side::before, .mail-row::before, .mail-plan::after, .faq-cool::before,
.places .sides:not(.head) .side + .side::before, .close-row .side.heat::before {
  position: absolute;
  z-index: -1;
  pointer-events: none;
  background: var(--tone);
  -webkit-mask-image: var(--art), var(--fade);
  mask-image: var(--art), var(--fade);
  -webkit-mask-position: var(--art-at), 0 0;
  mask-position: var(--art-at), 0 0;
  -webkit-mask-size: var(--art-size), 100% 100%;
  mask-size: var(--art-size), 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}

/* ---------- Hero ---------- */
.hero-sides { margin-top: 0; }
.hero .side { padding-top: calc(var(--header-h) + 0.25rem); }
.hero-lead { padding-bottom: clamp(1.5rem, 3vw, 2.5rem); }
.hero .crumbs { color: var(--fg); }
.hero-greeting {
  margin-top: clamp(0.25rem, 1vw, 0.75rem);
  font-family: var(--f-head);
  font-size: min(var(--t-mega), calc((50vw - var(--gutter) - var(--slab-pad)) / 3.3));
  font-weight: var(--w-loud);
  letter-spacing: var(--track-mega);
  line-height: 1;

  & span { display: block; }
  & span:first-child { font-weight: var(--w-quiet); }
}
.hero-title {
  margin-top: clamp(0.5rem, 1.2vw, 1rem);
  font-size: var(--t-l);
  font-weight: var(--w-head);
  letter-spacing: var(--track-l);
  line-height: 1.08;
}
.hero-rest {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: clamp(1rem, 2vw, 1.5rem);
}
.hero-press {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem var(--gutter);
}
.hero-action { padding-block-end: 0.3rem; }
.hero-count-where { font-weight: 650; line-height: 1.2; }
.hero-count-num {
  font-family: var(--f-head);
  font-size: var(--t-xl);
  font-weight: var(--w-loud);
  letter-spacing: var(--track-xl);
  line-height: 1.05;
  font-variant-numeric: lining-nums proportional-nums;
}
.hero-count-what { font-size: var(--t-s); color: var(--fg-muted); }
.hero-intro { font-size: var(--t-body); line-height: 1.45; }

/* ---------- Words that lie across a slab, one column to each side of the seam ---------- */
.energy-slab, .costs-words {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: calc(var(--slab-pad) * 2);
  font-size: var(--t-m);
  line-height: 1.32;

  & p { max-width: var(--read); }
}
.slab-lead { max-width: var(--read); line-height: 1.45; }

/* ---------- Where leads come from ---------- */
.sources-table {
  margin-top: clamp(1rem, 2vw, 1.5rem);
  font-size: var(--t-body);

  & thead th { font-size: var(--t-s); }
  & a { min-height: 1.5rem; }
  & tbody td:nth-of-type(2) { white-space: nowrap; }
}
.sources-notes {
  columns: 2;
  column-gap: calc(var(--slab-pad) * 2);
  margin-top: clamp(1.5rem, 3vw, 2.25rem);

  & p { max-width: var(--read); break-inside: avoid; margin-bottom: 0.9rem; }
  & p:last-child { margin-bottom: 0; }
  & strong { font-weight: 750; }
}

/* ---------- 35% ---------- */
.spend-figure {
  display: block;
  margin-block: 0.25rem 0.5rem;
  font-family: var(--f-head);
  font-size: var(--t-mega);
  font-weight: var(--w-loud);
  letter-spacing: var(--track-mega);
  line-height: 0.95;
  word-spacing: -0.16em;
  font-variant-numeric: lining-nums proportional-nums;

  & small { font-size: var(--t-m); font-weight: var(--w-sub); letter-spacing: -0.01em; word-spacing: normal; }
}
.spend-more {
  display: block;
  margin-bottom: 0.3rem;
  font-family: var(--f-head);
  font-size: var(--t-l);
  font-weight: var(--w-head);
  letter-spacing: var(--track-l);
  line-height: 1.1;
}

/* ---------- The month chart, on a ground of its own ---------- */
.chart-source { margin-bottom: clamp(1.25rem, 2.6vw, 2rem); color: var(--fg-muted); }
.chart-slab .big-chart-table { margin-top: 0.75rem; }

/* ---------- Inspection ---------- */
.left-undone {
  margin-top: 0.75rem;
  border-top: 2px solid var(--fg);

  & li {
    padding-block: 0.6rem;
    border-bottom: 1px solid var(--line);
    font-family: var(--f-head);
    font-size: var(--t-l);
    font-weight: var(--w-head);
    letter-spacing: var(--track-l);
    line-height: 1.1;
  }
}
.pull {
  display: block;
  margin-block: 0.15rem 0.3rem;
  font-family: var(--f-head);
  font-size: var(--t-l);
  font-weight: var(--w-head);
  letter-spacing: var(--track-l);
  line-height: 1.1;
  font-variant-numeric: lining-nums proportional-nums;
}
.side > .after-rule {
  max-width: none;
  margin-top: 1.25rem;
  padding-top: 1.25rem;
  padding-inline-end: max(0px, calc(100% - var(--read)));
  border-top: 1px solid var(--line);
}

/* ---------- Permit history ---------- */
.history-panel p + p { margin-top: 0.9rem; }
.history-swap { font-weight: 650; }
.history-year {
  display: block;
  font-family: var(--f-head);
  font-size: var(--t-xl);
  font-weight: var(--w-loud);
  letter-spacing: var(--track-xl);
  line-height: 1.05;
  font-variant-numeric: lining-nums proportional-nums;
}

/* ---------- The permit count ---------- */
.count-slab { padding-bottom: clamp(1.25rem, 2.4vw, 2rem); }
.count-source { color: var(--fg-muted); }
.count-article {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: calc(var(--slab-pad) * 2);
  align-items: end;
}
.count-trade { grid-column: 1 / -1; margin-top: 0.75rem; font-size: var(--t-m); font-weight: var(--w-sub); line-height: 1.2; }
.count-figure {
  display: grid;

  & strong {
    font-family: var(--f-head);
    font-size: var(--t-mega);
    font-weight: var(--w-loud);
    letter-spacing: var(--track-mega);
    line-height: 0.95;
    font-variant-numeric: lining-nums proportional-nums;
  }
  & span { margin-top: 0.35rem; font-size: var(--t-m); font-weight: 650; line-height: 1.2; }
}
.count-words {
  font-size: var(--t-m);
  line-height: 1.32;

  & strong { display: block; margin-top: 0.75rem; font-family: var(--f-head); font-size: var(--t-l); font-weight: var(--w-head); letter-spacing: var(--track-l); line-height: 1.1; }
}
.count-field {
  grid-column: 1 / -1;
  margin-top: clamp(1.25rem, 2.6vw, 2rem);

  & .unit-field, html.js & .unit-field.is-columns {
    grid-template-columns: none;
    grid-template-rows: repeat(14, auto);
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    grid-auto-rows: auto;
    gap: 4px;
  }
  & .unit-field .dot { width: auto; height: auto; aspect-ratio: 1; }
  & .trade-key { margin-top: 1rem; font-size: var(--t-s); }
}

/* ---------- The rebate ledger: each sentence stays whole, with its amount set large where it stands ---------- */
.rebates-lead strong { font-weight: 750; }
/* Two tables, one to a side, sharing two rows through subgrid: the rules line up across the seam. */
.ledger-sides { grid-template-rows: auto auto; }
.ledger-sides .side, .ledger, .ledger tbody { display: grid; grid-row: span 2; grid-template-rows: subgrid; }
.ledger {
  width: 100%;

  & tr { display: flex; flex-direction: column; padding-block: 0.75rem clamp(1.25rem, 2.4vw, 2rem); border-top: 2px solid var(--fg); }
  & tr + tr { border-top-width: 1px; border-top-color: var(--line); }
  & th, & td { display: block; max-width: var(--read); text-wrap: pretty; }
  & th { font-family: var(--f-head); font-size: var(--t-m); font-weight: var(--w-sub); letter-spacing: -0.01em; line-height: 1.2; text-align: left; }
  & td + td { margin-top: auto; padding-top: 0.75rem; }
}
/* ComEd's one sentence carries both tiers, so it runs across the two rows and sets a step larger. Its
   second row has no utility name to carry, so it starts a name's height down to level the two amounts. */
.ledger-sides .side + .side .ledger {
  font-size: var(--t-m);
  line-height: 1.32;

  & .amount { margin-block: 0.3rem 0.4rem; }
  & tr + tr td:first-child { padding-top: calc(var(--t-m) * 1.2); }
}
.amount {
  display: block;
  margin-block: 0.1rem 0.2rem;
  font-family: var(--f-head);
  font-size: var(--t-xl);
  font-weight: var(--w-loud);
  letter-spacing: var(--track-xl);
  line-height: 1.05;
  font-variant-numeric: lining-nums proportional-nums;
}

/* ---------- The mail plan: two cards facing across the seam, stepped so the order reads top to bottom ---------- */
.mail-plan {
  position: relative;
  counter-reset: step;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  row-gap: clamp(1rem, 2vw, 1.5rem);
  margin-top: var(--under-head);

  & > li { counter-increment: step; }
  & > li::before {
    content: counter(step);
    font-family: var(--f-head);
    font-size: var(--t-xl);
    font-weight: var(--w-loud);
    letter-spacing: var(--track-xl);
    line-height: 1;
    font-variant-numeric: lining-nums proportional-nums;
  }
}
.rail {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 3.5rem minmax(0, 1.25fr) minmax(0, 0.8fr) minmax(0, 1.4fr);
  column-gap: var(--gutter);
  align-items: baseline;
  margin-inline: var(--edge);
  padding: clamp(1rem, 2vw, 1.5rem) var(--slab-pad);
  background: var(--ground);
  font-size: var(--t-m);
  line-height: 1.3;

  & p:only-of-type { grid-column: 2 / -1; }
  & strong { font-weight: 750; white-space: nowrap; }
}
.card {
  display: grid;
  align-content: start;
  gap: 0.75rem;
  padding: var(--slab-pad);
  background: var(--ground);
  border: 2px solid var(--fg);

  /* Each card stays on its own season's ground and lies open at the seam, where the color change closes it. */
  &.spring { grid-column: 2; grid-row: 2; margin-inline-end: var(--edge); margin-block-end: var(--stagger); border-inline-start: 0; }
  &.heat { grid-column: 1; grid-row: 2; margin-inline-start: var(--edge); margin-block-start: var(--stagger); border-inline-end: 0; }
  &.heat::before { justify-self: end; }
}
.card > p { max-width: var(--read); }
.card-lead {
  font-family: var(--f-head);
  font-size: var(--t-l);
  font-weight: var(--w-head);
  letter-spacing: var(--track-l);
  line-height: 1.1;
}

/* ---------- Costs: the sum laid out as one strip across the seam ---------- */
.cost-strip.cost-table {
  display: block;
  width: 100%;
  max-width: none;
  margin-top: clamp(1.25rem, 2.6vw, 2rem);

  & tbody { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)) repeat(2, minmax(0, 1.55fr)); border-top: 2px solid var(--fg); }
  & tr { display: flex; flex-direction: column-reverse; justify-content: flex-end; gap: 0.35rem; padding: 0.9rem 1rem 0.25rem; }
  & tr:first-child { padding-inline-start: 0; }
  & tr + tr { border-left: 1px solid var(--line); }
  & tbody th { display: block; padding: 0; border: 0; font-size: var(--t-s); font-weight: 600; line-height: 1.3; text-align: left; }
  & td {
    display: block;
    padding: 0;
    border: 0;
    font-family: var(--f-head);
    font-size: var(--t-l);
    font-weight: var(--w-loud);
    letter-spacing: var(--track-l);
    line-height: 1.05;
    text-align: left;
    white-space: normal;
    font-variant-numeric: lining-nums tabular-nums;
  }
  & :is(.cost-mailedperowner, .cost-monthlytotal) td { font-size: var(--t-xl); letter-spacing: var(--track-xl); }
  & tbody :is(.cost-mailedperowner, .cost-monthlytotal) th { font-size: var(--t-body); font-weight: 650; }
}
@media (max-width: 1279.98px) {
  .cost-strip.cost-table {
    & tbody { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    & tr:nth-child(3n + 1) { padding-inline-start: 0; border-left: 0; }
    & tr:nth-child(n + 4) { border-top: 1px solid var(--line); }
    & :is(.cost-mailedperowner, .cost-monthlytotal) td { font-size: var(--t-l); letter-spacing: var(--track-l); }
    & tbody :is(.cost-mailedperowner, .cost-monthlytotal) th { font-size: var(--t-s); }
  }
}

/* ---------- Questions: the two with a season take its side, the rest sit on lit ---------- */
.faq-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));

  & > .title { grid-column: 1; grid-row: 1; padding-inline: var(--edge) var(--slab-pad); }
}
.faq {
  display: contents;

  & dt { font-weight: 750; line-height: 1.25; }
  & dd { margin: 0.35rem 0 0; max-width: var(--read); }
  & dd p + p { margin-top: 0.75rem; }
}
.faq-item { position: relative; isolation: isolate; min-width: 0; }
.faq-cool, .faq-heat {
  & dt { font-family: var(--f-head); font-size: var(--t-l); font-weight: var(--w-head); letter-spacing: var(--track-l); line-height: 1.1; }
  & dd { margin-top: 0.6rem; }
}
.faq-cool {
  grid-column: 2;
  grid-row: 1 / span 2;
  padding-inline: var(--slab-pad) var(--edge);
  padding-block-end: var(--under-head);

  & dd { font-size: var(--t-m); line-height: 1.32; }
}
.faq-heat { grid-column: 1; grid-row: 2; padding-inline: var(--edge) var(--slab-pad); padding-block: var(--under-head); }
.faq-both {
  padding: var(--slab-pad);
  background: var(--ground);

  & dt { font-size: var(--t-m); }
}
.faq-paid {
  grid-column: 1 / -1;
  grid-row: 3;
  margin-inline: var(--edge);
  padding-block-end: 0;

  & dd {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: calc(var(--slab-pad) * 2);
    max-width: none;
  }
  & dd p { max-width: var(--read); }
  & dd p + p { margin-top: 0; }
}
.faq-ideas { grid-column: 1; grid-row: 4 / span 2; margin-inline-start: var(--edge); }
.faq-cost { grid-column: 2; grid-row: 4; margin-inline-end: var(--edge); padding-block-end: 0; }
.faq-fresh { grid-column: 2; grid-row: 5; margin-inline-end: var(--edge); padding-block-start: 1.25rem; }

/* ---------- Cities, ZIPs and the other trades ---------- */
.places-lead { display: flex; align-items: center; min-height: 100%; }
.places .city-table td .small { margin-left: 0.4rem; font-weight: 450; }
.places .zips-title { margin-top: 0; margin-bottom: 0; color: var(--fg); font-size: var(--t-m); font-weight: var(--w-sub); line-height: 1.2; }
.places .zips-title + .chip-list {
  display: block;
  margin-top: 0.6rem;
  border-top: 2px solid var(--fg);

  & .chip {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto 1.25rem;
    align-items: center;
    column-gap: 1rem;
    min-height: 3.5rem;
    padding: 0 0.5rem;
    border: 0;
    border-bottom: 1px solid var(--line);
    border-radius: 0;
    font-family: var(--f-head);
    font-size: var(--t-m);
    font-weight: var(--w-sub);
    letter-spacing: -0.01em;
  }
  & .chip-count { font-family: var(--f); font-size: var(--t-body); font-weight: 600; color: var(--fg); }
}
.others { margin-top: clamp(2rem, 3.4vw, 3rem); }
.others-title { margin-bottom: 0.9rem; font-size: var(--t-xl); font-weight: var(--w-loud); letter-spacing: var(--track-xl); line-height: 1.02; }

/* ---------- Close ---------- */
.close-action { margin-top: clamp(1rem, 2vw, 1.5rem); }

/* ---------- Where each plate sits, wide. Every box stays inside its own half of the page. ---------- */
@media (min-width: 992px) {
  /* Air comes in along the top of the yellow half and turns down its outer edge, above and beside the count. */
  .hero-rest::before {
    content: '';
    inset: 0 0 auto 0;
    height: 62%;
    --tone: var(--ramp-1);
    --art: url('/assets/img/trades/hvac/air-bend.svg');
    --art-at: right top;
    --art-size: 100% auto;
    --fade: linear-gradient(to bottom, #000 62%, transparent 92%);
  }

  /* A wide curtain of heat in the ink half under the title. It fades at both ends: nothing covers its foot
     now, and it has to be gone before it reaches the words. */
  .spend-row .side.heat::before {
    content: '';
    inset: 0 0 calc(var(--row-top) * -0.5) 0;
    --tone: var(--ramp-2);
    --art: url('/assets/img/trades/hvac/heat-curtain.svg');
    --art-at: left bottom;
    --art-size: 100% auto;
    --fade: linear-gradient(to top, transparent, #000 12%, #000 24%, transparent 40%);
  }

  /* The ink half beside the inspection title belongs to the art: three plumes, fading out at both ends. */
  .inspect-row .head.flip::before {
    content: '';
    grid-column: 1 / 2;
    grid-row: 1 / 2;
    inset: calc(var(--row-top) * -1) 0 0 0;
    --tone: var(--ramp-2);
    --art: url('/assets/img/trades/hvac/heat-climb.svg');
    --art-at: center;
    --art-size: cover;
    --fade: linear-gradient(to bottom, transparent, #000 24%, #000 72%, transparent);
  }

  /* Two plumes low in the ink half under the permit title. */
  .permit-row .side.heat::before {
    content: '';
    inset: 0 0 calc(var(--row-top) * -1) 0;
    --tone: var(--ramp-2);
    --art: url('/assets/img/trades/hvac/heat-drift.svg');
    --art-at: left bottom;
    --art-size: 100% auto;
    --fade: linear-gradient(to top, #000 42%, transparent 66%);
  }

  /* Air runs off the outer edge of the yellow half, beside the ComEd amounts and clear of its sentences. */
  .ledger-sides .side + .side::before {
    content: '';
    inset: 26% 0 12% 62%;
    --tone: var(--ramp-1);
    --art: url('/assets/img/trades/hvac/air-edge.svg');
    --art-at: right center;
    --art-size: auto 100%;
    --fade: linear-gradient(to left, #000 44%, transparent 92%);
  }

  /* One tall plate behind the whole ink half of the mail row. The rail and the fall card are opaque and sit
     on top of it, so the same lines show beside the title and again in the open step above the card. */
  .mail-row::before {
    content: '';
    inset: 0 50% 0 0;
    --tone: var(--ramp-2);
    --art: url('/assets/img/trades/hvac/heat-tall.svg');
    --art-at: center top;
    --art-size: cover;
    --fade: linear-gradient(to bottom, transparent, #000 14%, #000 58%, transparent 76%);
  }
  /* The open step under the spring card. */
  .mail-plan::after {
    content: '';
    grid-column: 2 / 3;
    grid-row: 2 / 3;
    inset: auto 0 0 0;
    height: calc(var(--stagger) - 0.5rem);
    --tone: var(--ramp-1);
    --art: url('/assets/img/trades/hvac/air-band.svg');
    --art-at: right center;
    --art-size: cover;
    --fade: linear-gradient(to left, #000 60%, transparent 96%);
  }

  /* Air settles along the bottom of the yellow half under the cooling question. */
  .faq-cool::before {
    content: '';
    inset: 0;
    --tone: var(--ramp-1);
    --art: url('/assets/img/trades/hvac/air-stream.svg');
    --art-at: right bottom;
    --art-size: 100% auto;
    --fade: linear-gradient(to top, #000 22%, transparent 42%);
  }

  /* Air slides under the trade links and on behind the closing panel. */
  .places .sides:not(.head) .side + .side::before {
    content: '';
    inset: auto 0 calc(var(--row-top) * -1) 0;
    height: calc(var(--row-top) + 0.5rem);
    --tone: var(--ramp-1);
    --art: url('/assets/img/trades/hvac/air-band.svg');
    --art-at: left bottom;
    --art-size: cover;
    --fade: linear-gradient(to right, transparent, #000 40%);
  }

  /* The last heat on the page: the same curtain, turned the other way, running under the footer. */
  .close-row .side.heat::before {
    content: '';
    inset: 0 0 calc(var(--row-top) * -1) 0;
    scale: -1 1;
    --tone: var(--ramp-2);
    --art: url('/assets/img/trades/hvac/heat-curtain.svg');
    --art-at: left bottom;
    --art-size: 110% auto;
    --fade: linear-gradient(to top, #000 30%, transparent 58%);
  }
}

/* ---------- The narrowest split: short table heads keep each city on one line, and the air stays clear of the amounts ---------- */
@media (min-width: 992px) and (max-width: 1199.98px) {
  .places .th-long { display: none; }
  .places .th-short { display: inline; }
  .ledger-sides .side + .side::before { inset-inline-start: 74%; }
}

/* ---------- Narrow: the seam turns horizontal ---------- */
@media (max-width: 991.98px) {
  main { background: var(--porch); }

  .row, .row.close-row { padding-top: 0; padding-bottom: 0; }
  .sides { display: block; margin-top: 0; }
  .side, .side + .side {
    padding: 1.5rem var(--gutter);
    background: var(--ground);
    color: var(--fg);
  }
  .ledger-sides .side, .ledger, .ledger tbody { display: block; }
  .ledger-sides .side + .side .ledger tr + tr td:first-child { padding-top: 0; }

  .slab { margin: 0; padding: 1.5rem var(--gutter); }
  /* Two lit rows never run together: a band of yellow sits between them. */
  .row > .slab:first-child { margin-top: 2.5rem; }

  /* A title opens its band; a panel is a band of its own, edge to edge. */
  .head .side, .head .side + .side { padding-block: 0; }
  .head .title, .faq-row > .title { padding-block: 2.25rem 1.25rem; }
  .panel, .head.flip .panel {
    margin: 0 calc(var(--gutter) * -1);
    padding: 1.25rem var(--gutter);
  }
  .head.flip > .side { padding-inline: var(--gutter); }
  .mail-head .side { --ground: var(--ink); --fg: var(--porch); }

  .hero .side.hero-lead { padding-block: calc(var(--header-h) + 0.25rem) 1.5rem; }
  .hero .side.hero-rest { display: block; padding-block: 1.5rem 0; }
  .hero-press { align-items: flex-start; flex-direction: column; }
  .hero-action { padding-block-end: 0; }
  .hero-intro { margin-block-start: 1.5rem; }

  .mail-plan { display: block; margin-top: 0; }
  .rail, .card, .card.spring, .card.heat { margin: 0; padding: 1.5rem var(--gutter); border: 0; }
  .card.heat::before { justify-self: start; }
  .rail { display: block; }
  .rail p + p { margin-top: 0.5rem; }
  .mail-plan > li::before { display: block; margin-bottom: 0.25rem; }

  .faq-row, .faq { display: block; }
  .faq-row > .title { padding-inline: var(--gutter); background: var(--ground); }
  .faq-item, .faq-paid, .faq-ideas, .faq-cost, .faq-fresh, .faq-cool, .faq-heat { margin: 0; padding: 1.5rem var(--gutter); background: var(--ground); }
  .faq-both + .faq-both { padding-top: 0; }
  .faq-paid dd { display: block; }
  .faq-paid dd p + p { margin-top: 0.75rem; }
  .places-lead { display: block; }
  /* One plate once the page stacks: the open corner beside the hero count, behind no words. */
  .hero-rest::before {
    content: '';
    inset: 0 0 auto auto;
    width: 58%;
    height: 11rem;
    --tone: var(--ramp-1);
    --art: url('/assets/img/trades/hvac/air-bend.svg');
    --art-at: right top;
    --art-size: auto 100%;
    --fade: linear-gradient(to left, #000 40%, transparent 92%);
  }
}

/* ---------- Tablet: the page stacks, but each band keeps two columns so no band runs a third empty ---------- */
@media (min-width: 768px) and (max-width: 991.98px) {
  .hero-intro p, .history-panel { max-width: none; columns: 2; column-gap: calc(var(--gutter) * 2); }
  .history-panel p { max-width: none; break-inside: avoid; }
  .history-panel p + p { margin-top: 0; margin-bottom: 0.9rem; }
  .history-panel p:first-child { margin-bottom: 0.9rem; }

  /* The one sentence, still in reading order: its opening across the top, the figure, and the rest beside it. */
  .panel .spend { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: calc(var(--gutter) * 2); max-width: none; }
  .spend-lead { grid-column: 1 / -1; }
  .spend-figure { grid-row: 2 / span 2; align-self: end; margin-block-end: 0; white-space: nowrap; }
  .spend-more { grid-column: 2; grid-row: 2; align-self: end; }
  .spend-rest { grid-column: 2; grid-row: 3; }

  .cool-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: calc(var(--gutter) * 2); }
  .cool-facts > .after-rule { margin-top: 0; padding-top: 0; padding-inline-end: 0; border-top: 0; }

  .ledger tbody { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: calc(var(--gutter) * 2); }
  .ledger tr + tr { border-top-width: 2px; border-top-color: var(--fg); }
  .ledger-sides .side + .side .ledger tr + tr td:first-child { padding-top: calc(var(--t-m) * 1.2); }
}

/* ---------- Phone ---------- */
@media (max-width: 767.98px) {
  .sources-notes { columns: 1; }
  .energy-slab, .costs-words, .count-article { display: block; }
  .energy-slab p + p, .costs-words p + p { margin-top: 0.9rem; }
  .count-words { margin-top: 1rem; }
  .count-field .unit-field, html.js .count-field .unit-field.is-columns { grid-template-rows: repeat(28, auto); gap: 2px; }
  .cost-strip.cost-table {
    & tbody { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    & tr, & tr:nth-child(3n + 1) { padding-inline: 0.75rem; border-left: 1px solid var(--line); }
    & tr:nth-child(odd) { padding-inline-start: 0; border-left: 0; }
    & tr:nth-child(n + 3) { border-top: 1px solid var(--line); }
  }
  .sources-table {
    display: block;
    font-size: var(--t-body);

    & thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
    & tbody, & tr, & th, & td { display: block; }
    & tr { padding-block: 0.7rem; border-bottom: 1px solid var(--line); }
    & tbody th, & tbody td { padding: 0; border: 0; }
    & th:first-child { width: auto; }
    & tbody td { display: grid; grid-template-columns: 8.5rem minmax(0, 1fr); column-gap: 0.75rem; padding-top: 0.15rem; font-size: var(--t-s); }
    & tbody td:nth-of-type(2) { white-space: normal; }
    & tbody td::before { content: attr(data-label); color: var(--fg-muted); }
  }

}

/* ==================== The national guide names no place and shows no market's number ====================
   (docs/plan-national-pages.md; owner, 2026-11-12.) The rows the national switch changed use class names the pages by
   place don't use, so nothing here reaches them: the hero's figure comes from a national source, the permit count's
   slab holds a made-up sample row, the cost strip's slab holds the cost calculator, the month chart's slab holds a
   national month chart, and the cities row points to the Coverage page. Every new block is seasonless, so it lies on
   lit across the seam or sits whole on one side. What the calculator needs to work is in pages.css. */

/* A figure's source: the publisher, linked, and the day we read it, on a line of its own. */
.national-source {
  font-size: var(--t-xs);
  color: var(--fg-muted);
  line-height: 1.35;

  & a { color: var(--fg); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 0.2em; }
  & .national-read { display: block; }
}

/* The hero's figure keeps the count's place beside the button: the number, what it counts on a short measure, then
   its source. */
.hero-national {
  max-width: 24rem;

  & .hero-count-where { margin-top: 0.35rem; }
  & .national-source { margin-top: 0.4rem; }
}

/* ---------- The sample row: the file's fields ruled four across the slab, the middle gap on the seam ---------- */
/* (The home page's sample uses .sample-*, so this one is .example-*.) */
.example-slab .title { margin-bottom: clamp(0.75rem, 1.6vw, 1.25rem); }
.example-note { max-width: var(--read); font-size: var(--t-m); line-height: 1.32; }
.example-file { margin-top: clamp(1.25rem, 2.6vw, 2rem); }
.example-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
  padding: 0.3rem 0.75rem;
  border: 2px solid var(--fg);
  font-size: var(--t-xs);
  font-weight: 750;
  letter-spacing: 0.04em;
  line-height: 1.25;
  text-transform: uppercase;
}
.example-fields {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  column-gap: calc(var(--slab-pad) * 2);
  border-top: 2px solid var(--fg);
}
.example-field {
  display: flex;
  flex-direction: column-reverse;
  justify-content: flex-end;
  gap: 0.3rem;
  padding-block: 0.75rem 0.8rem;
  border-bottom: 1px solid var(--line);

  & dt { display: grid; gap: 0.1rem; }
  & dd {
    margin: 0;
    font-family: var(--f-head);
    font-size: var(--t-m);
    font-weight: var(--w-sub);
    letter-spacing: -0.01em;
    line-height: 1.2;
    overflow-wrap: anywhere;
    font-variant-numeric: lining-nums tabular-nums;
  }
}
.example-label { font-size: var(--t-s); font-weight: 650; line-height: 1.3; }
.example-column { font-size: var(--t-xs); color: var(--fg-muted); overflow-wrap: anywhere; }

/* ---------- Costs: the words across the slab as before, then the reader's boxes on one side of the seam and the
   results ledger on the other, level at the top. ---------- */
.calc-cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: calc(var(--slab-pad) * 2);
  align-items: start;
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
}
.calc-inputs {
  display: grid;
  gap: 1.25rem;
  max-width: 34rem;
  font-size: var(--t-body);
  line-height: 1.45;
}
.calc-field input { max-width: 16rem; font-size: var(--t-m); font-weight: 650; font-variant-numeric: tabular-nums; }
.calc-entry {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;

  & input { flex: 0 1 16rem; min-width: 0; }
}
.calc-money { position: relative; display: block; }
/* Past the house form rule's own padding (pages.css, .field input), so the dollar sign sits clear of the number. */
.field.calc-field .calc-money input { padding-left: 1.85rem; }
.calc-unit {
  position: absolute;
  left: 0.85rem;
  top: 50%;
  translate: 0 -50%;
  font-size: var(--t-m);
  font-weight: 650;
  pointer-events: none;
}
.calc-help { font-size: var(--t-xs); color: var(--fg-muted); line-height: 1.35; max-width: 52ch; }
/* The example's tag takes the sample row's tag, since both mark something made up. */
.calc-example {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.3rem 0.75rem;
  border: 2px solid var(--fg);
  font-size: var(--t-xs);
  font-weight: 750;
  letter-spacing: 0.04em;
  line-height: 1.25;
  text-transform: uppercase;
}
.calc-go { white-space: normal; text-align: left; }
.calc-prompt { max-width: 34ch; font-size: var(--t-m); font-weight: 650; line-height: 1.3; }
/* The results, ruled as the rebate ledger was: a heavy rule over the first line and under the total, light ones between. */
.calc-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, auto);
  column-gap: 1rem;
  align-items: baseline;
  padding-block: 0.8rem;
  border-bottom: 1px solid var(--line);

  &:first-child { border-top: 2px solid var(--fg); }
  &:last-child { border-bottom: 2px solid var(--fg); }
  & dt { font-family: var(--f-head); font-size: var(--t-m); font-weight: var(--w-sub); letter-spacing: -0.01em; line-height: 1.2; }
  & dd { margin: 0; display: grid; justify-items: end; text-align: right; }
}
.calc-value {
  font-family: var(--f-head);
  font-size: var(--t-l);
  font-weight: var(--w-loud);
  letter-spacing: var(--track-l);
  line-height: 1.1;
  font-variant-numeric: lining-nums tabular-nums;
}
.calc-total .calc-value { font-size: var(--t-xl); letter-spacing: var(--track-xl); }
.calc-how {
  margin-top: 0.2rem;
  max-width: 30ch;
  font-size: var(--t-s);
  line-height: 1.35;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}
.calc-echo { color: var(--fg); font-weight: 650; }

/* ---------- The national month chart: no month is singled out, so every bar is set in full ink ---------- */
.months-slab {
  & .national-source { margin-bottom: clamp(1.25rem, 2.6vw, 2rem); max-width: var(--read); }
  & .big-col-bar { background: var(--fg); }
  & .month-caption { max-width: var(--read); margin-top: 1rem; }
}

/* ---------- Coverage: the pointer's title and caption on the ink, the link and the other trades on the yellow ---------- */
.covered-sides { margin-top: 0; }
.covered-caption { max-width: var(--read); margin-top: clamp(0.75rem, 1.6vw, 1.25rem); font-size: var(--t-m); line-height: 1.32; }
.covered-list li {
  border-top: 2px solid var(--fg);
  border-bottom: 1px solid var(--line);
}
.covered-place {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 3.5rem;
  padding: 0.6rem 0.5rem;
  font-family: var(--f-head);
  font-size: var(--t-l);
  font-weight: var(--w-head);
  letter-spacing: var(--track-l);
  line-height: 1.1;
  text-decoration: none;

  & .fa-solid { flex: none; font-size: 0.6em; transition: translate 0.45s var(--roll); }
  &:focus-visible { outline: 2px solid var(--fg); outline-offset: 3px; }
}
@media (hover: hover) {
  a.covered-place:hover .fa-solid { translate: 6px 0; }
}
html.reduced .covered-place .fa-solid { transition: none; }

@media (min-width: 992px) {
  .example-fields { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .example-field:nth-last-child(-n + 4) { border-bottom: 2px solid var(--fg); }

  /* The title and caption take the ink half's two lines; the link and the other trades the yellow half's. */
  .covered-sides { grid-template-rows: auto minmax(0, 1fr); }
  .covered-head { grid-column: 1; grid-row: 1 / span 2; }
  .covered-list { grid-column: 2; grid-row: 1; }
  .covered-sides .others { grid-column: 2; grid-row: 2; }

  /* Two plates, each in its half's open stretch: heat drifting up the ink under the caption, fading before it, and
     air sliding under the other trades and on behind the closing panel, as it slid under the trade links before. */
  .covered-head::before, .covered-sides .others::before {
    content: '';
    position: absolute;
    z-index: -1;
    pointer-events: none;
    background: var(--tone);
    -webkit-mask-image: var(--art), var(--fade);
    mask-image: var(--art), var(--fade);
    -webkit-mask-position: var(--art-at), 0 0;
    mask-position: var(--art-at), 0 0;
    -webkit-mask-size: var(--art-size), 100% 100%;
    mask-size: var(--art-size), 100% 100%;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-composite: source-in;
    mask-composite: intersect;
  }
  /* It fades out at its foot too, so it is gone before the closing title below. */
  .covered-head::before {
    inset: 0 0 calc(var(--row-top) * -0.8) 0;
    --tone: var(--ramp-2);
    --art: url('/assets/img/trades/hvac/heat-drift.svg');
    --art-at: left bottom;
    --art-size: 100% auto;
    --fade: linear-gradient(to top, transparent, #000 15%, #000 26%, transparent 46%);
  }
  .covered-sides .others::before {
    inset: auto 0 calc(var(--row-top) * -1) 0;
    height: calc(var(--row-top) + 0.5rem);
    --tone: var(--ramp-1);
    --art: url('/assets/img/trades/hvac/air-band.svg');
    --art-at: left bottom;
    --art-size: cover;
    --fade: linear-gradient(to right, transparent, #000 40%);
  }
}
/* The narrowest split wraps the caption to three lines and leaves the heat no room under it. */
@media (min-width: 992px) and (max-width: 1199.98px) {
  .covered-head::before { content: none; }
}
@media (min-width: 576px) and (max-width: 991.98px) {
  .example-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .example-field:nth-last-child(-n + 2) { border-bottom: 2px solid var(--fg); }
}
@media (max-width: 575.98px) {
  .example-field:last-child { border-bottom: 2px solid var(--fg); }
}

/* Narrow: the seam turns horizontal, so each block takes the full width of its band. */
@media (max-width: 991.98px) {
  .covered-head { padding-top: 2.25rem; }
  .covered-sides .others { margin-top: 0; padding-bottom: 2.5rem; }
}
/* Tablet: the boxes and the results keep their two columns, as every band does here. */
@media (min-width: 768px) and (max-width: 991.98px) {
  .calc-cols { column-gap: calc(var(--gutter) * 2); }
}
/* Phone: the boxes, then the results under them. */
@media (max-width: 767.98px) {
  .calc-cols { display: block; }
  .calc-inputs:not([hidden]) + .costs-results { margin-top: 1.75rem; }
}

/* ==================== Trade pages by place: /for/hvac/<state>/ and /for/hvac/<state>/<city>/ ====================
   The state and city pages keep the seam, the three grounds, the type and the art above, and lay out their own rows
   here (trades/local/hvac-local.njk). Every rule is scoped to those pages, so nothing above changes on the national
   guide. The two levels compose differently: the state page titles its rows on the ink and sets its words on yellow
   and lit; the city page puts one big figure on the ink half and its title and words on the yellow half. */
[data-page="trade-local"] {
  /* The greeting fits its half by its longest word (the partial sets who-len-N), so a long place name steps the
     size down instead of running into the seam. 0.6em is a wide letter's share of Montserrat's width. */
  & .hero-lead { container-type: inline-size; }
  & .hero-greeting { font-size: min(var(--t-mega), calc(100cqi / var(--who-len, 7) / 0.6)); }
  & .who-len-6 { --who-len: 6; } & .who-len-7 { --who-len: 7; } & .who-len-8 { --who-len: 8; } & .who-len-9 { --who-len: 9; }
  & .who-len-10 { --who-len: 10; } & .who-len-11 { --who-len: 11; } & .who-len-12 { --who-len: 12; } & .who-len-13 { --who-len: 13; }
  & .who-len-14 { --who-len: 14; } & .who-len-15 { --who-len: 15; } & .who-len-16 { --who-len: 16; }

  /* Small labels: where a utility serves, and the heads over each half's block. */
  & .area-label {
    display: flex;
    align-items: baseline;
    gap: 0.55rem;
    max-width: var(--read);
    margin-bottom: 0.75rem;
    font-size: var(--t-s);
    font-weight: 700;
    line-height: 1.3;

    & .fa-solid { flex: none; font-size: 0.95em; }
  }
  & .side-label {
    max-width: var(--read);
    margin-bottom: 0.9rem;
    font-family: var(--f-head);
    font-size: var(--t-m);
    font-weight: var(--w-sub);
    letter-spacing: -0.01em;
    line-height: 1.2;
  }

  /* Licensing: the answer on the lit panel, the narrow state license on the ink, the federal types ruled on yellow. */
  & .license-panel p + p { margin-top: 0.9rem; }
  & .license-lead { font-weight: 650; }
  & .license-boiler p { max-width: var(--read); }
  & .type-list {
    border-top: 2px solid var(--fg);

    & li {
      padding-block: 0.7rem;
      border-bottom: 1px solid var(--line);
      font-family: var(--f-head);
      font-size: var(--t-m);
      font-weight: var(--w-sub);
      letter-spacing: -0.01em;
      line-height: 1.22;
      max-width: var(--read);
    }
  }

  /* What a row carries: across the seam, one column to each side, the median set large. */
  & .rows-cols {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: calc(var(--slab-pad) * 2);
    margin-top: clamp(1rem, 2vw, 1.5rem);

    & p { max-width: var(--read); }
  }
  & .rows-who p + p { margin-top: 0.9rem; }
  & .rows-lead { font-size: var(--t-m); line-height: 1.32; font-weight: 500; }
  & .rows-pull {
    font-family: var(--f-head);
    font-size: var(--t-mega);
    font-weight: var(--w-loud);
    letter-spacing: var(--track-mega);
    line-height: 0.95;
    font-variant-numeric: lining-nums proportional-nums;
  }
  & .rows-fresh { margin-top: 0.6rem; font-size: var(--t-m); line-height: 1.32; }
  & .rows-built { margin-top: 1.25rem; padding-top: 1.25rem; border-top: 1px solid var(--line); font-weight: 650; }

  /* The rebate ledger on the state page: one table to a half, no shared subgrid, since the halves hold different counts. */
  & .rebate-sides {
    & .ledger, & .ledger tbody { display: block; }
    & .side + .side .ledger {
      font-size: var(--t-m);
      line-height: 1.32;

      & .amount { margin-block: 0.3rem 0.4rem; }
    }
  }
  & .rebates-lead strong { font-weight: 750; }

  /* The fall card: a postcard on the heating side, open at the seam like the national plan's heating card. */
  & .fall-card {
    max-width: var(--read);
    margin-top: clamp(1.5rem, 3vw, 2.25rem);
    padding: clamp(1rem, 2vw, 1.5rem);
    border: 2px solid var(--fg);
    font-family: var(--f-head);
    font-size: var(--t-m);
    font-weight: var(--w-sub);
    letter-spacing: -0.01em;
    line-height: 1.25;
  }

  /* Contractor networks: each under a rule, its first sentence set as a head. */
  & .network {
    & p:not(.area-label) { max-width: var(--read); }
    & .area-label { max-width: none; padding-top: 0.75rem; border-top: 2px solid var(--fg); }
  }
  & .network-lead {
    margin-bottom: 0.6rem;
    font-family: var(--f-head);
    font-size: var(--t-m);
    font-weight: var(--w-sub);
    letter-spacing: -0.01em;
    line-height: 1.25;
  }

  /* The city page's split rows: words on the yellow, one big figure on the ink. */
  & .flip-words .panel { margin-top: var(--under-head); }
  & .permits-panel p + p { margin-top: 0.9rem; }
  & .permits-swap { font-weight: 650; }
  & .year-lead { max-width: var(--read); font-size: var(--t-m); font-weight: 650; line-height: 1.25; }
  & .year-big {
    font-family: var(--f-head);
    font-size: min(13rem, calc((50vw - var(--gutter) - var(--slab-pad)) / 3.2));
    font-weight: var(--w-loud);
    letter-spacing: var(--track-mega);
    line-height: 0.92;
    font-variant-numeric: lining-nums proportional-nums;
  }
  & .peoples-terms { max-width: var(--read); margin-top: clamp(1.25rem, 2.4vw, 1.75rem); padding-top: 0.9rem; border-top: 2px solid var(--fg); }
  & .peoples-line {
    max-width: var(--read);
    padding-top: 0.75rem;
    border-top: 2px solid var(--fg);
    font-size: var(--t-m);
    line-height: 1.32;
  }
  & .peoples-name {
    display: block;
    font-family: var(--f-head);
    font-weight: var(--w-sub);
    letter-spacing: -0.01em;
    line-height: 1.2;
  }

  /* The city page's license row: the two licenses ruled on the ink, the link to the state page's answer on the yellow. */
  & .city-license {
    padding-top: 0.75rem;
    border-top: 2px solid var(--fg);

    & p { max-width: var(--read); }
    & p + p { margin-top: 0.9rem; }
  }
  & .city-license-print { font-weight: 650; }
  & .state-license { max-width: 34rem; margin-top: clamp(1.25rem, 2.4vw, 1.75rem); }
  & .state-license .more-link { border-top: 2px solid var(--fg); border-bottom-width: 2px; border-bottom-color: var(--fg); }

  /* Costs on the city page: the basis under the title, the strip below. */
  & .costs-basis { max-width: var(--read); font-size: var(--t-m); line-height: 1.32; }

  /* ZIPs on the ink, as ruled rows. */
  & .zips-side .zips-title { margin-top: clamp(1.25rem, 2.4vw, 1.75rem); margin-bottom: 0; color: var(--fg); font-size: var(--t-m); font-weight: var(--w-sub); line-height: 1.2; }
  & .zips-side .zips-title + .chip-list {
    display: block;
    margin-top: 0.6rem;
    border-top: 2px solid var(--fg);

    & .chip {
      display: grid;
      grid-template-columns: minmax(0, 1fr) auto 1.25rem;
      align-items: center;
      column-gap: 1rem;
      min-height: 3.5rem;
      padding: 0 0.5rem;
      border: 0;
      border-bottom: 1px solid var(--line);
      border-radius: 0;
      font-family: var(--f-head);
      font-size: var(--t-m);
      font-weight: var(--w-sub);
      letter-spacing: -0.01em;
    }
    & .chip-count { font-family: var(--f); font-size: var(--t-body); font-weight: 600; color: var(--fg); }
  }

  /* Links out: big arrow links to the same trade elsewhere, chips for the other trades. */
  & .links-title {
    margin-bottom: 0.9rem;
    font-family: var(--f-head);
    font-size: var(--t-l);
    font-weight: var(--w-head);
    letter-spacing: var(--track-l);
    line-height: 1.08;
  }
  & .local-links .others { margin-top: clamp(2rem, 3.4vw, 3rem); }
  & .more-links { border-top: 2px solid var(--fg); }
  & .more-link {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    min-height: 2.75rem;
    padding-block: 0.7rem;
    border-bottom: 1px solid var(--line);
    font-family: var(--f-head);
    font-size: var(--t-m);
    font-weight: var(--w-sub);
    letter-spacing: -0.015em;
    line-height: 1.2;
    text-decoration: none;

    & .fa-solid { flex: none; font-size: 0.8em; transition: translate 0.45s var(--roll); }
    &:focus-visible { outline: 2px solid var(--fg); outline-offset: 3px; }
  }
}
@media (hover: hover) {
  [data-page="trade-local"] .more-link:hover .fa-solid { translate: 4px 0; }
}

/* Plates on the local rows: the same masks as the national guide's, each placed in an open stretch of its own half. */
[data-page="trade-local"] :is(.license-sides .side.heat, .local-networks .head.flip, .permit-sides .side.heat, .city-license-sides .flip-words, .zips-sides .side + .side)::before {
  position: absolute;
  z-index: -1;
  pointer-events: none;
  background: var(--tone);
  -webkit-mask-image: var(--art), var(--fade);
  mask-image: var(--art), var(--fade);
  -webkit-mask-position: var(--art-at), 0 0;
  mask-position: var(--art-at), 0 0;
  -webkit-mask-size: var(--art-size), 100% 100%;
  mask-size: var(--art-size), 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}

/* Wide: the seam runs down the middle. */
@media (min-width: 992px) {
  [data-page="trade-local"] {
    /* The city page's split rows: the words' half comes first in reading order and sits on the yellow; the figure
       takes the ink half, low, so the title and the figure sit on a diagonal. */
    & .flip-sides { margin-top: 0; }
    & .flip-sides > .flip-words { grid-column: 2; grid-row: 1; padding-inline: var(--slab-pad) var(--edge); }
    & .flip-sides > .flip-figure {
      grid-column: 1;
      grid-row: 1;
      display: flex;
      flex-direction: column;
      justify-content: flex-end;
      padding-inline: var(--edge) var(--slab-pad);
    }

    /* The ink half beside the federal types holds only art: heat drifts up through the open space. */
    & .license-sides .side.heat::before {
      content: '';
      inset: 0 0 calc(var(--row-top) * -0.5) 0;
      --tone: var(--ramp-2);
      --art: url('/assets/img/trades/hvac/heat-drift.svg');
      --art-at: left bottom;
      --art-size: 100% auto;
      --fade: linear-gradient(to top, #000 30%, transparent 62%);
    }
    & .license-sides .license-boiler { padding-bottom: clamp(6rem, 14vw, 12rem); }

    /* The ink half beside the networks title belongs to the art. */
    & .local-networks .head.flip::before {
      content: '';
      grid-column: 1 / 2;
      grid-row: 1 / 2;
      inset: calc(var(--row-top) * -1) 0 0 0;
      --tone: var(--ramp-2);
      --art: url('/assets/img/trades/hvac/heat-climb.svg');
      --art-at: center;
      --art-size: cover;
      --fade: linear-gradient(to bottom, transparent, #000 24%, #000 72%, transparent);
    }

    /* Heat climbs the top of the ink half and fades before the year at its foot. */
    & .permit-sides .side.heat::before {
      content: '';
      inset: calc(var(--row-top) * -1) 0 45% 0;
      --tone: var(--ramp-2);
      --art: url('/assets/img/trades/hvac/heat-tall.svg');
      --art-at: center top;
      --art-size: cover;
      --fade: linear-gradient(to bottom, transparent, #000 30%, #000 60%, transparent);
    }

    /* Air runs along the foot of the yellow half under the link to the state page, clear of the words above it. */
    & .city-license-sides .flip-words::before {
      content: '';
      inset: auto 0 0 0;
      height: clamp(5rem, 9vw, 8rem);
      --tone: var(--ramp-1);
      --art: url('/assets/img/trades/hvac/air-band.svg');
      --art-at: right bottom;
      --art-size: cover;
      --fade: linear-gradient(to left, #000 50%, transparent 96%);
    }
    & .city-license-sides .flip-words { padding-bottom: clamp(6rem, 10vw, 9rem); }
    & .city-licenses { gap: clamp(1.75rem, 3.4vw, 2.75rem); }

    /* Air slides under the links on the city page's last row, as under the national guide's trade links. */
    & .zips-sides .side + .side::before {
      content: '';
      inset: auto 0 calc(var(--row-top) * -1) 0;
      height: calc(var(--row-top) + 0.5rem);
      --tone: var(--ramp-1);
      --art: url('/assets/img/trades/hvac/air-band.svg');
      --art-at: left bottom;
      --art-size: cover;
      --fade: linear-gradient(to right, transparent, #000 40%);
    }
  }
}

/* In-flow plates, for the halves the final copy left with an open stretch: the half becomes a column and the art
   takes only the space its words leave, so it sits under no word at any width. The ComEd half and the Peoples Gas
   ink half lost their plates here, since their words now run the full height of the half. */
@media (min-width: 992px) {
  [data-page="trade-local"] {
    & .rebate-sides .side.heat, & .peoples-sides .flip-words { display: flex; flex-direction: column; }
    & .rebate-sides .side.heat::after, & .peoples-sides .flip-words::after {
      content: '';
      position: relative;
      z-index: -1;
      flex: 1 1 auto;
      min-height: 0;
      margin-top: clamp(2rem, 4vw, 3.5rem);
      pointer-events: none;
      background: var(--tone);
      -webkit-mask-image: var(--art), var(--fade);
      mask-image: var(--art), var(--fade);
      -webkit-mask-position: var(--art-at), 0 0;
      mask-position: var(--art-at), 0 0;
      -webkit-mask-size: var(--art-size), 100% 100%;
      mask-size: var(--art-size), 100% 100%;
      -webkit-mask-repeat: no-repeat;
      mask-repeat: no-repeat;
      -webkit-mask-composite: source-in;
      mask-composite: intersect;
    }

    /* Heat hangs in the ink half's open foot under Nicor's terms, gone at both ends so it meets neither the words
       above it nor the networks plate below it. */
    & .rebate-sides .side.heat::after {
      margin-inline: calc(var(--edge) * -1) calc(var(--slab-pad) * -1);
      --tone: var(--ramp-2);
      --art: url('/assets/img/trades/hvac/heat-curtain.svg');
      --art-at: center bottom;
      --art-size: cover;
      --fade: linear-gradient(to bottom, transparent, #000 26%, #000 50%, transparent 76%);
    }

    /* The closing heat starts a little lower than on the guide: here the guide's fade let the first strokes reach the
       descender of "weekly". */
    & .close-row .side.heat::before { --fade: linear-gradient(to top, #000 24%, transparent 50%); }

    /* Air streams in off the outer edge of the yellow half, through the open stretch under the Peoples Gas title and
       on into the gap above the links, where no word sits. */
    & .peoples-sides .flip-words::after {
      margin-inline: calc(var(--slab-pad) * -1) calc(var(--edge) * -1);
      margin-bottom: calc(var(--row-top) * -0.6);
      --tone: var(--ramp-1);
      --art: url('/assets/img/trades/hvac/air-stream.svg');
      --art-at: right center;
      --art-size: cover;
      --fade: radial-gradient(ellipse 100% 80% at 100% 50%, #000 36%, transparent 100%);
    }
  }
}

/* Narrow: the seam turns horizontal, and each block keeps its ground. */
@media (max-width: 991.98px) {
  [data-page="trade-local"] {
    & .flip-words .title { padding-block: 2.25rem 1.25rem; }
    /* The networks title opens an ink band, as the national mail plan's does, so it never runs into ComEd's yellow. */
    & .local-networks .head.flip .side { --ground: var(--ink); --fg: var(--porch); }
    & .flip-words { padding-top: 0; }
    & .flip-words .panel { margin: 0 calc(var(--gutter) * -1); padding: 1.25rem var(--gutter); }
    & .flip-figure { padding-block: 1.75rem; }
    & .year-big { font-size: min(9rem, calc((100vw - var(--gutter) * 2) / 3.2)); }
    & .license-sides .side, & .rebate-sides .side, & .network-sides .side, & .zips-sides .side { padding-block: 1.75rem; }
    & .local-links { padding-block: 1.75rem 2.5rem; }
    & .city-license + .city-license { margin-top: 1.75rem; }
    /* The ZIPs open on ink right after the Peoples Gas ink band, so a band of yellow sits between them. */
    & .local-zips { padding-top: 2.5rem; }
  }
}

/* Tablet: the page stacks, but each band keeps two columns so no band runs a third empty. */
@media (min-width: 768px) and (max-width: 991.98px) {
  [data-page="trade-local"] {
    & .license-panel, & .permits-panel {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      column-gap: calc(var(--gutter) * 2);

      & p + p { margin-top: 0; }
    }
    & .license-boiler { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: calc(var(--gutter) * 2); }
    & .type-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: calc(var(--gutter) * 2); }
    & .rebate-sides .side:first-child .ledger tr {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      column-gap: calc(var(--gutter) * 2);

      & th, & td:first-of-type { grid-column: 1; }
      & td + td { grid-column: 2; grid-row: 1 / span 2; margin-top: 0; padding-top: 0; }
    }
    & .rebate-sides .side + .side .ledger tbody { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: calc(var(--gutter) * 2); }
    & .network { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: calc(var(--gutter) * 2); align-items: start; }
    & .network .area-label { grid-column: 1 / -1; }
    & .network .network-lead { margin-bottom: 0; }
    & .city-licenses { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: calc(var(--gutter) * 2); align-items: start; }
    & .city-licenses .city-license + .city-license { margin-top: 0; }
    & .peoples-pay { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: calc(var(--gutter) * 2); align-items: start; }
    & .peoples-pay .area-label { grid-column: 1 / -1; }
    & .peoples-pay .fall-card { margin-top: 0; grid-column: 2; grid-row: 2 / span 2; }
    & .peoples-pay :is(.peoples-line, .peoples-terms) { grid-column: 1; }
    & .local-links { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: calc(var(--gutter) * 2); align-items: start; }
    & .local-links .others { margin-top: 0; }
  }
}

/* Phone: one column. */
@media (max-width: 767.98px) {
  [data-page="trade-local"] {
    & .rows-cols { display: block; }
    & .rows-when { margin-top: 1.5rem; }
  }
}

/* Stacked, the ink half beside the federal types would be an empty band, since it holds only art (the boiler
   repairer license it once held was left off on 2026-11-10). */
@media (max-width: 991.98px) {
  [data-page="trade-local"] .license-sides .license-boiler { display: none; }
}

/* The local pages' intros are one or two short sentences: split into two columns at tablet width they break
   mid-phrase, so they stay one column there (orchestrator, 2026-11-10, after the visual review). */
@media (min-width: 768px) and (max-width: 991.98px) {
  [data-page="trade-local"] .hero-intro p { columns: auto; max-width: 62ch; }
}
