/* 2CRSI Edge - design system v2 (2026-07-04 visual revamp).
   Grey/orange brand identity, centralised nav shell (see _AppLayout.cshtml
   and _Header.cshtml), responsive throughout. Replaces the v1 "minimal
   starting theme" - see DECISIONS.md for the brief §11 lineage (clean
   light layout, orange accent; chrome now grey per direct user request,
   content areas stay white/light as originally decided). */

:root {
    --ink-900: #202124;
    --ink-800: #3a3b3f;
    --ink-700: #4d4e52;
    --ink-600: #6b6c70;
    --orange-600: #f2801f;
    --orange-700: #d66c0f;
    --orange-100: #fef1e2;
    --bg: #f4f5f6;
    --surface: #ffffff;
    --border: #e2e3e6;
    --text: #202124;
    --muted: #6b6c70;
    --green: #2f8f4e;
    --green-bg: #eaf6ee;
    --red: #c0392b;
    --red-bg: #fdecea;
    --grey-chip: #eceef0;
    --font-sans: -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
    --font-mono: "Cascadia Code", "SF Mono", Consolas, monospace;

    /* legacy variable names - still referenced by a handful of inline
       styles across older pages; keep pointed at the new palette rather
       than hunting down every literal reference. */
    --edge-orange: var(--orange-600);
    --edge-orange-dark: var(--orange-700);
    --edge-text: var(--text);
    --edge-muted: var(--muted);
    --edge-border: var(--border);
    --edge-bg: var(--bg);
}

* {
    box-sizing: border-box;
}

/* Site-wide mobile overflow guard (2026-08-21) - found live: a wide,
   unconstrained element anywhere on a page (most often a data-dense table,
   e.g. Training Matrix's one-column-per-course grid) can push the
   document's own INTRINSIC width past the device's viewport. Desktop
   Chrome/DevTools device emulation reflows correctly regardless and never
   exposed this, but real mobile Safari falls back to rendering the whole
   page at that wider intrinsic width and zooming the viewport out to fit
   it - "the whole page is still in desktop mode", not just one wide table
   needing its own scrollbar. This is a belt-and-braces backstop on top of
   (not a replacement for) each wide table's own .table-scroll wrapper
   below - that still owns the contained, intentional horizontal scroll
   for its one table; this stops the mistake from ever reaching the page
   level at all, on any page, without needing to audit every page
   individually.

   html only, NOT body (2026-08-24 fix, found live - a real regression) -
   putting overflow-x:hidden on body too broke .sidebar's own
   position:sticky on any page taller than one screen (e.g. Admin/Rota/
   Groups' full list): per spec, setting overflow-x on an element without
   also setting overflow-y makes the browser compute overflow-y as auto
   instead of visible, turning body into an unintended second scroll
   container. .sidebar's sticky positioning then stuck to THAT container
   instead of the real viewport, so once the page's content ran taller
   than body's own box, the sidebar stopped scrolling along and visibly
   ran out partway down, leaving bare background below it. html alone
   already fully contains the same overflow this guard exists for. */
html {
    max-width: 100%;
    overflow-x: hidden;
}

body {
    margin: 0;
    max-width: 100%;
    font-family: var(--font-sans);
    color: var(--text);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
}

a {
    color: inherit;
}

svg {
    display: block;
}

/* ================= Login / ChangePin ================= */

.login-body {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    background: var(--bg);
    padding: 2rem 1rem;
}

.login-card {
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 2.25rem 2rem;
    width: 100%;
    max-width: 340px;
    box-shadow: 0 10px 40px rgba(32, 33, 36, 0.08);
}

/* Same look as .login-card but without its 340px cap - for data-dense
   panels (tables, multi-column forms) that need to fill a grid track
   rather than a centered login-style form. */
.data-card {
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 2.25rem 2rem;
    width: 100%;
    box-shadow: 0 10px 40px rgba(32, 33, 36, 0.08);
}

.login-brand {
    text-align: center;
    margin-bottom: 1.75rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}

.login-brand img.brand-logo {
    height: 32px;
    width: auto;
}

.brand-2crsi, .brand-edge {
    /* retained for any leftover literal usage; superseded by the logo image */
    font-weight: 700;
}

.brand-edge {
    color: var(--orange-600);
}

.login-field {
    margin-bottom: 1rem;
}

.login-field label {
    display: block;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--muted);
    margin-bottom: 0.35rem;
}

.login-input {
    width: 100%;
    padding: 0.65rem 0.8rem;
    border: 1px solid var(--border);
    border-radius: 8px;
    font-size: 1rem;
    font-family: var(--font-sans);
    background: #fff;
    color: var(--text);
}

.login-input:focus {
    outline: none;
    border-color: var(--orange-600);
    box-shadow: 0 0 0 3px var(--orange-100);
}

.login-validation {
    display: block;
    color: var(--red);
    font-size: 0.8rem;
    margin-top: 0.25rem;
}

.login-error {
    background: var(--red-bg);
    border: 1px solid #f5c6cb;
    color: #a4293a;
    padding: 0.65rem 0.8rem;
    border-radius: 8px;
    font-size: 0.9rem;
    margin-bottom: 1rem;
}

.login-button {
    width: 100%;
    background: var(--orange-600);
    color: #fff;
    border: none;
    border-radius: 8px;
    padding: 0.75rem;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    margin-top: 0.5rem;
    font-family: var(--font-sans);
}

.login-button:hover {
    background: var(--orange-700);
}

/* ================= App shell (sidebar layout, 2026-07-23 redesign) ================= */

.app-body {
    margin: 0;
    background: var(--bg);
    min-height: 100vh;
}

.app-body-sidebar {
    display: flex;
    align-items: stretch;
}

.sidebar {
    width: 288px;
    flex-shrink: 0;
    background: linear-gradient(180deg, var(--ink-700), var(--ink-800));
    color: #fff;
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
    z-index: 50;
}

.sidebar-brand {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px 16px;
    /* Light grey cap, deliberately not the dark ink gradient the rest of the
       sidebar uses - the logo's "crsi"/"Edge" text is a dark grey
       (~var(--ink-800)) and disappeared against the dark background. */
    background: var(--bg);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}

.sidebar-brand img {
    max-width: 100%;
    height: 34px;
    width: auto;
}

.sidebar-nav {
    flex: 1;
    padding: 14px 12px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.sidebar-category-toggle {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 10px;
    background: none;
    border: none;
    color: rgba(255, 255, 255, 0.75);
    font-family: var(--font-sans);
    /* Bumped 13.5px -> 15px (2026-08-07, post-Round-4 feedback) - a top-
       level category (e.g. "Administration") should read as clearly bigger
       than everything nested under it (sub-categories and pages, both
       13px) - at 13.5px the two were nearly indistinguishable. */
    font-size: 15px;
    font-weight: 600;
    padding: 10px 12px;
    border-radius: 8px;
    cursor: pointer;
    text-align: left;
}

.sidebar-category-toggle svg:not(.chevron) {
    width: 17px;
    height: 17px;
    flex-shrink: 0;
}

.sidebar-category-toggle .chevron {
    width: 15px;
    height: 15px;
    margin-left: auto;
    flex-shrink: 0;
    transition: transform 0.15s ease;
}

.sidebar-category-toggle:hover {
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
}

.sidebar-category-toggle.active {
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
}

/* 2026-08-07, Stage F - the category header used to be a single <button>
   that only toggled expand/collapse. It's now a <div> containing a real
   <a> (the icon+label, linking to that category's own auto-generated
   /Nav/<slug> tile page) plus a separate chevron-only <button> that still
   does the expand/collapse. Every other rule above targets the .sidebar-
   category-toggle class name, not the element tag, so nothing else here
   needed to change. */
.sidebar-category-link {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    color: inherit;
    text-decoration: none;
}

.sidebar-category-chevron-btn {
    background: none;
    border: none;
    padding: 4px;
    margin: -4px;
    color: inherit;
    cursor: pointer;
    display: flex;
    align-items: center;
    flex-shrink: 0;
}

.sidebar-subnav {
    display: block;
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.18s ease;
}

.sidebar-subnav.open {
    /* Bumped from 320px (2026-08-07, Round 4 Phase 1) - genuinely recursive
       nesting (_SidebarSubtree) can now legitimately contain more rows
       (a nested category header plus its own children) than the old
       single-level flattened list ever did. */
    max-height: 600px;
    /* Small gap so an active sub-link's highlight doesn't sit flush against
       the parent category toggle's own highlight above it (2026-07-23 fix -
       the two rounded rects were touching and reading as one merged blob). */
    margin-top: 3px;
}

/* :not(.sidebar-category-link) added (2026-08-07) - ROOT CAUSE of the
   reported misalignment, found only after direct DOM measurement (three
   rounds of guessing from screenshots alone had failed): .sidebar-subnav a
   is a bare descendant selector, matching ANY <a> tag anywhere inside a
   .sidebar-subnav, regardless of that anchor's own class. A clickable
   container's own toggle link (<a class="sidebar-category-link">, e.g.
   "System Admin") lives inside its PARENT's .sidebar-subnav, so it was
   ALSO matching this rule and getting this padding/margin applied DIRECTLY
   TO THE ANCHOR, layered on top of .sidebar-category-toggle-nested's own
   padding on the surrounding div - a genuine double-application, not a
   guess. The INERT variant (<span class="sidebar-category-link-inert">,
   e.g. "Manager") never matched (it's not an <a>), which is exactly why
   only inert containers ever looked correctly aligned. Confirmed via
   direct getBoundingClientRect() measurement in the browser before this
   fix, not assumed. */
.sidebar-subnav a:not(.sidebar-category-link) {
    display: block;
    text-decoration: none;
    color: rgba(255, 255, 255, 0.62);
    font-size: 13px;
    /* Normal weight by default (2026-08-07, post-Round-4 feedback) - was
       unconditionally 600, meaning every leaf was always bold regardless
       of whether it was the current page, leaving no visual weight left
       for .active to add. Bold is now reserved for .active below, so
       "which page am I on" reads from weight, not just background tint. */
    font-weight: 400;
    /* Inset via margin (not full-bleed to the container edge) so the active
       highlight reads as its own smaller, separate box. */
    margin: 2px 6px;
    /* padding-left recomputed, not guessed (2026-08-07, post-Round-4
       feedback: label text should start at the same X as a top-level
       category's own label). Top-level text starts at nav-padding(12) +
       toggle-padding(12) + icon-width(17) + icon-gap(10) = 51px from the
       sidebar's edge. This row's own contributors are nav-padding(12,
       same ancestor) + this row's own margin-left(6) = 18px, so
       padding-left must supply the remaining 51-18 = 33px for the two to
       land on the same pixel. */
    padding: 7px 10px 7px 33px;
    border-radius: 6px;
    /* Allow wrap (2026-07-23) - "User Access & PIN Administration" is long
       enough that forcing nowrap clipped it even after widening the
       sidebar; wrapping is robust to any future long label without having
       to keep re-guessing pixel widths. */
    white-space: normal;
    line-height: 1.35;
}

.sidebar-subnav a:not(.sidebar-category-link):hover {
    color: #fff;
    background: rgba(255, 255, 255, 0.06);
}

.sidebar-subnav a.active:not(.sidebar-category-link) {
    color: #fff;
    background: rgba(255, 255, 255, 0.14);
    font-weight: 600;
}

/* Nested container headers inside a subnav (2026-08-07, Round 4 Phase 1) -
   a real page or category that itself has children now renders as an
   expandable row at any depth, not just top-level categories. Reuses
   .sidebar-category-toggle's flex/chevron layout but sized down to match
   a leaf link's proportions (13px, same padding/indent) since it lives
   inside a subnav rather than the main nav list. */
.sidebar-category-toggle-nested {
    /* padding-left recomputed to 33px, matching .sidebar-subnav a's own
       recomputation just above - same formula, same reasoning, so a
       sub-category header's label lands on the same X as its top-level
       parent's label, not the previous 31px guess. */
    padding: 7px 10px 7px 33px;
    margin: 2px 6px;
    border-radius: 6px;
    font-size: 13px;
    color: rgba(255, 255, 255, 0.62);
    /* Normal weight by default (2026-08-07, post-Round-4 feedback) - this
       class previously never set font-weight at all, so it silently
       inherited 600 (bold) from the .sidebar-category-toggle base class it
       shares - meaning a sub-category header was ALWAYS bold, whether or
       not it was the current section, leaving .active nothing to add.
       Explicit override here so bold is reserved for .active below, same
       fix as .sidebar-subnav a. */
    font-weight: 400;
    /* Explicit line-height/white-space (2026-08-07, post-Round-4 feedback) -
       a plain leaf link (.sidebar-subnav a) already sets both; this rule
       never did, so a container header row (this class) could render at a
       slightly different height than a leaf row at the exact same depth,
       depending on the browser's default line-height. Matched to .sidebar-
       subnav a's values so every row at a given depth is pixel-consistent
       regardless of whether it happens to be a leaf, a category, or a real
       page acting as a container. */
    line-height: 1.35;
    white-space: normal;
}

.sidebar-category-toggle-nested:hover {
    color: #fff;
    background: rgba(255, 255, 255, 0.06);
}

.sidebar-category-toggle-nested.active {
    color: #fff;
    background: rgba(255, 255, 255, 0.14);
    font-weight: 600;
}

/* An inert (never-navigable) container header - a category (always inert,
   toggles expand/collapse on click, see toggleSidebarCategory) or a real
   page acting purely as a grouping for children this viewer can't reach
   themselves (also click-to-toggle, same reason). Pointer, not default -
   the whole row is a functional click target now, not dead space
   (2026-08-08, fixed alongside categories losing their broken /Nav/{slug}
   link). */
.sidebar-category-link-inert {
    cursor: pointer;
}

/* A second level of nesting (e.g. training pages under a nested "Training
   Manager" category, itself under "Training Module") gets extra indent so
   it doesn't look identical to its own parent row. Bumped 45px -> 47px to
   keep the same +14px step now that the base level moved 31px -> 33px
   (2026-08-07, post-Round-4 feedback). :not(.sidebar-category-link) added
   for the same reason as .sidebar-subnav a above - without it, a
   clickable container toggle two levels deep would double up on this
   indent too. */
.sidebar-subnav .sidebar-subnav a:not(.sidebar-category-link),
.sidebar-subnav .sidebar-subnav .sidebar-category-toggle-nested {
    padding-left: 47px;
}

.sidebar-toplink {
    display: flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
    color: rgba(255, 255, 255, 0.75);
    font-size: 13.5px;
    font-weight: 600;
    padding: 10px 12px;
    border-radius: 8px;
}

.sidebar-toplink svg {
    width: 17px;
    height: 17px;
    flex-shrink: 0;
}

.sidebar-toplink:hover {
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
}

.sidebar-toplink.active {
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
}

.sidebar-user {
    padding: 14px 16px;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.sidebar-user .user-chip {
    color: rgba(255, 255, 255, 0.85);
}

.sidebar-user-row {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
}

.sidebar-user-row form {
    flex-shrink: 0;
}

.sidebar-footer {
    padding: 14px 16px 18px;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    flex-shrink: 0;
}

.sidebar-footer p {
    margin: 0;
    font-size: 11px;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.45);
    text-align: center;
}

.sidebar-backdrop {
    display: none;
}

.app-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.topbar {
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    padding: 10px 24px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 16px;
}

.topbar-clock {
    font-size: 13px;
    font-weight: 600;
    color: var(--ink-700);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.user-chip {
    font-size: 13px;
    color: rgba(255, 255, 255, 0.85);
    display: flex;
    gap: 8px;
    align-items: center;
    white-space: nowrap;
}

.user-chip .avatar {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--orange-600);
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.25);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    font-weight: 700;
    flex-shrink: 0;
}

.logout-btn {
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.28);
    color: #fff;
    padding: 6px 10px;
    border-radius: 7px;
    font-size: 12.5px;
    cursor: pointer;
    font-family: var(--font-sans);
    display: flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}

.logout-btn svg {
    width: 15px;
    height: 15px;
}

/* Grey, not the old white-on-dark styling - lives in the light .topbar now
   (moved back from the sidebar 2026-07-23), needs to stand out against a
   white background instead of a dark one. */
.bell-btn {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--grey-chip);
    border: 1px solid var(--border);
    color: var(--ink-700);
    flex-shrink: 0;
}

.bell-btn:hover {
    background: #e2e3e6;
}

.bell-btn svg {
    width: 16px;
    height: 16px;
}

.bell-badge {
    position: absolute;
    top: -4px;
    right: -4px;
    background: var(--red, #c0392b);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
    padding: 2px 4px;
    border-radius: 999px;
    min-width: 16px;
    text-align: center;
}

.hamburger {
    display: none;
    background: none;
    border: none;
    color: var(--ink-800);
    cursor: pointer;
    padding: 4px;
    margin-right: auto;
}

.page-header {
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    padding: 16px 24px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}

.page-header-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    max-width: 1280px;
    margin: 0 auto;
    width: 100%;
}

.page-header .crumb {
    font-size: 12.5px;
    color: var(--muted);
    margin: 0 0 3px;
}

.page-header h1 {
    margin: 0;
    font-size: 19px;
    font-weight: 700;
    letter-spacing: -0.01em;
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Favourite-page star (2026-07-23) - rendered next to every page's H1 in
   _AppLayout.cshtml, so it appears on every page with zero per-page work. */
.favorite-star {
    background: none;
    border: none;
    cursor: pointer;
    padding: 2px;
    display: inline-flex;
    align-items: center;
    color: var(--muted);
}

.favorite-star svg {
    width: 20px;
    height: 20px;
}

.favorite-star:hover {
    color: var(--orange-600);
}

.favorite-star.active {
    color: var(--orange-600);
}

.page-header .actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.content {
    padding: 22px 24px 48px;
    max-width: 1280px;
    margin: 0 auto;
    /* The actual root cause of the site-wide mobile overflow (2026-08-21),
       confirmed live before/after, not guessed - .content is a flex ITEM
       of .app-main's column flex layout but never had its own `width`
       set, only `max-width`. Without an explicit width, its box sizing
       fell back to its own content's preferred/intrinsic size once any
       descendant panel contains an unbreakable wide table (e.g. Training
       Matrix's one-column-per-course grid) - min-width:0 alone (the usual
       flex-overflow fix, and the one .app-main itself already relies on
       one level up) was tried first and did NOT fix it; only adding an
       explicit width did. The html/body overflow guard above only hid
       the symptom (stopped the PAGE from scrolling to reveal it); this
       is what actually makes .content itself responsive, so each wide
       table's own .table-scroll wrapper gets its correct, viewport-sized
       box to scroll within instead of silently rendering off-screen. */
    width: 100%;
}

/* Opt-in via ViewData["WideContent"]=true - for data-dense pages (e.g. Staff
   Master Files) where the default width forces horizontal scroll on
   desktop, rather than widening every page site-wide. ~10% wider. */
.content-wide {
    max-width: 1408px;
}

/* Two-column field layout for data-dense forms (e.g. Staff Master Files
   Edit/Create) - the single-column .login-field stack reads fine for a
   short login/PIN form but wastes most of a desktop screen's width once a
   form has 30+ fields. */
.form-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0 1.5rem;
}

.form-grid .full-width {
    grid-column: 1 / -1;
}

.form-section-title {
    grid-column: 1 / -1;
    font-weight: 600;
    margin: 1.6rem 0 0.6rem;
    padding-top: 1.2rem;
    border-top: 1px solid var(--border);
}

.form-section-title:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
}

.form-section-note {
    grid-column: 1 / -1;
    color: var(--muted);
    font-size: 0.8rem;
    margin: -0.4rem 0 0.6rem;
}

@media (max-width: 720px) {
    .form-grid {
        grid-template-columns: 1fr;
    }
}

/* ================= Buttons & badges ================= */

.btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-family: var(--font-sans);
    font-size: 13.5px;
    font-weight: 600;
    padding: 9px 16px;
    border-radius: 8px;
    border: 1px solid transparent;
    cursor: pointer;
    text-decoration: none;
    line-height: 1.2;
    white-space: nowrap;
}

.btn svg {
    width: 16px;
    height: 16px;
}

.btn-primary {
    background: var(--orange-600);
    color: #fff;
}

.btn-primary:hover {
    background: var(--orange-700);
}

.btn-secondary {
    background: #fff;
    color: var(--ink-800);
    border-color: var(--border);
}

.btn-secondary:hover {
    background: #f6f7f8;
}

.btn-ghost {
    background: transparent;
    color: var(--muted);
    border-color: transparent;
}

/* Dull red for guarded-delete buttons (2026-07-23 backlog item) - visually
   distinct from the neutral .btn-secondary used everywhere else, so a
   destructive action stands out at a glance without being alarmingly bright. */
.btn-danger {
    background: #fff;
    color: var(--red);
    border-color: var(--red);
}

.btn-danger:hover {
    background: var(--red-bg);
}

.badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 12px;
    font-weight: 600;
    padding: 3px 10px;
    border-radius: 100px;
    white-space: nowrap;
}

.badge::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
}

.badge.ok { background: var(--green-bg); color: var(--green); }
.badge.pending { background: var(--orange-100); color: var(--orange-700); }
.badge.bad { background: var(--red-bg); color: var(--red); }
.badge.neutral { background: var(--grey-chip); color: var(--ink-700); }

/* ================= Sub-navigation tabs (used by Leave, Attendance,
   Training, HR Training/Capabilities, HR Attendance, Manager) ================= */

.subnav-tabs {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
    border-bottom: 1px solid var(--border);
    padding-bottom: 0;
}

.subnav-tabs a {
    text-decoration: none;
    color: var(--muted);
    font-weight: 600;
    font-size: 13.5px;
    padding: 0.6rem 0.9rem;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
}

.subnav-tabs a.active {
    color: var(--text);
    border-bottom-color: var(--orange-600);
}

.subnav-tabs a:hover {
    color: var(--text);
}

.filter-pills {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
    align-items: center;
    margin-bottom: 1.25rem;
}

.filter-pills a {
    text-decoration: none;
    color: var(--muted);
    font-size: 12.5px;
    font-weight: 600;
    padding: 0.35rem 0.8rem;
    border-radius: 100px;
    border: 1px solid var(--border);
    background: #fff;
    white-space: nowrap;
}

.filter-pills a.active {
    color: #fff;
    background: var(--ink-700);
    border-color: var(--ink-700);
}

.filter-pills a.accent.active {
    background: var(--orange-600);
    border-color: var(--orange-600);
}

/* ================= Dashboard cards ================= */

.edge-cards {
    display: grid;
    /* Fixed 4-wide (2026-07-23) - auto-fit used to give 2 or 3 per row
       depending on how many cards a given page had, which read as
       inconsistent between pages. Fixed column count instead; narrower
       breakpoints below step it down predictably. */
    grid-template-columns: repeat(4, 1fr);
    gap: 14px;
}

.edge-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 18px;
    text-decoration: none;
    color: var(--text);
    display: flex;
    flex-direction: column;
    gap: 10px;
    transition: box-shadow 0.15s, transform 0.15s;
}

.edge-card:hover {
    box-shadow: 0 6px 20px rgba(32, 33, 36, 0.10);
    transform: translateY(-1px);
}

.edge-card-icon {
    width: 38px;
    height: 38px;
    border-radius: 9px;
    background: var(--orange-100);
    color: var(--orange-700);
    display: flex;
    align-items: center;
    justify-content: center;
}

.edge-card-icon svg {
    width: 20px;
    height: 20px;
}

.edge-card h3 {
    margin: 0 0 0.4rem 0;
    font-size: 15px;
    font-weight: 700;
}

.edge-card p {
    margin: 0;
    color: var(--muted);
    font-size: 13px;
    line-height: 1.45;
}

/* ================= KPI row ================= */

.kpi-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 12px;
    margin-top: 1.5rem;
}

.kpi-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 14px 16px;
    display: flex;
    align-items: center;
    gap: 12px;
    box-shadow: none;
}

.kpi-icon {
    width: 36px;
    height: 36px;
    border-radius: 9px;
    background: var(--grey-chip);
    color: var(--ink-700);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.kpi-icon svg {
    width: 18px;
    height: 18px;
}

.kpi-label {
    font-size: 0.72rem;
    color: var(--muted);
    margin: 0 0 0.15rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.kpi-value {
    font-size: 1.1rem;
    font-weight: 700;
    margin: 0;
    font-variant-numeric: tabular-nums;
}

/* ================= Panels & forms ================= */

.panel {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 20px;
    margin-bottom: 20px;
}

.panel > h2 {
    margin: 0 0 14px;
    font-size: 15px;
    font-weight: 700;
}

.field-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
}

/* ================= Data tables ================= */

.table-scroll {
    overflow-x: auto;
    max-width: 100%;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--surface);
}

table.data {
    width: 100%;
    border-collapse: collapse;
    font-size: 13.5px;
    min-width: 640px;
    background: var(--surface);
}

/* List/Table element framework Phase 2 (2026-08-09) - a lone cell's width
   is only ever a hint under the default auto table layout (the browser can
   and does override it based on content), which is why resize needs a
   <colgroup> plus this class to actually hold - see _DataTableColgroup.cshtml
   and edge-table.js's ensureFixedLayout. Deliberately not applied to every
   table.data - only once a table actually has custom widths, so the
   unresized default stays content-sized, not evenly split. */
table.data.dt-fixed-layout {
    table-layout: fixed;
}

table.data th {
    text-align: left;
    font-size: 11.5px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted);
    padding: 11px 14px;
    background: #fafbfb;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
    position: relative;
}

/* List/Table element framework Phase 2 (2026-08-09) - column resize handle,
   a thin invisible-until-hover strip at the right edge of a header cell. */
.dt-col-resize-handle {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 6px;
    cursor: col-resize;
    user-select: none;
}

.dt-col-resize-handle:hover {
    background: var(--edge-orange, #e08a3c);
    opacity: 0.5;
}

/* List/Table element framework Phase 3 (2026-08-09) - the Excel-style
   filter row sits directly beneath the header row, inside the same
   <thead>; only holds an <input>, so it doesn't need the header row's
   full vertical padding. */
table.data .dt-filter-row th {
    padding: 6px 10px;
    white-space: normal;
}

table.data td {
    padding: 11px 14px;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}

table.data tbody tr:last-child td {
    border-bottom: none;
}

table.data tbody tr:hover {
    background: #fafbfb;
}

table.data .mono {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 12.5px;
    color: var(--muted);
}

/* Keeps a wide table's last column (usually row actions like Edit) visible
   without needing to scroll all the way right - opt-in per table, not
   applied to every table.data automatically. */
table.data th.sticky-actions,
table.data td.sticky-actions {
    position: sticky;
    right: 0;
    box-shadow: -6px 0 6px -6px rgba(0, 0, 0, 0.18);
}

table.data th.sticky-actions {
    background: #fafbfb;
}

table.data td.sticky-actions {
    background: var(--surface);
}

table.data tbody tr:hover td.sticky-actions {
    background: #fafbfb;
}

table.data .row-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

table.data .row-actions form {
    display: inline;
}

/* ================= Leave calendar ================= */

.leave-page {
    max-width: 1040px;
    margin: 0 auto;
    padding: 0 0 3rem;
}

.calendar-card {
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: none;
    padding: 1.75rem;
}

.cal-nav-v2 {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 1.5rem;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.cal-nav-v2 h2 {
    margin: 0;
    font-size: 1.2rem;
}

.cal-nav-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    text-decoration: none;
    color: var(--text);
    font-weight: 600;
    font-size: 0.85rem;
    padding: 0.5rem 0.9rem;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: #fafafa;
    white-space: nowrap;
}

.cal-nav-btn:hover {
    background: #f0f0f0;
}

.cal-grid-v2 {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 8px;
}

.cal-day-header-v2 {
    text-align: center;
    color: var(--muted);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    padding-bottom: 0.5rem;
}

.cal-day-v2 {
    aspect-ratio: 1.15;
    border-radius: 8px;
    border: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    padding: 0.5rem;
    font-weight: 600;
    font-size: 0.95rem;
    cursor: pointer;
    transition: transform 0.1s ease, box-shadow 0.1s ease;
    overflow: hidden;
    gap: 0.15rem;
}

.cal-day-number-v2 {
    font-weight: 600;
    font-size: 0.95rem;
}

.cal-day-entry-v2 {
    max-width: 100%;
    font-weight: 500;
}

.cal-day-v2:hover {
    box-shadow: 0 2px 8px rgba(32, 33, 36, 0.12);
}

.cal-day-v2.cal-today {
    outline: 2px solid var(--ink-800);
    outline-offset: -2px;
}

.cal-working-v2 { background: #fff; color: var(--text); }
.cal-nonworking-v2 { background: #e9eaec; color: #8d8e92; cursor: default; }
/* A non-working day that falls inside an active booking's date range - visibly darker than a plain non-working day so it's obvious it didn't use any holiday allowance. */
.cal-nonworking-inrange-v2 { background: #d3d4d7; color: #75767a; cursor: default; }
.cal-outside-v2 { background: #f6f6f7; color: #cfcfd1; cursor: default; border-color: #f0f0f1; }
.cal-pending-v2 { background: var(--orange-600); color: #fff; border-color: var(--orange-600); }
.cal-approved-v2 { background: var(--green); color: #fff; border-color: var(--green); }

.cal-legend-v2 {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
    align-items: center;
    margin-top: 1.5rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--border);
    font-size: 0.85rem;
    color: var(--text);
}

.swatch {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 3px;
    margin-right: 0.4rem;
    vertical-align: middle;
    border: 1px solid var(--border);
}

.cal-dialog {
    border: none;
    border-radius: 12px;
    padding: 1.5rem;
    max-width: 360px;
    width: calc(100% - 2rem);
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
}

.cal-dialog::backdrop {
    background: rgba(0, 0, 0, 0.4);
}

/* Wider variant (2026-08-05) - Staff Role's edit/create dialog needed more
   room for the Manages Departments checkbox grid; deliberately a separate
   modifier class rather than editing .cal-dialog itself, which ~14+ other
   dialogs across the app share. */
.cal-dialog-wide {
    max-width: 640px;
}

/* Extra-wide variant (2026-08-05, Phase 4) - User Groups' edit/create dialog
   needs room for two side-by-side fieldsets (Special Permissions + the
   Page Access tree, the latter itself scrollable) - again a separate
   modifier rather than widening .cal-dialog-wide itself, which StaffRoles
   already relies on staying at 640px. */
.cal-dialog-xwide {
    max-width: 920px;
}

.mgr-day { background: var(--green); }
.mgr-day.mgr-pending { background: var(--orange-600); }
.mgr-day.mgr-approved { background: var(--red); }
.mgr-day.mgr-clear { background: var(--green); }
.mgr-clear-v2 { background: var(--green); color: #fff; border-color: var(--green); }
.mgr-pending-v2 { background: var(--orange-600); color: #fff; border-color: var(--orange-600); }
.mgr-approved-v2 { background: var(--red); color: #fff; border-color: var(--red); }

/* ================= Manager Staff Calendar (single-employee detail) ================= */

.staff-cal-month {
    background: var(--surface);
    border: 1px solid var(--edge-border);
    border-radius: 10px;
    margin-bottom: 1rem;
    overflow: hidden;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}

.staff-cal-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1.1rem;
    padding: 0.85rem 1.1rem;
    cursor: pointer;
    list-style: none;
    /* Was var(--bg) - the same grey as the page itself, so a collapsed
       month (every month except the current one) showed nothing but this
       bar and looked see-through against the page background rather than
       a solid white card (2026-07-27 fix). */
    background: var(--surface);
    border-bottom: 1px solid var(--edge-border);
}

.staff-cal-summary::-webkit-details-marker { display: none; }

.staff-cal-month-label {
    font-weight: 600;
    margin-right: 0.5rem;
    min-width: 8rem;
}

.staff-cal-stat {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.85rem;
    color: var(--edge-text);
}

.staff-cal-stat svg { width: 16px; height: 16px; color: var(--edge-muted); }

.staff-cal-grid-scroll { overflow-x: auto; }

.staff-cal-grid { border-collapse: collapse; width: 100%; font-size: 0.75rem; }

.staff-cal-grid th, .staff-cal-grid td {
    border: 1px solid var(--edge-border);
    text-align: center;
    padding: 0.3rem 0.2rem;
    min-width: 1.9rem;
}

.staff-cal-rowlabel {
    text-align: left !important;
    font-weight: 600;
    white-space: nowrap;
    padding-left: 0.6rem !important;
    background: var(--surface);
    position: sticky;
    left: 0;
}

.staff-cal-daynum-row th { font-weight: 600; color: var(--edge-muted); }
.staff-cal-dayletter-row th { font-weight: 400; color: var(--edge-muted); }
.staff-cal-nonworking { background: var(--bg); }

/* Click-to-add (2026-07-27) - the day number itself is the click target for
   booking a holiday/logging an absence on that date. */
.staff-cal-daynum-row th.staff-cal-day-clickable { cursor: pointer; }
.staff-cal-daynum-row th.staff-cal-day-clickable:hover { background: var(--orange-100); color: var(--edge-orange-dark); }

.staff-cal-cell { height: 1.6rem; }
.staff-cal-cell-empty { color: var(--edge-border); }
.staff-cal-cell-empty.staff-cal-cell-nonworking { background: var(--bg); }

.staff-cal-cell-holiday { background: #dbe9fb; }
.staff-cal-cell-other { background: var(--grey-chip); }
.staff-cal-cell-sick { background: var(--red-bg); }
.staff-cal-cell-late { background: var(--orange-100); }
.staff-cal-cell-public { background: #e6e0f8; }
.staff-cal-cell-maternity { background: #fbe0ee; }
.staff-cal-cell-timesheet { background: var(--green-bg); }

/* Per-row click-to-add (2026-07-29) - Holidays/Other Events/Sick/
   Maternity-Paternity cells are also click targets, one row at a time,
   so clicking under e.g. Sick for a date logs that specific type directly
   instead of only being able to add from the top day-header. Late/Public
   Holidays/Timesheet stay display-only - they're derived from attendance
   records and the shared bank holiday calendar, not typed in per day. */
td.staff-cal-day-clickable { cursor: pointer; }
td.staff-cal-day-clickable:hover { outline: 2px solid var(--edge-orange-dark); outline-offset: -2px; }

/* ================= Status toast (2026-07-14) ================= */
/* A prominent, dismissible, auto-fading popup for a decision/action
   result - replaces plain grey <p>@Model.StatusMessage</p> text that gave
   no indication of success vs failure and was easy to miss. */

.status-toast {
    position: fixed;
    top: 1.25rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: 2000;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    max-width: min(90vw, 32rem);
    padding: 0.85rem 1rem;
    border-radius: 10px;
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.18);
    font-size: 0.9rem;
    font-weight: 500;
    animation: status-toast-in 0.2s ease-out;
}

@keyframes status-toast-in {
    from { opacity: 0; transform: translate(-50%, -12px); }
    to { opacity: 1; transform: translate(-50%, 0); }
}

.status-toast-success { background: var(--green-bg); color: var(--green); border: 1px solid var(--green); }
.status-toast-error { background: var(--red-bg); color: var(--red); border: 1px solid var(--red); }
.status-toast-icon { width: 20px; height: 20px; flex-shrink: 0; }
.status-toast-text { flex: 1; }

.status-toast-close {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 1.2rem;
    line-height: 1;
    color: inherit;
    opacity: 0.6;
    padding: 0 0.2rem;
}

.status-toast-close:hover { opacity: 1; }

/* Team Calendar header bar (2026-07-14) - restyled to match the per-month
   header bar on Manager Staff Calendar (.staff-cal-summary), without
   touching the shared .calendar-card definition Leave/Index also uses. */
.calendar-card-header {
    margin: -1.75rem -1.75rem 1.5rem -1.75rem;
    padding: 0.85rem 1.75rem;
    background: var(--bg);
    border-bottom: 1px solid var(--edge-border);
    border-radius: 12px 12px 0 0;
    text-align: center;
}

.calendar-card-header h2 {
    margin: 0;
    font-size: 1.1rem;
    font-weight: 600;
}

/* ================= Responsive ================= */

@media (max-width: 900px) {
    .edge-cards { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 760px) {
    /* Sidebar becomes an off-canvas drawer below this width - toggled by the
       hamburger button in .topbar (see toggleSidebarCategory's sibling
       inline handler in _AppLayout.cshtml), rather than the old inline
       .mobile-drawer that just listed portal links under the top bar. */
    .sidebar {
        position: fixed;
        left: 0;
        top: 0;
        transform: translateX(-100%);
        transition: transform 0.2s ease;
    }
    .sidebar.open {
        transform: translateX(0);
    }
    .sidebar-backdrop.open {
        display: block;
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.4);
        z-index: 45;
    }
    .hamburger { display: inline-flex; }
    /* Found live (2026-08-27, reported as garbled/cut-off text on some
       employees' phones) - .topbar's flex-end row, combined with
       .topbar-clock's white-space:nowrap, had no way to shrink: once the
       hamburger + full date/time string + the two icon buttons stopped
       fitting on one line (an aggressive Safari zoom/text-size
       accessibility setting shrinks the *effective* viewport the same way
       a genuinely narrow phone does), flex-end pushes the overflow off
       the LEFT edge - taking the hamburger menu button with it, not just
       clipping the clock text. The site-wide html{overflow-x:hidden}
       guard above (2026-08-21/24) then makes that overflow unreachable
       by scrolling too, unlike an ordinary overflowing element. Confirmed
       live at a 280px effective width: hamburgerLeft computed to -73.7px
       (fully off-screen) before this fix. flex-wrap lets the whole row
       drop to a second line as the ultimate safety net for extreme zoom;
       the smaller font + allowed wrap on the clock text itself should
       mean that second line is rarely actually needed. */
    .topbar { flex-wrap: wrap; row-gap: 4px; }
    .topbar-clock { font-size: 11px; white-space: normal; min-width: 0; text-align: right; }
    .field-row { grid-template-columns: 1fr; }
    .page-header { padding: 14px 16px; }
    .page-header h1 { font-size: 17px; }
    .content { padding: 16px 14px 40px; }
    .panel { padding: 16px; }
    .cal-day-v2 { font-size: 0.75rem; padding: 0.3rem; border-radius: 6px; }
    .cal-grid-v2 { gap: 4px; }
    .kpi-row { grid-template-columns: repeat(2, 1fr); }
    .edge-cards { grid-template-columns: 1fr; }
}

@media (max-width: 480px) {
    .kpi-row { grid-template-columns: 1fr; }
    .login-card { padding: 1.75rem 1.25rem; }
}

/* ================= User Groups: Page Access shuttle (Stage B, 2026-08-06) =================
   Replaces the old tri-state checkbox tree with a Blocked/Allowed dual list -
   see DECISIONS.md. Rendered entirely client-side from the pageTreeData JSON
   embedded in the page; these rows hold no checkboxes at all, only
   synthesized hidden inputs built at render time (see UserGroups.cshtml). */
.pt-access-block {
    margin-bottom: 1rem;
}

.pt-shuttle {
    display: flex;
    gap: 0.6rem;
    align-items: stretch;
}

.pt-fieldset {
    border: 1px solid var(--edge-border);
    border-radius: 6px;
    padding: 0.6rem;
    flex: 1;
    min-width: 200px;
    display: flex;
    flex-direction: column;
}

.pt-fieldset-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--edge-muted);
    margin-bottom: 0.4rem;
}

.pt-expand-all {
    background: none;
    border: none;
    color: var(--edge-orange);
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
    padding: 0;
}

.pt-expand-all:hover {
    text-decoration: underline;
}

.pt-pane {
    max-height: 280px;
    overflow-y: auto;
    flex: 1;
}

.pt-row {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.25rem 0.3rem;
    border-radius: 4px;
    font-size: 0.83rem;
}

.pt-row-context {
    color: var(--edge-muted);
    font-style: italic;
}

/* Stage C5 (2026-08-06) - a sitewide-Disabled page in the Blocked/Allowed
   shuttle, greyed and struck through rather than hidden, so an admin can
   still see it while granting access even though ticking it is a no-op. */
.pt-row-disabled {
    color: var(--edge-muted);
    text-decoration: line-through;
    opacity: 0.7;
}

/* Category/element colour-coding on System Settings > Visuals (2026-08-08)
   - categories (pure navigation/grouping, no page of their own) in orange,
   matching the site's existing accent colour; elements (real, hardcoded
   pages) in blue, so the two are visually distinct at a glance in a flat
   tree that can otherwise be hard to scan. */
.pt-row-category {
    background: var(--orange-100);
    border-left: 3px solid var(--orange-600);
}

.pt-row-element {
    background: var(--blue-100, #e3f0fd);
    border-left: 3px solid var(--blue-600, #2f7ed8);
}

.pt-legend-swatch {
    display: inline-block;
    width: 0.8rem;
    height: 0.8rem;
    border-radius: 3px;
}

.pt-legend-category {
    background: var(--orange-100);
    border-left: 3px solid var(--orange-600);
}

.pt-legend-element {
    background: var(--blue-100, #e3f0fd);
    border-left: 3px solid var(--blue-600, #2f7ed8);
}

.pt-selectable {
    cursor: pointer;
}

.pt-selectable:hover {
    background: var(--edge-bg);
}

.pt-row.selected {
    background: var(--orange-100);
    color: var(--orange-700);
    font-weight: 600;
}

.pt-chevron {
    background: none;
    border: none;
    color: var(--edge-muted);
    cursor: pointer;
    font-size: 0.7rem;
    width: 1rem;
    padding: 0;
    flex-shrink: 0;
    transition: transform 0.12s ease;
}

.pt-chevron.open {
    transform: rotate(90deg);
}

.pt-chevron-spacer {
    width: 1rem;
    flex-shrink: 0;
}

.pt-shuttle-buttons {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.5rem;
}
