/* One focus indicator for every interactive element. Zero-specificity :where()
   so any component can still override placement without fighting this rule. The
   ring is the one deliberate spend of green on chrome (see --focus-ring). */
:where(a, button, summary, input, select, textarea, [tabindex]):focus-visible {
  outline: var(--border-width) solid var(--focus-ring);
  outline-offset: 2px;
}

/* SECONDARY is the default for any button: hollow accent (outlined green). Every
   action that isn't the page's one primary commit or a destructive action looks
   like this — one secondary treatment, no separate "neutral box" vs "ghost". */
button, a.button {
  text-align: center;
  align-content: center;
  cursor: pointer;
  text-decoration: none;
  padding: 5px;
  border: var(--border-width) solid var(--theme-accent-color);
  border-radius: var(--border-radius);
  background-color: transparent;
  color: var(--theme-accent-color);

  /* PRIMARY: the single main commit of a page (opt-in; input[type=submit] is
     primary automatically). Filled accent so it's the one thing that stands out. */
  &.primary {
    background-color: var(--theme-accent-color);
    border-color: var(--theme-accent-color);
    color: var(--theme-on-accent);
  }

  /* Destructive: hollow warn at rest, fills warn on commit (hover/focus) — the
     single danger language, shared with .button-small.danger (scales by size,
     not by a different look). */
  &.delete {
    border-color: var(--theme-warn-color);
    background-color: transparent;
    color: var(--theme-warn-color);
  }

  &.delete:hover,
  &.delete:focus-visible {
    background-color: var(--theme-warn-color);
    color: var(--theme-bg-color);
  }

  &[disabled] {
    cursor: not-allowed;
    opacity: 0.5;
    background-color: var(--theme-bg-color);
  }
}

/* Icon buttons: a flat, boxless, muted clickable icon — the single shared role
   for every inline icon action (the admin event edit/delete on a row, the genre
   tag edit gears, …), on either an <a> or a <button>. This is the chrome reset
   only: no box, no link underline, muted with a hover lift. Layout — sizing,
   padding, margins, glyph centring — belongs to the context that places them.
   The `a.`/`button.` qualifiers out-specify the boxed button base above without
   depending on stylesheet order. Add `danger` for a destructive (delete) tone. */
a.icon-button,
button.icon-button {
  cursor: pointer;
  text-decoration: none;
  border: 0;
  background: none;
  color: var(--theme-fg-muted);
}

a.icon-button:hover,
button.icon-button:hover {
  color: var(--theme-fg-color);
}

.icon-button.danger:hover {
  color: var(--theme-warn-color);
}

/* Display-only icon: a non-interactive glyph (a field's leading handle, a search
   affordance, a metadata marker) — the counterpart to the clickable .icon-button.
   Muted, no hover lift, no cursor change. Centralises what was ad-hoc per context
   (.filter-icon, .sheet__search-icon, …). */
.icon {
  color: var(--theme-fg-muted);
  line-height: 1;
}

input[type=submit] {
  cursor: pointer;
  text-decoration: none;
  padding: 5px;
  border: var(--border-width) solid var(--theme-accent-color);
  border-radius: var(--border-radius);
  background-color: var(--theme-accent-color);
  color: var(--theme-on-accent);

  &[disabled] {
    color: var(--theme-fg-color);
    cursor: not-allowed;
    background-color: var(--theme-bg-color);
  }
}

/* ── The button ladder ───────────────────────────────────────────────────────
   Three weights, app-wide. "A box reads as clickable", so every one is a box
   (except .text-link, a navigation link). Weight is the role; size is just
   context (full-width vs small pill), NOT a separate tier:

     PRIMARY    input[type=submit], .primary    filled accent — the ONE main
                                                 commit of a page (Save, Log in,
                                                 the rule editor's done link)
     SECONDARY  <button> / .button / .button-small (default)
                                                 hollow accent — every other
                                                 action (Sign out, Enable, Test
                                                 now, Pause, Create link, …)
     DANGER     .delete / .danger               hollow warn → fills on commit
     ICON       .icon-button (+ .danger)        flat boxless inline icon action
     LINK       .text-link                      underlined accent navigation

   Per-page primary: at most one filled button per page; everything else is
   secondary (hollow) or danger, so the primary is the thing that stands out.
   (.button-ghost is kept as a no-op alias — secondary is already hollow — so
   existing markup needn't be swept.) Flat-text controls that aren't buttons
   (view switcher, favorites/notify shortcuts) keep their own domain classes. */
.button-small {
  /* inline-flex + a fixed line-height makes every pill the same height whether
     it's an <a>, a <button> (via button_to), or an <input> — otherwise the <a>
     inherits the body's 1.5 line-height and renders taller than the buttons'. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--font-size-small);
  line-height: 1.2;
  padding: var(--gap-small) var(--gap-medium);
  border: var(--border-width) solid var(--theme-accent-color);
  background: transparent;
  color: var(--theme-accent-color);
  border-radius: var(--border-radius);
  cursor: pointer;
  text-decoration: none;
}

/* Filled primary, small-pill size (the rule editor's done link, the cookie CTA). */
.button-small.primary {
  background: var(--theme-accent-color);
  color: var(--theme-on-accent);
}

.button-small[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

/* No-op alias: secondary is already hollow accent. Kept so existing markup that
   says .button-ghost still reads as secondary without a sweep. */
.button-small.button-ghost {
  background: transparent;
  color: var(--theme-accent-color);
}

/* Destructive pill: hollow warn at rest, fills warn on commit — the same danger
   language as .button.delete, just the small/pill size. */
.button-small.danger {
  background: none;
  border-color: var(--theme-warn-color);
  color: var(--theme-warn-color);
}

.button-small.danger:hover,
.button-small.danger:focus-visible {
  background: var(--theme-warn-color);
  color: var(--theme-bg-color);
}

/* A text navigation link (underlined accent), NOT a button — for "go somewhere
   else" sitting among in-place action buttons. Borderless: a link, not a box. */
.text-link {
  color: var(--theme-accent-color);
  text-decoration: underline;
  font-size: var(--font-size-small);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

/* ── Checkbox ─────────────────────────────────────────────────────────────────
   One custom box everywhere (forms, the favorites picker, …) so a native browser
   checkbox never sneaks in beside it. appearance:none lets us draw the box on the
   input itself — no sibling element, so no markup changes — matching the
   filter-sheet .opt__box exactly. The full-row sheet option (.opt) and the
   selectable .tag chip hide this input and draw their own affordance, but share
   this visual language. */
input[type=checkbox] {
  appearance: none;
  -webkit-appearance: none;
  flex-shrink: 0;
  width: 1.25rem;
  height: 1.25rem;
  display: inline-grid;
  place-content: center;
  border: var(--border-width) solid var(--border-color);
  background: var(--theme-bg-color);
  cursor: pointer;
  vertical-align: -0.2em;
}

/* The tick: a masked Phosphor check, hidden (scaled to 0) until checked. */
input[type=checkbox]::before {
  content: "";
  width: 0.8rem;
  height: 0.8rem;
  background-color: var(--theme-on-accent);
  -webkit-mask: var(--check-mask) center / contain no-repeat;
  mask: var(--check-mask) center / contain no-repeat;
  transform: scale(0);
}

input[type=checkbox]:checked {
  background: var(--theme-accent-color);
  border-color: var(--theme-accent-color);
}

input[type=checkbox]:checked::before {
  transform: scale(1);
}

input[type=radio] {
  accent-color: var(--theme-accent-color);
}

/* Placeholder text. The UA default is a low-opacity tint of the text colour,
   which washes out to poor contrast against our backgrounds; pin it to the muted
   foreground token at full opacity so it stays clearly legible in both themes. */
::placeholder {
  color: var(--theme-fg-muted);
  opacity: 1;
}

input[type=text] {
  background-color: inherit;
  color: inherit;
  border: none;
  font-size: inherit;
  /* The field now sits alone on its row (chips moved to their own row below), so
     it no longer needs to reserve half the combobox width against inline chips.
     min-width: 0 lets it shrink within flex instead of forcing horizontal
     overflow on narrow (mobile) viewports. */
  min-width: 0;
  padding: 0;
  text-overflow: ellipsis;
  max-width: 100%;
  flex-grow: 1;
  line-height: var(--filter-input-line-height);

  &:focus,
  &:focus-visible,
  &:focus-within {
    box-shadow: none;
    outline: none;
  }
}
