/* ht-kit — quote.css
   Layer 2 component. Reads the token contract only.
   No literal colour, font name or pixel value belongs in this file. */

.quote{
  --step-travel:var(--space-5);
  position:relative;
  width:100%;
  max-width:var(--measure);
  margin-inline:auto;
  padding-block:var(--space-6) var(--space-7);
}

/* ---------- progress ---------- */

.quote .quote__progress{
  position:sticky;
  top:0;
  z-index:2;
  height:calc(var(--border) * 3);
  margin-bottom:var(--space-6);
  background:var(--rule);
  border-radius:var(--border);
  overflow:hidden;
}

.quote .quote__bar{
  display:block;
  height:100%;
  background:var(--accent);
  transform:scaleX(0);
  transform-origin:left center;
  transition:transform var(--dur-base) var(--ease);
}

/* Without the enhancement the bar is meaningless. */
.quote:not(.is-enhanced) .quote__progress{display:none}

/* ---------- step stack ---------- */

/* Default state is every step stacked and readable. The one at a time
   behaviour is added by JS, never assumed. */
.quote .quote__steps{display:grid;gap:var(--space-8)}

.quote.is-enhanced .quote__steps{gap:0}

.quote.is-enhanced .step{
  grid-area:1 / 1;
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transition:
    opacity var(--dur-base) var(--ease),
    transform var(--dur-base) var(--ease),
    visibility 0s linear var(--dur-base);
}

.quote.is-enhanced .step[data-pos="ahead"]{transform:translateX(var(--step-travel))}
.quote.is-enhanced .step[data-pos="behind"]{transform:translateX(calc(var(--step-travel) * -1))}

.quote.is-enhanced .step[data-pos="here"]{
  opacity:1;
  visibility:visible;
  pointer-events:auto;
  transform:none;
  transition:
    opacity var(--dur-base) var(--ease),
    transform var(--dur-base) var(--ease),
    visibility 0s linear 0s;
}

@media (prefers-reduced-motion:reduce){
  .quote.is-enhanced .step,
.quote.is-enhanced .step[data-pos="here"],
.quote .quote__bar{transition:none}
  .quote.is-enhanced .step[data-pos="ahead"],
.quote.is-enhanced .step[data-pos="behind"]{transform:none}
}

/* ---------- question ---------- */

.quote .step__count{display:block;margin-bottom:var(--space-2)}

.quote .step__q{
  font-size:var(--step-3);
  margin-bottom:var(--space-5);
}
.quote .step__q:focus{outline:none}
.quote .step__q:focus-visible{
  outline:calc(var(--border) * 2) solid var(--accent);
  outline-offset:var(--space-2);
}

.quote .step__hint{
  margin-top:calc(var(--space-5) * -1 + var(--space-2));
  margin-bottom:var(--space-5);
  color:var(--muted);
  font-size:var(--step--1);
}

/* ---------- options ---------- */

.quote .step__options{display:grid;gap:var(--space-3)}

.quote .option{
  position:relative;
  display:flex;
  align-items:center;
  gap:var(--space-3);
  width:100%;
  min-height:var(--tap);
  padding:var(--space-3) var(--space-4);
  border:var(--border) solid var(--rule-strong);
  border-radius:var(--radius);
  background:var(--surface);
  cursor:pointer;
  transition:
    border-color var(--dur-fast) var(--ease),
    transform var(--dur-fast) var(--ease);
}
.quote .option:hover{border-color:var(--accent)}
.quote .option:active{transform:scale(0.99)}

.quote .option__input{
  position:absolute;
  width:var(--border);height:var(--border);
  margin:calc(var(--border) * -1);
  opacity:0;
  clip-path:inset(50%);
}

.quote .option__key{
  flex:0 0 auto;
  display:grid;
  place-items:center;
  width:var(--space-6);
  height:var(--space-6);
  border:var(--border) solid var(--rule-strong);
  border-radius:calc(var(--radius) / 2);
  color:var(--muted);
  font-family:var(--font-utility);
  font-size:var(--step--1);
  font-variant-numeric:tabular-nums;
  transition:
    background-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}

.quote .option__label{flex:1 1 auto}

.quote .option__input:checked ~ .option__key{
  background:var(--accent);
  border-color:var(--accent);
  color:var(--accent-ink);
}

.quote .option:has(.option__input:checked){border-color:var(--accent)}

.quote .option__input:focus-visible ~ .option__key{
  outline:calc(var(--border) * 2) solid var(--accent);
  outline-offset:calc(var(--border) * 2);
}

/* Fallback for browsers without :has(). The outline still lands. */
@supports not selector(:has(*)){
  .quote .option__input:focus-visible ~ .option__label{text-decoration:underline}
}

/* ---------- quantity ---------- */

.quote .qty{
  display:flex;
  align-items:center;
  gap:var(--space-3);
}

.quote .qty__btn{
  flex:0 0 auto;
  width:var(--tap);
  height:var(--tap);
  display:grid;
  place-items:center;
  border:var(--border) solid var(--rule-strong);
  border-radius:var(--radius);
  background:var(--surface);
  font-size:var(--step-1);
  line-height:1;
  cursor:pointer;
  transition:border-color var(--dur-fast) var(--ease);
}
.quote .qty__btn:hover:not(:disabled){border-color:var(--accent)}
.quote .qty__btn:disabled{opacity:0.4;cursor:not-allowed}

.quote .qty__field{
  flex:0 1 auto;
  width:var(--space-8);
  min-height:var(--tap);
  padding:var(--space-2) var(--space-3);
  border:var(--border) solid var(--rule-strong);
  border-radius:var(--radius);
  background:var(--surface);
  font-size:var(--step-1);
  font-variant-numeric:tabular-nums;
  text-align:center;
}

.quote .qty__unit{color:var(--muted)}

/* ---------- result ---------- */

.quote .quote__range{
  font-size:var(--step-4);
  font-variant-numeric:tabular-nums;
  margin-bottom:var(--space-3);
}

.quote .quote__small{
  color:var(--muted);
  font-size:var(--step--1);
  max-width:var(--measure);
  margin-bottom:var(--space-6);
}

.quote .quote__breakdown{
  display:grid;
  gap:var(--space-2);
  margin-bottom:var(--space-6);
  padding-top:var(--space-4);
  border-top:var(--border) solid var(--rule);
  font-size:var(--step--1);
}
.quote .quote__breakdown div{
  display:flex;
  justify-content:space-between;
  gap:var(--space-4);
}
.quote .quote__breakdown dt{color:var(--muted)}
.quote .quote__breakdown dd{margin:0;text-align:right}

/* ---------- fields ---------- */

.quote .field{display:grid;gap:var(--space-2);margin-bottom:var(--space-4)}

.quote .field__label{
  font-family:var(--font-utility);
  font-size:var(--step--1);
  font-weight:600;
}
.quote .field__note{font-weight:400;color:var(--muted)}

.quote .field__input{
  width:100%;
  min-height:var(--tap);
  padding:var(--space-3) var(--space-4);
  border:var(--border) solid var(--rule-strong);
  border-radius:var(--radius);
  background:var(--surface);
  transition:border-color var(--dur-fast) var(--ease);
}
.quote .field__input:hover{border-color:var(--accent)}

/* ---------- actions ---------- */

.quote .step__actions{display:flex;gap:var(--space-3);margin-top:var(--space-5)}

.quote .quote__back{
  margin-top:var(--space-6);
  padding:var(--space-2) 0;
  min-height:var(--tap);
  border:0;
  background:none;
  color:var(--muted);
  font-family:var(--font-utility);
  font-size:var(--step--1);
  cursor:pointer;
  text-decoration:underline;
  text-underline-offset:0.2em;
}
.quote .quote__back:hover{color:var(--ink)}

/* Honeypot. Off screen rather than display:none so a bot still finds it. */
.quote .hp{
  position:absolute;
  left:-100vw;
  width:var(--border);height:var(--border);
  opacity:0;
}

/* ---------- fallback ---------- */

.quote.is-fallback{
  padding-block:var(--space-6);
}
.quote .quote__note{
  padding:var(--space-4);
  margin-bottom:var(--space-5);
  border:var(--border) solid var(--rule);
  border-radius:var(--radius);
  background:var(--surface);
  color:var(--muted);
  font-size:var(--step--1);
}

/* ---------- phone ---------- */

@media (max-width:767px){
  .quote{padding-block:var(--space-5) var(--space-6)}
  .quote .option{padding:var(--space-4)}
  .quote .step__actions{flex-direction:column}
  .quote .step__actions .btn{width:100%}
}

/* ---------- text and textarea steps ---------- */

.quote .field__input--tall{
  min-height:calc(var(--tap) * 3);
  padding:var(--space-3) var(--space-4);
  line-height:var(--lh-body);
  resize:vertical;
}

/* ---------- photo step ---------- */

/* Clipped rather than display:none, so it keeps its place in the tab order
   and the styled label can show its focus ring. */
.quote .photo__input{
  position:absolute;
  width:var(--border);height:var(--border);
  margin:calc(var(--border) * -1);
  opacity:0;
  clip-path:inset(50%);
}

.quote .photo__add{margin-top:var(--space-3)}
.quote .photo__input:focus-visible + .photo__thumbs + .photo__add,
.quote .photo__input:focus-visible ~ .photo__add{
  outline:calc(var(--border) * 2) solid var(--accent);
  outline-offset:calc(var(--border) * 2);
}

.quote .photo__thumbs{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(var(--space-8),1fr));
  gap:var(--space-3);
}
.quote .photo__thumbs:empty{display:none}

.quote .thumb{
  position:relative;
  aspect-ratio:1;
  border:var(--border) solid var(--rule-strong);
  border-radius:var(--radius);
  overflow:hidden;
  background:var(--surface);
}

.quote .thumb__img{width:100%;height:100%;object-fit:cover}

.quote .thumb__drop{
  position:absolute;
  top:var(--space-1);
  right:var(--space-1);
  width:var(--space-6);
  height:var(--space-6);
  display:grid;
  place-items:center;
  border:0;
  border-radius:50%;
  background:var(--ink);
  color:var(--paper);
  font-size:var(--step-0);
  line-height:1;
  cursor:pointer;
  opacity:0.82;
  transition:opacity var(--dur-fast) var(--ease);
}
.quote .thumb__drop:hover{opacity:1}

/* ---------- hidden field bag ---------- */

.quote .quote__bag{display:contents}

/* ---------- done step, demo mode ---------- */

.quote .step--done .step__q{margin-bottom:var(--space-3)}

/* ---------- peek layout ---------- */

/* The frame clips the track sideways. overflow-x:clip rather than hidden,
   because hidden on one axis computes the other to auto, which would cut the
   focus ring off the top of a card. */
.quote.is-peek .quote__frame{
  overflow-x:clip;
  overflow-y:visible;
  overflow-clip-margin:var(--space-3);
}

.quote.is-peek .quote__steps{
  --peek-at:0;
  --peek-card:85%;
  display:grid;
  grid-auto-flow:column;
  grid-auto-columns:var(--peek-card);
  gap:var(--space-4);
  transform:translateX(calc(-1 * var(--peek-at) * (var(--peek-card) + var(--space-4))));
  transition:transform var(--dur-base) var(--ease);
}

/* Every card stays painted, so the stack rules that hide the inactive ones
   have to be undone rather than inherited. */
.quote.is-peek .step,
.quote.is-peek .step[data-pos="ahead"],
.quote.is-peek .step[data-pos="behind"],
.quote.is-peek .step[data-pos="here"]{
  grid-area:auto;
  opacity:1;
  visibility:visible;
  transform:none;
  transition:opacity var(--dur-base) var(--ease);
}

.quote.is-peek .step{
  display:flex;
  flex-direction:column;
  min-height:calc(var(--space-8) * 5);
  padding:var(--space-5);
  background:var(--surface);
  border:var(--border) solid var(--rule-strong);
  border-radius:var(--radius-lg);
}

/* The card you are not on reads as further away without moving. */
.quote.is-peek .step:not([data-pos="here"]){opacity:0.45}

.quote.is-peek .step__actions{margin-top:auto}

/* ---------- peek controls ---------- */

.quote .quote__nav{
  display:flex;
  justify-content:flex-end;
  gap:var(--space-3);
  margin-top:var(--space-5);
}

.quote .quote__nav-btn{
  width:var(--tap);
  height:var(--tap);
  display:grid;
  place-items:center;
  padding:0;
  border:var(--border) solid var(--rule-strong);
  border-radius:50%;
  background:var(--surface);
  color:var(--ink);
  cursor:pointer;
  transition:
    border-color var(--dur-fast) var(--ease),
    opacity var(--dur-fast) var(--ease);
}
.quote .quote__nav-btn:hover:not(:disabled){border-color:var(--accent)}
.quote .quote__nav-btn:disabled{opacity:0.35;cursor:not-allowed}

.quote .quote__nav-btn svg{
  width:var(--space-5);
  height:var(--space-5);
  fill:none;
  stroke:currentColor;
  stroke-width:2;
  stroke-linecap:round;
  stroke-linejoin:round;
}

/* Instant swap, and no peek offset, so nothing slides and nothing half shows. */
@media (prefers-reduced-motion:reduce){
  .quote.is-peek .quote__steps{--peek-card:100%;transition:none}
  .quote.is-peek .step{transition:none}
  .quote.is-peek .step:not([data-pos="here"]){opacity:1}
}

@media (max-width:767px){
  .quote.is-peek .quote__steps{--peek-card:86%}
  .quote.is-peek .step{padding:var(--space-4)}
}

/* ---------- field validation ---------- */

/* Empty while the value is fine, so it takes no room and the live region is
   still in the tree ready to announce. */
.quote .field__error{
  margin-top:var(--space-2);
  font-size:var(--step--1);
  line-height:var(--lh-body);
  color:var(--accent);
}
.quote .field__error:empty{display:none}

/* Doubling the border rather than changing its colour alone, so the state
   does not rely on a hue nobody can see at 1px. */
.quote .field__input[aria-invalid="true"]{
  border-color:var(--accent);
  box-shadow:inset 0 0 0 var(--border) var(--accent);
}
