/* ==========================================================================
   Forms - the site-wide form system, built from the Figma input components
   (VNF (Copy), visitor page node 7028:33001).

   Global on purpose: every form on the site - visitor, booth registration,
   payment, comments - is built from these classes, so a field looks the same
   wherever it appears. Nothing here is page-specific; page sheets may only
   place these blocks, never restyle them.

   Anatomy of one field:

     .field-group          label + control + error, stacked
       .field-label        12px label, .req marks it required
       .field              the control itself (input / select / textarea)
       .field-error        message, only visible while .is-error is set

   Rows: wrap fields in .form-row (.form-row--2 for two columns).
   ========================================================================== */

/* --- Form shell ----------------------------------------------------------- */
.form-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  padding: var(--space-md);
  border: 1px solid var(--c-border-card);
  border-radius: var(--radius-card);
  background: var(--c-surface);

  @media (min-width: 768px) {
    padding: var(--space-lg);
  }
}

.form-card__title {
  font-weight: var(--fw-semibold);
  font-size: var(--fs-card-title);
  line-height: var(--lh-snug);
  letter-spacing: var(--ls-org);
  color: var(--c-ink-navy);
}

.form-fields {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

/* Buttons sit on their own row, right-aligned as in the design. */
.form-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--space-sm);

  .btn {
    width: 100%;

    @media (min-width: 1024px) {
      width: auto;
    }
  }
}

/* --- Rows ----------------------------------------------------------------- */
.form-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-md);
}

@media (min-width: 640px) {
  .form-row--2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .form-row--3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* --- One field ------------------------------------------------------------ */
.field-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  min-width: 0;
}

/* A .field-group is display:flex, and that beats the browser's own
   display:none for [hidden] - a field hidden by script would stay on screen. */
.field-group[hidden] {
  display: none;
}

/* A <legend> is rendered outside the <fieldset>'s content box, so it never
   picks up the flex gap - give it a matching margin instead. */
.field-group > legend {
  float: none;
  margin-bottom: var(--space-xs);
  padding: 0;
}

.field-label {
  font-weight: var(--fw-regular);
  font-size: var(--fs-label);
  line-height: var(--lh-label);
  letter-spacing: var(--ls-label);
  color: var(--c-label);
}

.field-label .req {
  color: var(--c-required);
}

/* --- The control ----------------------------------------------------------
   One shell for input / select / textarea and for anything that has to look
   like a field (the radio pills below reuse the same recipe). */
.field {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  width: 100%;
  min-height: var(--field-h);
  /* 9 + 20 + 9 + 2 borders = the design's 40px; Figma draws its stroke inside
     the 10px padding, so a literal 10px here makes the field 42px. */
  padding: 9px 11px;
  border: 1px solid transparent;
  border-radius: var(--radius-input);
  background: var(--c-field-bg);
  box-shadow: var(--shadow-field);
  font-family: var(--font-display);
  font-weight: var(--fw-medium);
  font-size: var(--fs-sm);
  line-height: var(--lh-copy);
  letter-spacing: var(--ls-field);
  color: var(--c-field-text);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

input.field,
select.field,
textarea.field {
  appearance: none;
  display: block;
}

textarea.field {
  min-height: 96px;
  line-height: var(--lh-body);
  resize: vertical;
}

.field::placeholder {
  color: var(--c-placeholder);
}

.field:hover {
  border-color: var(--c-border-light);
}

.field:focus,
.field:focus-within,
.field.is-focus {
  outline: none;
  border-color: var(--c-primary);
  box-shadow: var(--shadow-field-focus);
}

.field[disabled],
.field[readonly] {
  color: var(--c-ink-disabled);
  cursor: not-allowed;
}

.field.is-error,
.field-group.is-error .field {
  border-color: var(--c-danger);
}

/* --- Select ---------------------------------------------------------------
   appearance:none removes the native arrow, so the design's chevron is drawn
   as a background image. Until something is picked the control shows its
   placeholder <option>, which must read as placeholder text - hence the
   :invalid / .has-value pair (the placeholder option carries `disabled` and an
   empty value, so an untouched required select is :invalid). */
select.field {
  padding-right: 36px;
  background-image: url("../img/icon-chevron-select.svg");
  background-repeat: no-repeat;
  background-position: right 8px center;
  background-size: 20px 20px;
  cursor: pointer;
  color: var(--c-placeholder);
}

select.field:valid,
select.field.has-value {
  color: var(--c-field-text);
}

/* --- Error message --------------------------------------------------------
   Hidden until JS (or PHP) puts .is-error on the group. */
.field-error {
  display: none;
}

.field-group.is-error .field-error {
  display: flex;
  align-items: center;
  gap: var(--space-3xs);
  font-weight: var(--fw-medium);
  font-size: var(--fs-caption);
  line-height: var(--lh-normal);
  color: var(--c-danger);
}

.field-error img {
  width: 12px;
  height: 12px;
  flex: none;
}

/* --- Radio / checkbox pills -----------------------------------------------
   Each option is a field-shaped pill with the control inside it, so a row of
   choices lines up with the inputs above. */
.choice-set {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}

.choice-set--fill > .choice {
  flex: 1 1 0;
  min-width: 180px;
}

.choice {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  min-height: var(--field-h);
  padding: 9px 11px;
  border: 1px solid transparent;
  border-radius: var(--radius-input);
  background: var(--c-field-bg);
  box-shadow: var(--shadow-field);
  font-family: var(--font-display);
  font-weight: var(--fw-medium);
  font-size: var(--fs-sm);
  line-height: var(--lh-copy);
  letter-spacing: var(--ls-field);
  color: var(--c-label);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease);
}

.choice:hover {
  border-color: var(--c-border-light);
}

.choice:has(input:checked) {
  border-color: var(--c-primary-selected);
}

.choice__label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.choice input[type="radio"],
.choice input[type="checkbox"] {
  appearance: none;
  flex: none;
  width: 16px;
  height: 16px;
  margin: 0;
  border: 1px solid var(--c-border-radio);
  border-radius: var(--radius-pill);
  background: var(--c-surface);
  box-shadow: var(--shadow-radio);
  cursor: pointer;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.choice input[type="checkbox"] {
  border-radius: var(--radius-xs);
}

.choice input[type="radio"]:checked {
  border-color: transparent;
  background: var(--c-primary) radial-gradient(circle, var(--c-surface) 0 4px, transparent 4px);
}

.choice input[type="checkbox"]:checked {
  border-color: transparent;
  background: var(--c-primary);
}

.choice input:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
}

/* --- Status line ----------------------------------------------------------
   The confirmation shown after a submit. Empty and hidden until JS fills it,
   so it never leaves a gap in the card. */
.form-status {
  display: none;
}

.form-status.is-done {
  display: block;
  font-weight: var(--fw-medium);
  font-size: var(--fs-sm);
  line-height: var(--lh-copy);
  color: var(--c-primary);
}

.form-status.is-error {
  display: block;
  font-weight: var(--fw-medium);
  font-size: var(--fs-sm);
  line-height: var(--lh-copy);
  color: var(--c-danger);
}

/* Hidden iframe a form posts into when its endpoint is a third party. It still
   loads while display:none, which is what the submit handler listens for. */
.form-sink {
  display: none;
}

/* --- Country picker --------------------------------------------------------
   One component, two jobs: the dial-code picker glued to a phone input and the
   standalone "Quốc gia" select. Both are built from
   template-parts/form/country-pick.php, which is why they cannot drift apart.

   The <select> is the real control and stays native - the flag before it and
   the chevron after it are decoration. main.js swaps the flag on change.

   .field--composite is a .field that HOLDS controls rather than being one, so
   the shell keeps the border, background and focus ring while the input and
   the select inside it are bare. */
.field--composite {
  padding-block: 0;
  cursor: text;
}

.country-pick {
  display: flex;
  align-items: center;
  gap: var(--space-3xs);
  flex: none;
  min-width: 0;
  align-self: stretch;
}

/* The standalone select: it is the whole field, so it takes the width. */
.country-pick--wide {
  flex: 1 1 auto;
}

.country-pick__flag {
  display: grid;
  place-items: center;
  flex: none;
  width: 16px;
  height: 16px;
  overflow: hidden;
  border-radius: var(--radius-pill);
  /* A mostly-white flag (JP) would otherwise dissolve into the field. */
  box-shadow: inset 0 0 0 1px var(--c-border-light);
}

.country-pick__flag[hidden] {
  display: none;
}

.country-pick__flag img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.country-pick__select {
  appearance: none;
  flex: 1 1 auto;
  min-width: 0;
  max-width: 100%;
  padding: 0 24px 0 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  font: inherit;
  letter-spacing: inherit;
  color: var(--c-field-text);
  text-overflow: ellipsis;
  cursor: pointer;
}

.country-pick__select:focus {
  outline: none;
}

.country-pick__select:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}

/* Untouched required select still shows its disabled placeholder option, which
   has to read as placeholder text - same trick as select.field above. */
.country-pick__select:invalid {
  color: var(--c-placeholder);
}

/* --- Short mode: the picker beside a phone number --------------------------
   The field has room for two letters, the list has to name 249 countries and
   their dial codes, and one native <select> paints the same text in both
   places. So the select is laid over the display at zero opacity: the browser
   still draws its popup, the field shows the flag, code and chevron
   underneath. It stays a real select - keyboard, type-ahead and the mobile
   picker are all untouched. */
.country-pick--short {
  gap: var(--space-3xs);
}

.country-pick--short .country-pick__select {
  position: absolute;
  inset: 0;
  width: 100%;
  padding: 0;
  opacity: 0;
  /* Safari paints a shrunken control at opacity 0 otherwise. */
  appearance: none;
}

.country-pick__code {
  font: inherit;
  letter-spacing: inherit;
  color: var(--c-field-text);
  white-space: nowrap;
}

/* The chevron belongs in the flow here - it sits right after the code, not at
   the far edge of a field the picker does not own. */
.country-pick--short .country-pick__caret {
  position: static;
  transform: none;
}

/* The select is invisible, so the focus ring has to be drawn by the shell. */
.country-pick--short:has( .country-pick__select:focus-visible ) {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}

.country-pick__caret {
  position: absolute;
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  flex: none;
  width: 16px;
  height: 16px;
  pointer-events: none;
}

.country-pick__caret img {
  width: 100%;
  height: 100%;
}

/* The design boxes the chevron of the standalone select in a grey tile. */
.country-pick__caret--boxed {
  width: 24px;
  height: 24px;
  padding: var(--space-3xs);
  border-radius: var(--radius-xs);
  background: var(--c-caret-box);
  margin-left: auto;
}

/* --- Phone field ----------------------------------------------------------
   Country picker + number in one shell. One value is submitted: main.js joins
   the picked dial code to the number on submit, so `<name>` carries the whole
   international number and the picker has no name of its own. */
.phone-field__number {
  appearance: none;
  flex: 1 1 auto;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  font: inherit;
  letter-spacing: inherit;
  color: var(--c-field-text);
}

.phone-field__number:focus {
  outline: none;
}

.phone-field__number::placeholder {
  color: var(--c-placeholder);
}

.country-pick {
  position: relative;
}
