/* ============================================================
   Hernandez Pro Detailing — Funnel styles (quote.html + book.html)
   All classes prefixed .fn-. Uses design tokens from css/styles.css
   (loaded first). No hardcoded brand hex — tokens only.
   ============================================================ */

body { min-height: 100vh; }

/* ---- Header: centered logo + optional back arrow ---- */
.fn-header {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px var(--gutter);
}
.fn-logo { display: inline-flex; }
.fn-logo img { height: 40px; width: auto; display: block; }
.fn-back {
  position: absolute;
  left: var(--gutter);
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  padding: 6px 4px;
  color: var(--text-muted);
  font-family: var(--font-sub);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 0.15s;
}
.fn-back:hover { color: var(--accent); }
.fn-back[hidden] { display: none; }

/* ---- Progress bar ---- */
.fn-progress {
  height: 3px;
  width: 100%;
  background: var(--surface-2);
}
.fn-progress__fill {
  height: 100%;
  width: 20%;
  background: var(--accent-grad);
  transition: width 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

/* ---- Main column ---- */
.fn-main {
  max-width: 560px;
  margin: 0 auto;
  padding: 28px var(--gutter) 96px;
}

/* ---- Steps ---- */
.fn-step { display: none; }
.fn-step.is-active { display: block; }
/* The final step ends with the city picker. Wherever the custom list renders,
   reserve scroll room beneath it so an open list always has visible space
   under it instead of running off the bottom of the screen. funnel.js scrolls
   the panel into view on open; this is the room it needs.
   ⚠ This query MUST stay identical to the one gating createSelect() in
   funnel.js — it reserves room for exactly the UI that gate builds. Both are
   width-based on purpose: pointer/hover queries do NOT detect a mouse on a
   touchscreen laptop (see the long comment on that gate). */
@media (min-width: 769px), (any-pointer: fine) {
  .fn-step[data-final] { padding-bottom: 200px; }
}
/* heading receives programmatic focus per step (screen-reader flow) — no ring */
.fn-step__title:focus, .fn-confirm:focus { outline: none; }

.fn-eyebrow {
  font-family: var(--font-sub);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
  margin-bottom: 10px;
}
.fn-step__title {
  font-family: var(--font-head);
  font-weight: 400;
  font-size: clamp(34px, 9vw, 46px);
  line-height: 1.02;
  letter-spacing: 0.01em;
  margin-bottom: 8px;
}
.fn-step__sub {
  color: var(--text-muted);
  font-size: 15px;
  line-height: 1.5;
  margin-bottom: 22px;
}
.fn-subhead {
  font-family: var(--font-head);
  font-weight: 400;
  font-size: 24px;
  letter-spacing: 0.02em;
  margin: 28px 0 12px;
}

/* ---- Cards ---- */
.fn-cards { display: grid; gap: 12px; }
.fn-cards--grid { grid-template-columns: repeat(2, 1fr); }
.fn-cards--list { grid-template-columns: 1fr; }

.fn-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: flex-start;
  text-align: left;
  width: 100%;
  padding: 16px 44px 16px 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  font-family: var(--font-sub);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, transform 0.08s;
}
.fn-cards--grid .fn-card {
  align-items: center;
  text-align: center;
  padding: 20px 12px;
}
.fn-card:hover { border-color: var(--accent); }
.fn-card:active { transform: scale(0.99); }
.fn-card.is-selected {
  border-color: var(--accent);
  background: var(--accent-dim);
}

.fn-card__label {
  font-size: 18px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.fn-card__desc {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 400;
  color: var(--text-muted);
  text-transform: none;
  letter-spacing: 0;
}
.fn-card__check {
  position: absolute;
  top: 50%;
  right: 16px;
  transform: translateY(-50%);
  color: var(--accent);
  font-size: 16px;
  opacity: 0;
  transition: opacity 0.15s;
}
.fn-cards--grid .fn-card__check { top: 12px; right: 12px; transform: none; }
.fn-card.is-selected .fn-card__check { opacity: 1; }

/* ---- Fields ---- */
.fn-field {
  display: block;
  margin-bottom: 14px;
}
.fn-field--mt { margin-top: 20px; }
.fn-field__label {
  display: block;
  margin-bottom: 6px;
  font-family: var(--font-sub);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text);
}
.fn-field__opt {
  color: var(--text-muted);
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
}
.fn-field input,
.fn-field textarea {
  width: 100%;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px; /* >=16px avoids iOS focus zoom */
  line-height: 1.4;
}
.fn-field textarea { resize: vertical; min-height: 78px; }
.fn-field input::placeholder,
.fn-field textarea::placeholder { color: var(--text-muted); }
.fn-field input:focus,
.fn-field textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-dim);
}
.fn-field input.fn-invalid,
.fn-field textarea.fn-invalid { border-color: #ff6b6b; }

/* ---- Custom select ----------------------------------------------
   Used twice: the city picker (address step) and the time picker
   (date step). Both are built by the same createSelect() factory.
   A real <select> is the form control. On touch it stays visible
   (the OS picker wins on phones). On non-touch pointers funnel.js
   adds .is-enhanced, hides the select visually — still in the DOM,
   still the source of truth — and layers the custom listbox over it.
   ----------------------------------------------------------------- */
.fn-sel { position: relative; }

.fn-sel__native {
  width: 100%;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px; /* >=16px avoids iOS focus zoom */
  line-height: 1.4;
}
.fn-sel__native:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-dim);
}
/* visually hidden, NOT display:none — the control still exists */
.fn-sel.is-enhanced .fn-sel__native {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Closed state */
.fn-sel__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-muted);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.4;
  text-align: left;
  cursor: pointer;
}
.fn-sel__trigger.has-value { color: var(--text); }
.fn-sel__trigger:hover { border-color: var(--accent); }
.fn-sel__trigger:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-dim);
}
.fn-sel.is-open .fn-sel__trigger { border-color: var(--accent); }
.fn-sel.fn-invalid .fn-sel__trigger,
.fn-sel.fn-invalid .fn-sel__native { border-color: #ff6b6b; }

/* Inert until it has something to offer (the time picker before a date
   is chosen). Genuinely disabled, not just visually dimmed. */
.fn-sel.is-disabled { opacity: 0.55; }
.fn-sel__trigger:disabled,
.fn-sel__native:disabled { cursor: not-allowed; }
.fn-sel__trigger:disabled:hover { border-color: var(--border); }

.fn-sel__chev {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  color: var(--text-muted);
}
.fn-sel.is-open .fn-sel__chev { transform: rotate(180deg); }

/* Panel — height 0 -> auto via the grid-row trick (no measured px) */
.fn-sel__menu {
  position: absolute;
  z-index: 20;
  left: 0;
  right: 0;
  top: calc(100% + 6px);
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  visibility: hidden;
  transform-origin: top;
}
.fn-sel.is-open .fn-sel__menu {
  grid-template-rows: 1fr;
  opacity: 1;
  visibility: visible;
}
.fn-sel__panel { min-height: 0; overflow: hidden; }
.fn-sel__list {
  position: relative;
  padding: 4px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

/* One highlight element that slides — options never get their own bg */
.fn-sel__hl {
  position: absolute;
  left: 4px;
  right: 4px;
  top: 0;
  height: 0;
  border-radius: var(--radius);
  background: var(--surface);
  opacity: 0;
  pointer-events: none;
}
.fn-sel__hl.is-on { opacity: 1; }

.fn-sel__opt {
  --fn-opt-px: 12px;
  --fn-opt-py: 10px;
  position: relative;
  padding: var(--fn-opt-py) var(--fn-opt-px);
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}

/* Two stacked, pixel-identical text layers: background-clip:text can't be
   transitioned, so the gradient copy fades in over the muted base. */
/* Base layer stays a block: an inline-block would sit on the line-box
   baseline and land 1px off the absolutely-positioned gradient layer. */
.fn-sel__txt {
  display: block;
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0;
  color: var(--text-muted);
}
/* Absolutely positioned, width:auto -> shrink-wraps the city name, so the
   gradient sweeps across the word itself rather than the full row. */
.fn-sel__txt--grad {
  position: absolute;
  left: var(--fn-opt-px);
  top: var(--fn-opt-py);
  width: auto;
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  opacity: 0;
}
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .fn-sel__txt--grad { color: var(--accent); }
}
.fn-sel__opt:hover .fn-sel__txt--grad,
.fn-sel__opt.is-active .fn-sel__txt--grad,
.fn-sel__opt[aria-selected="true"] .fn-sel__txt--grad { opacity: 1; }

/* Motion — opt-in. With reduced motion the panel still opens/closes, instantly. */
@media (prefers-reduced-motion: no-preference) {
  .fn-sel__chev { transition: transform 0.2s cubic-bezier(0.2, 0.8, 0.2, 1); }
  .fn-sel__menu {
    transform: translateY(-6px);
    transition:
      grid-template-rows 0.25s cubic-bezier(0.2, 0.9, 0.25, 1.1),
      transform 0.25s cubic-bezier(0.2, 0.9, 0.25, 1.1),
      opacity 0.25s cubic-bezier(0.2, 0.9, 0.25, 1.1),
      visibility 0.25s;
  }
  .fn-sel.is-open .fn-sel__menu { transform: translateY(0); }
  .fn-sel__hl {
    transition:
      transform 0.3s cubic-bezier(0.22, 1, 0.36, 1),
      height 0.2s ease-out,
      opacity 0.2s ease-out;
  }
  .fn-sel__txt--grad { transition: opacity 0.2s ease; }
  .fn-sel.is-open .fn-sel__opt {
    animation: fnSelOpt 0.25s cubic-bezier(0.16, 1, 0.3, 1) both;
    animation-delay: calc(var(--i, 0) * 40ms);
  }
  @keyframes fnSelOpt {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: none; }
  }
}

/* ---- Quote display ---- */
.fn-quote {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 24px;
  text-align: center;
  margin-bottom: 8px;
}
.fn-quote__range {
  font-family: var(--font-head);
  font-weight: 400;
  font-size: clamp(48px, 15vw, 64px);
  line-height: 1;
  letter-spacing: 0.01em;
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .fn-quote__range { color: var(--accent); }
}
.fn-quote__note {
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-muted);
  margin-top: 12px;
}

/* ---- Slots (calendar + time dropdown) ----------------------------
   Only dates present in the fetched availability are enabled; every
   other cell renders as a disabled button (not focusable).
   ------------------------------------------------------------------ */
.fn-slots { min-height: 60px; }

.fn-cal {
  background: transparent; /* fully see-through — the page shows through */
  border: 1px solid var(--accent);
  border-radius: 20px;
  padding: 12px;
}
.fn-cal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 10px;
}
.fn-cal__month {
  font-family: var(--font-sub);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--text);
  text-align: center;
}
.fn-cal__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-muted);
  cursor: pointer;
}
.fn-cal__nav svg { width: 16px; height: 16px; }
.fn-cal__nav:hover:not(:disabled) { border-color: var(--accent); color: var(--text); }
.fn-cal__nav:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-dim);
}
.fn-cal__nav:disabled { opacity: 0.3; cursor: not-allowed; }

.fn-cal__dows {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
  margin-bottom: 4px;
}
.fn-cal__dows span {
  font-family: var(--font-sub);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  text-align: center;
}

.fn-cal__row {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.fn-cal__cell { position: relative; }

.fn-cal__day {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 1 / 1;
  min-height: 40px; /* stays tappable at 375px */
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius);
  color: var(--text);
  font-family: var(--font-sub);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
/* Fallback hover for browsers without mask support — the gradient ring below replaces it */
.fn-cal__day:hover:not(:disabled) { border-color: var(--accent); }

/* Hover = a gradient RING (kept distinct from .is-selected, which is a gradient FILL).
   3-stop lime→cyan→lime so background-position can loop seamlessly; the flowing
   animation itself lives in the reduced-motion block at the end of this section. */
@supports ((-webkit-mask-composite: xor) or (mask-composite: exclude)) {
  .fn-cal__day:hover:not(:disabled) { border-color: transparent; }
  .fn-cal__day::before {
    content: "";
    position: absolute;
    inset: -1px; /* the cell's own 1px border is transparent — sit on the true edge */
    padding: 1px; /* ring thickness */
    border-radius: inherit;
    background: linear-gradient(90deg, #d4f000, #00c8f0, #d4f000);
    background-size: 200% 100%;
    background-position: 0% center;
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    opacity: 0;
    pointer-events: none;
  }
  .fn-cal__day:hover:not(:disabled):not(.is-selected)::before { opacity: 1; }
}
.fn-cal__day:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-dim);
}
/* Unavailable — dimmed, no hover, not focusable (disabled in the markup) */
.fn-cal__day:disabled {
  color: var(--text-muted);
  opacity: 0.35;
  cursor: default;
}
.fn-cal__day.is-selected {
  /* 3-stop so the flow loops seamlessly; at position 0% it reads lime→cyan,
     identical to --accent-grad. Animated in the reduced-motion block below. */
  background: linear-gradient(90deg, #d4f000, #00c8f0, #d4f000);
  background-size: 200% 100%;
  background-position: 0% center;
  border-color: transparent;
  color: var(--bg);
}
/* Today, only while it isn't the selected date */
.fn-cal__day.is-today:not(.is-selected)::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 5px;
  width: 4px;
  height: 4px;
  margin-left: -2px;
  border-radius: 50%;
  background: var(--accent-2);
}
.fn-cal__day.is-today:disabled::after { opacity: 0.5; }

.fn-cal__empty {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--text-muted);
  text-align: center;
  padding: 14px 8px 6px;
}

.fn-cal__timefield { margin-top: 14px; }

@media (prefers-reduced-motion: no-preference) {
  .fn-cal__nav,
  .fn-cal__day { transition: border-color 0.15s, background 0.15s, color 0.15s; }
  /* Flowing gradient — reuses the buttons' btn-grad-shift keyframe from styles.css
     (funnel pages load styles.css first). Hover matches the buttons' 1.5s; the
     selected day runs slower since it sits there permanently. */
  .fn-cal__day:hover:not(:disabled):not(.is-selected)::before {
    animation: btn-grad-shift 1.5s linear infinite;
  }
  .fn-cal__day.is-selected { animation: btn-grad-shift 3s linear infinite; }
  .fn-cal__grid.is-in { animation: fnCalIn 0.2s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
  @keyframes fnCalIn {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
  }
}

/* ---- Loading / error ---- */
.fn-loading {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text-muted);
  font-family: var(--font-body);
  font-size: 14px;
  padding: 8px 0;
}
.fn-spinner {
  width: 22px;
  height: 22px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: fnSpin 0.8s linear infinite;
}
@keyframes fnSpin { to { transform: rotate(360deg); } }
.fn-error {
  color: #ff6b6b;
  font-family: var(--font-body);
  font-size: 14px;
  margin: 10px 0;
}
.fn-error[hidden] { display: none; }
.fn-retry {
  margin-top: 8px;
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  font-family: var(--font-sub);
  font-size: 14px;
  padding: 8px 16px;
  cursor: pointer;
}
.fn-retry:hover { border-color: var(--accent); color: var(--accent); }

/* ---- Actions ---- */
.fn-actions { margin-top: 28px; }
.fn-actions .btn,
.fn-contact .btn {
  width: 100%;
  justify-content: center;
}
.btn.fn-is-loading { opacity: 0.7; pointer-events: none; }

/* ---- Confirmation ---- */
.fn-confirm {
  max-width: 560px;
  margin: 0 auto;
  padding: 44px var(--gutter) 96px;
  text-align: center;
}
.fn-confirm[hidden] { display: none; }
.fn-confirm__badge {
  width: 64px;
  height: 64px;
  margin: 0 auto 20px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-dim);
  border: 1px solid var(--accent);
  color: var(--accent);
  font-size: 30px;
}
.fn-confirm__title {
  font-family: var(--font-head);
  font-weight: 400;
  font-size: clamp(38px, 11vw, 52px);
  line-height: 1;
  margin-bottom: 8px;
}
.fn-confirm__sub {
  color: var(--text-muted);
  font-size: 15px;
  margin-bottom: 24px;
}
.fn-confirm__rows {
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 8px 18px;
  margin-bottom: 24px;
}
.fn-confirm__row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}
.fn-confirm__row:last-child { border-bottom: none; }
.fn-confirm__k {
  font-family: var(--font-sub);
  font-size: 13px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  flex: 0 0 auto;
}
.fn-confirm__v {
  font-family: var(--font-body);
  font-size: 15px;
  color: var(--text);
  text-align: right;
}
.fn-confirm__where {
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.6;
  color: var(--text);
  margin-bottom: 14px;
}
.fn-confirm__note {
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-muted);
}
.fn-confirm__note a { color: var(--accent); text-decoration: none; }

/* ---- Larger screens ---- */
@media (min-width: 480px) {
  .fn-cards--grid { grid-template-columns: repeat(3, 1fr); }
}

/* ---- Motion (opt-in) ---- */
@media (prefers-reduced-motion: no-preference) {
  .fn-step.is-active {
    animation: fnStepIn 0.35s cubic-bezier(0.16, 1, 0.3, 1) both;
  }
  @keyframes fnStepIn {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: none; }
  }
  .fn-confirm:not([hidden]) {
    animation: fnStepIn 0.4s cubic-bezier(0.16, 1, 0.3, 1) both;
  }
}

/* ---- SMS consent (final step of both funnels) ----
   Optional opt-in + the always-shown disclaimer. Both sit directly above the
   submit button. 13px floor so it stays readable on a phone. */
.fn-consent {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 18px 0 14px;
  cursor: pointer;
}
.fn-consent input[type="checkbox"] {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin: 2px 0 0;
  accent-color: var(--accent);   /* checked state uses the brand token */
  cursor: pointer;
}
.fn-consent input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.fn-consent__text {
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-muted);
}
.fn-consent:hover .fn-consent__text { color: var(--text); }

.fn-legal {
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-muted);
  margin-bottom: 16px;
}
.fn-legal a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.fn-legal a:hover { color: var(--accent-hover); }
