@propriety/court-calendar 1.0.166 → 1.0.168

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/.claude/settings.json +7 -0
  2. package/dist/__tests__/fixtures.d.ts +12 -0
  3. package/dist/_components/DayTypeChips.d.ts +0 -12
  4. package/dist/_components/Modal/DateDetails/DateDetails.d.ts +3 -1
  5. package/dist/_components/Toolbar/DateTypeFilter.d.ts +3 -2
  6. package/dist/court-calendar.css +1 -1
  7. package/dist/helpers/api/courtDates.d.ts +15 -1
  8. package/dist/helpers/cases.d.ts +12 -0
  9. package/dist/helpers/courtDates.d.ts +30 -1
  10. package/dist/helpers/dayTypeCounts.d.ts +66 -9
  11. package/dist/helpers/eventLabel.d.ts +0 -2
  12. package/dist/helpers/filtering.d.ts +4 -2
  13. package/dist/helpers/motionWindow.d.ts +9 -0
  14. package/dist/helpers/routing.d.ts +1 -1
  15. package/dist/hooks/UseCalendarEvents.d.ts +0 -26
  16. package/dist/hooks/UseModalActions.d.ts +1 -0
  17. package/dist/index.mjs +9749 -9387
  18. package/dist/theme/tokens.d.ts +17 -12
  19. package/dist/types.d.ts +14 -1
  20. package/package.json +1 -1
  21. package/src/__tests__/CalendarLegend.test.tsx +16 -5
  22. package/src/__tests__/CalendarListLabels.test.tsx +253 -44
  23. package/src/__tests__/DayTypeChips.test.tsx +213 -23
  24. package/src/__tests__/filtering.test.ts +227 -0
  25. package/src/__tests__/fixtures.ts +15 -0
  26. package/src/__tests__/helpers/cases.test.ts +42 -1
  27. package/src/__tests__/helpers/dayTypeCounts.test.ts +88 -11
  28. package/src/__tests__/helpers/eventLabel.test.ts +4 -14
  29. package/src/__tests__/helpers/routing.test.ts +33 -0
  30. package/src/__tests__/hooks/UseCalendarEventsDayLoad.test.ts +30 -9
  31. package/src/__tests__/hooks/UseCalendarEventsUploadMarkers.test.ts +182 -0
  32. package/src/_components/CCalendar.css +103 -10
  33. package/src/_components/CCalendar.tsx +17 -2
  34. package/src/_components/CalendarDecorative.css +8 -0
  35. package/src/_components/CalendarEvents.css +6 -22
  36. package/src/_components/CalendarLegend.tsx +3 -2
  37. package/src/_components/DayTypeChips.tsx +206 -24
  38. package/src/_components/List/CalendarList.tsx +194 -27
  39. package/src/_components/Modal/DateDetails/DateDetails.tsx +28 -1
  40. package/src/_components/Modal/Modal.tsx +9 -0
  41. package/src/_components/Toolbar/DateTypeFilter.tsx +33 -2
  42. package/src/_components/Toolbar/Toolbar.tsx +3 -1
  43. package/src/constants.ts +3 -0
  44. package/src/helpers/api/courtDates.ts +60 -0
  45. package/src/helpers/cases.ts +16 -0
  46. package/src/helpers/courtDates.ts +40 -1
  47. package/src/helpers/dayTypeCounts.ts +137 -20
  48. package/src/helpers/eventLabel.ts +1 -6
  49. package/src/helpers/filtering.ts +57 -6
  50. package/src/helpers/motionWindow.ts +15 -4
  51. package/src/helpers/routing.ts +11 -1
  52. package/src/hooks/UseCalendarEvents.ts +79 -35
  53. package/src/hooks/UseModalActions.ts +37 -1
  54. package/src/theme/tokens.ts +17 -12
  55. package/src/types.ts +27 -1
@@ -1,4 +1,11 @@
1
1
  {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(npx tsc *)",
5
+ "Bash(echo \"EXIT=$?\")",
6
+ "Bash(npx vitest *)"
7
+ ]
8
+ },
2
9
  "hooks": {
3
10
  "PostToolUse": [
4
11
  {
@@ -5,4 +5,16 @@ export declare const MOCK_USER_ID = 42;
5
5
  export declare function makeCourtDate(overrides?: Partial<CourtDate>): CourtDate;
6
6
  export declare function makeOpenCase(overrides?: Partial<OpenCase>): OpenCase;
7
7
  export declare function makeCase(overrides?: Partial<Case>): Case;
8
+ /**
9
+ * A neutral baseline, NOT a copy of constants.ts's DEFAULT_FILTER_CTX. The filters that
10
+ * would silently shrink a result set are switched off here so each test only exercises
11
+ * the dimension it sets:
12
+ * - showOnlyUnsettled (real default true) → false, so settled cases survive
13
+ * - showPastNegotiations (real default false) → true, so past negotiation dates
14
+ * survive; makeCourtDate's default CourtDate is a fixed past date, which would
15
+ * otherwise empty every negotiation fixture in the suite.
16
+ * - showOutForDecision (real default false) → true, for the same reason: a fixture
17
+ * case with SCARDeterminationAction 'D' would otherwise take its whole date with it.
18
+ * Tests covering any of these dimensions set it explicitly.
19
+ */
8
20
  export declare const DEFAULT_FILTER_CTX: CalendarFilterCtx;
@@ -1,16 +1,4 @@
1
1
  import { DayTypeChip } from '../helpers/dayTypeCounts';
2
- /**
3
- * The breakdown row in a month day cell's header, beside the day number.
4
- *
5
- * Always on. Collapsed, a chip is a colour swatch and a count — the same swatch language
6
- * as CalendarLegend, scaled down to fit the day-number line. Hovering one chip expands its
7
- * label; the row never wraps, so the others slide along and clip rather than dropping to a
8
- * second line. All of that is CSS (see .cc-day-chips in CCalendar.css); this stays a plain
9
- * DOM tree with no hooks or context so it can be tested without rendering FullCalendar.
10
- *
11
- * Rendered through FullCalendar's `dayCellContent`, which portals it back into the app's
12
- * own React tree — but it takes everything it needs as props, so that never matters here.
13
- */
14
2
  export default function DayTypeChips({ chips }: {
15
3
  chips: DayTypeChip[];
16
4
  }): import("react/jsx-runtime").JSX.Element | null;
@@ -1,10 +1,12 @@
1
1
  import { AdjournmentEntry, Case, CourtDate, DateEditItem } from '../../../types';
2
- export default function DateDetails({ selectedCourtDate, cases, isVillage, isFetchingCases, onUpdateChair, adjournments, courtDateHistory, canFileMotion, }: {
2
+ export default function DateDetails({ selectedCourtDate, cases, isVillage, isFetchingCases, onUpdateChair, onToggleComplete, adjournments, courtDateHistory, canFileMotion, }: {
3
3
  selectedCourtDate: CourtDate | null;
4
4
  cases: Case[];
5
5
  isVillage: boolean;
6
6
  isFetchingCases?: boolean;
7
7
  onUpdateChair?: (position: 'first' | 'second', userId: number | null) => void;
8
+ /** Negotiations only — undefined for every other type, and for read-only users. */
9
+ onToggleComplete?: (complete: boolean) => void;
8
10
  adjournments?: AdjournmentEntry[];
9
11
  courtDateHistory?: DateEditItem[];
10
12
  /** Passed straight to MotionToPreclude — see the note on its own prop. */
@@ -1,8 +1,9 @@
1
1
  import { CalendarFilterCtx } from '../../types';
2
2
  /**
3
3
  * `mode` mirrors CaseFilter's: the window-widening "Deadlines" / "Can Preclude" pills are
4
- * primary-row controls, while "Completed" lives in the More list — it is a rarely-wanted
5
- * escape hatch for markers the calendar has deliberately finished with.
4
+ * primary-row controls, while "Completed", "Past Negs" and "Out for Decision" live in the
5
+ * More list — all three are rarely-wanted escape hatches for dates the calendar has
6
+ * deliberately finished with.
6
7
  */
7
8
  export default function DateTypeFilter({ filterCtx, setFilterCtx, mode, }: {
8
9
  filterCtx: CalendarFilterCtx;
@@ -1 +1 @@
1
- .pop-in-ccalendar-event{opacity:0;transform:scale(.8);transform-origin:center center;animation:popInBounce .4s cubic-bezier(.34,1.56,.64,1) forwards;will-change:opacity,transform}@keyframes popInBounce{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:scale(1)}}#ccalendar-container *::-webkit-scrollbar{width:8px;background:var(--bg)}#ccalendar-container *::-webkit-scrollbar-thumb{background:var(--fc-border-color);border-radius:4px}#ccalendar-container *::-webkit-scrollbar-track{background:var(--bg)}#ccalendar-container *::-webkit-scrollbar-corner{background:var(--bg)}#ccalendar-container .MuiDataGrid-row:hover,#ccalendar-container .MuiDataGrid-row:hover>.MuiDataGrid-cell{background-color:var(--fc-today-bg-color)!important}.court-calendar a{color:var(--text)!important;text-decoration:none!important}.month-day-cell{background-color:var(--bg);color:var(--text);cursor:pointer;height:120px;padding:3px!important;position:relative}.month-day-cell.fc-day-other{filter:brightness(.9)}.month-day-cell.fc-day-today{background-color:var(--fc-today-bg-color)}.month-day-cell.overbooked-day{box-shadow:inset 0 0 0 2px #dc262673;background-color:#dc26260f}.month-day-cell.overbooked-day.fc-day-today{background-color:var(--fc-today-bg-color)}.month-day-cell:hover:after{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background-color:var(--fc-today-bg-color);opacity:.5;pointer-events:none}.fc-daygrid-day-top .fc-daygrid-day-number{display:flex;width:100%;align-items:center;gap:4px;padding:2px 4px}.cc-day-number{flex-shrink:0;margin-left:auto}.cc-day-chips{display:flex;flex-wrap:nowrap;align-items:center;gap:3px;min-width:0;overflow:hidden}.cc-day-chip{display:inline-flex;align-items:center;gap:2px;flex-shrink:0;font-size:.6rem;font-weight:600;line-height:1;padding:2px 3px;border-radius:4px;white-space:nowrap;background-color:color-mix(in srgb,currentColor 12%,transparent)}.cc-day-chip-swatch{display:inline-block;width:8px;height:8px;border-radius:2px;flex-shrink:0}.cc-day-chip-label{max-width:0;overflow:hidden;white-space:nowrap;transition:max-width .22s cubic-bezier(.4,0,.2,1)}.cc-day-chip:hover .cc-day-chip-label{max-width:90px;margin-right:1px}.cc-day-chip-count{flex-shrink:0}.day-header{background-color:var(--bg);color:var(--text);border-bottom:1px solid var(--fc-border-color)}.day-header a{padding:6px 4px!important;display:inline-block}.court-calendar th[role=presentation]{background-color:var(--bg)}.day-cell-allday{background-color:var(--bg)!important;color:var(--text)!important}.fc-daygrid-day-events{max-height:100px;min-height:100px;overflow-y:inherit;margin:0!important;overflow-y:auto;scrollbar-color:var(--fc-border-color) transparent}.fc-day-today .fc-daygrid-day-events{scrollbar-color:var(--fc-event-unknown-color) transparent}.court-calendar .fc-timegrid-slot-label{background-color:var(--bg);color:var(--text)}.court-calendar .fc-timegrid-axis{border-color:var(--fc-border-color);background-color:var(--bg);color:var(--text)}.court-calendar .fc-timegrid-divider{border-color:var(--fc-border-color);background-color:var(--bg)}.fc .fc-button,.fc-button{background-color:var(--bg);color:var(--text);border:1px solid var(--fc-border-color);font-family:Roboto,Helvetica,Arial,"sans-serif";padding:.25rem .5rem;cursor:pointer}:is(.fc .fc-button,.fc-button).fc-button-primary{background-color:var(--bg);color:var(--text);border:1px solid var(--fc-border-color)}:is(.fc .fc-button,.fc-button).fc-button-active.fc-button-primary{background-color:var(--fc-today-bg-color);color:var(--text)}:is(.fc .fc-button,.fc-button):hover{background-color:var(--fc-today-bg-color)}.fc.fc-media-screen{background-color:var(--bg);color:var(--text);font-family:Roboto,Helvetica,Arial,"sans-serif"}.CCButton{background-color:var(--bg);color:var(--text);border:1px solid var(--fc-border-color);font-family:Roboto,Helvetica,Arial,"sans-serif";padding:8px 16px;margin-right:8px;border-radius:4px;cursor:pointer;-webkit-user-select:none;user-select:none}.CCButton:hover{background-color:var(--fc-today-bg-color)}.CCButton-Icon{min-width:35px;max-width:35px;min-height:35px;max-height:35px;border:none;padding:0;display:flex;align-items:center;justify-content:center}.CCDropdown-Button{width:75px}.CCDropdown-Menu{background-color:var(--bg);color:var(--text);border:1px solid var(--fc-border-color);font-family:Roboto,Helvetica,Arial,"sans-serif";box-shadow:0 2px 8px #00000026}.CCDropdown-Menu div{padding:8px 19px}.CCDropdown-Menu div:hover{background-color:var(--fc-today-bg-color)}.CCButton-Primary{background-color:#1976d2;color:#fff;border:none}.CCButton-Primary:hover{background-color:#1565c0}.CCButton-Error{background-color:#c15a5a;color:#fff;border:none}.CCButton-Error:hover{background-color:#953838}.ccdisabled{pointer-events:none;opacity:.6}.switch-track{outline:2px solid var(--fc-border-color)}.ccalendar-list-row{cursor:pointer;transition:background-color .2s ease-in-out}.CCAvatarIcon:hover{cursor:pointer;transform:scale(1.1);box-shadow:0 4px 8px #0003}#event-tooltip{background-color:var(--text);color:var(--bg);border:1px solid var(--fc-border-color);border-radius:4px;padding:8px;box-shadow:0 4px 8px #00000026;z-index:9999;font-size:16px}.court-event{cursor:pointer;padding:4px 2px}.fc-list .fc-list-day-cushion{background-color:var(--bg)!important;color:var(--text)}.fc-list .fc-list-event:hover td{background-color:var(--fc-today-bg-color)!important}.fc-list .deadline-event .fc-list-event-dot{border:none;width:1em;height:1em;vertical-align:middle;background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><circle cx="8" cy="8" r="8" fill="%2300c853"/><path d="M4 8l3 3 5-5" stroke="white" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>') no-repeat center center;background-size:contain}.fc-list .deadline-event.inperson{--color: var(--fc-event-inperson-color)}.fc-list .deadline-event.virtual{--color: var(--fc-event-virtual-color)}.fc-list .deadline-event.unknown{--color: var(--fc-event-unknown-color)}.fc-list .deadline-event.negotiations{--color: var(--fc-event-negotiations-color)}.fc-list .deadline-event.collections{--color: var(--fc-event-collections-color)}.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event{background-color:transparent!important;border-color:transparent!important;display:flex;align-items:center;overflow-x:hidden;position:relative}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event) .fc-event-title{color:var(--text)!important}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).inperson{--color: var(--fc-event-inperson-color)}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).virtual{--color: var(--fc-event-virtual-color)}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).unknown{--color: var(--fc-event-unknown-color)}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).negotiations{--color: var(--fc-event-negotiations-color)}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).collections{--color: var(--fc-event-collections-color)}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).adjourned-no-date{--color: rgb(151, 11, 134) !important}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).status-uploaded:before{content:"";display:inline-block;width:1em;height:1em;vertical-align:middle;background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><circle cx="8" cy="8" r="8" fill="%2300c853"/><path d="M4 8l3 3 5-5" stroke="white" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>') no-repeat center center;background-size:contain;margin:0 4px 0 0;top:.5em;border:none;position:absolute}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).status-uploaded .fc-event-main{margin-left:1.5em!important}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event):not(.status-uploaded):before{content:"";display:inline-block;border-radius:calc(var(--fc-daygrid-event-dot-width) / 2);box-sizing:content-box;height:0px;margin:0 4px;width:0px;border:calc(var(--fc-daygrid-event-dot-width) / 2) solid var(--color)}.courtdate-event,.adjournment-event,.multipledate-event{border:1px solid var(--fc-border-color)!important}:is(.courtdate-event,.adjournment-event,.multipledate-event) .fc-event-title,:is(.courtdate-event,.adjournment-event,.multipledate-event) .fc-event-time{color:#fff!important}:is(.courtdate-event,.adjournment-event,.multipledate-event).inperson{background-color:var(--fc-event-inperson-color)!important;border-color:var(--fc-event-inperson-color)!important}:is(.courtdate-event,.adjournment-event,.multipledate-event).virtual{background-color:var(--fc-event-virtual-color)!important;border-color:var(--fc-event-virtual-color)!important}:is(.courtdate-event,.adjournment-event,.multipledate-event).unknown{background-color:var(--fc-event-unknown-color)!important;border-color:var(--fc-event-unknown-color)!important}:is(.courtdate-event,.adjournment-event,.multipledate-event).negotiations{background-color:var(--fc-event-negotiations-color)!important;border-color:var(--fc-event-negotiations-color)!important}:is(.courtdate-event,.adjournment-event,.multipledate-event).collections{background-color:var(--fc-event-collections-color)!important;border-color:var(--fc-event-collections-color)!important}:is(.courtdate-event,.adjournment-event,.multipledate-event) .fc-daygrid-event-dot,:is(.courtdate-event,.adjournment-event,.multipledate-event) .fc-list-event-dot{display:none}:is(.courtdate-event,.adjournment-event,.multipledate-event).adjourned-no-date{border-color:#970b86!important;background-color:#970b86!important}:is(.courtdate-event,.adjournment-event,.multipledate-event).scar-overbooked{border-color:var(--fc-event-overbooked-color)!important;background-color:var(--fc-event-overbooked-color)!important}:is(.courtdate-event,.adjournment-event,.multipledate-event).adjourned-no-date.scar-overbooked{background-image:linear-gradient(to right,rgb(151,11,134) 0 30%,var(--fc-event-overbooked-color) 70% 100%)!important}.village-date.courtdate-event,.village-date.adjournment-event,.village-date.multipledate-event{border:2px solid #f59e0b!important}.deadline-due-today.courtdate-event,.deadline-due-today.multipledate-event{border:2px solid #d32f2f!important;outline:1px solid #d32f2f}.deadline-due-today.courtdate-event .fc-event-main,.deadline-due-today.multipledate-event .fc-event-main{position:relative}.deadline-due-today.courtdate-event .fc-event-main:after,.deadline-due-today.multipledate-event .fc-event-main:after{content:"!";position:absolute;top:0;right:2px;background:#d32f2f;color:#fff;border-radius:50%;width:14px;height:14px;font-size:10px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;line-height:1;z-index:99999}.fc-view:not(.fc-list) .deadline-due-today.deadline-event{border:2px solid #d32f2f!important;border-radius:2px;padding-bottom:2px}.fc-view:not(.fc-list) .deadline-due-today.deadline-event .fc-event-title{color:#d32f2f!important;font-weight:700}.fc-view:not(.fc-list) .deadline-due-today.deadline-event:after{content:"!";position:absolute;left:2px;top:.7em;background:#d32f2f;color:#fff;border-radius:50%;width:14px;height:14px;font-size:10px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;line-height:1;z-index:99999}@keyframes overdueFlash{0%,to{border-color:#b71c1c!important;box-shadow:0 0 #b71c1c00}50%{border-color:#ff1744!important;box-shadow:0 0 8px 3px #ff174499}}.deadline-overdue.courtdate-event,.deadline-overdue.multipledate-event{border:2px solid #b71c1c!important;animation:overdueFlash 1.8s ease-in-out infinite!important}.deadline-overdue.courtdate-event .fc-event-main,.deadline-overdue.multipledate-event .fc-event-main{position:relative}.deadline-overdue.courtdate-event .fc-event-main:after,.deadline-overdue.multipledate-event .fc-event-main:after{content:"⚠";position:absolute;top:0;right:2px;background:#b71c1c;color:#fff;border-radius:50%;width:16px;height:16px;font-size:10px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;line-height:1;z-index:5}.fc-view:not(.fc-list) .deadline-overdue.deadline-event{border:2px solid #b71c1c!important;border-radius:2px;padding-bottom:2px;animation:overdueFlash 1.8s ease-in-out infinite!important}.fc-view:not(.fc-list) .deadline-overdue.deadline-event .fc-event-title{color:#b71c1c!important;font-weight:700}.fc-view:not(.fc-list) .deadline-overdue.deadline-event:after{content:"⚠";position:absolute;left:2px;top:.5em;background:#b71c1c;color:#fff;border-radius:50%;width:14px;height:14px;font-size:10px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;line-height:1;z-index:99999}#ccalendar-toolbar{position:relative}#ccalendar-header{box-shadow:0 2px 12px #00000012;position:relative}#ccalendar-header:after{content:"";position:absolute;bottom:0;left:0;right:0;height:2px;background:var(--cc-gradient);opacity:.55;pointer-events:none}#ccalendar-nav .MuiTypography-h6{background:var(--cc-gradient);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;font-weight:700!important}#ccalendar-toolbar .MuiButton-outlined:not([disabled]),#ccalendar-nav .MuiButton-outlined:not([disabled]){border:1.5px solid transparent!important;background:linear-gradient(var(--bg),var(--bg)) padding-box,var(--cc-gradient) border-box!important;transition:box-shadow .15s ease!important}#ccalendar-toolbar .MuiButton-outlined:not([disabled]):hover,#ccalendar-nav .MuiButton-outlined:not([disabled]):hover{background:linear-gradient(var(--fc-today-bg-color),var(--fc-today-bg-color)) padding-box,var(--cc-gradient) border-box!important;box-shadow:0 0 8px 1px var(--cc-glow-purple)!important}.month-day-cell.fc-day-today{background-image:linear-gradient(135deg,#3b82f612,#8b5cf612,#06b6d40d)}.courtdate-event,.adjournment-event,.multipledate-event{border-radius:4px!important;transition:filter .12s ease,box-shadow .12s ease!important}.courtdate-event:hover,.adjournment-event:hover,.multipledate-event:hover{filter:brightness(1.1)!important;box-shadow:0 2px 10px #0000004d!important;z-index:5}#event-tooltip{border:1.5px solid transparent!important;background:linear-gradient(var(--text),var(--text)) padding-box,var(--cc-gradient) border-box!important;box-shadow:0 0 14px 2px #8b5cf638,0 4px 18px #00000047!important;border-radius:10px!important;padding:0!important;font-size:16px!important;font-family:Roboto,Helvetica,Arial,sans-serif!important;min-width:240px!important;max-width:340px!important}#event-tooltip .tt-card{padding:14px 16px}#event-tooltip .tt-title{font-size:17px;font-weight:700;line-height:1.3;margin-bottom:4px}#event-tooltip .tt-date{font-size:15px;opacity:.7;margin-bottom:8px}#event-tooltip .tt-badge{display:inline-block;padding:3px 9px;border-radius:4px;font-size:13px;font-weight:600;letter-spacing:.03em;margin-bottom:8px}#event-tooltip .tt-badge--blue{background:#3b82f659}#event-tooltip .tt-badge--purple{background:#8b5cf659}#event-tooltip .tt-badge--amber{background:#f59e0b59}#event-tooltip .tt-badge--cyan{background:#06b6d459}#event-tooltip .tt-badge--red{background:#dc262659}#event-tooltip .tt-divider{height:1px;background:#80808047;margin:8px 0}#event-tooltip .tt-grid{display:grid;grid-template-columns:auto 1fr;gap:6px 14px;font-size:15px}#event-tooltip .tt-label{opacity:.58;white-space:nowrap;line-height:1.5}#event-tooltip .tt-value{font-weight:500;line-height:1.5}#event-tooltip .tt-footer{font-size:13px;opacity:.42;text-align:center;margin-top:8px;padding-top:6px;border-top:1px solid rgba(128,128,128,.22)}#ccalendar-nav .MuiToggleButtonGroup-root .MuiToggleButton-root{color:#1976d2;border:1.5px solid transparent!important;background:linear-gradient(var(--bg),var(--bg)) padding-box,var(--cc-gradient) border-box!important;transition:box-shadow .15s ease!important}#ccalendar-nav .MuiToggleButtonGroup-root .MuiToggleButton-root:hover{color:#1976d2!important;background:linear-gradient(var(--fc-today-bg-color),var(--fc-today-bg-color)) padding-box,var(--cc-gradient) border-box!important;box-shadow:0 0 8px 1px var(--cc-glow-purple)!important}#ccalendar-nav .MuiToggleButtonGroup-root .MuiToggleButton-root.Mui-selected{background:linear-gradient(var(--fc-today-bg-color),var(--fc-today-bg-color)) padding-box,var(--cc-gradient) border-box!important}#ccalendar-nav .MuiToggleButtonGroup-root .MuiToggleButton-root:not(.Mui-selected){color:#4397ecde}#ccalendar-toolbar .MuiToggleButton-root:hover:not(.Mui-selected){background-color:var(--fc-today-bg-color)!important}#ccalendar-toolbar .cc-more-btn-open{border:1.5px solid transparent!important;background:linear-gradient(var(--bg),var(--bg)) padding-box,var(--cc-gradient) border-box!important}.modal-footer .MuiButton-containedPrimary{background-image:var(--cc-gradient)!important;box-shadow:0 0 10px 1px var(--cc-glow-purple),0 2px 6px #0000002e!important;transition:opacity .15s ease,box-shadow .15s ease!important}.modal-footer .MuiButton-containedPrimary:hover:not([disabled]){background-image:var(--cc-gradient)!important;opacity:.9;box-shadow:0 0 16px 2px var(--cc-glow-purple),0 2px 8px #00000038!important}.modal-footer .MuiButton-containedPrimary{text-shadow:0 1px 3px rgba(0,0,0,.35)!important}@page{size:landscape;margin:.5in}@media print{#ccalendar-container>.MuiStack-root:first-child,#event-tooltip,.ReactModal__Overlay,.MuiDataGrid-footerContainer{display:none!important}#ccalendar-container{width:100%!important;overflow:visible!important;padding-top:10px}.fc.fc-media-screen,.fc .fc-scrollgrid,.fc .fc-scrollgrid-section>td,.fc .fc-daygrid-body,.fc table{width:100%!important;max-width:100%!important}.fc .fc-scrollgrid{overflow:visible!important}.fc colgroup col{width:auto!important}.fc-daygrid-day-events{max-height:none!important;min-height:auto!important;overflow:visible!important}.month-day-cell{height:auto!important}.cc-day-chips{display:none!important}#ccalendar-container .MuiDataGrid-root{height:auto!important;max-height:none!important}#ccalendar-container .MuiDataGrid-virtualScroller{overflow:visible!important;height:auto!important}*{-webkit-print-color-adjust:exact!important;print-color-adjust:exact!important}}@keyframes cc-crt-body{0%{transform:translate(0);filter:none;opacity:1}3%{filter:brightness(.85);opacity:.85}6%{filter:none;opacity:1}9%{filter:brightness(1.12);opacity:.75}12%{transform:translate(0);filter:none;opacity:1}15%{transform:translate(0);filter:blur(.5px) hue-rotate(80deg) brightness(.95);opacity:.95}18%{transform:translate(-3px) skew(-1.5deg);filter:blur(1px) hue-rotate(100deg) saturate(1.5);opacity:.9}22%{transform:translate(3px) skew(1.5deg);filter:blur(.5px) hue-rotate(90deg) brightness(1.1);opacity:.95}25%{transform:translate(0);filter:blur(1.5px) hue-rotate(110deg) saturate(1.8);opacity:.85}28%{transform:translate(-5px,1px) skew(-2deg);filter:blur(2px) hue-rotate(130deg) contrast(1.3);opacity:.8}31%{transform:translate(5px,-1px) skew(2deg);filter:blur(1px) hue-rotate(90deg) brightness(1.2);opacity:.88}35%{transform:translate(0);filter:blur(2px) hue-rotate(100deg) saturate(1.2);opacity:.75}38%{transform:translate(-8px,2px) skew(-4deg);filter:blur(3px) hue-rotate(160deg) contrast(1.6);opacity:.6}39%{transform:translate(8px,-2px) skew(4deg);filter:blur(1.5px) hue-rotate(60deg) brightness(1.4);opacity:.75}43%{transform:translate(-2px,1px);filter:blur(3.5px) grayscale(.2) saturate(.8);opacity:.65}47%{filter:blur(2px) brightness(.35);opacity:.18}50%{transform:translate(0);filter:blur(4px) grayscale(.4) contrast(1.4);opacity:.7}53%{transform:translate(-6px,2px) skew(-3deg);filter:blur(3px) grayscale(.3) hue-rotate(180deg);opacity:.55}55%{transform:translate(6px,-2px) skew(3deg);filter:blur(2px) brightness(1.5) contrast(1.8);opacity:.7}58%{transform:translate(0);filter:blur(5px) grayscale(.6) brightness(.6);opacity:.5}60%{filter:blur(4px) brightness(.25);opacity:.12}62%{filter:blur(3px) brightness(1.2);opacity:.6}65%{transform:translate(-10px,3px) skew(-5deg);filter:blur(6px) grayscale(.7) contrast(1.5);opacity:.45}66%{transform:translate(10px,-3px) skew(5deg);filter:blur(3px) grayscale(.5) brightness(1.8);opacity:.6}70%{transform:translate(-4px,2px);filter:blur(7px) grayscale(.8) saturate(.2);opacity:.35}73%{filter:blur(6px) brightness(.18);opacity:.08}75%{transform:translate(0);filter:blur(6px) grayscale(.85) brightness(.5);opacity:.4}78%{transform:translate(-12px,4px) skew(-6deg);filter:blur(8px) grayscale(.9) contrast(2);opacity:.3}79%{transform:translate(12px,-4px) skew(6deg);filter:blur(4px) grayscale(.7) brightness(1.6);opacity:.45}84%{transform:translate(-3px,1px);filter:blur(9px) grayscale(.95) brightness(.35);opacity:.2}88%{filter:blur(8px) brightness(.08);opacity:.04}90%{transform:translate(0);filter:blur(10px) grayscale(1) brightness(.25);opacity:.14}95%{transform:translate(0);filter:blur(12px) grayscale(1) brightness(.1);opacity:.05}to{transform:translate(0);filter:blur(14px) grayscale(1) brightness(0);opacity:0}}@keyframes cc-crt-scanlines{0%{opacity:0;background-position-y:0px}14%{opacity:0;background-position-y:0px}22%{opacity:.28;background-position-y:-4px}42%{opacity:.5;background-position-y:-18px}67%{opacity:.72;background-position-y:-42px}88%{opacity:.88;background-position-y:-66px}to{opacity:1;background-position-y:-84px}}@keyframes cc-crt-vignette{0%{opacity:0}22%{opacity:.25}to{opacity:.88}}.cc-glitch-active{position:relative;animation:cc-crt-body 2s linear forwards;pointer-events:none;overflow:hidden}.cc-glitch-active:before{content:"";position:absolute;inset:0;background:repeating-linear-gradient(to bottom,transparent 0px,transparent 2px,rgba(0,0,0,.1) 2px,rgba(0,0,0,.1) 4px);z-index:9999;pointer-events:none;animation:cc-crt-scanlines 2s linear forwards}.cc-glitch-active:after{content:"";position:absolute;inset:0;background:radial-gradient(ellipse at center,transparent 55%,rgba(0,0,0,.6) 100%);z-index:9998;pointer-events:none;animation:cc-crt-vignette 2s linear forwards}@keyframes cc-humphrey-appear{0%{color:transparent;text-shadow:none;opacity:0;transform:skew(0)}4%{color:red;text-shadow:0 0 30px #ff0000,0 0 60px #ff0000;opacity:.9;transform:skew(-8deg)}6%{color:transparent;text-shadow:none;opacity:0;transform:skew(0)}9%{color:red;text-shadow:0 0 20px #ff0000;opacity:.7;transform:skew(5deg)}11%{color:transparent;text-shadow:none;opacity:0;transform:skew(0)}14%{color:#ff2020;text-shadow:2px 0 0 #ff0000,-2px 0 0 #00ffff;opacity:1;transform:skew(-4deg)}17%{color:#dc143c;text-shadow:0 0 12px #dc143c;opacity:.4;transform:skew(2deg)}20%{color:#ff2020;text-shadow:4px 0 0 #ff0000,-4px 0 0 #00ffff;opacity:1;transform:skew(-6deg)}23%{color:transparent;text-shadow:none;opacity:0;transform:skew(0)}26%{color:#ff2020;text-shadow:0 0 8px #ff0000;opacity:.8;transform:skew(3deg)}30%{color:#ff2020;text-shadow:3px 0 0 #ff0000,-3px 0 0 #00ffff;opacity:1;transform:skew(-3deg)}34%{color:#dc143c;text-shadow:0 0 6px #dc143c,0 0 14px #dc143c50;opacity:.6;transform:skew(0)}38%{color:#ff2020;text-shadow:1px 0 0 #ff0000,-1px 0 0 #00ffff;opacity:1;transform:skew(-2deg)}43%{color:transparent;text-shadow:none;opacity:0;transform:skew(0)}45%{color:#ff1010;text-shadow:0 0 10px #ff0000;opacity:.9;transform:skew(4deg)}48%{color:#dc143c;text-shadow:0 0 4px #dc143c;opacity:.7;transform:skew(-1deg)}53%{color:#ff2020;text-shadow:2px 0 0 #ff0000,-2px 0 0 #00ffff;opacity:1;transform:skew(2deg)}57%{color:#dc143c;text-shadow:0 0 6px #dc143c;opacity:.85;transform:skew(0)}63%{color:transparent;text-shadow:none;opacity:0}65%{color:#dc143c;text-shadow:0 0 8px #dc143c,0 0 18px #dc143c60;opacity:1;transform:skew(-1deg)}72%{color:#dc143c;text-shadow:0 0 3px #dc143c;opacity:.9;transform:skew(0)}78%{opacity:.7}84%{color:#dc143c;text-shadow:0 0 5px #dc143c,0 0 10px #dc143c70;opacity:1}91%{opacity:.85}to{color:#dc143c;text-shadow:0 0 3px #dc143c,0 0 8px #dc143c90;opacity:1;transform:skew(0)}}.cc-humphrey{display:inline-block;animation:cc-humphrey-appear 1.6s steps(1,end) forwards}@keyframes cc-crt-flicker{0%,18%,22%,24%,53%,57%,to{opacity:1}20%,55%{opacity:.91}23%{opacity:.95}56%{opacity:.93}}@keyframes cc-crt-scanroll{0%{background-position-y:0}to{background-position-y:4px}}.cc-crt-ambient{position:relative;overflow:hidden;animation:cc-crt-flicker 7s linear infinite}.cc-crt-ambient:before{content:"";position:absolute;inset:0;background:repeating-linear-gradient(to bottom,transparent 0px,transparent 2px,rgba(0,0,0,.07) 2px,rgba(0,0,0,.07) 4px);pointer-events:none;z-index:9999;animation:cc-crt-scanroll .18s linear infinite}.cc-crt-ambient:after{content:"";position:absolute;inset:0;background:radial-gradient(ellipse at center,transparent 55%,rgba(0,0,0,.42) 100%);pointer-events:none;z-index:9998}.cc-crt-in{position:relative;overflow:hidden;animation:cc-crt-body 2s linear reverse both}.cc-crt-in:before{content:"";position:absolute;inset:0;background:repeating-linear-gradient(to bottom,transparent 0px,transparent 2px,rgba(0,0,0,.1) 2px,rgba(0,0,0,.1) 4px);z-index:9999;pointer-events:none;animation:cc-crt-scanlines 2s linear reverse both}.cc-crt-in:after{content:"";position:absolute;inset:0;background:radial-gradient(ellipse at center,transparent 55%,rgba(0,0,0,.6) 100%);z-index:9998;pointer-events:none;animation:cc-crt-vignette 2s linear reverse both}
1
+ .pop-in-ccalendar-event{transform-origin:center center;animation:popInBounce .4s cubic-bezier(.34,1.56,.64,1) backwards;will-change:opacity,transform}@keyframes popInBounce{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:scale(1)}}#ccalendar-container *::-webkit-scrollbar{width:8px;background:var(--bg)}#ccalendar-container *::-webkit-scrollbar-thumb{background:var(--fc-border-color);border-radius:4px}#ccalendar-container *::-webkit-scrollbar-track{background:var(--bg)}#ccalendar-container *::-webkit-scrollbar-corner{background:var(--bg)}#ccalendar-container .MuiDataGrid-row:hover,#ccalendar-container .MuiDataGrid-row:hover>.MuiDataGrid-cell{background-color:var(--fc-today-bg-color)!important}.court-calendar a{color:var(--text)!important;text-decoration:none!important}.month-day-cell{background-color:var(--bg);color:var(--text);cursor:pointer;height:120px;padding:3px!important;position:relative}.month-day-cell.fc-day-other{filter:brightness(.9)}.month-day-cell.fc-day-today{background-color:var(--fc-today-bg-color)}.month-day-cell.overbooked-day{box-shadow:inset 0 0 0 2px #dc262673;background-color:#dc26260f}.month-day-cell.overbooked-day.fc-day-today{background-color:var(--fc-today-bg-color)}.month-day-cell:hover:after{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background-color:var(--fc-today-bg-color);opacity:.5;pointer-events:none}.fc-daygrid-day-top .fc-daygrid-day-number{display:flex;width:100%;align-items:center;gap:4px;padding:2px 4px}.cc-day-number{flex-shrink:0;margin-left:auto}.cc-day-chips{display:flex;flex-wrap:nowrap;align-items:center;gap:3px;min-width:0;overflow:hidden}.cc-day-chip{display:inline-flex;align-items:center;gap:2px;flex-shrink:0;font-size:.7rem;font-weight:600;line-height:1;padding:1px 3px;border-radius:4px;white-space:nowrap;background-color:color-mix(in srgb,currentColor 22%,transparent)}.cc-day-chip--out{animation:chipPopOut .24s cubic-bezier(.4,0,1,1) forwards;pointer-events:none}@keyframes chipPopOut{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.6)}}.cc-day-chip-swatch{display:inline-block;width:8px;height:8px;border-radius:2px;flex-shrink:0}.cc-day-chip[data-mark=glyph]{color:var(--text)}.cc-day-chip--urgent{font-weight:700}.cc-day-chip-glyph{font-size:1rem;display:inline-flex;flex-shrink:0}.cc-day-chip-label{max-width:0;overflow:hidden;white-space:nowrap;transition:max-width .22s cubic-bezier(.4,0,.2,1)}.cc-day-chip:hover .cc-day-chip-label{max-width:90px;margin-right:1px}.cc-day-chip-count{flex-shrink:0}.day-header{background-color:var(--bg);color:var(--text);border-bottom:1px solid var(--fc-border-color)}.day-header a{padding:6px 4px!important;display:inline-block}.court-calendar th[role=presentation]{background-color:var(--bg)}.day-cell-allday{background-color:var(--bg)!important;color:var(--text)!important}.fc-daygrid-day-events{max-height:100px;min-height:100px;margin:0!important;overflow-y:auto;scrollbar-color:var(--fc-border-color) transparent}.fc-day-today .fc-daygrid-day-events{scrollbar-color:var(--fc-event-unknown-color) transparent}.cc-view-dayGridWeek .month-day-cell{height:auto;min-height:120px}.cc-view-dayGridWeek .fc-daygrid-day-events{max-height:none;min-height:0;overflow-y:visible}.court-calendar .fc-timegrid-slot-label{background-color:var(--bg);color:var(--text)}.court-calendar .fc-timegrid-axis{border-color:var(--fc-border-color);background-color:var(--bg);color:var(--text)}.court-calendar .fc-timegrid-divider{border-color:var(--fc-border-color);background-color:var(--bg)}.fc .fc-button,.fc-button{background-color:var(--bg);color:var(--text);border:1px solid var(--fc-border-color);font-family:Roboto,Helvetica,Arial,"sans-serif";padding:.25rem .5rem;cursor:pointer}:is(.fc .fc-button,.fc-button).fc-button-primary{background-color:var(--bg);color:var(--text);border:1px solid var(--fc-border-color)}:is(.fc .fc-button,.fc-button).fc-button-active.fc-button-primary{background-color:var(--fc-today-bg-color);color:var(--text)}:is(.fc .fc-button,.fc-button):hover{background-color:var(--fc-today-bg-color)}.fc.fc-media-screen{background-color:var(--bg);color:var(--text);font-family:Roboto,Helvetica,Arial,"sans-serif"}.CCButton{background-color:var(--bg);color:var(--text);border:1px solid var(--fc-border-color);font-family:Roboto,Helvetica,Arial,"sans-serif";padding:8px 16px;margin-right:8px;border-radius:4px;cursor:pointer;-webkit-user-select:none;user-select:none}.CCButton:hover{background-color:var(--fc-today-bg-color)}.CCButton-Icon{min-width:35px;max-width:35px;min-height:35px;max-height:35px;border:none;padding:0;display:flex;align-items:center;justify-content:center}.CCDropdown-Button{width:75px}.CCDropdown-Menu{background-color:var(--bg);color:var(--text);border:1px solid var(--fc-border-color);font-family:Roboto,Helvetica,Arial,"sans-serif";box-shadow:0 2px 8px #00000026}.CCDropdown-Menu div{padding:8px 19px}.CCDropdown-Menu div:hover{background-color:var(--fc-today-bg-color)}.CCButton-Primary{background-color:#1976d2;color:#fff;border:none}.CCButton-Primary:hover{background-color:#1565c0}.CCButton-Error{background-color:#c15a5a;color:#fff;border:none}.CCButton-Error:hover{background-color:#953838}.ccdisabled{pointer-events:none;opacity:.6}.switch-track{outline:2px solid var(--fc-border-color)}.ccalendar-list-row{cursor:pointer;transition:background-color .2s ease-in-out}.CCAvatarIcon:hover{cursor:pointer;transform:scale(1.1);box-shadow:0 4px 8px #0003}#event-tooltip{background-color:var(--text);color:var(--bg);border:1px solid var(--fc-border-color);border-radius:4px;padding:8px;box-shadow:0 4px 8px #00000026;z-index:9999;font-size:16px}.court-event{cursor:pointer;padding:4px 2px}.fc-list .fc-list-day-cushion{background-color:var(--bg)!important;color:var(--text)}.fc-list .fc-list-event:hover td{background-color:var(--fc-today-bg-color)!important}.fc-list .deadline-event .fc-list-event-dot{border:none;width:1em;height:1em;vertical-align:middle;background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><circle cx="8" cy="8" r="8" fill="%2300c853"/><path d="M4 8l3 3 5-5" stroke="white" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>') no-repeat center center;background-size:contain}.fc-list .deadline-event.inperson{--color: var(--fc-event-inperson-color)}.fc-list .deadline-event.virtual{--color: var(--fc-event-virtual-color)}.fc-list .deadline-event.unknown{--color: var(--fc-event-unknown-color)}.fc-list .deadline-event.negotiations{--color: var(--fc-event-negotiations-color)}.fc-list .deadline-event.collections{--color: var(--fc-event-collections-color)}.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event{background-color:transparent!important;border-color:transparent!important;display:flex;align-items:center;overflow-x:hidden;position:relative}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event) .fc-event-title{color:var(--text)!important}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).inperson{--color: var(--fc-event-inperson-color)}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).virtual{--color: var(--fc-event-virtual-color)}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).unknown{--color: var(--fc-event-unknown-color)}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).negotiations{--color: var(--fc-event-negotiations-color)}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).collections{--color: var(--fc-event-collections-color)}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).adjourned-no-date{--color: rgb(151, 11, 134) !important}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).status-uploaded:before{content:"";display:inline-block;width:1em;height:1em;vertical-align:middle;background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><circle cx="8" cy="8" r="8" fill="%2300c853"/><path d="M4 8l3 3 5-5" stroke="white" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>') no-repeat center center;background-size:contain;margin:0 4px 0 0;top:.5em;border:none;position:absolute}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event).status-uploaded .fc-event-main{margin-left:1.5em!important}:is(.fc-view:not(.fc-list) .deadline-event,.fc-view:not(.fc-list) .motion-event):not(.status-uploaded):before{content:"";display:inline-block;border-radius:calc(var(--fc-daygrid-event-dot-width) / 2);box-sizing:content-box;height:0px;margin:0 4px;width:0px;border:calc(var(--fc-daygrid-event-dot-width) / 2) solid var(--color)}.courtdate-event,.adjournment-event,.multipledate-event{border:1px solid var(--fc-border-color)!important}:is(.courtdate-event,.adjournment-event,.multipledate-event) .fc-event-title,:is(.courtdate-event,.adjournment-event,.multipledate-event) .fc-event-time{color:#fff!important}:is(.courtdate-event,.adjournment-event,.multipledate-event).inperson{background-color:var(--fc-event-inperson-color)!important;border-color:var(--fc-event-inperson-color)!important}:is(.courtdate-event,.adjournment-event,.multipledate-event).virtual{background-color:var(--fc-event-virtual-color)!important;border-color:var(--fc-event-virtual-color)!important}:is(.courtdate-event,.adjournment-event,.multipledate-event).unknown{background-color:var(--fc-event-unknown-color)!important;border-color:var(--fc-event-unknown-color)!important}:is(.courtdate-event,.adjournment-event,.multipledate-event).negotiations{background-color:var(--fc-event-negotiations-color)!important;border-color:var(--fc-event-negotiations-color)!important}:is(.courtdate-event,.adjournment-event,.multipledate-event).collections{background-color:var(--fc-event-collections-color)!important;border-color:var(--fc-event-collections-color)!important}:is(.courtdate-event,.adjournment-event,.multipledate-event) .fc-daygrid-event-dot,:is(.courtdate-event,.adjournment-event,.multipledate-event) .fc-list-event-dot{display:none}:is(.courtdate-event,.adjournment-event,.multipledate-event).adjourned-no-date{border-color:#970b86!important;background-color:#970b86!important}.village-date.courtdate-event,.village-date.adjournment-event,.village-date.multipledate-event{border:2px solid #f59e0b!important}.deadline-due-today.courtdate-event,.deadline-due-today.multipledate-event{border:2px solid #d32f2f!important;outline:1px solid #d32f2f}.deadline-due-today.courtdate-event .fc-event-main,.deadline-due-today.multipledate-event .fc-event-main{position:relative}.deadline-due-today.courtdate-event .fc-event-main:after,.deadline-due-today.multipledate-event .fc-event-main:after{content:"!";position:absolute;top:0;right:2px;background:#d32f2f;color:#fff;border-radius:50%;width:14px;height:14px;font-size:10px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;line-height:1;z-index:99999}.fc-view:not(.fc-list) .deadline-due-today.deadline-event{border:2px solid #d32f2f!important;border-radius:2px;padding-bottom:2px}.fc-view:not(.fc-list) .deadline-due-today.deadline-event .fc-event-title{color:#d32f2f!important;font-weight:700}.fc-view:not(.fc-list) .deadline-due-today.deadline-event:after{content:"!";position:absolute;left:2px;top:.7em;background:#d32f2f;color:#fff;border-radius:50%;width:14px;height:14px;font-size:10px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;line-height:1;z-index:99999}@keyframes overdueFlash{0%,to{border-color:#b71c1c!important;box-shadow:0 0 #b71c1c00}50%{border-color:#ff1744!important;box-shadow:0 0 8px 3px #ff174499}}.deadline-overdue.courtdate-event,.deadline-overdue.multipledate-event{border:2px solid #b71c1c!important;animation:overdueFlash 1.8s ease-in-out infinite!important}.deadline-overdue.courtdate-event .fc-event-main,.deadline-overdue.multipledate-event .fc-event-main{position:relative}.deadline-overdue.courtdate-event .fc-event-main:after,.deadline-overdue.multipledate-event .fc-event-main:after{content:"⚠";position:absolute;top:0;right:2px;background:#b71c1c;color:#fff;border-radius:50%;width:16px;height:16px;font-size:10px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;line-height:1;z-index:5}.fc-view:not(.fc-list) .deadline-overdue.deadline-event{border:2px solid #b71c1c!important;border-radius:2px;padding-bottom:2px;animation:overdueFlash 1.8s ease-in-out infinite!important}.fc-view:not(.fc-list) .deadline-overdue.deadline-event .fc-event-title{color:#b71c1c!important;font-weight:700}.fc-view:not(.fc-list) .deadline-overdue.deadline-event:after{content:"⚠";position:absolute;left:2px;top:.5em;background:#b71c1c;color:#fff;border-radius:50%;width:14px;height:14px;font-size:10px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;line-height:1;z-index:99999}#ccalendar-toolbar{position:relative}#ccalendar-header{box-shadow:0 2px 12px #00000012;position:relative}#ccalendar-header:after{content:"";position:absolute;bottom:0;left:0;right:0;height:2px;background:var(--cc-gradient);opacity:.55;pointer-events:none}#ccalendar-nav .MuiTypography-h6{background:var(--cc-gradient);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;font-weight:700!important}#ccalendar-toolbar .MuiButton-outlined:not([disabled]),#ccalendar-nav .MuiButton-outlined:not([disabled]){border:1.5px solid transparent!important;background:linear-gradient(var(--bg),var(--bg)) padding-box,var(--cc-gradient) border-box!important;transition:box-shadow .15s ease!important}#ccalendar-toolbar .MuiButton-outlined:not([disabled]):hover,#ccalendar-nav .MuiButton-outlined:not([disabled]):hover{background:linear-gradient(var(--fc-today-bg-color),var(--fc-today-bg-color)) padding-box,var(--cc-gradient) border-box!important;box-shadow:0 0 8px 1px var(--cc-glow-purple)!important}.month-day-cell.fc-day-today{background-image:linear-gradient(135deg,#3b82f612,#8b5cf612,#06b6d40d)}.courtdate-event,.adjournment-event,.multipledate-event{border-radius:4px!important;transition:filter .12s ease,box-shadow .12s ease!important}.courtdate-event:hover,.adjournment-event:hover,.multipledate-event:hover{filter:brightness(1.1)!important;box-shadow:0 2px 10px #0000004d!important;z-index:5}#event-tooltip{border:1.5px solid transparent!important;background:linear-gradient(var(--text),var(--text)) padding-box,var(--cc-gradient) border-box!important;box-shadow:0 0 14px 2px #8b5cf638,0 4px 18px #00000047!important;border-radius:10px!important;padding:0!important;font-size:16px!important;font-family:Roboto,Helvetica,Arial,sans-serif!important;min-width:240px!important;max-width:340px!important}#event-tooltip .tt-card{padding:14px 16px}#event-tooltip .tt-title{font-size:17px;font-weight:700;line-height:1.3;margin-bottom:4px}#event-tooltip .tt-date{font-size:15px;opacity:.7;margin-bottom:8px}#event-tooltip .tt-badge{display:inline-block;padding:3px 9px;border-radius:4px;font-size:13px;font-weight:600;letter-spacing:.03em;margin-bottom:8px}#event-tooltip .tt-badge--blue{background:#3b82f659}#event-tooltip .tt-badge--purple{background:#8b5cf659}#event-tooltip .tt-badge--amber{background:#f59e0b59}#event-tooltip .tt-badge--cyan{background:#06b6d459}#event-tooltip .tt-badge--red{background:#dc262659}#event-tooltip .tt-divider{height:1px;background:#80808047;margin:8px 0}#event-tooltip .tt-grid{display:grid;grid-template-columns:auto 1fr;gap:6px 14px;font-size:15px}#event-tooltip .tt-label{opacity:.58;white-space:nowrap;line-height:1.5}#event-tooltip .tt-value{font-weight:500;line-height:1.5}#event-tooltip .tt-value--urgent{color:#ff8a80}#event-tooltip .tt-footer{font-size:13px;opacity:.42;text-align:center;margin-top:8px;padding-top:6px;border-top:1px solid rgba(128,128,128,.22)}#ccalendar-nav .MuiToggleButtonGroup-root .MuiToggleButton-root{color:#1976d2;border:1.5px solid transparent!important;background:linear-gradient(var(--bg),var(--bg)) padding-box,var(--cc-gradient) border-box!important;transition:box-shadow .15s ease!important}#ccalendar-nav .MuiToggleButtonGroup-root .MuiToggleButton-root:hover{color:#1976d2!important;background:linear-gradient(var(--fc-today-bg-color),var(--fc-today-bg-color)) padding-box,var(--cc-gradient) border-box!important;box-shadow:0 0 8px 1px var(--cc-glow-purple)!important}#ccalendar-nav .MuiToggleButtonGroup-root .MuiToggleButton-root.Mui-selected{background:linear-gradient(var(--fc-today-bg-color),var(--fc-today-bg-color)) padding-box,var(--cc-gradient) border-box!important}#ccalendar-nav .MuiToggleButtonGroup-root .MuiToggleButton-root:not(.Mui-selected){color:#4397ecde}#ccalendar-toolbar .MuiToggleButton-root:hover:not(.Mui-selected){background-color:var(--fc-today-bg-color)!important}#ccalendar-toolbar .cc-more-btn-open{border:1.5px solid transparent!important;background:linear-gradient(var(--bg),var(--bg)) padding-box,var(--cc-gradient) border-box!important}.modal-footer .MuiButton-containedPrimary{background-image:var(--cc-gradient)!important;box-shadow:0 0 10px 1px var(--cc-glow-purple),0 2px 6px #0000002e!important;transition:opacity .15s ease,box-shadow .15s ease!important}.modal-footer .MuiButton-containedPrimary:hover:not([disabled]){background-image:var(--cc-gradient)!important;opacity:.9;box-shadow:0 0 16px 2px var(--cc-glow-purple),0 2px 8px #00000038!important}.modal-footer .MuiButton-containedPrimary{text-shadow:0 1px 3px rgba(0,0,0,.35)!important}@page{size:landscape;margin:.5in}@media print{#ccalendar-container>.MuiStack-root:first-child,#event-tooltip,.ReactModal__Overlay,.MuiDataGrid-footerContainer{display:none!important}#ccalendar-container{width:100%!important;overflow:visible!important;padding-top:10px}.fc.fc-media-screen,.fc .fc-scrollgrid,.fc .fc-scrollgrid-section>td,.fc .fc-daygrid-body,.fc table{width:100%!important;max-width:100%!important}.fc .fc-scrollgrid{overflow:visible!important}.fc colgroup col{width:auto!important}.fc-daygrid-day-events{max-height:none!important;min-height:auto!important;overflow:visible!important}.month-day-cell{height:auto!important}.cc-day-chips{display:none!important}#ccalendar-container .MuiDataGrid-root{height:auto!important;max-height:none!important}#ccalendar-container .MuiDataGrid-virtualScroller{overflow:visible!important;height:auto!important}*{-webkit-print-color-adjust:exact!important;print-color-adjust:exact!important}}@keyframes cc-crt-body{0%{transform:translate(0);filter:none;opacity:1}3%{filter:brightness(.85);opacity:.85}6%{filter:none;opacity:1}9%{filter:brightness(1.12);opacity:.75}12%{transform:translate(0);filter:none;opacity:1}15%{transform:translate(0);filter:blur(.5px) hue-rotate(80deg) brightness(.95);opacity:.95}18%{transform:translate(-3px) skew(-1.5deg);filter:blur(1px) hue-rotate(100deg) saturate(1.5);opacity:.9}22%{transform:translate(3px) skew(1.5deg);filter:blur(.5px) hue-rotate(90deg) brightness(1.1);opacity:.95}25%{transform:translate(0);filter:blur(1.5px) hue-rotate(110deg) saturate(1.8);opacity:.85}28%{transform:translate(-5px,1px) skew(-2deg);filter:blur(2px) hue-rotate(130deg) contrast(1.3);opacity:.8}31%{transform:translate(5px,-1px) skew(2deg);filter:blur(1px) hue-rotate(90deg) brightness(1.2);opacity:.88}35%{transform:translate(0);filter:blur(2px) hue-rotate(100deg) saturate(1.2);opacity:.75}38%{transform:translate(-8px,2px) skew(-4deg);filter:blur(3px) hue-rotate(160deg) contrast(1.6);opacity:.6}39%{transform:translate(8px,-2px) skew(4deg);filter:blur(1.5px) hue-rotate(60deg) brightness(1.4);opacity:.75}43%{transform:translate(-2px,1px);filter:blur(3.5px) grayscale(.2) saturate(.8);opacity:.65}47%{filter:blur(2px) brightness(.35);opacity:.18}50%{transform:translate(0);filter:blur(4px) grayscale(.4) contrast(1.4);opacity:.7}53%{transform:translate(-6px,2px) skew(-3deg);filter:blur(3px) grayscale(.3) hue-rotate(180deg);opacity:.55}55%{transform:translate(6px,-2px) skew(3deg);filter:blur(2px) brightness(1.5) contrast(1.8);opacity:.7}58%{transform:translate(0);filter:blur(5px) grayscale(.6) brightness(.6);opacity:.5}60%{filter:blur(4px) brightness(.25);opacity:.12}62%{filter:blur(3px) brightness(1.2);opacity:.6}65%{transform:translate(-10px,3px) skew(-5deg);filter:blur(6px) grayscale(.7) contrast(1.5);opacity:.45}66%{transform:translate(10px,-3px) skew(5deg);filter:blur(3px) grayscale(.5) brightness(1.8);opacity:.6}70%{transform:translate(-4px,2px);filter:blur(7px) grayscale(.8) saturate(.2);opacity:.35}73%{filter:blur(6px) brightness(.18);opacity:.08}75%{transform:translate(0);filter:blur(6px) grayscale(.85) brightness(.5);opacity:.4}78%{transform:translate(-12px,4px) skew(-6deg);filter:blur(8px) grayscale(.9) contrast(2);opacity:.3}79%{transform:translate(12px,-4px) skew(6deg);filter:blur(4px) grayscale(.7) brightness(1.6);opacity:.45}84%{transform:translate(-3px,1px);filter:blur(9px) grayscale(.95) brightness(.35);opacity:.2}88%{filter:blur(8px) brightness(.08);opacity:.04}90%{transform:translate(0);filter:blur(10px) grayscale(1) brightness(.25);opacity:.14}95%{transform:translate(0);filter:blur(12px) grayscale(1) brightness(.1);opacity:.05}to{transform:translate(0);filter:blur(14px) grayscale(1) brightness(0);opacity:0}}@keyframes cc-crt-scanlines{0%{opacity:0;background-position-y:0px}14%{opacity:0;background-position-y:0px}22%{opacity:.28;background-position-y:-4px}42%{opacity:.5;background-position-y:-18px}67%{opacity:.72;background-position-y:-42px}88%{opacity:.88;background-position-y:-66px}to{opacity:1;background-position-y:-84px}}@keyframes cc-crt-vignette{0%{opacity:0}22%{opacity:.25}to{opacity:.88}}.cc-glitch-active{position:relative;animation:cc-crt-body 2s linear forwards;pointer-events:none;overflow:hidden}.cc-glitch-active:before{content:"";position:absolute;inset:0;background:repeating-linear-gradient(to bottom,transparent 0px,transparent 2px,rgba(0,0,0,.1) 2px,rgba(0,0,0,.1) 4px);z-index:9999;pointer-events:none;animation:cc-crt-scanlines 2s linear forwards}.cc-glitch-active:after{content:"";position:absolute;inset:0;background:radial-gradient(ellipse at center,transparent 55%,rgba(0,0,0,.6) 100%);z-index:9998;pointer-events:none;animation:cc-crt-vignette 2s linear forwards}@keyframes cc-humphrey-appear{0%{color:transparent;text-shadow:none;opacity:0;transform:skew(0)}4%{color:red;text-shadow:0 0 30px #ff0000,0 0 60px #ff0000;opacity:.9;transform:skew(-8deg)}6%{color:transparent;text-shadow:none;opacity:0;transform:skew(0)}9%{color:red;text-shadow:0 0 20px #ff0000;opacity:.7;transform:skew(5deg)}11%{color:transparent;text-shadow:none;opacity:0;transform:skew(0)}14%{color:#ff2020;text-shadow:2px 0 0 #ff0000,-2px 0 0 #00ffff;opacity:1;transform:skew(-4deg)}17%{color:#dc143c;text-shadow:0 0 12px #dc143c;opacity:.4;transform:skew(2deg)}20%{color:#ff2020;text-shadow:4px 0 0 #ff0000,-4px 0 0 #00ffff;opacity:1;transform:skew(-6deg)}23%{color:transparent;text-shadow:none;opacity:0;transform:skew(0)}26%{color:#ff2020;text-shadow:0 0 8px #ff0000;opacity:.8;transform:skew(3deg)}30%{color:#ff2020;text-shadow:3px 0 0 #ff0000,-3px 0 0 #00ffff;opacity:1;transform:skew(-3deg)}34%{color:#dc143c;text-shadow:0 0 6px #dc143c,0 0 14px #dc143c50;opacity:.6;transform:skew(0)}38%{color:#ff2020;text-shadow:1px 0 0 #ff0000,-1px 0 0 #00ffff;opacity:1;transform:skew(-2deg)}43%{color:transparent;text-shadow:none;opacity:0;transform:skew(0)}45%{color:#ff1010;text-shadow:0 0 10px #ff0000;opacity:.9;transform:skew(4deg)}48%{color:#dc143c;text-shadow:0 0 4px #dc143c;opacity:.7;transform:skew(-1deg)}53%{color:#ff2020;text-shadow:2px 0 0 #ff0000,-2px 0 0 #00ffff;opacity:1;transform:skew(2deg)}57%{color:#dc143c;text-shadow:0 0 6px #dc143c;opacity:.85;transform:skew(0)}63%{color:transparent;text-shadow:none;opacity:0}65%{color:#dc143c;text-shadow:0 0 8px #dc143c,0 0 18px #dc143c60;opacity:1;transform:skew(-1deg)}72%{color:#dc143c;text-shadow:0 0 3px #dc143c;opacity:.9;transform:skew(0)}78%{opacity:.7}84%{color:#dc143c;text-shadow:0 0 5px #dc143c,0 0 10px #dc143c70;opacity:1}91%{opacity:.85}to{color:#dc143c;text-shadow:0 0 3px #dc143c,0 0 8px #dc143c90;opacity:1;transform:skew(0)}}.cc-humphrey{display:inline-block;animation:cc-humphrey-appear 1.6s steps(1,end) forwards}@keyframes cc-crt-flicker{0%,18%,22%,24%,53%,57%,to{opacity:1}20%,55%{opacity:.91}23%{opacity:.95}56%{opacity:.93}}@keyframes cc-crt-scanroll{0%{background-position-y:0}to{background-position-y:4px}}.cc-crt-ambient{position:relative;overflow:hidden;animation:cc-crt-flicker 7s linear infinite}.cc-crt-ambient:before{content:"";position:absolute;inset:0;background:repeating-linear-gradient(to bottom,transparent 0px,transparent 2px,rgba(0,0,0,.07) 2px,rgba(0,0,0,.07) 4px);pointer-events:none;z-index:9999;animation:cc-crt-scanroll .18s linear infinite}.cc-crt-ambient:after{content:"";position:absolute;inset:0;background:radial-gradient(ellipse at center,transparent 55%,rgba(0,0,0,.42) 100%);pointer-events:none;z-index:9998}.cc-crt-in{position:relative;overflow:hidden;animation:cc-crt-body 2s linear reverse both}.cc-crt-in:before{content:"";position:absolute;inset:0;background:repeating-linear-gradient(to bottom,transparent 0px,transparent 2px,rgba(0,0,0,.1) 2px,rgba(0,0,0,.1) 4px);z-index:9999;pointer-events:none;animation:cc-crt-scanlines 2s linear reverse both}.cc-crt-in:after{content:"";position:absolute;inset:0;background:radial-gradient(ellipse at center,transparent 55%,rgba(0,0,0,.6) 100%);z-index:9998;pointer-events:none;animation:cc-crt-vignette 2s linear reverse both}
@@ -1,6 +1,20 @@
1
- import { DateType, CourtDate, CourtDateDetail, DateEditLog } from '../../types';
1
+ import { DateType, CourtDate, CourtDateDetail, DateEditLog, Notes } from '../../types';
2
2
  export declare function getAllDates(apiKey: string, type?: DateType, dateFrom?: string, dateTo?: string): Promise<Array<CourtDate>>;
3
3
  export declare function updateCourtDate(courtDateId: number, updatedData: Partial<CourtDate>, apiKey: string, courtCases?: string[], user?: number, type?: DateType, skipMotion?: boolean, noticeFiles?: File[]): Promise<boolean>;
4
+ /**
5
+ * Append one note to a court date, negotiation date or collections hearing.
6
+ *
7
+ * Deliberately not routed through `updateCourtDate`'s `notes` field: that endpoint treats the
8
+ * array as a list of notes to *insert*, so sending the existing history back re-inserts all of
9
+ * it. (That is why NotesField has to dedupe by Message before rendering.) This endpoint appends
10
+ * exactly one row to Court.CourtDateNotes and returns its id, so the table view can add a note
11
+ * without first owning the whole list.
12
+ *
13
+ * `userName` is a display name, not a UserID — Court.CourtDateNotes.User is a varchar, and the
14
+ * modal's "which note is mine" matching compares against the same name. `user` is the numeric
15
+ * id, sent only as the audit header.
16
+ */
17
+ export declare function addCourtDateNote(courtDateId: number, message: string, userName: string, apiKey: string, user?: number, type?: DateType): Promise<Notes | null>;
4
18
  export declare function getCourtDate(courtDateId: number, apiKey: string, type?: DateType): Promise<CourtDate | null>;
5
19
  /**
6
20
  * The full GET /court-dates/{id} payload, including the two history fields `getCourtDate`
@@ -1,5 +1,17 @@
1
1
  import { CalendarFilterCtx, Case, NegotiationLog } from '../types';
2
2
  export declare function isCaseSettled(c: Case, isVillage: boolean): boolean;
3
+ /**
4
+ * The case is waiting on a hearing officer's decision.
5
+ *
6
+ * `D` is written by Utility-API's nightly `set_past_cases_to_awaiting_decision` job, which
7
+ * stamps every hearing that has passed with no determination recorded. It is not a settled
8
+ * action, so none of the case-level filters can retire one — hence `showOutForDecision`.
9
+ *
10
+ * Exact equality, deliberately unlike `isCaseSettled`'s substring match: `SD` (settled by
11
+ * decision, the single most common action in the table) contains a `d`, and matching the way
12
+ * `isCaseSettled` does would label every settled-by-decision case as still awaiting one.
13
+ */
14
+ export declare function isCaseOutForDecision(c: Case, isVillage: boolean): boolean;
3
15
  /**
4
16
  * The raw upload fact: this case's evidence is up on NYSCEF. Says nothing about
5
17
  * settlement — use this when settled cases have already been filtered out.
@@ -1,5 +1,20 @@
1
- import { DateType, Case, CourtDate } from '../types';
1
+ import { DateType, HearingType, Case, CourtDate } from '../types';
2
2
  export declare function isVillageDate(muniCode: string): boolean;
3
+ /**
4
+ * The CSS class that paints a hearing type — `.inperson`, `.virtual`, `.unknown` in
5
+ * CalendarEvents.css.
6
+ *
7
+ * Deliberately a lookup and not `hearingType.toLowerCase()`. The enum's *value* for the
8
+ * unknown case is 'Other', which lowercases to a class no rule matches, so every hearing
9
+ * with no Type rendered as a transparent block with a 1px border — invisible against the
10
+ * cell. It went unnoticed because the two states that overpainted the fill (overbooked,
11
+ * adjourned-no-date) were hiding it wherever anyone was likely to look.
12
+ *
13
+ * 'unknown' is the codebase's canonical token for this everywhere else: EVENT_COLORS.unknown,
14
+ * --fc-event-unknown-color, DAY_TYPE_META.unknown, the showUnknown filter. The enum value is
15
+ * the outlier, so the mapping lives here rather than the rules being renamed to match it.
16
+ */
17
+ export declare function hearingTypeClass(hearingType: HearingType | null | undefined): string;
3
18
  /**
4
19
  * Parenthetical muni-code suffix for event labels, e.g. " (3100)". Collections may
5
20
  * have no municipality; for a blank code this returns "" so a label reads as
@@ -33,6 +48,20 @@ export declare function dateKeyOf(dateType: DateType | null | undefined, courtDa
33
48
  * type reads as SCAR — matching how the API omits the field for court dates.
34
49
  */
35
50
  export declare function isScarDate(date: Pick<CourtDate, 'DateType'>): boolean;
51
+ /** The value written to Court.NegotiationDates.Status to retire a negotiation date. */
52
+ export declare const NEGOTIATION_COMPLETE = "Complete";
53
+ /**
54
+ * The negotiation has been marked finished by hand.
55
+ *
56
+ * A negotiation carries no linked cases, so nothing about it can be *derived* as done — the
57
+ * only automatic rule is the date passing. This is the manual counterpart, and it shares the
58
+ * `showPastNegotiations` filter: both mean "this negotiation is over", one by the calendar
59
+ * and one by a person, and the same pill brings both back.
60
+ *
61
+ * The column is free text shared with other writers, so this compares case-insensitively
62
+ * and never assumes it is the only thing that can appear there.
63
+ */
64
+ export declare function isNegotiationComplete(date: Pick<CourtDate, 'DateType' | 'Status'>): boolean;
36
65
  /**
37
66
  * A hearing link safe to hand to window.open, or null.
38
67
  *
@@ -10,23 +10,72 @@ import { CalEvent } from './CalEvent';
10
10
  * and as WeekWidget's eventColor resolves.
11
11
  */
12
12
  export type DayEventType = 'inperson' | 'virtual' | 'unknown' | 'negotiations' | 'collections' | 'upload' | 'motion';
13
+ /** Marker families get an icon rather than a colour — see DAY_TYPE_META. */
14
+ export type MarkerGlyph = 'upload' | 'motion';
15
+ /** How close an upload deadline is to biting. Only ever non-'none' on the upload type. */
16
+ export type UploadUrgency = 'none' | 'dueToday' | 'overdue';
13
17
  export interface DayTypeChip {
14
18
  type: DayEventType;
15
19
  label: string;
16
- color: string;
17
20
  count: number;
21
+ /** 'swatch' → colour square; 'glyph' → icon. Which channel carries this type's identity. */
22
+ mark: 'swatch' | 'glyph';
23
+ /** Set on glyph chips only; the component maps it to an icon. */
24
+ glyph?: MarkerGlyph;
25
+ /**
26
+ * Swatches: the event's own calendar colour. Glyphs: the urgency red once a deadline is
27
+ * biting, else the colour of the hearing behind it — which is what the marker itself is
28
+ * painted in the cell below. Undefined only when a glyph has no source type at all.
29
+ */
30
+ color?: string;
31
+ /**
32
+ * Glyph chips only, and only when a day's markers come from more than one kind of
33
+ * hearing: every contributing colour, in DAY_TYPE_META order. The component fills the
34
+ * icon with a gradient across them.
35
+ *
36
+ * One chip, not one per type. Splitting was tried and read worse than the problem it
37
+ * solved — three "1 Upload" chips in a row are four pixels apart and identical at a
38
+ * glance, so the row looked broken rather than precise.
39
+ */
40
+ colors?: string[];
41
+ /** Glyph chips only: the hearing types behind this marker, for the hover title. */
42
+ sourceTypes?: DayEventType[];
43
+ /** Always 'none' for anything but upload. */
44
+ urgency: UploadUrgency;
18
45
  }
46
+ export type DayTypeMeta = {
47
+ label: string;
48
+ mark: 'swatch';
49
+ color: string;
50
+ } | {
51
+ label: string;
52
+ mark: 'glyph';
53
+ glyph: MarkerGlyph;
54
+ };
19
55
  /**
20
- * Label and swatch colour per type. Declaration order is render order, so the chip row
21
- * reads the same way every day regardless of which types happen to be present.
56
+ * How each type identifies itself. Declaration order is render order, so the chip row reads
57
+ * the same way every day regardless of which types happen to be present.
58
+ *
59
+ * Two channels, because there are two kinds of thing here:
22
60
  *
23
- * Every colour comes from a token — no hex literals here. The repo already carries four
24
- * hand-copied type-to-colour tables that disagree with each other; this is not a fifth.
61
+ * - **Swatch** for the five event types. They earn a colour because the events sitting in
62
+ * the cell below are painted those exact colours, so the association is re-taught every
63
+ * time you look at the calendar. Every value comes from a token — the repo already
64
+ * carries four hand-copied type-to-colour tables that disagree; this is not a fifth.
65
+ * - **Glyph** for the two derived markers. An invented colour for "upload deadline" told
66
+ * nobody anything and collided with the adjourned-no-date magenta at swatch size. The
67
+ * icons instead reuse the ones labelling the toolbar's own "Deadlines" and "Can Preclude"
68
+ * pills, so the meaning is already learned from a row above the calendar.
69
+ *
70
+ * The split carries real information beyond disambiguation: a swatch means an event
71
+ * happens *on this day*, a glyph means a deadline *about a hearing on another day*.
72
+ *
73
+ * The glyph still takes a colour, it just does not get one of its own: it borrows the
74
+ * hearing type of the date it is about, which is exactly what the marker itself is painted
75
+ * with in the cell below (`.deadline-event.inperson` et al in CalendarEvents.css). So the
76
+ * icon says which kind of marker and the colour says which kind of hearing — see glyphColor.
25
77
  */
26
- export declare const DAY_TYPE_META: Record<DayEventType, {
27
- label: string;
28
- color: string;
29
- }>;
78
+ export declare const DAY_TYPE_META: Record<DayEventType, DayTypeMeta>;
30
79
  /**
31
80
  * Which chip a hearing occurrence belongs to.
32
81
  *
@@ -38,6 +87,14 @@ export interface DayTypeEntry {
38
87
  /** 'YYYY-MM-DD', from dateToKey. */
39
88
  dayKey: string;
40
89
  type: DayEventType;
90
+ /** Upload entries only. Defaults to 'none'. */
91
+ urgency?: UploadUrgency;
92
+ /**
93
+ * Glyph entries only: the chip type of the hearing this marker is *about* — the same
94
+ * value hearingChipType gives that hearing — so the glyph can be painted the colour
95
+ * the marker itself carries in the cell below.
96
+ */
97
+ sourceType?: DayEventType;
41
98
  }
42
99
  /**
43
100
  * Groups entries into per-day chip lists.
@@ -46,8 +46,6 @@ export interface EventTitleOptions {
46
46
  caseCount?: number;
47
47
  /** Leading verb for derived events, e.g. 'Upload' or 'Can Preclude'. */
48
48
  prefix?: string;
49
- /** This occurrence sits past the day's SCAR limit — see helpers/dayLoad.ts. */
50
- overbooked?: boolean;
51
49
  }
52
50
  /**
53
51
  * The FullCalendar event title.
@@ -3,12 +3,14 @@ import { CalEvent } from './CalEvent';
3
3
  /**
4
4
  * Filters the full CourtDate list down to dates that pass every active filter
5
5
  * dimension: search, hearing type, chair assignment, muni, case-level flags,
6
- * and date type.
6
+ * date recency, and date type.
7
7
  *
8
8
  * searchedDateIDs: null = search results still loading (show all dates),
9
9
  * Set = results received; empty set means 0 matches.
10
+ * today: injectable clock, so the recency rule is testable without faking the
11
+ * system time (same pattern as resolveMotionWindow).
10
12
  */
11
- export declare function filterCourtDates(courtDates: CourtDate[], filterCtx: CalendarFilterCtx, allCases: Record<string, Case[]>, searchedDateIDs: Set<number> | null): CourtDate[];
13
+ export declare function filterCourtDates(courtDates: CourtDate[], filterCtx: CalendarFilterCtx, allCases: Record<string, Case[]>, searchedDateIDs: Set<number> | null, today?: Date): CourtDate[];
12
14
  /**
13
15
  * Filters the CalEvent list for the sidebar / case modal: respects
14
16
  * showAdjournmentDates and case-level filters (unsettled, evidence, unreviewed).
@@ -30,6 +30,15 @@ export interface MotionWindow {
30
30
  * is day-granular, so one bad parse is a whole day of wrong answer.
31
31
  */
32
32
  export declare function startOfDay(value: Date | string | null | undefined): Date | null;
33
+ /**
34
+ * The last day a court date is actually scheduled for: its `CourtDate`, or the final entry
35
+ * of `MultipleDates` when the hearing runs over several days. Day-granular, local midnight.
36
+ * Adjournments are *not* considered — this is the scheduled span, not the effective one.
37
+ *
38
+ * Shared with filterCourtDates' past-negotiation rule, because "has this date happened yet"
39
+ * has to mean the same thing in both places: a two-day hearing is not over on its first day.
40
+ */
41
+ export declare function lastScheduledDay(courtDate: Pick<CourtDate, 'CourtDate' | 'MultipleDates'> | null | undefined): Date | null;
33
42
  /**
34
43
  * Resolves the Motion to Preclude upload window for a court date.
35
44
  *
@@ -1,6 +1,6 @@
1
1
  import { DateType, CalendarFilterCtx, CalendarRouteParams } from '../types';
2
2
  import { DEFAULT_FILTER_CTX } from '../constants';
3
- export declare const CALENDAR_PARAM_KEYS: readonly ["view", "date", "cdId", "cdType", "ci", "ht", "user", "dl", "md", "adj", "done", "dt", "muni", "settled", "noEvid", "unrev", "q"];
3
+ export declare const CALENDAR_PARAM_KEYS: readonly ["view", "date", "cdId", "cdType", "ci", "ht", "user", "dl", "md", "adj", "done", "pastNeg", "ofd", "dt", "muni", "settled", "noEvid", "unrev", "q"];
4
4
  export declare function serializeCalendarParams(params: CalendarRouteParams): URLSearchParams;
5
5
  export declare function parseCalendarSearchParams(params: URLSearchParams | Record<string, string | undefined>): CalendarRouteParams;
6
6
  export declare function buildCalendarRouteParams(view: string, date: Date, courtDateId: number | null, caseIdx: string | null, filterCtx: CalendarFilterCtx, courtDateType?: DateType | null): CalendarRouteParams;
@@ -1,32 +1,6 @@
1
1
  import { Case, CourtDate, CalendarFilterCtx } from '../types';
2
2
  import { CalEvent } from '../helpers/CalEvent';
3
3
  import { EventSourceInput, EventMountArg, Calendar } from '@fullcalendar/core/index.js';
4
- /**
5
- * Derives FullCalendar event objects from court dates, cases, and filter state.
6
- *
7
- * Responsibilities:
8
- * - Runs async case-term searches and accumulates matching court date IDs.
9
- * - Filters `courtDates` according to every dimension in `filterCtx`
10
- * (hearing type, assignment, muni, unsettled/no-evidence/unreviewed, search term).
11
- * - Calls `buildCalEvents` to produce one `CalEvent` per visual occurrence
12
- * (original, extra-day, and adjournment events — bucketing/suppression lives there).
13
- * - Maps each `CalEvent` to a FullCalendar event object.
14
- * - Suppresses event updates while the modal is open to avoid UI churn.
15
- * - Applies a staggered `pop-in` CSS animation to newly-appearing events via
16
- * `handleEventMount`, and attaches HTML tooltip content to each event element.
17
- *
18
- * @param courtDates Full list of court dates to derive events from.
19
- * @param allCases Map of `CourtDateID → Case[]` for filtering and case counts.
20
- * @param apiKey API key forwarded to the search helper.
21
- * @param modalIsOpen When `true`, event state updates are paused.
22
- * @param filterCtx Active filter/search context from the calendar UI.
23
- *
24
- * @returns
25
- * - `events` – current FullCalendar `EventSourceInput` array.
26
- * - `filteredDates` – `CalEvent[]` that survive all active filters.
27
- * - `eventHash` – JSON hash of `events`; changes whenever the event list changes.
28
- * - `handleEventMount` – callback to pass to FullCalendar's `eventDidMount` prop.
29
- */
30
4
  export declare function useCalendarEvents({ courtDates, allCases, apiKey, modalIsOpen, filterCtx, }: {
31
5
  courtDates: CourtDate[];
32
6
  allCases: Record<string, Case[]>;
@@ -36,6 +36,7 @@ export declare function useModalActions({ modalMode, selectedCourtDate, selected
36
36
  handleSave: () => Promise<boolean>;
37
37
  handleDelete: () => Promise<boolean>;
38
38
  handleViewUpdateChair: (position: "first" | "second", userId: number | null) => void;
39
+ handleToggleNegotiationComplete: (complete: boolean) => void;
39
40
  handleSelectedCasesAdjournmentChange: (casesToUpdate: Case[], date: Date | null) => Promise<boolean>;
40
41
  handleSelectedCasesClearDetermination: (casesToUpdate: Case[]) => Promise<boolean>;
41
42
  };