/* ════════════════════════════════════════════════════════════════════
   bdyna-forms.css — Layer 4 of 5. Requires tokens + layout.

   Every control is at least 44px tall, every label is visible, and every
   error is announced as well as shown. Placeholder text is never the label:
   it disappears on focus, which strands anyone who looks away mid-entry.
   ════════════════════════════════════════════════════════════════════ */

.bd-form{display:flex;flex-direction:column;gap:var(--bd-s-5)}
.bd-fieldset{border:1px solid var(--bd-border);border-radius:var(--bd-r);
  padding:var(--bd-s-5);margin:0}
.bd-fieldset > legend{font-size:var(--bd-fs-h4);font-weight:var(--bd-w-bold);
  padding:0 var(--bd-s-2);color:var(--bd-fg)}
.bd-form-section{margin-bottom:var(--bd-s-8)}
.bd-form-section__title{font-size:var(--bd-fs-h3);font-weight:var(--bd-w-bold);
  margin:0 0 var(--bd-s-1)}
.bd-form-section__hint{font-size:var(--bd-fs-small);color:var(--bd-fg-muted);
  margin:0 0 var(--bd-s-5);max-width:var(--bd-measure)}

.bd-field{display:flex;flex-direction:column;gap:var(--bd-s-2)}
.bd-label{font-size:var(--bd-fs-small);font-weight:var(--bd-w-semi);color:var(--bd-fg)}
.bd-label .bd-req{color:var(--bd-error);margin-left:3px}
/* "(optional)" beats a required asterisk when most fields are required,
   but both are supported because forms differ. */
.bd-label .bd-opt{color:var(--bd-fg-muted);font-weight:var(--bd-w-normal);margin-left:5px}
.bd-help{font-size:var(--bd-fs-small);color:var(--bd-fg-muted);line-height:var(--bd-lh-normal);
  max-width:var(--bd-measure)}

.bd-input,.bd-select,.bd-textarea{
  width:100%;min-height:var(--bd-touch-min);
  padding:var(--bd-s-3) var(--bd-s-4);
  font-size:var(--bd-fs-body);   /* 16px — anything smaller makes iOS zoom */
  font-family:inherit;line-height:var(--bd-lh-normal);
  color:var(--bd-fg);background:var(--bd-surface);
  border:1px solid var(--bd-border);border-radius:var(--bd-r-sm);
  transition:border-color var(--bd-t) var(--bd-ease);
}
[data-bd-theme="light"] .bd-input,
[data-bd-theme="light"] .bd-select,
[data-bd-theme="light"] .bd-textarea{background:var(--bd-paper)}
.bd-textarea{min-height:120px;resize:vertical}
.bd-select{appearance:none;padding-right:var(--bd-s-10);
  background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),
                   linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-position:calc(100% - 20px) 52%,calc(100% - 14px) 52%;
  background-size:6px 6px,6px 6px;background-repeat:no-repeat}
.bd-input::placeholder,.bd-textarea::placeholder{color:var(--bd-fg-muted);opacity:.75}
.bd-input:hover,.bd-select:hover,.bd-textarea:hover{border-color:var(--bd-fg-muted)}
.bd-input:disabled,.bd-select:disabled,.bd-textarea:disabled{opacity:.55;cursor:not-allowed}
.bd-input[readonly]{background:var(--bd-surface-2);cursor:default}

/* Error and success. Colour alone never carries the meaning — the message
   text and aria-describedby do. */
.bd-input[aria-invalid="true"],.bd-select[aria-invalid="true"],.bd-textarea[aria-invalid="true"]{
  border-color:var(--bd-error);background:var(--bd-error-bg)}
.bd-input.is-valid,.bd-select.is-valid,.bd-textarea.is-valid{border-color:var(--bd-ok)}
.bd-msg{display:flex;align-items:flex-start;gap:6px;font-size:var(--bd-fs-small);
  line-height:var(--bd-lh-normal)}
.bd-msg--error{color:var(--bd-error)}
.bd-msg--ok{color:var(--bd-ok)}
.bd-msg--error::before{content:"\26A0";flex:0 0 auto}
.bd-msg--ok::before{content:"\2713";flex:0 0 auto}

/* Error summary — focusable, at the top, listing every failure as a link
   to the field. This is the single biggest accessibility win on a form. */
.bd-error-summary{border:1px solid var(--bd-error-line);background:var(--bd-error-bg);
  border-radius:var(--bd-r);padding:var(--bd-s-5);margin-bottom:var(--bd-s-6)}
.bd-error-summary__title{font-size:var(--bd-fs-h4);font-weight:var(--bd-w-bold);
  color:var(--bd-error);margin:0 0 var(--bd-s-3)}
.bd-error-summary ul{margin:0;padding-left:var(--bd-s-5)}
.bd-error-summary li{margin-bottom:var(--bd-s-2);font-size:var(--bd-fs-small)}
.bd-error-summary a{color:var(--bd-error)}

/* Radio and checkbox — the whole row is the target, so it clears 44px. */
.bd-choices{display:flex;flex-direction:column;gap:var(--bd-s-2)}
.bd-choices--inline{flex-direction:row;flex-wrap:wrap;gap:var(--bd-s-4)}
.bd-choice{display:flex;align-items:flex-start;gap:var(--bd-s-3);
  min-height:var(--bd-touch-min);padding:var(--bd-s-2) var(--bd-s-3);
  border:1px solid var(--bd-border);border-radius:var(--bd-r-sm);
  cursor:pointer;font-size:var(--bd-fs-small);line-height:var(--bd-lh-normal)}
.bd-choice:hover{border-color:var(--bd-fg-muted)}
.bd-choice input{margin-top:2px;width:18px;height:18px;flex:0 0 auto;
  accent-color:var(--bd-gold);cursor:pointer}
.bd-choice:has(input:checked){border-color:var(--bd-gold);background:rgba(255,215,0,.07)}
.bd-choice__label{font-weight:var(--bd-w-semi);color:var(--bd-fg)}
.bd-choice__hint{display:block;color:var(--bd-fg-muted);font-weight:var(--bd-w-normal);margin-top:2px}

.bd-form-actions{display:flex;gap:var(--bd-s-3);flex-wrap:wrap;align-items:center;
  padding-top:var(--bd-s-4);border-top:1px solid var(--bd-border)}
.bd-form-actions--end{justify-content:flex-end}

/* A honeypot must be hidden from sight but reachable by a bot, and never
   announced or focusable for a real person. */
.bd-hp{position:absolute!important;left:-9999px!important;width:1px;height:1px;
  overflow:hidden;opacity:0;pointer-events:none}
