/* Created by Andy */
/* UC-105 phase 4: only what the booking page adds on top of the site's own style.css.
   Buttons, fonts and the page frame all come from there, so this file stays small and the
   page keeps looking like the rest of lapianotuning.com when it moves onto the VPS.

   Several rules here exist to UNDO something style.css does at a wider breakpoint. That is
   the awkward part of reusing a stylesheet built for a different page, and each one says
   which value it is overriding and why, because they look arbitrary otherwise. */

/* Sits on the shell's own left edge rather than centred inside it, so the h1 lines up with
   the header nav and the footer nav. #main.container already supplies the gutters. */
.scheduling {
  max-width: 700px;
  margin: 0;
  padding: 30px 0 60px;
  /* The panel and the footer jumped on every step change without this. */
  min-height: 520px;
}

/* The site steps h1 24px -> 30px at 768px but this file pins h2 at one size, so on a phone
   the page title came out 2px larger than the section heading under it, same weight and same
   colour — it read as a fourth section rather than the title. Both are sized here so the gap
   survives every width. Darker than the inherited body grey for the same reason: it is the
   one line that has to look like a title. */
.scheduling h1 {
  margin-bottom: 20px;
  font-size: 26px;
  line-height: 30px;
  color: #3f3f3f;
}

/* style.css sets a 32px line-height on h2 and 28px on h3 above 768px. Overriding only the
   size leaves the headings floating in that leading, adrift from what they introduce. */
.scheduling h2 {
  margin: 34px 0 14px;
  font-size: 20px;
  line-height: 24px;
}

@media (min-width: 768px) {
  .scheduling h1 {
    font-size: 32px;
    line-height: 36px;
  }
  .scheduling h2 {
    font-size: 22px;
    line-height: 26px;
  }
}

/* Small caps rather than 17px bold: at one pixel above body text the old size did no work,
   and the parent site already uses letterspaced caps for section labels. */
.scheduling h3 {
  margin: 26px 0 10px;
  font-size: 14px;
  line-height: 18px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: #757474;
}

.scheduling-field {
  flex: 1 1 180px;
  margin-bottom: 20px;
}

.scheduling-field-small {
  flex: 0 1 110px;
}

.scheduling-field label {
  display: block;
  margin-bottom: 4px;
  font-weight: 500;
}

/* Square and with a border you can see, matching the site's own inputs. Pale rounded boxes
   read as a different, newer product bolted into the shell. */
.scheduling-field input,
.scheduling-field select,
.scheduling-field textarea {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid #8c8b8b;
  border-radius: 0;
  font: inherit;
  background: #fff;
}

/* A native select renders 39px against the inputs' 36px, so the row's bottoms disagree. */
.scheduling-field input,
.scheduling-field select {
  height: 38px;
}

.scheduling-field textarea {
  height: auto;
  resize: vertical;
}

/* style.css sets `outline: none` on inputs and replaces it with nothing, so a focused field
   is indistinguishable from an unfocused one. On a form the business runs on, that is a
   defect. The colour is the site's own link blue. */
.scheduling-field input:focus,
.scheduling-field select:focus,
.scheduling-field textarea:focus,
.scheduling-time:focus,
.scheduling-suggestion:focus,
.scheduling .btn:focus {
  outline: 2px solid #0f598e;
  outline-offset: 1px;
}

/* showStep focuses the step's heading so the change is announced. Chrome paints no ring on
   programmatic focus of a tabindex="-1" element, so :focus here would draw a box around the
   heading for someone who had just clicked. :focus-visible keeps it for the keyboard only. */
.scheduling h2:focus-visible {
  outline: 2px solid #0f598e;
  outline-offset: 1px;
}

.scheduling-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0 15px;
}

/* City 180 + State 110 + ZIP 110 + gaps overflows a phone, which wrapped ZIP alone onto its
   own line with two thirds of the row empty beside it. */
@media (max-width: 520px) {
  .scheduling-row .scheduling-field {
    flex-basis: 100%;
  }
  .scheduling-row .scheduling-field-small {
    flex: 1 1 0;
  }
}

/* The label carries the touch target; a bare checkbox is too small to hit on a phone. */
.scheduling-check {
  margin-bottom: 2px;
}

/* A floated checkbox beside a BLOCK label, which is the shape the phone breakpoint already
   used and is now the only one. The description lives inside the label, and an inline-block
   label brought two separate problems with it: it takes its baseline from its LAST line, so a
   baseline-aligned checkbox dropped down beside the description; and it shrink-to-fits to the
   description measured as one unwrapped line, which at 690px in a 700px column left no room
   for the checkbox at all and stranded it on a line of its own. A block label neither
   baseline-aligns nor shrink-to-fits, so both go away. margin-left clears the float
   horizontally; vertically it is the label's own min-height plus padding (44px, 54px on the
   phone) that outgrows the float's reach (margin-top plus 16px) and keeps it inside the row.
   Trim that min-height, or grow the checkbox for a bigger touch target, and the float escapes
   into the next row with nothing to catch it — and no test covers CSS.

   One deliberate consequence: on desktop the label is now the full width of the column, so
   clicking anywhere on the row ticks the box. It used to shrink-wrap to the text. The phone
   breakpoint already behaved this way; this makes the two agree. */
.scheduling-check input[type="checkbox"] {
  width: 16px;
  height: 16px;
  float: left;
  margin-top: 11px;
}

.scheduling-check label {
  display: block;
  margin-left: 26px;
  padding: 8px 0;
  min-height: 28px;
}

/* Marks the four fields the server refuses a booking without. */
.scheduling-required {
  margin-left: 2px;
  color: #c0392b;
}

#booking-summary,
#done-place {
  margin-bottom: 22px;
}

.scheduling-summary-heading {
  margin: 12px 0 2px;
  font-size: 15px;
  font-weight: bold;
  color: #565555;
}

.scheduling-summary-address {
  margin: 0;
}

.scheduling-summary-services {
  margin: 0;
  padding-left: 22px;
}

.scheduling-required-note {
  margin: 0 0 18px;
}

/* Both messages are scrolled to by showError. Without the margin one lands flush against the
   top of the viewport, under a phone's URL bar or notch. */
#request-error,
#contact-error {
  scroll-margin-top: 16px;
}

/* A block inside the label, so it sits under the service name and shares the label's own
   indent — and, being inside, taking a tap ticks the box like the name does. */
.scheduling-service-note {
  display: block;
  margin: 2px 0 0;
  font-size: 14px;
}

.scheduling-muted {
  color: #666;
  font-size: 15px;
}

/* Separated from the service rows, which it otherwise reads as a fourth item of. */
/* David asked for the appointment duration to be very large. The identical sentence appears
   on both step 1 and step 2 — "Approximate Duration: 1h 30m" — so both carry the same size;
   shrinking it on the way to choosing a time would read as a different number. #chosen-time
   is deliberately left alone: it is the time the customer picked, not the duration. */
#duration-summary,
#times-summary {
  color: #565555;
  font-size: 26px;
  line-height: 32px;
  font-weight: bold;
}

#duration-summary {
  margin: 18px 0 0;
}

/* The one reassuring fact on the details screen; it was the smallest, greyest type there.
   The gap that used to separate it from the form now belongs to the summary under it. */
#chosen-time {
  margin-bottom: 4px;
  font-size: 18px;
  line-height: 24px;
  color: #565555;
}

.scheduling-error {
  margin: 15px 0;
  padding: 10px 12px;
  border-left: 3px solid #c0392b;
  background: #fdf0ee;
  color: #c0392b;
}

/* Having no openings is a normal answer, not the customer's mistake. In the red error style
   it read as one, on the screen where the only thing left to do is phone us. */
.scheduling-notice {
  margin: 15px 0;
  padding: 10px 12px;
  border-left: 3px solid #8c8b8b;
  background: #f4f4f4;
  color: #565555;
}

/* On the no-openings screen this link is the only thing left to do, and as a bare inline
   anchor it was an 18px tall target. The negative margin keeps the notice the same height. */
.scheduling-notice a {
  display: inline-block;
  padding: 13px 4px;
  margin: -13px 0;
}

/* A ruled list, not five bordered boxes. Boxed and full width, a time slot looked exactly
   like the empty text inputs on the step before it — the customer is asked to click things
   that read as form fields. */
.scheduling-times {
  list-style: none;
  margin: 0 0 26px;
  padding: 0;
  border-top: 1px solid #ddd;
}

.scheduling-times li {
  margin: 0;
}

/* Link blue and a chevron. In body grey with no underline, border or box, a slot was 700px
   of plain text that happened to be clickable — and hover, the only hint, does not exist on
   a phone. This is the screen where the customer has to act. */
.scheduling-time {
  position: relative;
  display: block;
  width: 100%;
  padding: 14px 26px 14px 2px;
  border: 0;
  border-bottom: 1px solid #ddd;
  border-radius: 0;
  background: none;
  font: inherit;
  font-size: 18px;
  color: #0f598e;
  text-align: left;
  cursor: pointer;
}

.scheduling-time::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 6px;
  width: 8px;
  height: 8px;
  margin-top: -5px;
  border-right: 2px solid #0f598e;
  border-bottom: 2px solid #0f598e;
  transform: rotate(-45deg);
}

.scheduling-time:hover,
.scheduling-time:focus {
  background: #f6f6f6;
}

/* The list hangs under the street field, so the field is the positioning context. */
.scheduling-suggest {
  position: relative;
}

.scheduling-suggestions {
  position: absolute;
  z-index: 10;
  left: 0;
  right: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  /* Matches the field it hangs from; at #bbb the list looked darker than its own input. */
  border: 1px solid #8c8b8b;
  border-top: none;
  background: #fff;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.18);
  /* Five suggestions wrap to two lines each on a phone, so the last of them sat under the
     keyboard with no way to scroll to it. */
  max-height: 45vh;
  overflow-y: auto;
}

.scheduling-suggestions li {
  margin: 0;
}

.scheduling-suggestions li + li .scheduling-suggestion {
  border-top: 1px solid #e6e6e6;
}

.scheduling-suggestion {
  display: block;
  width: 100%;
  padding: 11px 10px;
  border: none;
  background: none;
  font: inherit;
  font-size: 15px;
  line-height: 19px;
  text-align: left;
  cursor: pointer;
}

.scheduling-suggestion:hover,
.scheduling-suggestion:focus {
  background: #f0f0f0;
}

/* Announced to a screen reader without taking space on the page. */
.scheduling-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.scheduling .btn {
  padding: 10px 18px;
  margin: 10px 10px 10px 0;
}

/* style.css gives .btn-secondary min-width:303px and font-size:20px above 1024px, so the
   "go back" button rendered LARGER and taller than "Reserve My Appointment" — the escape
   hatch outranking the button that books the job. Only its colours were overridden before. */
.scheduling .btn.btn-secondary {
  min-width: 0;
  padding: 10px 18px;
  border-radius: 10px;
  background: #fff;
  border: 1px solid #999;
  color: #565555;
  font-size: 16px;
  line-height: 20px;
  text-shadow: none;
  box-shadow: none;
}

@media (min-width: 768px) {
  .scheduling .btn.btn-secondary {
    font-size: 18px;
    line-height: 20px;
  }
}

.scheduling .btn.btn-secondary:hover {
  background: #f4f4f4;
  border-color: #333;
  color: #565555;
}

.scheduling .btn[disabled] {
  opacity: 0.6;
  cursor: default;
}

/* "Find Times" becomes "Looking for times…" and grew 116px -> 176px mid-press, moving under
   the finger that had just tapped it. 200 rather than 180 because style.css takes .btn from
   16px to 18px above 768px, where the longer label needs 193. */
#find-times {
  min-width: 200px;
}

/* Same reason: "Reserve My Appointment" shrinks to "Reserving…" mid-press, and it has a
   sibling button beside it that would slide under the finger. */
#reserve {
  min-width: 250px;
}

/* A slot list on step 2 makes the page taller than the viewport and step 3 shorter, so the
   scrollbar appeared and disappeared between steps and everything slid 7.5px sideways.
   overflow-y rather than scrollbar-gutter: the header and footer bars bleed to +/-9999px and
   are clipped by #wrapper, so they end at the html content box — a reserved gutter would show
   as a pale stripe past the end of the black bar. This renders a real empty track instead. */
html {
  overflow-y: scroll;
}

/* 38px inputs and 40px buttons are under the 44px a finger reliably hits, and the checkbox
   label was only as wide as its own text. Keyed to the site's own 768px mobile breakpoint, not
   to 520px: at 520px every one of these targets shrank again on any phone bigger than an SE,
   including the .btn-secondary line below, whose whole purpose is to stop the back button
   out-sizing "Reserve My Appointment". The second query picks up the wider phones held
   sideways, 768-950px, which the first arm misses. The 950px ceiling keeps the widest desktop
   windows out of it; a short window narrower than that does get the phone treatment, which is
   the right trade for a rare case. */
@media (max-width: 767px), (max-height: 500px) and (max-width: 950px) {
  .scheduling-field input,
  .scheduling-field select {
    height: 44px;
  }

  .scheduling .btn {
    padding: 12px 18px;
  }

  /* .scheduling .btn.btn-secondary above is more specific than .scheduling .btn, so without
     naming it here the back buttons keep the 10px padding and stay at 42px. The line-height
     comes with it: at the secondary's own 20px the back button ends up 2px TALLER than
     "Reserve My Appointment", which is what that rule exists to prevent. */
  .scheduling .btn.btn-secondary {
    padding: 12px 18px;
    line-height: 18px;
  }

  /* Same mechanism as the base rules; only the touch-sized numbers differ. */
  .scheduling-check label {
    padding: 13px 0;
  }

  .scheduling-check input[type="checkbox"] {
    margin-top: 14px;
  }
}

/* With the real catalogue — 4 groups, 14 services, each with a description — step 1 measures
   2046px inside a 2447px page on a 390px phone, which left "Find Times" 2.5 screens below the
   fold and the running duration total down there with it: the customer ticked a service at the
   top and could not see either the total or the way forward. Pinning both to the bottom keeps
   the action, and the number it commits them to, on screen the whole way down the list.

   These are fixed rather than sticky because #wrapper in the site stylesheet sets
   overflow: hidden, which stops sticky from ever engaging. Do NOT "fix" that by clearing the
   overflow — it is holding back a decorative element roughly 10000px wide, and lifting it
   gives the page a horizontal scrollbar. */
@media (max-width: 767px), (max-height: 500px) and (max-width: 950px) {
  /* A solid band behind the pinned controls. Without it the service row underneath shows
     through the button's rounded corners and the gutters either side of it. It hangs off
     #step-request so it goes away with the step, leaving steps 2-4 untouched. */
  #step-request::after {
    content: "";
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: 64px;
    z-index: 4;
    background: #fff;
  }

  /* margin must be cleared: .scheduling .btn carries margin: 10px 10px 10px 0, and against
     left/right offsets that pushed the button 10px off the column it is meant to line up with
     (15px left, 25px right) and sat its top edge flush on the band boundary. max-width holds
     it to the 700px column .scheduling caps the fields at, so it does not run the full width
     of a landscape phone. */
  #find-times {
    position: fixed;
    left: 15px;
    right: 15px;
    bottom: 10px;
    width: auto;
    max-width: 700px;
    margin: 0;
    z-index: 6;
  }

  /* scrollIntoView("nearest") in showError does nothing once the message is inside the
     viewport, and it cannot know the bottom of that viewport is covered by the band. Without
     this the error — including the no-openings message giving the phone number — can be
     painted over, and the button reads as dead. */
  #request-error {
    scroll-margin-bottom: calc(var(--scheduling-pinned-height, 160px) + 20px);
  }

  /* Keeps the last service clear of the pinned controls before the footer scrolls under. */
  #step-request {
    padding-bottom: 70px;
  }

  /* The band is pinned to the viewport, so at full scroll it lies over the end of the footer
     and cuts a white stripe through the black bar, hiding the copyright line. Extending the
     wrapper gives the page 64px more to scroll, which clears the footer out from under it.
     Scoped with :has so the extra space exists only on the step that has the band; browsers
     without :has simply keep the overlap. */
  #wrapper:has(#step-request:not([hidden])) {
    padding-bottom: 64px;
  }
}

/* The total is pinned too, but only where there is height to spare for it: on a landscape
   phone the pair would eat well over a quarter of a 390px-tall viewport, so there it stays in
   the flow and only the button is pinned. */
@media (max-width: 767px) and (min-height: 501px) {
  #duration-summary {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 64px;
    z-index: 5;
    margin: 0;
    padding: 8px 15px 6px;
    background: #fff;
  }

  #step-request {
    padding-bottom: calc(var(--scheduling-pinned-height, 160px) + 20px);
  }

  /* The pinned summary carries its own opaque background, so on this branch the stack covering
     the footer is 96px, not the band's 64px. Sized here the same way #step-request is, rather
     than leaving the wrapper padding set for the band alone and clearing the footer by a
     fraction of a pixel. */
  #wrapper:has(#step-request:not([hidden])) {
    padding-bottom: calc(var(--scheduling-pinned-height, 160px) + 20px);
  }
}

/* Placeholders in the site's stylesheet are dark enough to read as filled-in values — the
   address looked complete when every field was empty. #aaa read at 2.32:1, though, and these
   carry real format guidance ("1234 Ocean Ave", "CA", "90401"), so this is the lightest grey
   that still passes AA on white. */
.scheduling-field input::placeholder {
  color: #767676;
}

/* David asked for something far more prominent while times are being searched. It covers the
   viewport, the pinned button included, so the wait reads as deliberate rather than as a dead
   button — the call really does take seconds, because it measures live travel times.
   The [hidden] guard is required: display:flex here would otherwise beat the site's
   [hidden] { display: none } and the panel would never go away. */
.scheduling-searching {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: #fff;
}

.scheduling-searching[hidden] {
  display: none;
}

.scheduling-searching-panel {
  max-width: 420px;
  text-align: center;
}

.scheduling-spinner {
  width: 64px;
  height: 64px;
  margin: 0 auto 24px;
  border: 6px solid #e2e2e2;
  border-top-color: #2a6ebb;
  border-radius: 50%;
  animation: scheduling-spin 900ms linear infinite;
}

@keyframes scheduling-spin {
  to {
    transform: rotate(360deg);
  }
}

/* Some people get motion sick from a spinner; the text alone still says what is happening. */
@media (prefers-reduced-motion: reduce) {
  .scheduling-spinner {
    animation: none;
  }
}

.scheduling-searching-title {
  margin: 0 0 10px;
  font-size: 26px;
  line-height: 32px;
  color: #333;
}

.scheduling-searching-note {
  margin: 0;
  font-size: 16px;
  line-height: 22px;
  color: #666;
}

/* These rows WERE 41px, separated by a 1px rule; this takes them to 45px. Keyed to the
   POINTER rather than the viewport: a portrait iPad is 768-1024px wide and misses the phone
   query entirely, and this is the one list where a mis-tap has a real cost — the wrong pick
   silently rewrites all four address fields and a tuner is sent to it. Every other touch
   target in this file is still viewport-keyed, so that tablet gets bigger suggestion rows
   while its inputs and buttons stay at desktop sizes. Deliberate for now: this is the row
   worth the inconsistency, and moving the rest is a change of its own. */
@media (pointer: coarse) {
  .scheduling-suggestion {
    padding: 13px 10px;
  }
}
