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

/* No own max-width/margin/padding here - body already provides those
   (styles.css) and #main-view (list view) relies on the same, unset,
   inheritance rather than redeclaring them. #month-view redeclaring its
   own padding used to stack on top of body's, nudging its header out of
   alignment with list view's. */

/* Exact same grid as styles.css's #main-view header - duplicated here
   rather than shared, since it's scoped to #main-view specifically.
   .header-top-row itself (display:contents) is a plain, unscoped class
   already defined once in styles.css and works here unchanged. */
#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
   styles.css's #main-view header::after (see that rule's comment). */
#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 styles.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 (see
   styles.css's own comment on why that page gets its own bounded scroll
   box) - #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. */
#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 admin's schedule colgroup widths and public's
   own .mobile-schedule font-size. 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, since nothing here can render/inspect it. */
  --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;
}

.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/cards (app.js sets
   an identical class + --custom-row-color/--custom-row-fg pair) - 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, styles.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 - it's now
   an in-flow "card" that lives in the static header area above the
   weekday row/toolbar/grid, always in view the instant it opens, no
   backdrop needed. Same field grid (.detail-grid, defined once in
   styles.css) as before, just read-only here (this page has no editing
   at all) - admin/month.css's own .event-panel has the editable
   equivalent. */
.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 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;
}

/* ---- 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;
  }
}
