/* Forms - the inputs, the stacked .form layout, fields that slide open,
   checkboxes and file inputs. Loaded on every page (base.html), right
   after base.css: the login and create-account pages have forms too. */

.input {
    padding: var(--vpad) 0.75rem;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: var(--gray-0);
    color: var(--text);
    font: inherit;
    /* After `font` - the shorthand resets line-height to `normal`, which
       inputs and selects each resolve to a different height. */
    line-height: 1.25;
}

.input:focus {
    outline: 1px solid var(--red-pastel);
}

/* A multi-line text box (a support ticket's message and comments): it can
   be dragged taller, never wider - wider would push it out of its card. */
textarea.input {
    resize: vertical;
}

/* Shown but not editable (e.g. the email that comes with an invitation) -
   muted text, and no text cursor suggesting you can type in it. */
.input:disabled {
    color: var(--text-muted);
    cursor: not-allowed;
}

/* The browser's own dropdown arrow is pinned to the right edge and ignores
   padding, so it's switched off and redrawn as a background image, which
   can be positioned. The SVG can't read CSS variables - its stroke is
   --text-muted (#909090) written out, URL-encoded as %23909090. */
select.input {
    appearance: none;
    padding-right: 2.25rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23909090' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M2 5l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.75rem center;
    cursor: pointer;
}

/* Shared layout for a stacked form - label above each field, even gaps,
   buttons bottom-right (in an .actions row). Page-specific extras (e.g. the profile
   image controls) stay in that page's own CSS. */
.form {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    width: 100%;
    max-width: var(--width-form);
}

.form label {
    font-size: var(--font-sm);
    color: var(--text-muted);
}

/* Room above a label (or a group of fields) that follows a field (+: the
   element right before it; :is(): any of these) - a text box or dropdown,
   a file input, a field that slides open, a checkbox row, a group, a row
   of buttons in the middle of the form (a machine's Restore factory
   tolerances), a phone number's row - so between one field and the next,
   but never above the form's first label or below its last field. */
.form :is(.input, input[type="file"], .reveal, .checkbox-field, fieldset, .button-row, .phone-field) + :is(label, fieldset) {
    margin-top: 0.5rem;
}

/* A group of fields under one caption - a <fieldset> and its <legend>: a
   supporter's departments, Book service's day. The browser draws a border,
   padding and a margin round a fieldset; here the fields inside are what's
   seen, so none of them. min-width: 0 - a fieldset is otherwise never
   narrower than its content, so a calendar couldn't scroll sideways inside
   one on a phone. */
.form fieldset {
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
}

/* The group's caption reads like the form's labels. */
.form legend {
    padding: 0;
    font-size: var(--font-sm);
    color: var(--text-muted);
}

/* A field that slides open (.reveal, below): its label (or a group's
   fieldset) is the first thing inside the part that slides, so the room
   above it goes there too - as padding, inside, so it slides shut with the
   field instead of leaving a gap behind. */
.form .reveal__inner > :is(label, fieldset):first-child {
    padding-top: 0.5rem;
}

/* A note in a form (e.g. what saving a change does) - quiet, like the
   labels: background information, not something to fill in. */
.form-note {
    font-size: var(--font-sm);
    color: var(--text-muted);
    padding-top: 0.25rem;
}

/* The form's own gap is tight (it keeps each label close to its field),
   so the buttons need extra room to read as separate from the last field. */
.form .actions {
    margin-top: 1rem;
}

/* === Phone numbers === */

/* A phone number's country code and the number on one row
   (authentication/phone_field.html), 2 parts to 3 of the row (fr - a share
   of the room) - not the dropdown's own width, which for "Bosnia and
   Herzegovina +387" would leave the number no room on a phone; a long name
   is cut off in the closed dropdown instead. minmax(0, ...) - a grid
   column is otherwise never narrower than its content. */
.phone-field {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    gap: 0.5rem;
}

/* === Fields that slide open === */

/* A form field that slides open/closed - the profile's current password,
   a supporter's departments, a license's number and expiration date (their page's script toggles
   .reveal--open). Same trick as the sidebar's .nav-sub: height can't be
   animated to/from `auto`, but a one-row grid can go from 0fr to 1fr. */
.reveal {
    display: grid;
    grid-template-rows: 0fr;
    /* Closed, it's still an item in the form's flex column, so the form's
       0.25rem gap would leave an empty sliver - pulled back up while closed. */
    margin-top: -0.25rem;
    /* Keeps the closed input out of the Tab order; transitioning it delays
       the switch to hidden until the row has finished closing. */
    visibility: hidden;
}

.reveal--open {
    grid-template-rows: 1fr;
    margin-top: 0;
    visibility: visible;
}

/* Only added by the script after the page's starting state is set - so the
   field doesn't visibly slide shut on every page load. */
.reveal--animated {
    transition: grid-template-rows var(--trans) ease, margin-top var(--trans) ease, visibility var(--trans);
}

/* Laid out like the rest of the form (label above input, same gap).
   overflow: hidden clips it while the row is shorter than its content;
   the 1px padding/negative margin pair leaves room for the input's focus
   outline, which would otherwise be clipped too. */
.reveal__inner {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-height: 0;
    overflow: hidden;
    padding: 1px;
    margin: -1px;
}

/* === Checkboxes === */

/* A checkbox (or a radio button) next to its label, on one line (profile's
   SMS notifications, a license's Subscription, a ticket's remote session) -
   .form stacks everything else label-over-field.
   The room a label gets above it when it follows a field goes on the whole
   row instead (padding-top): on the label it would push the label below the
   middle of its checkbox. */
.checkbox-field {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding-top: 0.5rem;
}

.checkbox-field input {
    width: 1.1rem;
    height: 1.1rem;
    accent-color: var(--red);
    cursor: pointer;
}

.checkbox-field label {
    cursor: pointer;
}

/* === File inputs === */

input[type="file"]::file-selector-button {
    padding: var(--vpad) var(--hpad);
    margin-right: 0.75rem;
    background: var(--gray-2);
    color: var(--text);
    border: 0;
    border-radius: var(--radius);
    font: inherit;
    cursor: pointer;
    transition: background-color var(--trans) ease;
}

input[type="file"]::file-selector-button:hover {
    background: var(--gray-3);
}

/* The saved image on an edit page (profile, milling machine model), shown
   above the file input that replaces it, with a way to remove it. */
.current-image {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.current-image__preview {
    width: 3rem;
    height: 3rem;
    object-fit: contain;
    border-radius: var(--radius);
    border: 1px solid var(--border);
}

/* The "Remove image" button (image_remove.js) - a button, since it does
   something, but looking like a small red link. */
.remove-label {
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    font-size: var(--font-sm);
    color: var(--red);
    text-decoration: underline;
    cursor: pointer;
}

/* === The per-axis fields === */

/* A milling machine model's per-axis fields and a milling machine's own
   tolerances, as a small table: a row per axis (X, Y, Z), a column per
   value (a model's drive, warning, alarm). Every child of .axis-grid is one
   cell, filled in left to right, a new row every 4 cells. */
.axis-grid {
    display: grid;
    /* The axis letter only as wide as it needs to be, the fields sharing
       the rest equally. */
    grid-template-columns: auto 1fr 1fr 1fr;
    gap: 0.5rem;
    align-items: center;
    /* The same space above as a .form label has, so it doesn't sit tighter
       under the field before it than the other fields do. */
    padding-top: 0.5rem;
}

/* A machine's tolerances - no drive, so a new row every 3 cells. Its
   Restore factory tolerances button (a .button-row) right under it. */
.axis-grid--limits {
    grid-template-columns: auto 1fr 1fr;
}

/* A field's natural width is wider than a third of the form - without
   min-width: 0 a grid column never shrinks below its contents, and the
   fields would stick out of the card. */
.axis-grid .input {
    min-width: 0;
}

/* Column headings, styled like the form's labels. */
.axis-grid__head {
    font-size: var(--font-sm);
    color: var(--text-muted);
}

.axis-grid__axis {
    color: var(--text-muted);
}

/* The row of buttons right under the grid (a machine's Restore factory
   tolerances) - the grid's own gap between its rows, not the form's tighter
   one, so it doesn't read as the grid's last row. */
.form .axis-grid + .button-row {
    margin-top: 0.25rem;
}
