/* Portal composition for the authenticated interactive surface (MainLayout + pages).
   Mint-only classes layered on the design system's chrome/component vocabulary (README,
   "Design system") — ds/tokens/components.css owns .portal-*, .nav-item, .data-table,
   .status-pill, …; this sheet adds what the User & Role reference screens compose on top.
   Tokens only, no raw hex; the dark theme comes from the aliases remapping underneath. */

/* ── Chrome extras ───────────────────────────────────────────────────────── */
.nav-rail {
    display: flex;
    flex-direction: column;
    min-height: 100%;
}

.nav-rail .nav-item {
    text-decoration: none;
}

.nav-item-btn {
    width: 100%;
    border: 0;
    background: none;
    font-family: inherit;
    text-align: left;
}

/* Team Hub's nav footer: avatar, name + role line, sign out — pinned to the bottom of the
   rail. The logout form no longer carries the bottom margin; the footer row owns it. */
.nav-footer {
    margin-top: auto;
    padding-top: var(--space-5);
    border-top: var(--border-w) solid var(--border-default);
    display: flex;
    align-items: center;
    gap: var(--space-4);
    min-width: 0;
}

.nav-footer-id {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1;
}

.nav-footer-name {
    font-size: var(--fs-label);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The role line is secondary information — --text-label, never --text-tertiary (2.56:1). */
.nav-footer-role {
    font-size: var(--fs-eyebrow);
    color: var(--text-label);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nav-logout {
    display: flex;
}

/* Top-bar search: inert in ZiePieHRApp, inert here — reproduced for parity of chrome. */
.topbar-search {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: 0 var(--space-6);
    height: var(--control-h-sm);
    border: var(--border-w) solid var(--border-default);
    border-radius: var(--radius-pill);
    color: var(--text-label);
    font-size: var(--fs-body-sm);
    background: var(--surface-secondary);
}

/* Presence dot on the top-bar avatar. Signed-in reads as the success token. */
.presence-wrap {
    position: relative;
}

.presence-dot {
    position: absolute;
    right: -1px;
    bottom: -1px;
    width: 9px;
    height: 9px;
    border-radius: var(--radius-pill);
    background: var(--status-success);
    border: 2px solid var(--surface-primary);
}

.portal-user {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    min-width: 0;
}

.portal-user-name {
    font-size: var(--fs-label);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 260px;
}

.nav-burger {
    display: none;
}

/* Theme toggle — one glyph per choice; the button carries data-choice (set by site.js). */
.theme-toggle .i-moon,
.theme-toggle .i-system {
    display: none;
}

.theme-toggle[data-choice="dark"] .i-sun,
.theme-toggle[data-choice="system"] .i-sun {
    display: none;
}

.theme-toggle[data-choice="dark"] .i-moon,
.theme-toggle[data-choice="system"] .i-system {
    display: inline-flex;
}

@media (max-width: 880px) {
    .nav-burger {
        display: inline-flex;
    }

    .portal-sidebar {
        position: fixed;
        top: var(--top-nav-height);
        bottom: 0;
        left: 0;
        z-index: 30;
        transform: translateX(-100%);
        transition: transform var(--transition-fast);
        box-shadow: var(--shadow-drawer);
    }

    .portal-sidebar.is-open {
        transform: none;
    }
}

/* ── Page canvas: every screen lines up with every other ─────────────────────
   The centred column (.page-wrap, max-width 1180px, margin: 0 auto) is the design
   system's own layout and is kept as-is. What made screens disagree was the SCROLLBAR:
   .portal-main scrolls, so a long page lost ~15px of width to the scrollbar and its
   centred content sat left of a short page's. Reserving the gutter permanently makes
   a scrolling page and a short one start at the identical x-position.

   Any new screen inherits this by rendering inside MainLayout — pages must not set
   their own outer padding, margin, or max-width. */
.portal-main {
    scrollbar-gutter: stable;
}

/* ── Page header (reference: .page-title / .page-sub) ────────────────────── */
.page-title {
    font-family: var(--font-display);
    font-weight: var(--fw-medium);
    font-size: var(--fs-page-title);
    letter-spacing: var(--ls-display);
    color: var(--text-primary);
}

.page-sub {
    font-size: 13.5px;
    color: var(--text-secondary);
    margin-top: 3px;
    max-width: 62ch;
}

/* Sub-heading inside a page body (below .page-title). */
.section-title {
    font-family: var(--font-display);
    font-weight: var(--fw-semibold);
    font-size: var(--fs-card-title);
    color: var(--text-primary);
    margin: var(--space-11) 0 var(--space-4);
}

/* ── List toolbar (search + count) ───────────────────────────────────────── */
.list-toolbar {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    margin-bottom: var(--space-5);
}

.list-toolbar .input-search {
    width: 300px;
}

.count-label {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: var(--ls-chip);
    color: var(--text-label);
}

.list-toolbar.wrap {
    flex-wrap: wrap;
    align-items: flex-end;
}

.filter-field {
    display: flex;
    flex-direction: column;
}

.filter-field .form-select,
.filter-field .form-input {
    min-width: 170px;
}

/* ── Utilities the reference leans on ────────────────────────────────────── */
/* .row / .row-between / .stack are the design system's own flex utilities
   (ds/tokens/components.css). Only the wrap modifier is added here.
   Historical note: these were temporarily renamed .zrow while Bootstrap was still
   loaded — its grid owned .row, and its `.row > *` rule (width: 100%) outranked a bare
   .row, stretching every chip, tag and icon button to full cell width. Bootstrap is
   gone, so the DS-native names are back. */
.row.wrap {
    flex-wrap: wrap;
}

/* Modal helpers */
.modal-title {
    font-family: var(--font-display);
    font-weight: var(--fw-semibold);
    font-size: var(--fs-drawer-title);
    color: var(--text-primary);
}

/* Titled modal (Modal.razor): the DS ships .modal-card/.modal-body/.modal-foot but no
   header row, because its own modals are confirmations. Team Hub's are forms. */
.modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding: 18px 24px 0;
}

.modal-card.is-wide {
    width: min(560px, 100%);
}

/* Stacked form fields inside a modal body. */
.modal-body .field-stack {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

/* One checkbox row in a list of them — the invite/edit modals' role picker. */
.check-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: 4px 0;
    font-size: 13px;
    cursor: pointer;
}

.check-row .check-name {
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

.check-row .check-desc {
    font-size: 11.5px;
    color: var(--text-label);
}

.delete-head {
    align-items: flex-start;
    gap: var(--space-6);
}

.delete-head .empty-icon {
    margin-bottom: 0;
}

.empty-icon.is-danger {
    background: var(--status-danger-soft);
    color: var(--status-danger-text);
}

.blocked-note {
    margin-top: var(--space-6);
}

/* Danger-toned ghost icon button (row delete actions). */
.btn.is-danger-tone {
    color: var(--text-danger);
}

.btn.is-danger-tone:hover:not(:disabled) {
    background: var(--status-danger-soft);
    color: var(--status-danger-text);
}

.mono {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
}

.muted {
    color: var(--text-label);
}

.eyebrow {
    font: var(--type-label);
    letter-spacing: var(--ls-eyebrow);
    text-transform: uppercase;
    color: var(--text-label);
}

/* Card wrapper for a .data-table. A wide table (the audit log's seven columns) scrolls
   HORIZONTALLY INSIDE its own card — the page itself must never scroll sideways, which
   would drag the header and rail out of view. overflow-x on the card both enables that
   scroll and clips the table's corners to the radius. */
.table-card {
    background: var(--surface-primary);
    border: var(--rule);
    border-radius: var(--radius-lg);
    overflow-x: auto;
    overflow-y: hidden;
}

/* The minimum is the table's own natural content width (the audit log's seven columns
   measure ~810px). Below that the columns would squeeze instead of scrolling; at or above
   it the card simply fits and shows no scrollbar. Never guess this number lower than the
   content — a too-small minimum silently disables the scroll it was meant to provide. */
.table-card .data-table {
    min-width: 810px;
}

.cell-title {
    font-size: 13.5px;
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

.cell-sub {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--text-label);
}

/* ── Role editor: grouped permission accordions ──────────────────────────── */
.field-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--space-7);
}

.perm-search {
    width: 260px;
}

.feat-title {
    flex: 1;
    min-width: 0;
    gap: 1px;
}

.summary-count {
    align-items: baseline;
    margin: var(--space-3) 0 var(--space-5);
}

/* Page-level notices between the header and the content (RoleEdit's cascade + system-role
   banners). Without this they sat flush against both, breaking the 22px page rhythm every
   other screen keeps. */
.banner {
    margin-bottom: var(--space-5);
}

.page-head + .banner {
    margin-top: calc(-1 * var(--space-2));
}

.role-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: var(--space-10);
    align-items: start;
    margin-top: var(--space-10);
}

.role-summary {
    position: sticky;
    top: calc(var(--top-nav-height) + var(--space-7));
}

.feat-group {
    border: var(--rule);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.feat-group + .feat-group {
    margin-top: var(--space-4);
}

.feat-head {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    width: 100%;
    padding: var(--space-5) var(--space-6);
    border: 0;
    background: var(--surface-secondary);
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}

.feat-head .caret {
    transition: transform var(--transition-fast);
    color: var(--text-label);
    flex: none;
}

.feat-group.is-open .feat-head .caret {
    transform: rotate(90deg);
}

.feat-name {
    font-size: 13.5px;
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

.feat-desc {
    font-size: var(--text-xs);
    color: var(--text-label);
}

.feat-body {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: var(--space-3);
    padding: var(--space-5) var(--space-6);
    background: var(--surface-primary);
}

.perm-check {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    border: var(--rule);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: var(--transition-control);
}

.perm-check:hover {
    border-color: var(--border-strong);
}

.perm-check.is-checked {
    border-color: var(--brand-primary);
    background: var(--brand-primary-soft);
}

.perm-key {
    font-family: var(--font-mono);
    font-size: 9.5px;
    letter-spacing: .03em;
    color: var(--text-label);
}

.pill-count {
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: var(--fw-semibold);
    padding: 2px 8px;
    border-radius: var(--radius-pill);
    background: var(--surface-tertiary);
    color: var(--text-secondary);
    white-space: nowrap;
}

.perm-summary-chip {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-3) 0;
    border-top: var(--rule);
    font-size: var(--fs-body-sm);
}

.perm-summary-chip .acts {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--text-label);
    text-align: right;
}

/* ── User detail: layout + effective access + overrides ──────────────────── */
.detail-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));
    gap: var(--space-9);
    align-items: start;
}

.col-stack {
    gap: var(--space-9);
}

.card-pad {
    padding: var(--space-6) var(--space-8);
}

.card-pad > .page-sub {
    margin: 0 0 var(--space-5);
}

.overflow-visible {
    overflow: visible;
}

.click-catcher {
    position: fixed;
    inset: 0;
    z-index: 39;
}

.acc-text {
    font-size: var(--fs-body-sm);
    color: var(--text-secondary);
}

.acc-expiry {
    font-family: var(--font-mono);
    font-size: 10.5px;
    color: var(--text-label);
}

.mode-chip {
    font-family: var(--font-mono);
    font-size: 9px;
    font-weight: var(--fw-semibold);
    text-transform: uppercase;
    letter-spacing: .06em;
    padding: 2px 7px;
    border-radius: var(--radius-pill);
    background: var(--brand-primary-soft);
    color: var(--brand-on-soft);
    white-space: nowrap;
}

.mode-chip.is-block {
    background: var(--status-danger-soft);
    color: var(--status-danger-text);
}


.acc-line {
    display: flex;
    align-items: baseline;
    gap: var(--space-4);
    padding: var(--space-4) 0;
    border-top: var(--rule);
    font-size: var(--fs-body-sm);
}

.acc-line:first-of-type {
    border-top: 0;
}

.acc-feature {
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
    min-width: 110px;
}

.acc-badge {
    font-family: var(--font-mono);
    font-size: 9px;
    font-weight: var(--fw-semibold);
    text-transform: uppercase;
    letter-spacing: .06em;
    padding: 2px 7px;
    border-radius: var(--radius-sm);
    white-space: nowrap;
}

.acc-badge.via-role {
    background: var(--brand-primary-soft);
    color: var(--brand-on-soft);
}

.acc-badge.via-override {
    background: var(--brand-accent-soft);
    color: var(--tint-violet-fg);
}

.acc-badge.via-none {
    background: var(--surface-tertiary);
    color: var(--text-label);
}

.res-card {
    border: var(--rule);
    border-radius: var(--radius-md);
    padding: var(--space-5) var(--space-6);
    background: var(--surface-primary);
}

.res-card + .res-card {
    margin-top: var(--space-4);
}

.res-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
}

.res-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-7);
    margin-top: var(--space-4);
}

.act-cell {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--fs-body-sm);
    color: var(--text-secondary);
}

.intent-card {
    display: flex;
    align-items: flex-start;
    gap: var(--space-4);
    padding: var(--space-5) var(--space-6);
    border: var(--rule);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: var(--transition-control);
}

.intent-card:hover {
    border-color: var(--border-strong);
}

.intent-card.is-selected {
    border-color: var(--brand-primary);
    background: var(--brand-primary-soft);
}

.search-result {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    width: 100%;
    padding: var(--space-4) var(--space-5);
    border: 0;
    border-radius: var(--radius-md);
    background: none;
    font-family: inherit;
    font-size: var(--fs-body-sm);
    text-align: left;
    cursor: pointer;
}

.search-result:hover {
    background: var(--surface-secondary);
}

/* ── My Dashboard: attendance status hero + stat strip ────────────────────────
   Layered on the design system's .config-section card. The four attendance
   states map onto DS STATUS tokens rather than ZiePieHRApp's own palette (plan
   §6.1): signed in → success, on break → warning, signed out → neutral border,
   off today → the violet accent. */
/* .config-section is a padding-FREE shell: the design system's own children
   (.config-section-head, .config-row) each supply their own inset. Anything else placed
   directly inside therefore sits flush against the border. This is the padded body for
   screens that put their own content in a section card. */
.config-body {
    padding: var(--space-6) var(--space-7);
}

/* A body that stacks its children (the role editor's permission rows). */
.config-body.is-stacked {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.status-hero {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-6);
    padding: var(--space-7);
    border-left: 3px solid var(--border-strong);
}

.status-hero.is-in {
    border-left-color: var(--status-success);
}

.status-hero.is-break {
    border-left-color: var(--status-warning);
}

.status-hero.is-off {
    border-left-color: var(--brand-primary);
}

.status-hero .eyebrow {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

.status-hero .status-dot {
    width: 9px;
    height: 9px;
    border-radius: var(--radius-pill);
    background: var(--text-label);
}

.status-hero.is-in .status-dot {
    background: var(--status-success);
}

.status-hero.is-break .status-dot {
    background: var(--status-warning);
}

.status-hero.is-off .status-dot {
    background: var(--brand-primary);
}

.hero-label {
    font-family: var(--font-display);
    font-weight: var(--fw-medium);
    font-size: var(--fs-page-title);
    color: var(--text-primary);
}

.hero-detail {
    font-size: var(--fs-body-sm);
}

.hero-actions {
    align-items: flex-start;
    gap: var(--space-4);
}

.hero-actions .gate {
    gap: var(--space-2);
}

/* The reason a button is disabled, printed under it — the tooltip alone is not
   reachable by keyboard or touch, and this sentence is the whole explanation. */
.gate-reason {
    font-size: var(--fs-eyebrow);
    color: var(--text-label);
    max-width: 34ch;
}

.break-picker {
    gap: var(--space-2);
}

/* ── Day-at-a-glance strip ───────────────────────────────────────────────── */
.stat-strip {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--space-4);
    margin-top: var(--space-5);
}

.stat {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--space-5);
    background: var(--surface-primary);
    border: var(--border-w) solid var(--border-default);
    border-radius: var(--radius-lg);
}

.stat.is-accent {
    border-color: var(--brand-primary);
}

.stat-k {
    font-size: var(--fs-eyebrow);
    letter-spacing: var(--ls-chip);
    text-transform: uppercase;
    color: var(--text-label);
}

.stat-v {
    font-size: var(--fs-card-title);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

.stat-sub {
    font-size: var(--fs-eyebrow);
    color: var(--text-label);
    min-height: 1em;
}

.stat-sub.is-late {
    color: var(--text-danger);
}

/* ── Setting row (Policy Settings, Integration) ──────────────────────────────
   Label + explanation on the left, control on the right. The DS's own .config-row
   is a fixed 200px grid built for read-only key/value pairs; these rows carry real
   inputs of differing widths, so they use flex and let the control size itself. */
.setting-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-6);
    padding: var(--space-4) 0;
    border-bottom: var(--border-w) solid var(--border-default);
}

.setting-row:last-child {
    border-bottom: 0;
}

.setting-label {
    font-size: var(--fs-label);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

.setting-desc {
    font-size: var(--fs-eyebrow);
    color: var(--text-label);
}

.setting-control {
    flex: none;
}

.setting-control .form-input,
.setting-control .form-select {
    width: auto;
    min-width: 130px;
}

/* A bare checkbox needs a hit target of its own once it leaves a .chk label. */
.chk-wrap {
    display: inline-flex;
    align-items: center;
    cursor: pointer;
}

/* ── Teams & Departments: card list + detail pane ─────────────────────────────
   ZiePieHRApp's 1.3 : 1 split. It collapses at the width where the detail pane's
   own fields start to wrap, not at a device breakpoint. */
.team-layout {
    display: grid;
    grid-template-columns: 1.3fr 1fr;
    gap: var(--space-9);
    align-items: start;
}

@media (max-width: 900px) {
    .team-layout {
        grid-template-columns: 1fr;
    }
}

.team-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
}

/* A <button>, not a clickable <div>: selecting a team is a control, so it has to be
   reachable by keyboard and announced as one. */
.team-card {
    display: block;
    width: 100%;
    padding: var(--space-5) var(--space-6);
    border: var(--rule);
    border-left: 3px solid transparent;
    border-radius: var(--radius-md);
    background: var(--surface-primary);
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    transition: var(--transition-control);
}

.team-card:hover {
    border-color: var(--border-strong);
    border-left-color: var(--border-strong);
}

.team-card.is-selected {
    border-color: var(--brand-primary);
    border-left-color: var(--brand-primary);
    background: var(--brand-primary-soft);
}

.team-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    flex: none;
    border-radius: var(--radius-md);
    background: var(--surface-tertiary);
    color: var(--text-label);
}

.team-card-body {
    flex: 1;
    min-width: 0;
}

.team-name {
    font-weight: var(--fw-semibold);
    font-size: var(--fs-body);
    color: var(--text-primary);
}

.team-desc {
    font-size: var(--fs-body-sm);
    color: var(--text-secondary);
}

.team-lead {
    margin-top: var(--space-3);
    font-size: var(--fs-eyebrow);
    color: var(--text-label);
}

.member-row {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-4) 0;
    border-bottom: var(--border-w) solid var(--border-default);
}

.member-row:last-child {
    border-bottom: 0;
}

.member-name {
    flex: 1;
    font-size: var(--fs-body-sm);
    color: var(--text-primary);
}

/* The design system's .role-tag is brand-tinted, which Team Hub reserves for a Manager or
   above; an Employee's tag is neutral so the tinted ones actually stand out. */
.role-tag.is-quiet {
    background: var(--surface-tertiary);
    color: var(--text-secondary);
}

/* ── Teams Integration: routing table beside the channel + reminder cards ──────
   ZiePieHRApp's 1.5 : 1 split, collapsing at the width where the routing table's
   four columns stop fitting beside a second column. */
.integration-layout {
    display: grid;
    grid-template-columns: 1.5fr 1fr;
    gap: var(--space-9);
    align-items: start;
}

@media (max-width: 1000px) {
    .integration-layout {
        grid-template-columns: 1fr;
    }
}

/* A routing rule that is switched off still shows its settings — dimming says "not in
   force" without hiding what it would do if it were turned back on. */
.data-table tbody tr.is-off td {
    opacity: 0.55;
}

.data-table tbody tr.is-off td:last-child {
    opacity: 1;
}

/* ── Timesheet: day grid beside the heat-map ─────────────────────────────────── */
.timesheet-layout {
    display: grid;
    grid-template-columns: 1.6fr 1fr;
    gap: var(--space-9);
    align-items: start;
}

@media (max-width: 1000px) {
    .timesheet-layout {
        grid-template-columns: 1fr;
    }
}

.data-table tbody tr.is-clickable {
    cursor: pointer;
}

.data-table tbody tr.is-clickable:hover {
    background: var(--surface-secondary);
}

/* A day with a missed punch. The left rule marks it without recolouring the whole row,
   which would fight the hover state. */
.data-table tbody tr.is-flagged td:first-child {
    box-shadow: inset 3px 0 0 var(--status-danger);
}

.td-chevron {
    width: 28px;
}

.chevron {
    color: var(--text-label);
    transition: transform var(--transition-fast);
}

.chevron.is-open {
    transform: rotate(90deg);
}

.data-table tbody tr.detail-row > td {
    background: var(--surface-secondary);
}

/* ── Activity timeline (timesheet detail, team day detail) ───────────────────── */
.timeline {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.timeline-row {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    font-size: var(--fs-body-sm);
}

.timeline-dot {
    width: 8px;
    height: 8px;
    flex: none;
    border-radius: var(--radius-pill);
    background: var(--text-label);
}

.timeline-dot.is-in {
    background: var(--status-success);
}

.timeline-dot.is-out {
    background: var(--text-label);
}

.timeline-dot.is-break {
    background: var(--status-warning);
}

.timeline-dot.is-work {
    background: var(--brand-primary);
}

.timeline-label {
    flex: 1;
    color: var(--text-primary);
}

.timeline-time,
.timeline-dur {
    font-size: var(--fs-eyebrow);
    color: var(--text-label);
    white-space: nowrap;
}

.timeline-dur {
    min-width: 64px;
    text-align: right;
}

/* ── Attendance heat-map ──────────────────────────────────────────────────────
   Five buckets of net hours against the 8-hour standard day, plotted from the SAME
   days the grid shows. Level -1 is padding outside the loaded range. */
.heat {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.heat-row {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 4px;
}

.heat-cell {
    aspect-ratio: 1;
    border-radius: 3px;
    background: var(--surface-tertiary);
}

.heat-cell.heat--1 {
    background: transparent;
}

.heat-cell.heat-0 {
    background: var(--surface-tertiary);
}

.heat-cell.heat-1 {
    background: color-mix(in oklab, var(--status-success) 25%, var(--surface-tertiary));
}

.heat-cell.heat-2 {
    background: color-mix(in oklab, var(--status-success) 50%, var(--surface-tertiary));
}

.heat-cell.heat-3 {
    background: color-mix(in oklab, var(--status-success) 75%, var(--surface-tertiary));
}

.heat-cell.heat-4 {
    background: var(--status-success);
}

.heat-legend {
    margin-top: var(--space-4);
    font-size: var(--fs-eyebrow);
}

.heat-spacer {
    flex: 1;
}

/* ── My Tasks: list beside the detail pane ───────────────────────────────────── */
.task-layout {
    display: grid;
    grid-template-columns: 1.3fr 1fr;
    gap: var(--space-9);
    align-items: start;
}

@media (max-width: 1000px) {
    .task-layout {
        grid-template-columns: 1fr;
    }
}

.tasklist {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.taskrow {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    border-left: 3px solid transparent;
    cursor: pointer;
}

.taskrow:hover {
    background: var(--surface-secondary);
}

.taskrow.is-selected {
    background: var(--brand-primary-soft);
    border-left-color: var(--brand-primary);
}

.taskrow.is-done .taskrow-title {
    color: var(--text-label);
    text-decoration: line-through;
}

.taskrow-title {
    flex: 1;
    font-size: var(--fs-body-sm);
    color: var(--text-primary);
}

.taskrow-move {
    display: flex;
    gap: var(--space-2);
}

/* The tick box. A real <button>, so completing a task is reachable without the mouse. */
.task-check {
    width: 18px;
    height: 18px;
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: var(--border-w) solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface-primary);
    color: var(--surface-primary);
    cursor: pointer;
}

.task-check:hover {
    border-color: var(--brand-primary);
}

.task-check.is-checked {
    background: var(--status-success);
    border-color: var(--status-success);
    color: #fff;
}

/* Priority tag. Three levels, mapped onto DS status tones rather than a private palette. */
.prio-tag {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: var(--radius-pill);
    font-size: 10.5px;
    font-weight: var(--fw-semibold);
    text-transform: uppercase;
    letter-spacing: .04em;
    white-space: nowrap;
}

.prio-tag.is-high {
    background: var(--status-danger-soft);
    color: var(--status-danger-text);
}

.prio-tag.is-medium {
    background: var(--status-warning-soft);
    color: var(--status-warning-text);
}

.prio-tag.is-low {
    background: var(--surface-tertiary);
    color: var(--text-secondary);
}

.row.space-between {
    justify-content: space-between;
    width: 100%;
}

.tradeoff-note {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-5);
    border-left: 3px solid var(--status-danger);
    border-radius: var(--radius-md);
    background: var(--status-danger-soft);
}

.tradeoff-row {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    font-size: var(--fs-body-sm);
}

.comments {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.comment {
    display: flex;
    align-items: flex-start;
    gap: var(--space-4);
}

.comment-body {
    font-size: var(--fs-body-sm);
    color: var(--text-primary);
}

/* ── Time Off: balances beside the request form ──────────────────────────────── */
.timeoff-layout {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-9);
    align-items: start;
}

@media (max-width: 1000px) {
    .timeoff-layout {
        grid-template-columns: 1fr;
    }
}

.balance {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.balance-name {
    font-weight: var(--fw-semibold);
    font-size: var(--fs-body-sm);
    color: var(--text-primary);
}

/* A balance bar: how much of the year's accrual is already spent. */
.progress {
    height: 6px;
    border-radius: var(--radius-pill);
    background: var(--surface-tertiary);
    overflow: hidden;
}

/* --fill is set inline by the page (the one inline form the guardrail allows: a runtime
   value carried on a custom property, never a hard-coded declaration). */
.progress > span {
    display: block;
    height: 100%;
    width: var(--fill, 0%);
    background: var(--brand-primary);
}

.history {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.history-row {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-4) 0;
    border-bottom: var(--border-w) solid var(--border-default);
}

.history-row:last-child {
    border-bottom: 0;
}

.history-main {
    flex: 1;
    min-width: 0;
}

.history-title {
    font-size: var(--fs-body-sm);
    font-weight: var(--fw-medium);
    color: var(--text-primary);
}

/* ── Dashboard: focus clock, activity table and the task panel ───────────────── */
.dash-grid {
    display: grid;
    grid-template-columns: 1.4fr 1fr;
    gap: var(--space-9);
    align-items: start;
    margin-top: var(--space-9);
}

@media (max-width: 1000px) {
    .dash-grid {
        grid-template-columns: 1fr;
    }
}

.focus-label {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    font-weight: var(--fw-semibold);
    font-size: var(--fs-body);
    color: var(--text-primary);
}

/* The running thing gets the brand tint; everything else stays quiet. */
.pill-count.is-active {
    background: var(--brand-primary-soft);
    color: var(--brand-on-soft);
}

.breakdown-key {
    min-width: 110px;
}

.dash-task {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-3) 0;
    border-bottom: var(--border-w) solid var(--border-default);
}

.dash-task:last-of-type {
    border-bottom: 0;
}

.dash-task-title {
    flex: 1;
    font-size: var(--fs-body-sm);
    color: var(--text-primary);
}

/* The focus picker's task list. Capped so a long backlog scrolls inside the dialog
   rather than pushing its footer off the screen. */
.focus-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    max-height: 240px;
    overflow-y: auto;
}

.focus-option {
    justify-content: flex-start;
    width: 100%;
    text-align: left;
}

/* ── Approvals queue ─────────────────────────────────────────────────────────── */
.approval-row {
    display: flex;
    align-items: center;
    gap: var(--space-5);
    padding: var(--space-5) 0;
    border-bottom: var(--border-w) solid var(--border-default);
}

.approval-row:last-child {
    border-bottom: 0;
}

.approval-main {
    flex: 1;
    min-width: 0;
}

.approval-name {
    font-weight: var(--fw-semibold);
    font-size: var(--fs-body-sm);
    color: var(--text-primary);
}

/* ── Team Tasks board ────────────────────────────────────────────────────────── */
.board {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-6);
    align-items: start;
}

@media (max-width: 1000px) {
    .board {
        grid-template-columns: 1fr;
    }
}

.board-column {
    min-width: 0;
}

.board-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    border: var(--rule);
    border-radius: var(--radius-md);
    background: var(--surface-primary);
}

.board-title {
    font-weight: var(--fw-medium);
    font-size: var(--fs-body-sm);
    color: var(--text-primary);
}

/* ── Team Dashboard: roster, insights feed, session cards ────────────────────── */
.team-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: var(--space-6);
    align-items: start;
    margin-top: var(--space-6);
}

.roster-row {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-3) 0;
    border-bottom: var(--border-w) solid var(--border-default);
}

.roster-row:last-child {
    border-bottom: 0;
}

.roster-main {
    flex: 1;
    min-width: 0;
}

.roster-name {
    font-weight: var(--fw-semibold);
    font-size: var(--fs-body-sm);
    color: var(--text-primary);
}

.roster-figures {
    text-align: right;
    font-size: var(--fs-eyebrow);
}

.feed-item {
    display: flex;
    align-items: flex-start;
    gap: var(--space-4);
    padding: var(--space-4) 0;
    border-bottom: var(--border-w) solid var(--border-default);
}

.feed-item:last-child {
    border-bottom: 0;
}

.feed-body {
    flex: 1;
    min-width: 0;
}

.feed-msg {
    font-size: var(--fs-body-sm);
    color: var(--text-primary);
}

.feed-tasks {
    margin: var(--space-2) 0 0;
    padding-left: var(--space-6);
    font-size: var(--fs-body-sm);
    color: var(--text-secondary);
}

.session-card + .session-card {
    margin-top: var(--space-6);
}

/* ── Team Attendance: the status matrix ───────────────────────────────────────
   One column per day. It scrolls inside its own card (the .table-card already
   sets overflow-x) rather than making the page scroll sideways. */
.matrix-head {
    text-align: center;
    min-width: 30px;
}

.matrix-cell {
    text-align: center;
}

.day-dot {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 3px;
    background: var(--surface-tertiary);
}

.day-dot.is-present {
    background: var(--status-success);
}

.day-dot.is-late {
    background: var(--status-warning);
}

.day-dot.is-absent {
    background: var(--status-danger);
}

.day-dot.is-off {
    background: var(--surface-tertiary);
    border: var(--border-w) solid var(--border-default);
}

.matrix-legend {
    margin-top: var(--space-5);
}

.legend-item {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin-right: var(--space-6);
    font-size: var(--fs-eyebrow);
    color: var(--text-label);
}

/* ── Notifications: the bell, the nav badges and the feed ────────────────────── */
.bell {
    position: relative;
}

/* The count rides the bell's corner. It is a live region only in the sense that it
   re-renders — announcing every poll would be noise, so the link's title carries the
   readable version. */
.bell-count {
    position: absolute;
    top: 2px;
    right: 2px;
    min-width: 15px;
    height: 15px;
    padding: 0 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    background: var(--status-danger);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 9.5px;
    font-weight: var(--fw-semibold);
    line-height: 1;
}

.nav-badge {
    margin-left: auto;
    min-width: 18px;
    padding: 1px 6px;
    border-radius: var(--radius-pill);
    background: var(--brand-primary-soft);
    color: var(--brand-on-soft);
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: var(--fw-semibold);
    text-align: center;
}

.notif-card {
    max-width: 760px;
}

/* A row is a <button>: marking one read is an action, so it must be reachable by keyboard. */
.notif-row {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    width: 100%;
    padding: var(--space-4);
    border: 0;
    border-left: 3px solid transparent;
    border-radius: var(--radius-md);
    background: none;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}

.notif-row:hover {
    background: var(--surface-secondary);
}

.notif-row.is-unread {
    border-left-color: var(--brand-primary);
    background: var(--brand-primary-soft);
}

.notif-main {
    flex: 1;
    min-width: 0;
}

.notif-title {
    font-weight: var(--fw-semibold);
    font-size: var(--fs-body-sm);
    color: var(--text-primary);
}

.unread-dot {
    width: 7px;
    height: 7px;
    border-radius: var(--radius-pill);
    background: var(--brand-primary);
}

/* Notification tones, carried on the row so a message keeps the colour it was written with. */
.tone-dot {
    width: 10px;
    height: 10px;
    flex: none;
    border-radius: var(--radius-pill);
    background: var(--text-label);
}

.tone-dot.tone-in {
    background: var(--status-success);
}

.tone-dot.tone-break {
    background: var(--status-warning);
}

.tone-dot.tone-leave {
    background: var(--brand-primary);
}

.tone-dot.tone-danger {
    background: var(--status-danger);
}

.tone-dot.tone-accent {
    background: var(--brand-accent);
}

/* ── Reports: the daily present-vs-late chart ─────────────────────────────────
   --h is set inline by the page (the one inline form the guardrail allows: a runtime
   value on a custom property). Bars stack late ON TOP of present, so the column's
   height is the day's headcount and the warning band is the part that ran late. */
.report-layout {
    display: grid;
    grid-template-columns: 1.5fr 1fr;
    gap: var(--space-9);
    align-items: start;
}

@media (max-width: 1000px) {
    .report-layout {
        grid-template-columns: 1fr;
    }
}

.chart {
    display: flex;
    align-items: flex-end;
    gap: var(--space-3);
    min-height: 140px;
    overflow-x: auto;
}

.chart-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    flex: 1;
    min-width: 28px;
}

.chart-stack {
    display: flex;
    flex-direction: column-reverse;
    justify-content: flex-start;
    width: 100%;
    max-width: 26px;
}

.chart-present,
.chart-late {
    display: block;
    width: 100%;
    height: var(--h, 0);
}

.chart-present {
    background: var(--status-success);
    border-radius: 0 0 3px 3px;
}

.chart-late {
    background: var(--status-warning);
    border-radius: 3px 3px 0 0;
}

.chart-label {
    font-size: var(--fs-eyebrow);
    color: var(--text-label);
    white-space: nowrap;
}

.chart-legend {
    margin-top: var(--space-5);
}
