/* =========================================================
   Component — Field (label + control + help/error)
   ========================================================= */
.field {
  --field-bg: var(--color-surface-sunken);
  --field-border: var(--color-line);
  --field-fg: var(--color-text);

  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.field__label {
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  color: var(--color-text);
}
.field__required {
  color: var(--color-gold);
  margin-inline-start: var(--space-1);
}

/*
   The three custom properties are scoped to .field, so a control written on
   its own — a select inside a table row, a filter with no label — resolved
   them to nothing and rendered as bare text on a transparent ground: no
   border, no background, invisible as a control. The admin stores screen
   worked around it by redeclaring all three on .store-status; the next
   screen to do the same would be the second copy of a fix.

   The fallbacks below are read only when nothing above has set them, so a
   control inside .field still takes .field's values — including the ones
   .field.is-invalid overrides.
*/
.field__control {
  width: 100%;
  padding: 0.8rem 1rem;
  border: 1px solid var(--field-border, var(--color-line));
  border-radius: var(--radius-sm);
  background: var(--field-bg, var(--color-surface-sunken));
  color: var(--field-fg, var(--color-text));
  font-size: var(--fs-sm);
  transition:
    border-color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out);
}
.field__control::placeholder { color: var(--color-text-muted); }
.field__control:hover { --field-border: var(--color-line-strong); }
.field__control:focus {
  outline: none;
  --field-border: var(--color-focus);
  box-shadow: var(--ring-focus);
}
.field__control:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

textarea.field__control {
  min-height: 7rem;
  resize: vertical;
  line-height: var(--lh-normal);
}

/*
   The chevron is two solid half-squares that meet at a point, drawn in
   currentColor so no icon file and no hardcoded hex is involved.

   Order matters and was reversed until 2026-08-27: the first gradient is
   the triangle whose mass sits top-RIGHT, so it has to be the LEFT half of
   the pair, and the second (mass top-LEFT) the right half. Placed the other
   way round the two wedges lean apart and the arrow reads as a notched bar
   rather than a v. The offsets are in px because the two boxes must sit
   exactly one width apart: 0.25rem between them left a pixel of overlap.
*/
select.field__control {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: left 13px top 55%, left 18px top 55%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-inline-start: 2.4rem;
}
:root[dir="ltr"] select.field__control {
  background-position: right 18px top 55%, right 13px top 55%;
  padding-inline-start: 1rem;
  padding-inline-end: 2.4rem;
}

.field__help {
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
}

/* Errors state what happened and what to do. They do not apologise. */
.field__error {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--color-danger);
}

.field.is-invalid { --field-border: var(--color-danger); }
.field.is-invalid .field__control:focus {
  box-shadow: 0 0 0 3px var(--color-danger-soft);
}

/* Input with a trailing affordance (password reveal, unit, search) */
.field__wrap { position: relative; display: flex; align-items: center; }
.field__wrap .field__control { padding-inline-end: 2.9rem; }
.field__affix {
  position: absolute;
  inset-inline-end: 0.6rem;
  display: inline-flex;
  padding: var(--space-2);
  border: 0;
  border-radius: var(--radius-xs);
  background: none;
  color: var(--color-text-muted);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out);
}
.field__affix:hover { color: var(--color-text); }
.field__affix:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 1px;
  color: var(--color-text);
}

/* One eye at a time, chosen by the button's own pressed state — the same
   pattern as the sun and moon on the theme toggle. Pressed means the secret
   is on screen, so the crossed-out eye is what you press to hide it again. */
.field__eye { inline-size: 1.15rem; block-size: 1.15rem; }
.field__affix .field__eye--shut,
.field__affix[aria-pressed="true"] .field__eye--open { display: none; }
.field__affix[aria-pressed="true"] .field__eye--shut { display: inline; }
.field__affix[aria-pressed="true"] { color: var(--color-text); }
/* =========================================================
   Component — Field · additions
   ---------------------------------------------------------
   م0 defined the label, the control, the help line and the error.
   Two things the forms in م6–م15 needed and it did not have: a
   checkbox row, and a way to lay fields out side by side.
   ========================================================= */

/* A checkbox and its label on one line. The box keeps the brand
   colour rather than the browser's, and the whole row is the hit
   target — a 13px square is not one. */
.field__check {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  font-size: var(--fs-sm);
  color: var(--color-text);
  cursor: pointer;
  line-height: var(--lh-snug);
}
.field__check input[type="checkbox"] {
  flex: none;
  inline-size: 1.1rem;
  block-size: 1.1rem;
  margin-block-start: 0.15rem;
  accent-color: var(--color-primary);
  cursor: pointer;
}
.field__check:hover { color: var(--color-text); }
.field__check input:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}

/* Fields in a row. Collapses to one column early: two number inputs
   side by side at 380px are two inputs nobody can read the labels of. */
.field-row {
  display: grid;
  gap: var(--space-4);
}
@media (min-width: 620px) {
  .field-row--2 { grid-template-columns: 1fr 1fr; }
  .field-row--3 { grid-template-columns: repeat(3, 1fr); }
}

/* A group of fields under a heading, inside a card. */
.field-set {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

/* ---------------------------------------------------------
   The file picker
   ---------------------------------------------------------
   ::file-selector-button could be painted, but the words on
   it belong to the browser: «Choose file / No file chosen»,
   in the browser's language, unmoved by our own switch. So
   the input is moved out of sight and a face is drawn for
   it — and the input stays focusable, because a control you
   cannot reach with Tab is worse than an ugly one.

   The input is 1px at the start corner rather than pushed
   off with a negative offset: in RTL the overflow lands on
   the left, and a -1px margin is a scrollbar across the
   whole page.
   --------------------------------------------------------- */
.field__file { position: relative; }

.field__file-input {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  inline-size: 1px;
  block-size: 1px;
  opacity: 0;
  pointer-events: none;
}

.field__file-face {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2);
  border: 1px solid var(--field-border, var(--color-line));
  border-radius: var(--radius-sm);
  background: var(--field-bg, var(--color-surface-sunken));
  cursor: pointer;
  transition:
    border-color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out);
}
.field__file-face:hover { --field-border: var(--color-line-strong); }

/* The ring goes on the face, because the face is what is on screen. */
.field__file-input:focus-visible + .field__file-face {
  --field-border: var(--color-focus);
  box-shadow: var(--ring-focus);
}
.field.is-invalid .field__file-input:focus-visible + .field__file-face {
  box-shadow: 0 0 0 3px var(--color-danger-soft);
}
.field__file-input:disabled + .field__file-face {
  opacity: 0.5;
  cursor: not-allowed;
}

.field__file-btn {
  flex: none;
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-xs);
  background: var(--color-surface-raised);
  color: var(--color-text);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
}

/* One line however many names: a chosen file must not push the
   button out of the card. */
.field__file-name {
  min-inline-size: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
}
.field__file.has-file .field__file-name {
  color: var(--color-text);
  font-weight: var(--fw-medium);
}

/* A value that cannot be edited, shown where its input would have been. It
   keeps the field's rhythm so a locked row does not fall out of the column. */
.field__static {
  padding: var(--space-2) 0;
  color: var(--color-text);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
}

/* ---------------------------------------------------------
   A line under a field that offers a way out
   ---------------------------------------------------------
   The same size and colour as .field__help, because it is
   the same kind of line: quiet, and read only by somebody
   who has stopped and looked.
   --------------------------------------------------------- */
.field__aside {
  margin: calc(var(--space-2) * -1) 0 0;
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
  line-height: var(--lh-snug);
}

/* A button that has to read as a link: it submits, so it cannot be an <a>,
   and it sits mid-sentence, so it cannot look like a button either. */
.link-button {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--color-primary-text);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.link-button:hover { color: var(--color-text); }
.link-button:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}

/* ---------------------------------------------------------
   The shape of a date
   ---------------------------------------------------------
   An empty date input carries the browser's own «يوم/شهر/سنة»,
   and Chrome lays the three words out left to right — day
   first on the left, the order the figures go in. Read right
   to left, as Arabic is, they arrive as سنة/شهر/يوم and the
   field looks like it is asking for the year first. dir on
   the input does not move them; neither does direction on
   ::-webkit-datetime-edit. The order is fixed in the browser.

   So while the box is empty and unfocused the browser's line
   is painted transparent — the calendar button is an image
   and stays where it was — and ours is printed over it as
   ordinary Arabic. A filled field is left alone: ٢٥/٠٣/١٩٩٠
   is a run of numerals and reads correctly on its own.

   .is-empty comes from js/date-field.js, so a page with no
   JavaScript keeps the browser's field untouched rather than
   an empty box with nothing written in it.
   --------------------------------------------------------- */
.field__date { position: relative; display: flex; align-items: center; }

/* The side it sits on is the side the browser puts its own figures
   on, which is the browser locale's and not the page's: an Arabic
   Chrome keeps the date box RTL — calendar button on the left, text
   on the right — even after the page switches to English. So the
   dir here is written by js/date-field.js from what the input
   actually computed to. Anchored to the page instead, the hint slid
   under the calendar button the moment somebody pressed EN. */
.field__date-hint {
  position: absolute;
  inset-inline-start: 1rem;
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
  pointer-events: none;
  opacity: 0;
}
.field__date-hint[dir="rtl"] { inset: auto 1rem auto auto; }
.field__date-hint[dir="ltr"] { inset: auto auto auto 1rem; }

.field__date.is-empty:not(:focus-within) .field__control { color: transparent; }
.field__date.is-empty:not(:focus-within) .field__date-hint { opacity: 1; }
