/* ═══════════════════════════════════════════════════════════
   Portfolio · Design System · Primitives
   ───────────────────────────────────────────────────────────
   Canonical ds-* primitives. Use these for new code.
   Visuals match the current .btn-*, .section-marker / .cs-marker,
   .cs-prose, .field — but those legacy classes stay defined
   in their own places (style.css / _template/index.html) for
   pixel fidelity. The dedup win lives at the TOKEN level above.
   ═══════════════════════════════════════════════════════════ */


/* ─── ds-button ─────────────────────────────────────────────
   Variants: --primary (filled persimmon), --ghost (outlined),
   --tertiary (text-only with accent hover).
   ─────────────────────────────────────────────────────────── */
.ds-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 0 var(--space-5);
  height: 50px;
  font-family: inherit;
  font-size: var(--type-caption);
  font-weight: 500;
  line-height: 1;
  border-radius: var(--radius-full);
  border: 1.5px solid transparent;
  background: transparent;
  color: var(--color-fg);
  cursor: pointer;
  text-decoration: none;
  box-sizing: border-box;
  transition: all var(--duration-medium) var(--ease-standard);
}
.ds-button:active { transform: scale(0.98); }
.ds-button:focus-visible {
  outline: 2px solid var(--color-fg);
  outline-offset: 3px;
}

/* Buttons are NEUTRAL — themes never recolour them (common controls
   stay neutral; the accent lives in point text / highlight / small
   visuals only). */
.ds-button--primary {
  background: var(--color-button-fill);
  color: var(--color-button-label);
  border-color: var(--color-button-fill);
  font-weight: 600;
}
.ds-button--primary:hover {
  background: var(--color-button-fill-hover);
  border-color: var(--color-button-fill-hover);
  transform: scale(1.02);
}

.ds-button--ghost {
  border-color: var(--color-button-border);
  color: var(--color-fg);
}
.ds-button--ghost:hover {
  border-color: var(--color-button-border-hover);
  color: var(--color-fg);
  transform: scale(1.02);
}

.ds-button--tertiary {
  height: auto;
  padding: 0;
  border: none;
  background: none;
  font-weight: 600;
  color: var(--color-fg);
  border-radius: var(--radius-sm);
  transition: color var(--duration-short) ease, transform var(--duration-short) ease;
}
.ds-button--tertiary:hover {
  color: var(--color-fg);
  transform: translateX(2px);
}

/* States — neutral (no brand colour in the control) */
.ds-button[disabled],
.ds-button[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}
.ds-button.is-loading {
  position: relative;
  color: transparent !important;
  pointer-events: none;
}
.ds-button.is-loading::after {
  content: "";
  position: absolute;
  width: 1em; height: 1em;
  border: 2px solid var(--color-button-label);
  border-top-color: transparent;
  border-radius: var(--radius-full);
  animation: ds-spin 0.6s linear infinite;
}
.ds-button--ghost.is-loading::after,
.ds-button--tertiary.is-loading::after { border-color: var(--color-fg); border-top-color: transparent; }
@keyframes ds-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .ds-button.is-loading::after { animation: none; } }


/* ─── ds-marker ─────────────────────────────────────────────
   Section marker — eyebrow + dot + number + label.
   Modifier --sub for inner sub-section markers.
   Modifier --light for inverse / dark backgrounds.
   ─────────────────────────────────────────────────────────── */
.ds-marker {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: inherit;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-fg-muted);
  white-space: nowrap;
}
.ds-marker__dot {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--color-accent);
  display: inline-block;
  flex-shrink: 0;
}
.ds-marker__num { color: var(--color-fg); font-weight: 600; }
.ds-marker__sep { opacity: 0.45; }
.ds-marker--light { color: #B5ADAA; }
.ds-marker--light .ds-marker__num { color: var(--color-bg); }
.ds-marker--sub {
  font-size: var(--type-micro);
  letter-spacing: 0.18em;
  color: var(--color-fg-subtle);
}
.ds-marker--sub .ds-marker__dot { width: 4px; height: 4px; }
.ds-marker--sub .ds-marker__num { color: var(--color-fg-muted); font-weight: 500; }


/* ─── ds-prose ──────────────────────────────────────────────
   Body copy with persimmon em highlight wash.
   ─────────────────────────────────────────────────────────── */
.ds-prose {
  max-width: 58ch;
  font-size: 1.125rem;
  line-height: var(--leading-loose);
  color: var(--color-fg-muted);
}
.ds-prose p { margin: 0 0 1em; }
.ds-prose p:last-child { margin-bottom: 0; }
.ds-prose em {
  font-style: normal;
  font-weight: 500;
  color: var(--color-accent-text);
  background-image: linear-gradient(var(--color-accent-soft), var(--color-accent-soft));
  background-repeat: no-repeat;
  background-size: 100% 42%;
  background-position: 0 88%;
  padding: 0 0.05em;
}
.ds-prose strong { color: var(--color-fg); font-weight: 600; }


/* ─── ds-field ──────────────────────────────────────────────
   Form input. Border-only, focus collapses to ink.
   ─────────────────────────────────────────────────────────── */
.ds-field {
  width: 100%;
  padding: 14px 16px;
  background: var(--color-bg);
  border: 1.5px solid var(--color-line-strong);
  border-radius: 12px;
  font-family: inherit;
  font-size: var(--type-caption);
  color: var(--color-fg);
  transition: border-color var(--duration-short) ease, box-shadow var(--duration-short) ease;
  outline: none;
}
.ds-field::placeholder { color: var(--color-line-strong); }
.ds-field:focus { border-color: var(--color-fg); box-shadow: none; outline: none; }
.ds-field:focus-visible { outline: 2px solid var(--color-fg); outline-offset: 2px; }
.ds-field:disabled { opacity: 0.5; cursor: not-allowed; background: var(--color-bg-surface); }


/* ─── ds-card ───────────────────────────────────────────────
   Variants: (basic, default) --elevated --interactive --selectable.
   Neutral — no brand colour, selected ring is ink. Parts __title __text.
   ─────────────────────────────────────────────────────────── */
.ds-card {
  background: var(--color-bg);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
}
.ds-card__title { font-size: var(--type-h4); font-weight: 600; color: var(--color-fg); margin: 0 0 var(--space-2); }
.ds-card__text  { font-size: var(--type-caption); line-height: var(--leading-base); color: var(--color-fg-muted); margin: 0; }
.ds-card--elevated { border-color: transparent; box-shadow: var(--shadow-card); }
.ds-card--interactive {
  cursor: pointer;
  transition: border-color var(--duration-short) var(--ease-standard),
              box-shadow var(--duration-short) var(--ease-standard),
              transform var(--duration-short) var(--ease-standard);
}
.ds-card--interactive:hover { border-color: var(--color-line-strong); box-shadow: var(--shadow-card); transform: translateY(-2px); }
.ds-card--interactive:focus-visible { outline: 2px solid var(--color-fg); outline-offset: 2px; }
.ds-card--selectable { cursor: pointer; transition: border-color var(--duration-short) var(--ease-standard), box-shadow var(--duration-short) var(--ease-standard); }
.ds-card--selectable:hover { border-color: var(--color-line-strong); }
.ds-card--selectable.is-selected,
.ds-card--selectable[aria-pressed="true"] { border-color: var(--color-fg); box-shadow: 0 0 0 2px var(--color-fg); }
@media (prefers-reduced-motion: reduce) {
  .ds-card--interactive, .ds-card--selectable { transition: none; }
  .ds-card--interactive:hover { transform: none; }
}


/* ─── ds-reveal ─────────────────────────────────────────────
   Scroll-triggered fade + rise. Toggle .is-visible on the
   element from your IntersectionObserver.
   Delay variants --d1..--d5 for stagger.
   ─────────────────────────────────────────────────────────── */
.ds-reveal {
  opacity: 0;
  transform: translateY(22px);
  transition:
    opacity var(--duration-x-long) var(--ease-standard),
    transform var(--duration-x-long) var(--ease-standard);
}
.ds-reveal.is-visible { opacity: 1; transform: translateY(0); }
.ds-reveal--d1 { transition-delay: 90ms; }
.ds-reveal--d2 { transition-delay: 180ms; }
.ds-reveal--d3 { transition-delay: 270ms; }
.ds-reveal--d4 { transition-delay: 360ms; }
.ds-reveal--d5 { transition-delay: 450ms; }
@media (max-width: 767px) {
  .ds-reveal--d2,
  .ds-reveal--d3,
  .ds-reveal--d4,
  .ds-reveal--d5 { transition-delay: 0ms; }
}
@media (prefers-reduced-motion: reduce) {
  .ds-reveal { opacity: 1; transform: none; transition: none; }
}
