/* public/assets/css/s37-meeting-rooms.css
   KHMER HRMS — Meeting Room Booking (M19)
   Season: S37 — Meeting Room Booking

   Everything here is namespaced (.room-cal-*) except the two
   room-card tweaks at the top, which lean on the existing shared
   .card/.card-grid classes and only add what those don't already
   cover. Colours come only from theme CSS variables (Day/Night safe).
   Spacing follows the 8px scale (8/16/24/32). The week calendar grid
   is rendered entirely by public/assets/js/s37-room-calendar.js —
   no external calendar library (zero CDN, Rule #10). */

/* ═══ Tabs + page actions, one row ══════════════════════════════
   Nini's ask: the Meeting Rooms / Book a Room buttons used to sit in
   their own .table-action-dock row above the Calendar/List tabs,
   which left a tall gap of empty space under the "Room Bookings"
   title. Putting both in one flex row removes that extra row/margin
   entirely (so the tabs sit closer to the title) and keeps the
   buttons level with the tabs instead of floating above them. */
.tabs-nav-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px 12px;
    border-bottom: 1px solid var(--border);
    margin-bottom: var(--space-2);
}
.tabs-nav-row .tabs-nav {
    margin-bottom: 0;
    border-bottom: none;
    flex: 1 1 auto;
    min-width: 0;
}
.tabs-nav-row .header-actions {
    flex: 0 0 auto;
    padding-bottom: 6px;
}
@media (max-width: 767.98px) {
    .tabs-nav-row .tabs-nav { order: 2; flex: 1 1 100%; }
    .tabs-nav-row .header-actions { order: 1; flex: 1 1 100%; justify-content: flex-end; padding-bottom: 8px; }
}

/* ═══ Create/Edit form + live preview sidebar ══════════════════
   Named class (not an inline style) so the mobile override below
   actually applies — see s34-certifications.css's documented gotcha:
   an inline grid-template-columns on .card-grid always wins over any
   external stylesheet rule, at every viewport width, and crushes the
   1fr column on small screens. */
.room-grid-sidebar { grid-template-columns: minmax(0, 1fr) 300px; align-items: start; }

@media (max-width: 900px) {
    .room-grid-sidebar { grid-template-columns: 1fr; }
    .room-preview-panel { position: static !important; }
}

.room-preview-panel { position: sticky; top: var(--space-3); }

/* ═══ Room list grid ═════════════════════════════════════════════
   The shared .card-grid stretches its tracks to 1fr at every
   breakpoint (responsive.css), so a short list (1-3 rooms) leaves
   the unused tracks rendered as bare empty space out to the page's
   full width — this is what the screenshot showed. auto-fit collapses
   empty trailing tracks instead of keeping them, and capping the
   track size (not 1fr) stops the real cards from stretching to fill
   the freed space, so the row simply ends after the last real card/
   the add-tile, like a normal card list. This file loads after
   responsive.css (see layouts/main.php), so at equal specificity it
   wins over .card-grid's breakpoint rules without needing !important. */
.room-list-grid {
    grid-template-columns: repeat(auto-fit, minmax(280px, 340px));
    justify-content: start;
}

/* ═══ Room list — "Add Room" ghost tile ═════════════════════════
   meeting_rooms/index.php's .card-grid stretches to fill the page
   width (same shared .card-grid as everywhere else), so with only
   one or two rooms the remaining grid slots were bare empty space.
   This tile sits as the grid's last item, so it fills a slot with
   a real action instead of nothing — dashed-border style matches
   the existing upload-zone/logo-preview convention elsewhere in
   app.css, not a one-off look. */
.room-add-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-height: 220px;
    border: 1.5px dashed var(--border);
    background: var(--surface-alt);
    color: var(--text-muted);
    text-decoration: none;
    text-align: center;
    font-weight: 600;
    transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.room-add-card svg { width: 28px; height: 28px; }
.room-add-card:hover,
.room-add-card:focus-visible {
    border-color: var(--primary);
    color: var(--primary);
    background: color-mix(in srgb, var(--primary) 6%, var(--surface-alt));
}

/* ═══ Meeting Rooms page — header + redesigned room cards ═══════
   Title left, page buttons right on ONE row (they used to float in a
   separate dock with a tall empty gap). Colours: theme variables only. */
.room-page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px 16px;
}
.room-page-header-text { min-width: 0; flex: 1 1 260px; }
.room-page-header .header-actions { flex: 0 0 auto; }
/* Mobile: responsive.css turns .page-header into a COLUMN flex container, so the
   desktop `flex: 1 1 260px` on the text block becomes a 260px-tall HEIGHT — that was
   the big empty gap between the subtitle and the buttons. Reset it to content height
   and tighten the gap so the buttons sit right under the title/subtitle. */
@media (max-width: 767.98px) {
    .room-page-header {
        flex-wrap: nowrap;
        gap: 12px;
        margin-bottom: var(--space-2);
    }
    .room-page-header-text { flex: 0 0 auto; width: 100%; }
    .room-page-header .header-actions {
        flex: 0 0 auto;
        width: 100%;
        justify-content: flex-start;
    }
}

/* Empty state: icon bubble + message + one CTA, centred, not full-bleed */
.room-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    padding: 48px 24px;
    max-width: 560px;
    margin: 8px auto 0;
    text-align: center;
    border: 1.5px dashed var(--border);
}
.room-empty p { margin: 0; color: var(--text-muted); }
.room-empty-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 72px;
    height: 72px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--primary) 12%, var(--surface));
    color: var(--primary);
}
.room-empty-icon svg { width: 34px; height: 34px; }

/* Room card */
.room-card {
    display: flex;
    flex-direction: column;
    padding: 0;
    overflow: hidden;
    transition: box-shadow 0.18s ease, transform 0.18s ease;
}
.room-card:hover { transform: translateY(-2px); box-shadow: 0 10px 24px rgba(0, 0, 0, 0.10); }
.room-card.row-inactive .room-card-media,
.room-card.row-inactive .room-card-body { opacity: 0.65; }

.room-card-media {
    position: relative;
    height: 150px;
    background: color-mix(in srgb, var(--primary) 10%, var(--surface-alt));
}
.room-card-media .room-card-photo {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    cursor: pointer;
}
.room-card-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    color: color-mix(in srgb, var(--primary) 55%, var(--text-muted));
}
.room-card-placeholder svg { width: 44px; height: 44px; }
.room-card-status { position: absolute; top: 10px; right: 10px; }
.room-card-status .badge { box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18); }

.room-card-body { padding: 16px 16px 12px; flex: 1 1 auto; }
.room-card-title { margin: 0; font-size: 1.05rem; line-height: 1.3; }
.room-card-subtitle { font-size: 0.8rem; margin-top: 2px; }
.room-card-meta {
    list-style: none;
    margin: 12px 0 0;
    padding: 0;
    display: grid;
    gap: 6px;
    font-size: 0.85rem;
    color: var(--text-muted);
}
.room-card-meta li { display: flex; align-items: center; gap: 8px; }
.room-card-meta svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--primary); }
.room-card-facilities { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }

.room-card-footer {
    padding: 12px 16px 16px;
    border-top: 1px solid var(--border);
    background: var(--surface-alt);
    display: grid;
    gap: 10px;
}
.room-card-stat { font-size: 0.78rem; color: var(--text-muted); }
.room-card-stat strong { color: var(--text); font-size: 0.95rem; }
.room-card-cta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.room-card-admin { margin-left: auto; width: auto; flex: 0 0 auto; }

.room-add-card { min-height: 100%; }

/* Room card photo — clickable to open the shared image lightbox
   (data-lightbox-image, wired up globally in app.js/layouts/main.php).
   Slight dim-on-hover is the only affordance needed since cursor:pointer
   is already set inline. */
.room-card-photo { transition: opacity 0.15s; }
.room-card-photo:hover { opacity: 0.88; }

.badge-dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    margin-left: auto;
    border-radius: 999px;
    background: var(--danger, #DC2626);
    color: #fff;
    font-size: 0.68rem;
    font-weight: 700;
    line-height: 1;
}

/* ═══ Week calendar shell ═══════════════════════════════════════ */

.room-cal-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

.room-cal-toolbar-nav {
    display: flex;
    align-items: center;
    gap: 8px;
}

.room-cal-toolbar-label {
    font-weight: 700;
    font-size: 0.95rem;
    min-width: 160px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.room-cal-grid {
    display: grid;
    grid-template-columns: 44px repeat(7, minmax(96px, 1fr));
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    overflow-x: auto;
    /* Vertical scroll — the grid now renders the full 24h day (00:00–
       23:00), which no longer fits one screen at the original 40px/hour
       density. Scrolling inside a capped-height box (instead of just
       stretching the page) keeps the rest of the page reachable without
       an enormous scroll; .room-cal-head below is pinned via
       position:sticky so the day names stay visible while scrolling. */
    overflow-y: auto;
    max-height: 620px;
}

.room-cal-head {
    background: var(--surface-alt, var(--surface));
    padding: 8px 4px 6px;
    text-align: center;
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--text-muted);
    border-bottom: 1px solid var(--border);
    border-left: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 3;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}
/* Two-line header: day name (small, muted) over the date number. */
.room-cal-head-name { text-transform: uppercase; letter-spacing: 0.04em; font-size: 0.66rem; }
.room-cal-head-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 28px;
    height: 28px;
    padding: 0 4px;
    border-radius: 999px;
    font-size: 0.95rem;
    color: var(--text);
}
.room-cal-head.is-today { color: var(--primary); }
.room-cal-head.is-today .room-cal-head-num { background: var(--primary); color: #fff; }

/* The top-left corner cell above the hour-label column — same sticky/
   background treatment as .room-cal-head so it doesn't show day-column
   content scrolling underneath it while the header row is pinned.
   Nini's ask: labelled "ម៉ោង"/"Time" (via JS, data-lang-time-col) so an
   unlabelled header cell doesn't make the row look uneven next to the
   day-name headers, which all carry text. */
.room-cal-corner {
    background: var(--surface-alt, var(--surface));
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 8px 2px;
    font-size: 0.62rem;
    font-weight: 700;
    color: var(--text-muted);
    text-align: center;
}

.room-cal-hour-label {
    grid-column: 1;
    /* Centered horizontally in the Time column, and vertically in the
       MIDDLE of its hour row (JS places it at line + 30 min;
       translateY(-50%) + line-height:1 = true optical centre). The solid
       background masks the dashed half-hour guide that would otherwise
       run through the number. */
    text-align: center;
    padding: 2px 0;
    line-height: 1;
    font-size: 0.7rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
    background: var(--surface);
    transform: translateY(-50%);
}

.room-cal-day-col {
    position: relative;
    border-left: 1px solid var(--border);
    min-height: 960px;
}
/* Weekend + today tints are translucent on purpose: the shared hour-line
   overlay sits underneath the day columns and must stay visible. */
.room-cal-day-col.is-weekend { background: color-mix(in srgb, var(--text-muted) 5%, transparent); }
.room-cal-day-col.is-today { background: color-mix(in srgb, var(--primary) 6%, transparent); }

/* Current-time marker (today's column only). */
.room-cal-now {
    position: absolute;
    left: 0;
    right: 0;
    height: 0;
    border-top: 2px solid var(--danger, #DC2626);
    z-index: 1;
    pointer-events: none;
}
.room-cal-now::before {
    content: '';
    position: absolute;
    left: -4px;
    top: -5px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--danger, #DC2626);
}

/* Shared hour-line overlay — Nini's ask: the 24 hour rows in the Time
   column didn't read as equal height. They used to come from two
   independent approximations of "40px per hour": the JS placed each
   label at an exact px offset, while every day column separately drew
   its own lines via a CSS repeating-linear-gradient background. Those
   two never had to agree pixel-for-pixel — repeating-gradient tiles are
   rasterised/anti-aliased per tile, so at non-integer browser zoom or
   Windows display-scaling the gradient's "40px" tiles can render a
   fraction of a pixel apart from tile to tile, drifting away from the
   labels' exact positions and reading as uneven rows. This single
   overlay (added by s37-room-calendar.js) spans every column — the Time
   label column included — and draws one real line per hour at the exact
   same top offset used for the label above it, so there is only one
   source of truth for row height and every row is guaranteed identical
   however the browser is zoomed or scaled. */
.room-cal-hour-lines {
    grid-column: 1 / -1;
    grid-row: 2;
    position: relative;
    pointer-events: none;
}

.room-cal-hour-line {
    position: absolute;
    left: 0;
    right: 0;
    border-top: 1px solid var(--border);
}
.room-cal-hour-line.is-half {
    border-top-style: dashed;
    border-top-color: color-mix(in srgb, var(--border) 55%, transparent);
}

.room-cal-event {
    position: absolute;
    left: 3px;
    right: 3px;
    z-index: 2;
    border-radius: 6px;
    padding: 3px 6px 3px 8px;
    font-size: 0.68rem;
    line-height: 1.25;
    background: color-mix(in srgb, var(--primary) 18%, var(--surface));
    border: 1px solid color-mix(in srgb, var(--primary) 45%, transparent);
    border-left: 3px solid var(--primary);
    color: var(--text);
    overflow: hidden;
    cursor: pointer;
    text-decoration: none;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
    transition: box-shadow 0.12s ease, transform 0.12s ease;
}
.room-cal-event:hover { box-shadow: 0 3px 8px rgba(0, 0, 0, 0.16); transform: translateY(-1px); }
.room-cal-event.is-pending {
    background: color-mix(in srgb, var(--warning, #D97706) 20%, var(--surface));
    border-color: color-mix(in srgb, var(--warning, #D97706) 45%, transparent);
    border-left-color: var(--warning, #D97706);
}
.room-cal-event-title { font-weight: 700; display: block; }
.room-cal-event-meta { display: block; color: var(--text-muted); }

.room-cal-empty {
    text-align: center;
    color: var(--text-muted);
    font-size: 0.8rem;
    padding: 24px 8px;
}

.room-cal-slot-add {
    position: absolute;
    inset: 0;
    cursor: pointer;
    transition: background 0.12s ease;
}
.room-cal-slot-add:hover { background: color-mix(in srgb, var(--primary) 5%, transparent); }

@media (max-width: 767px) {
    .room-cal-grid { grid-template-columns: 36px repeat(7, minmax(84px, 1fr)); }
    .room-cal-toolbar-label { min-width: 0; text-align: left; width: 100%; }
    .room-cal-head-num { min-width: 24px; height: 24px; font-size: 0.85rem; }
}

/* ═══ Attendee picker — dual-panel add/remove ═══════════════════════
   Replaces the native <select multiple> Ctrl/Cmd-click list on
   room_bookings/create.php, which doesn't scale once the employee
   roster is long and gives no way to find someone by typing. Two
   independently searchable panels; clicking a row (or its own
   Add/Remove button) moves that employee between them. Reuses the
   existing .combo-search-input look (searchable-combo.js's field,
   app.css) so this reads as the same search-input language as the
   rest of the app rather than a one-off. Colours are CSS variables
   only (Day/Night safe); spacing follows the 8px scale. */
.attendee-picker {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: stretch;
    gap: 10px;
    margin-top: 6px;
}

.attendee-picker-arrows {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
}
.attendee-picker-arrows svg { width: 18px; height: 18px; transform: rotate(-90deg); }

.attendee-picker-col {
    display: flex;
    flex-direction: column;
    min-width: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface-alt, var(--surface));
    overflow: hidden;
}

.attendee-picker-col-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 10px 12px;
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--text);
    border-bottom: 1px solid var(--border);
}

.attendee-picker-count {
    min-width: 22px;
    height: 20px;
    padding: 0 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: color-mix(in srgb, var(--primary) 14%, transparent);
    color: var(--primary);
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1;
}

.attendee-picker-search-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 10px;
    border-bottom: 1px solid var(--border);
}
.attendee-picker-search-row svg { width: 15px; height: 15px; color: var(--text-muted); flex-shrink: 0; }
/* .combo-search-input ships its own border/background for use as a
   standalone field elsewhere (filter bars); inside this bordered panel
   row it only needs to behave like plain text, so its chrome is
   stripped here without touching the shared class itself. */
.attendee-picker-search-row .combo-search-input {
    border: none !important;
    padding: 2px !important;
    background: transparent !important;
    box-shadow: none !important;
}

.attendee-picker-list {
    max-height: 240px;
    overflow-y: auto;
    padding: 4px;
}

.attendee-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 7px 8px;
    border-radius: 6px;
    cursor: pointer;
    transition: background 0.12s ease;
}
.attendee-row:hover { background: color-mix(in srgb, var(--primary) 8%, transparent); }
.attendee-row-name { font-size: 0.82rem; color: var(--text); line-height: 1.3; }
.attendee-row-code { color: var(--text-muted); font-size: 0.74rem; }

.attendee-row-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    flex-shrink: 0;
    border: none;
    border-radius: 999px;
    background: color-mix(in srgb, var(--primary) 14%, transparent);
    color: var(--primary);
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease;
}
.attendee-row-btn svg { width: 12px; height: 12px; }
.attendee-row-btn:hover { background: var(--primary); color: #fff; }
.attendee-row-btn.is-remove {
    background: color-mix(in srgb, var(--danger, #DC2626) 14%, transparent);
    color: var(--danger, #DC2626);
}
.attendee-row-btn.is-remove:hover { background: var(--danger, #DC2626); color: #fff; }

.attendee-picker-empty {
    padding: 18px 10px;
    text-align: center;
    font-size: 0.78rem;
    color: var(--text-muted);
}

.attendee-picker-bulk-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 100%;
    padding: 8px 10px;
    border: none;
    border-top: 1px solid var(--border);
    background: transparent;
    color: var(--primary);
    font-size: 0.78rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.12s ease;
}
.attendee-picker-bulk-btn svg { width: 13px; height: 13px; }
.attendee-picker-bulk-btn:hover { background: color-mix(in srgb, var(--primary) 8%, transparent); }
.attendee-picker-bulk-btn:disabled { opacity: 0.4; cursor: default; pointer-events: none; }
.attendee-picker-bulk-btn-danger { color: var(--danger, #DC2626); }
.attendee-picker-bulk-btn-danger:hover { background: color-mix(in srgb, var(--danger, #DC2626) 8%, transparent); }

@media (max-width: 640px) {
    .attendee-picker { grid-template-columns: 1fr; }
    .attendee-picker-arrows svg { transform: rotate(0deg); }
    .attendee-picker-arrows { padding: 2px 0; }
}

/* Fix (2026-09-22 patch): field-level error state for Book a Room's
   client-side pre-submit validation (room, title, date/time picker) —
   same visual language as the s11 date/time picker's own
   .s11-picker-display.is-invalid (s11-leave.css), extended here to the
   plain <select>/<input> fields and the picker's own wrapper div so a
   missing/invalid field is obvious before the confirm dialog ever
   shows, not just after a failed server round-trip. */
.room-booking-form .form-group select.is-invalid,
.room-booking-form .form-group input.is-invalid,
.room-booking-form .form-group .s11-picker-field.is-invalid .s11-picker-display {
    border-color: var(--danger, #dc2626);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger, #dc2626) 15%, transparent);
}
.room-booking-field-error {
    display: block;
    color: var(--danger, #dc2626);
    font-size: 0.78rem;
    margin-top: 4px;
}

/* ── Action audit trail (Room Bookings + Consultations, migration 177) ──
   Shared by room_bookings/show.php and consultations/show.php via
   ActionTrailService::render(). Colors come only from theme CSS
   variables so Day/Night mode needs nothing extra. Mobile-first: the
   meta line simply wraps under the title on narrow screens. */
.action-trail {
    list-style: none;
    margin: 0;
    padding: 0;
    position: relative;
}
.action-trail::before {
    content: '';
    position: absolute;
    left: 15px;
    top: 14px;
    bottom: 14px;
    width: 2px;
    background: var(--border);
}
.action-trail-item {
    display: flex;
    gap: 14px;
    padding: 8px 0;
    position: relative;
}
.action-trail-dot {
    flex: 0 0 32px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--surface);
    border: 2px solid var(--border);
    color: var(--text-muted);
    z-index: 1;
}
.action-trail-dot svg { width: 16px; height: 16px; }
.action-trail-item.tone-info    .action-trail-dot { border-color: var(--primary); color: var(--primary); }
.action-trail-item.tone-warning .action-trail-dot { border-color: #D97706; color: #D97706; }
.action-trail-item.tone-success .action-trail-dot { border-color: #16A34A; color: #16A34A; }
.action-trail-item.tone-danger  .action-trail-dot { border-color: #DC2626; color: #DC2626; }
.action-trail-body { flex: 1; min-width: 0; }
.action-trail-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 2px 14px;
    font-size: 0.8rem;
    color: var(--text-muted);
}
.action-trail-meta b { color: var(--text); font-weight: 600; }
.action-trail-when { white-space: nowrap; }
.action-trail-note {
    margin-top: 4px;
    padding: 8px 10px;
    border-radius: 8px;
    background: var(--surface);
    border: 1px solid var(--border);
    font-size: 0.85rem;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}
