/* ds-components.css -- the shared component layer (UX phase P1). Loaded by the three layouts AFTER each page's
   Styles section so it wins at equal specificity. Every selector starts with .ds- (or is a :where() with zero
   specificity), so nothing that exists today can match: pages opt in by using the classes. Values come from
   ds-tokens.css only: no hex literals, no font-size below 12px, @media widths 480/768/1024/1440 only. */

/* ---- base: focus ring and reduced motion (zero-specificity, existing rules win) ---- */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--ds-focus); outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
  .ds-btn, .ds-field__control, .ds-card, .ds-toast, .ds-sheet, .ds-meter__bar > i, .ds-skeleton { transition: none; animation: none; }
}
.ds-sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.ds-root { font-family: var(--ds-font-sans); font-size: var(--ds-fs-ui); line-height: var(--ds-lh-dense); color: var(--ds-text); background: var(--ds-bg); }

/* ---- button ---- */
.ds-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--ds-sp-2);
  min-height: var(--ds-ctl-h); padding: 0 var(--ds-sp-5); box-sizing: border-box;
  font: inherit; font-size: var(--ds-fs-ui); font-weight: var(--ds-fw-bold); line-height: 1.2; text-decoration: none; text-align: center;
  color: var(--ds-text); background: var(--ds-surface); border: 1.5px solid var(--ds-border-strong); border-radius: var(--ds-r-pill);
  cursor: pointer; transition: background var(--ds-dur-1) var(--ds-ease), border-color var(--ds-dur-1) var(--ds-ease), box-shadow var(--ds-dur-1) var(--ds-ease);
}
.ds-btn:hover { background: var(--ds-surface-2); border-color: var(--ds-text-faint); }
.ds-btn--primary { color: var(--ds-on-brand); background: var(--ds-brand-600); border-color: var(--ds-brand-600); box-shadow: var(--ds-sh-primary); }
.ds-btn--primary:hover { color: var(--ds-on-brand); background: var(--ds-brand-700); border-color: var(--ds-brand-700); }
.ds-btn--secondary { color: var(--ds-brand-600); background: transparent; border-color: var(--ds-brand-600); }
.ds-btn--secondary:hover { background: var(--ds-brand-tint); border-color: var(--ds-brand-600); }
.ds-btn--ghost { color: var(--ds-brand-600); background: transparent; border-color: transparent; }
.ds-btn--ghost:hover { background: var(--ds-brand-tint); border-color: transparent; }
.ds-btn--danger { color: var(--ds-surface); background: var(--ds-danger-ink); border-color: var(--ds-danger-ink); }
.ds-btn--danger:hover { color: var(--ds-surface); background: var(--ds-danger-ink); border-color: var(--ds-danger-ink); filter: brightness(.92); }
.ds-btn--danger-outline { color: var(--ds-danger-ink); background: transparent; border-color: var(--ds-danger-ink); }
.ds-btn--danger-outline:hover { background: var(--ds-danger-bg); border-color: var(--ds-danger-ink); }
.ds-btn--compact { min-height: var(--ds-ctl-h-sm); padding: 0 var(--ds-sp-3); }
.ds-btn--block { display: flex; width: 100%; }
.ds-btn:disabled, .ds-btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; box-shadow: none; pointer-events: none; }
.ds-btn[aria-busy="true"] { cursor: progress; pointer-events: none; }
.ds-btn[aria-busy="true"]::before {
  content: ""; width: 14px; height: 14px; flex: none; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent; animation: ds-spin .8s linear infinite;
}
@keyframes ds-spin { to { transform: rotate(360deg); } }
.ds-icon-btn {
  display: inline-flex; align-items: center; justify-content: center; width: var(--ds-tap); height: var(--ds-tap); padding: 0; box-sizing: border-box;
  color: var(--ds-text-body); background: transparent; border: 0; border-radius: var(--ds-r-xs); cursor: pointer;
}
.ds-icon-btn:hover { background: var(--ds-surface-2); color: var(--ds-text); }

/* ---- field ---- */
.ds-field { display: flex; flex-direction: column; gap: var(--ds-sp-1); margin: 0 0 var(--ds-sp-4); }
.ds-field__label { font-size: var(--ds-fs-value); font-weight: var(--ds-fw-bold); color: var(--ds-text); }
.ds-field__hint { font-size: var(--ds-fs-label); color: var(--ds-text-muted); }
.ds-field__error { font-size: var(--ds-fs-value); color: var(--ds-danger-ink); }
.ds-field__control {
  width: 100%; min-height: var(--ds-ctl-h); padding: 0 var(--ds-sp-3); box-sizing: border-box;
  font: inherit; font-size: var(--ds-fs-input); color: var(--ds-text); background: var(--ds-surface);
  border: 1.5px solid var(--ds-border-strong); border-radius: var(--ds-r-md); transition: border-color var(--ds-dur-1) var(--ds-ease);
}
textarea.ds-field__control { min-height: 96px; padding: var(--ds-sp-3); }
.ds-field__control:hover { border-color: var(--ds-text-faint); }
.ds-field__control:focus { border-color: var(--ds-brand-600); }
/* A text field shows focus as one crisp blue border (the border plus a 1px inset line), not a border with a second ring floating outside it. */
.ds-field__control:focus-visible { outline: none; border-color: var(--ds-brand-600); box-shadow: inset 0 0 0 1px var(--ds-brand-600); }
/* The consoles draw their own 2px ring 2px outside every input and a soft tinted halo on the older .form-input; for text fields both give way to the same single border. */
:is(body.admin, .org-console, .account-console) .portal-content :is(.ds-field__control, .form-input):is(:focus, :focus-visible),
dialog.ui-dialog .form-input:is(:focus, :focus-visible) { outline: none; border-color: var(--ds-brand-600); box-shadow: inset 0 0 0 1px var(--ds-brand-600); }
.ds-field__control:disabled { opacity: .5; cursor: not-allowed; }
.ds-field__control[aria-invalid="true"] { border-color: var(--ds-danger-ink); }
.ds-check { display: flex; align-items: center; gap: var(--ds-sp-3); min-height: var(--ds-tap); font-size: var(--ds-fs-ui); color: var(--ds-text); }
.ds-check input { width: 20px; height: 20px; flex: none; margin: 0; accent-color: var(--ds-brand-600); }

/* ---- card ---- */
.ds-card { background: var(--ds-surface); color: var(--ds-text); border: 1px solid var(--ds-border); border-radius: var(--ds-r-md); box-shadow: var(--ds-sh-1); padding: var(--ds-sp-5); }
.ds-card--marketing { border-radius: var(--ds-r-xl); box-shadow: var(--ds-sh-2); }
.ds-card__title { margin: 0 0 var(--ds-sp-2); color: var(--ds-text); font-size: var(--ds-fs-title); font-weight: var(--ds-fw-bold); line-height: var(--ds-lh-tight); }
.ds-card__body { margin: 0; font-size: var(--ds-fs-prose); color: var(--ds-text-body); line-height: var(--ds-lh-body); }

/* ---- badge ---- */
.ds-badge {
  display: inline-flex; align-items: center; gap: var(--ds-sp-1); padding: 2px var(--ds-sp-3); box-sizing: border-box;
  font-size: var(--ds-fs-value); font-weight: var(--ds-fw-semibold); line-height: 1.4; white-space: nowrap;
  color: var(--ds-text-body); background: var(--ds-surface-2); border: 1px solid var(--ds-border-strong); border-radius: var(--ds-r-pill);
}
.ds-badge--info { color: var(--ds-info-ink); background: var(--ds-info-bg); border-color: var(--ds-info); }
.ds-badge--success { color: var(--ds-success-ink); background: var(--ds-success-bg); border-color: var(--ds-success); }
.ds-badge--warning { color: var(--ds-warning-ink); background: var(--ds-warning-bg); border-color: var(--ds-warning); }
.ds-badge--danger { color: var(--ds-danger-ink); background: var(--ds-danger-bg); border-color: var(--ds-danger); }

/* ---- alert ---- */
.ds-alert {
  display: flex; align-items: flex-start; gap: var(--ds-sp-3); padding: var(--ds-sp-3) var(--ds-sp-4); box-sizing: border-box;
  font-size: var(--ds-fs-ui); color: var(--ds-text); background: var(--ds-info-bg); border: 1px solid var(--ds-info); border-left-width: 4px; border-radius: var(--ds-r-md);
}
.ds-alert__title { margin: 0; font-weight: var(--ds-fw-bold); }
.ds-alert__body { margin: 2px 0 0; color: var(--ds-text-body); font-size: var(--ds-fs-prose); }
.ds-alert__text { flex: 1; min-width: 0; }
.ds-alert__close { margin: calc(var(--ds-sp-2) * -1) calc(var(--ds-sp-2) * -1) calc(var(--ds-sp-2) * -1) 0; }
.ds-alert--info .ds-alert__title { color: var(--ds-info-ink); }
.ds-alert--success { background: var(--ds-success-bg); border-color: var(--ds-success); }
.ds-alert--success .ds-alert__title { color: var(--ds-success-ink); }
.ds-alert--warning { background: var(--ds-warning-bg); border-color: var(--ds-warning); }
.ds-alert--warning .ds-alert__title { color: var(--ds-warning-ink); }
.ds-alert--danger { background: var(--ds-danger-bg); border-color: var(--ds-danger); }
.ds-alert--danger .ds-alert__title { color: var(--ds-danger-ink); }

/* ---- toast: one live region, bottom centre above the safe area ---- */
.ds-toast-region {
  position: fixed; left: 50%; bottom: calc(var(--ds-sp-4) + var(--ds-safe-b)); transform: translateX(-50%);
  z-index: var(--ds-z-popover); width: min(92vw, 420px); display: flex; flex-direction: column; align-items: stretch; pointer-events: none;
}
.ds-toast {
  display: flex; align-items: center; gap: var(--ds-sp-3); padding: var(--ds-sp-3) var(--ds-sp-4); pointer-events: auto;
  font-size: var(--ds-fs-ui); color: var(--ds-on-brand); background: var(--ds-navy-800); border-radius: var(--ds-r-md); box-shadow: var(--ds-sh-3);
}
.ds-toast[hidden] { display: none; }
:root[data-ds-theme="dark"] .ds-toast { background: var(--ds-surface-2); color: var(--ds-text); border: 1px solid var(--ds-border-strong); }
.ds-toast__msg { flex: 1; min-width: 0; }
.ds-toast__action { color: var(--ds-accent-cyan); font-weight: var(--ds-fw-bold); background: none; border: 0; min-height: var(--ds-tap); padding: 0 var(--ds-sp-2); cursor: pointer; font: inherit; }

/* ---- empty state ---- */
.ds-empty { display: flex; flex-direction: column; align-items: center; gap: var(--ds-sp-3); padding: var(--ds-sp-8) var(--ds-sp-5); text-align: center; color: var(--ds-text-body); border: 1.5px dashed var(--ds-border-strong); border-radius: var(--ds-r-md); }
.ds-empty__icon { width: 40px; height: 40px; color: var(--ds-text-faint); }
.ds-empty__text { margin: 0; font-size: var(--ds-fs-prose); max-width: 38ch; }

/* ---- pager ---- */
.ds-pager { display: flex; align-items: center; justify-content: space-between; gap: var(--ds-sp-3); font-size: var(--ds-fs-value); color: var(--ds-text-muted); }

/* ---- meter: usage bar with "x of y" and a reset line ---- */
.ds-meter { display: flex; flex-direction: column; gap: var(--ds-sp-1); }
.ds-meter__head { display: flex; justify-content: space-between; gap: var(--ds-sp-3); font-size: var(--ds-fs-value); color: var(--ds-text); font-weight: var(--ds-fw-semibold); }
.ds-meter__bar { height: 8px; overflow: hidden; background: var(--ds-surface-2); border: 1px solid var(--ds-border); border-radius: var(--ds-r-pill); }
.ds-meter__bar > i { display: block; height: 100%; width: var(--ds-meter, 0%); background: var(--ds-brand-600); border-radius: var(--ds-r-pill); transition: width var(--ds-dur-3) var(--ds-ease); }
.ds-meter--warning .ds-meter__bar > i { background: var(--ds-warning); }
.ds-meter--danger .ds-meter__bar > i { background: var(--ds-danger); }
.ds-meter__reset { font-size: var(--ds-fs-label); color: var(--ds-text-muted); }

/* ---- table (+ card list below 768) ---- */
.ds-table { width: 100%; border-collapse: collapse; font-size: var(--ds-fs-ui); color: var(--ds-text); }
.ds-table th { padding: var(--ds-sp-3); text-align: left; font-size: var(--ds-fs-value); font-weight: var(--ds-fw-bold); color: var(--ds-text-muted); background: var(--ds-bg-soft); border-bottom: 1px solid var(--ds-border-strong); }
.ds-table td { padding: var(--ds-sp-3); border-bottom: 1px solid var(--ds-border); vertical-align: middle; }
.ds-table tbody tr:hover { background: var(--ds-bg-soft); }
.ds-table .ds-num { text-align: right; font-variant-numeric: tabular-nums; }
@media (max-width: 768px) {
  .ds-table--cards, .ds-table--cards tbody, .ds-table--cards tr, .ds-table--cards td { display: block; width: 100%; box-sizing: border-box; }
  .ds-table--cards thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .ds-table--cards tr { margin: 0 0 var(--ds-sp-3); padding: var(--ds-sp-2) var(--ds-sp-4); background: var(--ds-surface); border: 1px solid var(--ds-border); border-radius: var(--ds-r-md); }
  .ds-table--cards tbody tr:hover { background: var(--ds-surface); }
  .ds-table--cards td { display: flex; justify-content: space-between; gap: var(--ds-sp-4); padding: var(--ds-sp-2) 0; border-bottom: 1px solid var(--ds-border); text-align: right; }
  .ds-table--cards td:last-child { border-bottom: 0; }
  .ds-table--cards td::before { content: attr(data-label); flex: none; font-size: var(--ds-fs-value); font-weight: var(--ds-fw-bold); color: var(--ds-text-muted); text-align: left; }
  .ds-table--cards td:first-child { display: block; font-size: var(--ds-fs-title); font-weight: var(--ds-fw-bold); text-align: left; }
  .ds-table--cards td:first-child::before { display: none; }
}

/* ---- sheet: a <dialog>; centred card on desktop, bottom sheet on phones ---- */
.ds-sheet {
  width: min(92vw, 420px); max-height: 90vh; max-height: 90dvh; margin: auto; padding: var(--ds-sp-6); box-sizing: border-box; overflow: auto;
  color: var(--ds-text); background: var(--ds-surface); border: 1px solid var(--ds-border); border-radius: var(--ds-r-lg); box-shadow: var(--ds-sh-3);
}
.ds-sheet::backdrop { background: color-mix(in srgb, var(--ds-navy-900) 55%, transparent); }
.ds-sheet__title { margin: 0 0 var(--ds-sp-2); font-family: var(--ds-font-sans); color: var(--ds-text); font-size: var(--ds-fs-title); font-weight: var(--ds-fw-bold); }
.ds-sheet__body { margin: 0 0 var(--ds-sp-5); font-size: var(--ds-fs-prose); color: var(--ds-text-body); line-height: var(--ds-lh-body); }
.ds-sheet__actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--ds-sp-3); }
@media (max-width: 480px) {
  .ds-sheet { width: min(92vw, 420px); max-width: calc(100vw - 32px); margin: auto; border-radius: var(--ds-r-lg); }
  .ds-sheet__actions { flex-direction: column-reverse; }
  .ds-sheet__actions .ds-btn { width: 100%; }
}

/* ---- skeleton ---- */
.ds-skeleton { display: block; height: 1em; background: linear-gradient(90deg, var(--ds-surface-2), var(--ds-bg-soft), var(--ds-surface-2)); background-size: 200% 100%; border-radius: var(--ds-r-xs); animation: ds-shimmer 1.4s linear infinite; }
@keyframes ds-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* ---- layout helpers used by the gallery ---- */
.ds-stack { display: flex; flex-direction: column; gap: var(--ds-sp-4); }
.ds-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ds-sp-3); }
@media (max-width: 480px) { .ds-form-actions .ds-btn { width: 100%; } }

/* ---- one popup design: the confirm dialog (console.js, dialog.ui-dialog) takes the sheet's tokens ----
   It was built before the design system, on the legacy console tokens (own radius, padding, 17px title, 40px square buttons), so the app had two
   popups. Same surface, border, radius, shadow, backdrop, type scale, field and pill buttons as .ds-sheet; the markup and behaviour are unchanged. */
html dialog.ui-dialog {
  width: min(92vw, 420px); padding: var(--ds-sp-6); box-sizing: border-box;
  color: var(--ds-text); background: var(--ds-surface); border: 1px solid var(--ds-border); border-radius: var(--ds-r-lg); box-shadow: var(--ds-sh-3);
  font-family: var(--ds-font-sans);
}
html dialog.ui-dialog::backdrop { background: color-mix(in srgb, var(--ds-navy-900) 55%, transparent); }
html dialog.ui-dialog h2 { margin: 0 0 var(--ds-sp-2); font: inherit; font-family: var(--ds-font-sans); font-size: var(--ds-fs-title); font-weight: var(--ds-fw-bold); letter-spacing: 0; color: var(--ds-text); }
html dialog.ui-dialog #ui-dialog-body { margin: 0 0 var(--ds-sp-5); font-size: var(--ds-fs-prose); font-weight: inherit; line-height: var(--ds-lh-body); color: var(--ds-text-body); }
html dialog.ui-dialog .ui-dialog-slot { margin-top: 0; }
html dialog.ui-dialog form { gap: var(--ds-sp-4); }
html dialog.ui-dialog .form-group { gap: var(--ds-sp-2); }
html dialog.ui-dialog .form-group > label, html dialog.ui-dialog label.form-label { font-size: var(--ds-fs-ui); font-weight: var(--ds-fw-semibold); color: var(--ds-text); }
html dialog.ui-dialog .form-input { height: auto; min-height: var(--ds-ctl-h); padding: 0 var(--ds-sp-3); font-size: var(--ds-fs-input); color: var(--ds-text); background-color: var(--ds-surface); border: 1.5px solid var(--ds-border-strong); border-radius: var(--ds-r-md); }
html dialog.ui-dialog .ui-dialog-detail { font-size: var(--ds-fs-ui); color: var(--ds-text-body); }
html dialog.ui-dialog .ui-dialog-actions { gap: var(--ds-sp-3); margin-top: 0; flex-wrap: wrap; }
html dialog.ui-dialog .btn { height: auto; min-height: var(--ds-ctl-h); padding: 0 var(--ds-sp-5); border-radius: var(--ds-r-pill); font-size: var(--ds-fs-ui); font-weight: var(--ds-fw-bold); line-height: 1.2; border-width: 1.5px; }
html dialog.ui-dialog .btn-outline { color: var(--ds-text); background: var(--ds-surface); border-color: var(--ds-border-strong); }
html dialog.ui-dialog .btn-outline:hover { background: var(--ds-surface-2); border-color: var(--ds-text-faint); color: var(--ds-text); }
html dialog.ui-dialog .btn-primary { color: var(--ds-on-brand); background: var(--ds-brand-600); border-color: var(--ds-brand-600); box-shadow: var(--ds-sh-primary); }
html dialog.ui-dialog .btn-primary:hover { background: var(--ds-brand-700); border-color: var(--ds-brand-700); color: var(--ds-on-brand); }
html dialog.ui-dialog .btn-danger { color: var(--ds-surface); background: var(--ds-danger-ink); border-color: var(--ds-danger-ink); }
html[data-theme="dark"] dialog.ui-dialog .btn-primary { color: var(--ds-on-brand); }
html[data-theme="dark"] dialog.ui-dialog .btn-danger { color: var(--ds-surface); }
@media (max-width: 480px) {
  html dialog.ui-dialog { width: min(92vw, 420px); max-width: calc(100vw - 32px); margin: auto; border-radius: var(--ds-r-lg); }
}
html dialog.ui-dialog #ui-dialog-body[hidden] + .ui-dialog-slot { margin-top: var(--ds-sp-4); }
html[data-ds-ask-danger] dialog.ui-dialog .btn-primary { color: var(--ds-surface); background: var(--ds-danger-ink); border-color: var(--ds-danger-ink); box-shadow: none; }
html[data-ds-ask-danger] dialog.ui-dialog .btn-primary:hover { color: var(--ds-surface); background: var(--ds-danger-ink); border-color: var(--ds-danger-ink); filter: brightness(.92); }

/* Opening a popup focuses the dialog box itself; the shared :focus-visible ring then drew a blue frame around the whole popup. The box is not a control:
   no ring on it, while the fields and buttons inside keep theirs. */
html dialog.ds-sheet:focus, html dialog.ds-sheet:focus-visible, html dialog.ui-dialog:focus, html dialog.ui-dialog:focus-visible { outline: none; }

/* Dropdowns: the browser's own arrow hugged the right edge. Draw one from two token-coloured gradients (so it follows the theme) and inset it. */
select.ds-field__control {
  --ds-select-caret: 6px;
  -webkit-appearance: none; appearance: none; padding-right: var(--ds-sp-10, 40px);
  background-image: linear-gradient(45deg, transparent 50%, var(--ds-text-muted) 50%), linear-gradient(135deg, var(--ds-text-muted) 50%, transparent 50%);
  background-repeat: no-repeat; background-size: var(--ds-select-caret) var(--ds-select-caret), var(--ds-select-caret) var(--ds-select-caret);
  background-position: calc(100% - var(--ds-sp-6) - var(--ds-select-caret)) 50%, calc(100% - var(--ds-sp-6)) 50%;
}
select.ds-field__control:hover, select.ds-field__control:focus { background-image: linear-gradient(45deg, transparent 50%, var(--ds-text) 50%), linear-gradient(135deg, var(--ds-text) 50%, transparent 50%); }

/* Friendly status pages (404, 403, 429, ...): a themed panel, readable in light and dark whatever the page behind it is. */
.ds-status { max-width: 600px; margin: clamp(24px, 4vw, 56px) auto; padding: clamp(24px, 4vw, 48px); text-align: center; color: var(--ds-text); background: var(--ds-surface); border: 1px solid var(--ds-border); border-radius: var(--ds-r-lg); box-shadow: var(--ds-sh-2); }
.ds-status__code { font-size: var(--ds-fs-label); font-weight: var(--ds-fw-bold); letter-spacing: .18em; color: var(--ds-brand-600); }
.ds-status__title { margin: var(--ds-sp-2) 0 0; font-family: var(--ds-font-display); font-size: var(--ds-fs-display); font-weight: var(--ds-fw-regular); line-height: var(--ds-lh-tight); color: var(--ds-text); }
.ds-status__text { margin: var(--ds-sp-4) 0 0; font-size: var(--ds-fs-prose); line-height: var(--ds-lh-body); color: var(--ds-text-muted); }
.ds-status__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--ds-sp-3); margin-top: var(--ds-sp-6); }
