/* ============================================================================
   hello-design · forms primitives
   ----------------------------------------------------------------------------
   Token-only stylesheet. Every color, dimension, radius, motion, type-scale,
   and font-weight resolves through a CSS custom property declared in
   src/tokens/_global.css or the per-brand color map in src/brands.js. Run
   `node tools/lint-tokens.js --file src/forms.css` to verify drift.
   ========================================================================== */

/* -------------------------------------------------------------- Forms grid */

.forms-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--grid-tile-2xl), 1fr));
  gap: var(--space-6);
}

/* -------------------------------------------------------------- Card tile */

.fm-card {
  border: var(--border-1) solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  padding: var(--space-5) var(--space-5) var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.fm-card-label {
  font-size: var(--type-scale-sm);
  text-transform: uppercase;
  letter-spacing: var(--letter-wider);
  color: var(--color-fg-subtle);
  font-weight: var(--font-weight-semibold);
}
.fm-card-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.fm-card-caption {
  font-size: var(--type-scale-xs);
  color: var(--color-fg-subtle);
  letter-spacing: var(--letter-wide);
  margin-top: auto;
  padding-top: var(--space-2);
  border-top: var(--border-1) solid var(--color-border);
}

/* -------------------------------------------------------------- Field shell */

.fm-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}
.fm-label {
  font-size: var(--type-scale-xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg-muted);
  letter-spacing: var(--letter-wide);
}
.fm-helper {
  font-size: var(--type-scale-xs);
  color: var(--color-fg-subtle);
  line-height: var(--line-height-normal);
  margin-top: var(--space-1);
}
.fm-helper-hint {
  color: var(--color-fg-muted);
}
.fm-helper-error {
  color: var(--color-danger);
  font-weight: var(--font-weight-medium);
}

/* -------------------------------------------------------------- Inputs */

.fm-input,
.fm-textarea,
.fm-select {
  font-family: var(--type-body);
  font-size: var(--type-scale-md);
  font-weight: var(--font-weight-regular);
  line-height: var(--line-height-normal);
  color: var(--color-fg);
  background: var(--color-bg);
  border: var(--border-1) solid var(--color-border-strong);
  border-radius: var(--radius);
  padding: var(--space-2) var(--space-3);
  outline: none;
  width: 100%;
  transition:
    border-color var(--motion-dur) var(--motion-ease),
    box-shadow   var(--motion-dur) var(--motion-ease),
    background   var(--motion-dur) var(--motion-ease);
}
.fm-input::placeholder,
.fm-textarea::placeholder {
  color: var(--color-fg-subtle);
}
.fm-input:hover,
.fm-textarea:hover,
.fm-select:hover {
  border-color: var(--color-fg-muted);
}
.fm-input:focus,
.fm-input.is-focused,
.fm-textarea:focus,
.fm-select:focus {
  border-color: var(--color-focus-ring);
  box-shadow: 0 0 0 var(--border-3)
    color-mix(in srgb, var(--color-focus-ring) 30%, transparent);
}
.fm-input:disabled,
.fm-textarea:disabled,
.fm-select:disabled {
  color: var(--color-fg-subtle);
  background: var(--color-surface-hover);
  border-color: var(--color-border);
  cursor: not-allowed;
}

/* Error variant — applied via `.fm-field.is-error` so the message + control
   stay visually correlated. */
.fm-field.is-error .fm-input,
.fm-field.is-error .fm-textarea,
.fm-field.is-error .fm-select {
  border-color: var(--color-danger);
  background: color-mix(in srgb, var(--color-danger) 6%, var(--color-bg));
}
.fm-field.is-error .fm-input:focus,
.fm-field.is-error .fm-textarea:focus,
.fm-field.is-error .fm-select:focus {
  box-shadow: 0 0 0 var(--border-3)
    color-mix(in srgb, var(--color-danger) 28%, transparent);
}

/* Textarea-specific tweaks. */
.fm-textarea {
  min-height: var(--space-10);
  resize: vertical;
}

/* Native select chevron — pure CSS gradient mask using token-driven currentColor
   so the chevron tints with the surrounding text color without inline SVG. */
.fm-select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: var(--space-7);
  background-image:
    linear-gradient(45deg,  transparent 50%, currentColor 50%),
    linear-gradient(-45deg, transparent 50%, currentColor 50%);
  background-position:
    calc(100% - var(--space-4)) 55%,
    calc(100% - var(--space-3)) 55%;
  background-size: var(--space-1) var(--space-1), var(--space-1) var(--space-1);
  background-repeat: no-repeat;
}

/* -------------------------------------------------------------- Input wrap
   Wrap that hosts a leading icon (canvas) and/or a trailing affordance
   (clear button) inside the same visual frame as a regular input. */

.fm-input-wrap {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
}
.fm-input-glyph {
  position: absolute;
  left: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
  pointer-events: none;
  color: var(--color-fg-muted);
}
.fm-input-with-leading {
  padding-left: var(--space-8);
}
.fm-input-with-trailing {
  padding-right: var(--space-8);
}
.fm-input-clear {
  position: absolute;
  right: var(--space-2);
  top: 50%;
  transform: translateY(-50%);
  width: var(--space-6);
  height: var(--space-6);
  display: grid;
  place-items: center;
  border: 0;
  background: transparent;
  color: var(--color-fg-muted);
  font-size: var(--type-scale-lg);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-tight);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition:
    background var(--motion-dur-fast) var(--motion-ease-standard),
    color      var(--motion-dur-fast) var(--motion-ease-standard);
}
.fm-input-clear:hover {
  background: var(--color-surface-hover);
  color: var(--color-fg);
}
.fm-input-clear:focus-visible {
  outline: var(--border-2) solid var(--color-focus-ring);
  outline-offset: var(--border-1);
}

/* -------------------------------------------------------------- Choice group
   Shared shell for checkboxes + radios. Hides the native input visually
   (still focusable for a11y) and renders the box/dot via a sibling element. */

.fm-choice-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.fm-choice {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--space-3);
  cursor: pointer;
  font-size: var(--type-scale-sm);
  color: var(--color-fg);
}
.fm-choice-input {
  position: absolute;
  width: var(--border-1);
  height: var(--border-1);
  opacity: 0;
  pointer-events: none;
  margin: 0;
}
.fm-choice-mark {
  width: var(--space-4);
  height: var(--space-4);
  display: inline-grid;
  place-items: center;
  border: var(--border-2) solid var(--color-border-strong);
  background: var(--color-bg);
  flex-shrink: 0;
  transition:
    background   var(--motion-dur-fast) var(--motion-ease-standard),
    border-color var(--motion-dur-fast) var(--motion-ease-standard),
    box-shadow   var(--motion-dur-fast) var(--motion-ease-standard);
}
.fm-choice-mark-box {
  border-radius: var(--radius-xs);
}
.fm-choice-mark-dot {
  border-radius: var(--radius-pill);
}
.fm-choice:hover .fm-choice-mark {
  border-color: var(--color-fg-muted);
}
.fm-choice-input:focus-visible + .fm-choice-mark {
  border-color: var(--color-focus-ring);
  box-shadow: 0 0 0 var(--border-3)
    color-mix(in srgb, var(--color-focus-ring) 30%, transparent);
}
/* Checked states. The check + dot are drawn with pseudo-element box tricks
   so we don't have to ship inline SVGs for them. */
.fm-choice-input:checked + .fm-choice-mark-box {
  background: var(--color-primary);
  border-color: var(--color-primary);
}
.fm-choice-input:checked + .fm-choice-mark-box::after {
  content: '';
  width: var(--space-2);
  height: var(--space-1);
  border-left: var(--border-3) solid var(--color-primary-fg);
  border-bottom: var(--border-3) solid var(--color-primary-fg);
  transform: rotate(-45deg) translate(var(--border-1), calc(var(--border-1) * -1));
}
.fm-choice-input:checked + .fm-choice-mark-dot {
  border-color: var(--color-primary);
}
.fm-choice-input:checked + .fm-choice-mark-dot::after {
  content: '';
  width: var(--space-2);
  height: var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--color-primary);
}
.fm-choice-label {
  font-size: var(--type-scale-sm);
  color: var(--color-fg);
  line-height: var(--line-height-normal);
}

/* -------------------------------------------------------------- Toggle */

.fm-toggle-row {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-3);
  align-items: center;
}
.fm-toggle {
  appearance: none;
  width: var(--space-8);
  height: var(--space-5);
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--color-border-strong);
  position: relative;
  cursor: pointer;
  flex-shrink: 0;
  padding: 0;
  transition: background var(--motion-dur) var(--motion-ease);
}
.fm-toggle-thumb {
  position: absolute;
  top: var(--space-1);
  left: var(--space-1);
  width: var(--space-4);
  height: var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  transition: transform var(--motion-dur) var(--motion-ease);
}
.fm-toggle.is-on {
  background: var(--color-primary);
}
.fm-toggle.is-on .fm-toggle-thumb {
  transform: translateX(var(--space-4));
  background: var(--color-primary-fg);
}
.fm-toggle:focus-visible {
  outline: var(--border-2) solid var(--color-focus-ring);
  outline-offset: var(--border-2);
}
.fm-toggle-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-0);
  min-width: 0;
}
.fm-toggle-label {
  font-size: var(--type-scale-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
}
.fm-toggle-sub {
  font-size: var(--type-scale-xs);
  color: var(--color-fg-subtle);
  line-height: var(--line-height-normal);
}

/* -------------------------------------------------------------- Dropzone */

.fm-dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-7) var(--space-5);
  border: var(--border-2) dashed var(--color-border-strong);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--color-fg) 3%, var(--color-bg));
  text-align: center;
  cursor: pointer;
  transition:
    background   var(--motion-dur) var(--motion-ease),
    border-color var(--motion-dur) var(--motion-ease),
    transform    var(--motion-dur) var(--motion-ease);
}
.fm-dropzone:hover {
  border-color: var(--color-focus-ring);
  background: color-mix(in srgb, var(--color-focus-ring) 6%, var(--color-bg));
}
.fm-dropzone.is-drag {
  border-color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 8%, var(--color-bg));
  transform: translateY(calc(var(--border-3) * -1));
}
.fm-dropzone-glyph {
  width: var(--space-8);
  height: var(--space-8);
  border-radius: var(--radius-pill);
  display: grid;
  place-items: center;
  background: var(--color-surface);
  border: var(--border-1) solid var(--color-border);
  font-family: var(--type-display);
  font-size: var(--type-scale-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  line-height: var(--line-height-tight);
}
.fm-dropzone-title {
  font-size: var(--type-scale-md);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
}
.fm-dropzone-sub {
  font-size: var(--type-scale-xs);
  color: var(--color-fg-subtle);
  line-height: var(--line-height-normal);
}
.fm-dropzone-input {
  position: absolute;
  width: var(--border-1);
  height: var(--border-1);
  opacity: 0;
  pointer-events: none;
}

/* -------------------------------------------------------------- Form layout */

.fm-layout {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.fm-grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3) var(--space-4);
}
.fm-grid-full {
  grid-column: 1 / -1;
}
.fm-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  justify-content: flex-end;
  align-items: center;
  padding-top: var(--space-2);
  border-top: var(--border-1) solid var(--color-border);
}

/* Buttons inside the form layout. Mirrors the primary/ghost contract used
   elsewhere but lives in this file so forms.css is self-contained. */
.fm-btn {
  appearance: none;
  cursor: pointer;
  font-family: var(--type-body);
  font-size: var(--type-scale-sm);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-snug);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius);
  border: var(--border-1) solid transparent;
  transition:
    background   var(--motion-dur) var(--motion-ease),
    border-color var(--motion-dur) var(--motion-ease),
    color        var(--motion-dur) var(--motion-ease),
    transform    var(--motion-dur-fast) var(--motion-ease-standard);
}
.fm-btn-primary {
  background: var(--color-primary);
  color: var(--color-primary-fg);
}
.fm-btn-primary:hover {
  background: var(--color-primary-hover);
}
.fm-btn-primary:active {
  transform: translateY(var(--border-1));
}
.fm-btn-ghost {
  background: transparent;
  color: var(--color-fg);
  border-color: var(--color-border-strong);
}
.fm-btn-ghost:hover {
  background: var(--color-surface-hover);
  border-color: var(--color-fg-muted);
}
.fm-btn:focus-visible {
  outline: var(--border-2) solid var(--color-focus-ring);
  outline-offset: var(--border-2);
}

/* Single-column collapse on narrow viewports. The 640 / 1024 breakpoints
   mirror --bp-sm and --bp-lg literally; @media cannot read CSS custom
   properties (see src/tokens/_global.css). */
@media (max-width: 640px) {
  .fm-grid-2 { grid-template-columns: 1fr; }
  .forms-grid { grid-template-columns: 1fr; }
}
