/*
 * The board G shell (docs/superpowers/design/board-g-light.dc.html): top bar, module rail,
 * navigation column, detail pane, and the minimal auth layout. Measurements are the board's;
 * "L" numbers are board G lines. Colours come only from the tokens in aoc-tokens.css, so night
 * mode (board H) follows from html[data-theme="dark"] with no colour rule here.
 */

/* The browser's own parts of native controls (a date input's calendar icon and picker, scrollbars) follow the mode
   (C2b visual check V3): light by day, dark by night. A keyword, not a colour. */
:root {
    color-scheme: light;
}

html[data-theme="dark"] {
    color-scheme: dark;
}

a {
    color: var(--aoc-action-link);
}

a:hover {
    color: var(--aoc-action-link-hover);
}

.aoc-app :focus-visible,
.aoc-auth :focus-visible {
    outline: 2px solid var(--aoc-action-primary);
    outline-offset: 1px;
}

.aoc-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.aoc-skip-link {
    position: absolute;
    top: -40px;
    left: 8px;
    z-index: 100;
    padding: 6px 10px;
    border-radius: 3px;
    background: var(--aoc-surface);
    border: 1px solid var(--aoc-border-control);
}

.aoc-skip-link:focus {
    top: 8px;
}

/* --- The frame (L16, L31) ------------------------------------------------------------------ */

.aoc-app {
    display: flex;
    flex-direction: column;
    height: 100vh;
    overflow: hidden;
}

.aoc-shell {
    flex-grow: 1;
    display: flex;
    min-height: 0;
}

/* --- Top bar: 48 px (L18-L29) --------------------------------------------------------------- */

.aoc-topbar {
    position: relative;
    z-index: 4;
    box-sizing: border-box;
    height: 48px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 14px;
    background: var(--aoc-surface);
    border-bottom: 1px solid var(--aoc-border-hairline);
}

.aoc-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--aoc-text-primary);
    text-decoration: none;
}

.aoc-brand:hover {
    color: var(--aoc-text-primary);
}

.aoc-brand-mark {
    width: 24px;
    height: 24px;
    flex-shrink: 0;
    border-radius: 3px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--aoc-action-primary);
    color: var(--aoc-action-primary-text);
    font-size: 12px;
    font-weight: 700;
}

/* The company's app mark in place of the brand letter (PF-03 Task 6): 32 x 32 on the top bar and the sign-in card. The image
   keeps its own colours and shape; a PNG with a transparent background shows the surface behind it. */
.aoc-brand-image {
    display: block;
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    object-fit: contain;
}
.aoc-brand-name {
    font-size: 15px;
    font-weight: 600;
    white-space: nowrap;
}

/* Pinned shortcuts (L21): 26 px chips, each a grip and a link, with a small disclosure button for its menu
   (Move left, Move right, Unpin). Chips shrink and their titles truncate before the bar overflows; the list does not
   clip, so a chip's menu can drop below the bar. js/aoc-pins.js marks the nav data-enhanced; until then (and without
   script) a menu opens while its chip holds focus, so its forms still work from the keyboard. */
.aoc-pins {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    /* The pins take the bar's free space (the search box and the rest keep theirs), and are the container the
       queries below measure to hide the chips that do not fit. */
    flex: 1 1 0;
    container: aoc-pins / inline-size;
}

.aoc-pins-label {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--aoc-text-faint);
    white-space: nowrap;
}

.aoc-pin-list {
    display: flex;
    gap: 6px;
    margin: 0;
    padding: 0;
    list-style: none;
    min-width: 0;
}

.aoc-pin-chip {
    position: relative;
    box-sizing: border-box;
    flex: 0 1 auto;
    /* The narrowest a chip goes (visual check V4): its border (2 px), the link's padding (12), the grip and its gap
       (12) and the actions button (21) leave 33 px, at least 4 characters of title. */
    min-inline-size: 80px;
    display: flex;
    align-items: center;
    height: 26px;
    border: 1px solid var(--aoc-border-hairline);
    border-radius: 3px;
    background: var(--aoc-panel);
}

.aoc-pin-chip:hover {
    border-color: var(--aoc-border-control);
}

.aoc-pin {
    display: flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
    height: 100%;
    padding: 0 3px 0 9px;
    border-radius: 2px;
    color: var(--aoc-text-secondary);
    font-size: 12px;
    text-decoration: none;
    white-space: nowrap;
}

.aoc-pin:hover {
    color: var(--aoc-text-primary);
}

.aoc-pin svg {
    flex-shrink: 0;
    color: var(--aoc-icon);
    cursor: grab;
}

.aoc-pin-title {
    min-inline-size: 4ch;
    overflow: hidden;
    text-overflow: ellipsis;
}

.aoc-pin-more {
    flex-shrink: 0;
    box-sizing: border-box;
    width: 20px;
    height: 24px;
    margin-right: 1px;
    padding: 0;
    border: 0;
    border-radius: 2px;
    background: transparent;
    color: var(--aoc-text-muted);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.aoc-pin-more:hover,
.aoc-pin-more[aria-expanded="true"] {
    color: var(--aoc-text-primary);
    background: var(--aoc-raised);
}

.aoc-pin-menu {
    position: absolute;
    top: calc(100% + 6px);
    left: -1px;
    z-index: 10;
    display: none;
    flex-direction: column;
    min-width: 140px;
    margin: 0;
    padding: 4px;
    list-style: none;
    border: 1px solid var(--aoc-border-hairline);
    border-radius: 3px;
    background: var(--aoc-surface);
    box-shadow: var(--aoc-shadow-drag);
}

.aoc-pin-menu form {
    margin: 0;
}

.aoc-pins:not([data-enhanced]) .aoc-pin-chip:focus-within > .aoc-pin-menu,
.aoc-pins[data-enhanced] .aoc-pin-more[aria-expanded="true"] + .aoc-pin-menu {
    display: flex;
}

/* Dragging (js/aoc-pins.js): the chip being dragged fades, more so while it is outside the pins (a drop there unpins
   it); a line in the action blue shows where a chip dropped among the others would go. */
.aoc-pin-chip[data-dragging] {
    opacity: 0.55;
}

.aoc-pins[data-drag-out] .aoc-pin-chip[data-dragging] {
    opacity: 0.3;
}

.aoc-pin-chip[data-drop="before"] {
    box-shadow: -4px 0 0 -2px var(--aoc-action-primary);
}

.aoc-pin-chip[data-drop="after"] {
    box-shadow: 4px 0 0 -2px var(--aoc-action-primary);
}

/* "Drop to pin" (L21), shown only while a screen is dragged from the navigation column: dashed in the action blue on
   its tint, after a hairline divider; solid once the screen is over the pins. */
.aoc-pins-divider,
.aoc-pin-drop {
    display: none;
}

.aoc-pins[data-dragging="row"] .aoc-pins-divider {
    display: block;
    width: 1px;
    height: 18px;
    background: var(--aoc-border-hairline);
}

.aoc-pins[data-dragging="row"] .aoc-pin-drop {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: 5px;
    height: 26px;
    padding: 0 11px;
    border: 1px dashed var(--aoc-action-primary);
    border-radius: 3px;
    background: var(--aoc-action-tint);
    color: var(--aoc-action-link);
    font-size: 12px;
    white-space: nowrap;
}

.aoc-pins[data-drop-over] .aoc-pin-drop {
    border-style: solid;
}

/* The pins' live region (js/aoc-pins.js). Successes are for screen readers only (the chips show them); a refusal or a
   failure is drawn as an alert just below the pins, as the colour-mode switch draws its own. */
.aoc-pins-status {
    position: absolute;
    margin: 0;
    width: 1px;
    height: 1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.aoc-pins-status[data-kind="error"]:not(:empty) {
    top: calc(100% + 4px);
    left: 14px;
    width: auto;
    height: auto;
    overflow: visible;
    clip-path: none;
    white-space: normal;
    max-width: 420px;
    padding: 6px 10px;
    border: 1px solid var(--aoc-alert-border);
    border-radius: 3px;
    background: var(--aoc-alert-bg);
    color: var(--aoc-alert-fg);
    font-size: 12px;
}

/* Search (L23), a placeholder. 190 px, and the first to give way on a narrow bar (visual check V4): it starts at its
   120 px minimum below 1000 px, and can shrink to it at any width. */
.aoc-search {
    box-sizing: border-box;
    flex: 0 1 190px;
    min-inline-size: 120px;
    height: 30px;
    padding: 0 9px;
    border: 1px solid var(--aoc-border-control);
    border-radius: 3px;
    font: inherit;
    font-size: 13px;
    background: var(--aoc-surface);
    color: var(--aoc-text-primary);
}

.aoc-search::placeholder {
    color: var(--aoc-text-muted);
}

/* The day/night switch (L24): a 30 px track holding two 28 x 24 segments. The pressed segment
   is --aoc-segment-on-bg with its own outline (board H draws it above the surface by night).
   It is a form (it posts without script), so it drops a form's margin. */
.aoc-mode-switch {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: 2px;
    height: 30px;
    margin: 0;
    padding: 2px;
    border: 1px solid var(--aoc-border-control);
    border-radius: 15px;
    background: var(--aoc-panel);
}

.aoc-mode-switch button {
    box-sizing: border-box;
    width: 28px;
    height: 24px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 12px;
    background: transparent;
    color: var(--aoc-text-faint);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.aoc-mode-switch button[aria-pressed="true"] {
    border-color: var(--aoc-segment-on-border);
    background: var(--aoc-segment-on-bg);
    color: var(--aoc-action-link);
}

/* The switch's live region (js/aoc-color-mode.js reports a failed save here). It is in the page from the start so the
   message is announced, hidden while empty, and drawn as an alert just below the top bar when it holds one. Both
   states are out of the bar's flow. */
.aoc-mode-status {
    position: absolute;
    margin: 0;
}

.aoc-mode-status:empty {
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.aoc-mode-status:not(:empty) {
    top: calc(100% + 4px);
    right: 14px;
    padding: 6px 10px;
    border: 1px solid var(--aoc-alert-border);
    border-radius: 3px;
    background: var(--aoc-alert-bg);
    color: var(--aoc-alert-fg);
    font-size: 12px;
}

/* The account's live region: hidden while empty, a small info note below the bar when it confirms a change. */
.aoc-account-status {
    position: absolute;
    margin: 0;
}

.aoc-account-status:empty {
    width: 1px;
    height: 1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    border: 0;
}

.aoc-account-status:not(:empty) {
    top: calc(100% + 4px);
    left: 50%;
    z-index: 5;
    transform: translateX(-50%);
    padding: 6px 10px;
    border-radius: 3px;
    background: var(--aoc-info-bg);
    color: var(--aoc-info-fg);
    font-size: 12px;
    white-space: nowrap;
}

/* Notifications (L24), a placeholder. */
.aoc-icon-button {
    box-sizing: border-box;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 1px solid var(--aoc-border-control);
    border-radius: 3px;
    background: var(--aoc-raised);
    color: var(--aoc-text-secondary);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* The user (L25-L28), a disclosure that holds Sign out. */
.aoc-user {
    position: relative;
    padding-left: 4px;
}

.aoc-user > summary {
    display: flex;
    align-items: center;
    gap: 7px;
    cursor: pointer;
    list-style: none;
    border-radius: 3px;
}

.aoc-user > summary::-webkit-details-marker {
    display: none;
}

.aoc-avatar {
    width: 26px;
    height: 26px;
    border-radius: 13px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--aoc-border-hairline);
    color: var(--aoc-text-secondary);
    font-size: 11px;
    font-weight: 600;
}

.aoc-user-name {
    font-size: 13px;
    color: var(--aoc-text-secondary);
    white-space: nowrap;
}

.aoc-user-menu {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    z-index: 10;
    min-width: 160px;
    padding: 4px;
    border: 1px solid var(--aoc-border-hairline);
    border-radius: 3px;
    background: var(--aoc-surface);
    box-shadow: var(--aoc-shadow-drag);
}

.aoc-user-menu form {
    margin: 0;
}

.aoc-menu-item {
    width: 100%;
    height: 30px;
    padding: 0 10px;
    border: 0;
    border-radius: 3px;
    background: transparent;
    color: var(--aoc-text-primary);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.aoc-menu-item:hover {
    background: var(--aoc-panel);
}

/* "Change password" is a link styled as the menu's buttons are. */
a.aoc-menu-item {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    text-decoration: none;
    white-space: nowrap;
}

/* --- A narrow top bar (visual check V4) --------------------------------------------------------
   The bar gives way in order. Below 1000 px the search box starts at its 120 px minimum and the
   user's name is hidden, visually only: it stays the user menu's accessible name, and the avatar
   stays. The pins then have the rest: chips shrink to their minimum (80 px, a 4-character title),
   and the chips that still do not fit are hidden from the end of the list. Each threshold is the
   label (about 42 px and its 6 px gap) plus that many minimum chips and their gaps. They are
   reachable from the navigation column all the same; an overflow menu for them is deferred. */
@media (max-width: 999.98px) {
    .aoc-search {
        flex-basis: 120px;
    }

    .aoc-user-name {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: -1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }
}

@container aoc-pins (width < 128px) {
    .aoc-pins-label,
    .aoc-pin-chip {
        display: none;
    }
}

@container aoc-pins (width < 214px) {
    .aoc-pin-chip:nth-child(n + 2) {
        display: none;
    }
}

@container aoc-pins (width < 300px) {
    .aoc-pin-chip:nth-child(n + 3) {
        display: none;
    }
}

@container aoc-pins (width < 386px) {
    .aoc-pin-chip:nth-child(n + 4) {
        display: none;
    }
}

@container aoc-pins (width < 472px) {
    .aoc-pin-chip:nth-child(n + 5) {
        display: none;
    }
}

@container aoc-pins (width < 558px) {
    .aoc-pin-chip:nth-child(n + 6) {
        display: none;
    }
}

@container aoc-pins (width < 644px) {
    .aoc-pin-chip:nth-child(n + 7) {
        display: none;
    }
}

@container aoc-pins (width < 730px) {
    .aoc-pin-chip:nth-child(n + 8) {
        display: none;
    }
}

/* --- Module rail: 56 px, 44 px links (L33-L43) --------------------------------------------- */

.aoc-rail {
    box-sizing: border-box;
    width: 56px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 8px 0;
    overflow-y: auto;
    background: var(--aoc-panel);
    border-right: 1px solid var(--aoc-border-hairline);
}

.aoc-rail-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Administration at the foot of the rail, as board G draws Configuration (L41-L42). */
.aoc-rail-list-bottom {
    margin-top: auto;
    padding-top: 2px;
}

.aoc-rail-link {
    width: 44px;
    height: 44px;
    border-radius: 3px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--aoc-text-muted);
}

.aoc-rail-link:hover {
    color: var(--aoc-text-primary);
    background: var(--aoc-raised);
}

/* The active module (L35): the green state and the inset left bar. */
.aoc-rail-link[aria-current] {
    color: var(--aoc-state-selected-fg);
    background: var(--aoc-state-selected-bg);
    box-shadow: inset 2px 0 0 var(--aoc-state-accent);
}

/* --- Navigation column: 288 px (L45-L81) --------------------------------------------------- */

.aoc-navcol {
    position: relative;
    box-sizing: border-box;
    width: 288px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    min-height: 0;
    border-right: 1px solid var(--aoc-border-hairline);
    background: var(--aoc-page);
}

/* What the collapse toggle hides: the screen list and the work queue. */
.aoc-navcol-body {
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* --- The column's collapse toggle (D1 visual check V3, owner decision 2026-10-04) ----------------
   A 24 px icon button at the column's top right, over the first module header's free end; collapsed, the column is a
   28 px edge holding only this button (the rail stays). Both chevrons are in the markup and the state picks one, so the
   script never redraws the icon. Its live region is the day/night switch's: hidden while empty, the alert when a save
   failed. From 1100 px only; below it the overlay (V2) takes over. Tokens only. */

.aoc-nav-toggle {
    position: absolute;
    top: 8px;
    right: 6px;
    z-index: 1;
    margin: 0;
}

.aoc-nav-toggle-button {
    box-sizing: border-box;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 1px solid var(--aoc-border-control);
    border-radius: 3px;
    background: var(--aoc-raised);
    color: var(--aoc-text-secondary);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.aoc-nav-toggle-button:hover {
    color: var(--aoc-text-primary);
}

.aoc-nav-toggle-button > span {
    display: flex;
}

.aoc-shell[data-nav-collapsed="true"] .aoc-nav-toggle-collapse {
    display: none;
}

.aoc-shell:not([data-nav-collapsed="true"]) .aoc-nav-toggle-expand {
    display: none;
}

.aoc-nav-status {
    position: absolute;
    top: 38px;
    left: 4px;
    z-index: 2;
    margin: 0;
}

.aoc-nav-status:empty {
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.aoc-nav-status:not(:empty) {
    min-width: 220px;
    padding: 6px 10px;
    border: 1px solid var(--aoc-alert-border);
    border-radius: 3px;
    background: var(--aoc-alert-bg);
    color: var(--aoc-alert-fg);
    font-size: 12px;
}

@media (min-width: 1100px) {
    .aoc-shell[data-nav-collapsed="true"] .aoc-navcol {
        width: 28px;
    }

    .aoc-shell[data-nav-collapsed="true"] .aoc-navcol-body {
        display: none;
    }

    .aoc-shell[data-nav-collapsed="true"] .aoc-nav-toggle {
        right: 1px;
    }
}

/* --- The column below 1100 px (D1 visual check V2, owner decision 2026-10-04) ---------------------
   Where script runs, the 288 px column hides (the rail stays) and the top bar's Menu button opens it as an overlay over
   the detail pane, below the bar and beside the rail, sliding in (not for a user who asks for reduced motion). Where
   script does not run, or the browser cannot say, nothing is hidden: the column stays where it is. The collapse toggle is
   not offered below 1100 px either way. Above 1100 px the Menu button is not drawn. Tokens only. */

.aoc-menu-button {
    display: none;
    flex-shrink: 0;
}

@media (max-width: 1099.98px) {
    .aoc-nav-toggle {
        display: none;
    }
}

@media (max-width: 1099.98px) and (scripting: enabled) {
    html[data-nav-ready="true"] .aoc-menu-button {
        display: flex;
    }

    html[data-nav-ready="true"] .aoc-navcol {
        display: none;
    }

    html[data-nav-ready="true"] .aoc-shell[data-nav-open="true"] .aoc-navcol {
        display: flex;
        position: fixed;
        top: 48px;
        bottom: 0;
        left: 56px;
        z-index: 6;
        width: 288px;
        box-shadow: var(--aoc-shadow-drag);
        animation: aoc-nav-slide-in 120ms ease-out;
    }
}

@keyframes aoc-nav-slide-in {
    from {
        transform: translateX(-16px);
        opacity: 0;
    }

    to {
        transform: none;
        opacity: 1;
    }
}

@media (prefers-reduced-motion: reduce) {
    html[data-nav-ready="true"] .aoc-shell[data-nav-open="true"] .aoc-navcol {
        animation: none;
    }
}

.aoc-nav {
    flex: 0 1 auto;
    min-height: 0;
    overflow-y: auto;
}

/* With no work queue below it, the screen list takes the whole column. */
.aoc-nav:last-child {
    flex-grow: 1;
}

.aoc-nav-section {
    border-bottom: 1px solid var(--aoc-border-hairline);
}

/* The module header (L48). */
.aoc-nav-header {
    box-sizing: border-box;
    height: 36px;
    margin: 0;
    padding: 0 12px;
    display: flex;
    align-items: center;
    background: var(--aoc-panel);
    border-bottom: 1px solid var(--aoc-border-hairline);
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--aoc-text-muted);
}

.aoc-nav-list,
.aoc-nav-views {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* A screen (L49, L55-L57): 36 px. */
.aoc-nav-screen {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    height: 36px;
    padding: 0 12px;
    border-bottom: 1px solid var(--aoc-border-row);
    color: var(--aoc-text-secondary);
    text-decoration: none;
}

.aoc-nav-list > li:last-child > .aoc-nav-item:last-child > .aoc-nav-screen {
    border-bottom: 0;
}

/* A row and its Pin or Unpin button (C1 task 6). The button sits at the row's right end, after the chevron; a row that
   can be pinned keeps room for it. Pin shows while the row is hovered or holds focus, and always on a touch screen;
   Unpin, the pinned state, always shows. */
.aoc-nav-item {
    position: relative;
}

.aoc-nav-screen[data-pin-key],
.aoc-nav-view[data-pin-key] {
    padding-right: 36px;
}

.aoc-nav-pin,
.aoc-nav-unpin {
    position: absolute;
    top: 50%;
    right: 6px;
    box-sizing: border-box;
    width: 24px;
    height: 24px;
    margin-top: -12px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 3px;
    background: transparent;
    color: var(--aoc-action-link);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.aoc-nav-pin[hidden],
.aoc-nav-unpin[hidden] {
    display: none;
}

.aoc-nav-pin {
    opacity: 0;
}

.aoc-nav-item:hover > .aoc-nav-pin,
.aoc-nav-item:focus-within > .aoc-nav-pin,
.aoc-nav-pin:focus,
.aoc-nav-pin:focus-visible {
    opacity: 1;
}

/* A coarse pointer (touch) cannot hover, so the Pin button is always there to tap. */
@media (pointer: coarse) {
    .aoc-nav-pin {
        opacity: 1;
    }
}

.aoc-nav-pin:hover,
.aoc-nav-unpin:hover {
    border-color: var(--aoc-border-control);
    background: var(--aoc-surface);
}

.aoc-nav-pin-form {
    display: none;
}

.aoc-nav-screen:hover,
.aoc-nav-view:hover {
    color: var(--aoc-text-primary);
    background: var(--aoc-panel);
}

.aoc-nav-title {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.aoc-nav-chevron {
    display: flex;
    margin-left: auto;
    padding-left: 8px;
    color: var(--aoc-icon);
}

/* A saved view (L51): 32 px, indented under its screen. Its divider is a shade apart from a screen's:
   the boards draw it in the raised value (#EAEFF4 by day, #202A36 by night), not border-row. */
.aoc-nav-view {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    height: 32px;
    padding: 0 12px 0 26px;
    border-bottom: 1px solid var(--aoc-raised);
    color: var(--aoc-text-secondary);
    font-size: 13px;
    text-decoration: none;
}

/* The active screen and view (L49, L210): the green state. A screen whose view is current is
   part of the trail (aria-current="true") and is drawn the same way, as on the board. */
.aoc-nav-screen[aria-current],
.aoc-nav-view[aria-current] {
    color: var(--aoc-state-selected-fg);
    background: var(--aoc-state-selected-bg);
    font-weight: 600;
}

.aoc-nav-screen[aria-current] .aoc-nav-chevron {
    color: currentColor;
}

.aoc-nav-empty {
    margin: 0;
    padding: 12px;
    color: var(--aoc-text-muted);
}

/* A screen's work queue (L60-L81), filled by the screen's Queue section. */
.aoc-queue {
    flex-grow: 1;
    min-height: 0;
    overflow-y: auto;
}

/* --- Detail pane (L84) ----------------------------------------------------------------------- */

.aoc-detail {
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
    background: var(--aoc-page);
}

.aoc-detail:focus {
    outline: none;
}

/* The screen's header row (L86): 52 px. */
.aoc-detail-header {
    box-sizing: border-box;
    height: 52px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 14px;
    border-bottom: 1px solid var(--aoc-border-hairline);
}

.aoc-detail-header h1 {
    margin: 0;
    font-size: 17px;
    font-weight: 600;
}

.aoc-detail-body {
    flex-grow: 1;
    min-height: 0;
    overflow: auto;
}

.aoc-page-body {
    padding: 14px;
}

.aoc-lead {
    margin: 0 0 8px;
    color: var(--aoc-text-secondary);
}

.aoc-note {
    margin: 0;
    color: var(--aoc-text-muted);
}

/* --- The auth layout: sign in, not permitted, errors ----------------------------------------- */

.aoc-auth {
    min-height: 100vh;
}

.aoc-auth-main {
    box-sizing: border-box;
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}

.aoc-auth-card {
    box-sizing: border-box;
    width: 360px;
    max-width: 100%;
    padding: 24px;
    border: 1px solid var(--aoc-border-hairline);
    border-radius: 3px;
    background: var(--aoc-surface);
}

.aoc-auth-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 20px;
}

.aoc-auth-title,
.aoc-auth-header h1 {
    margin: 0 0 16px;
    font-size: 17px;
    font-weight: 600;
}

.aoc-form {
    margin: 0;
}

.aoc-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 12px;
}

.aoc-field label {
    font-size: 12px;
    color: var(--aoc-text-muted);
}

.aoc-input {
    box-sizing: border-box;
    height: var(--aoc-control-height);
    padding: 0 9px;
    border: 1px solid var(--aoc-border-control);
    border-radius: 3px;
    font: inherit;
    background: var(--aoc-surface);
    color: var(--aoc-text-primary);
}

.aoc-check {
    margin-bottom: 16px;
}

.aoc-check label {
    display: flex;
    align-items: center;
    gap: 6px;
}

.aoc-button-primary {
    box-sizing: border-box;
    height: var(--aoc-control-height);
    padding: 0 14px;
    border: 1px solid var(--aoc-action-primary);
    border-radius: 3px;
    background: var(--aoc-action-primary);
    color: var(--aoc-action-primary-text);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

/* The board's row and toolbar button (board G L116 to L119, board H the same lines): the default style at toolbar size,
   the surface fill and the control border, never the primary blue, which is kept for a page's one main action (C2b
   visual check V1). A link (Turn off…) takes the same look. */
.aoc-button-row {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    height: 28px;
    padding: 0 10px;
    border: 1px solid var(--aoc-border-control);
    border-radius: 3px;
    background: var(--aoc-surface);
    color: var(--aoc-text-primary);
    font: inherit;
    font-size: 12px;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
}

a.aoc-button-row:hover,
a.aoc-button-row:visited {
    color: var(--aoc-text-primary);
}

/* The sign-in failure message: an alert banner (L175), never a row. */
.aoc-form-errors.validation-summary-errors {
    margin-bottom: 12px;
    padding: 9px 11px;
    border: 1px solid var(--aoc-alert-border);
    border-radius: 3px;
    background: var(--aoc-alert-bg-subtle);
    color: var(--aoc-alert-fg);
}

.aoc-form-errors ul {
    margin: 0;
    padding-left: 18px;
}

.aoc-form-errors.validation-summary-valid {
    display: none;
}

/* A form in the detail pane (change password): one column at the sign-in card's width. */
.aoc-form-narrow {
    max-width: 360px;
}

/* A field's own message: an alert, beside the field it concerns. Empty (valid) messages take no space. */
.aoc-field-error {
    font-size: 12px;
    color: var(--aoc-alert-fg);
}

.aoc-field-error:empty {
    display: none;
}

/* Why a page is shown (the must-change-password gate): information, not an alert. */
.aoc-banner {
    max-width: 640px;
    margin: 0 0 14px;
    padding: 9px 11px;
    border-radius: 3px;
    background: var(--aoc-info-bg);
    color: var(--aoc-info-fg);
}

/* --- Admin screens (C2a) ----------------------------------------------------------------------
   The users and roles screens (Views/Users, Views/Roles) and their forms, on board G's 8 and 14 px rhythm. Tokens only:
   blue is the action (the primary links and buttons), green the state (Kendo's current row and sort indicator, from
   aoc-kendo-state.css), red the alert region only, never a row. An inactive row is muted text with a neutral chip. */

/* The header row: the screen's title, and its primary action at the far end. */
.aoc-admin-toolbar {
    display: flex;
    flex-grow: 1;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.aoc-admin-toolbar h1 {
    margin: 0;
    font-size: 17px;
    font-weight: 600;
}

.aoc-admin-toolbar > a,
.aoc-admin-toolbar > button {
    margin-left: auto;
}

/* The primary action as a link ("New user"): the primary button's look. */
a.aoc-button-primary {
    display: inline-flex;
    align-items: center;
    text-decoration: none;
}

a.aoc-button-primary:hover,
a.aoc-button-primary:visited {
    color: var(--aoc-action-primary-text);
}

/* Links beside one another: a page's own actions, and a grid row's. */
.aoc-admin-links {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px;
    margin: 0 0 14px;
}

.aoc-grid-actions {
    white-space: nowrap;
}

/* The admin grids (div.aoc-grid, built by js/aoc-admin.js) against board G's grid (C2a visual check). Each rule outranks
   the Kendo rule it replaces by specificity (this sheet also loads later); DesignTokenContrastTests pins them.
   V1: 14 px side padding in cells and headers (Kendo's is 12 px). */
.k-grid.aoc-grid .k-table-th,
.k-grid.aoc-grid .k-table-td {
    padding-inline: 14px;
}

/* V2: a 1 px row divider in the row border token (#E8EDF2 / #232D3A) under every data row, the last included; Kendo
   draws none. The header keeps its own bottom border in the hairline (--kendo-color-border). */
.k-grid.aoc-grid .k-table-tbody .k-table-row > .k-table-td {
    border-block-end: 1px solid var(--aoc-border-row);
}

/* V3: the row action links in action blue, with its hover; Kendo's ".k-grid a" paints every grid link in the text
   colour. */
.k-grid.aoc-grid .aoc-grid-actions a {
    color: var(--aoc-action-link);
}

.k-grid.aoc-grid .aoc-grid-actions a:hover {
    color: var(--aoc-action-link-hover);
    text-decoration: underline;
}

.aoc-grid-actions a + a {
    margin-left: 8px;
}

/* The polite live region: a success notice in secondary text. Empty, it takes no space. */
.aoc-admin-status {
    margin: 0 0 8px;
    color: var(--aoc-text-secondary);
}

.aoc-admin-status:empty {
    margin: 0;
}

/* A short status label. Neutral (an inactive user) is the badge grey with muted text; never a red fill. */
.aoc-chip {
    display: inline-flex;
    align-items: center;
    box-sizing: border-box;
    height: 20px;
    padding: 0 8px;
    border-radius: 10px;
    font-size: 12px;
    line-height: 1;
    white-space: nowrap;
    background: var(--aoc-badge-bg);
    color: var(--aoc-text-muted);
}

.aoc-chip[data-kind="neutral"] {
    background: var(--aoc-badge-bg);
    color: var(--aoc-text-muted);
}

.aoc-chip[data-kind="warn"] {
    background: var(--aoc-warn-bg);
    color: var(--aoc-warn-fg);
}

.aoc-chip[data-kind="info"] {
    background: var(--aoc-info-bg);
    color: var(--aoc-info-fg);
}

/* A caution that is not an alert (the one-time password's refresh note). */
.aoc-banner[data-kind="warn"] {
    background: var(--aoc-warn-bg);
    color: var(--aoc-warn-fg);
}

/* Muted text: a role's description, and an inactive row, in the no-script table and in the Kendo grid alike. */
.aoc-muted {
    color: var(--aoc-text-muted);
}

.aoc-table tr.aoc-muted > td,
.k-grid .k-table-row.aoc-muted > .k-table-td {
    color: var(--aoc-text-muted);
}

/* The form's alert region: a refusal or a conflict, in the alert border and text, with no fill. Empty, it is not drawn.
   Several messages (a script's 400 lists one per line) keep their own lines. */
.aoc-form-alert:not(:empty) {
    white-space: pre-line;
    margin-bottom: 14px;
    padding: 8px 11px;
    border: 1px solid var(--aoc-alert-border);
    border-radius: 3px;
    color: var(--aoc-alert-fg);
}

.aoc-form-alert:focus,
.aoc-form-errors:focus {
    outline: 2px solid var(--aoc-action-primary);
    outline-offset: 1px;
}

/* The one-time password: large monospace on the raised surface, selectable in one click. */
.aoc-otp {
    display: inline-block;
    padding: 8px 14px;
    border-radius: 3px;
    font-family: Consolas, 'Cascadia Mono', 'Courier New', monospace;
    font-size: 18px;
    letter-spacing: 0.05em;
    background: var(--aoc-raised);
    color: var(--aoc-text-primary);
    user-select: all;
}

.aoc-otp-page p {
    max-width: 640px;
    margin: 0 0 14px;
}

/* A form in the detail pane that is wider than the narrow sign-in column. */
.aoc-form-wide {
    max-width: 640px;
}

.aoc-fieldset {
    margin: 0 0 14px;
    padding: 8px 14px 14px;
    border: 1px solid var(--aoc-border-hairline);
    border-radius: 3px;
}

.aoc-fieldset legend {
    padding: 0 8px;
    font-weight: 600;
}

.aoc-fieldset .aoc-fieldset {
    margin-bottom: 8px;
}

.aoc-fieldset .aoc-check {
    margin-bottom: 8px;
}

/* A role checkbox: the name beside the box, the description under the name. */
.aoc-role {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 8px;
    align-items: center;
}

.aoc-role .aoc-muted {
    grid-column: 2;
    font-size: 12px;
}

/* The role form's permission tree: a heading, then one fieldset per module. */
.aoc-section-heading {
    margin: 14px 0 8px;
    font-size: 14px;
    font-weight: 600;
}

/* A permission: the box, then its name and code; under the name its description and, when its module's feature is
   off, why it is not effective. A muted row (feature off) is secondary text only, never a fill, and its box stays
   enabled: the permission can still be granted. */
.aoc-permission {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 8px;
    align-items: center;
}

.aoc-permission label {
    display: inline;
}

.aoc-permission code {
    margin-left: 6px;
    font-family: Consolas, 'Cascadia Mono', 'Courier New', monospace;
    font-size: 12px;
    color: var(--aoc-text-muted);
}

.aoc-permission-description,
.aoc-permission-reason {
    grid-column: 2;
    font-size: 12px;
    color: var(--aoc-text-muted);
}

.aoc-permission-reason {
    font-style: italic;
}

/* "Grants full administration" (final review I1), beside users.manage and roles.manage: secondary text at the weight of
   a label, so it reads as part of the permission, never as an alert. */
.aoc-permission-hint {
    grid-column: 2;
    font-size: 12px;
    font-weight: 600;
    color: var(--aoc-text-secondary);
}

.aoc-permission.aoc-muted label {
    color: var(--aoc-text-muted);
}

.aoc-textarea {
    height: auto;
    min-height: 80px;
    padding: 8px 9px;
    resize: vertical;
}

.aoc-form-actions {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-top: 14px;
}

/* The users list without script: a plain table at the grid's row height, and a pager under it. */
.aoc-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--aoc-surface);
}

.aoc-table th,
.aoc-table td {
    height: var(--aoc-row-height);
    padding: 0 14px;
    border-bottom: 1px solid var(--aoc-border-row);
    text-align: left;
}

.aoc-table th {
    font-weight: 600;
    color: var(--aoc-text-secondary);
    border-bottom-color: var(--aoc-border-hairline);
}

.aoc-pager {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-top: 8px;
    color: var(--aoc-text-muted);
}

/* The effective access page: the user picker (a Kendo ComboBox, or without script a search form), then the report. */
.aoc-picker,
.aoc-picker-search {
    max-width: 360px;
    margin-bottom: 14px;
}

.aoc-picker .k-combobox {
    width: 100%;
}

.aoc-access-matches ul,
.aoc-access-scope {
    margin: 0 0 14px;
    padding-left: 18px;
}

.aoc-access-matches li,
.aoc-access-scope li {
    margin-bottom: 4px;
}

.aoc-access-status {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 14px;
    color: var(--aoc-text-secondary);
}

.aoc-access-table {
    margin-bottom: 14px;
}

.aoc-access-table caption {
    padding: 0 0 6px;
    text-align: left;
    font-weight: 600;
}

.aoc-access-table code {
    margin-left: 6px;
    font-family: Consolas, 'Cascadia Mono', 'Courier New', monospace;
    font-size: 12px;
    color: var(--aoc-text-muted);
}

/* --- Admin screens (C2b) ----------------------------------------------------------------------
   The settings screen (Views/Settings): a row per setting, its control with the Default or Changed marker and Reset to
   default beside it, and under the brand row the preview. Tokens only: blue is the action (Save, the Reset link), the
   markers are the neutral and info chips, a stored value outside its rule is a warn note, and red is the field error
   and the alert region only. The preview's own colours are the brand's, drawn as SVG fill attributes by the server and
   js/aoc-admin.js, never a style. */

.aoc-setting {
    margin-bottom: 14px;
}

.aoc-setting:last-child {
    margin-bottom: 0;
}

.aoc-setting > label {
    font-size: 13px;
    font-weight: 600;
    color: var(--aoc-text-primary);
}

.aoc-setting > .aoc-note {
    font-size: 12px;
}

/* The control, then the marker chip and Reset to default, on one line where they fit. */
.aoc-setting-control {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

.aoc-setting-text {
    width: 280px;
    max-width: 100%;
}

.aoc-setting-number {
    width: 96px;
}

.aoc-setting-choice {
    min-width: 160px;
}

.aoc-setting-colour {
    width: 104px;
    font-family: Consolas, 'Cascadia Mono', 'Courier New', monospace;
}

.aoc-setting-reset {
    font-size: 12px;
    color: var(--aoc-action-link);
}

.aoc-setting-reset:hover {
    color: var(--aoc-action-link-hover);
}

/* A stored value outside its rule (Decision 7): a caution, not an alert. */
.aoc-setting-problem {
    margin: 2px 0 0;
    padding: 6px 9px;
    border-radius: 3px;
    font-size: 12px;
    background: var(--aoc-warn-bg);
    color: var(--aoc-warn-fg);
}

/* The colour's swatch: its fill is the colour; the outline keeps a pale or dark colour visible on the surface. */
.aoc-swatch {
    flex: none;
}

.aoc-swatch rect {
    stroke: var(--aoc-border-control);
    stroke-width: 1;
}

/* The brand preview: day and night side by side, each on its mode's own surface, then the warnings. */
.aoc-brand-preview {
    margin: 0 0 14px;
}

.aoc-brand-preview-modes {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 4px 0 8px;
}

.aoc-brand-sample > rect:first-child {
    stroke: var(--aoc-border-hairline);
    stroke-width: 1;
}

.aoc-brand-warnings {
    margin: 0;
    padding: 0;
    list-style: none;
}

.aoc-brand-warnings > li {
    margin: 0 0 6px;
}

/* The features screen (Views/Features): a row per feature with its state, what it gates and its grants, and the action.
   Off is the neutral chip; On is plain text. Turn on and Turn off… are both the 28 px row button (.aoc-button-row, visual
   check V1), each with the row's own alert region (red border and text, no fill), which holds a refusal and takes no
   space while empty. The board's geometry (V2): a 36 px header and 40 px rows (comfortable; 28 and 32 compact), the
   button centred in the row, and the gating note and the grant count on one line. The gated modules and their screens are
   a compact nested list in secondary text, so a gated feature's row grows with them. The turn-off page lists the screens,
   permissions and roles the same way. Tokens only. */

.aoc-features-table th {
    height: calc(var(--aoc-row-height) - 4px);
}

.aoc-features-table td {
    box-sizing: border-box;   /* a table cell's height excludes its padding otherwise: 40 px became 52 */
    padding-top: calc((var(--aoc-row-height) - 28px) / 2);
    padding-bottom: calc((var(--aoc-row-height) - 28px) / 2);
    vertical-align: middle;
}

.aoc-features-table td > .aoc-note,
.aoc-feature-grants {
    font-size: 12px;
    color: var(--aoc-text-muted);
    white-space: nowrap;
}

.aoc-feature-toggle > .aoc-form-alert:empty {
    display: none;
}

.aoc-feature-gates,
.aoc-feature-screens,
.aoc-feature-preview-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.aoc-feature-gates > li + li {
    margin-top: 4px;
}

.aoc-feature-module {
    font-weight: 600;
    color: var(--aoc-text-primary);
}

.aoc-feature-screens {
    padding-left: 14px;
    font-size: 12px;
    color: var(--aoc-text-secondary);
}

.aoc-feature-toggle {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
}

.aoc-feature-toggle > .aoc-form-alert:not(:empty) {
    margin-bottom: 0;
}

.aoc-feature-preview-list > li {
    margin: 0 0 4px;
}

.aoc-feature-affected {
    margin: 14px 0;
    font-weight: 600;
    color: var(--aoc-text-primary);
}

/* The audit screen (Views/Audit): the filter form as one row of labelled fields that wraps on a narrow pane, Filter (the
   blue primary button) and the All dates link at its end, then the grid. A field error is the shared red inline message;
   the key column wraps rather than widening the table. Tokens only. */

.aoc-audit-filter {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 8px 14px;
    margin: 0 0 14px;
}

.aoc-audit-filter > .aoc-field {
    margin-bottom: 0;
}

.aoc-audit-filter .aoc-field-error {
    max-width: 200px;
}

.aoc-audit-user {
    width: 180px;
    max-width: 100%;
}

/* Lined up with the controls, below the labels. */
.aoc-audit-filter-actions {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-top: 20px;
}

.aoc-audit-filter-actions > a {
    color: var(--aoc-action-link);
}

.aoc-audit-filter-actions > a:hover {
    color: var(--aoc-action-link-hover);
}

.aoc-audit-key {
    overflow-wrap: anywhere;
}

/* The audit entry (Views/Audit/Detail): the entry's facts as a two-column definition list, then the changes table. A
   value keeps its own line breaks and spaces and wraps anywhere, so a long value (a JSON object, a hash-like key) never
   widens the page; a cell keeps the row height as its least and grows to fit. A marker (empty, redacted,
   pending) is muted text, never a fill. Tokens only. */

.aoc-audit-summary {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    gap: 6px 14px;
    margin: 0 0 14px;
}

.aoc-audit-summary dt {
    font-weight: 600;
    color: var(--aoc-text-secondary);
}

.aoc-audit-summary dd {
    margin: 0;
    overflow-wrap: anywhere;
}

.aoc-audit-key-parts {
    margin: 0;
    padding: 0;
    list-style: none;
}

.aoc-audit-values {
    table-layout: fixed;
}

.aoc-audit-values th[scope="col"]:first-child {
    width: 25%;
}

.aoc-audit-values th,
.aoc-audit-values td {
    padding-top: 6px;
    padding-bottom: 6px;
    vertical-align: top;
    overflow-wrap: anywhere;
}

/* Only the value itself keeps its spaces and line breaks: the cell's own markup whitespace stays collapsed. */
.aoc-audit-values .aoc-audit-value,
.aoc-audit-key-parts .aoc-audit-value {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* --- Lists (D1) --------------------------------------------------------------------------------
   The Lists screen (Views/Lists, plan Decision 12): the chooser row (a labelled select and Show, the default button at the
   control's height, on one line that wraps on a narrow pane), then the list as a plain .aoc-table at the board's row
   height: the code in monospace, the sort order in tabular figures, Active as plain text and Inactive as the neutral chip
   on a muted row, and Edit and Deactivate or Reactivate as the 28 px row buttons, centred in the row. The item form shows
   a stored code as text. Tokens only: blue is New and Save, red the field errors and the alert region only. */

.aoc-lists-chooser {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 8px 14px;
    margin: 0 0 14px;
}

.aoc-lists-chooser > .aoc-field {
    margin-bottom: 0;
}

.aoc-lists-chooser .aoc-input {
    min-width: 200px;
}

.aoc-lists-chooser > .aoc-button-row {
    height: var(--aoc-control-height);
}

.aoc-lists-table caption {
    padding: 0 0 6px;
    text-align: left;
    font-weight: 600;
    color: var(--aoc-text-primary);
}

/* Visual check V1: the board's 36 px header (compact 28), as on the Features table; .aoc-table th alone takes the 40 px
   row height. */
.aoc-lists-table th {
    height: calc(var(--aoc-row-height) - 4px);
}

.aoc-lists-table td {
    box-sizing: border-box;
    padding-top: calc((var(--aoc-row-height) - 28px) / 2);
    padding-bottom: calc((var(--aoc-row-height) - 28px) / 2);
    vertical-align: middle;
}

.aoc-lists-table code,
.aoc-lists-code code {
    font-family: Consolas, 'Cascadia Mono', 'Courier New', monospace;
    font-size: 12px;
    color: var(--aoc-text-primary);
}

.aoc-lists-table tr.aoc-muted code {
    color: var(--aoc-text-muted);
}

.aoc-lists-sort {
    font-variant-numeric: tabular-nums;
}

.aoc-lists-actions {
    display: flex;
    align-items: center;
    gap: 8px;
}

.aoc-lists-actions > form {
    margin: 0;
}

/* The label of a value shown as text (a stored code), as a field's label is drawn. */
.aoc-field-label {
    font-size: 12px;
    color: var(--aoc-text-muted);
}

.aoc-lists-code {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: var(--aoc-control-height);
}

.aoc-lists-code-input,
.aoc-lists-sort-input {
    max-width: 200px;
}

/* --- Customers (D1) ----------------------------------------------------------------------------
   The Customers grid (Views/Customers, plan Decision 21). A held account's credit hold is board G's L219 "Credit hold"
   chip: the alert pair, --aoc-alert-fg on --aoc-alert-bg (held to AA by DesignTokenContrastTests). It is an alert
   status in its own cell, never a row fill: the row keeps the grid's own surface, and an inactive account is muted
   with the neutral chip. */

.aoc-chip[data-kind="alert"] {
    background: var(--aoc-alert-bg);
    color: var(--aoc-alert-fg);
}

/* A custom field's warning (Core D3 Task 5, Decision 10): a stored value that no longer fits its field, or a required one
   that is missing. A warning, never a field error: the warn pair of the warn chip, not red, and it never blocks a save.
   The required marker beside a custom field's label is secondary text. */
.aoc-field-warning {
    display: block;
    margin: 2px 0 0;
    padding: 6px 9px;
    border-radius: 3px;
    font-size: 12px;
    background: var(--aoc-warn-bg);
    color: var(--aoc-warn-fg);
}

.aoc-required-mark {
    color: var(--aoc-text-secondary);
    font-weight: 400;
}

/* The customer page (Views/Customers: Detail, New and the confirmation pages, Core D1 Task 9): three sections (Account,
   Ship-tos, Contacts), each an h2 over its content on the board's 14 px rhythm. A viewer's account is a read-only field
   list: labels in the muted 12 px of a field's label, values in the body text. The credit block is the form's fieldset,
   as inputs or as the same list with its note. An inactive customer's banner is neutral, the raised fill with secondary
   text: a state, not an alert, so never red. Tokens only: blue is Save and Create, red the field errors and the alert
   region only. */

.aoc-section {
    margin: 0 0 22px;
}

.aoc-section > h2 {
    margin: 0 0 10px;
    font-size: 15px;
    font-weight: 600;
}

.aoc-fields {
    display: grid;
    grid-template-columns: minmax(120px, max-content) minmax(0, 1fr);
    gap: 6px 14px;
    max-width: 640px;
    margin: 0 0 14px;
}

.aoc-fields > dt {
    font-size: 12px;
    color: var(--aoc-text-muted);
}

.aoc-fields > dd {
    margin: 0;
    min-height: 1em;
    overflow-wrap: anywhere;
}

/* Notes keep their line breaks. */
.aoc-fields-notes {
    white-space: pre-line;
}

.aoc-credit .aoc-fields {
    margin-bottom: 8px;
}

.aoc-customer-amount-text {
    font-variant-numeric: tabular-nums;
}

.aoc-banner[data-kind="neutral"] {
    background: var(--aoc-raised);
    color: var(--aoc-text-secondary);
}

.aoc-customer-number {
    font-variant-numeric: tabular-nums;
}

/* A toggle (tax exempt, credit hold): the box, its label beside it, and its hint under the label. */
.aoc-toggle {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 8px;
    align-items: center;
}

.aoc-toggle > .aoc-note {
    grid-column: 2;
    font-size: 12px;
}

.aoc-customer-country {
    max-width: 80px;
}

.aoc-customer-short,
.aoc-customer-amount,
.aoc-customer-number-input {
    max-width: 200px;
}

.aoc-customer-amount {
    font-variant-numeric: tabular-nums;
}

/* The shared custom-fields section's inputs (Views/Shared/_CustomFieldsSection, for any entity): the same width and
   figures as the customer page's short and amount inputs, under names no entity owns. */
.aoc-field-short,
.aoc-field-amount {
    max-width: 200px;
}

.aoc-field-amount {
    font-variant-numeric: tabular-nums;
}

.aoc-customer-table {
    margin-bottom: 8px;
}

.aoc-contact-group {
    margin: 0 0 14px;
}

.aoc-contact-group > .aoc-section-heading {
    margin-top: 0;
}

/* The ship-tos and contacts (Views/ShipTos, Views/CustomerContacts and the customer page's two sections, Core D1 Task 10).
   Each section's add link sits under its heading, and each row's actions are links in one line: all the default row
   button (.aoc-button-row), never the primary blue, which is the page's Save. A new ship-to's number is the account's
   fixed part, in the body text, beside the short suffix field. The delivery days are seven boxes in a wrapping row, and
   the receiving window two time fields side by side. Tokens only: no colour is set here. */

.aoc-section-actions {
    margin: 0 0 10px;
}

.aoc-customer-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

.aoc-shipto-number-input,
.aoc-shipto-number-text {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-height: var(--aoc-control-height);
}

.aoc-shipto-number-text {
    gap: 8px;
}

.aoc-shipto-suffix {
    max-width: 72px;
    font-variant-numeric: tabular-nums;
}

.aoc-shipto-days {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 18px;
}

.aoc-shipto-days > .aoc-check {
    margin-bottom: 0;
}

.aoc-shipto-window {
    display: flex;
    flex-wrap: wrap;
    gap: 0 14px;
}

.aoc-shipto-time {
    max-width: 140px;
    font-variant-numeric: tabular-nums;
}

.aoc-contact-owner {
    display: inline-flex;
    align-items: center;
    min-height: var(--aoc-control-height);
}

/* --- Custom fields (D3) ------------------------------------------------------------------------
   The custom-fields screen (Views/CustomFields, spec D3 §1): one group per extensible entity, its heading beside its New
   field button, then a plain .aoc-table at the board's row height, as on Lists: the key in monospace, In grid as the
   neutral chip and Leaving grid as the warn chip with the time the removal can finish, and the row's actions as the 28 px
   row buttons. The field form shows a fixed key, type and length as text, and a choice field's options as a small table
   (code as text, label input, Active box). A confirmation page lists the plan's figures in tabular figures. Tokens only:
   blue is New field and the confirming button, red the field errors and the alert region only. */

.aoc-cf-group {
    margin: 0 0 24px;
}

.aoc-cf-group-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px 14px;
    margin: 0 0 10px;
}

.aoc-cf-group-header > h2 {
    margin: 0;
    font-size: 15px;
    font-weight: 600;
    color: var(--aoc-text-primary);
}

.aoc-cf-table th,
.aoc-cf-options th {
    height: calc(var(--aoc-row-height) - 4px);
}

.aoc-cf-table td,
.aoc-cf-options td {
    box-sizing: border-box;
    padding-top: calc((var(--aoc-row-height) - 28px) / 2);
    padding-bottom: calc((var(--aoc-row-height) - 28px) / 2);
    vertical-align: middle;
}

.aoc-cf-table code,
.aoc-cf-options code,
.aoc-cf-fixed code,
.aoc-cf-form .aoc-note code {
    font-family: Consolas, 'Cascadia Mono', 'Courier New', monospace;
    font-size: 12px;
    color: var(--aoc-text-primary);
}

.aoc-cf-state {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 8px;
}

.aoc-cf-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

.aoc-cf-fixed {
    display: inline-flex;
    align-items: center;
    min-height: var(--aoc-control-height);
    color: var(--aoc-text-primary);
}

.aoc-cf-key-input {
    max-width: 320px;
}

.aoc-cf-length-input {
    max-width: 120px;
    font-variant-numeric: tabular-nums;
}

.aoc-cf-options-group {
    margin: 0 0 14px;
    padding: 0;
    border: 0;
    min-width: 0;
}

.aoc-cf-options-group > legend {
    padding: 0;
    margin: 0 0 6px;
    font-size: 12px;
    color: var(--aoc-text-muted);
}

.aoc-cf-options .aoc-input {
    min-width: 200px;
}

.aoc-cf-plan {
    margin: 0 0 14px;
    padding-left: 18px;
    color: var(--aoc-text-secondary);
    font-variant-numeric: tabular-nums;
}

.aoc-cf-plan > li {
    margin: 2px 0;
}

/* --- Items setup (Items plan, Task 3) ------------------------------------------------------------
   The categories table (Views/ItemSetup/Categories): each subcategory is the row under its category, its code set in from
   the category's by one level. The units and conversions tables are the Lists screen's (.aoc-lists-table). Nothing here
   draws a colour: the muted and chip states are the shared ones. */

.aoc-items-sub td:first-child {
    padding-left: 28px;
}

/* --- Grid state (D3) -----------------------------------------------------------------------------
   The Reset layout form above a grid that remembers its user's layout (Views/Shared/_GridLayoutReset). The button is the
   28 px row button (.aoc-button-row), never the primary blue, which belongs to the page's one main action; the form sits at
   the grid toolbar's far end. Nothing here draws a colour. */
.aoc-grid-reset {
    display: flex;
    justify-content: flex-end;
    margin: 0 0 8px;
}

/* --- Data access picker (D3) ---------------------------------------------------------------------
   The user form's warehouse picker (Views/Users/_UserForm, js/aoc-admin-picker.js, plan Decision 21): without script a
   checkbox list in columns, one box per warehouse; with script the list is hidden and a Kendo MultiSelect posts the same
   names. A kept option (a held code that is inactive or no longer in the list) is shown muted and italic, beside its
   "(inactive)" or "(not in the list)" label, so it reads as something to review. Tokens only. */
.aoc-scope-picker .aoc-fieldset {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(14em, 1fr));
    column-gap: 16px;
}

.aoc-scope-picker .aoc-fieldset > .aoc-note {
    grid-column: 1 / -1;
}

.aoc-scope-picker .aoc-kept label {
    color: var(--aoc-text-muted);
    font-style: italic;
}

.aoc-scope-picker [hidden] {
    display: none;
}

/* --- The company screen (PF-03 Task 5) -----------------------------------------------------------
   Views/Company: the profile (a form, or text for a viewer) beside the dials only our team changes. The side panel drops
   under the form on a narrow screen. A caution is the warn banner, never red; the tax-number rows are fields in a row of
   their own, and the buttons script unhides stay hidden until it runs. Tokens only. */
.aoc-company {
    display: grid;
    grid-template-columns: minmax(0, 640px) minmax(220px, 280px);
    gap: 0 24px;
    align-items: start;
}

.aoc-company-main {
    min-width: 0;
}

.aoc-company-dials {
    box-sizing: border-box;
    padding: 12px 14px;
    border: 1px solid var(--aoc-border-hairline);
    border-radius: 3px;
    background: var(--aoc-raised);
    color: var(--aoc-text-secondary);
}

.aoc-company-dials h2 {
    margin: 0 0 8px;
    font-size: 14px;
    font-weight: 600;
    color: var(--aoc-text-primary);
}

.aoc-company-dials ul {
    margin: 0 0 8px;
    padding: 0;
    list-style: none;
}

.aoc-company-dials li {
    margin: 0 0 4px;
    overflow-wrap: anywhere;
}

.aoc-company-warnings .aoc-banner {
    margin-bottom: 8px;
}

.aoc-company-tax-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.aoc-tax-row {
    margin: 0 0 10px;
    padding: 0 0 10px;
    border-bottom: 1px solid var(--aoc-border-hairline);
}

.aoc-company [hidden] {
    display: none;
}

/* The company's images (PF-03 Task 6): one block per kind, the picture and, for a manager, an upload form and Remove. The
   logo's preview is capped in CSS, since its pixel size can be large; the app mark is at most 64 px. The buttons are the
   default row buttons: Save stays the page's one blue control. Tokens only. */
.aoc-company-images h2 {
    margin: 0 0 8px;
    font-size: 14px;
    font-weight: 600;
}

.aoc-image-block {
    margin: 0 0 14px;
    padding: 0 0 14px;
    border-bottom: 1px solid var(--aoc-border-hairline);
}

.aoc-image-block h3 {
    margin: 0 0 4px;
    font-size: 13px;
    font-weight: 600;
}

.aoc-image-preview {
    display: block;
    max-width: 100%;
    max-height: 96px;
    margin: 8px 0;
    object-fit: contain;
    border: 1px solid var(--aoc-border-hairline);
    border-radius: 3px;
    background: var(--aoc-raised);
}

.aoc-image-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: end;
    margin-top: 8px;
}

.aoc-image-actions .aoc-field {
    margin-bottom: 0;
}

.aoc-image-actions form {
    margin: 0;
}

@media (max-width: 900px) {
    .aoc-company {
        grid-template-columns: minmax(0, 1fr);
    }

    .aoc-company-dials {
        margin-bottom: 14px;
    }
}
