/* Do Directory: the listing form and its interaction states (F5). Loaded after site.css and directory.css;
   reuses their tokens. No framework. Works without JS; directory-form.js only adds counters and copy feedback.

   Class list (all prefixed dir-). Markup hooks printed by templates/_directory_form.html are marked (F1).

   form (F1)
     .dir-form                      the form (#dir-form, [data-mode="join"|"manage"])
     .dir-fs > legend.dir-fs-legend section; .dir-fs-num (step circle)  .dir-fs-title  p.dir-fs-sub
     .dir-group                     nested fieldset (radio cards, skills)
     .dir-req  .dir-req-note        required asterisk + its explanation
     .dir-field-meta                hint (left) + counter (right) under a field
     .dir-count[data-count-for]     live character counter; JS sets .is-short | .is-near | .is-over
     .dir-textarea                  bio textarea
     .dir-err                       per-field error (with site.css .status.bad)
     .dir-choices (.dir-choices-3)  radio cards (site.css .plan) ; .dir-choice
     .dir-avail-dot.dir-avail-open | -limited | -busy
     .dir-skill-pick[data-max]      skill picker; JS sets .is-full and --dir-fill
     .dir-skill-count               "3 of 8 chosen" (aria-live); .is-full | .is-empty | .is-nudge
     .dir-skill-group  .dir-skill-group-name  .dir-skill-chips
     label.dir-skill-chip > input[type=checkbox] + span     chip checkbox (checked / focus / disabled)
     .dir-remote  .dir-terms  .dir-submit
   copy feedback (join_done.html, F2 owns the box layout)
     button[data-copy-target]       JS copies the target's value; adds .is-copied for ~2s
     .dir-copy-btn.is-copied        green "Copied" state;  [data-copy-status=<id>] gets the spoken message
   page chrome for join / join_done / manage / admin lives in those templates' own <style> blocks
   (dir-join-*, dir-done-*, dir-manage-*, dir-adm-*), so it is not repeated here.
   utilities
     .dir-sr-live                   visually hidden live region JS creates for announcements
*/

/* ---------- tokens ---------- */
:root {
  --dir-f-ring: 0 0 0 4px rgba(106, 92, 255, .2);
  --dir-f-ring-bad: 0 0 0 4px rgba(239, 68, 68, .16);
  --dir-f-chip-bg: var(--surface);
  --dir-f-chip-line: var(--line-2);
  --dir-f-chip-on: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  --dir-f-sec-bg: var(--surface-2);
  --dir-f-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --dir-f-plus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 6v12M6 12h12' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round'/%3E%3C/svg%3E");
}
@media not all { /* dark theme switched off: the public site is light-only (Oct 2026); restore with (prefers-color-scheme: dark) */
  :root {
    --dir-f-ring: 0 0 0 4px rgba(157, 147, 255, .28);
    --dir-f-ring-bad: 0 0 0 4px rgba(248, 113, 113, .2);
    --dir-f-chip-bg: var(--surface-2);
    --dir-f-chip-line: rgba(255, 255, 255, .18);
    --dir-f-sec-bg: color-mix(in srgb, var(--surface-2) 70%, var(--bg));
  }
}

/* ---------- form sections ---------- */
.dir-form { gap: 0; }
.dir-form > .dir-req-note { margin: 0 0 22px; }
.dir-fs { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; padding: 0 0 30px; margin: 0 0 30px; border-bottom: 1px solid var(--line); }
.dir-fs:last-of-type { border-bottom: 0; margin-bottom: 8px; padding-bottom: 8px; }
.dir-fs-legend { display: flex; align-items: center; gap: 12px; padding: 0; margin: 0 0 6px; font-size: 1rem; }
.dir-fs-num {
  flex: none; width: 30px; height: 30px; border-radius: 10px; display: grid; place-items: center;
  font: 700 .86rem/1 var(--f-display); color: #fff; background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  box-shadow: 0 6px 14px -8px rgba(91, 77, 255, .8);
}
.dir-fs-title { font: 700 1.2rem/1.2 var(--f-display); letter-spacing: -.02em; color: var(--ink); }
.dir-fs-sub { margin: 0; padding-left: 42px; }
@media (max-width: 420px) { .dir-fs-sub { padding-left: 0; } }
.dir-group { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
.dir-group > legend { padding: 0; margin: 0 0 8px; }
.dir-group > .hint { margin-top: -4px; }
.dir-req { color: var(--bad-ink); font-weight: 700; margin-left: 2px; }
.dir-req-note .dir-req { margin: 0 2px; }

/* fields not covered by site.css: textarea, url inputs, invalid selects */
.dir-form textarea, .dir-textarea {
  width: 100%; min-height: 168px; padding: 12px 14px; border-radius: 12px; border: 1px solid var(--line-2); background: var(--surface); color: var(--ink);
  font: 400 16px/1.55 var(--f-body); resize: vertical; transition: border-color .15s, box-shadow .15s; -webkit-appearance: none; appearance: none;
}
.dir-form textarea::placeholder { color: var(--ink-3); opacity: .8; }
.dir-form textarea:hover, .dir-form .field input[type="url"]:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--line-2)); }
.dir-form textarea:focus, .dir-form .field input[type="url"]:focus, .dir-form .input:focus { outline: none; border-color: var(--accent); box-shadow: var(--dir-f-ring); }
.dir-form [aria-invalid="true"]:is(input, textarea, select) { border-color: var(--bad); background-color: color-mix(in srgb, var(--bad) 3%, var(--surface)); }
.dir-form [aria-invalid="true"]:is(input, textarea, select):focus { border-color: var(--bad); box-shadow: var(--dir-f-ring-bad); }
/* Text-like controls show focus with a box-shadow ring; keep a transparent outline so Windows High Contrast
   (forced colours) still draws a visible focus indicator. Checkboxes and radios keep the global :focus-visible ring. */
.dir-form :is(input:not([type="checkbox"], [type="radio"]), textarea, select):focus { outline: 2px solid transparent; outline-offset: 2px; }
/* Full-strength placeholders so example text meets contrast (site.css dims them to .8). */
.dir-form .field input::placeholder, .dir-form textarea::placeholder { opacity: 1; }
.dir-form .field input[type="number"] { max-width: 12rem; font-variant-numeric: tabular-nums; }
.dir-form .hint svg { display: inline-block; vertical-align: -2px; margin-right: 4px; color: var(--ink-3); }

/* hint + counter row */
.dir-field-meta { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 16px; }
.dir-field-meta .hint { flex: 1 1 16rem; min-width: 0; }
.dir-form .dir-count {
  flex: none; margin-left: auto; font: 600 .8rem/1.3 var(--f-body); color: var(--ink-3); font-variant-numeric: tabular-nums; white-space: nowrap;
  padding: 2px 8px; border-radius: 999px; background: var(--surface-2); border: 1px solid var(--line); transition: color .15s, background-color .15s, border-color .15s;
}
.dir-form .dir-count.is-short { color: var(--ink-2); }
.dir-form .dir-count.is-near { color: var(--warn-ink); background: var(--warn-soft); border-color: rgba(245, 158, 11, .35); }
.dir-form .dir-count.is-over { color: var(--bad-ink); background: var(--bad-soft); border-color: rgba(239, 68, 68, .35); }

/* errors */
.dir-err { align-items: flex-start; font-weight: 550; line-height: 1.4; }
.dir-err svg { flex: none; margin-top: 1px; }
.dir-group > .dir-err { margin-top: 2px; }

/* ---------- radio cards (site.css .plan) ---------- */
.dir-choices { margin-top: 0; }
.dir-choices-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 720px) { .dir-choices-3 { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 420px) { .dir-choices { grid-template-columns: minmax(0, 1fr); } }
.dir-choice .box { min-height: 100%; align-content: start; }
/* Stronger unchecked radio ring (3:1 against the card). The checked rule in site.css,
   .plan input:checked + .box::before, is more specific (0,3,2 vs 0,2,1) so its 5px accent border still wins. */
.dir-choice .box::before { border-color: var(--ink-3); }
.dir-choice:hover .box { border-color: color-mix(in srgb, var(--accent) 45%, var(--line-2)); }
.dir-choice input:checked + .box { border-color: var(--accent); }
.dir-choice .pr { font-size: .86rem; line-height: 1.45; }
.dir-avail-dot { display: inline-block; flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--ink-3); }
.dir-avail-dot.dir-avail-open { background: var(--ok); box-shadow: 0 0 0 3px var(--ok-soft); }
.dir-avail-dot.dir-avail-limited { background: var(--dir-month, #f59e0b); box-shadow: 0 0 0 3px var(--warn-soft); }
.dir-avail-dot.dir-avail-busy { background: transparent; box-shadow: inset 0 0 0 2px var(--dir-idle, #8b92a8); }
.dir-group:has(> .dir-err) .plan .box { border-color: color-mix(in srgb, var(--bad) 55%, var(--line-2)); }

/* ---------- skill picker ---------- */
.dir-skill-pick { --dir-fill: 0%; display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px; padding: 18px; border-radius: var(--r); background: var(--dir-f-sec-bg); border: 1px solid var(--line); }
@media (max-width: 420px) { .dir-skill-pick { padding: 14px; margin: 0 -2px; } }
.dir-group:has(> .dir-err) .dir-skill-pick { border-color: rgba(239, 68, 68, .45); background: color-mix(in srgb, var(--bad) 4%, var(--dir-f-sec-bg)); }
.dir-skill-count {
  position: relative; justify-self: start; display: inline-flex; align-items: center; gap: 8px; margin: 0; padding: 7px 14px 9px;
  border-radius: 999px; background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-sm);
  font: 650 .86rem/1.2 var(--f-body); color: var(--ink-2); font-variant-numeric: tabular-nums; overflow: hidden;
}
.dir-skill-count::after {
  content: ""; position: absolute; left: 14px; right: 14px; bottom: 4px; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--accent) 0 var(--dir-fill), var(--line-2) var(--dir-fill) 100%); transition: background .2s;
}
.dir-skill-count.is-full { color: var(--accent-ink); border-color: rgba(106, 92, 255, .35); }
.dir-skill-count.is-empty { color: var(--ink-3); }
@media (prefers-reduced-motion: no-preference) {
  .dir-skill-count.is-nudge { animation: dir-nudge .38s cubic-bezier(.36, .07, .19, .97); }
  @keyframes dir-nudge { 20%, 60% { transform: translateX(-3px); } 40%, 80% { transform: translateX(3px); } }
}
.dir-skill-count.is-nudge { border-color: var(--accent); }
.dir-skill-group { display: grid; gap: 9px; min-width: 0; }
.dir-skill-group-name { margin: 0; font: 650 .74rem/1 var(--f-body); letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3); }
.dir-skill-chips { display: flex; flex-wrap: wrap; gap: 8px; }

.dir-skill-chip { position: relative; display: inline-flex; max-width: 100%; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.dir-skill-chip input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: inherit; z-index: 1; }
.dir-skill-chip span {
  display: inline-flex; align-items: center; gap: 7px; min-height: 40px; max-width: 100%; padding: 8px 15px 8px 11px; border-radius: 999px;
  background: var(--dir-f-chip-bg); border: 1.5px solid var(--dir-f-chip-line); color: var(--ink-2);
  font: 550 .9rem/1.25 var(--f-body); overflow-wrap: anywhere; user-select: none;
  transition: background-color .15s, border-color .15s, color .15s, box-shadow .15s, opacity .15s;
}
.dir-skill-chip span::before {
  content: ""; flex: none; width: 16px; height: 16px; background: currentColor; opacity: .7;
  -webkit-mask: var(--dir-f-plus) center / contain no-repeat; mask: var(--dir-f-plus) center / contain no-repeat;
}
.dir-skill-chip:hover span { border-color: color-mix(in srgb, var(--accent) 55%, var(--dir-f-chip-line)); color: var(--ink); }
.dir-skill-chip input:checked + span {
  color: #fff; background: var(--dir-f-chip-on); border-color: transparent; box-shadow: 0 6px 16px -8px rgba(91, 77, 255, .75), inset 0 1px 0 rgba(255, 255, 255, .2);
}
.dir-skill-chip input:checked + span::before { opacity: 1; -webkit-mask-image: var(--dir-f-check); mask-image: var(--dir-f-check); }
.dir-skill-chip input:focus-visible + span { outline: 3px solid var(--focus); outline-offset: 2px; }
.dir-skill-chip input:disabled { cursor: not-allowed; pointer-events: none; } /* lets the click reach the label, so JS can explain why */
.dir-skill-chip:has(input:disabled) { cursor: not-allowed; }
.dir-skill-chip input:disabled + span { color: var(--ink-3); background: transparent; border-style: dashed; border-color: var(--line-2); opacity: .75; }
.dir-skill-chip input:disabled + span::before { opacity: .45; }
@media (prefers-reduced-motion: no-preference) {
  .dir-skill-chip input:checked + span { animation: dir-pop .22s cubic-bezier(.2, .7, .2, 1.4); }
  @keyframes dir-pop { 0% { transform: scale(.94); } 100% { transform: scale(1); } }
}
@media (forced-colors: active) {
  .dir-skill-chip span { border: 1px solid CanvasText; }
  .dir-skill-chip input:checked + span { border: 3px solid Highlight; background: Canvas; color: CanvasText; }
  .dir-skill-chip span::before { background: CanvasText; }
  .dir-skill-chip input:disabled + span { color: GrayText; border-color: GrayText; }
  .dir-fs-num { border: 1px solid CanvasText; }
}

/* ---------- checkboxes ---------- */
.dir-remote { align-items: center; min-height: 32px; }
.dir-remote input { margin-top: 0; }
.dir-terms { display: grid; gap: 8px; padding: 14px 16px; border-radius: 14px; background: var(--dir-f-sec-bg); border: 1px solid var(--line); }
.dir-terms:has([aria-invalid="true"]) { border-color: rgba(239, 68, 68, .45); }
.dir-terms .check span { color: var(--ink-2); }

/* ---------- submit ---------- */
.dir-form .form-foot { margin-top: 18px; }
.dir-form[data-mode="manage"] .form-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 14px; }
.dir-form[data-mode="manage"] .reassure { flex: 1 1 18rem; }
@media (max-width: 560px) { .dir-submit { width: 100%; } }

/* ---------- copy feedback ---------- */
.dir-copy-btn { transition: background-color .2s, color .2s, border-color .2s, box-shadow .2s; }
.dir-copy-btn.is-copied, .dir-copy-btn.is-copied:hover { color: var(--ok-ink); background: var(--ok-soft); border-color: rgba(34, 197, 94, .5); box-shadow: none; transform: none; }

/* ---------- utilities ---------- */
.dir-sr-live { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ---------- small screens (360px: 16px gutters, nothing wider than the viewport) ---------- */
@media (max-width: 560px) {
  .dir-fs { gap: 18px; padding-bottom: 26px; margin-bottom: 26px; }
  .dir-skill-chip span { font-size: .88rem; padding: 8px 13px 8px 10px; }
}
@media print {
  .dir-skill-chip input:not(:checked) + span { display: none; }
  .dir-copy-btn { display: none; }
}
