/* ---- Header / toolbar ---- */

/* No own max-width/margin/padding here - body already provides those
   (styles.css) and stacking a second padding on top of body's own nudged
   this header out of alignment with the public month view's (same fix
   already applied there - see public/month.css's identical comment). */

/* Same grid technique as public/month.css's #month-view header (see that
   rule's own comment) - duplicated here rather than shared, since it's
   scoped to this page's own #month-view. */
#month-view header {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  grid-template-areas:
    ". title account"
    "filterbar filterbar filterbar";
  align-items: center;
  column-gap: 0.6rem;
  row-gap: 0.6rem;
  margin-bottom: 1rem;
  padding-bottom: 0.75rem;
}

/* Full-bleed divider line under the header - same technique as
   public/month.css's own #month-view header::after. */
#month-view header::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 100vw;
  transform: translateX(-50%);
  border-bottom: 1px solid var(--border);
}

/* Centered independently of both the (empty) first column and account-
   controls - see styles.css's identical #main-view rule for the full
   comment. */
#month-view header h1 {
  grid-area: title;
  justify-self: center;
  font-size: 1.15rem;
}

#month-view header .filter-bar {
  grid-area: filterbar;
  margin-bottom: 0;
}

#month-view header .account-controls {
  grid-area: account;
  justify-self: end;
}

/* .view-toggle / .header-btn-active are defined in admin.css (also loaded
   by this page), shared with index.html's identical toggle - not
   duplicated here. */

/* Just prev/next/vandaag now - no separate month/year title text here
   anymore (removed .month-title and updateTitleFromScroll() in month.js)
   since .month-block-label further down already shows the current
   month's name, sticky right under the weekday row - a second copy here
   was redundant and cost a whole row of vertical space for no benefit. */
.month-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin-bottom: 1rem;
}

/* ---- Continuous month scroll ----
   Same #main-view/.table-scroll pattern the list view uses - #month-view
   is a column flexbox filling the viewport so .month-scroll can
   flex-grow to reach the bottom edge, and everything above it (header,
   filter-bar, toolbar) stays outside the scrolling area, so it never
   scrolls away and needs no sticky positioning of its own. A whole-page-
   scroll version (letting the cursor scroll from anywhere, not just over
   the calendar) was tried here for a while, but the sticky header/
   toolbar/weekday/month-label stack it required kept causing new
   problems (a header that shifted or left a gap depending on the fix,
   prev/next silently landing on the wrong month, months short enough to
   be entirely swallowed by the sticky stack) for a benefit that didn't
   end up being worth that cost - reverted back to this simpler, more
   reliable setup (see public/month.css's identical comment). */
#month-view {
  display: flex;
  flex-direction: column;
  height: calc(100vh - 1.5rem);
  height: calc(100dvh - 1.5rem);
}

/* Full-bleed to the viewport's actual width (desktop only, see the media
   query further down) is applied here on wider screens - not just body's
   own (max-width:1100px, centered) content column - so the mouse can
   scroll the calendar from the empty side margins on a wide window too,
   not only while directly over the grid. width:100vw specifically (not
   100% or a JS-measured width) turned out to be unreliable on mobile
   Safari - it can measure slightly wider than the true visible viewport
   there (a known quirk, related to how iOS handles the dynamic toolbar/
   safe-area), which was producing a small but real horizontal scroll
   range on an iPhone 13 mini that a vertical swipe could accidentally
   trigger, panning the grid sideways out of alignment with its own
   sticky weekday header. Mobile has little to no visible side-margin to
   begin with, so it just keeps the original, simpler non-full-bleed
   sizing instead - this narrower desktop-only fix is a smaller change
   than the earlier whole-page-scroll experiment above either way:
   nothing about the sticky-header/label/prev-next architecture changes
   at all, only .month-scroll's own *hit area* on wide screens. */
.month-scroll {
  overflow: auto;
  flex: 1;
  min-height: 0;
  /* Own compositing layer - confirmed via diagnostic that the target
     month's grid has fully correct layout (right size, right position)
     after a JS-triggered scrollBy() lands on it, but Safari sometimes
     fails to *paint* that newly-revealed region until something else
     forces a repaint (e.g. the user scrolling by hand) - a known
     WebKit quirk with position:sticky descendants inside a
     programmatically-scrolled container. will-change:transform on the
     sticky label alone (used elsewhere in this app for a related
     quirk) wasn't enough here; forcing the whole scrollable area onto
     its own layer is. */
  will-change: transform;
}

/* ---- Grid ----
   Same --zoom mechanism as the list view's text-size buttons (see
   month.js's applyZoom) - every size below that matters for "the whole
   calendar reads bigger/smaller" is scaled from it directly, the same
   pattern already used for this table's own colgroup widths. Base values
   (at zoom=1) bumped up from the original pass so the calendar reads
   larger by default, independent of the zoom controls. */

/* Sticky at the very top, above the weekday row - shows the currently-
   scrolled month's name (updateTitleFromScroll() in month.js) plus the
   prev/next/vandaag buttons, right-aligned. Since this now owns the
   "always-visible current month name" job, .month-block-label further
   down goes back to plain in-flow text (not sticky) - showing it twice,
   stacked in adjacent sticky rows while scrolling, would just be double
   naming again. */
.month-title-bar {
  position: sticky;
  /* -1px instead of 0: same fix as styles.css's own thead th - avoids a
     hairline gap of scrolled-past content showing above a sticky element
     pinned at exactly top:0. */
  top: -1px;
  z-index: 3;
  /* 1.8rem for the title/buttons themselves (unchanged) + 0.4rem visible
     margin below them before .month-grid-weekdays starts - a fixed total
     height, not just padding-bottom tacked onto the old 1.8rem, since
     box-sizing:border-box would otherwise shrink the content area by
     that same 0.4rem instead of adding visible space below it. */
  height: calc(1.8rem + 0.4rem);
  padding-bottom: 0.4rem;
  display: flex;
  /* flex-end, not center - .month-title and .month-nav (the buttons)
     aren't the same rendered height (the buttons' own padding/border
     make them taller than the title's plain text), so centering them
     within this fixed-height row gave them different-sized gaps to
     .month-grid-weekdays below. Bottom-aligning both (against the
     padding-bottom above, not the box's own edge) makes that gap equal
     for each, regardless of their own height difference. */
  align-items: flex-end;
  gap: 0.5rem;
  background: var(--bg);
}

.month-title {
  margin: 0;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: calc(1.05rem * var(--zoom, 1));
  font-weight: 700;
  letter-spacing: 0.03em;
}

.month-nav {
  display: flex;
  gap: 0.3rem;
  flex-shrink: 0;
}

/* height is fixed (not zoom-scaled) so .month-title-bar above and
   .month-block-label below both have a deterministic offset to stick
   to/underneath - same tradeoff styles.css's thead th makes for
   tr.month-header-row's own offset (fixed height regardless of zoomed
   font-size, rather than measuring it in JS, which that rule's own
   comment notes was unreliable). top is .month-title-bar's own height
   (now 1.8rem + 0.4rem margin, see that rule's own comment) minus 1px,
   not the plain height - same calc(2rem - 1px) compensation styles.css's
   tr.month-header-row makes for thead th's own -1px (see
   .month-title-bar's comment): without it, this row sticks 1px too low,
   leaving a hairline gap above it that scrolled-past content peeks
   through, the same bug -1px itself exists to fix. */
/* padding-left/right: 1px - .month-grid further down has its own 1px
   border on each side (border-box, so it eats into its content width,
   not added on top), making its 7 columns 2px narrower overall than
   this row's would otherwise be with no border of its own. Matches that
   inset here so both sets of 7 columns end up exactly the same width,
   keeping the weekday letters aligned with their date columns below. */
.month-grid-weekdays {
  position: sticky;
  top: calc(1.8rem + 0.4rem - 1px);
  z-index: 2;
  height: 1.8rem;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  align-items: center;
  padding-left: 1px;
  padding-right: 1px;
  font-size: calc(0.8rem * var(--zoom, 1));
  text-transform: uppercase;
  text-align: center;
  background: var(--header-bg);
  border-radius: 6px;
}

/* Desktop-only full-bleed setup (see .month-scroll's own comment above
   for why mobile is excluded) - .month-scroll spans the true viewport
   width so the mouse can scroll it from the side margins too, and these
   three re-apply body's own max-width/margin/padding so the visible
   content still lines up under the header exactly as it would without
   the full-bleed change. */
@media (min-width: 701px) {
  .month-scroll {
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
  }

  .month-title-bar,
  .month-grid-weekdays,
  #month-list {
    max-width: 1100px;
    margin-left: auto;
    margin-right: auto;
    padding-left: 0.75rem;
    padding-right: 0.75rem;
  }
}

/* opacity lives on the labels themselves, not the row - opacity on the
   row would also fade its own background, letting scrolled-past days
   show through the sticky row instead of sitting fully opaque behind it. */
.month-grid-weekdays span {
  opacity: 0.6;
}

/* Every month's own label scrolls out of view behind the sticky title
   bar/weekday row once you've scrolled into it (see scrollToMonth's own
   comment, month.js) - except the very first month in the whole range,
   which has nowhere further up to scroll to: scrollTop can't go negative,
   so at the natural scroll-up limit its label would otherwise sit right
   below the sticky stack, duplicating the title bar's text. Pulling just
   the first month's block up by its label's own rendered height
   (padding-top:0.4rem*2 + line-height:1.2 * font-size:1.05rem*zoom, see
   .month-block-label further down) tucks that label behind the sticky
   stack even at scrollTop:0, so the natural top-of-scroll already looks
   like every other month once you've scrolled past its label. A calc()
   here instead of measuring the label in JS once at render time
   specifically so it stays correct after a zoom change too, without
   needing a re-render to recompute it. */
#month-list > .month-block:first-child {
  margin-top: calc(-1 * (0.8rem + 1.26rem * var(--zoom, 1)));
}

.month-block {
  padding-bottom: 1.5rem;
}

/* Not sticky - .month-title-bar above already shows the currently-
   scrolled month's name at all times, so a second copy pinned here too
   would be double naming. Plain in-flow text, scrolls away with the
   rest of its month like the day grid does. line-height is set
   explicitly (not left to the browser default, which varies by font/
   platform) so the first month-block's negative margin-top further up
   can predict this label's exact rendered height via the same calc(). */
.month-block-label {
  margin: 0;
  padding: 0.4rem 0;
  font-size: calc(1.05rem * var(--zoom, 1));
  line-height: 1.2;
  font-weight: 700;
  letter-spacing: 0.03em;
  background: var(--bg);
}

.month-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  /* Shared with month.js's bar-overlay math (monthBarHtml/dayCellHtml) - a
     .month-bar overlays a week's day cells rather than living inside one
     (it needs to span several columns' width), so it can't just inherit
     .month-day's own padding/day-num layout the normal way a real child
     would. These are the single source of truth both sides read from
     instead of two independently hardcoded numbers that could drift
     apart - if .month-day's padding or .month-day-num's height below
     ever change, update --month-bars-top to match, or bars will visibly
     drift from "right under the date number". --month-bar-slot (one
     bar's rendered height + gap to the next) is an estimate, not
     measured - it may need a small manual nudge once actually seen
     rendered. */
  --month-day-pad: calc(0.4rem * var(--zoom, 1));
  --month-bars-top: calc(var(--month-day-pad) + 1.8rem * var(--zoom, 1) + 0.25rem);
  --month-bar-slot: calc(1.1rem * var(--zoom, 1));
}

/* min-width:0 overrides the default min-width:auto every grid item gets -
   without it, a long unwrapped chip title's own intrinsic content width
   becomes a floor on this cell's grid track, so a day with a long title
   ends up visibly wider than its neighbors even though the grid asks for
   7 equal (1fr) columns. With it, the track sizes actually stay equal and
   .month-chip's own overflow:hidden/text-overflow:ellipsis (below) can
   truncate long titles instead of forcing the column wider. */
.month-day {
  background: var(--bg);
  min-height: calc(6rem * var(--zoom, 1));
  min-width: 0;
  padding: var(--month-day-pad);
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

/* Leading/trailing days from the adjacent months - shown dimmed so the
   grid always has complete weeks, never a ragged first/last row. */
.month-day-outside {
  background: var(--detail-bg);
  opacity: 0.5;
}

.month-day-num {
  font-size: calc(0.9rem * var(--zoom, 1));
  width: calc(1.8rem * var(--zoom, 1));
  height: calc(1.8rem * var(--zoom, 1));
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.month-day-today .month-day-num {
  background: var(--accent);
  color: #fff;
  border-radius: 50%;
}

.month-day-chips {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  overflow: hidden;
  /* Same reasoning as .month-day's own min-width:0 above - this is a flex
     item within .month-day's column layout, so it needs the same
     override to stop a long chip title's intrinsic width from pushing
     its own box (and therefore .month-day's) wider than its siblings. */
  min-width: 0;
}

/* Every chip is a <button> (opens the event panel, see .month-chip-more's
   own already-working precedent below) - border/font/text-align/cursor
   reset the default button chrome a <button> would otherwise pick up. */
.month-chip {
  display: block;
  width: 100%;
  min-width: 0;
  border: none;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
  font-size: calc(0.78rem * var(--zoom, 1));
  padding: calc(0.15rem * var(--zoom, 1)) calc(0.35rem * var(--zoom, 1));
  border-radius: 4px;
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: inherit;
}

/* Hidden (soft-hidden via "Verbergen") events still show, dimmed - same
   convention as tr.row-hidden-event in the list view - so nothing
   silently disappears from the calendar for admins. */
.month-chip-hidden {
  opacity: 0.5;
}

.month-chip-more {
  border: none;
  font: inherit;
  font-size: 0.65rem;
  background: none;
  color: var(--accent);
  text-align: left;
  cursor: pointer;
  padding: 0.1rem 0.3rem;
}

/* Same production-color system as the list view's rows (admin.js sets an
   identical class + --custom-row-color/--custom-row-fg pair on tr.event-
   row) - reused as-is here so a production's color reads identically in
   both views. */
.month-chip.row-thuis { background: var(--thuis); }
.month-chip.row-mijnkleuren { background: var(--mijnkleuren); }
.month-chip.row-geel { background: var(--geel); }
.month-chip.row-oma { background: var(--oma); }
.month-chip.row-abrikoos { background: var(--abrikoos); }
.month-chip.row-other { background: var(--other); }
.month-chip.row-hotel { background: var(--hotel); }
.month-chip.row-appointment { background: var(--appointment); }
.month-chip.row-blokkade { background: var(--blokkade); }
.month-chip.row-blokkade-conflict { background: var(--blokkade-conflict); }
.month-chip.row-custom { background: var(--custom-row-color); color: var(--custom-row-fg, inherit); }

/* Same "this involves you" cue as the list view's own .row-mine (see that
   rule's own comment, admin.css) - a slightly thicker, accent-colored
   left border, independent of the chip's own row-color background.
   Padding-left compensates for the extra border width so the label text
   doesn't shift/crowd against it (chips have no sticky-column concern
   like the list view's table, so a plain border here is fine). */
.month-chip-mine {
  border-left: 3px solid var(--accent);
  padding-left: calc(0.35rem * var(--zoom, 1) - 2px);
}

/* Highlights whichever chip/bar the currently-open event panel belongs to
   (openEventUid in month.js, re-applied after every re-render) - an
   inset ring rather than another border side, so it can't collide with
   .month-chip-mine's own left border on a chip that's both "yours" and
   currently open. */
.month-chip-open {
  box-shadow: inset 0 0 0 2px var(--accent);
}

/* A multi-day span's bar (see month.js's monthBarHtml/computeWeekSegments) -
   overlaid on top of the day cells it spans (shares their grid-row,
   .month-grid) rather than living inside just one of them, since it needs
   to cover several columns' width at once. align-self:start (not stretch)
   so it only takes its own natural height instead of filling the whole
   row, positioned via the margin-top set inline (JS) using .month-grid's
   --month-bars-top/--month-bar-slot custom properties - lands right under
   the date number the same way dayCellHtml's chips-area offset does,
   both reading the same source-of-truth values (see .month-grid's own
   comment). The left/right inset matches .month-day's own padding so its
   edges align with the date numbers/chips above and below it instead of
   sitting flush against the grid lines. */
.month-bar {
  /* .month-chip's own width:100% resolves against the full grid area
     (before margins), not "grid area minus margins" the way a stretched
     item with the default width:auto would - so with a fixed 100% width,
     the margin-left/right below just added on top of that instead of
     sharing the space, pushing the bar past the grid's right edge
     (visibly, in a real render - not something the calc() math above
     alone could have caught). width:auto restores the normal
     stretch-minus-margins sizing. */
  width: auto;
  align-self: start;
  margin-left: var(--month-day-pad);
  margin-right: var(--month-day-pad);
  font-weight: 600;
  /* Smaller/shorter than a regular .month-chip - a bar spans several days
     at once, so it reads fine (still bold, still colored) even at a more
     compact size, and shrinking it leaves more of the day cell free for
     its own single-day chips below. Font-size only nudged down a little
     (not dropped further) so the label stays legible; --month-bar-slot
     above (.month-grid) is shrunk to match this shorter rendered height. */
  font-size: calc(0.65rem * var(--zoom, 1));
  padding-top: calc(0.08rem * var(--zoom, 1));
  padding-bottom: calc(0.08rem * var(--zoom, 1));
}

/* Squares off whichever edge is a mid-span continuation (this bar
   segment isn't the event's real start/end, just where the grid clipped
   it - at a week boundary, or the edge of the currently-rendered month)
   rather than rounding it like a genuine start/end, so a span that wraps
   across weeks/months reads as one continuous thing, not a new bar each
   time. */
.month-bar.month-bar-continues-before {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  margin-left: 0;
}

.month-bar.month-bar-continues-after {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  margin-right: 0;
}

/* ---- Day popover (the "+N meer" overflow trigger, and tapping an empty
   part of a day cell on mobile) ---- */

.day-popover-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.35);
  z-index: 30;
}

.day-popover {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 31;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
  width: min(320px, 90vw);
  max-height: 70vh;
  overflow-y: auto;
  padding: 0.75rem;
}

.day-popover-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-weight: 700;
  margin-bottom: 0.5rem;
}

.day-popover-list {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.day-popover-list .month-chip {
  font-size: 0.85rem;
  padding: 0.4rem 0.5rem;
  white-space: normal;
}

/* ---- Event detail panel - opened by clicking any chip (in the grid or
   inside the day-popover above). No longer a floating modal - same
   in-flow "card" treatment as .add-row-form (admin.css), living in the
   static header area above the weekday row/toolbar/grid so it's always
   in view the instant it opens, never needing its own backdrop or
   fixed-centered positioning. Its own max-height/overflow-y is a safety
   cap .add-row-form doesn't need - unlike that fixed-shape form, this
   panel's field count and Notitie textarea can genuinely grow tall
   enough to crowd out the calendar below it otherwise. */
.event-panel {
  position: relative;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  max-height: 45vh;
  overflow-y: auto;
  padding: 0.75rem 1rem;
  margin-bottom: 1rem;
}

.event-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  font-weight: 700;
  margin-bottom: 0.5rem;
}

.event-panel-nav {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-shrink: 0;
}

/* First disabled-button case in either page - .header-btn had no such
   state before. Used at the first/last event in the currently filtered,
   date-sorted list (see visibleEventsSorted, month.js), where there's
   nowhere further to step to. */
.header-btn:disabled {
  opacity: 0.35;
  cursor: default;
}

/* "13 sep 2026" part of the title ("Mijn Kleuren - 13 sep 2026") - a bit
   smaller and lighter than the production name it follows, same weight
   distinction as a lot of this app's other title/subtitle pairs. */
.event-panel-title-date {
  font-size: 0.85em;
  font-weight: 400;
  opacity: 0.8;
}

/* Same spacing as public/app.js's own compact mobile detail card's
   identical note-below-the-columns layout (.mobile-card-detail
   .detail-note-full, styles.css) - that rule is scoped to a class this
   panel doesn't have, so it needs its own copy here. */
#event-panel-grid .detail-note-full {
  margin-top: 0.4rem;
}

.event-panel-date-edit {
  margin-bottom: 0.6rem;
}

/* Same reasoning as admin.css's identical tr.row-appointment override -
   an Event row's Titel is stored the same "derived from summary" way
   every manual row's name is, so it renders through the placeholder
   slot by default, picking up the general italic/hint styling. Tied
   specificity with admin.css's own .detail-edit-grid rule is enough to
   win here (month.css loads after admin.css), no #id padding needed. */
.field-titel input::placeholder {
  font-style: normal;
}

/* admin.css's own .visibility-select-list is z-index:20, fine in the list
   view (nothing else there goes above it) - but here it can be opened
   from inside .event-panel, and needs to render above .day-popover
   (z-index:31 further up) once portaled to document.body (see
   openVisibilitySelectList in month.js) in case both happen to be open
   at once. */
.visibility-select-list {
  z-index: 32;
}

.event-panel-footer {
  margin-top: 0.75rem;
  display: flex;
  justify-content: flex-end;
  gap: 0.6rem;
}

/* ---- Mobile ---- */

@media (max-width: 700px) {
  /* Left-align the title here too - same technique as the 480px block
     below (that one still applies underneath this one at any width below
     480px too, since both target the same rule; the narrower media query
     just wins on cascade order, not that anything conflicts). */
  #month-view header {
    grid-template-columns: auto 1fr auto;
    grid-template-areas:
      "title . account"
      "filterbar filterbar filterbar";
  }

  #month-view header h1 {
    justify-self: start;
  }

  .month-grid {
    /* .month-day's own padding below is a flat 0.25rem here, not the
       calc(0.4rem*zoom) the base --month-day-pad assumes - without
       redefining it too, .month-bar's margin/offset math (both read
       --month-day-pad, .month-grid's own comment) would stay based on
       the desktop padding value and drift out of alignment at this
       width. */
    --month-day-pad: 0.25rem;
    --month-bars-top: calc(var(--month-day-pad) + 1.8rem * var(--zoom, 1) + 0.25rem);
    --month-bar-slot: 0.85rem;
  }

  .month-day {
    min-height: 4.5rem;
    padding: 0.25rem;
  }

  .month-chip {
    font-size: 0.68rem;
  }

  .month-bar {
    font-size: 0.58rem;
    padding-top: 0.05rem;
    padding-bottom: 0.05rem;
  }
}

@media (max-width: 480px) {
  /* Left-align the title at the narrowest width - see styles.css's
     identical #main-view rule (same breakpoint) for the full reasoning;
     duplicated here since #month-view has its own copy of the base header
     grid. */
  #month-view header {
    grid-template-columns: auto 1fr auto;
    grid-template-areas:
      "title . account"
      "filterbar filterbar filterbar";
  }

  #month-view header h1 {
    justify-self: start;
  }
}
