/* ==========================================================================
   Pan D Endz : reserve.css
   The reservation request form, built by PDE.reserve.mount() into the
   #reserve section between Visit and the footer.

   Scope: every rule starts inside .rv, the wrapper mount() builds, so nothing
   here can leak into the after-film or into a concept's own film styles.
   World: dark. #reserve carries data-tone="dark", so base.css has already set
   the background, the text colour, the muted colour and the gold focus ring
   before a single rule below runs.
   Names: BEM, .rv__<element>, state classes .is-*.
   Values: tokens only. No raw colour, size or easing is written by hand.
   Order: mobile first. Wider screens are added in min-width blocks.
   ========================================================================== */

/* ------------------------------------------------------------------ LAYOUT
   One column on a phone. Two side by side once there is room: the reason to
   call on the left, the form on the right. */

.rv {
  display: grid;
  gap: var(--s-6);
  padding: var(--s-7) var(--gutter);
}

.rv__left > .kicker {
  margin: 0 0 var(--s-2);
  color: var(--gold);
}

.rv__title {
  margin: 0;
}

.rv__body {
  /* 40ch, the same tighter measure the landing and visit blocks use: this is
     one spoken line, not a paragraph of reading. */
  max-width: 40ch;
  margin: var(--s-3) 0 0;
  color: var(--cream-muted);          /* 10.1:1 on char */
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}

/* The number, still the first and fastest way to book a table. Set in Fraunces
   at display size so it reads as the headline answer and the form reads as the
   second option, exactly as the Visit block does it one section up. */
.rv__phone {
  display: inline-block;
  margin: var(--s-4) 0 0;
  color: var(--gold);                 /* 12.4:1 on char */
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-d3);
  font-variation-settings: var(--fraunces-soft);
  line-height: 1;
  letter-spacing: var(--track-display);
  text-decoration: none;
}

.rv__phone:hover {
  text-decoration: underline;
  text-underline-offset: 0.12em;
}

/* The same link at body size, under a failure message or a confirmation. */
.rv__phone--small {
  margin-top: var(--s-3);
  font-size: var(--fs-d3);
}

/* -------------------------------------------------------------------- FORM
   A self sizing grid: as many 14rem columns as fit, which means one column on
   a phone and two on anything wider, with no media query to keep in step with
   the outer layout.

   color-scheme: dark is the whole reason the native date picker, the dropdown
   list a select opens and the text caret all come up dark instead of glaring
   white. It is a hint to the browser, not a colour, so nothing is hard-coded. */

.rv__form {
  position: relative;                 /* the honeypot is parked against this */
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--s-3) var(--s-2);
  color-scheme: dark;
}

/* The fields that always want the full width: a name, the special requests
   box, the bot check and the button. */
.rv__field--wide,
.rv__turnstile,
.rv__submit {
  grid-column: 1 / -1;
}

.rv__field {
  display: grid;
  align-content: start;
  gap: var(--s-1);
}

/* Labels are always visible and always above the box. There are no
   placeholders anywhere in this form: a placeholder disappears the moment
   somebody starts typing, which is exactly when they need it. */
.rv__label {
  color: var(--cream);                /* 17.5:1 on char */
  font-size: var(--fs-small);
  font-weight: 600;
  line-height: 1.3;
}

.rv__hint {
  max-width: none;
  margin: 0;
  color: var(--cream-muted);          /* 10.1:1 on char */
  font-size: var(--fs-small);
  line-height: 1.4;
}

/* --------------------------------------------------------------- CONTROLS */

.rv__control {
  position: relative;
}

/* The border is the only thing that says where the box is, because the box has
   no fill of its own. That makes it a user interface component boundary under
   WCAG 1.4.11, which asks for 3:1 against what is behind it.

   --cream-muted on --char is 10.1:1. The hairline --cork used elsewhere in the
   dark world is 1.72:1, which is fine for the decorative dividers it draws in
   afterfilm.css and not fine for this. Director ruling, 2026-09-20. */
.rv__input {
  width: 100%;
  min-height: 48px;                   /* comfortably past the 44px tap target */
  padding: 0.6rem 0.9rem;
  border: 1px solid var(--cream-muted);
  border-radius: 0;                   /* the only rounded shapes on this site
                                         are pills and 6px price tags */
  background: transparent;
  color: var(--cream);
  font-family: var(--font-body);
  /* 16px exactly. Anything smaller and iOS Safari zooms the whole page in when
     the box takes focus, which throws the visitor out of the layout. */
  font-size: 1rem;
  line-height: 1.4;
  transition: border-color var(--t-fast) var(--ease-smoke);
}

/* Up to full cream, 17.5:1, so the box under the pointer is obvious without
   changing colour family. */
.rv__input:hover {
  border-color: var(--cream);
}

/* base.css already draws the 2px gold ring on :focus-visible. This lifts the
   border out of the hairline at the same moment so the box itself reads as the
   live one, not just the ring around it. */
.rv__input:focus {
  border-color: var(--gold);
  outline-offset: 3px;
}

/* A select the browser has drawn itself cannot be given a transparent
   background, so the arrow is ours: two borders turned 45 degrees, in
   currentColor, so it follows the theme like everything else. */
.rv__select {
  padding-right: 2.75rem;
  appearance: none;
  -webkit-appearance: none;
}

.rv__control--select::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 1.1rem;
  width: 0.5rem;
  height: 0.5rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
}

/* A shut day has no times to offer. Said with a dashed edge and the muted
   colour rather than with a drop in opacity, because opacity alone is both a
   contrast risk and a state nobody can see. The message under the date field
   is what actually explains it. */
.rv__input:disabled {
  border-style: dashed;
  color: var(--cream-muted);
  cursor: not-allowed;
}

.rv__control--select:has(.rv__input:disabled)::after {
  color: var(--cream-muted);
}

.rv__textarea {
  min-height: 7rem;
  resize: vertical;
}

/* Digits and a slash, so there is nothing here to translate. Tabular figures
   stop the line jittering as the count climbs. */
.rv__counter {
  max-width: none;
  margin: 0;
  color: var(--cream-muted);
  font-family: var(--font-sign);
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* ------------------------------------------------------------------ ERRORS
   Gold, 12.4:1 on char, and never colour on its own: every message is led by a
   bold "!" and tied to its box with aria-describedby and aria-invalid. There is
   no red in this palette that passes on char, which is why gold does this job.
   The glyph is marked aria-hidden, so a screen reader hears the sentence and
   not the punctuation. */

.rv__err,
.rv__failed {
  display: flex;
  gap: 0.4em;
  max-width: none;
  margin: 0;
  color: var(--gold);
  font-size: var(--fs-small);
  line-height: 1.4;
}

.rv__bang {
  flex: none;
  font-family: var(--font-sign);
  line-height: 1.3;
}

/* The box that is being complained about. An inset line doubles the gold edge
   without moving anything by a pixel. */
.rv__input[aria-invalid="true"] {
  border-color: var(--gold);
  box-shadow: inset 0 0 0 1px var(--gold);
}

/* ---------------------------------------------------------------- HONEYPOT
   In the page, out of the layout, off the screen, out of the tab order and out
   of the accessibility tree. Anything typed in here was typed by a script. */

.rv__hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ------------------------------------------------------------------ BUTTON */

.rv__submit {
  justify-self: start;
  margin-top: var(--s-2);
}

/* Still gold on char at 12.4:1 while it sends: dimming a disabled button is the
   usual move and it is the one thing this palette will not allow. The changed
   word and the cursor carry the state instead. */
.rv__submit:disabled {
  cursor: progress;
}

.rv__submit:disabled:hover {
  transform: none;
}

/* ------------------------------------------------------------------ ANSWER
   One polite live region holds both answers: the failure line while the form is
   still standing, and the whole confirmation once it has gone. */

.rv__status:not(:empty) {
  margin-top: var(--s-4);
}

.rv__done {
  display: grid;
  justify-items: start;
  gap: var(--s-2);
  padding: var(--s-4);
  border: 1px solid var(--cork);
  background: var(--coal);            /* cream on coal is 14.9:1 */
}

.rv__donetitle {
  margin: 0;
  color: var(--gold);                 /* 10.6:1 on coal */
}

.rv__donetitle:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

/* The line that has to be read: a request is not a booking until the
   restaurant replies. Cream rather than muted, because this is the point. */
.rv__donebody {
  margin: 0;
  max-width: 44ch;
  color: var(--cream);                /* 14.9:1 on coal */
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}

.rv__failed {
  font-size: var(--fs-body);
}

/* -------------------------------------------------------------- TURNSTILE
   Inert until site.json carries business.turnstileSiteKey, which it does not.
   The rule only reserves the row so the button never jumps when it appears. */

.rv__turnstile:not(:empty) {
  margin-top: var(--s-1);
}

/* ====================================================== WIDER SCREENS ONLY */

@media (min-width: 900px) {
  .rv {
    grid-template-columns: 1fr 1fr;
    gap: var(--s-7);
    align-items: start;
  }
}

/* ========================================================== REDUCED MOTION
   The only thing in here that moves is the border colour fading in on hover
   and focus. It stops moving and simply changes. */

@media (prefers-reduced-motion: reduce) {
  .rv__input {
    transition: none;
  }
}
