/* ===========================================================================
   GLEAM & GLOW — THE QUOTE SHEET AND ITS BUILDER
   ---------------------------------------------------------------------------
   Two things live in here and they have opposite jobs.

   .qb__*   the builder: an app, on her phone, at eight o'clock at night, in a
            customer's driveway. Big targets, no ceremony, one thumb.

   .sheet   the document: A4, on somebody else's screen or somebody else's
            printer, deciding whether she looks like a business. Every
            dimension in it is in millimetres, so what she sees is the size it
            prints, and the PDF is not a screenshot of a website.

   The sheet is measured in mm ON SCREEN TOO, and scaled to fit by a CSS
   custom property the script sets. Laying it out in px and "roughly" fixing
   it up at print time is how a quote ends up with the terms alone on page 2.
   ========================================================================= */

@import url('tokens.css');

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body.qb {
  margin: 0;
  background: var(--cream-warm);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 300;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* =========================================================================
   THE BAR
   ========================================================================= */

.qb__bar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: .7rem clamp(.9rem, 3vw, 1.6rem);
  padding-top: calc(.7rem + env(safe-area-inset-top));
  background: rgba(249, 245, 244, .92);
  backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid var(--cream-deep);
}
.qb__home {
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  flex: none;
  border-radius: 999px;
  color: var(--rose);
  text-decoration: none;
  transition: background-color .25s var(--ease-soft);
}
.qb__home:hover { background: var(--blush-pale); }
.qb__home svg { width: 20px; height: 20px; }

.qb__title {
  display: flex;
  align-items: center;
  gap: .6rem;
  font-family: var(--display);
  font-size: 1.3rem;
  margin-right: auto;
}
.qb__title img { width: 20px; height: auto; }

.qb__saved-btn {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-height: 40px;
  padding: 0 1rem;
  border: 1px solid var(--blush);
  border-radius: 999px;
  color: var(--rose);
  font-size: .78rem;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.qb__count {
  display: inline-grid;
  place-items: center;
  min-width: 1.4em;
  height: 1.4em;
  padding: 0 .35em;
  border-radius: 999px;
  background: var(--rose);
  color: var(--white);
  font-size: .72rem;
  letter-spacing: 0;
}

/* =========================================================================
   LAYOUT
   ========================================================================= */

.qb__layout {
  display: grid;
  /* An EXPLICIT minmax(0, 1fr), not the default single `auto` track.
     *
     THE BUG: the sheet inside is laid out at its real size — 210mm, about
     794px — and only scaled down by a transform, which does not change
     layout. An `auto` track sizes to max-content, so on a phone the single
     column measured 794px, the document became two and a half screens wide,
     and the whole builder could be swiped sideways off the edge. A zero
     minimum lets the track be the width of the screen and the scaled sheet is
     clipped to it. Same trap as the hero grid in styles.css. */
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.25rem, 3vw, 2.5rem);
  padding: clamp(1rem, 3vw, 2.5rem);
  max-width: 1600px;
  margin-inline: auto;
  align-items: start;
}
@media (min-width: 1100px) {
  .qb__layout { grid-template-columns: minmax(0, 420px) minmax(0, 1fr); }
  /* The sheet follows her down the form, because the whole point of a live
     preview is watching the document change as you type. */
  .qb__preview { position: sticky; top: 5rem; }
}

/* =========================================================================
   THE FORM
   ========================================================================= */

.qb__hint {
  margin: 0 0 1.25rem;
  padding: .9rem 1.1rem;
  background: var(--blush-pale);
  border-radius: var(--radius-lg);
  color: var(--rose-deep);
  font-size: .9rem;
  line-height: 1.55;
}
.qb__hint--foot { background: none; padding: 0; color: var(--ink-faint); font-size: .82rem; }

.qb__group {
  background: var(--white);
  border: 1px solid var(--cream-deep);
  border-radius: var(--radius-lg);
  padding: clamp(1rem, 2.5vw, 1.5rem);
  margin-bottom: 1rem;
}
.qb__group--price { border-color: var(--blush); box-shadow: var(--shadow-sm); }

.qb__h {
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 300;
  margin: 0 0 1rem;
  color: var(--rose-deep);
}

.qb__note {
  margin: -.5rem 0 1rem;
  font-size: .84rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

.qb__row { display: grid; gap: .9rem; }
@media (min-width: 460px) {
  .qb__row { grid-template-columns: 1fr 1fr; }
  .qb__row--3 { grid-template-columns: 1fr 1fr 1fr; }
}

.qb__field { display: block; margin-bottom: .9rem; }
.qb__field:last-child { margin-bottom: 0; }
.qb__field > span {
  display: block;
  margin-bottom: .35rem;
  font-size: .74rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.qb__field > span em {
  font-style: normal;
  letter-spacing: .06em;
  text-transform: none;
  color: var(--ink-faint);
}

.qb__field input,
.qb__field select,
.qb__field textarea {
  width: 100%;
  /* 16px minimum. Anything smaller and iOS zooms the page in the moment the
     field is focused, which on this layout throws the preview off screen. */
  font-size: 16px;
  font-family: inherit;
  font-weight: 300;
  padding: .7rem .85rem;
  min-height: 46px;
  color: var(--ink);
  background: var(--cream);
  border: 1px solid var(--cream-deep);
  border-radius: var(--radius);
  transition: border-color .2s var(--ease-soft), background-color .2s var(--ease-soft);
}
.qb__field textarea { min-height: 70px; resize: vertical; line-height: 1.5; }
.qb__field input:focus, .qb__field select:focus, .qb__field textarea:focus {
  outline: none;
  border-color: var(--rose);
  background: var(--white);
}
.qb__field select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%238a4d5e' stroke-width='1.4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .85rem center;
  background-size: 11px;
  padding-right: 2.2rem;
}

/* ---- the money field --------------------------------------------------- */
.qb__money {
  display: flex;
  align-items: center;
  gap: .5rem;
  background: var(--cream);
  border: 1px solid var(--blush);
  border-radius: var(--radius);
  padding-inline: .85rem;
}
.qb__money i {
  font-style: normal;
  font-family: var(--display);
  font-size: 1.9rem;
  color: var(--rose);
  line-height: 1;
}
.qb__money input {
  border: 0;
  background: none;
  padding-inline: 0;
  font-family: var(--display);
  font-size: 2rem;
  min-height: 58px;
  /* Spinners on a price field are a way to be off by one without noticing. */
  appearance: textfield;
}
.qb__money input::-webkit-outer-spin-button,
.qb__money input::-webkit-inner-spin-button { appearance: none; margin: 0; }
.qb__money input:focus { background: none; }
.qb__money em {
  font-style: normal;
  font-size: .74rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}

/* ---- checkboxes -------------------------------------------------------- */
.qb__check {
  display: flex;
  align-items: flex-start;
  gap: .65rem;
  padding: .45rem 0;
  min-height: 40px;
  font-size: .92rem;
  line-height: 1.45;
  cursor: pointer;
}
.qb__check--wide { margin-top: .5rem; color: var(--ink-soft); font-size: .88rem; }
.qb__check input {
  appearance: none;
  flex: none;
  width: 21px; height: 21px;
  margin-top: .15rem;
  border: 1px solid var(--blush);
  border-radius: 4px;
  background: var(--white);
  transition: background-color .18s var(--ease-soft), border-color .18s var(--ease-soft);
}
.qb__check input:checked {
  background: var(--rose) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.5l3.2 3.2L13 5' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/13px no-repeat;
  border-color: var(--rose);
}
.qb__check input:focus-visible { outline: 2px solid var(--rose); outline-offset: 2px; }

/* ---- the included list ------------------------------------------------- */
.qb__room { border-top: 1px solid var(--cream-deep); padding-top: .6rem; margin-top: .6rem; }
.qb__room:first-child { border-top: 0; margin-top: 0; padding-top: 0; }
.qb__room-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.qb__room-head h3 {
  margin: 0;
  font-family: var(--sans);
  font-size: .74rem;
  font-weight: 400;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--rose);
}
.qb__mini {
  font-size: .72rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--rose);
  border: 1px solid var(--blush);
  border-radius: 999px;
  padding: .35rem .75rem;
  min-height: 32px;
  transition: background-color .2s var(--ease-soft);
}
.qb__mini:hover { background: var(--blush-pale); }
.qb__room-items { display: grid; gap: 0; }
@media (min-width: 560px) { .qb__room-items { grid-template-columns: 1fr 1fr; } }

.qb__chips { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .6rem; }
.qb__chip {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .35rem .5rem .35rem .8rem;
  background: var(--blush-pale);
  border-radius: 999px;
  font-size: .84rem;
  color: var(--rose-deep);
}
.qb__chip button { color: var(--rose); font-size: 1.1rem; line-height: 1; padding: 0 .25rem; }

/* ---- extras rows ------------------------------------------------------- */
.qb__sub { margin-top: 1.25rem; border-top: 1px solid var(--cream-deep); padding-top: 1rem; }
.qb__sub-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: .5rem; }
.qb__sub-head h3 {
  margin: 0;
  font-family: var(--sans);
  font-size: .74rem;
  font-weight: 400;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--rose);
}
.qb__extra { display: grid; grid-template-columns: 1fr 7rem 40px; gap: .5rem; margin-bottom: .5rem; }
.qb__extra input {
  width: 100%;
  font-size: 16px;
  font-family: inherit;
  font-weight: 300;
  padding: .6rem .7rem;
  min-height: 44px;
  background: var(--cream);
  border: 1px solid var(--cream-deep);
  border-radius: var(--radius);
}
.qb__extra input:focus { outline: none; border-color: var(--rose); }
.qb__extra button {
  color: var(--ink-faint);
  font-size: 1.3rem;
  border-radius: var(--radius);
  transition: color .2s var(--ease-soft);
}
.qb__extra button:hover { color: var(--rose); }

/* =========================================================================
   THE PREVIEW SHELL
   ========================================================================= */

.qb__preview-inner {
  /* Height is set by the script to the scaled sheet's height, because a
     transform does not affect layout and the actions would otherwise sit on
     top of the document. */
  height: var(--sheet-box, auto);
  overflow: hidden;
}
.qb__actions {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
  margin-top: 1.25rem;
}
.qb__btn {
  flex: 1 1 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .55rem;
  min-height: 52px;
  padding: 0 1.4rem;
  border-radius: 999px;
  background: var(--rose);
  color: var(--white);
  border: 1px solid var(--rose);
  font-size: .78rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  transition: transform .35s var(--ease), box-shadow .35s var(--ease),
              background-color .25s var(--ease-soft);
}
.qb__btn:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
.qb__btn svg { width: 1.15em; height: 1.15em; }
.qb__btn--wa { background: var(--whatsapp); border-color: var(--whatsapp); }
.qb__btn--wa:hover { background: #1eb85a; }
.qb__btn--ghost { background: none; color: var(--rose); border-color: var(--blush); }
.qb__btn--ghost:hover { background: var(--white); }

/* =========================================================================
   THE SHEET — everything below is in millimetres
   ========================================================================= */

.sheet {
  width: 210mm;
  min-height: 297mm;
  padding: 16mm 16mm 14mm;
  background: var(--white);
  color: var(--ink);
  /* One font-size, in mm, and every rule under here is a multiple of it. Set
     the sheet's size and the whole document scales in proportion. */
  font-size: 3.5mm;
  line-height: 1.5;
  box-shadow: var(--shadow-lg);
  transform: scale(var(--sheet-scale, 1));
  transform-origin: top left;
  position: relative;
  overflow: hidden;
  /* A column, so the contact footer sinks to the bottom of the page rather
     than floating halfway up a short quote. */
  display: flex;
  flex-direction: column;
}

/* A band of her rose across the very top. It is 4mm, not the full-bleed
   header block this started as: she prints these at home, and a header that
   lays down an A4 width of solid colour costs her a cartridge a fortnight. */
.sheet__rule {
  position: absolute;
  inset: 0 0 auto;
  height: 4mm;
  background: linear-gradient(100deg, var(--rose-deep), var(--rose) 42%,
              var(--blush) 62%, var(--rose-deep));
}

.sheet__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10mm;
  padding-bottom: 7mm;
  border-bottom: .3mm solid var(--cream-deep);
}
.sheet__logo { width: 34mm; height: auto; }

.sheet__stamp { text-align: right; }
.sheet__kind {
  margin: 0 0 3mm;
  font-family: var(--display);
  font-size: 2.6em;
  line-height: 1;
  font-weight: 300;
  color: var(--rose);
  letter-spacing: .01em;
}
.sheet__meta { display: grid; gap: 1.5mm; margin: 0; }
.sheet__meta > div { display: flex; justify-content: flex-end; gap: 4mm; }
.sheet__meta dt {
  font-size: .74em;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.sheet__meta dd { margin: 0; font-size: .92em; }

.sheet__label {
  margin: 0 0 1.5mm;
  font-size: .7em;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--rose);
}

.sheet__parties {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8mm;
  padding: 7mm 0;
}
.sheet__strong { margin: 0; font-size: 1.15em; }
.sheet__soft { margin: .5mm 0 0; color: var(--ink-soft); white-space: pre-line; }
.sheet__soft:empty { display: none; }

/* ---- the price panel --------------------------------------------------- */
.sheet__price {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 6mm;
  padding: 7mm 8mm;
  background: var(--blush-pale);
  border-radius: 3mm;
  position: relative;
  overflow: hidden;
}
/* The gleam, one more time — a still one, because paper does not animate. */
.sheet__price::after {
  content: '';
  position: absolute;
  inset: -20% auto -20% 62%;
  width: 26mm;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .75), transparent);
  transform: skewX(-18deg);
  pointer-events: none;
}
.sheet__price-what { position: relative; z-index: 1; }
.sheet__service { margin: 0; font-family: var(--display); font-size: 1.9em; line-height: 1.1; }
.sheet__price-num { text-align: right; position: relative; z-index: 1; }
.sheet__amount {
  margin: 0;
  font-family: var(--display);
  font-size: 4.6em;
  line-height: .9;
  color: var(--rose-deep);
  letter-spacing: -.02em;
}
.sheet__per {
  margin: 1mm 0 0;
  font-size: .76em;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--rose);
}
.sheet__fixed {
  grid-column: 1 / -1;
  margin: 0;
  padding-top: 4mm;
  border-top: .3mm solid rgba(138, 77, 94, .22);
  font-size: .88em;
  font-style: italic;
  color: var(--rose-deep);
  position: relative;
  z-index: 1;
}

/* ---- blocks ------------------------------------------------------------ */
.sheet__block { padding-top: 7mm; }
.sheet__body { margin: 0; white-space: pre-line; color: var(--ink-soft); }

.sheet__list {
  margin: 0;
  padding: 0;
  list-style: none;
  columns: 2;
  column-gap: 8mm;
}
.sheet__list li {
  break-inside: avoid;
  padding-left: 5mm;
  margin-bottom: 1.2mm;
  position: relative;
  color: var(--ink-soft);
}
/* Her glint, as the bullet. The one drawn shape in the identity, doing a job
   rather than sitting in a corner being decorative. */
.sheet__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: .62em;
  width: 2.2mm;
  height: 2.2mm;
  background: var(--rose);
  clip-path: polygon(50% 0%, 58% 42%, 100% 50%, 58% 58%, 50% 100%, 42% 58%, 0% 50%, 42% 42%);
}
.sheet__list li strong { color: var(--ink); font-weight: 400; }

.sheet__table { width: 100%; border-collapse: collapse; }
.sheet__table td, .sheet__table th {
  padding: 2mm 0;
  border-bottom: .3mm solid var(--cream-deep);
  text-align: left;
  font-weight: 300;
}
.sheet__table td:last-child, .sheet__table th:last-child {
  text-align: right;
  white-space: nowrap;
  font-family: var(--display);
  font-size: 1.25em;
}
.sheet__table tfoot th { border-bottom: 0; border-top: .5mm solid var(--rose); color: var(--rose-deep); }
.sheet__table tfoot td { border-bottom: 0; border-top: .5mm solid var(--rose); color: var(--rose-deep); }

/* ---- the foot ---------------------------------------------------------- */
.sheet__foot {
  margin-top: auto;
  padding-top: 8mm;
}
.sheet__badges {
  display: flex;
  flex-wrap: wrap;
  gap: 2mm;
  margin-bottom: 4mm;
}
.sheet__badge {
  display: inline-flex;
  align-items: center;
  gap: 1.5mm;
  padding: 1mm 3mm;
  border: .3mm solid var(--blush);
  border-radius: 999px;
  font-size: .74em;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--rose);
}
.sheet__contact {
  display: flex;
  flex-wrap: wrap;
  gap: 2mm 6mm;
  padding-top: 4mm;
  border-top: .3mm solid var(--cream-deep);
  font-size: .84em;
  color: var(--ink-soft);
}
.sheet__contact strong { color: var(--rose); font-weight: 400; }

/* Anything with nothing in it takes itself off the page. Same rule as the
   website: a blank field hides its section, it never prints a heading over
   thin air. */
[hidden] { display: none !important; }

/* =========================================================================
   THE DRAWER
   ========================================================================= */

.qb__drawer {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(38, 24, 29, .45);
  backdrop-filter: blur(3px);
  display: grid;
  place-items: end center;
}
.qb__drawer-panel {
  width: min(100%, 560px);
  max-height: 86vh;
  overflow-y: auto;
  background: var(--cream);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  padding: 1.25rem clamp(1rem, 3vw, 1.75rem) calc(1.5rem + env(safe-area-inset-bottom));
  animation: qb-rise .45s var(--ease);
}
@keyframes qb-rise { from { transform: translateY(30px); opacity: 0; } }
.qb__drawer-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1rem; }
.qb__drawer-head h2 { margin: 0; font-family: var(--display); font-weight: 300; font-size: 1.75rem; }
.qb__x { font-size: 2rem; line-height: 1; color: var(--ink-soft); width: 44px; height: 44px; }

.qb__saved {
  display: flex;
  align-items: center;
  gap: 1rem;
  width: 100%;
  text-align: left;
  padding: .85rem 1rem;
  background: var(--white);
  border: 1px solid var(--cream-deep);
  border-radius: var(--radius-lg);
  margin-bottom: .6rem;
}
.qb__saved-main { flex: 1; min-width: 0; }
.qb__saved-main b { display: block; font-weight: 400; }
.qb__saved-main span { font-size: .82rem; color: var(--ink-faint); }
.qb__saved-price { font-family: var(--display); font-size: 1.5rem; color: var(--rose); }
.qb__empty { color: var(--ink-faint); text-align: center; padding: 2rem 0; }

/* =========================================================================
   TOAST
   ========================================================================= */

.qb__toast {
  position: fixed;
  left: 50%;
  bottom: calc(1.5rem + env(safe-area-inset-bottom));
  transform: translate(-50%, 140%);
  z-index: 200;
  padding: .8rem 1.4rem;
  border-radius: 999px;
  background: var(--rose-deep);
  color: var(--white);
  font-size: .88rem;
  box-shadow: var(--shadow);
  transition: transform .5s var(--ease);
  pointer-events: none;
}
.qb__toast.is-up { transform: translate(-50%, 0); }

/* =========================================================================
   PRINT — the sheet, alone, at exactly A4
   ========================================================================= */

@page { size: A4; margin: 0; }

@media print {
  body.qb { background: #fff; }
  .qb__bar, .qb__form, .qb__actions, .qb__drawer, .qb__toast { display: none !important; }
  .qb__layout { display: block; padding: 0; max-width: none; }
  .qb__preview, .qb__preview-inner {
    position: static;
    height: auto !important;
    overflow: visible;
  }
  .sheet {
    /* The screen scale is undone here — this is the one place the sheet is
       shown at its real size. */
    transform: none !important;
    box-shadow: none;
    width: 210mm;
    min-height: 297mm;
    margin: 0;
  }
  /* Colour is the whole point of the price panel. Without this, Chrome and
     Safari drop every background on the page and it prints as a white box. */
  .sheet, .sheet * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .sheet__block, .sheet__price { break-inside: avoid; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
}
