*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --header-h: 56px;
  --time-col-w: 52px;
  --slot-h: 30px;       /* height per 30-min slot */
  --hour-start: 8;
  --hour-end: 24;
  --accent: #1a56a0;
  --booking-bg: #2563eb;
  --booking-text: #fff;
  --grid-line: #e2e8f0;
  --header-bg: #1e293b;
  --header-text: #f1f5f9;
  --past-bg: #f1f5f9;
  --past-text: #94a3b8;
}

body {
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 14px;
  background: #f8fafc;
  color: #1e293b;
  height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* ── Header ── */
header {
  background: var(--header-bg);
  color: var(--header-text);
  height: var(--header-h);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  padding: 0 1rem;
}
.header-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1.5rem;
  width: 100%;
}
h1 { font-size: 1.1rem; font-weight: 600; white-space: nowrap; }

/* #chrome (refresh/view-toggle/date-nav) never actually shrinks below its
   own content's natural width - none of its buttons wrap or truncate. The
   old `min-width: 0` here let flexbox squeeze #chrome's outer box smaller
   than that content anyway (that's what min-width: 0 is *for* - it's the
   standard trick to let a flex item shrink for text-overflow: ellipsis)
   without anything inside #chrome actually shrinking or wrapping to match -
   so the content just overflowed #chrome's too-small box, unclipped,
   straight into #auth-box sitting right after it. That's what "the user's
   name box overlaps Today" actually was, and it's why flex-wrap: wrap above
   didn't help on its own: flexbox's line-wrapping only looks at whether the
   *outer* boxes fit, and #chrome's outer box was lying about how much room
   it needed. Removing min-width: 0 makes #chrome report its true minimum
   width, so if it doesn't fit alongside h1 and #auth-box, flex-wrap now
   correctly wraps it to its own line instead of letting it overflow. */
#chrome {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex: 1;
}

#auth-box {
  margin-left: auto;
  flex-shrink: 0;
  display: flex;
  align-items: center;
}
.btn-login {
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.2);
  color: var(--header-text);
  border-radius: 4px;
  cursor: pointer;
  padding: 0 0.8rem;
  height: 32px;
  display: flex;
  align-items: center;
  text-decoration: none;
  font-family: inherit;
  font-size: 0.9rem;
  transition: background 0.15s;
}
.btn-login:hover { background: rgba(255,255,255,0.2); }

.user-menu-wrap { display: contents; }
.menu-caret { margin-left: 0.5rem; font-size: 0.7rem; opacity: 0.7; }

#user-menu-popup {
  position: fixed;
  background: #1e293b;
  border: 1px solid rgba(255,255,255,0.15);
  border-radius: 8px;
  padding: 0.35rem;
  z-index: 100;
  min-width: 140px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.4);
}
#user-menu-popup a {
  display: block;
  padding: 0.5rem 0.6rem;
  border-radius: 4px;
  color: var(--header-text);
  text-decoration: none;
  font-size: 0.85rem;
}
#user-menu-popup a:hover { background: rgba(255,255,255,0.1); }

.login-prompt {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: #64748b;
  font-size: 0.95rem;
}
.login-prompt a { color: #2563eb; text-decoration: none; font-weight: 600; }
.login-prompt a:hover { text-decoration: underline; }

#btn-refresh {
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.2);
  color: var(--header-text);
  border-radius: 4px;
  cursor: pointer;
  padding: 0 0.5rem;
  height: 32px;
  display: flex;
  align-items: center;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
  flex-shrink: 0;
}
#btn-refresh:hover:not(:disabled) { background: rgba(255,255,255,0.2); }
#btn-refresh:disabled { cursor: default; opacity: 0.6; }
#btn-refresh.rate-limited {
  background: rgba(234,179,8,0.25);
  border-color: rgba(234,179,8,0.6);
  color: #fde047;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}
#btn-refresh.loading #refresh-icon {
  animation: spin 0.9s linear infinite;
}

.view-toggle {
  display: flex;
  gap: 2px;
  background: rgba(0,0,0,0.3);
  border-radius: 6px;
  padding: 3px;
}
.view-toggle button {
  background: transparent;
  border: none;
  color: rgba(255,255,255,0.6);
  border-radius: 4px;
  cursor: pointer;
  padding: 0.2rem 0.7rem;
  font-size: 0.85rem;
  transition: background 0.15s, color 0.15s;
}
.view-toggle button.active {
  background: rgba(255,255,255,0.15);
  color: var(--header-text);
  font-weight: 600;
}
.view-toggle button:hover:not(.active) { color: var(--header-text); }

.week-day-col {
  border-right: 1px solid var(--grid-line);
  text-align: center;
  padding: 0.5rem 0.25rem;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  flex: 1;
  transition: background 0.15s;
}
.week-day-col:hover { background: #f0f4f8; }
.week-day-col .week-date { font-weight: 400; color: #64748b; font-size: 0.7rem; }
.week-day-col.is-today { color: #2563eb; }
.week-day-col.is-today .week-date { color: #2563eb; }

.date-nav {
  display: flex;
  align-items: stretch;
  gap: 0.4rem;
  margin-left: auto;
  height: 32px;
}
.date-nav > button,
.date-picker-wrap > button {
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.2);
  color: var(--header-text);
  border-radius: 4px;
  cursor: pointer;
  padding: 0 0.6rem;
  font-size: 0.9rem;
  line-height: 1;
  transition: background 0.15s;
  display: flex;
  align-items: center;
}
.date-nav > button:hover,
.date-picker-wrap > button:hover { background: rgba(255,255,255,0.2); }
#btn-date-label {
  font-weight: 600;
  min-width: 224px;
  justify-content: center;
}

#btn-today,
#btn-user-menu { font-size: 0.8rem; }
/* Keeps prev/date/next tightly grouped as a unit and only pushes Today away
   from them - a no-op on desktop (.date-nav has no spare room to push into
   there), but exactly what's needed once .date-nav is flex:1 on narrow
   viewports, rather than justify-content: space-between spreading all four
   controls apart evenly and floating prev/next away from the date. */
#btn-today { margin-left: auto; }

.date-picker-wrap {
  display: contents;
}

#date-picker-popup {
  position: fixed;
  background: #1e293b;
  border: 1px solid rgba(255,255,255,0.15);
  border-radius: 8px;
  padding: 0.5rem;
  z-index: 100;
  width: 224px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.4);
  color: var(--header-text);
}

.dp-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.4rem;
}
.dp-header button {
  background: transparent;
  border: none;
  color: var(--header-text);
  font-size: 1.1rem;
  cursor: pointer;
  padding: 0.2rem 0.5rem;
  border-radius: 4px;
  min-width: unset;
  height: unset;
  line-height: 1;
}
.dp-header button:hover { background: rgba(255,255,255,0.1); }
#dp-month-label {
  font-weight: 600;
  font-size: 0.85rem;
}

.dp-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.dp-day-header {
  text-align: center;
  font-size: 0.7rem;
  color: #94a3b8;
  padding: 0.2rem 0;
}
.dp-day {
  background: transparent;
  border: none;
  color: var(--header-text);
  font-size: 0.8rem;
  text-align: center;
  padding: 0.3rem 0;
  border-radius: 4px;
  cursor: pointer;
  min-width: unset;
  height: unset;
  line-height: 1;
}
.dp-day:hover { background: rgba(255,255,255,0.1); }
.dp-day.dp-today { color: #60a5fa; font-weight: 700; }
.dp-day.dp-selected { background: #2563eb; color: #fff; }
.dp-day.dp-selected:hover { background: #3b82f6; }
.dp-day.dp-in-week { background: rgba(37,99,235,0.25); }
.dp-day.dp-in-week:hover { background: rgba(37,99,235,0.4); }

/* ── Header, deliberate 2-row layout ──
   Title/refresh/view-toggle/date-nav/account menu's natural (unshrinkable)
   widths add up to something in the region of 900-950px, well above the
   768px breakpoint that governs day view/week-label compacting (see
   COMPACT_QUERY in app.js - that's about the *calendar grid*, not the
   header, and the header needs more room than the grid does). If this
   threshold were left at 768px too, there'd be a dead zone between ~800px
   and this breakpoint where content had already stopped fitting on one row
   but the deliberate rearrangement hadn't kicked in yet - the generic
   flex-wrap safety net below would wrap *something* (#auth-box, alone, in
   plain DOM order) without moving it to sit next to the title as intended,
   producing a jarring halfway state before this breakpoint properly took
   over. Setting this comfortably wider than that natural minimum means the
   deliberate layout always applies before the safety net would ever need
   to. */
@media (max-width: 960px) {
  header { height: auto; padding: 0.5rem 0.75rem; }
  .header-inner { row-gap: 0.4rem; gap: 0.5rem; }
  h1 { order: 1; }
  #auth-box { order: 2; }
  #chrome {
    order: 3;
    flex-basis: 100%;
    gap: 0.5rem;
    justify-content: space-between;
  }
  .date-nav { margin-left: 0; flex: 1; }
}

/* ── Header, phone-width cosmetics (matches the JS COMPACT_QUERY breakpoint) ──
   Pure sizing polish once we're at actual phone widths, layered on top of
   the 2-row layout above (960px) which is already active by this point. */
@media (max-width: 768px) {
  h1 { font-size: 0.95rem; }
  #btn-date-label { min-width: unset; font-size: 0.8rem; padding: 0 0.5rem; }
}

/* ── Header, landscape phone ──
   The 2-row nav bar (needed for width reasons - see the 960px block above)
   costs real vertical space, which is scarce specifically in landscape on a
   phone (short viewport height, unlike portrait or any desktop/tablet
   width). Scoped by height as well as orientation so this never engages on
   a wide-but-tall device. See the matching LANDSCAPE_PHONE_QUERY/scroll
   listener in app.js, which toggles .header-hidden based on scroll
   direction within the calendar. main's flex: 1 automatically reclaims the
   space as header's max-height collapses - no repositioning needed. */
@media (orientation: landscape) and (max-height: 500px) {
  header {
    max-height: 200px;
    overflow: hidden;
    transition: max-height 0.2s ease, padding 0.2s ease;
  }
  header.header-hidden {
    max-height: 0;
    padding-top: 0;
    padding-bottom: 0;
  }
}

/* ── Main ── */
main {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.loading, .error {
  padding: 2rem;
  text-align: center;
  color: #64748b;
}
.error { color: #dc2626; }
.hidden { display: none !important; }

/* ── Calendar grid ── */
.calendar {
  flex: 1;
  overflow: auto;
  display: flex;
  flex-direction: column;
}

.cal-header {
  display: flex;
  position: sticky;
  top: 0;
  z-index: 10;
  background: #fff;
  border-bottom: 2px solid var(--grid-line);
}
.cal-header .time-col {
  width: var(--time-col-w);
  flex-shrink: 0;
  border-right: 1px solid var(--grid-line);
}
.cal-header .resource-col {
  flex: 1;
  padding: 0.5rem 0.4rem;
  font-weight: 600;
  font-size: 0.78rem;
  border-right: 1px solid var(--grid-line);
  line-height: 1.3;
}
.cal-header .resource-col .room-number {
  font-weight: 400;
  color: #64748b;
  font-size: 0.7rem;
}

.cal-body {
  display: flex;
  position: relative;
  /* No flex: 1 - sizing to natural content height (rather than stretching
     to fill the viewport) means there's a real edge to put a border on,
     instead of the grid just trailing off into blank space below 23:00
     on a tall screen. */
  border-bottom: 2px solid var(--grid-line);
}

.time-col {
  width: var(--time-col-w);
  flex-shrink: 0;
  border-right: 1px solid var(--grid-line);
}
.time-slot {
  height: var(--slot-h);
  border-bottom: 1px solid var(--grid-line);
  display: flex;
  align-items: flex-start;
  padding: 2px 4px 0;
  font-size: 0.7rem;
  color: #94a3b8;
  font-variant-numeric: tabular-nums;
}
.time-slot.hour { color: #475569; font-weight: 600; }
.time-slot.half { border-bottom-color: transparent; }

.resources-area {
  flex: 1;
  display: flex;
  overflow: hidden;
}

.resource-lane {
  flex: 1;
  border-right: 1px solid var(--grid-line);
  position: relative;
}

.lane-bg {
  position: absolute;
  inset: 0;
}
.lane-slot {
  height: var(--slot-h);
  border-bottom: 1px solid var(--grid-line);
}
.lane-slot.half { border-bottom-color: rgba(226,232,240,0.4); }
.lane-slot.past { background: var(--past-bg); }

.booking-block {
  position: absolute;
  left: 2px;
  right: 2px;
  background: var(--booking-bg);
  color: var(--booking-text);
  border-radius: 4px;
  padding: 3px 5px;
  font-size: 0.72rem;
  overflow: hidden;
  cursor: default;
  transition: filter 0.1s;
  z-index: 2;
}
.booking-block:hover { filter: brightness(1.15); z-index: 3; }
.booking-block-ext {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  background: rgba(255,255,255,0.3);
  border-radius: 0 0 4px 4px;
  pointer-events: none;
}
.booking-block .b-time { font-weight: 600; white-space: nowrap; }
.booking-block .b-name {
  display: block;
  opacity: 0.9;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: inherit;
  text-decoration: none;
}
a.b-name:hover { text-decoration: underline; }

.week-sub-lane {
  position: absolute;
  top: 0;
  bottom: 0;
  border-right: 1px solid rgba(0,0,0,0.06);
}
.week-sub-block {
  position: absolute;
  left: 1px;
  right: 1px;
  border-radius: 2px;
  min-height: 4px;
  cursor: default;
  transition: filter 0.1s;
  z-index: 2;
}
.week-sub-block:hover { filter: brightness(1.2); z-index: 3; }

#booking-popover {
  position: fixed;
  background: #fff;
  border: 2px solid;
  border-radius: 8px;
  padding: 0.75rem 1rem;
  z-index: 300;
  min-width: 210px;
  max-width: 300px;
  box-shadow: 0 4px 24px rgba(0,0,0,0.15);
  font-size: 0.85rem;
}
.bp-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}
.bp-resource {
  font-weight: 600;
  line-height: 1.3;
  color: #1e293b;
}
#bp-close {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 1.2rem;
  color: #94a3b8;
  padding: 0;
  line-height: 1;
  flex-shrink: 0;
  margin-top: -2px;
}
#bp-close:hover { color: #475569; }
.bp-time {
  font-weight: 600;
  color: #475569;
  margin-bottom: 0.3rem;
}
.bp-booker { color: #334155; }
.bp-booker a { color: inherit; text-decoration: none; }
.bp-booker a:hover { text-decoration: underline; }

/* Same breakpoint as COMPACT_QUERY in app.js - the popover is sized for
   desktop/tablet by default, which feels oversized against week view's tiny
   per-resource slivers on a phone. */
@media (max-width: 768px) {
  #booking-popover {
    padding: 0.45rem 0.6rem;
    min-width: 140px;
    max-width: 200px;
    font-size: 0.72rem;
  }
}

.week-lane-loading {
  background: repeating-linear-gradient(
    -45deg,
    transparent,
    transparent 8px,
    rgba(0,0,0,0.03) 8px,
    rgba(0,0,0,0.03) 16px
  );
}
.week-lane-error { background: #fff1f1; }

.now-line {
  position: absolute;
  left: 0; right: 0;
  height: 2px;
  background: #ef4444;
  z-index: 5;
  pointer-events: none;
}
.now-line-dot::before {
  content: '';
  position: absolute;
  left: -4px;
  top: -4px;
  width: 10px;
  height: 10px;
  background: #ef4444;
  border-radius: 50%;
}
