/* form-controls.css — the console's one checkbox and one radio, and which way an empty text field runs.
 *
 * Loaded right after sadaa.css by every page that loads sadaa.css, before the page's own sheet.
 * Colours, radii and motion come from the tokens (echo-tokens.css, motion.css and the :root of
 * sadaa.css).
 */

/* ==========================================================================
   CHECKBOX AND RADIO — the console's one checkbox and one radio.

   `.sd-check` goes on an <input type="checkbox">, `.sd-radio` on an
   <input type="radio">; `SadaaKit.Checkbox` / `SadaaKit.Radio` (ui-kit.jsx)
   write the whole labelled row, `.sd-checkrow`. The native input stays, so
   the keyboard, the label click, the form value and what a screen reader says
   are the browser's own; `appearance: none` hands over only the drawing. The
   browser's own boxes (small, blue, different on every system) were what made
   the console's forms look unfinished.

   Checked is the ported switch's "on" (an ink fill, `.sd-as-switch.is-on`).
   The state shows at once; the tick drawing in and the dot growing in are
   decoration only, and they stop under reduced motion.
   ========================================================================== */
.sd-check, .sd-radio {
  appearance: none; -webkit-appearance: none;
  display: inline-grid; place-content: center; flex: none;
  inline-size: 20px; block-size: 20px; margin: 0; padding: 0;
  border: 1.5px solid var(--line-strong); background-color: var(--surface);
  vertical-align: middle; cursor: pointer;
  transition: box-shadow var(--motion-fast, 120ms) var(--motion-ease-out, cubic-bezier(0.2, 0.8, 0.2, 1));
}
.sd-check { border-radius: 6px; }
.sd-radio { border-radius: var(--r-full); }
/* On a dark card the box is a step lighter than the card, as the ported fields
   are. `:where()` keeps this at the weight of the checked fill below, which
   comes later and so still wins. */
:root[data-theme="dark"] :where(.sd-check, .sd-radio) { background-color: var(--surface-2); }

/* The tick and the pen that draws it. The tick is an SVG mask filled with the
   surface colour. Over it sits a block the colour of the fill, which shrinks
   away to the right and uncovers the tick in the order a hand writes it. A tick
   is a mark, not text, so it is drawn left to right in Arabic too and is never
   mirrored. The SVG's namespace is percent-encoded like the rest of the image:
   it is a name, not an address, and nothing is fetched. */
.sd-check::before, .sd-check::after {
  content: ""; grid-area: 1 / 1; place-self: center; inline-size: 12px; block-size: 12px;
}
.sd-check::before {
  background-color: var(--surface); opacity: 0;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg' viewBox='0 0 12 12'%3E%3Cpath d='M2.25 6.25l2.5 2.5 5-5.5' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 12px 12px no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg' viewBox='0 0 12 12'%3E%3Cpath d='M2.25 6.25l2.5 2.5 5-5.5' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 12px 12px no-repeat;
}
.sd-check::after { background-color: inherit; transform-origin: right center; }
.sd-check:checked, .sd-check:indeterminate { background-color: var(--ink); border-color: var(--ink); }
.sd-check:checked::before, .sd-check:indeterminate::before { opacity: 1; }
.sd-check:checked::after, .sd-check:indeterminate::after {
  transform: scaleX(0);
  transition: transform var(--motion-base, 180ms) var(--motion-ease-out, cubic-bezier(0.2, 0.8, 0.2, 1));
}
/* Some, not all (a "select all" over a partly ticked list): a dash, drawn the same way. */
.sd-check:indeterminate::before { -webkit-mask: none; mask: none; block-size: 2px; inline-size: 10px; border-radius: 1px; }

/* The radio's dot grows in from nothing. */
.sd-radio::before {
  content: ""; inline-size: 10px; block-size: 10px; border-radius: var(--r-full);
  background-color: var(--ink); transform: scale(0);
}
.sd-radio:checked { border-color: var(--ink); }
.sd-radio:checked::before {
  transform: scale(1);
  transition: transform var(--motion-base, 180ms) var(--motion-ease-spring, cubic-bezier(0.34, 1.4, 0.64, 1));
}

/* Hover: on the box or anywhere on its row, a firmer edge and a soft halo. */
.sd-check:hover:not(:disabled), .sd-radio:hover:not(:disabled),
.sd-checkrow:hover > .sd-check:not(:disabled), .sd-checkrow:hover > .sd-radio:not(:disabled) {
  box-shadow: 0 0 0 4px color-mix(in oklab, var(--ink) 8%, transparent);
}
.sd-check:hover:not(:disabled):not(:checked):not(:indeterminate), .sd-radio:hover:not(:disabled):not(:checked),
.sd-checkrow:hover > .sd-check:not(:disabled):not(:checked):not(:indeterminate),
.sd-checkrow:hover > .sd-radio:not(:disabled):not(:checked) {
  border-color: var(--ink-2);
}
.sd-check[aria-invalid="true"]:not(:checked), .sd-radio[aria-invalid="true"]:not(:checked) { border-color: var(--crit); }
/* Inside the shell the general focus ring (sadaa.css > FOCUS) would round the box
   into a pill; the two controls keep their own shape under the ring. */
.sd-check:focus-visible, .sd-radio:focus-visible,
.sd-app .sd-check:focus-visible, .sd-app .sd-radio:focus-visible {
  outline: 2px solid var(--focus); outline-offset: 2px; box-shadow: none;
}
.sd-app .sd-check:focus-visible { border-radius: 6px; }
.sd-app .sd-radio:focus-visible { border-radius: var(--r-full); }
.sd-check:disabled, .sd-radio:disabled { cursor: not-allowed; opacity: 0.45; }
@media (prefers-reduced-motion: reduce) {
  .sd-check, .sd-radio, .sd-check:checked::after, .sd-check:indeterminate::after,
  .sd-radio:checked::before { transition: none; }
}
/* High contrast (forced colours) paints every background in the page colour, and the fill,
   tick, dash and dot above are all backgrounds, so a ticked box looked empty. There the
   browser draws its own box, in the system's colours; the focus ring stays (an outline). */
@media (forced-colors: active) {
  .sd-check, .sd-radio { appearance: auto; -webkit-appearance: auto; }
  .sd-check::before, .sd-check::after, .sd-radio::before { content: none; }
}

/* The labelled row: the whole row is the target (44 px at least), the box sits
   on the first line of the words, and a hint may follow under them. */
.sd-checkrow {
  display: flex; align-items: flex-start; gap: 12px; min-inline-size: 0;
  min-block-size: 44px; padding-block: 10px; box-sizing: border-box;
  font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink); cursor: pointer;
}
.sd-checkrow > .sd-check, .sd-checkrow > .sd-radio {
  margin-block-start: calc((var(--text-small) * var(--lh-small) - 20px) / 2);
}
.sd-checkrow__t { display: grid; gap: 2px; min-inline-size: 0; overflow-wrap: anywhere; }
.sd-checkrow__hint { font-size: var(--text-meta); line-height: var(--lh-meta); color: var(--ink-2); }
.sd-checkrow:has(> .sd-check:disabled), .sd-checkrow:has(> .sd-radio:disabled) { cursor: not-allowed; color: var(--ink-2); }
/* A list of such rows: each row's own 44 px is the spacing, so the list adds none. */
.sd-checklist { list-style: none; margin: 0; padding: 0; display: grid; min-inline-size: 0; }

/* ==========================================================================
   A FREE-TEXT FIELD ON AN ARABIC PAGE (UI round 2, item 8).

   Name, service, reason, notes and search fields carry dir="auto", so typed text runs the way
   its own first letter says: a Latin name lays out left to right, an Arabic one right to left.
   But an EMPTY dir="auto" field has no letter to go by, and the browser then takes it as left
   to right: on an Arabic page the placeholder («الاسم بالكامل», «مثلاً: كشف») and the caret sat
   on the left of the box. So, inside a right-to-left page or card, an empty dir="auto" field
   (its placeholder showing, or -- for a field with no placeholder -- the empty value React
   writes into its `value` attribute) is right to left. Once something is typed the rule no
   longer matches and dir="auto" decides again.

   Only text, search and untyped inputs, and textareas: a phone number, an email, an address,
   a number, a password or a time stays left to right (they are never dir="auto" here, and the
   type list keeps them out even if one were). A field with no dir of its own inherits the
   page's direction already. A left-to-right block inside a right-to-left one (an English card
   on an Arabic page) puts its fields back, and a right-to-left block inside that again, each
   later rule a step more specific than the one before.
   ========================================================================== */
[dir="rtl"] :is(input:is(:not([type]), [type="text"], [type="search"]), textarea)[dir="auto"]:is(:placeholder-shown, [value=""]) {
  direction: rtl; unicode-bidi: isolate; text-align: right;
}
[dir="rtl"] [dir="ltr"] :is(input:is(:not([type]), [type="text"], [type="search"]), textarea)[dir="auto"]:is(:placeholder-shown, [value=""]) {
  direction: ltr; text-align: left;
}
[dir="rtl"] [dir="ltr"] [dir="rtl"] :is(input:is(:not([type]), [type="text"], [type="search"]), textarea)[dir="auto"]:is(:placeholder-shown, [value=""]) {
  direction: rtl; text-align: right;
}
