/* ==========================================================================
   Quote/contact modal — opened from every "Get a quote" / "Get Info &
   Pricing" button site-wide (js/quote-modal.js finds them by their exact
   button text, so no page markup ever needed to change). Same visual
   language as the rest of the site: elevated card recipe (background/
   border/shadow) already used for .shop__featured / .blog__featured /
   .article__cta, box-shadow-ring inputs (border-style can't transition,
   same reasoning as .filter-pill/.pagination__btn), and the brand-gradient
   .btn--cta for the primary action.
   ========================================================================== */

.quote-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: none;
  /* "safe center" falls back to start-alignment once the panel is taller
     than the viewport, instead of plain "center" clipping its top end
     unreachably off-screen (a well-known flex-centering + overflow
     pitfall) — a long form on a short mobile viewport needs this. */
  align-items: safe center;
  justify-content: safe center;
  padding: var(--space-6);
  overflow-y: auto;
  /* Nothing in the modal is selectable except what the user types — the
     input/textarea values get selection re-enabled just below. */
  -webkit-user-select: none;
  user-select: none;
}

.quote-modal__field input,
.quote-modal__field textarea {
  -webkit-user-select: text;
  user-select: text;
}

/* :not([hidden]) (not a plain .is-open class) is what actually flips this
   to display:flex — keeps `hidden` as the single source of truth for
   "is this in the DOM's render tree at all", so nothing can show the
   modal by accident just by toggling a class while `hidden` is still
   set. */
.quote-modal:not([hidden]) {
  display: flex;
}

.quote-modal__backdrop {
  position: fixed;
  inset: 0;
  background: rgba(2, 2, 3, 0.96);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  opacity: 0;
  transition: opacity var(--duration-base) var(--ease-standard);
}

.quote-modal__panel {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 560px;
  max-height: calc(100vh - var(--space-12));
  overflow-y: auto;
  padding: var(--space-10);
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  opacity: 0;
  transform: translateY(24px) scale(0.97);
  transition: opacity var(--duration-base) var(--ease-standard),
    transform var(--duration-base) var(--ease-standard);
}

.quote-modal.is-visible .quote-modal__backdrop {
  opacity: 1;
}

.quote-modal.is-visible .quote-modal__panel {
  opacity: 1;
  transform: translateY(0) scale(1);
}

.quote-modal__close {
  position: absolute;
  top: var(--space-5);
  right: var(--space-5);
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--color-text-muted);
  transition: background var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard);
}

.quote-modal__close:hover {
  background: var(--color-bg-elevated-hover);
  color: var(--color-text);
}

.quote-modal__close svg {
  width: 18px;
  height: 18px;
}

.quote-modal__eyebrow {
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-pill);
  background: rgba(255, 122, 26, 0.12);
  color: var(--color-orange);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.quote-modal__title {
  margin-top: var(--space-4);
  font-family: var(--font-heading);
  font-size: 28px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--color-text);
  padding-right: var(--space-8);
}

.quote-modal__subtitle {
  margin-top: var(--space-2);
  font-size: var(--fs-small);
  line-height: 1.6;
  color: var(--color-text-muted);
}

.quote-modal__form {
  margin-top: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.quote-modal__row {
  display: grid;
  /* minmax(0, 1fr), not plain 1fr — a bare 1fr track won't shrink past its
     input's min-content width, so the fields would push past the modal's
     own edges at narrow widths. Desktop keeps Name/Email side by side;
     tablet/mobile stacks them (below). */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-4);
}

.quote-modal__field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
}

.quote-modal__field label {
  font-size: 13px;
  font-weight: 600;
  color: var(--color-text-muted);
}

/* box-shadow ring instead of a real border — same reasoning as
   .filter-pill/.pagination__btn: the focus state below swaps this
   box-shadow for a colored one, and border-style/color can't transition
   as smoothly as box-shadow can. */
.quote-modal__field input,
.quote-modal__field select,
.quote-modal__field textarea {
  width: 100%;
  min-width: 0;
  height: 48px;
  padding: 0 var(--space-4);
  border: none;
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.03);
  box-shadow: inset 0 0 0 1px var(--color-border);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--fs-small);
  transition: box-shadow var(--duration-fast) var(--ease-standard);
}

.quote-modal__field textarea {
  height: auto;
  min-height: 108px;
  padding: var(--space-3) var(--space-4);
  line-height: 1.5;
  resize: vertical;
}

.quote-modal__field input::placeholder,
.quote-modal__field textarea::placeholder {
  color: var(--color-text-faint);
}

.quote-modal__field input:focus,
.quote-modal__field select:focus,
.quote-modal__field textarea:focus {
  outline: none;
  box-shadow: inset 0 0 0 1px var(--color-border-strong);
}

/* .was-validated is added to the form on the first submit attempt (see
   js/quote-modal.js) — without it, :invalid would already ring every
   empty required field red on first render, before the visitor has typed
   anything at all. Placed after the :focus rule above so a field that's
   both invalid and focused still reads as invalid — same red-outline
   language as the custom select's own .is-invalid. */
.quote-modal__form.was-validated input:invalid,
.quote-modal__form.was-validated textarea:invalid {
  box-shadow: inset 0 0 0 1px #ff5a5a;
}

/* --- Custom "select" (service picker) ---
   A real <select>'s own BOX can be fully restyled (see the shared input
   rule above this used to cover it), but its dropdown POPUP is drawn by
   the browser/OS, not by page CSS — no amount of styling, not even
   color-scheme, reliably reaches it everywhere. Built as its own
   button + listbox instead — same "trigger + absolutely-positioned
   panel" shape as .nav__dropdown (css/header.css) — so the option list is
   just normal page content this stylesheet fully owns. */
.quote-modal__select-wrap {
  position: relative;
}

.quote-modal__select {
  width: 100%;
  height: 48px;
  padding: 0 var(--space-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  border: none;
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.03);
  box-shadow: inset 0 0 0 1px var(--color-border);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--fs-small);
  text-align: left;
  cursor: pointer;
  transition: box-shadow var(--duration-fast) var(--ease-standard);
}

.quote-modal__select[data-placeholder="true"] {
  color: var(--color-text-faint);
}

.quote-modal__select:focus-visible,
.quote-modal__select.is-open {
  outline: none;
  box-shadow: inset 0 0 0 1px var(--color-border-strong);
}

.quote-modal__select.is-invalid {
  box-shadow: inset 0 0 0 1px #ff5a5a;
}

.quote-modal__select-chevron {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
  color: var(--color-text-faint);
  transition: transform var(--duration-fast) var(--ease-standard);
}

.quote-modal__select.is-open .quote-modal__select-chevron {
  transform: rotate(180deg);
}

.quote-modal__select-menu {
  position: absolute;
  z-index: 5;
  top: calc(100% + var(--space-2));
  left: 0;
  right: 0;
  max-height: 230px;
  overflow-y: auto;
  margin: 0;
  padding: var(--space-2);
  list-style: none;
  background: #101014;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5);
}

.quote-modal__select-menu[hidden] {
  display: none;
}

.quote-modal__select-option {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--fs-small);
  color: var(--color-text-muted);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard);
}

.quote-modal__select-option:hover,
.quote-modal__select-option.is-active {
  background: var(--color-bg-elevated-hover);
  color: var(--color-text);
}

.quote-modal__select-option[aria-selected="true"] {
  color: var(--color-text);
  font-weight: 600;
}

.quote-modal__submit {
  margin-top: var(--space-2);
  width: 100%;
  height: 52px;
  font-size: 15px;
  gap: var(--space-2);
}

.quote-modal__submit-spinner {
  display: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  animation: quote-modal-spin 700ms linear infinite;
}

.quote-modal__submit.is-loading {
  pointer-events: none;
  opacity: 0.85;
}

.quote-modal__submit.is-loading .quote-modal__submit-spinner {
  display: inline-block;
}

.quote-modal__submit.is-loading .quote-modal__submit-label {
  opacity: 0.85;
}

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

.quote-modal__note {
  margin-top: var(--space-3);
  font-size: 12px;
  line-height: 1.5;
  color: var(--color-text-faint);
  text-align: center;
}

/* Submit error (network / server failure) — reuses the invalid-field accent. */
.quote-modal__error,
.contacts__error {
  margin-top: var(--space-3);
  font-size: 13px;
  line-height: 1.5;
  text-align: center;
  color: #ff6b6b;
}

/* --- Socials row --- */

.quote-modal__socials {
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
  text-align: center;
}

.quote-modal__socials-label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-faint);
}

/* .footer__social-link (css/footer.css) supplies the icon itself — this
   just centers that row inside the modal instead of the footer's own
   left-aligned one. The modal reuses the plain single-<svg> markup (no
   .footer__social-reel wrapper), so the footer's slide (reel) hover has
   nothing to move here — we don't want that animation anyway. Instead the
   icons take the footer's own two-tone COLOR: faint at rest, full-strength
   on hover, cross-faded (the <svg> is fill:currentColor, so it follows). */
.quote-modal__socials-list {
  margin-top: var(--space-3);
  justify-content: center;
}

.quote-modal__socials-list .footer__social-link {
  color: var(--color-text-faint);
  transition: color var(--duration-fast) var(--ease-standard);
}

@media (hover: hover) {
  .quote-modal__socials-list .footer__social-link:hover {
    color: var(--color-text);
  }
}

/* Tablet/mobile only: stack Name/Email full width (like the service select)
   and enlarge the social icons (20x15 -> 27x20) with a wider gap. Desktop
   keeps the original 2-column fields and small icons. */
@media (max-width: 1024px) {
  .quote-modal__row {
    grid-template-columns: 1fr;
  }

  .quote-modal__socials-list {
    gap: var(--space-6);
  }

  .quote-modal__socials-list .footer__social-link {
    width: 27px;
    height: 20px;
  }

  .quote-modal__socials-list .footer__social-link svg {
    height: 20px;
  }
}

/* --- Success state --- */

/* display: none by default, :not([hidden]) flips it to flex — same
   "hidden stays the single source of truth" reasoning as .quote-modal
   itself above; without this, [hidden]'s native display:none loses the
   cascade tie against this class's own display:flex (equal specificity,
   later source wins), leaving the success view visible underneath the
   form instead of swapped in for it. */
.quote-modal__success {
  display: none;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding-block: var(--space-6);
}

.quote-modal__success:not([hidden]) {
  display: flex;
}

.quote-modal__success-icon {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--gradient-brand-btn);
  box-shadow: var(--shadow-brand);
  color: #fff;
}

.quote-modal__success-icon svg {
  width: 28px;
  height: 28px;
}

.quote-modal__success-title {
  margin-top: var(--space-5);
  font-family: var(--font-heading);
  font-size: 22px;
  font-weight: 700;
  color: var(--color-text);
}

.quote-modal__success-text {
  margin-top: var(--space-2);
  max-width: 38ch;
  font-size: var(--fs-small);
  line-height: 1.6;
  color: var(--color-text-muted);
}

.quote-modal__success .btn {
  margin-top: var(--space-6);
}

@media (max-width: 560px) {
  .quote-modal {
    padding: var(--space-3);
  }

  .quote-modal__panel {
    padding: var(--space-6) var(--space-5);
  }

  .quote-modal__row {
    grid-template-columns: 1fr;
  }

  .quote-modal__title {
    font-size: 24px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .quote-modal__backdrop,
  .quote-modal__panel {
    transition: none;
  }
}
