/* Rules */
/* ===== */
/*
  The Rulesets dialog's list (gear/rules/index), and its rule editor (gear/rules/edit):
  sections for the rule's header form and the table of its slots
  and includes with the buttons that add to it; and the add and edit screens' forms.

  Status is never colour alone: every status chip carries an icon and its word, and the
  event tag chip is dashed and says "event tag:" before the tag it stands for.
*/

/* The editor's sections, one under another with a hairline between each */
.rule-editor {
  display: flex;
  flex-direction: column;
}

.rule-editor > * + * {
  margin-top: 1.25rem;
  padding-top: 1.25rem;

  border-top: var(--bs-border-width) solid var(--bs-border-color);
}

/* The event dialog's field labels (.calendar-form__label), as headings here */
.rule-section__heading {
  display: flex;
  align-items: center;
  gap: 0.375rem;

  margin: 0 0 0.625rem;

  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;

  color: var(--bs-secondary-color);
}

/* A section's hint sits close under its heading, and a little apart from what it explains */
.rule-section__heading + .rule-editor__hint {
  margin: -0.25rem 0 0.75rem;
}

.rule-editor__header-form {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
}

.rule-editor__note,
.rule-editor__hint {
  color: var(--bs-secondary-color);

  font-size: 0.8125rem;
}

.rule-header-fields {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  width: 100%;

  /* The section's hairline, or the new form's hint, follows - not another field */
  > .form-field:last-child {
    margin-bottom: 0;
  }
}


/* Status chips: Ready, Missing, None yet */
.rule-status {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;

  padding: 0.2em 0.6em;

  border: 1px solid;
  border-radius: 999px;

  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
}

.rule-status--ready {
  border-color: var(--bs-success-border-subtle);
  background-color: var(--bs-success-bg-subtle);
  color: var(--bs-success-text-emphasis);
}

.rule-status--missing {
  border-color: var(--bs-danger-border-subtle);
  background-color: var(--bs-danger-bg-subtle);
  color: var(--bs-danger-text-emphasis);
}

.rule-status--none_yet {
  border-color: var(--bs-border-color);
  background-color: var(--bs-secondary-bg);
  color: var(--bs-body-color);
}


/* Chips in the slot table */
.rule-category-chip {
  display: inline-block;

  padding: 0.2em 0.5em;

  border: 1px solid var(--bs-border-color);
  border-radius: 0.25rem;
  background-color: var(--bs-body-bg);

  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}

/* A slot's Conditions cell: its item, or its categories with its tag filters beneath */
.rule-conditions {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.25rem;
}

/* Every rule row is as tall as two lines of chips (categories, then tag filters), so rows
   with one line of conditions line up with those that have two. A chip is 0.75rem text at
   line-height 1.2, 0.2em padding top and bottom, and a 1px border. */
.rule-slot-row .rule-conditions {
  min-height: calc(2 * (0.75rem * 1.6 + 2px) + 0.25rem);
}

/* "the event tag" - dashed, so it reads as standing in for a tag rather than being one */
.rule-event-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25em;

  padding: 0.2em 0.6em;

  border: 1px dashed var(--bs-body-color);
  border-radius: 999px;
  background-color: var(--bs-body-bg);
  color: var(--bs-body-color);

  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}

/* How many items a rule takes (rule_count): plain text at its surroundings' size, its
   digits tabular so counts line up down the editor's column, muted when optional - not a
   hard requirement. Shared with the event dialog's rule summaries. */
.rule-count {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.rule-count--optional {
  color: var(--bs-secondary-color);
}

.rule-event-chip--unset {
  border-color: var(--bs-danger-text-emphasis);
  color: var(--bs-danger-text-emphasis);
  font-style: italic;
}

/* The slot form's event tag chip is a toggle like the tag chips beside it */
.rule-event-chip--toggle {
  --pg-tag-fg: var(--bs-body-color);
  --pg-tag-bg: var(--bs-body-bg);
  --pg-tag-border: var(--bs-body-color);

  border-style: dashed;

  /* Off, the shared toggle style fades the border almost to the page; keep the dash
     visible, since it's what marks this chip as standing in for a tag */
  &[aria-pressed="false"] {
    border-color: var(--bs-secondary-color);
  }
}


/* The table of slots and includes. It (or its empty state) ends the body, so it keeps
   some air above the footer's hairline rather than sitting on it. */
.rule-entries-wrapper {
  margin-bottom: 1rem;

  border: var(--bs-border-width) solid var(--bs-border-color);
  border-radius: 0.5rem;
}

.rule-entries {
  min-width: 860px;
  margin: 0;

  th,
  td {
    vertical-align: middle;
  }

  thead th {
    color: var(--bs-secondary-color);

    font-size: 0.75rem;
    white-space: nowrap;
  }
}

.rule-entries-empty {
  margin-bottom: 1rem;
  padding: 1rem;

  border: 1px dashed var(--bs-border-color);
  border-radius: 0.5rem;

  color: var(--bs-secondary-color);
}

.rule-slot-row__name {
  font-weight: 400;
}

.rule-slot-row__title {
  font-weight: 700;
}

/* Included slots are read-only: indented and on a tinted ground under their include, hung
   off a tree. One vertical line starts at the include header's bottom edge, under its
   chevron, and drops through each of its rows (across the borders between them),
   stopping at the last row's middle; each slot branches off it with a thinner arrow to
   its name. */
.rule-entries {
  /* between the muted text grey and the include header's pale grey, nearer the text */
  --rule-tree-colour: color-mix(in srgb, var(--bs-secondary-color) 60%, var(--bs-secondary-bg));
  --rule-tree-x: 1.25rem; /* the chevron's centre: cell padding, toggle padding, half the icon */
  --rule-tree-width: 1.5px;
  --rule-branch-width: 1.5px;
}

.rule-slot-row--included > * {
  background-color: var(--bs-tertiary-bg);
}

.rule-slot-row--included > :first-child {
  position: relative;

  padding-left: 2.5rem;
}

.rule-slot-row--included > :first-child::before {
  position: absolute;
  top: calc(-1 * var(--bs-border-width));
  bottom: calc(-1 * var(--bs-border-width));
  left: calc(var(--rule-tree-x) - var(--rule-tree-width) / 2);

  width: var(--rule-tree-width);

  background-color: var(--rule-tree-colour);

  content: "";
}

.rule-slot-row--included:last-child > :first-child::before {
  bottom: 50%;
}

/* The branch: a short line from the tree's edge to the slot's name, ending in an arrowhead */
.rule-slot-row__branch {
  position: absolute;
  top: 50%;
  left: calc(var(--rule-tree-x) + var(--rule-tree-width) / 2);

  width: calc(0.9rem - var(--rule-tree-width) / 2);
  height: var(--rule-branch-width);
  margin-top: calc(var(--rule-branch-width) / -2);

  background-color: var(--rule-tree-colour);

  &::after {
    position: absolute;
    top: 50%;
    right: 0;

    width: 0.4rem;
    height: 0.4rem;

    border-top: var(--rule-branch-width) solid var(--rule-tree-colour);
    border-right: var(--rule-branch-width) solid var(--rule-tree-colour);

    content: "";
    transform: translateY(-50%) rotate(45deg);
    transform-origin: center;
  }
}

/* The items meeting the conditions, under the chips with a gap so they read as a separate
   (but related) line rather than one more condition */
.rule-slot-row__availability {
  margin-top: 0.625rem;

  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.5rem;
}

/* Items available: a status icon, then the items, or why there are none. The icons
   differ in shape (tick, warning triangle, dash) as well as colour. */
.rule-availability {
  display: inline-flex;
  align-items: baseline;
  gap: 0.375rem;

  font-size: 0.875rem;
}

.rule-availability__icon {
  flex: none;
}

.rule-availability__icon--ready { color: var(--bs-success); }
.rule-availability__icon--missing { color: var(--bs-danger); }
.rule-availability__icon--optional { color: var(--bs-secondary-color); }

/* The items list is detail; a gap's reason is the point of the row, so it keeps the
   body colour. Optional rules are always muted, items or not. */
.rule-availability--ready .rule-availability__text,
.rule-availability--optional .rule-availability__text {
  color: var(--bs-secondary-color);
}

/* Move, edit and remove: one row of matching icon buttons */
.rule-row-actions {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.375rem;

  form {
    margin: 0;
  }
}

/* Plain like its neighbours until hovered, then red as the other dialogs' delete tools
   turn (.calendar-form__tool--danger) */
.rule-row-actions__remove:not(:disabled):hover {
  border-color: var(--bs-danger);

  color: var(--bs-danger);
}

.rule-move-buttons {
  display: inline-flex;
  gap: 0.25rem;

  form {
    display: inline;
  }
}

.rule-include-group__header > td {
  background-color: var(--bs-secondary-bg);
}

.rule-include-group__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
}

.rule-include-group__toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;

  padding: 0.25rem 0.25rem;

  border: 0;
  background: none;
  color: inherit;

  font: inherit;

  .bi {
    transition: transform 0.15s;
  }

  &[aria-expanded="false"] .bi {
    transform: rotate(-90deg);
  }

  &:focus-visible {
    outline: 2px solid var(--bs-focus-ring-color, var(--bs-primary));
    outline-offset: 2px;
  }
}

.rule-include-group__resolved {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;

  font-size: 0.8125rem;
}

/* On its own line under the include's title, lined up with the title's text rather
   than the chevron before it */
.rule-include-group__setting {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem;
  margin: 0.375rem 0 0;
  padding-left: 1.65rem;

  .form-select {
    width: auto;
  }
}

.rule-include-group__bar > .rule-row-actions {
  margin-left: auto;
}

.rule-include-group__error {
  margin: 0.5rem 0 0;

  color: var(--bs-danger-text-emphasis);

  font-size: 0.8125rem;
}


/* Above the table, under the section's hint, the buttons that open the add screens */
.rule-editor__add-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;

  margin-bottom: 0.75rem;
}

.rule-category-options {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
  gap: 0.125rem 1rem;
  max-height: 14rem;
  overflow-y: auto;

  padding: 0.5rem 0.75rem;

  border: var(--bs-border-width) solid var(--bs-border-color);
  border-radius: 0.375rem;

  &.is-invalid {
    border-color: var(--bs-form-invalid-border-color);
  }
}

.rule-slot-form__filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
}

.rule-slot-form__counts {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0 1rem;

  .form-field {
    width: 8rem;
  }

  .form-text {
    flex-basis: 100%;
    margin-top: 0;
  }
}

.rule-slot-form__preview {
  margin: 0.75rem 0;
  padding: 0.5rem 0.75rem;

  border-radius: 0.375rem;
  background-color: var(--bs-tertiary-bg);

  font-size: 0.875rem;

  strong {
    margin-right: 0.5rem;
  }
}


/* The specific item form's picker (gear/rule_slots/_item_form): the event dialog's
   Extras tiles, one ticked at a time. The category holding the chosen item is marked as a
   chosen Extras category is, here without a controller's help. */
.rule-item-picker {
  .calendar-gear-group:has(.calendar-gear-tile__check:checked) {
    border-color: var(--pg-accent);

    .calendar-gear-group__count {
      color: var(--pg-accent);
    }
  }

  &.is-invalid .calendar-gear-group {
    border-color: var(--bs-form-invalid-border-color);
  }
}

/* Opens the picture in the lightbox; a link, so clicking it doesn't pick the tile */
.rule-item-picker__zoom {
  position: absolute;
  right: 0.1875rem;
  bottom: 0.1875rem;

  display: flex;
  align-items: center;
  justify-content: center;

  width: 1.375rem;
  height: 1.375rem;

  background-color: rgba(var(--bs-body-bg-rgb), 0.85);
  border-radius: 50%;
  color: var(--bs-emphasis-color);

  font-size: 0.75rem;
  line-height: 1;
  text-decoration: none;

  &:hover,
  &:focus-visible {
    background-color: var(--bs-body-bg);
    color: var(--pg-accent);
  }
}
