/* The `appointments_new_ui` calendar: one column per scheduled physician.
   Deliberately its own file rather than additions to weekly_schedule.css — the two views
   are swapped wholesale by a flag, and keeping their styles apart means removing whichever
   one loses is a deletion rather than an untangling. */

.column-calendar {
  --column-calendar-gutter: 5.5rem;
  /* Below this a column cannot show an avatar and a readable name, so the week scrolls
     sideways rather than squeezing further. */
  --column-calendar-min-column: 6rem;
  --column-calendar-slot-height: 3.25rem;
  --column-calendar-day-head-height: 2.5rem;
  --column-calendar-staff-height: 1.75rem;
  /* Breathing room around an appointment card, applied evenly on all four sides. */
  --column-calendar-card-inset: var(--rem-2);
  /* Declared once and used by both the grid cells and the footer key below, which sits
     inside this element — so the key always shows the fills the grid is actually drawing.
     Tentative is built FROM uncovered rather than alongside it, so the two stay one step
     apart however this is tuned: the stripes are always exactly half the solid fill. */
  --column-calendar-uncovered: var(--surface-tertiary);
  --column-calendar-tentative: repeating-linear-gradient(
    45deg,
    var(--column-calendar-uncovered),
    var(--column-calendar-uncovered) var(--rem-4),
    transparent var(--rem-4),
    transparent var(--rem-8)
  );

  display: flex;
  flex-direction: column;
  height: 100%;
  background: white;
  border-radius: var(--radius-md);
  overflow: hidden;
}

.column-calendar--scroll {
  flex: 1;
  min-height: 0;
  overflow: auto;
}

.column-calendar--grid {
  display: grid;
  min-width: min-content;
}

/* The two header rows and the time gutter stay put while the grid scrolls under them.
   Each needs its own background — a sticky element is transparent by default and the
   cells passing beneath would show through. */
.column-calendar--corner {
  position: sticky;
  top: 0;
  left: 0;
  z-index: 5;
  grid-column: 1;
  grid-row: 1 / span 2;
  background: white;
}

.column-calendar--day-head {
  position: sticky;
  top: 0;
  z-index: 4;
  grid-row: 1;
  background: white;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--rem-8);
  border-left: 1px solid var(--border-secondary);

  &[data-current="true"] {
    background-color: var(--primary-500);

    span {
      color: white;
    }
  }
}

.column-calendar--day-name {
  font-size: var(--rem-12);
  font-weight: var(--text-medium);
  color: var(--text-information);
  text-transform: uppercase;
}

.column-calendar--day-date {
  font-size: var(--rem-18);
  font-weight: var(--text-semibold);
  color: var(--text-heading);
}

/* One per column: who this strip of the day belongs to. The name truncates rather than
   wrapping — at seven days across, a column is narrow and a second line would push the
   grid down. */
.column-calendar--staff {
  position: sticky;
  top: var(--column-calendar-day-head-height);
  z-index: 4;
  grid-row: 2;
  display: flex;
  align-items: center;
  gap: var(--rem-4);
  min-width: 0;
  padding: 0 var(--rem-4);
  border-left: 1px solid var(--border-secondary);
  border-bottom: 1px solid var(--border-secondary);
  background: white;

  /* No avatar to lead the row, so the label centres — matching the day-wide
     "No working staff" placeholder rather than hanging off the left edge. */
  &[data-placeholder="true"] {
    justify-content: center;
  }
}

.column-calendar--staff-name {
  font-size: var(--rem-11);
  font-weight: var(--text-medium);
  color: var(--text-label);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  /* `overflow: hidden` clips to this box, and the default line box is too short for a
     descender — which is why the italic "Unassigned" lost the tail of its g. The trailing
     padding covers the same overhang horizontally. */
  line-height: 1.5;
  padding-right: 1px;

  &[data-unassigned="true"],
  &[data-unbooked="true"] {
    font-style: italic;
    color: var(--text-information);
  }
}

.column-calendar--staff-empty {
  justify-content: center;
  font-size: var(--rem-11);
  font-style: italic;
  color: var(--text-information);
}

.column-calendar--time-cell {
  position: sticky;
  left: 0;
  z-index: 2;
  grid-column: 1;
  background: white;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: var(--rem-12);
  font-size: var(--rem-12);
  color: var(--text-information);
  border-bottom: 1px solid var(--border-subtle);
}

/* White is somebody working, filled is nobody. Unlike the old calendar's overlay this is
   the cell's own background, because here availability is what the column is made of.

   A flat fill rather than a hatch: unworked time then reads as a hole in the sheet rather
   than as content, which is what makes the white columns carry the eye. A step darker than
   the page itself (--surface-tertiary, not --surface-page) so the edge between worked and
   unworked is legible rather than merely present. */
.column-calendar--slot {
  border-left: 1px solid var(--border-secondary);
  border-bottom: 1px solid var(--border-subtle);

  /* A scale of certainty, built from one colour so the three read as steps rather than as
     three unrelated treatments:
       white            somebody is definitely working
       gray on white    pencilled in — literally half the fill, so it sits between
       solid gray       nobody is scheduled
     "unknown" — coverage off, or not back yet — draws plain: asserting an empty schedule
     and then taking it back is worse than saying nothing. */
  &[data-state="uncovered"] {
    background-color: var(--column-calendar-uncovered);
  }

  &[data-state="tentative"] {
    background-image: var(--column-calendar-tentative);
  }
}

/* Footer key. Same fills as the cells, by construction. */
.column-calendar--key-swatch {
  width: var(--rem-20);
  height: var(--rem-12);
  border: 1px solid var(--border-secondary);
  border-radius: var(--radius-xs);
  background-color: white;

  &[data-state="tentative"] {
    background-image: var(--column-calendar-tentative);
  }
}

/* Cards sit above the slots. Lanes only ever come into play when one physician has two
   overlapping appointments, which the column shape makes rare rather than routine. */
.column-calendar--appointment {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--rem-2);
  justify-self: start;
  /* The inset is taken off both sides and added back to the offset, so the card sits
     centred in its lane. Subtracting it from the width alone — which is what this did —
     puts the whole gap on the right and leaves the card flush against the left edge. */
  width: calc((100% / var(--lanes)) - (var(--column-calendar-card-inset) * 2));
  margin-left: calc((100% / var(--lanes)) * var(--lane) + var(--column-calendar-card-inset));
  /* The grid rows are whole slots; the card is drawn to the minute inside them. --offset
     and --span are in slots, set per card by the component, so a 25-minute visit is
     shorter than a 40-minute one and two back-to-back visits never cover each other. */
  align-self: start;
  margin-top: calc(var(--offset, 0) * var(--column-calendar-slot-height) + var(--column-calendar-card-inset));
  height: calc(var(--span, 1) * var(--column-calendar-slot-height) - (var(--column-calendar-card-inset) * 2));
  padding: var(--rem-4);
  overflow: hidden;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-secondary);
  border-left: 3px solid var(--border-primary);
  background: white;
  text-decoration: none;

  &[data-appointment-type="new_patient"] {
    border-left-color: #EEB479;
    background: #FDF6EE;
  }

  &[data-appointment-type="follow_up"] {
    border-left-color: #62B6CB;
    background: #EFF7F9;
  }

  &[data-appointment-type="procedure"] {
    border-left-color: #BB62D3;
    background: #F6EEF9;
  }

  &:hover {
    box-shadow: var(--shadow-neutral-sm);
  }

  /* Each card is its own stacking context, so an open menu would otherwise paint under the
     cards after this one, the now line and the sticky rows. Lifted only while it is open. */
  &:has(.dropdowns--menu:not([hidden])) {
    z-index: 9999;
  }
}

/* A visit with a note staff must act on (a patient who needs a driver). The ring sits
   apart from the card, with a gap, so it does not read as the live-recording ring, which
   hugs it. The note itself is in the tooltip. */
.column-calendar--appointment[data-needs-attention="true"] {
  outline: 2px solid var(--warning-500);
  outline-offset: 1px;
}

/* Inside the card, which clips anything past its edge, at the end of the name row. */
.column-calendar--appointment-attention {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  margin-left: auto;
  border-radius: 50%;
  background-color: var(--warning-500);
}

.column-calendar--appointment-head {
  display: flex;
  align-items: center;
  gap: var(--rem-4);
  min-width: 0;
}

/* The card's click target, stretched over the whole card. Only the patient's name sits
   above it. */
.column-calendar--appointment-open {
  position: absolute;
  inset: 0;
}

.column-calendar--appointment-patient {
  position: relative;
  z-index: 1;
  min-width: 0;
  font-size: var(--rem-11);
  font-weight: var(--text-semibold);
  color: var(--text-heading);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The actions menu, shown on hover as it was on the old calendar. Above the stretched link,
   or its click would open the appointment. It takes the card's own fill so it covers the
   end of the patient's name rather than sitting across it.

   Hidden by opacity rather than `display`, so the trigger can still take keyboard focus,
   and held visible while the menu is open: the menu is fixed-position, and the pointer
   crosses a gap outside the card to reach it. */
.column-calendar--appointment-menu {
  position: absolute;
  top: var(--rem-2);
  right: var(--rem-2);
  z-index: 1;
  border-radius: var(--radius-xs);
  background: inherit;
  opacity: 0;

  /* The shared trigger is a 2rem button, which would cover most of a half-hour card.
     `!important` because buttons.css sizes an icon-only button from inside a nested
     selector list, which weighs as much as its heaviest member plus four attributes —
     more than any selector worth writing here. */
  .buttons--button {
    width: var(--rem-20) !important;
    height: var(--rem-20) !important;
    padding: 0 !important;
  }
}

.column-calendar--appointment:hover > .column-calendar--appointment-menu,
.column-calendar--appointment-menu:focus-within,
.column-calendar--appointment-menu:has(.dropdowns--menu:not([hidden])) {
  opacity: 1;
}

.column-calendar--appointment-time,
.column-calendar--appointment-status {
  font-size: var(--rem-10);
  color: var(--text-information);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* "Add an appointment here", matching the old calendar's empty-slot affordance. Only
   rendered on slots this column has nothing booked in, so it can never invite a double
   booking — including over an appointment the Hide filter is currently not drawing. */
.column-calendar--add {
  display: block;
  width: 100%;
  height: 100%;
  text-decoration: none;
}

.column-calendar--add-affordance {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  border: dashed 2px var(--primary-500);
  border-radius: var(--radius-md);
  background-color: var(--primary-50);
  opacity: 0;
}

.column-calendar--add:hover .column-calendar--add-affordance {
  opacity: 1;
}

/* The current-time line, on the week that contains today. The wrapper covers the slot rows
   so the line can be placed in slot units; clicks pass through to the slots and cards
   beneath. It shares the cards' z-index and comes after them, so it draws over them but
   under the sticky gutter and header rows. */
.column-calendar--now {
  position: relative;
  z-index: 1;
  grid-column: 2 / -1;
  pointer-events: none;
}

.column-calendar--now-line {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--column-calendar-slot-height) * var(--now-slots, 0));
  height: 2px;
  margin-top: -1px;
  background: black;
}

/* The time rides in the gutter, over the time labels, and scrolls sideways with it — the
   gutter's own stickiness, a step above the time cells and a step below the header rows.
   Flush with the gutter's edge so it reads as the head of the line. */
.column-calendar--now-gutter {
  position: sticky;
  left: 0;
  z-index: 3;
  grid-column: 1;
  pointer-events: none;
}

/* A white band across the gutter, centred on the line, so a time label the pill would half
   cover is hidden rather than peeking out above and below it. */
.column-calendar--now-band {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--column-calendar-slot-height) * var(--now-slots, 0));
  translate: 0 -50%;
  display: flex;
  justify-content: flex-end;
  padding: var(--rem-6) 0;
  background: white;

  &[hidden] {
    display: none;
  }
}

.column-calendar--now-time {
  padding: 2px 6px;
  border-radius: var(--radius-xs);
  background: black;
  color: white;
  font-size: var(--rem-11);
  font-weight: var(--text-semibold);
  white-space: nowrap;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

/* The day view: the same grid with one day in it. Everything that draws availability and
   the cards' colours is shared with the week; only what a wide column has room for
   changes. */
.column-calendar[data-view="day"] {
  .column-calendar--day-name {
    font-size: var(--rem-13);
    font-weight: var(--text-regular);
    text-transform: none;
  }

  .column-calendar--day-date {
    font-size: var(--rem-16);
  }

  /* A wide card puts the status at the end of the name row, as the design does, instead
     of stacking it under the time. */
  .column-calendar--appointment {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-content: start;
    column-gap: var(--rem-8);
    row-gap: var(--rem-4);
    padding: var(--rem-6) var(--rem-12);
  }

  .column-calendar--appointment-head {
    grid-column: 1;
    grid-row: 1;
  }

  .column-calendar--appointment-status {
    grid-column: 2;
    grid-row: 1;
    align-self: center;
    font-size: var(--rem-11);
  }

  .column-calendar--appointment-time {
    grid-column: 1 / -1;
    grid-row: 2;
    font-size: var(--rem-11);
  }

  .column-calendar--appointment-patient {
    font-size: var(--rem-13);
    font-weight: var(--text-medium);
  }
}
