/* Rulesets on events */
/* ------------------ */
/*
  The ruleset an event follows (a Gear::Rule in code, its rules being slots): the event
  dialog's rules section (gear/calendar/_rule_allocation), the marker on an event with
  required rules still unfilled (_ruleset_warning) and the bar of missing chips on an
  expanded card and the dialog's reading face (_ruleset_legend).

  The marker and the bar are the legacy rulesets' own, brought back for the new rulesets
  with the same look - red, since gear that falls short of the event's ruleset is a
  problem rather than work not yet begun.
*/


/* The rules section */
/* ----------------- */

.calendar-rules {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;

  &:empty {
    display: none;
  }
}

.calendar-rules__notice {
  margin: 0;

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

  font-size: 0.8125rem;

  &:empty {
    display: none;
  }
}

.calendar-rules__group {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
}

.calendar-rules__group-title {
  margin: 0.25rem 0 0;

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

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

/* One rule: a disclosure drawn as an Extras category (.calendar-gear-group, see
   calendar-form.css) - its name and range beside its status in the summary row, then its
   items as tiles once opened */
.calendar-rule__summary {
  align-items: center;

  /* A required rule still short: the bar takes the danger-subtle ground, as the
     missing-rules legend does. Keyed off the status mark, so it follows it as tiles are
     pressed; only the bar, so an opened rule's tiles keep the plain ground. */
  &:has(.calendar-rule__status--needed) {
    background-color: var(--bs-danger-bg-subtle);
  }
}

.calendar-rule__title {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 0.5rem;

  min-width: 0;
  margin-right: auto;
}

.calendar-rule__name {
  font-weight: 700;
}

.calendar-rule__range {
  color: var(--bs-secondary-color);

  font-size: 0.75rem;
  font-weight: 400;
}

/* A rule's status at the end of its summary row, at the size the editor's items-available
   line draws its marks (.rule-availability, rules.css). A required rule: the editor's
   green tick once it's filled, its red warning while it's short. An optional rule: the
   same tick in grey once it has something, an empty dashed circle until then. Not colour
   alone - the shapes differ, and each status's word is still there for a screen reader. */
.calendar-rule__status {
  flex: none;
  display: inline-flex;

  font-size: 0.875rem;
}

.calendar-rule__status--filled .bi { color: var(--bs-success); }
.calendar-rule__status--needed .bi { color: var(--bs-danger); }
.calendar-rule__status--optional_filled .bi { color: var(--bs-tertiary-color); }

/* The size of the tick's circle, so the two line up down the column. Dashed by hand
   rather than with border-style, which gives a circle this small only four dashes:
   twelve segments of a conic gradient, masked to a 1.5px ring. */
.calendar-rule__empty {
  display: block;
  width: 1em;
  height: 1em;

  border-radius: 50%;
  background: repeating-conic-gradient(var(--bs-tertiary-color) 0 15deg, transparent 15deg 30deg);
  mask: radial-gradient(farthest-side, transparent calc(100% - 1.5px), #000 calc(100% - 1.5px));
}

.calendar-rule__body {
  padding: 0.5rem;

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

.calendar-rule__tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(4.25rem, 1fr));
  gap: 0.5rem;
}

/* An item as a toggle: the Extras picker's tile (calendar-form.css), as a button. Chosen
   is drawn the same way - the accent ring and the corner tick - keyed off aria-pressed
   rather than a checkbox, which also says it to a screen reader. */
.calendar-rule__tile {
  padding: 0;

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

  font: inherit;
  text-align: center;

  &[aria-pressed="true"] .calendar-gear-tile__frame {
    border-color: var(--pg-accent);
  }

  &[aria-pressed="true"] .calendar-gear-tile__tick {
    display: flex;
  }

  &[aria-pressed="true"] .calendar-gear-tile__name {
    color: var(--bs-emphasis-color);
  }

  &:focus-visible {
    outline: none;
  }

  &:focus-visible .calendar-gear-tile__frame {
    border-color: var(--bs-primary);
    box-shadow: 0 0 0 2px rgba(var(--bs-primary-rgb), 0.35);
  }

  /* Another rule has this item: faded like an Extras tile in a rule, but still
     pressable, to move it here */
  &:has(.calendar-rule__elsewhere:not([hidden])) .calendar-gear-tile__frame {
    opacity: 0.55;
  }

  /* Hidden by the tag filter, like the picker's tiles */
  &.tag-filter-hidden {
    display: none;
  }
}

.calendar-rule__none {
  margin: 0;

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

  font-size: 0.8125rem;
}

/* Extras: the gear picker below the rules, under a heading of its own once there are rules
   above it */
.calendar-rules__extras-title {
  margin: 0.75rem 0 0;
}

.calendar-rules__extras-hint {
  margin: 0 0 0.25rem;

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

  font-size: 0.8125rem;
}

/* An Extras tile for an item one of the rules already has: switched off, and saying so */
.calendar-gear-tile:has(.calendar-gear-tile__check:disabled) {
  cursor: default;
  opacity: 0.55;
}

/* ...and the note on either tile saying which rule has the item */
.calendar-gear-tile__in-rule,
.calendar-rule__elsewhere {
  display: block;

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

  font-size: 0.6875rem;
  font-weight: 600;
}

/* The Ruleset field and Gear share one controller (rule_allocation_controller.js) without
   the wrapper that gives them one taking part in the form's own layout */
.calendar-form__contents {
  display: contents;
}


/* Markers on the calendar */
/* ----------------------- */

/* The ruleset's own marker, beside the no-items one: red, since packed gear that falls
   short of the rules the event was given is a problem rather than work not yet begun.
   No ring of its own - the amber one already means "look here", and a second colour
   round the same card would read as neither. */
.calendar-event__ruleset-warning {
  flex: 0 0 auto;

  color: var(--bs-danger);

  font-size: 0.875rem;
  line-height: 1;

  @media (width >=768px) {
    font-size: 0.9375rem;
  }
}

/* The month view's marker, on the same dark halo as the no-items one beside it for the
   same reason - a red event colour would swallow a flat red glyph. A lighter red than
   --bs-danger, which sinks into the halo at this size. */
.calendar-month__pill-ruleset-warning,
.calendar-month__band-ruleset-warning {
  flex: 0 0 auto;

  color: #ff6b6b;

  font-size: 0.6875rem;
  line-height: 1;
  text-shadow: 0 0 2px rgba(0, 0, 0, 0.75);
}


/* Missing-rules legend */
/* -------------------- */
/*
  The bar of missing chips on an expanded card and the dialog's reading face - see
  gear/calendar/_ruleset_legend, built on the shared .event-legend/.event-legend__row box
  and .event-badge chip (gear/calendar/_missing_chip). ruleset-legend__title names the
  ruleset the row is checking against, wearing .calendar-form__label so it reads as the
  same kind of label as the "Notes"/"Items" headings around it.

  Below 768px the title wraps onto its own line above the chips rather than sitting inline
  before them - a full ruleset name on a narrow card would otherwise eat the width the
  chips need. Pinned to the start on every width (.event-legend centres its row on a
  phone), so the title and the chips it labels share a left edge. Qualified as
  .event-legend.ruleset-legend so this beats calendar-legend.css's own mobile rule on
  specificity rather than on which file is linked second.

  The danger-subtle fill is the cue the missing chips already carry: the row itself should
  read as "something's missing" at a glance. Padded to match .calendar-view__notes, since
  the two boxes sit stacked on the same expanded card.
*/
.event-legend.ruleset-legend,
.calendar-event__expanded .event-legend.ruleset-legend {
  flex-wrap: wrap;
  justify-content: start;
  row-gap: 0.375rem;

  padding: 0.4375rem 0.625rem;

  background-color: var(--bs-danger-bg-subtle);
}

/* Above 768px the card is wide enough for the title and chips to share a line, so the
   title sits inline before them; centred against the taller chips, with a little extra
   room after it so it doesn't read as the first chip. */
.ruleset-legend__title {
  flex: 1 0 100%;

  @media (width >768px) {
    flex: 0 0 auto;
    align-self: center;
    margin-right: 0.25rem;
  }
}

/* The missing-rules marker before the ruleset's name, in the marker's own red */
.ruleset-legend__icon {
  margin-right: 0.25em;

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

/* ...and on the green bar, the green tick the dialog's filled rules carry */
.ruleset-legend__icon--complete {
  color: var(--bs-success);
}

/* The reading face's bar once every required rule is filled (counted: true): the same
   row, green, with nothing missing to list */
.event-legend.ruleset-legend--complete {
  background-color: var(--bs-success-bg-subtle);
}

/* On the reading face the bar stands in for the Ruleset field's answer box, so it takes
   that box's corners (.calendar-view__value) rather than the subcard's rounder ones */
.calendar-view .event-legend.ruleset-legend {
  border-radius: var(--pg-form-radius);
}
