/*
 * Wedding Budget
 * Copyright (c) 2026 Amar Micro Inc.
 * Author: Jacques Amar
 *
 * All rights reserved. Proprietary software — see LICENSE for terms.
 *
 * Version: 1.0.0
 *
 * Reusable form-field component — portable across projects.
 * Every size and colour flows through the --field-* custom properties defined
 * in app.css :root. Never hardcode a value that is already a token; use rem/em.
 *
 * Two layouts share one control style:
 *
 *   .form-field  CANONICAL. Floating label — the <label> comes AFTER the
 *                control. Default for all new forms. Text-like inputs float
 *                their label up on content/focus and let it rest as a
 *                placeholder when empty; selects, date and color controls never
 *                match :placeholder-shown so their label stays floated. Use for
 *                every single-line text/email/tel/number/textarea/select field.
 *
 *   .form-group  LEGACY top-aligned label — the <label> comes BEFORE the
 *                control. Retained so not-yet-migrated pages keep working and
 *                still pick up focus/validation/token styling. Prefer
 *                .form-field for new markup; reach for .form-group only for
 *                composite controls where a floating label is not appropriate
 *                (e.g. the emoji-picker row).
 *
 * Accessibility contract (enforced in markup, supported here):
 *   - Every control has a visible <label for="id"> / <input id="id">.
 *   - Helper text uses .form-help, error text uses .form-error; the control
 *     points at them with aria-describedby. .form-error carries role="alert".
 *   - :focus-within gives the field a clear keyboard focus state.
 */

/* ── Shared control ─────────────────────────────────────────────────────── */
.form-control {
    width: 100%;
    font: inherit;                       /* inherit the global font family/weight */
    font-size: var(--field-font-size);
    padding: var(--field-padding-y) var(--field-padding-x);
    color: var(--field-text);
    background: var(--field-bg);
    border: 1px solid var(--field-border);
    border-radius: var(--field-radius);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.form-control:focus {
    outline: none;
    border-color: var(--field-border-focus);
    box-shadow: 0 0 0 0.18rem var(--field-focus-ring);
}

/* Native browser validation. :user-invalid (not bare :invalid) so a pristine,
 * empty, required field is NOT flagged red before the user has interacted with
 * it. Use setCustomValidity() in JS only when a rule can't be expressed with
 * native constraint attributes (required, type, min, max, step, pattern). */
.form-control:user-invalid {
    border-color: var(--field-invalid);
}
.form-control:user-invalid:focus {
    box-shadow: 0 0 0 0.18rem var(--field-invalid-ring);
}

select.form-control {
    appearance: auto;
}

textarea.form-control {
    min-height: 4.5rem;
    resize: vertical;
}

/* Native color picker styled as a control (kept on a static .form-group label,
 * since a color input never has an empty/placeholder state to float against). */
input[type="color"].form-control {
    height: 2.4rem;
    padding: 0.2rem;
    cursor: pointer;
}

/* Checkbox / radio — native control, tinted with the brand accent. */
input[type="checkbox"],
input[type="radio"] {
    accent-color: var(--field-accent);
}

/* ── Helper & error text (wire to the control via aria-describedby) ─────── */
.form-help {
    font-size: var(--field-help-size);
    color: var(--text-muted);
    margin: 0.25rem 0 0;
}

.form-error {
    font-size: var(--field-help-size);
    color: var(--field-invalid);
    margin: 0.25rem 0 0;
}

/* Small "quick-set" links under a field (e.g. set a date to today / the event). */
.field-quickset-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-top: 0.3rem;
}
.field-quickset {
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-size: var(--field-help-size);
    color: var(--field-border-focus);
    cursor: pointer;
}
.field-quickset[hidden] { display: none; }
.field-quickset:hover { text-decoration: underline; }

/* ── Layout rows ────────────────────────────────────────────────────────── */
.form-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}
.form-row > .form-field,
.form-row > .form-group,
.form-row > .form-check {
    flex: 1 1 10rem;
}

/* ── Canonical: floating-label field ───────────────────────────────────── */
.form-field {
    position: relative;
    margin-bottom: var(--field-gap);
}

/* Reserve room at the top of the control for the floated label. */
.form-field > .form-control {
    padding-top: calc(var(--field-padding-y) + 0.55rem);
    padding-bottom: calc(var(--field-padding-y) - 0.05rem);
}

.form-field > label {
    position: absolute;
    left: calc(var(--field-padding-x) - 0.15rem);
    top: 0.32rem;
    padding: 0 0.2rem;
    font-size: var(--field-label-size);
    line-height: 1;
    color: var(--field-label-color);
    background: var(--field-bg);          /* mask the control's own placeholder */
    pointer-events: none;
    transition: transform 0.12s ease, font-size 0.12s ease, color 0.12s ease;
    transform-origin: left center;
}

/* Empty + unfocused text inputs: drop the label down to act as the placeholder.
 * Selects / date / color never match :placeholder-shown, so their label stays
 * floated — which is exactly what we want for those controls. */
.form-field > .form-control:placeholder-shown:not(:focus) + label {
    transform: translateY(0.85rem);
    font-size: var(--field-font-size);
    color: var(--field-placeholder-color);
    background: transparent;
}

/* Focus-within: tint the field's label (and keep it floated). */
.form-field:focus-within > label {
    color: var(--field-border-focus);
}

/* Floated label over an invalid control. */
.form-field > .form-control:user-invalid + label {
    color: var(--field-invalid);
}

/* ── Amount field: floating label + fixed currency-symbol prefix ────────── */
.amount-field > .amount-prefix {
    position: absolute;
    left: var(--field-padding-x);
    top: calc(var(--field-padding-y) + 0.55rem);
    font-size: var(--field-font-size);
    line-height: 1;
    color: var(--field-label-color);
    pointer-events: none;
}
/* Reserve room for the (variable-width) symbol; JS sets --amount-prefix-w (ch). */
.amount-field > .form-control {
    padding-left: calc(var(--field-padding-x) + var(--amount-prefix-w, 1ch) + 0.45rem);
}
/* Amount fields keep the label floated at all times — the prefix occupies the
   placeholder slot, so the label must never drop on top of the symbol. */
.form-field.amount-field > .form-control:placeholder-shown:not(:focus) + label {
    transform: none;
    font-size: var(--field-label-size);
    color: var(--field-label-color);
    background: var(--field-bg);
}

/* ── Inline check field (checkbox / radio + label) ─────────────────────── */
.form-check {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: var(--field-gap);
}
.form-check > label {
    font-size: var(--field-font-size);
    color: var(--field-text);
    cursor: pointer;
}

/* ── Legacy: top-aligned label field ───────────────────────────────────── */
.form-group {
    margin-bottom: var(--field-gap);
}
/* Descendant selector (not child) preserves the exact pre-refactor matching. */
.form-group label {
    display: block;
    margin-bottom: 0.2rem;
    font-size: var(--field-label-size);
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--field-label-color);
}
.form-group:focus-within label {
    color: var(--field-border-focus);
}
