/*
 * App shell layout corrections.
 *
 * Loaded last so these win over global-hrms.css, theme.css and
 * sidebar-collapse.css.
 *
 * Three problems this fixes:
 *
 * 1. THE SIDEBAR COULD NOT SCROLL. `.sidebar` is `position: fixed` with
 *    `height: calc(100vh - 60px)` and no `overflow-y`, so any nav item past
 *    the bottom of the viewport was simply unreachable -- not clipped with a
 *    scrollbar, just gone. It went unnoticed while the nav was short; grouping
 *    Leave, Calendar and IT & Support made it tall enough to overflow on a
 *    laptop, and at browser zoom it overflows almost immediately.
 *
 * 2. THE HEADER HEIGHT WAS WRITTEN IN THREE PLACES. The header is 60px, the
 *    sidebar starts at `top: 60px` and is `100vh - 60px` tall, and the main
 *    content has `margin-top: 60px`. At high zoom the header's contents need
 *    more than 60px, so it grew and slid underneath the other two. All three
 *    now derive from `--header-height`, which is the only place the number
 *    appears.
 *
 * 3. THE BREAKPOINTS DISAGREED. global-hrms.css turns the sidebar into an
 *    off-canvas overlay below 768px, but sidebar-collapse.css cancelled the
 *    collapsed width below 900px. Between 769px and 900px -- which is where a
 *    zoomed-in laptop lands -- the sidebar was 240px wide while the content's
 *    left margin was 0, so the sidebar sat on top of the page. Both now use
 *    the same breakpoint.
 */

:root {
    --header-height: 60px;
}

/* ============================================================ the header */

.top-header {
    /* min-height, not height: at zoom the contents need more room, and a fixed
       height made them spill out of the bar instead of growing it. */
    height: auto;
    min-height: var(--header-height);
    gap: 12px;
    flex-wrap: nowrap;
}

/* The branding block gives way before the controls do -- a truncated company
   name is better than a wrapped header that overlaps the page. */
.top-header .logo-section {
    min-width: 0;
    flex: 1 1 auto;
}

.top-header .logo-section .company-name,
.top-header .logo-section h1,
.top-header .logo-section h2 {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.top-header .header-actions,
.top-header .header-right {
    flex: 0 0 auto;
}

/* =========================================================== the sidebar */

.sidebar {
    top: var(--header-height);
    height: calc(100vh - var(--header-height));
    /* dvh accounts for mobile browser chrome that appears and disappears. */
    height: calc(100dvh - var(--header-height));

    /* The actual fix. overflow-x must be stated too: when one axis is
       `visible` and the other is not, the spec computes `visible` to `auto`,
       which would add a pointless horizontal scrollbar. */
    overflow-y: auto;
    overflow-x: hidden;

    /* Keeps a flick at the end of the nav from scrolling the page behind it. */
    overscroll-behavior: contain;

    display: flex;
    flex-direction: column;

    /* A slim, themed scrollbar. The sidebar is chrome, not content, so a
       full-width scrollbar reads as clutter. */
    scrollbar-width: thin;
    scrollbar-color: var(--border-strong, var(--border)) transparent;
}

.sidebar::-webkit-scrollbar { width: 8px; }
.sidebar::-webkit-scrollbar-track { background: transparent; }

.sidebar::-webkit-scrollbar-thumb {
    background: var(--border-strong, var(--border));
    border-radius: 99px;
    /* Inset the thumb so it does not touch the panel edge. */
    border: 2px solid transparent;
    background-clip: content-box;
}

.sidebar::-webkit-scrollbar-thumb:hover {
    background: var(--text-secondary);
    background-clip: content-box;
}

/* The nav takes the slack so anything pinned below it stays at the bottom. */
.sidebar-nav {
    flex: 1 1 auto;
    min-height: 0;
}

.sidebar-nav ul {
    /* Breathing room at the end, so the last item is not flush against the
       bottom edge when scrolled fully down. */
    padding-bottom: 22px;
}

/* The collapse toggle stays put while the nav scrolls under it. */
.sidebar-toolbar {
    position: sticky;
    top: 0;
    z-index: 2;
    flex: 0 0 auto;
    background: var(--bg-raised);
}

/* ====================================================== the content area */

.main-content {
    margin-top: var(--header-height);
    min-height: calc(100vh - var(--header-height));
    /* Long words and wide tables must not push the page sideways. */
    overflow-x: hidden;
}

/* ======================================================= zoom resilience
 * High browser zoom is, to CSS, a narrow viewport. These are ordered from the
 * mildest response to the strongest, so zooming degrades step by step rather
 * than breaking all at once.
 */

/* Around 150% zoom on a 1440px laptop: give the header more room and tighten
   the nav so more of it fits before scrolling is needed. */
@media (max-width: 1100px) {
    :root { --header-height: 58px; }

    .sidebar-nav li a {
        padding-block: 10px;
        font-size: 13.5px;
    }

    .sidebar-nav .nav-group-label {
        padding-block: 8px 6px;
        font-size: 10.5px;
    }
}

/* Around 200% zoom: the header needs two rows for its controls, so let it
   wrap -- everything else follows --header-height automatically. */
@media (max-width: 900px) {
    :root { --header-height: 64px; }
    .top-header { flex-wrap: wrap; padding-block: 8px; }

    /* Match global-hrms.css's off-canvas breakpoint rather than pre-empting
       it: between these two widths the sidebar used to overlap the content. */
    body.sidebar-collapsed .sidebar { width: var(--sidebar-width-collapsed); }
    body.sidebar-collapsed .main-content { margin-left: var(--sidebar-width-collapsed); }
}

/* The off-canvas overlay takes over here, matching global-hrms.css. */
@media (max-width: 768px) {
    :root { --header-height: 60px; }

    body.sidebar-collapsed .sidebar { width: var(--sidebar-width); }
    body.sidebar-collapsed .main-content { margin-left: 0; }

    .main-content { padding: 14px; }
}

/* Very high zoom or a small phone. Keep a usable gutter and stop the stat and
   card grids from forcing a minimum width wider than the screen. */
@media (max-width: 560px) {
    .main-content { padding: 12px; }

    .it-stat-row,
    .emp-dash-stats {
        grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
    }

    .it-grid,
    .profile-grid-cards,
    .emp-dash-two-col {
        grid-template-columns: 1fr;
    }

    .modal-content {
        width: calc(100vw - 24px) !important;
        max-width: calc(100vw - 24px) !important;
        margin: 14px auto !important;
    }
}

/*
 * Anything that must never shrink below a readable size, regardless of the
 * branded font-size tokens. Users reported text disappearing at zoom; the
 * cause was a token multiplied down past legibility, so these are floors.
 */
.it-cell-sub,
.it-stat-note,
.field-hint,
.attendance-subtitle {
    font-size: max(11.5px, 0.78rem);
}

/* Tables are the one thing allowed to scroll sideways, inside their own box. */
.it-table-wrap,
.table-responsive {
    max-width: 100%;
}

/* ==================================================== dark-mode contrast
 * Found by measuring real contrast ratios in the browser rather than by eye.
 * Both of these were reported as "text is invisible in dark mode".
 */

/*
 * 1. UNCLASSED LINKS WERE BROWSER-DEFAULT BLUE.
 *
 * A plain <a href="#/..."> inside prose gets no styling from this app, so it
 * fell back to the user-agent default #0000EE. On the dark page background
 * that measures 1.7:1 -- unreadable. It was invisible rather than merely ugly
 * because nothing in the app ever set a link colour for body text.
 *
 * `a:not([class])` is deliberately narrow: every styled link in the app
 * (.btn-primary, .btn-export, .link-button, .nav-*, .it-contact-mail) carries
 * a class and keeps its own colour. Only the unstyled ones are corrected.
 */
a:not([class]) {
    color: var(--link, var(--accent));
    text-decoration-color: color-mix(in srgb, var(--link, var(--accent)) 45%, transparent);
    text-underline-offset: 2px;
    font-weight: 600;
}

a:not([class]):hover {
    text-decoration-color: currentColor;
}

/*
 * The light-mode accent (#0891b2) on white is about 3.4:1 -- fine for a chunky
 * button, thin for 13px body text -- so body links get a darker shade. In dark
 * mode the accent (#3cc3de) already measures ~7.9:1 against the page, so it is
 * used as-is.
 */
:root {
    --link: #0e7490;
    /* Text that sits on top of an accent-filled surface. Near-black teal
       rather than white: the accent is a light cyan in dark mode, where white
       measured only 2.09:1. This reads at 4.8:1 on the light accent and
       8.3:1 on the dark one, so one value is correct in both themes. */
    --on-accent: #04222b;
}

body.dark-mode,
[data-theme="dark"] {
    --link: var(--accent);
}

/*
 * 2. WHITE TEXT ON THE ACCENT PILL WAS 2.09:1.
 *
 * The contact button is filled with the accent colour, which is a light cyan
 * in dark mode; white on it is close to unreadable. Dark text fixes it in both
 * themes without needing a per-theme override.
 */
.it-contact-mail {
    color: var(--on-accent);
}

.it-contact-mail:hover {
    color: var(--on-accent);
}

/* Links inside the accent-tinted contact bar sit on the page background, not
   on the accent fill, so they follow the normal link colour. */
.it-contact-bar .it-contact-copy a {
    color: var(--link, var(--accent));
    font-weight: 600;
}

/* ============================================ dark mode: light containers
 *
 * Found by opening every modal in dark mode and measuring. Several containers
 * hardcode a light background but let their text inherit the theme colour, so
 * in dark mode they painted near-white text on a near-white panel -- measured
 * at 1.06:1, which is invisible, not merely low contrast.
 *
 * The worst was `.form-section { background: #fcfcfc }`. The Manage Week-Off
 * dialog is wrapped in one, so its whole contents disappeared; the same
 * wrapper is used by Apply for Leave, Add Staff and Department, which were all
 * equally unreadable.
 *
 * Status chips (.status-active and friends) are deliberately left alone: they
 * set a light background AND a matching dark text colour, so they stay
 * readable in either theme.
 *
 * These are overrides rather than edits to the original rules because the
 * light theme wants exactly what those rules say; only dark mode needs a
 * different surface.
 */

body.dark-mode .form-section,
body.dark-mode .admin-card,
body.dark-mode .modal-content,
body.dark-mode .calendar-modal,
body.dark-mode .day-cell.other-month {
    background: var(--bg-raised);
    background-color: var(--bg-raised);
    color: var(--text-primary);
    border-color: var(--border);
}

/* Panels inside a card want the recessed surface, not the raised one. */
body.dark-mode .form-section {
    background: var(--bg-sunken);
    background-color: var(--bg-sunken);
}

/* Labels and headings inside a dialog follow the theme rather than whatever
   the surrounding page happened to set. */
body.dark-mode .modal-content h3,
body.dark-mode .modal-content h4,
body.dark-mode .form-section h3,
body.dark-mode .form-section h4,
body.dark-mode .modal-content label,
body.dark-mode .form-section label {
    color: var(--text-primary);
}

/*
 * theme.css targets `body.theme-dark`, but ui-loader.js toggles
 * `body.dark-mode`. Those rules have therefore never applied. Rather than
 * rewrite that file, the class is mirrored below so both spellings work --
 * see the note in ui-loader for which one is authoritative.
 */
body.dark-mode .attendance-panel,
body.dark-mode .dashboard-stat-card,
body.dark-mode .dashboard-soft-card,
body.dark-mode .dashboard-mini-card {
    background: var(--bg-raised);
    color: var(--text-primary);
    border-color: var(--border);
}

/* Leaflet draws its own controls with fixed light colours. */
body.dark-mode .leaflet-control-scale-line,
body.dark-mode .leaflet-control-attribution {
    background: rgba(15, 23, 42, .78) !important;
    color: var(--text-secondary) !important;
    border-color: var(--border) !important;
}

/* A link-styled button on a light dialog was 1.93:1. */
body.dark-mode .btn-link,
.modal-content .btn-link {
    color: var(--link, var(--accent));
    font-weight: 600;
}

/* ==========================================================================
   One visual language across the pages.

   The app grew page by page, and each page brought its own version of the
   same three things: a figure in a box, a panel, and a row of filters. There
   are four separate stat-card families (dashboard-stat-card, leave-stat-card,
   attendance-card, wk-stat), three card paddings and two table looks, so
   moving between pages feels like moving between applications.

   Nothing here changes any page's markup. It gives the existing class names
   one set of measurements: the same padding, the same corner radius, the same
   label size, the same number size, the same gaps. This sheet loads last, so
   it settles the disagreements between the page sheets.
   ========================================================================== */

:root {
    --tile-pad: 14px 16px;
    --tile-radius: 14px;
    --panel-pad: 20px 22px;
    --panel-radius: 16px;
    --stack-gap: 18px;
}

/* ----------------------------------------------------- figures in a box */
.dashboard-shell .dashboard-stat-card,
.leave-shell .leave-stat-card,
.attendance-stack .records-summary-card,
.dashboard-stat-card,
.leave-stat-card,
.wk-stats .wk-stat,
.records-summary-card,
.dashboard-mini-card {
    padding: var(--tile-pad);
    border-radius: var(--tile-radius);
    background: var(--bg-raised);
    border: 1px solid var(--border);
    box-shadow: none;
    min-width: 0;
}

/* The label above or below the figure: small, spaced, quiet. */
.dashboard-stat-label,
.leave-stat-card span,
.wk-stats .wk-stat span,
.records-summary-label {
    font-size: 10.5px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--text-secondary);
    line-height: 1.35;
}

/* The figure itself. One size everywhere, so a number on one page means the
   same as a number on another. */
.dashboard-shell .dashboard-stat-value,
.leave-shell .leave-stat-card strong,
.attendance-stack .records-summary-value,
.dashboard-stat-value,
.leave-stat-card strong,
.wk-stats .wk-stat strong,
.records-summary-value {
    font-size: 22px;
    font-weight: 700;
    line-height: 1.15;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.dashboard-stat-note,
.leave-stat-card small,
.wk-stats .wk-stat small {
    font-size: 11.5px;
    line-height: 1.45;
    color: var(--text-secondary);
}

/* Rows of tiles: narrow enough that seven fit on one line rather than six
   plus a lonely seventh on the next. */
.dashboard-shell .dashboard-stat-grid,
.leave-shell .leave-summary-grid,
.attendance-stack .records-summary-grid,
.wk-shell .wk-stats,
.dashboard-stat-grid,
.leave-summary-grid,
.records-summary-grid,
.wk-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(138px, 1fr));
    gap: 12px;
    min-width: 0;
}
.dashboard-stat-grid > *,
.leave-summary-grid > *,
.records-summary-grid > *,
.wk-stats > * { min-width: 0; }

/* ---------------------------------------------------------------- panels */
.content-card,
.attendance-card,
.attendance-panel,
.table-container-card {
    padding: var(--panel-pad);
    border-radius: var(--panel-radius);
    background: var(--bg-raised);
    border: 1px solid var(--border);
}

/* A panel heading should not sit hard against the content under it. */
.content-card > h2:first-child,
.content-card > h3:first-child,
.attendance-card > h3:first-child,
.attendance-panel > h3:first-child { margin-top: 0; }

/* ------------------------------------------------------------- the stack */
.attendance-stack,
.dashboard-shell,
.leave-shell,
.wk-shell,
.farm-shell,
.it-shell { gap: var(--stack-gap); }

/* --------------------------------------------------------------- filters */
/* Labels above their control, at the same size on every page. */
.attendance-toolbar .form-field label,
.filter-bar .form-field label,
.leave-toolbar-grid label,
.table-controls label,
.wk-filters label {
    font-size: 10.5px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--text-secondary);
}

/* One control height, so a select does not stand taller than the input or
   the button beside it. */
.hrms-input, .search-input,
input[type="text"], input[type="search"], input[type="date"],
input[type="month"], input[type="number"], input[type="email"],
input[type="password"], input[type="time"], select, textarea {
    min-height: 38px;
    border-radius: 10px;
}
textarea { min-height: 84px; }

/* --------------------------------------------------------------- buttons */
.btn-submit, .btn-export, .btn-cancel, .btn-primary, .btn-danger, .btn-secondary {
    min-height: 38px;
    padding: 9px 16px;
    border-radius: 10px;
    font-size: 13px;
    font-weight: 700;
    line-height: 1.25;
    white-space: nowrap;
}

/* A button is as wide as its words. Inside a filter grid it used to inherit
   the column and stretch across half the screen -- "Load Report" was wider
   than the three fields it applied to. */
.attendance-toolbar .btn-submit,
.attendance-toolbar .btn-export,
.filter-bar .btn-submit,
.filter-bar .btn-export,
.leave-toolbar-grid .btn-submit,
.leave-toolbar-grid .btn-export,
.table-controls .btn-submit,
.table-controls .btn-export,
.records-filter-grid .btn-primary,
.records-filter-grid .btn-submit,
.wk-filters .btn-submit,
.farm-filters .btn-submit { justify-self: start; align-self: end; width: auto; }

/* Groups of buttons keep a consistent gap and wrap rather than overflow. */
.split-actions, .table-controls, .page-header-row, .records-view-header {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
}

/* ---------------------------------------------------------------- tables */
/* employee-management.css sets a hardcoded #f0f0f0 cell border, which is
   invisible on the dark theme, and a 12px font in every table on every page.
   Both come from the token set now. */
.hrms-table th,
.hrms-table td {
    border-bottom: 1px solid var(--border-soft);
    font-size: 12.5px;
    padding: 11px 14px;
}
.hrms-table thead th {
    font-size: 10.5px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--text-secondary);
}
.hrms-table tbody tr:last-child td { border-bottom: 0; }

/* --------------------------------------------------------- page headings */
/* Every page states what it is the same way: the name, then one line saying
   what the page is for, then its actions. */
.page-header-row h2, .page-title, .attendance-title {
    margin: 0;
    font-size: 21px;
    font-weight: 700;
    letter-spacing: -.01em;
    color: var(--text-primary);
}
.page-subtitle, .attendance-subtitle, .page-header-row p {
    margin: 4px 0 0;
    font-size: 13px;
    line-height: 1.6;
    color: var(--text-secondary);
    max-width: 78ch;
}

/* ----------------------------------------------------------------- phone */
@media (max-width: 760px) {
    :root { --panel-pad: 15px 16px; --stack-gap: 14px; }
    .dashboard-stat-grid,
    .leave-summary-grid,
    .records-summary-grid,
    .wk-stats { grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); gap: 10px; }
    .dashboard-stat-value,
    .leave-stat-card strong,
    .wk-stats .wk-stat strong,
    .records-summary-value { font-size: 20px; }
}

/* --------------------------------------------------- the profile pages
   The label sat in a fixed 160px column inside a card barely twice that
   wide, so "Health Insurance Card" wrapped onto three lines next to a dash,
   and the cards in each row stretched to match the tallest, leaving half a
   card of empty space. The label now sits above its value, the way it does
   everywhere else in the app.
   These out-specify the <style> block the page injects at runtime. */
.profile-shell .profile-grid-cards,
.profile-shell .profile-doc-grid { align-items: start; }

.profile-shell .profile-item {
    grid-template-columns: 1fr;
    gap: 2px;
    padding-bottom: 9px;
}
.profile-shell .profile-item strong {
    font-size: 10.5px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--text-secondary);
    line-height: 1.35;
}
.profile-shell .profile-item span {
    font-size: 13px;
    line-height: 1.55;
    color: var(--text-primary);
    overflow-wrap: anywhere;
}
.profile-shell .profile-item span:empty::before { content: "3"; color: var(--text-secondary); }

/* Two value pairs side by side once there is room for them. */
@media (min-width: 900px) {
    .profile-shell .profile-list {
        grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
        gap: 10px 20px;
    }
}

/* Cards here carried a 22px radius and a deep shadow while every other panel
   in the app has 16px and none. */
.profile-shell .profile-card,
.profile-shell .profile-section {
    border-radius: var(--panel-radius);
    padding: var(--panel-pad);
    box-shadow: none;
}
.profile-shell .profile-card h4,
.profile-shell .profile-section h4 {
    font-size: 13px;
    letter-spacing: .01em;
    margin-bottom: 12px;
}

/* --------------------------------------------------- change password */
.pw-backdrop { position:fixed; inset:0; z-index:3000; display:grid; place-items:center; padding:16px;
    background:rgba(15,23,42,.55); backdrop-filter:blur(2px); }
.pw-box { width:min(440px, 100%); display:grid; gap:14px; padding:24px 24px 20px; border-radius:16px;
    background: var(--bg-raised); border:1px solid var(--border); box-shadow:0 24px 60px rgba(15,23,42,.3); }
.pw-box h2 { margin:0; font-size:19px; color: var(--text-primary); }
.pw-lead { margin:0; font-size:13px; line-height:1.6; color: var(--text-secondary); }
.pw-field { display:grid; gap:6px; font-size:10.5px; font-weight:800; text-transform:uppercase; letter-spacing:.06em; color: var(--text-secondary); }
.pw-field input { font-size:14px; text-transform:none; letter-spacing:normal; }
.pw-hint { font-size:11.5px; font-weight:500; text-transform:none; letter-spacing:normal; color: var(--text-secondary); }
.pw-error { margin:0; min-height:18px; font-size:13px; font-weight:600; color: var(--danger); }
.pw-actions { display:flex; justify-content:flex-end; gap:10px; }
