
/* The plain list's scroll box inside the viewport-fit roster card — the list
   layout's .global-grid-wrap. The card (#list-container) is a .global-page-fill
   flex column (main.css), so this wrap takes the height flex hands it and
   scrolls the rows inside; a short roster leaves the card reaching the bottom
   of the screen with room to spare. */
.workers-list-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
}

.workers-list-table {
    table-layout: auto;
    font-size: var(--font-size-lg);
}

.workers-list-table td {
    padding: var(--spacing-smd) var(--spacing-smd);
    vertical-align: middle;
}

.workers-list-table .workers-col-name {
    white-space: nowrap;
    width: 1%;  /* Shrink to fit content */
    font-size: var(--font-size-base);
}

/* ── The person cell ── photo, name, and everything true *about* the person.
   Work status is a dot on the photo and a payout problem is a chip beside the
   name, so neither fact costs a column of its own; the same arrangement the
   bills dashboard uses, kept identical so a state means one thing everywhere. */
.workers-list-table .workers-row__person {
    display: flex;
    align-items: center;
    gap: var(--spacing-smd);
}

.workers-list-table .workers-row__portrait {
    position: relative;
    flex: 0 0 auto;
    display: flex;
}

/* Tucked into the photo's lower-right, with a card-coloured collar so the dot
   reads as its own mark instead of a smudge on the edge of the picture. The
   collar is an outline, not a border: the dot component already spends its
   border on the state colour, and an outline costs the layout nothing. */
.workers-list-table .workers-row__status-dot {
    position: absolute;
    right: -1px;
    bottom: -1px;
    outline: 2px solid var(--color-card-bg);
    outline-offset: 0;
}

.workers-list-table .workers-row__ident {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
    min-width: 0;
}

.workers-list-table .workers-row__name-row {
    display: flex;
    align-items: center;
    gap: var(--spacing-xsm);
}

.workers-list-table .workers-row__email {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}

.workers-list-table .workers-col-skills {
}

.workers-list-table .workers-col-skills .badge {
    font-size: var(--font-size-sm);
    padding: 0.35em 0.65em;
}

.workers-list-table .workers-col-contact {
    width: 80px;
    white-space: nowrap;
}

.workers-list-table .workers-col-contact .global-btn-icon-copy,
.workers-list-table .workers-col-contact .global-btn-icon-placeholder {
    width: 32px;
    height: 32px;
    font-size: var(--font-size-base);
}

/* Placeholder icon for missing contact info */
.global-btn-icon-placeholder {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    color: var(--color-border);
    opacity: 0.4;
}

@media (max-width: 767.98px) {
    .workers-list-table .workers-col-name {
        white-space: normal;
        min-width: 120px;
    }
}

/* Card chrome comes from the canonical .card recipe in main.css; only the
   detail page's roomier header padding and brand icon tint live here. */
.workers-detail .card-header {
    padding: var(--spacing-smd) var(--spacing-mdlg);
}

.workers-detail .card-header .bi {
    color: var(--color-action);
}

.workers-hero-body {
    display: flex;
    align-items: center;
    gap: var(--spacing-mdlg);
    padding: var(--spacing-lg) var(--spacing-lg);
}

/* Worker hero face — DELETED. The 104px circle, its img cascade, the brand
   gradient behind the initials, and the halo ring all moved to the atom:
   `.global-avatar .global-avatar--xl .global-avatar--ring` (+ `--gradient` for
   the initials case). 104px IS the platform's single --xl hero step, so the
   hero renders unchanged. Only the lightbox button reset stays — that is button
   chrome, not avatar geometry. */
.workers-hero-avatar--button {
    padding: 0;
    border: 0;
    background: transparent;
    cursor: zoom-in;
}

.workers-hero-meta {
    min-width: 0;
    flex: 1;
}

.workers-hero-name-row {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    flex-wrap: wrap;
}

.workers-hero-name {
    font-size: 1.75rem;
    font-weight: var(--font-weight-medium);
    margin: 0;
}

.workers-hero-eyebrow {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    flex-wrap: wrap;
    margin-top: var(--spacing-xsm);
    font-size: var(--font-size-md);
    color: var(--color-text-muted);
}

.workers-bio {
    font-size: var(--font-size-md);
    color: var(--color-text-muted);
}

.workers-hero-actions {
    margin-left: auto;
    /* Sit at the top of the meta block so the buttons line up with the name
       row, not the centered bio. */
    align-self: flex-start;
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    flex: 0 0 auto;
}

.workers-hero-actions #worker-status-actions {
    display: flex;
    gap: var(--spacing-sm);
}

.workers-tabs {
    margin-top: var(--spacing-lg);
}

/* The name on a skill row. */
.workers-ability-name {
    font-weight: var(--font-weight-medium);
}

/* The add row sits under the rows as a quiet footer strip. */
.workers-ability-add {
    padding-top: var(--spacing-smd);
    border-top: 1px solid var(--color-border);
}

@media (max-width: 575.98px) {
    .workers-hero-body {
        flex-wrap: wrap;
    }

    .workers-hero-actions {
        margin-left: 0;
        width: 100%;
    }
}

.workers-files-help {
    padding: var(--spacing-sm) var(--spacing-md) 0;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}

/* ===== Worker profile shell (one-scroll admin layout) ==================
   Three zones: rail (who they are) / feed (what happened) / side (what
   they can do + files). The rails stick and scroll on their own so the
   feed column owns the page's scrollbar.

   Columns follow the shell's own width, never the window's (the container
   blocks under Breakpoints): under 1200px of room the side cards stack
   under the rail; under 768px everything is one column.

   The Details toggle is a different rule and reads the window: on a phone
   (under 768px) the rail's detail cards collapse behind it. Wider screens
   hold them open whatever Alpine last set (the min-width block), so a
   one-column shell beside a drawer on a desktop still shows every card. */

.workers-profile-shell {
    display: grid;
    /* Rails grow with the screen (keeping their 264:300 proportion) so a
       wide monitor widens all three zones instead of handing every spare
       pixel to the feed column. */
    grid-template-columns: minmax(264px, 1fr) minmax(560px, 2fr) minmax(300px, 1.15fr);
    gap: var(--spacing-md);
    align-items: start;
}

.workers-profile-rail,
.workers-profile-side {
    position: sticky;
    /* Pin exactly where the column rests — the sticky header's own offset
       plus .global-app-content's top padding — so scrolling never visibly slides
       the columns before they stick. The bottom reserve must equal the
       content gutter too: a shorter reserve makes the column outrun its
       grid slack by the difference, and the page's last few scrolled
       pixels drag the rails up by exactly that much. */
    top: calc(var(--header-bottom) + var(--page-gutter));
    max-height: calc(100vh - var(--header-bottom) - var(--bottom-bar-h) - 2 * var(--page-gutter));
    max-height: calc(100dvh - var(--header-bottom) - var(--bottom-bar-h) - 2 * var(--page-gutter));
    overflow-y: auto;
}

/* One gap for the whole page (Nick, 09-03): each column stacks its cards on
   the shell's own gap, so no card carries a bottom margin. */
.workers-profile-rail,
.workers-profile-rail-details,
.workers-profile-main,
.workers-profile-side {
    display: grid;
    gap: var(--spacing-md);
    min-width: 0;
}

/* Every top bar the same height: the title line stands as tall as the small
   round button some bars carry (.global-icon-btn--sm, 28px). */
.workers-profile-shell .card-header {
    line-height: 28px;
}

/* The three-dot menu's wrapper is inline-block by default, which seats the
   button on the text baseline and adds a descender's worth of height. */
.workers-profile-shell .card-header .global-action-dropdown {
    display: flex;
}

/* --- Photo card (the record highlight) --------------------------------- */
/* Laid out like the top of a HubSpot contact record (Nick, 08-29): a
   header naming the section — Profile — with the three-dot Actions menu
   riding in it (Nick, 08-30), then the face beside the name with the
   status chip and the classification word stacked under it. */

.workers-profile-identity-actions {
    flex-shrink: 0;
}

/* The Merge row is a link among buttons: it reads as a menu row, not as a
   link, so Bootstrap's anchor underline stays off it. */
.workers-profile-identity-actions .global-action-dropdown-item {
    text-decoration: none;
}

.workers-profile-record {
    display: flex;
    align-items: center;
    gap: var(--spacing-smd);
    min-width: 0;
}

/* The portrait — bigger than a list avatar, smaller than the old hero, so
   the name sits beside it. profile-photo.css's frame and its edit / add
   affordances shrink-wrap this size. */
.workers-profile-photo-face {
    width: 80px;
    height: 80px;
    font-size: 1.75rem;
    flex-shrink: 0;
}

button.workers-profile-photo-face {
    padding: 0;
    border: 0;
    cursor: zoom-in;
}

/* Wraps whichever face arm renders so the status dot has a box to sit on. */
.workers-profile-photo-wrap {
    position: relative;
    flex: 0 0 auto;
    display: flex;
}

/* The roster's dot, tucked into the photo's lower-right with the same
   card-coloured collar. The include hardcodes the 10px --sm the roster
   rows want; at the 80px face that reads as a fleck, so this surface
   buys back the component's base 14px geometry. */
.workers-profile-photo-dot {
    position: absolute;
    right: 4px;
    bottom: 4px;
    width: 14px;
    height: 14px;
    border-width: 2px;
    outline: 2px solid var(--color-card-bg);
    outline-offset: 0;
}

.workers-profile-identity {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
    min-width: 0;
    flex: 1;
}

/* A value line: the text and, for a viewer who may edit, a pencil that
   appears on hover / focus — the HubSpot property affordance. */
.workers-profile-identity-line {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    min-width: 0;
}

.workers-profile-identity-line--editable {
    cursor: pointer;
}

.workers-profile-identity-pencil {
    opacity: 0;
    flex-shrink: 0;
}

.workers-profile-identity-line--editable:hover .workers-profile-identity-pencil,
.workers-profile-identity-line--editable:focus-within .workers-profile-identity-pencil {
    opacity: 1;
}

.workers-profile-identity-name {
    font-size: 1.0625rem;
    font-weight: var(--font-weight-medium);
    line-height: 1.3;
    margin: 0;
    color: var(--color-text);
    overflow-wrap: anywhere;
}

.workers-profile-identity-sub {
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
    line-height: 1.4;
}

.workers-profile-identity-classline {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
    min-width: 0;
}

.workers-profile-identity-edit,
.workers-profile-identity-class {
    width: 100%;
}

/* --- Property rows (HubSpot "About this contact") ----------------------- */
/* A small label over a value. Hover a row and its tools appear at the top
   right; an editable row is a pointer and tints on hover; an open row
   holds its editor (fields + Save / Cancel) in place of the value. */
.workers-profile-props {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
}

.workers-profile-prop {
    position: relative;
    padding: var(--spacing-xs) var(--spacing-sm);
    margin: 0 calc(-1 * var(--spacing-sm));
    border-radius: var(--radius-sm);
}

.workers-profile-prop--editable {
    cursor: pointer;
}

.workers-profile-prop--editable:hover,
.workers-profile-prop--editable:focus-within {
    background: var(--color-grey-50);
}

.workers-profile-prop--open {
    cursor: default;
}

.workers-profile-prop-label {
    font-size: var(--font-size-xs);
    color: var(--color-text-secondary);
    line-height: 1.4;
    padding-right: 3.5rem;
}

/* The "still owed" marker beside a required-and-blank label. */
.workers-profile-prop-required {
    margin-left: var(--spacing-xs);
    vertical-align: middle;
}

.workers-profile-prop-value {
    font-size: var(--font-size-sm);
    color: var(--color-text);
    line-height: 1.5;
    overflow-wrap: anywhere;
}

/* A value that is a link (the email) reads as plain text, like the phone
   beside it; the underline comes on hover. */
.workers-profile-prop-value a {
    text-decoration: none;
}

.workers-profile-prop-value a:hover {
    text-decoration: underline;
}

.workers-profile-prop-value--empty {
    color: var(--color-text-muted);
}

.workers-profile-prop--nolabel {
    padding-right: var(--spacing-xl);
}

.workers-profile-prop-tools {
    position: absolute;
    top: 2px;
    right: var(--spacing-xs);
    display: inline-flex;
    gap: var(--spacing-2xs);
    opacity: 0;
    transition: opacity var(--transition-fast);
}

.workers-profile-prop:hover .workers-profile-prop-tools,
.workers-profile-prop:focus-within .workers-profile-prop-tools {
    opacity: 1;
}

/* The tools themselves are .global-icon-btn --ghost --sm (icon-button.css). */

/* No hover on a touch screen — the tools stay put. */
@media (hover: none) {
    .workers-profile-prop-tools,
    .workers-profile-identity-pencil,
    .workers-profile-email-tools {
        opacity: 1;
        pointer-events: auto;
    }
}

.workers-profile-prop-editor {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    margin-top: var(--spacing-xs);
}

.workers-profile-prop-editor__actions {
    display: flex;
    gap: var(--spacing-sm);
}

/* "+ Add email" — a text button in brand ink. */
.workers-profile-prop-add {
    align-self: flex-start;
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--color-action);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    cursor: pointer;
}

.workers-profile-prop-add:hover {
    text-decoration: underline;
}

/* Locations card rows — the label line leaves room for the three hover
   tools (make primary, edit, delete: 3 × 28px + gaps ≈ 96px), spelled as
   scale steps (2.5 + 2.5 + 1 rem) so the row stays on the spacing scale. */
.workers-profile-address-label {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    padding-right: calc(var(--spacing-2xl) + var(--spacing-2xl) + var(--spacing-md));
}

/* Their own About blurb, read as text until its pencil opens the box. */
.workers-profile-about-text {
    margin: 0;
    font-size: var(--font-size-sm);
    line-height: 1.5;
    white-space: pre-line;
    overflow-wrap: anywhere;
}

/* --- Mobile details toggle --------------------------------------------- */

.workers-profile-details-toggle {
    display: none;
    width: 100%;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-xs);
    background: var(--color-card-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-card);
    padding: var(--spacing-sm) var(--spacing-smd);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    text-align: left;
}

.workers-profile-details-toggle-hint {
    color: var(--color-text-muted);
    font-weight: var(--font-weight-body);
}

@media (min-width: 768px) {
    /* Wider screens keep the rail's cards open; the toggle only exists on
       phones, so its Alpine state must not hide anything here. */
    .workers-profile-rail-details {
        display: grid !important;
    }
}

/* The rail is 264px, so the contact card's side-by-side label/value columns
   left a value ~170px wide — emails wrapped mid-word. Stack the label over
   the value at every width, and keep each value to one line: a too-long
   email ellipsizes instead of wrapping. The margin overrides beat the mt-2
   utilities that aligned the old side-by-side rows. */
.workers-profile-rail-details dt[class*="col-sm"],
.workers-profile-rail-details dd[class*="col-sm"] {
    width: 100%;
    flex: 0 0 100%;
    max-width: 100%;
}

.workers-profile-rail-details dt[class*="col-sm"] {
    margin-bottom: var(--spacing-2xs);
}

.workers-profile-rail-details dd[class*="col-sm"] {
    margin-top: 0 !important;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Address lines in the Locations card keep to one line each too. Only those:
   a muted sentence elsewhere in the rail (the add-email hint) must wrap. */
.workers-profile-rail-details .workers-profile-address-line {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* --- Contact card (property rows: email, phone, locations) -------------- */

.workers-profile-contact-body {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
}

/* A row the worker's privacy setting hides from this viewer — the label
   stays, the value is the lock. */
.workers-profile-group-blocked {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    opacity: 0.7;
}

/* Emails: one row per address — the address (mailto), its icon flags, and
   its tools at the right: copy at rest; with the row's editor open, the
   per-address actions instead. */
.workers-profile-email-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
}

.workers-profile-email-row {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
    min-width: 0;
}

/* A long address wraps, so the flags and tools hold to its first line. */
.workers-profile-email-line {
    position: relative;
    display: flex;
    align-items: first baseline;
    gap: var(--spacing-xs);
    min-width: 0;
    min-height: 1.625rem;
}

/* Icon flags beside the address — a star (Primary — mail goes here) and
   a warning triangle (Unconfirmed), each explained by its tooltip. Words
   in a row still crowded the rows (Nick, 08-28); the envelope flag left
   with the per-org mail action (round 22). */
.workers-profile-email-flags {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    flex-shrink: 0;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}

.workers-profile-email-flag {
    display: inline-flex;
    align-items: center;
}

/* Unconfirmed is the one flag that asks for action, so it carries the
   warning ink instead of the muted grey. */
.workers-profile-email-flag--warn {
    color: var(--color-warning-text);
}

/* The row's tools, pushed to the right; they show on hover and whenever
   the Email row's editor is open. */
.workers-profile-email-tools {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-2xs);
    margin-left: auto;
    flex-shrink: 0;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--transition-fast);
}

.workers-profile-email-row:hover .workers-profile-email-tools,
.workers-profile-email-row:focus-within .workers-profile-email-tools,
.workers-profile-prop--open .workers-profile-email-tools {
    opacity: 1;
    pointer-events: auto;
}

/* Where the tools hide until hover, they keep no room beside the address:
   they float over the end of its last line, where a wrapped address leaves
   space, so the address gets the whole row and the flag never moves. Open
   in the editor, or always shown on a touch screen, they keep their room. */
@media (hover: hover) {
    .workers-profile-prop:not(.workers-profile-prop--open) .workers-profile-email-tools {
        position: absolute;
        right: 0;
        bottom: 0;
    }
}

/* The armed "Remove this address?" strip, in the row's place. */
.workers-profile-email-confirm {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-xs) 0;
}

.workers-profile-email-confirm__actions,
.workers-profile-email-form__actions {
    display: flex;
    gap: var(--spacing-sm);
    flex-shrink: 0;
}

/* The add-email form, under the rows inside the editor. Add and Cancel
   move as one: beside the box when the rail is wide, under it when not. */
.workers-profile-email-form {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-xs);
}

/* The box and its refusal, so the reason sits right under the box. */
.workers-profile-email-form__field {
    display: flex;
    flex-direction: column;
    flex: 1 1 12rem;
    min-width: 0;
}

.workers-profile-email-addr {
    min-width: 0;
    overflow-wrap: anywhere;
    /* The dense secondary size — full-size addresses truncated constantly
       (Nick, 08-28: "the font on the email might just need to be smaller"). */
    font-size: var(--font-size-sm);
    color: var(--color-text);
    text-decoration: none;
}

.workers-profile-email-addr:hover {
    text-decoration: underline;
}

.workers-profile-phone-row {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    max-width: 100%;
}

.workers-profile-phone-row--edit .form-control {
    flex: 1 1 auto;
    min-width: 0;
}

/* The plain email editor a no-login person's address gets (Nick, 08-30). */
.workers-profile-email-plain-edit .form-control {
    flex: 1 1 auto;
    min-width: 0;
}

/* --- Activity feed ----------------------------------------------------- */

.workers-profile-activity {
    overflow: hidden;
}

/* The feed scrolls inside the card. Scrollbar hidden; the hover arrows
   below are the affordance (sidebar nav convention — sidebar.css). */
.workers-profile-activity-scroll {
    position: relative;
}

.workers-profile-activity-body {
    padding: var(--spacing-xs) 0;
    max-height: 26rem;
    overflow: hidden auto;
    overscroll-behavior: contain;
    scrollbar-width: none;
}

.workers-profile-activity-body::-webkit-scrollbar {
    display: none;
}

/* The gradients fade into the card surface — keep them on the same token as
   .global-card's background or the fade shows a seam. --z-raised lifts the up
   arrow over the rows that follow it in the DOM. */
.workers-profile-activity-arrow {
    position: absolute;
    left: 0;
    right: 0;
    height: 28px;
    z-index: var(--z-raised);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    cursor: pointer;
    color: var(--color-text-muted);
    opacity: 0.7;
    transition: opacity var(--transition-fast);
}

.workers-profile-activity-arrow:hover {
    opacity: 1;
}

.workers-profile-activity-arrow--up {
    top: 0;
    background: linear-gradient(to bottom, var(--color-card-bg) 40%, transparent);
}

.workers-profile-activity-arrow--down {
    bottom: 0;
    background: linear-gradient(to top, var(--color-card-bg) 40%, transparent);
}

.workers-profile-led-coming {
    border-bottom: 1px solid var(--color-border);
}

.workers-profile-led-list {
    display: block;
}

.workers-profile-led {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-sm) var(--spacing-smd);
    font-size: var(--font-size-sm);
    color: inherit;
    text-decoration: none;
}

.workers-profile-led + .workers-profile-led {
    border-top: 1px solid var(--color-border);
}

/* A day's caps label above its rows. It carries the group's top rule (the
   adjacent-row rule above can't see across it), except when it opens the
   list. Paging swaps the sentinel for more rows INSIDE .workers-profile-led-list, so a
   later page's first label is never :first-child and keeps its rule. */
.workers-profile-led-day {
    padding: var(--spacing-sm) var(--spacing-smd) 0;
    border-top: 1px solid var(--color-border);
}

.workers-profile-led-list > .workers-profile-led-day:first-child {
    border-top: 0;
}

/* The kind dot. Money = the payments card's paid tone; abilities wear the
   brand on a quiet ground; work and files stay neutral. */
.workers-profile-led-glyph {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: var(--radius-pill);
    font-size: var(--font-size-2xs);
    background: var(--color-surface-subtle);
    color: var(--color-text-secondary);
}

.workers-profile-led-glyph--money {
    background: var(--status-success-bg);
    color: var(--color-success);
}

.workers-profile-led-glyph--abilities {
    color: var(--color-action);
}

.workers-profile-led-time {
    flex-shrink: 0;
    margin-left: auto;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
}

/* Who did it — a micro person chip just left of the time. The chip takes
   the auto margin when present (one auto margin per row, or the free space
   would split between them). */
.workers-profile-led-actor {
    flex-shrink: 0;
    margin-left: auto;
}

.workers-profile-led-actor .global-person-chip__name {
    max-width: 110px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow-wrap: normal;
}

.workers-profile-led-actor + .workers-profile-led-time {
    margin-left: 0;
}

.workers-profile-led--link:hover {
    background: var(--color-grey-50);
    color: inherit;
}

.workers-profile-led--up {
    background: var(--status-success-bg);
}

.workers-profile-led--up.workers-profile-led--link:hover {
    background: var(--status-success-bg);
    filter: brightness(0.98);
}

.workers-profile-led-date {
    flex-shrink: 0;
    width: 3.25rem;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
}

.workers-profile-led-text {
    min-width: 0;
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.workers-profile-led-obj {
    color: var(--color-text-muted);
}

.workers-profile-led-amt {
    flex-shrink: 0;
    margin-left: auto;
    font-weight: var(--font-weight-medium);
    font-variant-numeric: tabular-nums;
}

.workers-profile-led-sentinel {
    padding: var(--spacing-sm) var(--spacing-smd);
    border-top: 1px solid var(--color-border);
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    text-align: center;
}

/* --- Blocked sections --------------------------------------------------- */

/* A section this viewer can't read (_blocked_card.html): the real card's
   header, then one quiet centered mark. The lock is the whole message —
   the words sit in its tooltip and a screen-reader line — so it stands a
   step larger. */
.workers-profile-blocked-body {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-muted);
}

.workers-profile-blocked-body .bi-lock {
    font-size: var(--font-size-md);
}

/* --- Payments (an open section, not a fold) ----------------------------- */

.workers-profile-payments {
    margin-bottom: var(--spacing-md);
}

/* --- Abilities card (one row per holding, A-Z) --------------------------- */

.workers-profile-ability-body {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-smd);
}

.workers-skill-rows {
    display: flex;
    flex-direction: column;
    /* One step back out to the card edge, spelled from the scale (0 - step)
       so the rhythm ratchet reads it as on-token. */
    margin-inline: calc(0px - var(--spacing-sm));
}

.workers-skill-row {
    padding: var(--spacing-xs) var(--spacing-sm);
}

.workers-skill-row + .workers-skill-row {
    border-top: 1px solid var(--color-border-hairline);
}

/* The row head: name, then level and standing, the chevron at the far
   right when the row is a door. The door is a real button drawn as the
   row (no button chrome), with the hover the property rows use. */
.workers-skill-row__head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--spacing-xs) var(--spacing-sm);
    width: 100%;
    min-height: 1.75rem;
    font-size: var(--font-size-sm);
    color: var(--color-text);
    text-align: left;
}

.workers-skill-row__head--door {
    padding: 0;
    margin-inline: calc(0px - var(--spacing-sm));
    width: calc(100% + 2 * var(--spacing-sm));
    padding-inline: var(--spacing-sm);
    border: 0;
    background: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background var(--transition-fast);
}

.workers-skill-row__head--door:hover,
.workers-skill-row__head--door:focus-visible {
    background: var(--color-grey-50);
}

.workers-skill-row__head--door:focus-visible {
    outline: 2px solid var(--color-focus-ring);
    outline-offset: -2px;
}

.workers-skill-row__level {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}

.workers-skill-row__go {
    margin-left: auto;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}

/* The checklist under a row (ADR-165): one line per property that speaks
   to the holding, its mark at the left. Done in success ink, optional in
   muted ink, the two states that want a look — missing and lapsed — in
   the warning ink the standing badge uses. */
.workers-skill-checks {
    list-style: none;
    margin: var(--spacing-2xs) 0 0;
    padding: 0 0 var(--spacing-2xs) var(--spacing-2xs);
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
    font-size: var(--font-size-xs);
}

.workers-skill-check {
    display: flex;
    align-items: baseline;
    gap: var(--spacing-xs);
    color: var(--color-text-secondary);
}

.workers-skill-check .bi {
    flex: 0 0 auto;
    color: var(--color-text-muted);
}

.workers-skill-check--done .bi {
    color: var(--color-success);
}

.workers-skill-check--missing,
.workers-skill-check--lapsed {
    color: var(--color-warning-text);
}

.workers-skill-check--missing .bi,
.workers-skill-check--lapsed .bi {
    color: var(--color-warning-text);
}

.workers-skill-check__label {
    flex: 0 0 auto;
}

.workers-skill-check__text {
    color: var(--color-text-muted);
    overflow-wrap: anywhere;
}

.workers-skill-check--missing .workers-skill-check__text,
.workers-skill-check--lapsed .workers-skill-check__text {
    color: inherit;
}

/* Competency ratings (a coordinator's read) under the checklist. */
.workers-skill-ratings {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
    margin-top: var(--spacing-2xs);
    padding-left: var(--spacing-2xs);
    font-size: var(--font-size-xs);
}

.workers-skill-ratings .workers-ability-rating {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-sm);
}

/* --- Right rail file rows ---------------------------------------------- */

.workers-profile-file-row {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
}

.workers-profile-file-main {
    min-width: 0;
    flex: 1;
}

.workers-profile-file-name {
    display: block;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-decoration: none;
}

.workers-profile-file-name:hover {
    text-decoration: underline;
}

.workers-profile-file-sub {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}

.workers-profile-file-remove {
    flex-shrink: 0;
}

/* Empty files card: an icon-only add tile spanning the card, drawn as the
   slot a first file would land in. Full width, not a square hugging the
   left edge (Nick, 08-27). */
.workers-profile-file-drop {
    display: flex;
    width: 100%;
    height: 96px;
    align-items: center;
    justify-content: center;
    background: none;
    border: 1px dashed var(--color-border);
    border-radius: var(--radius-md);
    color: var(--color-text-muted);
    font-size: var(--font-size-lg);
    cursor: pointer;
    transition: border-color var(--transition-fast), color var(--transition-fast);
}

.workers-profile-file-drop:hover,
.workers-profile-file-drop:focus-visible {
    border-color: var(--color-action);
    color: var(--color-action);
}

/* --- Breakpoints -------------------------------------------------------- */

/* The columns answer to the width the shell actually has, never the window's.
   A drawer pushes the page 500px over with the window unchanged
   (components/drawer.css), the settings hub's nav takes 240px off the self
   profile, and the sidebar comes and goes — the window misjudged all three,
   and the side column ran under an open drawer (Nick, 09-04). One container
   on the shell's wrapper answers them together, at the ladder's own 1200 and
   768 tiers (ADR-125 rule 7) read in the shell's space. The container makes
   .workers-detail the anchor for any position: fixed descendant — keep
   drawers, lightboxes and toasts outside it (they are, today). */
.workers-detail {
    container-type: inline-size;
    container-name: profile;
}

/* Two columns, a 1/3–2/3 split (Nick, 09-03): the side cards stack UNDER
   the rail on the left, and the feed takes the right on its own. Both left
   columns scroll with the page. The line sits 44px over the three columns'
   minimums, so the third never appears already squeezed. */
@container profile (max-width: 1199.98px) {
    .workers-profile-shell {
        grid-template-columns: minmax(264px, 1fr) minmax(0, 2fr);
    }

    .workers-profile-rail,
    .workers-profile-side {
        grid-column: 1;
        position: static;
        max-height: none;
        overflow-y: visible;
    }

    .workers-profile-rail {
        grid-row: 1;
    }

    .workers-profile-side {
        grid-row: 2;
    }

    .workers-profile-main {
        grid-column: 2;
        grid-row: 1 / 3;
    }
}

/* One column: the phone's shape, the shell beside an open drawer on a 1440
   screen, and the self profile in the settings hub on a ~1024 window (a
   680px pane split 264 + 400 left the feed cramped). */
@container profile (max-width: 767.98px) {
    .workers-profile-shell {
        grid-template-columns: minmax(0, 1fr);
    }

    .workers-profile-rail,
    .workers-profile-side,
    .workers-profile-main {
        grid-column: auto;
        grid-row: auto;
    }
}

/* The Details toggle is the phone's, so it keeps reading the window: a
   one-column shell beside a drawer on a desktop still shows every card. */
@media (max-width: 767.98px) {
    .workers-profile-details-toggle {
        display: flex;
    }
}

/* --- Avatar lightbox --------------------------------------------------- */
/* Layout lives here, never inline: Alpine's x-show rewrites the element's
   inline display on every toggle, so an inline "display: flex" survived
   only until the first open and the photo rendered at the top left. The
   class keeps the flex centering through every toggle (Nick, 08-30), and
   the photo shows as the circle it is cropped to on the card. */
.workers-avatar-lightbox-backdrop {
    position: fixed;
    inset: 0;
    z-index: var(--z-overlay-top);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--spacing-xl);
    background: rgba(0, 0, 0, 0.85);
    cursor: zoom-out;
}

.workers-avatar-lightbox-img {
    width: min(70vmin, 26rem);
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: var(--radius-pill);
    box-shadow: var(--shadow-modal);
    cursor: default;
}

.workers-avatar-lightbox-close {
    position: absolute;
    top: 1rem;
    right: 1rem;
    width: 2.5rem;
    height: 2.5rem;
    border: 0;
    border-radius: var(--radius-pill);
    background: rgba(255, 255, 255, 0.1);
    color: var(--color-neutral-ink-fg);
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
}

/* --- Properties card --------------------------------------------------- */
/* Group labels between fields — rendered only when the org sorts its
   worker properties into more than one group, so a single-group org's
   card is not headed by a label that names nothing. */
.workers-profile-props-group {
    margin-bottom: var(--spacing-xs);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--color-text-muted);
}

/* Inside the tight row stack a later group's heading needs its own air —
   the rows above it sit only the stack's 2px gap away. */
.workers-profile-props > .workers-profile-props-group:not(:first-child) {
    margin-top: var(--spacing-sm);
}

/* A calculated value: shown like a saved answer, never an editor. */
.workers-profile-prop-readonly {
    color: var(--color-text);
}

/* The holding drawer (_skill_drawer.html): the standing badge and the
   level control on one line up top, then the checklist rows. The level is
   the site's segmented control; a holder who may see the level and not
   move it reads it as a word. */
.workers-skill-drawer-top {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--spacing-sm) var(--spacing-md);
    margin-bottom: var(--spacing-md);
}

.workers-skill-drawer-level {
    margin-left: auto;
}

.workers-skill-drawer-levelword {
    margin-left: auto;
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
}

/* A drawer row leads with its checklist mark: the row keeps the property
   row's own layout and makes room at the left for the mark, which sits on
   the label's line. Same inks as the card's checklist. */
.workers-profile-prop--marked {
    padding-left: calc(var(--spacing-sm) + var(--spacing-mdlg));
}

.workers-skill-mark {
    position: absolute;
    left: var(--spacing-sm);
    top: calc(var(--spacing-xs) + 1px);
    font-size: var(--font-size-sm);
    line-height: 1;
    color: var(--color-text-muted);
}

.workers-skill-mark--done {
    color: var(--color-success);
}

.workers-skill-mark--missing,
.workers-skill-mark--lapsed {
    color: var(--color-warning-text);
}

/* Merge review — the side-by-side compare grid. Column 1 is the field
   label; columns 2 and 3 are the two accounts (Stays / Folds in). A
   pickable row renders a radio in each account cell; the note row under
   it spans the grid and says where the unpicked value goes. */
.workers-merge-compare {
    display: grid;
    grid-template-columns: minmax(5rem, 8rem) 1fr 1fr;
    column-gap: var(--spacing-md);
    row-gap: var(--spacing-xs);
    align-items: start;
}

.workers-merge-compare__head {
    padding-bottom: var(--spacing-sm);
    border-bottom: 1px solid var(--color-border);
    margin-bottom: var(--spacing-xs);
}

.workers-merge-compare__who {
    margin-top: var(--spacing-xs);
    font-weight: var(--font-weight-medium);
}

.workers-merge-compare__meta {
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
    overflow-wrap: anywhere;
}

.workers-merge-compare__label {
    padding-top: var(--spacing-xsm);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary);
}

.workers-merge-compare__choice {
    display: flex;
    align-items: baseline;
    gap: var(--spacing-sm);
    margin: 0;
    padding: var(--spacing-xsm) var(--spacing-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    cursor: pointer;
}

.workers-merge-compare__choice--on {
    border-color: var(--color-action);
    background: color-mix(in srgb, var(--color-action) 6%, transparent);
}

.workers-merge-compare__cell {
    padding: var(--spacing-xsm) var(--spacing-sm);
}

.workers-merge-compare__value {
    overflow-wrap: anywhere;
}

.workers-merge-compare__rownote {
    grid-column: 2 / -1;
    padding: 0 var(--spacing-sm) var(--spacing-xs);
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
}

/* Quiet footer line under a card: the "same on both" note on the merge
   review, and the contact card's line naming who this profile absorbed. */
.workers-merge-compare__same,
.workers-profile-merged-from {
    margin-top: var(--spacing-smd);
    padding-top: var(--spacing-sm);
    border-top: 1px solid var(--color-border);
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
}
