/*
 * The planner's one screen (docs/design/planner-2.md): the inputs and the answer together, phone first, then two columns
 * on a wide screen (inputs left, answer right). Nothing here is sticky. Colours, type and spacing are the site's tokens
 * (site/assets/css/site.css); no raw colour is used. The order on the page is the order in the document, so a keyboard and
 * a screen reader meet the fields, then the answer, then the folds.
 */

.jobplan {
  /* A screen's height is kept for the planner before its script has drawn it, so what follows it on the page stays where it is. */
  min-height: 46rem;
  margin-top: var(--space-smd);
}

.jobplan__cols {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: minmax(0, 1fr);
}

.jobplan__inputs,
.jobplan__answer,
.jobplan__extra,
.jobplan__more {
  min-width: 0;
}

/* WP-2.2: what is counted in the room, the drawing and the typical rooms, after the answer on a phone. */
.jobplan__extra {
  display: grid;
  gap: var(--space-md);
}

/* The answer in one line under the sizes, for a phone with its keyboard up; the card is beside the fields on a wide screen.
   16 px since the home page's Release 2 (it was 18 px), so it never outranks the numbers it repeats. */
.jobplan__live {
  margin: var(--space-sm) 0 0;
  font-family: var(--font-heading);
  font-size: var(--text-base);
  font-weight: 700;
}

.jobplan__live:empty {
  display: none;
}

.jobplan__live.is-stale {
  opacity: 0.45;
}

/* WP-2.2: the example's answer in the page's HTML, before the script draws the screen over it (components/Planner.astro). */
.jobplan__working {
  margin: var(--space-xs) 0 0;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

/* A laminate's typical packs, drawn in the HTML beside "Pack size?" (the home page's Release 1), are greyed as the fields are
   until the script makes them work; the words under them stay at full strength. */
[data-static-planner] .jobplan__jobs,
[data-static-planner] .jobplan__fields,
[data-static-planner] .pnumber__extras .pchoice {
  opacity: 0.6;
}

/* The analytics question, when it is asked (WP-2.1): one line straight after the answer card, across the whole width. */
.jobplan__cols > .consent {
  grid-column: 1 / -1;
  margin: 0;
}

/* ---- the job --------------------------------------------------------------------------------------------- */

.jobplan__jobs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  min-inline-size: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

/* WP-2.3: every job a chip. Until 19 October 2026 the chips were one row that scrolled sideways on a phone, with a chip cut
   at the edge to say there was more; at 390 px nine of the eleven were off the screen, and the owner could not see the
   jobs ("on phone you cannot see the different jobs they go past the screen"). They wrap now on every screen, a little
   smaller on a phone (below), so that every job is in sight and the example's first number is still on the first screen. */
.jobplan__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
}

.jobplan__chip {
  position: relative;
  display: inline-flex;
}

.jobplan__chips .jobplan__chip {
  flex: none;
}

/* A job's name stays on one line; other chips (the kinds of paint) wrap their words as before. */
.jobplan__chips .jobplan__chip span {
  white-space: nowrap;
}

/* On a phone the job chips are a little tighter (a 20 px picture, 14 px words, 6 px at the sides), so the eleven take four
   rows at 390 px where they would take five; each is still a 44 px target. */
@media (max-width: 39.99rem) {
  .jobplan__chips .jobplan__chip span {
    gap: 0.25rem;
    padding-inline: 0.375rem;
    font-size: 0.875rem;
  }

  .jobplan__chips .jobplan__chip .ill {
    width: 1.25rem;
    height: 1.25rem;
  }
}

.jobplan__chip .ill {
  width: 1.5rem;
  height: 1.5rem;
  flex: none;
}

.jobplan__chip input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.jobplan__chip span {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 2.75rem;
  padding: var(--space-xs) 0.625rem;
  border: var(--border-thin) solid var(--color-control-border);
  border-radius: var(--radius);
  background: var(--color-card);
  color: var(--color-foreground);
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 600;
}

.jobplan__chip input:checked + span {
  border-color: var(--color-primary);
  background: var(--color-primary);
  color: var(--color-on-primary);
}

.jobplan__chip input:focus-visible + span {
  outline: 3px solid var(--color-ring);
  outline-offset: 2px;
}


.jobplan__jobs-legend {
  width: 100%;
  margin-bottom: var(--space-xs);
  padding: 0;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
  font-weight: 600;
}

.jobplan__more .jobplan__jobs {
  margin-top: var(--space-sm);
}

/* ---- the fields ------------------------------------------------------------------------------------------ */

.jobplan__rows {
  display: grid;
  gap: var(--space-smd);
}

.jobplan__cols > .jobplan__jobs {
  margin-bottom: calc(var(--space-smd) - var(--space-lg));
}

.jobplan__row {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 0.375rem;
}

/* The sizes, with the metres-or-feet switch at their end: the fields give a little so that the switch stays on their row. */
.jobplan__row--sizes .pfield {
  flex-basis: 4.5rem;
}

.punits {
  display: flex;
  flex: 0 0 4.5rem;
  align-self: center;
  min-height: 2.75rem;
  border: var(--border-control) solid var(--color-control-border);
  border-radius: var(--radius);
  overflow: hidden;
}

.punits__button {
  flex: 1 1 50%;
  min-width: 0;
  min-height: 2.75rem;
  padding: 0;
  border: 0;
  background: var(--color-card);
  color: var(--color-foreground);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
}

.punits__button[aria-pressed="true"] {
  background: var(--color-primary);
  color: var(--color-on-primary);
}

.punits__button:focus-visible {
  outline: 3px solid var(--color-ring);
  outline-offset: -3px;
}

.jobplan__units-note {
  margin: var(--space-xs) 0 0;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

/* WP-2.2: a size few rooms have, asked under the sizes, with the likely one as a button. */
.jobplan__size-ask {
  margin: var(--space-xs) 0 0;
}

.jobplan__size-question {
  margin: var(--space-xs) 0 0;
  color: var(--color-warning-text);
  font-size: var(--text-sm);
}

/* One field: its name small inside the box, the figure under it, the unit at the end. The whole box is the label. */
.pfield {
  display: grid;
  flex: 1 1 5.5rem;
  min-width: 0;
  max-width: 11rem;
  padding: var(--space-xs) var(--space-sm) 0.125rem;
  border: var(--border-thin) solid var(--color-control-border);
  border-radius: var(--radius);
  background: var(--color-card);
  cursor: text;
}

.pfield:hover {
  border-color: var(--color-primary);
}

.pfield:focus-within {
  outline: 3px solid var(--color-ring);
  outline-offset: 2px;
}

.pfield--wide {
  flex-basis: 9rem;
  max-width: 16rem;
}

.pfield__label {
  color: var(--color-muted-foreground);
  font-size: var(--text-sm); /* release F (WP-2.4 step 3): field labels at 14 px */
  font-weight: 600;
  line-height: 1.3;
}

.pfield__box {
  display: flex;
  align-items: baseline;
  gap: var(--space-xs);
}

.pfield__input {
  width: 100%;
  min-width: 0;
  min-height: 1.875rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-foreground);
  font: inherit;
  font-size: var(--text-lg);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.pfield__input:focus-visible {
  outline: 0; /* the ring is on the whole box */
}

select.pfield__input {
  font-size: var(--text-base);
  cursor: pointer;
}

.pfield__unit {
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

.pfield[data-invalid] {
  border-color: var(--color-destructive-text);
}

.jobplan__times {
  align-self: center;
  color: var(--color-muted-foreground);
  font-weight: 600;
}

/* A stepper: what is counted, small, over less, the count and more. Each button is 44 px; three share a phone's row. */
.stepper {
  display: grid;
  flex: 1 1 7rem;
  min-width: 0;
  max-width: 11rem;
  padding: var(--space-xs) 0 0;
  border: var(--border-thin) solid var(--color-control-border);
  border-radius: var(--radius);
  background: var(--color-card);
}

.stepper__label {
  padding: 0 var(--space-sm);
  color: var(--color-muted-foreground);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.3;
}

.stepper__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.stepper__button {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius);
  background: none;
  color: var(--color-foreground);
  font: inherit;
  font-size: var(--text-xl);
  line-height: 1;
  cursor: pointer;
}

.stepper__button:hover {
  background: var(--color-muted);
}

.stepper__button:disabled {
  color: var(--color-control-border);
  cursor: not-allowed;
}

/* Beside a count that is more than was typed: "(one for the colour change)" (WP-1.4). */
.stepper__note {
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

.stepper__value {
  min-width: 1.25rem;
  font-size: var(--text-lg);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

/* A tick as a chip: the whole chip is the label. */
.ptick {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  min-height: 2.75rem;
  padding: var(--space-xs) var(--space-smd);
  border: var(--border-thin) solid var(--color-control-border);
  border-radius: var(--radius);
  background: var(--color-card);
  font-weight: 600;
  cursor: pointer;
}

.ptick input {
  width: 1.25rem;
  height: 1.25rem;
  margin: 0;
  accent-color: var(--color-primary);
}

.ptick:has(input:focus-visible) {
  outline: 3px solid var(--color-ring);
  outline-offset: 2px;
}

.jobplan__link {
  min-height: 2.75rem;
  padding: var(--space-xs) 0;
  border: 0;
  background: none;
  color: var(--color-link);
  font: inherit;
  font-size: var(--text-sm);
  text-align: left;
  text-decoration: underline;
  text-underline-offset: 0.18em;
  cursor: pointer;
}

.jobplan__link:hover {
  color: var(--color-link-hover);
}

.jobplan__rooms {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--space-md);
  margin: calc(-1 * var(--space-sm)) 0;
  padding: 0;
  list-style: none;
}

.jobplan__problem {
  margin: 0;
  color: var(--color-destructive-text);
  font-size: var(--text-sm);
  font-weight: 600;
}

.jobplan__notice {
  margin: 0 0 var(--space-md);
  padding: var(--space-smd);
  border: var(--border-thin) solid var(--color-warning-text);
  border-radius: var(--radius);
  background: var(--color-warning-tint);
  color: var(--color-warning-text);
  font-size: var(--text-sm);
}

.jobplan__defaults {
  margin: 0;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

/* The room to scale. Its height is fixed, so a drawing that changes never moves what is under it. */
.jobplan__drawing {
  margin: var(--space-smd) 0 0;
}

/* Release F (WP-2.5; DU-14): the room's drawing is a small picture under the card, 88 px tall at most, where it took 161 px of
   the first screen; its one line of figures under it. */
.jobplan__drawing svg {
  display: block;
  width: 100%;
  height: auto;
  max-height: 5.5rem;
}

/* The layout under the answer: the tiles with their cuts, the boards row by row, the drops by roll, at the page's width. */
.jobplan__layout {
  margin: var(--space-lg) 0 0;
  padding-top: var(--space-md);
  border-top: var(--border-thin) solid var(--color-border);
}

.jobplan__layout-title {
  margin-bottom: var(--space-sm);
  font-family: var(--font-body);
  font-size: var(--text-base);
}

.jobplan__layout svg {
  display: block;
  width: 100%;
  height: auto;
  max-width: 40rem;
}

.jobplan__layout svg + svg {
  margin-top: var(--space-md);
}

.jobplan__layout-words {
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

.jobplan__layout-words p {
  margin: var(--space-xs) 0 0;
}

/* Under a painted room's drawing, beside its ceiling's area: one wall on its own, or the whole room again. The link is a
   full target, drawn into the caption's own line so the answer under it does not move down. */
.jobplan__drawing figcaption {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0 var(--space-md);
}

.jobplan__drawing figcaption .jobplan__link {
  margin: calc(-1 * var(--space-smd)) 0;
}

.jobplan__drawing figcaption {
  margin-top: var(--space-xs);
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

/* ---- the answer ------------------------------------------------------------------------------------------ */

/* Release F (WP-2.4 step 3; DU-09): lime is the primary button, a chosen chip's underline and the focus ring on graphite, and
   nothing else; the card's lime edge went. */
.jobplan__answer {
  padding: var(--space-md);
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-card);
}

.jobplan__answer.is-stale .jobplan__numbers,
.jobplan__answer.is-stale .jobplan__cost {
  opacity: 0.55;
}

.jobplan__example {
  display: inline-block;
  margin: 0 0 var(--space-xs);
  padding: 0.125rem var(--space-sm);
  border-radius: 4px;
  background: var(--color-muted);
  color: var(--color-foreground);
  font-size: var(--text-sm);
  font-weight: 600;
}

/* The sentence heads the answer, the room in one small line, on a phone too (release F, WP-2.4 step 1; AM-9: a phone reader
   scrolled back up sees which room the figures are for). */
.jobplan__sentence {
  margin: 0;
  color: var(--color-muted-foreground);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.4;
}

.jobplan__numbers {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-md) var(--space-md);
  margin: var(--space-sm) 0 0;
}

/* A purchase in two parts ("1 × 5 L + 1 × 2.5 L") wraps at the same size (release F, WP-2.4 step 1: one size for every
   number of the answer, wrapping not shrinking). Since the home page's Release 1 (19 October 2026) a long quantity ("2 bulk
   bags", "10 × 25 kg") takes the whole row of the numbers on a phone, where half the card's width cannot hold it, and on the
   narrowest phones every number has the whole row: a quantity wraps only between words (answer.js, unbrokenQuantity). */
.pnumber--long .pnumber__quantity {
  font-size: var(--text-num);
}

@media (max-width: 29.99rem) {
  .pnumber--long {
    grid-column: 1 / -1;
  }
}

@media (max-width: 22.49rem) {
  .jobplan__numbers {
    grid-template-columns: minmax(0, 1fr);
  }
}

.pnumber {
  min-width: 0;
  margin: 0;
}

.pnumber__label {
  margin: 0;
  color: var(--color-muted-foreground);
  font-family: var(--font-body);
  font-size: var(--text-label);
  font-weight: 600;
}

.pnumber__quantity {
  display: inline;
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--text-num);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  /* A word is never broken inside: "2 bulk bag / s" read as broken arithmetic (the home page's Release 1). */
  overflow-wrap: normal;
  /* The mark of a number that has just changed: a graphite line under it that fades in 150 ms (release F; it was lime). */
  background-image: linear-gradient(var(--color-bar), var(--color-bar));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 0;
}

@media (prefers-reduced-motion: no-preference) {
  .pnumber.is-changed .pnumber__quantity {
    animation: planner-changed 1s var(--ease-out) 1;
  }
}

@keyframes planner-changed {
  0% { background-size: 100% 0.15em; }
  85% { background-size: 100% 0.15em; }
  100% { background-size: 100% 0; }
}

.pnumber__detail,
.pnumber__spare,
.pnumber__product {
  margin: 0.125rem 0 0;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

/* A paint in a colour the person named, under its number ("Dulux Heritage Sage Green, your colour"): no shop's product.
   Since the home page's Release 2 a shop's product is a line of the money, with its price. */
.pnumber__product {
  overflow-wrap: anywhere;
}

.pnumber__bar svg {
  display: block;
  width: 100%;
  max-width: 14rem;
  height: auto;
  margin-top: var(--space-xs);
}

.pask {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs) var(--space-sm);
  margin-top: var(--space-sm);
  font-size: var(--text-sm);
}

.pask__label {
  font-weight: 600;
}

.pask__box {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
}

.pask__input {
  width: 4.5rem;
  min-height: 2.75rem;
  padding: var(--space-xs) var(--space-sm);
  border: var(--border-thin) solid var(--color-control-border);
  border-radius: var(--radius);
  background: var(--color-card);
  color: var(--color-foreground);
  font: inherit;
  font-size: var(--text-base);
  font-variant-numeric: tabular-nums;
}

.pask__input:hover {
  border-color: var(--color-primary);
}

/* A box with an example in it ("e.g. 1.08", what a box of tiles covers) is wide enough to show the example whole. */
.pask__input[placeholder] {
  width: 6rem;
}

/* An example in a box ("e.g. 53", the typical roll's width; "e.g. 1.08", a box of tiles) is slate, 6.57:1 on paper, where the
   browser's own grey can fall under 4.5:1; a figure typed is graphite. Every example says "e.g.", so none reads as typed
   (the home page's Release 1). */
.pask__input::placeholder {
  color: var(--color-muted-foreground);
  opacity: 1;
}

.pnumber__body {
  margin: 0;
}

.pnumber__line {
  display: block;
}

/* The cost (the home page's Release 2): whose prices and their day as its head, then one row of money at 32 px ("£84 paint
   for the walls and ceiling"), below the number to buy; the products it is priced in at 14 px; the materials at 16 px; the
   labour at 14 px, never larger than the materials. */
.jobplan__cost {
  min-height: 5.5rem;
  margin-top: var(--space-sm);
  padding-top: var(--space-sm);
  border-top: var(--border-thin) solid var(--color-border);
}

.pcost__figure {
  display: block;
  font-family: var(--font-heading);
  font-size: var(--text-num);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

/* The lead row: the figure, then what it is, on one line where it fits. */
.pcost__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 var(--space-sm);
  margin: var(--space-sm) 0 0;
}

.pcost__head .pcost__figure {
  display: inline;
  font-size: var(--text-money);
}

.pcost__head-words {
  font-size: var(--text-base);
}

/* The products the lead figure is priced in, in the buy rows' own words, with each tin's price. */
.pcost__products {
  margin: var(--space-xs) 0 0;
  font-size: var(--text-sm);
}

/* One line each where it fits: the product's name gives way, ended by an ellipsis, so what it is for and its price always show
   (the full name is the line's own text for a screen reader, its title for a pointer, and the buy row's under "Where to buy
   it"). The specification's first lever, taken because the lime button measured lower than 1,040 px on a phone without it.
   Where what it is for and its price would leave the name less than 5em (the walls and the ceiling in one tin, or a 320 px
   phone), they go under the name and may wrap there, so the name stays readable and nothing runs out of the card (the review
   of Release 2). */
.pcost__product {
  display: flex;
  flex-wrap: wrap;
  min-width: 0;
  margin: 0.125rem 0 0;
  white-space: nowrap;
}

.pcost__product-count {
  flex: none;
  margin-right: 0.25em;
}

.pcost__product-name {
  flex: 1 1 5em;
  max-width: max-content;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pcost__product-for {
  flex: 0 1 auto;
  min-width: 0;
  margin-left: 0.25em;
  white-space: normal;
}

.pcost__product-for--comma {
  margin-left: 0;
}

.pcost__price {
  color: var(--color-price);
  font-variant-numeric: tabular-nums;
}

/* The materials in one line under the paint's own row ("Materials £148, with filler, …"), 600. At 14 px, the specification's
   second lever (its 16 px left the lime button lower than 1,040 px on a phone and 768 px on a laptop); still no smaller
   than the labour under it. */
.pcost__materials {
  margin: var(--space-sm) 0 0;
  font-size: var(--text-sm);
  font-weight: 600;
}

.pcost__figure--inline {
  display: inline;
  font-family: var(--font-body);
  font-size: inherit;
  font-weight: 600;
}

/* Having it done: text size, the figures 600; its second line opens "Having it done instead". */
.pcost__labour {
  margin: var(--space-sm) 0 0;
  font-size: var(--text-sm);
}

.pcost__labour-line {
  margin: 0;
}

.pcost__labour strong {
  font-weight: 600;
}

.pcost__labour-open {
  display: inline-block;
  min-height: 0;
  margin: -0.75rem 0;
  padding: 0.75rem 0;
  color: var(--color-link);
  line-height: 1.5;
}

.pcost__what {
  display: block;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

/* The second layer, after the lime button: "Where to buy it", the paid buy buttons, the other tins, the grades, the tools, the
   delivery and the shops' table. */
.pcost__more {
  margin-top: var(--space-md);
  padding-top: var(--space-smd);
  border-top: var(--border-thin) solid var(--color-border);
}

.pcost__more:not(:has(> :not([hidden]))) {
  display: none;
}

.pcost__more-title {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: 600;
}

.pcost__others {
  margin: var(--space-sm) 0 0;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

.pcost__other {
  margin: 0.125rem 0 0;
}

.pcost__grades-legend {
  margin-bottom: var(--space-xs);
  padding: 0;
  font-size: var(--text-sm);
  font-weight: 600;
}

/* WP-4.3: where no shop prices the job's own material, its price is the money: a question the width of the card, its box
   44 px tall at the numbers' size, the typical range as its hint, and the one figure above it once a price is typed. */
.pcost__lead {
  margin: 0 0 var(--space-smd);
}

.pcost__lead .pnumber__label {
  margin: 0;
}

.pcost__lead .pcost__what {
  margin: var(--space-xs) 0 0;
}

.pask--lead {
  margin-top: var(--space-xs);
  font-size: var(--text-base);
}

.pask--lead .pask__input {
  width: 6rem;
  font-family: var(--font-heading);
  font-size: var(--text-lg);
  font-weight: 700;
}

.pcost__lead .pcost__grades {
  margin-top: var(--space-sm);
}

/* WP-7.2: the main material's own product, bought from the card: picture, name and price, then the paid link and "Change". */
.pcost__buy {
  display: grid;
  gap: var(--space-sm);
  margin: var(--space-smd) 0 0;
}

.pbuy {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs) var(--space-sm);
}

.pbuy__picture {
  flex: none;
  width: 3rem;
  height: 3rem;
  object-fit: contain;
  border-radius: var(--radius);
  background: var(--color-card);
}

.pbuy__words {
  flex: 1 1 12rem;
  min-width: 0;
  font-size: var(--text-sm);
}

.pbuy__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs) var(--space-sm);
}

.pbuy__link {
  min-height: 2.75rem;
}

/* "Pick one at Travis Perkins · 17 products ›": the shops' own products open under it, in place. */
.pcost__pick {
  margin-top: var(--space-xs);
}

.pcost__pick > summary {
  display: inline-flex;
  align-items: center;
  list-style: none;
  cursor: pointer;
}

.pcost__pick > summary::-webkit-details-marker {
  display: none;
}

.pcost__pick[open] > summary {
  margin-bottom: var(--space-xs);
}

.pcost__whose,
.pcost__note {
  margin: var(--space-xs) 0 0;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

.pcost__ad {
  display: inline;
}

/* "Paid links", a link's colour and underline (the "Ad" pill until 0.129.0): what is tapped is 44 px tall round it,
   without making its line of text taller. */
.pcost__ad summary {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  margin: -0.75rem 0;
  padding: 0 var(--space-xs);
  color: var(--color-link);
  text-decoration: underline;
  text-underline-offset: 0.18em;
  vertical-align: middle;
  list-style: none;
  cursor: pointer;
}

.pcost__ad summary:hover {
  color: var(--color-link-hover);
}

.pcost__ad summary::-webkit-details-marker {
  display: none;
}

.pcost__ad[open] {
  display: block;
  margin-top: var(--space-xs);
}

.pcost__grades {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin: var(--space-sm) 0 0;
  padding: 0;
  border: 0;
}

.pcost__shops {
  width: 100%;
  margin-top: var(--space-sm);
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.pcost__shops caption {
  padding-bottom: var(--space-xs);
  color: var(--color-muted-foreground);
  text-align: left;
}

.pcost__shops th,
.pcost__shops td {
  padding: var(--space-xs) var(--space-sm) var(--space-xs) 0;
  border-top: var(--border-thin) solid var(--color-border);
  font-weight: 400;
  text-align: left;
  vertical-align: top;
}

.pcost__shops td:last-child {
  padding-right: 0;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.jobplan__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs) var(--space-md);
  margin-top: var(--space-md);
}

.jobplan__actions .button--accent {
  flex: 1 1 100%;
}

.jobplan__status {
  flex: 1 1 100%;
  min-height: 1.3rem;
  margin: 0;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

.jobplan__copy-text {
  width: 100%;
  min-height: 8rem;
  margin-top: var(--space-sm);
  font: inherit;
  font-size: var(--text-sm);
}

.jobplan__basis {
  margin: var(--space-sm) 0 0;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

.jobplan__basis p {
  margin: 0;
}

.jobplan__basis .jobplan__link {
  display: block;
}

/* ---- the list: a table, not a card for each line --------------------------------------------------------- */

.jobplan__list {
  margin-top: var(--space-lg);
  padding-top: var(--space-md);
  border-top: var(--border-thin) solid var(--color-border);
}

.jobplan__list-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-xs) var(--space-md);
}

.jobplan__list-title {
  font-size: var(--text-xl);
}

.jobplan__prices-of {
  margin: var(--space-xs) 0 0;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

.plist {
  width: 100%;
  margin-top: var(--space-sm);
  border-collapse: collapse;
}

.plist__group-name {
  margin: var(--space-md) 0 0;
  color: var(--color-muted-foreground);
  font-family: var(--font-body);
  font-size: var(--text-label);
  font-weight: 600;
}

.plist__group th {
  padding: var(--space-md) 0 var(--space-xs);
  color: var(--color-muted-foreground);
  font-family: var(--font-body);
  font-size: var(--text-label);
  font-weight: 600;
  text-align: left;
}

.plist__row > * {
  padding: 0;
  border-top: var(--border-thin) solid var(--color-border);
  vertical-align: top;
}

.plist__tick {
  width: 2.75rem;
}

.plist__tick label {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  min-height: 2.75rem;
  cursor: pointer;
}

.plist__tick input {
  width: 1.375rem;
  height: 1.375rem;
  margin: 0;
  accent-color: var(--color-primary);
}

/* The name, the quantity and the price of a line are one button that opens its sheet. */
.plist__open {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-auto-flow: row;
  gap: 0 var(--space-sm);
  width: 100%;
  min-height: 2.75rem;
  padding: var(--space-sm) 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.plist__open:hover .plist__name {
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

.plist__name {
  min-width: 0;
  font-weight: 600;
  overflow-wrap: anywhere;
}

.plist__quantity {
  font-variant-numeric: tabular-nums;
}

.plist__quantity--measure {
  color: var(--color-muted-foreground);
}

/* A typical range is lighter than a shop's price: it is a range of shelf prices, not a price. */
.plist__price[data-price-kind="typical"] {
  font-style: italic;
}

/* Release F (WP-2.4 step 2; DU-08): a price is never the quietest text on its line. */
.plist__price {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: start;
  color: var(--color-price);
  font-size: var(--text-base);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.plist__question {
  grid-column: 1;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

/* The dot of a line that still asks something: a shape and words, not colour alone. */
.plist__dot {
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  margin-right: var(--space-xs);
  border-radius: 50%;
  background: var(--color-warning-text);
  vertical-align: 0.1em;
}

/* The shop's product for a line, or whose figure it rests on: on its own line under the name, wrapped and kept to two lines,
   so a long feed name never pushes the page sideways or paints over the quantity and the price (the review of 16 October
   2026, CP-3 and F8). The full name is in the line's sheet. */
/* Release D (WP-1.10 step 2): the shop's product under a line's name, and what one pack fewer would leave short. */
.plist__product,
.plist__short {
  display: block;
  margin-top: 0.125rem;
  color: var(--color-muted-foreground);
  font-size: 0.875rem;
  font-weight: 400;
  overflow-wrap: anywhere;
}

.plist__mark {
  display: -webkit-box;
  width: fit-content;
  max-width: 100%;
  margin-top: 0.125rem;
  padding: 0 var(--space-xs);
  overflow: hidden;
  border: var(--border-thin) solid var(--color-control-border);
  border-radius: 4px;
  color: var(--color-muted-foreground);
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: normal;
  overflow-wrap: anywhere;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

.plist__row.is-got .plist__name,
.plist__row.is-got .plist__quantity {
  color: var(--color-muted-foreground);
  text-decoration: line-through;
}

.plist__row--off .plist__name,
.plist__row--off .plist__quantity {
  color: var(--color-muted-foreground);
}

.plist__fold > summary {
  padding: var(--space-md) 0 var(--space-xs);
}

.jobplan__before {
  margin-top: var(--space-md);
  padding: var(--space-smd);
  border-radius: var(--radius);
  background: var(--color-muted);
  font-size: var(--text-sm);
}

.jobplan__before h3 {
  font-family: var(--font-body);
  font-size: var(--text-sm);
}

.jobplan__before ul,
.jobplan__warnings ul {
  margin: var(--space-xs) 0 0;
  padding-left: 1.1rem;
}

.jobplan__warnings {
  margin-top: var(--space-md);
  padding: var(--space-smd);
  border: var(--border-thin) solid var(--color-warning-text);
  border-radius: var(--radius);
  background: var(--color-warning-tint);
  color: var(--color-warning-text);
  font-size: var(--text-sm);
}

.jobplan__warnings h3 {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  font-family: var(--font-body);
  font-size: var(--text-sm);
}

/* ---- the folds: make it closer, how it was worked out, having it done --------------------------------------- */

.jobplan__more {
  display: grid;
  gap: var(--space-sm);
}

.pfold {
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-card);
}

.pfold > summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--space-sm);
  min-height: 2.75rem;
  padding: var(--space-sm) var(--space-smd);
  font-weight: 600;
  cursor: pointer;
}

/* "How this was worked out" opens a sheet, so it is a button set as the folds beside it are. */
.jobplan__fold-button {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--space-sm);
  width: 100%;
  min-height: 2.75rem;
  padding: var(--space-sm) var(--space-smd);
  color: inherit;
  font: inherit;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}

.jobplan__fold-button:hover,
.pfold > summary:hover {
  background: var(--color-muted);
}

.pfold__value {
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
  font-weight: 400;
}

.pfold__body {
  padding: 0 var(--space-smd) var(--space-smd);
}

.pfold__body > :first-child {
  margin-top: 0;
}

.pcloser {
  display: grid;
  gap: 0;
}

.pcloser__item {
  border-top: var(--border-thin) solid var(--color-border);
}

.pcloser__item > summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--space-sm);
  min-height: 2.75rem;
  padding: var(--space-xs) 0;
  cursor: pointer;
}

.pcloser__name {
  font-weight: 600;
}

.pcloser__body {
  display: grid;
  gap: var(--space-smd);
  padding: var(--space-xs) 0 var(--space-md);
}

.pcloser__hint {
  margin: 0;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

.popening {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm);
  padding-top: var(--space-sm);
  border-top: var(--border-thin) solid var(--color-border);
}

.popening:first-of-type {
  padding-top: 0;
  border-top: 0;
}

.pproducts__list {
  display: grid;
  gap: var(--space-xs);
  margin: 0;
  padding: 0;
  list-style: none;
}

.pproducts__choice {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0 var(--space-md);
  width: 100%;
  min-height: 2.75rem;
  padding: var(--space-sm);
  border: var(--border-thin) solid var(--color-control-border);
  border-radius: var(--radius);
  background: var(--color-card);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.pproducts__choice[aria-pressed="true"] {
  border-color: var(--color-primary);
  background: var(--color-muted);
}

/* ---- the sheets: a line's own, the working, sending ------------------------------------------------------------ */

.psheet {
  box-sizing: border-box;
  width: min(100%, 38rem);
  max-width: min(100%, 100vw);
  /* Release F (WP-2.6; AM-5): the dynamic viewport where a browser has one, so the last rows are never behind Safari's
     toolbar, and room for a phone's home bar. */
  max-height: 88vh;
  max-height: 88dvh;
  margin: auto auto 0;
  padding: 0 0 env(safe-area-inset-bottom);
  border: var(--border-control) solid var(--color-primary);
  border-bottom: 0;
  border-radius: var(--radius) var(--radius) 0 0;
  background: var(--color-card);
  color: var(--color-foreground);
}

.psheet::backdrop {
  background: var(--color-primary);
  opacity: 0.6;
}

.psheet__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-md) var(--space-md) 0;
}

.psheet__title {
  font-size: var(--text-xl);
}

.psheet__close {
  flex: none;
  min-height: 2.75rem;
}

.psheet__body {
  display: grid;
  gap: var(--space-md);
  padding: var(--space-md);
}

.psheet__body h3 {
  font-family: var(--font-body);
  font-size: var(--text-base);
}

.psheet__body p,
.psheet__body ul {
  margin: var(--space-xs) 0 0;
}

.psheet__quantity {
  margin: var(--space-xs) 0 0;
  font-family: var(--font-heading);
  font-size: var(--text-xl);
  font-weight: 700;
}

.psheet__status {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-top: var(--space-sm);
}

.psheet__status .button[aria-pressed="true"] {
  background: var(--color-primary);
  color: var(--color-on-primary);
}

.psheet__products {
  display: grid;
  gap: var(--space-sm);
  padding: 0;
  list-style: none;
}

.psheet__product {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm) var(--space-md);
}

.psheet__product-words {
  flex: 1 1 12rem;
}

.psheet__product .button {
  min-height: 2.75rem;
}

.pproducts {
  display: grid;
  gap: var(--space-md);
}

.pproducts__line {
  display: grid;
  gap: var(--space-xs);
}

.pworking {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.pworking th,
.pworking td {
  padding: var(--space-xs) var(--space-sm) var(--space-xs) 0;
  border-top: var(--border-thin) solid var(--color-border);
  font-weight: 400;
  text-align: left;
  vertical-align: top;
}

.pworking th {
  width: 34%;
  font-weight: 600;
}

.jobplan__print {
  display: none;
}

/* Beside a number: more than one question (a roll's width and length), a choice that answers one ("No pattern"), and the
   shop's own page to read the figure on. */
.pnumber__asks {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--space-md);
}

.pnumber__extras {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs) var(--space-md);
  margin-top: var(--space-xs);
  font-size: var(--text-sm);
}

/* The words under a set of sizes beside a number (a laminate's typical packs: whose figures they are), on a line of their own
   (the home page's Release 1). */
.pnumber__hint {
  flex-basis: 100%;
}

.jobplan__chip-button {
  min-height: 2.75rem;
  padding: var(--space-xs) var(--space-md);
  border: var(--border-control) solid var(--color-control-border);
  border-radius: var(--radius);
  background: var(--color-card);
  color: var(--color-foreground);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
}

.jobplan__chip-button[aria-pressed="true"] {
  border-color: var(--color-primary);
  background: var(--color-primary);
  color: var(--color-on-primary);
}

.jobplan__chip-button:focus-visible,
.pnumber__page:focus-visible {
  outline: 3px solid var(--color-ring);
  outline-offset: 2px;
}

.pnumber__page {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  min-height: 2.75rem;
}

.pnumber--wide {
  grid-column: 1 / -1;
}

/* A number that is a question still ("Roll size?") is not set as large as a count. */
.pnumber--asking .pnumber__quantity {
  font-size: var(--text-xl);
}

/* Under the list: the second choices (print with the working, copy the full list), and under "Having it done" its two doors. */
.jobplan__list-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--space-lg);
  margin-top: var(--space-md);
  padding-top: var(--space-xs);
  border-top: var(--border-thin) solid var(--color-border);
}

.jobplan__doors {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--space-lg);
  margin: var(--space-sm) 0 0;
  padding: 0;
  list-style: none;
}

.jobplan__doors a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
}

.jobplan__below {
  margin-top: var(--space-xl);
}

/* ---- two columns on a wide screen ---------------------------------------------------------------------------- */

/* ---- the questions asked in the open (template 1.30.0) ---------------------------------------------------------- */

/* Under the cost: the two or three questions that move the answer most, each with its answers as buttons. The answer it
   has now is the pressed one. They come after the numbers and the cost, so neither moves down a phone's first screen. */
.pquestions {
  margin-top: var(--space-smd);
  padding-top: var(--space-smd);
  border-top: var(--border-thin) solid var(--color-border);
}

.pquestions__title {
  margin: 0 0 var(--space-xs);
  color: var(--color-muted-foreground);
  font-family: var(--font-body);
  font-size: var(--text-label);
  font-weight: 700;
}

.pquestions__rows {
  display: grid;
  gap: var(--space-sm);
}

.pquestion {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs) var(--space-smd);
}

.pquestion__ask {
  flex: 1 1 9rem;
  min-width: 0;
  font-weight: 600;
}

.pquestion__answers,
.plist__answers,
.pchoice {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
}

.pquestion__detail {
  flex: 1 1 100%;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

/* A choice of a few with what each comes to: the ways to buy a slab's concrete, the lengths skirting is sold in. Each is
   one button, whole width, its name and what it takes; the one the list is counted in is pressed. */
.pways {
  display: grid;
  gap: var(--space-xs);
}

.pquestions__rows + .pways {
  margin-top: var(--space-sm);
}

.pways__way {
  display: grid;
  gap: 0.125rem;
  width: 100%;
  min-height: 2.75rem;
  padding: var(--space-sm) var(--space-smd);
  border: var(--border-control) solid var(--color-control-border);
  border-radius: var(--radius);
  background: var(--color-card);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.pways__way:hover {
  border-color: var(--color-primary);
}

.pways__way[aria-pressed="true"] {
  border-color: var(--color-primary);
  background: var(--color-muted);
  box-shadow: inset 0.25rem 0 0 var(--color-primary);
}

.pways__way:focus-visible {
  outline: 3px solid var(--color-ring);
  outline-offset: 2px;
}

.pways__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 var(--space-sm);
}

.pways__name {
  font-weight: 700;
}

.pways__usual {
  padding: 0 var(--space-xs);
  border: var(--border-thin) solid var(--color-control-border);
  border-radius: 4px;
  color: var(--color-muted-foreground);
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: nowrap;
}

.pways__words,
.pways__cost {
  font-size: var(--text-sm);
}

.pways__words {
  color: var(--color-muted-foreground);
}

.pways__cost {
  font-variant-numeric: tabular-nums;
}

/* Under a line of the list, or a note of what has to be in place first: the question it still asks, and its answers. */
.plist__ask {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs) var(--space-smd);
  padding-bottom: var(--space-sm);
}

.jobplan__before .plist__ask {
  padding: var(--space-xs) 0 0;
}

.plist__ask .plist__question {
  flex: 1 1 9rem;
  min-width: 0;
}

/* The skirting, wall by wall: the length bought, each wall's pieces, and the other lengths sold. */
.pskirt__lead {
  margin: 0 0 var(--space-sm);
}

.pskirt__cuts th {
  width: 34%;
  white-space: normal;
}

.pskirt__subtitle {
  margin: var(--space-md) 0 var(--space-xs);
  font-family: var(--font-body);
  font-size: var(--text-sm);
}

@media (min-width: 40rem) {
  /* The lengths skirting is sold in sit two to a row where there is the width. */
  .pskirt .pways {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .jobplan__numbers {
    grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  }

  /* Room for three columns: the name, how much, the price. */
  .plist__open {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(4.5rem, auto);
  }

  .plist__name { grid-column: 1; grid-row: 1; }
  .plist__quantity { grid-column: 2; grid-row: 1; }
  .plist__price { grid-column: 3; grid-row: 1; }
  .plist__question { grid-column: 1 / span 2; grid-row: 2; }

  .jobplan__actions .button--accent {
    flex: 0 1 auto;
  }

  .psheet {
    margin: auto;
    border-bottom: var(--border-control) solid var(--color-primary);
    border-radius: var(--radius);
  }
}

@media (min-width: 64rem) {
  /* On a wide screen the list is open beside the fields, so the planner is always taller than the window: the window's
     height is kept for it from the start, and what follows the planner on the page is never seen to move down. */
  .jobplan {
    min-height: max(40rem, 100vh);
  }

  .jobplan__cols {
    grid-template-columns: minmax(0, 24rem) minmax(0, 1fr);
    grid-template-areas:
      "jobs jobs"
      "inputs answer"
      "extra answer"
      "more answer";
    grid-template-rows: auto auto auto 1fr;
    align-items: start;
    gap: var(--space-lg) var(--space-xl);
  }

  .jobplan__cols > .jobplan__jobs { grid-area: jobs; }
  .jobplan__inputs { grid-area: inputs; }
  .jobplan__answer { grid-area: answer; padding: var(--space-lg); }
  .jobplan__extra { grid-area: extra; }
  .jobplan__more { grid-area: more; }
  .jobplan__live { display: none; }

  /* The home page (Release 2): no chips over the columns; the room's controls stay in view in the left column, the folds and
     "Other jobs" under them, the card on the right. The list opens closed, so the left column never stands empty beside it. */
  .jobplan[data-layout="home"] {
    min-height: 40rem;
  }

  .jobplan[data-layout="home"] .jobplan__cols {
    grid-template-areas:
      "inputs answer"
      "more answer";
    grid-template-rows: auto 1fr;
  }

  .jobplan[data-layout="home"] .jobplan__cols {
    gap: var(--space-lg) var(--space-xl);
  }

  .jobplan[data-layout="home"] .jobplan__assume,
  .jobplan[data-layout="home"] .jobplan__room-foot {
    display: none;
  }

  /* From 1024 px a number's need, its bar and what is left over share one line under the quantity, as there is the width (the
     specification's laptop sketch). The quantity keeps a line of its own, so its words never run on from it ("2 × 5 L5.7 L
     needed", the review of Release 2) and the two columns break their second line alike. */
  .jobplan__numbers .pnumber__quantity {
    display: block;
    width: fit-content;
  }

  .jobplan__numbers .pnumber__detail,
  .jobplan__numbers .pnumber__bar,
  .jobplan__numbers .pnumber__spare {
    display: inline-block;
    margin-right: var(--space-sm);
    vertical-align: middle;
  }

  .jobplan__numbers .pnumber__bar svg {
    width: 5.5rem;
    margin-top: 0;
  }
}

/* ---- on paper ----------------------------------------------------------------------------------------------------------
   The answer strip and the room at the top; the list as a table (a box to tick, the name, how much, the price) with whose
   the prices are said once in its own header, where the "Ad" label is; the shops a line can be searched for at, named once;
   and one short block of what the list assumed. A list of fifteen lines is one sheet of A4, or two with a layout drawn.
   With the class `print-with-working` on the body (the screen's "Print with the working"), the working of every counted
   line follows, as it does for the site's other lists. No control is printed, and no "Ad" note outside the list's header. */

@media print {
  .jobplan {
    min-height: 0;
    font-size: 10pt;
  }

  .jobplan__cols {
    display: block;
  }

  /* Of the fields' column, only the room's drawing; of the rest, only the answer and the list. */
  .jobplan__inputs > :not(.jobplan__drawing),
  .jobplan__more,
  .jobplan__actions,
  .jobplan__list-foot,
  .psteps,
  .jobplan__example,
  .jobplan__basis .jobplan__link,
  .jobplan__list-head [data-ticked],
  .pask,
  .pnumber__asks,
  .pnumber__extras,
  .pcost__asks,
  .pcost__grades,
  .pcost__pick,
  .pcost__buy,
  .pcost__ad,
  .pcost__ad-dot,
  .plist__dot,
  .pquestions,
  .jobplan__drawing figcaption .jobplan__link,
  .plist__answers,
  .pskirt .pways,
  .pskirt__subtitle,
  .psheet,
  .pcost__whose-ad,
  .pcost__labour-open,
  .jobplan__several {
    display: none !important;
  }

  /* The home page's room panel (Release 2): closed or open on the screen, on paper it gives the room's drawing and no control. */
  .jobplan__inputs > .jobplan__room,
  .jobplan__inputs > .jobplan__room.is-closed {
    display: block !important;
  }

  .jobplan__room > :not(.jobplan__drawing) {
    display: none !important;
  }

  /* On paper the skirting's cut list is kept, at the width of the page: it is what is taken to the saw. */
  .jobplan__layout.pskirt {
    max-width: none;
  }

  .plist__ask {
    padding: 0;
  }

  .jobplan__drawing {
    float: right;
    width: 52mm;
    margin: 0 0 2mm 4mm;
  }

  .jobplan__drawing figcaption {
    font-size: 8pt;
  }

  .jobplan__answer {
    padding: 0;
    border: 0;
  }

  .jobplan__sentence {
    position: static;
    width: auto;
    height: auto;
    margin: 0 0 1mm;
    overflow: visible;
    clip-path: none;
    white-space: normal;
    font-size: 12pt;
  }

  .jobplan__numbers {
    gap: 0.5mm 6mm;
    margin: 0;
  }

  .pnumber {
    margin: 0;
    padding: 0;
  }

  .pnumber__quantity {
    font-size: 15pt;
  }

  .pnumber__detail,
  .pnumber__spare,
  .pcost__what {
    font-size: 8.5pt;
    line-height: 1.3;
  }

  .pnumber__bar {
    display: none;
  }

  .jobplan__cost {
    margin-top: 1mm;
    padding-top: 1mm;
  }

  .pcost__figure,
  .pcost__head .pcost__figure {
    font-size: 14pt;
  }

  .pcost__figure--inline {
    font-size: inherit;
  }

  .pcost__note,
  .pcost__whose,
  .jobplan__basis {
    margin: 0.5mm 0 0;
    font-size: 8.5pt;
    color: #000;
  }

  .jobplan__layout {
    max-width: 90mm;
    margin: 2mm 0 0;
    break-inside: avoid;
  }

  .jobplan__list,
  .jobplan__list[hidden] {
    display: block !important;
    clear: both;
    margin-top: 2mm;
    padding-top: 0.5mm;
    border-top: 1.5pt solid #000;
  }

  .jobplan__list-title {
    margin: 0;
    font-size: 12pt;
  }

  .jobplan__prices-of {
    margin: 0;
    font-size: 8.5pt;
    color: #000;
  }

  .jobplan__warnings,
  .jobplan__before {
    margin: 0.7mm 0;
    padding: 0.5mm 2mm;
    border: 0.5pt solid #000;
    background: none;
    font-size: 8.5pt;
    break-inside: avoid;
  }

  .jobplan__warnings h3,
  .jobplan__before h3 {
    margin: 0;
    font-size: 9pt;
  }

  .jobplan__warnings ul,
  .jobplan__before ul {
    margin: 0;
  }

  /* The table: a row a line, a rule under it, the columns the screen's wide layout has. */
  .plist__group-name,
  .plist__fold > summary {
    display: block;
    min-height: 0;
    margin: 2mm 0 0;
    padding: 0 0 0.4mm;
    border-bottom: 1pt solid #000;
    color: #000;
    font-size: 8.5pt;
    list-style: none;
    break-after: avoid;
  }

  .plist__fold > summary::before,
  .plist__fold > summary::-webkit-details-marker {
    display: none;
  }

  .plist__row {
    break-inside: avoid;
  }

  .plist__row > * {
    padding: 0;
    border-bottom: 0.5pt solid #777;
  }

  .plist__tick {
    width: 7mm;
  }

  .plist__tick label {
    min-width: 0;
    min-height: 0;
    padding: 0.4mm 0;
  }

  .plist__tick input {
    width: 4mm;
    height: 4mm;
    margin: 0;
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
  }

  .plist__open {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(18mm, auto);
    min-height: 0;
    padding: 0.4mm 0;
    color: #000;
    font-size: 10pt;
    line-height: 1.25;
    cursor: default;
  }

  .plist__name { grid-column: 1; grid-row: 1; }
  .plist__quantity { grid-column: 2; grid-row: 1; text-align: left; }
  .plist__price { grid-column: 3; grid-row: 1; }

  .plist__question {
    grid-column: 1 / span 3;
    grid-row: 2;
    margin: 0;
    font-size: 8.5pt;
    color: #000;
  }

  .plist__row.is-got .plist__name,
  .plist__row.is-got .plist__quantity {
    text-decoration: none;
    opacity: 1;
  }

  /* What the list assumed, the shops named once, the versions: one short block. With the working, the working says them. */
  .jobplan__print {
    display: block;
    margin-top: 2mm;
  }

  .jobplan__print-short {
    padding-top: 1mm;
    border-top: 0.5pt solid #777;
    font-size: 8pt;
    line-height: 1.3;
  }

  .jobplan__print-short p {
    margin: 0 0 0.5mm;
  }

  .jobplan__print-working {
    display: none;
  }

  .print-with-working .jobplan__print-working {
    display: block;
    margin-top: 3mm;
    font-size: 9pt;
  }

  /* The working says what the list assumed and names the versions itself. */
  .print-with-working .jobplan__print-short > [data-printed="assumed"],
  .print-with-working .jobplan__print-short > [data-printed="versions"] {
    display: none;
  }

  .jobplan__print-working .pworking,
  .jobplan__print-working p,
  .jobplan__print-working li {
    margin-top: 0;
    margin-bottom: 0.5mm;
    font-size: 8.5pt;
    line-height: 1.3;
  }

  .jobplan__print-working ul {
    margin: 0;
  }

  .jobplan__print-working .pworking th,
  .jobplan__print-working .pworking td {
    padding: 0.6mm 2mm 0.6mm 0;
  }

  .jobplan__print-working h2 {
    margin: 0;
    font-size: 12pt;
  }

  .jobplan__print-working h3 {
    margin: 2mm 0 0;
    font-size: 10pt;
  }

  /* The page round the screen: the heading smaller, and what the page has under the calculator left off the sheet. */
  main:has(.jobplan) h1 {
    margin: 0 0 1mm;
    font-size: 15pt;
  }

  main:has(.jobplan) > :not(h1, .jobplan),
  .jobplan__below {
    display: none !important;
  }

  /* The foot's statement stays on the sheet, in the list's small print (as under the site's other printed lists). */
  main:has(.jobplan) ~ .site-footer {
    margin-top: 1.5mm;
    padding: 1mm 0 0;
    font-size: 8pt;
  }

  main:has(.jobplan) ~ .site-footer .site-footer__status {
    margin: 0;
    padding-left: 2mm;
    font-size: 8pt;
    line-height: 1.35;
  }
}

/* Release K (WP-4.1, WP-4.2): where the work is, over the labour figures; and a quote or a budget beside the plan. */
.jobplan__region,
.pmoney__chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs) var(--space-sm);
  margin-top: var(--space-sm);
  font-size: var(--text-sm);
}

.pmoney .pmoney__input {
  width: 6rem;
}

.pmoney [data-quote-line],
.pmoney [data-budget-line] {
  color: var(--color-foreground);
  font-size: var(--text-base);
}

/* Release G (WP-3.2 step 1, WP-3.1 stage 1): a chimney breast, a bay or an alcove, one row each under the sizes; and the
   wall paint's colour, finish and name. */
.jobplan__feature {
  display: grid;
  gap: var(--space-xs);
  margin-top: var(--space-sm);
  padding: var(--space-sm);
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius);
}

.jobplan__row--feature {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-xs);
  margin: 0;
}

.jobplan__feature .jobplan__link {
  justify-self: start;
}

.jobplan__paint {
  display: grid;
  gap: var(--space-xs);
  margin-top: var(--space-sm);
}

/* Release C (WP-1.5 step 2): on /list/ the example room is not shown while the link is read; the line that says so keeps a
   screen's height until the script draws the list over it. */
.jobplan[data-mode="list"] [data-static-planner] {
  display: none;
}
.jobplan[data-mode="list"]:has(> [data-list-opening]) {
  min-height: 100svh;
}

/* Release C (WP-1.5 step 2): on /list/ the screen is read-only and list first. What changes the figures (the questions, a
   price typed, a grade, a quote or a budget) is on /start/, which "Change the figures" opens. */
.jobplan[data-mode="list"] [data-questions],
.jobplan[data-mode="list"] [data-price-asks],
.jobplan[data-mode="list"] [data-money],
.jobplan[data-mode="list"] .pcost__grades,
.jobplan[data-mode="list"] .plist__answers,
.jobplan[data-mode="list"] [data-change-product] {
  display: none;
}
/* With no fields above it, the room's sentence is shown on a phone too: it is the first thing the list says. */
.jobplan[data-mode="list"] .jobplan__sentence {
  position: static;
  width: auto;
  height: auto;
  margin: 0 0 var(--space-sm);
  overflow: visible;
  clip-path: none;
  white-space: normal;
}

/* Release I (WP-3.4): a row of sizes, one tap each, under the job's figures: a laminate pack, an underlay roll, a slab, a board,
   a slab's thickness and a shed's base. Its name above the buttons; where the sizes are typical figures, the words that say so
   and where they were found, small, under them. */
.jobplan__size-row {
  display: grid;
  gap: var(--space-xs);
  margin-top: var(--space-sm);
}

/* Release I (WP-3.2 step 3; the review's F1, VA-05): the drawing board inside "Not a rectangle" sits in the fields' column, under
   400 px wide even on a wide screen, where the board's own two columns (app.css, for the room planner's whole page) left the
   drawing about 130 px wide with its summary over it. In the planner it is one column: the drawing at the column's width,
   the walls under it. */
.jobplan [data-draw-room] .planner__layout {
  grid-template-columns: minmax(0, 1fr);
}

/* Release F (WP-2.4 step 1; DU-13): every way to take the list away in one "Share" menu beside the lime button, opened in the
   page's flow (nothing floats over the card), each item a 44 px row. */
.pshare {
  flex: 0 0 auto;
}

.pshare[open] {
  flex: 1 1 100%;
}

.pshare__summary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  min-height: 2.75rem;
  list-style: none;
  cursor: pointer;
}

.pshare__summary::-webkit-details-marker {
  display: none;
}

.pshare__items {
  display: grid;
  margin-top: var(--space-xs);
  border-top: var(--border-thin) solid var(--color-border);
}

.pshare__items .jobplan__link {
  border-bottom: var(--border-thin) solid var(--color-border);
}

/* The paint's two questions as toggle chips, and the one line under the cost that says who has checked the figures. */
.pquestions__toggles {
  margin-bottom: var(--space-xs);
}

.jobplan__honesty {
  margin-top: var(--space-sm);
}

/* Release F (WP-2.4 step 1; DU-15): the typical rooms in one chip that opens in place, each room a 44 px row. */
.pchip-menu__summary {
  display: inline-flex;
  align-items: center;
  list-style: none;
  cursor: pointer;
}

.pchip-menu__summary::-webkit-details-marker {
  display: none;
}

.pchip-menu__summary::after {
  content: " ▾";
  white-space: pre;
}

.pchip-menu[open] .pchip-menu__summary::after {
  content: " ▴";
}

.pchip-menu__items {
  display: grid;
  margin-top: var(--space-xs);
}

/* Release F (WP-2.4 step 2): the list's total at its head and foot, and a subtotal under each group, at reading size. */
.plist__total {
  margin: var(--space-sm) 0 0;
  color: var(--color-price);
  font-size: var(--text-base);
  font-weight: 600;
}

.plist__subtotal {
  margin: var(--space-xs) 0 0;
  color: var(--color-price);
  font-size: var(--text-sm);
  font-weight: 600;
  text-align: right;
}

/* Release F (WP-2.6; AM-5): the page behind an open sheet does not scroll with it. Overflow only: a fixed position would lose
   the place on the page. */
body:has(dialog[open]) {
  overflow: hidden;
}

/* The line's own words, first under the product: what it is for. */
.psheet__for {
  margin: var(--space-sm) 0 0;
}

/* Release N (WP-5.1): what to do, in order, under the list: the steps numbered, a maker's wait under its step, the
   mistakes folded. */
.psteps {
  margin-top: var(--space-md);
  font-size: var(--text-base);
}

.psteps__time {
  margin: var(--space-xs) 0 0;
  font-size: var(--text-sm);
}

.psteps__list {
  display: grid;
  gap: var(--space-xs);
  margin: var(--space-smd) 0 0;
  padding-left: 1.4rem;
}

.psteps__wait {
  display: block;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

/* ---- the home page's Release 2 (19 October 2026): the job line, the example in the boxes, what is assumed, the room's panel,
   the card's tags and its new lines. Tokens only; nothing sticky; every control 44 px or more. --------------------------- */

/* On the home page the card follows the sizes and what is assumed closely (16 px, where 24 px parted the columns' parts). */
.jobplan[data-layout="home"] .jobplan__cols {
  gap: var(--space-md);
}

/* "Job: Paint" and "Other jobs ↓", one 44 px row. */
.jobplan__jobline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0 var(--space-md);
  min-height: 2.75rem;
  margin-bottom: var(--space-xs);
}

.jobplan__jobline-name {
  font-size: var(--text-sm);
  font-weight: 600;
}

.jobplan__jobline-link {
  display: inline-flex;
  align-items: center;
  gap: 0.25em;
  min-height: 2.75rem;
  color: var(--color-link);
  font-size: var(--text-sm);
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

.jobplan__jobline-link:hover {
  color: var(--color-link-hover);
}

/* A size box still holding the example room's figure: slate (6.57:1 on paper); a figure typed is graphite. */
.pfield__input--example {
  color: var(--color-muted-foreground);
}

/* The height note under the sizes, once the other sizes are the visitor's. */
.jobplan__height-note {
  margin: var(--space-xs) 0 0;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

/* What the answer assumes, with "Change ›" opening the room's panel; on the home page below 1024 px only. */
.jobplan__assume {
  margin: var(--space-xs) 0 0;
  font-size: var(--text-sm);
}

/* "Change ›" keeps to the line of words it ends: a 44 px target that does not make the line taller (as "Paid links"). */
.jobplan__assume-change {
  display: inline-block;
  min-height: 0;
  margin: -0.75rem 0;
  padding: 0.75rem var(--space-xs);
  line-height: 1.5;
}

/* From 340 to 413 px "Change ›" has a line of its own, in both layers, whichever face the line is painted in (the planner's
   largest paint, 0.147.0, and its review). Where it went onto a second line depended on the face: measured on
   19 October 2026, the example's line took two lines up to 396 px in Work Sans, up to 412 px in its stand-in (site.css, Arial
   sized to Work Sans; Chromium and WebKit alike) and up to 378 px in system-ui, and one line from 414 px in all three. So
   between about 380 and 413 px the card below it moved 21 px when Work Sans arrived after the first paint (a layout shift
   of 0.20 at 402 and 412 px), or "Change ›" jumped between the lines. The words alone fit on one line from 336 px in every
   face; below 340 px every face takes two lines, with "Change ›" on the second, as before. In rem, as the text is. */
@media (min-width: 21.25rem) and (max-width: 25.85rem) {
  .jobplan__assume {
    display: flow-root;
  }

  .jobplan__assume-change {
    display: block;
    width: fit-content;
  }
}

/* The room's panel: what is counted in the room, the drawing and "Done", in the page's flow (nothing floats). Closed on a phone
   until "Change ›"; from 1024 px always open, in the left column. */
.jobplan__room {
  display: grid;
  gap: var(--space-md);
  margin-top: var(--space-sm);
  padding-top: var(--space-md);
  border-top: var(--border-thin) solid var(--color-border);
}

@media (max-width: 63.99rem) {
  .jobplan__room.is-closed {
    display: none;
  }
}

@media (min-width: 64rem) {
  .jobplan__room {
    border-top: 0;
    padding-top: 0;
  }
}

.jobplan__room > .jobplan__fields--counts,
.jobplan__room > .jobplan__features {
  display: grid;
  gap: var(--space-smd);
}

.jobplan__draw-links {
  margin: 0;
  font-size: var(--text-sm);
}

/* Each link's target is 44 px tall (its padding) without making the line taller, and the words still wrap as one sentence. */
.jobplan__draw-links a {
  padding: 0.875rem 0;
}

/* The panel's last row on a phone: the answer in one line, so it is in sight at both ends of an open panel, and "Done". */
.jobplan__room-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm) var(--space-md);
  padding-top: var(--space-sm);
  border-top: var(--border-thin) solid var(--color-border);
}

.jobplan__room-live {
  flex: 1 1 12rem;
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--text-base);
  font-weight: 700;
}

.jobplan__room-foot .button {
  min-height: var(--control-height);
}

/* The card's tags: the example's in stone, "Your room" graphite on paper with the card's lime edge, which carries no meaning on
   its own (the words do). The edge is a stripe inside the card's left edge, so nothing moves. */
.jobplan__example--yours {
  border: var(--border-thin) solid var(--color-control-border);
  background: var(--color-card);
}

.jobplan__answer {
  position: relative;
}

.jobplan__answer.is-yours::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 4px;
  border-radius: var(--radius) 0 0 var(--radius);
  background: var(--color-accent);
}

/* On the home page below 1024 px the card's sentence is for a screen reader, print and the Markdown copy while an example's tag
   shows: the boxes and the assumptions line already say the room. It is shown from 1024 px, and once the room is the
   visitor's. */
@media (max-width: 63.99rem) {
  .jobplan[data-layout="home"] .jobplan__answer.is-example .jobplan__sentence {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}

/* What one pack fewer would leave short, in graphite; and the paint's working, slate, tabular, under the numbers. */
.pnumber__shorts {
  margin: var(--space-sm) 0 0;
}

.pnumber__short {
  margin: 0.125rem 0 0;
  color: var(--color-foreground);
  font-size: var(--text-sm);
}

.jobplan__sum {
  margin: var(--space-sm) 0 0;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}

.jobplan__answer > .jobplan__honesty {
  color: var(--color-foreground);
}

/* "Doing more than one room?", after the lime button. */
.jobplan__several {
  margin-top: var(--space-sm);
}

/* "Other jobs" after the card on the home page: its heading, the hint once the sizes are the visitor's, and the chips. */
.jobplan__other {
  margin-top: var(--space-sm);
}

.jobplan__other-title {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: 600;
}

.jobplan__other-hint {
  margin: var(--space-xs) 0 0;
  color: var(--color-muted-foreground);
  font-size: var(--text-sm);
}

/* Before the script: the home page's static job line and assumptions are greyed with the boxes, and the money's slot keeps
   its place, so nothing in the first screen moves when the prices arrive. */
[data-static-planner] .jobplan__jobline,
[data-static-planner] .jobplan__assume {
  opacity: 0.6;
}

.jobplan__cost--waiting {
  min-height: 9.5rem;
}

@media (min-width: 64rem) {
  .jobplan__cost--waiting {
    min-height: 12rem;
  }
}

/* With scripts refused nothing will work the prices out or the screen: neither waiting line stands, nor the money's empty slot
   (the review of Release 2); the page's noscript line says the calculator needs JavaScript. */
@media (scripting: none) {
  .jobplan__cost--waiting,
  [data-static-planner] .jobplan__working {
    display: none;
  }
}
