/* ==========================================================================
   Deskrune — Element-level v2 IMPECCABLE pass (universal)
   File: /assets/v2-elements-v20260508b.css

   Scope: every BUTTON, every INPUT, every LINK, every focus state across
   the entire site. Loaded LAST in <head> after style.css, contrast-fixes,
   theme.css, and any page-specific v2-*.css. This file is THE final say
   on element-level micro-polish.

   Reuses the canonical --ds-* tokens from theme.css for color so dark mode
   is automatic. Brand orange is #c9613f (light) / lighter coral derivative
   in dark mode via the token system. No new color tokens introduced.

   Layered as @layer impeccable so we beat author-stylesheet specificity
   without resorting to !important when possible. Where legacy
   contrast-fixes use !important on the same selector, we explicitly
   match it. Each block is commented with category + principle.
   ========================================================================== */

@layer impeccable {

/* ==========================================================================
   UNIVERSAL — applies to every interactive node site-wide
   ========================================================================== */

/* --------------------------------------------------------------------------
   U1. Selection color — branded.
   Principle: when a user highlights any text, the selection feels like the
   brand, not a default OS blue. rgba so text contrast remains.
   -------------------------------------------------------------------------- */
::selection {
  background: rgba(201, 97, 63, 0.25);
  color: var(--ds-ink, #14140e);
}
:root[data-theme="dark"] ::selection {
  background: rgba(232, 133, 106, 0.32);
  color: var(--ds-ink, #f0e9dc);
}

/* --------------------------------------------------------------------------
   U2. Custom branded scrollbars (WebKit + Firefox).
   Principle: chrome details belong to the brand. 8px is wide enough to
   grab on trackpads, narrow enough not to dominate.
   -------------------------------------------------------------------------- */
* {
  scrollbar-width: thin;
  scrollbar-color: rgba(201, 97, 63, 0.32) transparent;
}
*::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
*::-webkit-scrollbar-track {
  background: transparent;
}
*::-webkit-scrollbar-thumb {
  background: rgba(201, 97, 63, 0.30);
  border-radius: 8px;
}
*::-webkit-scrollbar-thumb:hover {
  background: rgba(201, 97, 63, 0.55);
}
:root[data-theme="dark"] * {
  scrollbar-color: rgba(232, 133, 106, 0.36) transparent;
}
:root[data-theme="dark"] *::-webkit-scrollbar-thumb {
  background: rgba(232, 133, 106, 0.32);
}
:root[data-theme="dark"] *::-webkit-scrollbar-thumb:hover {
  background: rgba(232, 133, 106, 0.55);
}

/* --------------------------------------------------------------------------
   U3. Universal :focus-visible ring — final word.
   Principle: every keyboardable element gets a 2px brand orange ring with
   2px offset. NEVER suppressed by `*` rules. Works in both modes via the
   --ds-accent token. We use double-layer (outline + box-shadow halo) for
   3:1+ non-text contrast on busy backgrounds (WCAG SC 1.4.11).
   -------------------------------------------------------------------------- */
:where(a, button, input, select, textarea, summary, [tabindex], [role="button"], [role="link"], label):focus {
  outline: none;
}
:where(a, button, input, select, textarea, summary, [tabindex], [role="button"], [role="link"], label):focus-visible {
  outline: 2px solid var(--ds-accent, #c9613f);
  outline-offset: 2px;
  border-radius: 3px;
  box-shadow: 0 0 0 4px rgba(201, 97, 63, 0.18);
  transition: box-shadow 120ms ease-out;
}
:root[data-theme="dark"] :where(a, button, input, select, textarea, summary, [tabindex], [role="button"], [role="link"], label):focus-visible {
  outline-color: var(--ds-accent, #e8856a);
  box-shadow: 0 0 0 4px rgba(232, 133, 106, 0.24);
}


/* ==========================================================================
   BUTTONS — every <button>, .btn, .cta, [role="button"]
   ========================================================================== */

/* --------------------------------------------------------------------------
   B1. Idle state — clear visual weight, consistent transition.
   Principle: every button feels solid before you touch it. 180ms cubic
   timing on transform + filter + box-shadow gives a sinusoidal feel that
   matches the rest of the brand motion language.
   -------------------------------------------------------------------------- */
button,
.btn,
.cta,
[role="button"] {
  transition:
    transform 180ms cubic-bezier(0.34, 1.16, 0.64, 1),
    filter 180ms ease-out,
    box-shadow 180ms ease-out,
    background-color 180ms ease-out,
    border-color 180ms ease-out,
    color 180ms ease-out;
  will-change: transform, filter;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* --------------------------------------------------------------------------
   B2. Hover — lift + brightness shift (only when not disabled).
   Principle: response is felt before it's seen. 1px lift + 1.05 brightness
   reads as "primed to act" without shouting. Excluding :disabled and
   [aria-disabled="true"] is critical — disabled buttons must not animate.
   -------------------------------------------------------------------------- */
button:not(:disabled):not([aria-disabled="true"]):hover,
.btn:not(:disabled):not([aria-disabled="true"]):hover,
.cta:not(:disabled):not([aria-disabled="true"]):hover,
[role="button"]:not([aria-disabled="true"]):hover {
  transform: translateY(-1px);
  filter: brightness(1.05);
}

/* --------------------------------------------------------------------------
   B3. Active (pressed) — depressed, no transition.
   Principle: when the finger is down, the button must not lag. We force
   transition to 0ms so the press feels immediate, then the release uses
   the normal 180ms back to idle.
   -------------------------------------------------------------------------- */
button:not(:disabled):not([aria-disabled="true"]):active,
.btn:not(:disabled):not([aria-disabled="true"]):active,
.cta:not(:disabled):not([aria-disabled="true"]):active,
[role="button"]:not([aria-disabled="true"]):active {
  transform: translateY(0);
  filter: brightness(0.95);
  transition: transform 0ms, filter 0ms;
}

/* --------------------------------------------------------------------------
   B4. Disabled — readable, not just dimmed.
   Principle: disabled buttons must remain visually parseable. opacity:0.55
   keeps them >3:1 for non-text contrast. cursor:not-allowed signals
   "I see this, I cannot use it." Existing contrast-fixes already pins
   colors — we add the cursor + remove transforms.
   -------------------------------------------------------------------------- */
button:disabled,
button[aria-disabled="true"],
.btn:disabled,
.cta:disabled,
[role="button"][aria-disabled="true"] {
  cursor: not-allowed;
  transform: none !important;
  filter: none !important;
}


/* ==========================================================================
   INPUTS — text, email, search, tel, url, password, number, textarea
   ========================================================================== */

/* --------------------------------------------------------------------------
   I1. Idle — soft 1px border, smooth focus prep.
   Principle: inputs invite, they don't intimidate. The base is calm; the
   focus is where the attention lives.
   -------------------------------------------------------------------------- */
input[type="text"],
input[type="email"],
input[type="search"],
input[type="tel"],
input[type="url"],
input[type="password"],
input[type="number"],
input[type="date"],
input[type="time"],
textarea {
  transition:
    border-color 180ms ease-out,
    box-shadow 180ms ease-out,
    background-color 180ms ease-out;
  -webkit-appearance: none;
  appearance: none;
}

/* --------------------------------------------------------------------------
   I2. Focus — brand-orange border + soft halo, NOT a hard outline jump.
   Principle: the border itself becomes the focus ring + a 3px tinted halo
   provides the secondary signal. This reads as "this is where you are
   typing" without the harsh OS-default outline jolt. The :focus-visible
   ring from U3 sits OUTSIDE the halo for keyboard focus, layered.
   -------------------------------------------------------------------------- */
input[type="text"]:focus,
input[type="email"]:focus,
input[type="search"]:focus,
input[type="tel"]:focus,
input[type="url"]:focus,
input[type="password"]:focus,
input[type="number"]:focus,
input[type="date"]:focus,
input[type="time"]:focus,
textarea:focus {
  border-color: var(--ds-accent, #c9613f);
  box-shadow: 0 0 0 3px rgba(201, 97, 63, 0.15);
}
:root[data-theme="dark"] input[type="text"]:focus,
:root[data-theme="dark"] input[type="email"]:focus,
:root[data-theme="dark"] input[type="search"]:focus,
:root[data-theme="dark"] textarea:focus {
  border-color: var(--ds-accent, #e8856a);
  box-shadow: 0 0 0 3px rgba(232, 133, 106, 0.22);
}

/* --------------------------------------------------------------------------
   I3. Invalid — red-orange border + halo, mirrors the focus pattern.
   Principle: errors are part of the conversation, not a punishment. We
   reuse the focus halo shape so the visual rhythm is preserved, just in a
   "stop and read" hue. Only applied via :user-invalid (modern, post-blur)
   to avoid shouting at people while they type.
   -------------------------------------------------------------------------- */
input:user-invalid,
textarea:user-invalid {
  border-color: #c9461c;
  box-shadow: 0 0 0 3px rgba(201, 70, 28, 0.15);
}
:root[data-theme="dark"] input:user-invalid,
:root[data-theme="dark"] textarea:user-invalid {
  border-color: #e6724b;
  box-shadow: 0 0 0 3px rgba(230, 114, 75, 0.20);
}

/* --------------------------------------------------------------------------
   I4. Disabled — bg shifted, cursor not-allowed.
   Principle: matches the button disabled language. The bg shift signals
   "frozen state," the cursor confirms it.
   -------------------------------------------------------------------------- */
input:disabled,
textarea:disabled {
  cursor: not-allowed;
  background: var(--ds-surface-2, #f2ede3);
  border-color: var(--ds-rule, #e8e2d7);
  color: var(--ds-ink-faint, #6f6a60);
}
:root[data-theme="dark"] input:disabled,
:root[data-theme="dark"] textarea:disabled {
  background: var(--ds-surface-2, #221e1a);
  border-color: var(--ds-rule, #2f2a24);
  color: var(--ds-ink-faint, #9a9285);
}

/* --------------------------------------------------------------------------
   I5. Mobile — prevent iOS auto-zoom. font-size must be ≥16px.
   Principle: nothing breaks the flow worse than the page zooming when an
   input gets focus. iOS does this if font-size <16px. We force minimum.
   -------------------------------------------------------------------------- */
@media (max-width: 768px) {
  input[type="text"],
  input[type="email"],
  input[type="search"],
  input[type="tel"],
  input[type="url"],
  input[type="password"],
  input[type="number"],
  textarea,
  select {
    font-size: max(16px, 1rem);
  }
}


/* ==========================================================================
   SELECTS + DROPDOWNS — native <select> + <option>
   ========================================================================== */

/* --------------------------------------------------------------------------
   S1. Native select with custom chevron.
   Principle: native menus have correct accessibility but ugly default
   chrome. We strip the appearance and inject a brand-orange chevron SVG
   so it reads as "ours" without losing the OS picker.
   -------------------------------------------------------------------------- */
select {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' stroke='%23c9613f' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 12px 8px;
  padding-right: 36px;
  transition:
    border-color 180ms ease-out,
    box-shadow 180ms ease-out;
  cursor: pointer;
}

/* --------------------------------------------------------------------------
   S2. Select focus — same halo as inputs.
   -------------------------------------------------------------------------- */
select:focus {
  border-color: var(--ds-accent, #c9613f);
  box-shadow: 0 0 0 3px rgba(201, 97, 63, 0.15);
}

/* Dark-mode chevron — flip to lighter coral so it stays visible */
:root[data-theme="dark"] select {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' stroke='%23e8856a' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}

/* RTL — chevron on left */
[dir="rtl"] select {
  background-position: left 12px center;
  padding-right: 0;
  padding-left: 36px;
}

/* --------------------------------------------------------------------------
   S3. Optgroup labels — distinct weight, brand color.
   Principle: optgroup labels are the only "header" inside a native menu
   we can style. Make them feel intentional.
   -------------------------------------------------------------------------- */
select optgroup {
  font-weight: 700;
  color: var(--ds-accent-ink, #6e2e18);
  font-style: normal;
}


/* ==========================================================================
   CHECKBOXES + RADIOS — branded, 24px tap target
   ========================================================================== */

/* --------------------------------------------------------------------------
   C1. Custom appearance — square check, round radio, both 18px visual,
   24px tap target via padding box.
   Principle: native browser checkboxes are inconsistent across platforms.
   We replace the visual chrome but keep the native input semantics.
   The tick + dot are pure CSS — no images, no JS.
   -------------------------------------------------------------------------- */
input[type="checkbox"],
input[type="radio"] {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  border: 1.5px solid var(--ds-rule-strong, #cfc6b6);
  background: var(--ds-surface, #ffffff);
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
  transition:
    border-color 150ms ease-out,
    background-color 150ms ease-out,
    box-shadow 150ms ease-out;
  /* 24px tap target via outset padding box */
  margin: 3px;
}

input[type="checkbox"] {
  border-radius: 4px;
}
input[type="radio"] {
  border-radius: 50%;
}

/* Hover — border darkens to brand orange */
input[type="checkbox"]:not(:disabled):hover,
input[type="radio"]:not(:disabled):hover {
  border-color: var(--ds-accent, #c9613f);
}

/* Checked state — fill with brand orange */
input[type="checkbox"]:checked,
input[type="radio"]:checked {
  background: var(--ds-accent, #c9613f);
  border-color: var(--ds-accent, #c9613f);
}

/* Checkbox tick — pure CSS via clip-path */
input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  inset: 0;
  background: #ffffff;
  clip-path: polygon(15% 50%, 38% 73%, 85% 22%, 78% 15%, 38% 58%, 22% 43%);
}

/* Radio dot — pure CSS centered circle */
input[type="radio"]:checked::after {
  content: "";
  position: absolute;
  inset: 4px;
  background: #ffffff;
  border-radius: 50%;
}

/* Indeterminate — bar (for "select all" patterns) */
input[type="checkbox"]:indeterminate {
  background: var(--ds-accent, #c9613f);
  border-color: var(--ds-accent, #c9613f);
}
input[type="checkbox"]:indeterminate::after {
  content: "";
  position: absolute;
  left: 22%;
  right: 22%;
  top: 46%;
  height: 2px;
  background: #ffffff;
  border-radius: 1px;
}

/* Disabled */
input[type="checkbox"]:disabled,
input[type="radio"]:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}


/* ==========================================================================
   SLIDERS — <input type="range">
   ========================================================================== */

/* --------------------------------------------------------------------------
   R1. Slider track — 4px, full-bleed, branded.
   Principle: range inputs are notorious for inconsistent rendering. We
   style WebKit + Firefox tracks identically so the brand is uniform.
   -------------------------------------------------------------------------- */
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  height: 24px; /* tap target */
  cursor: pointer;
}

input[type="range"]::-webkit-slider-runnable-track {
  height: 4px;
  background: var(--ds-rule, #e8e2d7);
  border-radius: 2px;
}
input[type="range"]::-moz-range-track {
  height: 4px;
  background: var(--ds-rule, #e8e2d7);
  border-radius: 2px;
}

/* --------------------------------------------------------------------------
   R2. Slider thumb — 18px, white center, brand-orange border, lifts on hover.
   Principle: the thumb is what the finger grabs. Big enough to grab
   (18px visual, 24px tap), branded enough to feel.
   -------------------------------------------------------------------------- */
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #ffffff;
  border: 2px solid var(--ds-accent, #c9613f);
  margin-top: -7px; /* center on 4px track */
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
  transition: transform 150ms ease-out, box-shadow 150ms ease-out;
}
input[type="range"]::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #ffffff;
  border: 2px solid var(--ds-accent, #c9613f);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
  transition: transform 150ms ease-out, box-shadow 150ms ease-out;
}

input[type="range"]:not(:disabled):hover::-webkit-slider-thumb {
  transform: scale(1.12);
  box-shadow: 0 2px 6px rgba(201, 97, 63, 0.25);
}
input[type="range"]:not(:disabled):hover::-moz-range-thumb {
  transform: scale(1.12);
  box-shadow: 0 2px 6px rgba(201, 97, 63, 0.25);
}


/* ==========================================================================
   LINKS — body links, nav links, external link affordance
   ========================================================================== */

/* --------------------------------------------------------------------------
   L1. Body link transitions — smooth color + underline thickness.
   Principle: hover is a verb. The underline thickening from 1px → 2px is
   a tactile signal: "I'm pointing at this." 150ms is fast enough to feel
   responsive, slow enough to feel intentional.
   -------------------------------------------------------------------------- */
p a,
li a,
.prose a,
article a,
main p a,
main li a {
  transition:
    color 150ms ease-out,
    text-decoration-thickness 150ms ease-out,
    text-underline-offset 150ms ease-out;
}

/* --------------------------------------------------------------------------
   L2. Body link hover — accent color, thicker underline, more offset.
   Principle: scoped to body content (paragraphs, lists, prose) so we
   don't hijack nav/CTA links that have their own visual language.
   -------------------------------------------------------------------------- */
p a:hover,
li a:hover,
.prose a:hover,
article a:hover {
  color: var(--ds-accent, #c9613f);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

/* --------------------------------------------------------------------------
   L3. External link arrow — subtle ↗ glyph after target="_blank" body links.
   Principle: tells the user "this leaves the page" before they click.
   Scoped tightly to body text so navigation/CTAs stay clean.
   -------------------------------------------------------------------------- */
.prose a[target="_blank"]:not(:has(img)):not(.no-arrow)::after,
article p a[target="_blank"]:not(:has(img)):not(.no-arrow)::after,
main p a[target="_blank"]:not(:has(img)):not(.no-arrow)::after {
  content: " \2197"; /* ↗ */
  font-size: 0.85em;
  display: inline-block;
  margin-left: 1px;
  opacity: 0.7;
  transition: transform 150ms ease-out;
}
.prose a[target="_blank"]:not(:has(img)):not(.no-arrow):hover::after,
article p a[target="_blank"]:not(:has(img)):not(.no-arrow):hover::after,
main p a[target="_blank"]:not(:has(img)):not(.no-arrow):hover::after {
  transform: translate(1px, -1px);
  opacity: 1;
}

/* --------------------------------------------------------------------------
   L4. Visited body links — subtle desaturation, ONLY in body content.
   Principle: helps users remember what they've read. Not applied to
   nav, CTAs, or buttons styled as links — those should always look fresh.
   -------------------------------------------------------------------------- */
.prose a:visited,
article p a:visited,
article li a:visited {
  filter: saturate(0.7);
}


/* ==========================================================================
   LABELS + FIELDSETS — small consistency wins
   ========================================================================== */

/* --------------------------------------------------------------------------
   F1. Label + input pairing — clickable label feel.
   Principle: a label connected to an input should feel hot. cursor:pointer
   on labels with a `for` attribute is a subtle but real affordance.
   -------------------------------------------------------------------------- */
label[for] {
  cursor: pointer;
}
label:has(input[type="checkbox"]),
label:has(input[type="radio"]) {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  user-select: none;
}


/* ==========================================================================
   PREFERS-REDUCED-MOTION — kill every animation introduced above
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  button,
  .btn,
  .cta,
  [role="button"],
  input,
  select,
  textarea,
  a,
  input[type="range"]::-webkit-slider-thumb,
  input[type="range"]::-moz-range-thumb,
  input[type="checkbox"],
  input[type="radio"] {
    transition: none !important;
  }
  button:not(:disabled):hover,
  .btn:not(:disabled):hover,
  .cta:not(:disabled):hover,
  [role="button"]:not([aria-disabled="true"]):hover {
    transform: none !important;
    filter: none !important;
  }
  input[type="range"]:not(:disabled):hover::-webkit-slider-thumb,
  input[type="range"]:not(:disabled):hover::-moz-range-thumb {
    transform: none !important;
  }
  .prose a[target="_blank"]:hover::after,
  article p a[target="_blank"]:hover::after {
    transform: none !important;
  }
}

} /* end @layer impeccable */
