/* ==========================================================================
   13 QUOTE — split. Form on the left, NAP panel on --radius-slab on the right.
   There is no form server: the form's action is a mailto: to the studio, which
   the browser performs with JS off. With JS on, js/modules/quote.js intercepts
   the submit and answers in .quote__sent, which carries the same message on a
   link the visitor presses. 0 images.
   ========================================================================== */

.quote { background: var(--surface-page); }

.quote__inner { display: grid; gap: var(--space-stack); align-items: start; }

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

.field { display: grid; gap: var(--space-3xs); }
.field--wide { grid-column: 1 / -1; }

.field__label {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}
.field__req { color: var(--text-accent); }

.field__input,
.field__select,
.field__textarea {
  --chamfer: var(--chamfer-sm);
  width: 100%;
  min-height: var(--control-h);
  padding: var(--space-2xs) var(--space-sm);
  background: var(--surface-inset);
  border: var(--border-width-hair) solid var(--border-strong);
  border-radius: var(--radius-inset);
  clip-path: var(--chamfer-clip);
  color: var(--text-primary);
  font-size: var(--text-body-sm);
  transition: border-color var(--dur-fast) var(--ease-state), background-color var(--dur-fast) var(--ease-state);
}
.field__textarea { min-height: var(--space-5xl); resize: vertical; line-height: var(--leading-body); }

/* iOS SAFARI ZOOMS THE VIEWPORT on focus for any field whose computed size is
   under 16px, and --text-body-sm is 15. On the site's only booking path that
   throws the layout sideways in the middle of typing and leaves the page
   zoomed afterwards. The other cure, maximum-scale=1 in the viewport meta,
   also kills pinch zoom for low-vision users, so it is not on the table.
   --text-body is exactly 16px, which is the threshold, and the fields are the
   only thing on the page that changes.
   Two conditions, because the two populations are not the same set: every
   phone and portrait tablet by width, and every touch screen at any width by
   pointer. Above both, the 15px calibration stands. */
@media (max-width: 1023px), (pointer: coarse) {
  .field__input,
  .field__select,
  .field__textarea { font-size: var(--text-body); }
}

/* THE SELECT IS THE ONE CONTROL EVERY ENGINE DRAWS DIFFERENTLY. Chrome puts a
   grey chevron inside the padding box, Firefox on Windows draws its own arrow
   and paints the popup from the control's own colours, and Safari and iOS
   overlay a rounded native bezel that ignores the chamfer entirely. Three
   renderings of one field. appearance: none takes the control back in all
   three; the -moz- and -webkit- lines stay because the unprefixed property is
   younger than the engines this pass is aimed at.
   The chevron is redrawn on the wrapper, not on the select: a background-image
   on the control itself is wiped by the `background` shorthand in the hover
   rule below, and this site has no gradient chevrons. Two borders on a square,
   turned 45deg — the same construction as the site's arrow marks. */
.field__select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  padding-inline-end: calc(var(--space-sm) * 2 + var(--icon-sm));
}
.field--select { position: relative; }
.field--select::after {
  content: "";
  position: absolute;
  inset-inline-end: var(--space-sm);
  inset-block-end: calc(var(--control-h) / 2);
  width: var(--space-2xs);
  height: var(--space-2xs);
  border-inline-end: var(--border-width-medium) solid var(--text-muted);
  border-block-end: var(--border-width-medium) solid var(--text-muted);
  transform: translate3d(0, 50%, 0) rotate(45deg);
  pointer-events: none;
}
/* the popup list is UA chrome and inherits nothing, so it is inked here or it
   ships as near-black on near-black in Firefox on Windows, which paints the
   list from the control's own colours rather than from the system menu */
.field__select option { background: var(--surface-inset); color: var(--text-primary); }
.field__input:hover,
.field__select:hover,
.field__textarea:hover { border-color: var(--border-soft); background-color: var(--surface-inset-hover); }
/* chamfered, so the ring is drawn inside rather than as a clipped outline */
.field__input:focus-visible,
.field__select:focus-visible,
.field__textarea:focus-visible {
  outline: none;
  border-color: var(--border-accent);
  box-shadow: var(--focus-ring-inset);
}
.field__input::placeholder, .field__textarea::placeholder { color: var(--text-faint); }

.quote__consent {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-2xs);
  align-items: start;
  font-size: var(--text-caption);
  line-height: var(--leading-snug);
  color: var(--text-muted);
}
.quote__consent input { accent-color: var(--surface-accent); width: var(--icon-md); height: var(--icon-md); }

.quote__submit { justify-self: start; }

/* --- the confirmation panel ----------------------------------------------
   Swapped in for the form after a valid submit, and swapped back out by the
   "edit" button. Both boxes declare their own display, so both need the
   [hidden] pair: an author `display` beats the UA sheet's [hidden] rule and
   the panel would otherwise ship visible. */
.quote__form[hidden],
.quote__sent[hidden] { display: none; }

.quote__sent {
  --chamfer: var(--chamfer-md);
  --chamfer-edge-ink: var(--border-accent-soft);
  display: grid;
  justify-items: start;
  gap: var(--space-sm);
  padding: var(--card-pad-lg);
  border: var(--border-width-hair) solid var(--border-accent-soft);
  border-radius: var(--radius-card);
  clip-path: var(--chamfer-clip);
  background: var(--chamfer-edge), var(--surface-accent-wash);
}
/* chamfered: the outline would be clipped, so the ring is drawn inside */
.quote__sent:focus-visible { outline: none; box-shadow: var(--focus-ring-inset); }

.quote__sent-title { font-size: var(--text-h3); color: var(--text-primary); }
.quote__sent-body {
  max-width: var(--width-measure);
  font-size: var(--text-body-sm);
  line-height: var(--leading-body);
  color: var(--text-secondary);
}
.quote__sent-fallback {
  max-width: var(--width-measure);
  font-size: var(--text-caption);
  line-height: var(--leading-body);
  color: var(--text-muted);
}
.quote__sent-link {
  color: var(--text-accent);
  transition: color var(--dur-fast) var(--ease-state);
}
.quote__sent-link:hover { color: var(--text-accent-strong); }

/* the handoff and the way back, side by side until the column is too narrow */
.quote__sent-acts { display: flex; flex-wrap: wrap; gap: var(--space-2xs); }

/* --- the NAP panel ------------------------------------------------------- */
.quote__nap {
  --chamfer: var(--chamfer-lg);
  display: grid;
  gap: var(--space-md);
  padding: var(--card-pad-lg);
  background: var(--chamfer-edge), var(--surface-raised);
  border: var(--border-width-hair) solid var(--border-hairline);
  border-radius: var(--radius-slab);
  clip-path: var(--chamfer-clip);
}

.nap__row { display: grid; gap: var(--space-3xs); }
.nap__key {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}
.nap__val { font-size: var(--text-body-sm); line-height: var(--leading-body); color: var(--text-secondary); }
.nap__val--big {
  font-family: var(--font-mono);
  font-size: var(--text-h4);
  font-weight: var(--weight-bold);
  color: var(--text-primary);
  transition: color var(--dur-fast) var(--ease-state);
}
a.nap__val--big:hover { color: var(--text-accent); }

.nap__hours { display: grid; gap: var(--space-3xs); }
.nap__hours-row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-sm);
  /* every horizontal rule on this site is a tick rule (docs/uniqueness.md
     move 6). This row was the last plain hairline left. */
  padding-block: var(--space-2xs);
  background: var(--tick-rule-fine);
  background-position: bottom;
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  color: var(--text-muted);
}
.nap__hours-row b { color: var(--text-secondary); font-weight: var(--weight-medium); }

.nap__certs { display: flex; flex-wrap: wrap; gap: var(--space-2xs); }
.nap__cert {
  padding: var(--space-3xs) var(--space-2xs);
  border: var(--border-width-hair) solid var(--border-accent-soft);
  border-radius: var(--radius-pill);
  background: var(--surface-accent-wash);
  color: var(--text-secondary);
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: var(--tracking-mono-label);
}

/* --- /book/: the form IS the page ----------------------------------------
   The only page on the site with no hero, so the block has to clear the fixed
   header itself, and the masthead sets at display scale rather than at h2 —
   .sec-title would put the h1:body ratio at 3.5:1 and fail the type-contrast
   law. Same reasoning specs/020 records for .hero__title. The confirmation
   plate grows with it: at card scale it read as a notice dropped into a page
   whose whole job is the action it answers. */
.quote--page { padding-block-start: calc(var(--header-h) + var(--space-xl)); }
.quote--page .sec-title {
  font-size: var(--text-display);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
}
.quote--page .quote__sent { justify-self: stretch; --chamfer: var(--chamfer-lg); }
.quote--page .quote__sent-title { font-size: var(--text-h2); }

@media (min-width: 768px) {
  .quote__form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .quote__inner { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); column-gap: var(--space-2xl); }
}
