/* ============================================================
   components/choice.css — checkbox · radio · toggle
   A label wraps a visually-hidden native input (kept focusable +
   accessible) plus a faux control. Coral fill, the checkbox "checks"
   with the brand dot/check, the toggle knob springs on --ease-dreamy.

   Markup:
     <label class="dd-choice">
       <input type="checkbox" class="dd-choice__input">    (native, hidden)
       <span class="dd-choice__box"><svg .dd-choice__check></span>
       <span class="dd-choice__label">…</span>
     </label>
   Variants: .dd-choice--radio, .dd-choice--toggle.
   ============================================================ */

.dd-choice {
  /* Two knobs, deliberately independent of `font-size` (#187):

       --dd-choice-size  the checkbox/radio box's side
       --dd-toggle-h     the toggle track's height

     Everything else — border, padding, the knob, the distance it travels — is
     derived from them, so a size change stays proportional and the knob can
     never fall out of its track. Font-size moves the *label* and nothing else.

     The defaults are `em`, so any instance that sets neither knob still tracks
     type exactly as it did before these variables existed. Resize with the
     knobs, in whatever unit suits; do not set `font-size` and hope. */
  --dd-choice-size: 1.4em;
  --dd-toggle-h: 1.45em;
  --dd-choice-border: calc(var(--dd-choice-size) * 0.0857);
  --dd-toggle-inset: calc(var(--dd-toggle-h) * 0.083);
  --dd-toggle-w: calc(var(--dd-toggle-h) * 1.793);
  --dd-toggle-knob: calc(var(--dd-toggle-h) - 4 * var(--dd-toggle-inset));

  display: inline-flex;
  align-items: flex-start;
  gap: var(--space-3);
  cursor: pointer;
  font-size: var(--fs-body);
  color: var(--text);
  line-height: var(--lh-snug);
}

/* The native input stays in the DOM (submits, focusable, SR-readable)
   but is visually replaced by .dd-choice__box. */
.dd-choice__input {
  position: absolute;
  width: 1.25em;
  height: 1.25em;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

/* ---- checkbox / radio box ----------------------------------------- */
.dd-choice__box {
  flex-shrink: 0;
  position: relative;
  width: var(--dd-choice-size);
  height: var(--dd-choice-size);
  margin-top: 0.05em;
  display: grid;
  place-items: center;
  background: var(--surface-tint);
  border: var(--dd-choice-border) solid var(--coral-200);
  border-radius: var(--radius-sm);
  color: var(--text-on-coral);
  transition: background-color var(--dur-base) var(--ease-soft),
              border-color var(--dur-base) var(--ease-soft),
              transform var(--dur-fast) var(--ease-dreamy);
}

/* the check glyph, hidden until checked */
.dd-choice__check {
  width: 1em;
  height: 1em;
  opacity: 0;
  transform: scale(0.4);
  transition: opacity var(--dur-fast) var(--ease-soft),
              transform var(--dur-base) var(--ease-dreamy);
}

.dd-choice__input:checked ~ .dd-choice__box {
  background: var(--grad-coral);
  border-color: var(--accent-strong);
}
.dd-choice__input:checked ~ .dd-choice__box .dd-choice__check {
  opacity: 1;
  transform: scale(1);
}

/* press feedback */
.dd-choice__input:active ~ .dd-choice__box { transform: scale(0.92); }

/* focus ring on the faux control */
.dd-choice__input:focus-visible ~ .dd-choice__box {
  outline: var(--focus-outline);
  outline-offset: 2px;
}

.dd-choice__input:disabled ~ .dd-choice__box {
  opacity: 0.5;
}
.dd-choice:has(.dd-choice__input:disabled) {
  cursor: not-allowed;
  opacity: 0.7;
}

.dd-choice__label { padding-top: 0.08em; }
.dd-choice__label a { color: var(--link); text-decoration: underline; }

/* ---- radio --------------------------------------------------------- */
.dd-choice--radio .dd-choice__box { border-radius: var(--radius-pill); }
/* radios use a centre dot rather than a check icon */
.dd-choice--radio .dd-choice__box::after {
  content: "";
  width: 0.55em;
  height: 0.55em;
  border-radius: var(--radius-pill);
  background: var(--text-on-coral);
  opacity: 0;
  transform: scale(0.3);
  transition: opacity var(--dur-fast) var(--ease-soft),
              transform var(--dur-base) var(--ease-dreamy);
}
.dd-choice--radio .dd-choice__input:checked ~ .dd-choice__box::after {
  opacity: 1;
  transform: scale(1);
}

/* ---- toggle -------------------------------------------------------- */
.dd-choice--toggle .dd-choice__box {
  width: var(--dd-toggle-w);
  height: var(--dd-toggle-h);
  border-width: var(--dd-toggle-inset);
  border-radius: var(--radius-pill);
  background: var(--coral-200);
  border-color: transparent;
  place-items: center start;
  padding: var(--dd-toggle-inset);
}
.dd-choice--toggle .dd-choice__box::after {
  content: "";
  /* Derived, so it always fits the track exactly rather than overflowing it
     by whatever the border happens to be. */
  width: var(--dd-toggle-knob);
  height: var(--dd-toggle-knob);
  border-radius: var(--radius-pill);
  background: var(--paper);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-base) var(--ease-dreamy);
}
.dd-choice--toggle .dd-choice__input:checked ~ .dd-choice__box {
  background: var(--grad-coral);
}
.dd-choice--toggle .dd-choice__input:checked ~ .dd-choice__box::after {
  /* The width left over once the knob and both insets are accounted for —
     computed rather than guessed, so it lands flush at any size. */
  transform: translateX(
    calc(var(--dd-toggle-w) - var(--dd-toggle-knob) - 4 * var(--dd-toggle-inset))
  );
}
/* toggle has no check glyph */
.dd-choice--toggle .dd-choice__check { display: none; }

/* ---- small (a control beside body text, not a form row) ------------
   A choice that sits next to something it belongs to — a switch beside a
   name — rather than standing as a form field. Body-size type there reads
   as the thing itself rather than as a control for it.

   The variant exists because font-size alone does NOT shrink this component
   correctly: everything else here is `em`, but `.dd-choice__box`'s border is
   `2px`, so at a smaller size the border stops being proportional and the
   toggle's knob no longer centres in its track. Scale it with the rest and
   the geometry holds. (#187) */
.dd-choice--sm {
  /* Both knobs in px: the point of the variant is a control that does *not*
     shrink with its label. */
  --dd-choice-size: 15px;
  --dd-toggle-h: 17px;
  font-size: var(--fs-label);
  gap: var(--space-2);
}
.dd-choice--sm .dd-choice__label {
  padding-top: 0;
  color: var(--text-muted);
}

/* ---- group (stack of choices) ------------------------------------- */
.dd-choice-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.dd-choice-group--inline {
  flex-direction: row;
  flex-wrap: wrap;
  gap: var(--space-5);
}

@media (prefers-reduced-motion: reduce) {
  .dd-choice__box,
  .dd-choice__check,
  .dd-choice--radio .dd-choice__box::after,
  .dd-choice--toggle .dd-choice__box::after { transition: none; }
}
