/* ===================================================================
   AKSHAR ERP — DESIGN SYSTEM
   akshar-erp.css · v2.24.0 · 19 October 2026
   -------------------------------------------------------------------
   CHANGELOG
     2.24.0 19 Oct 2026 New parts of .ak-calendar (21.3): __long and
                        __short. Below 640px a day is too narrow for a
                        sentence, so __long (the words) is kept for screen
                        readers only and __short (a dot, aria-hidden) shows
                        that the day has something; the list under the
                        month says what. Above 640px nothing changes.
                        Specimen in the design book (Calendar of days).
                        First used by the Manav calendar, where "Holiday:
                        Gandhi Jayanti" broke letter by letter at 320px.
     2.23.0 18 Oct 2026 New. .ak-input-action (13.10): a field with one
                        button inside its end edge, the show-password eye
                        on the sign-in first (owner, 18 Oct). The button is
                        the existing .ak-btn--ghost.ak-btn--icon, placed,
                        not restyled: its focus ring, hover and 44px under
                        a finger come from the button. The field leaves
                        room so text never runs under it.
     2.22.0 18 Oct 2026 New variant: .ak-td-main--lead, a lead title, the
                        name a table is scanned by (a customer, a
                        destination). Its title stays on one line, so a
                        long prose column beside it cannot squeeze it onto
                        two; in a card table below 768px it wraps again.
                        Specimen in the design book (Table). First used by
                        Vidhi's document checklist, where "United Arab
                        Emirates" broke over two lines at 1280px.
     2.21.0 18 Oct 2026 New. .ak-facts (25.7): a list of labels and their
                        values, every value starting on one line. A <dl>
                        whose pairs are each a <div>; the label column is
                        as wide as the longest label, at most 40%, and on
                        a phone a label sits over its value. Pages built
                        it from .ak-inline-between rows, which put each
                        value wherever its label ended (seen on Manav's
                        My profile under the new skin).
     2.20.3 18 Oct 2026 Fix. A KPI figure never runs out of its tile.
                        A tile is a size container and its figure is
                        clamp(--ak-fs-body, 10.5cqi, --ak-fs-kpi): full size
                        where it fits, smaller in a narrow tile (a 15-
                        character money figure fits). A strip of four
                        is four across from 1200px; 768-1199px it is two
                        by two (with the rail open, four across left
                        each tile ~165px and 45,67,890.50 ran out of it,
                        seen on Vasuli at 1024px). The 1200px width is on
                        section 12's list (ak-contract).
     2.20.2 18 Oct 2026 Fix. A code marked to break, .ak-ref.ak-break,
                        now wraps. .ak-ref is nowrap in utilities and
                        .ak-break (overflow-wrap only) is in layout, so a
                        long UTR on Vasuli's advances never wrapped and
                        widened the table past the screen. The override
                        sits in utilities beside .ak-ref. The same pairing
                        in Nirikshan and Sales now wraps too.
     2.20.1 18 Oct 2026 The rail in the Manav skin (25.6): its group names
                        and counts at full ink. 3.1 draws them at .72 and
                        .8 opacity, which on the Manav blue is 3.37:1 and
                        3.80:1; at full ink, 5.00:1. Found by axe on the
                        first Manav pages (Task Box, My Access). The navy
                        rail (6.19, 7.31) and the dark skin are unchanged.
     2.20.0 18 Oct 2026 The Manav skin and its people components (Manav
                        Wave 1, owner 17-18 Oct). data-skin="manav" (1.14)
                        re-maps tokens only: actions and the header in
                        #1769C9 (5.38:1 on white; white on it 5.38), a
                        cooler page, Darwinbox's #1E7BE6 as --ak-skin-mark
                        for icons only; dark: #5AA2F0 (6.50 on the
                        surface), header #0E2D57. Same components, status
                        colours, type and focus ring (owner: system
                        colours, IBM Plex, HR pages only). New (25):
                        .ak-tiles--launcher with .ak-tile__icon and
                        __count; .ak-person and .ak-initials;
                        dialog.ak-drawer and --half; .ak-orgchain;
                        .ak-moodpicker and .ak-mood. Tokens
                        --ak-launcher-min, --ak-drawer-w, --ak-skin-mark.
                        Specimens in the design book (The Manav skin).
     2.19.1 17 Oct 2026 A field's edge can be seen (WCAG 1.4.11, 3:1 for
                        the boundary of a control). New tokens
                        --ak-line-control and --ak-line-control-hover. The
                        input, select, textarea, check, radio, secondary
                        button, stepper, token box, split button and
                        editable grid cell take them; table rules, menus,
                        steps and other dividers keep --ak-line-strong.
                        Light #BDB6A8 (2.02:1 on white) -> n-500 #8A8478
                        (3.72 on surface, 3.56 on surface-2, 3.29 on bg),
                        hover n-400 -> n-600 so it still darkens. Dark
                        #34405E (1.69) -> #6B7AA0 (4.06, 3.73, 4.43),
                        hover #8E9BBD. No change to layout.
     2.19.0 17 Oct 2026 A navigation tree, .ak-tree (24.1): nested records
                        picked one at a time, as disclosure navigation (a
                        button per row, a toggle per branch, the row on
                        show marked aria-current); and .ak-grid--tree
                        (24.2), the tree in a narrow column beside its
                        detail, stacked below 900px; token --ak-tree-w.
                        First use: Yojana, the 52-week plan (Company >
                        Vertical > Segment > Channel). Specimen in the
                        design book (Tree).
     2.18.0 15 Oct 2026 An open dialog prints alone (7 · Print): while a
                        dialog is open, the page behind it is left off the
                        paper and the dialog prints as a plain block, its
                        whole body, without its buttons or backdrop. First
                        use: Bhandar's Post a movement confirmation (2.15).
                        Specimen in the design book (Dialog).
     2.17.0 14 Oct 2026 A full-sheet dialog, dialog.ak-modal--sheet (4.11):
                        the modal filling the screen less the gutter, its
                        head and foot fixed and only its body scrolling;
                        the whole screen on a phone. First use: Bhandar's
                        New voucher (2.11). Specimen in the design book
                        (Dialog). The entry table (4.18): a field's error
                        message is as wide as the wide cell and wraps in
                        it, instead of running on one line across the
                        table, and its words start even under a figure.
     2.16.1 13 Oct 2026 Toasts fit a 320px screen: the stack is never wider
                        than the screen less its gutters, and a long word
                        wraps instead of running off the left edge.
     2.16.0 12 Oct 2026 The palette measured, and every rule back in a
                        layer (Block 6, D8 and D5). tools/ak-palette.mjs
                        computes CIEDE2000 between the status hues and
                        between the series, for normal vision and
                        simulated protanopia, deuteranopia and tritanopia
                        (Machado 2009), and each ink's contrast on its tint
                        and the page. Warning against failed was 2.0
                        (light) and 4.9 (dark) under deuteranopia, against
                        a floor of 10: the amber is re-stepped, nothing
                        else moves. --ak-warning, and so its ink, light
                        #8A6400 -> #4F3500 (a deeper amber; 10.0:1 on its
                        tint, was 4.74), dark #B88C1E -> #CF9B00 (6.00:1,
                        was 4.90). Its tints are unchanged. Every warning
                        chip, banner edge, age badge and KPI figure shows
                        it; specimen and figures in the design book
                        (Colour and ink). No change to layout. Layers: the
                        forced-colours rules of 19.16, 20.1, 21.1, 21.3
                        and 21.4 and the coarse-pointer rule of 20.1 sat
                        outside every layer; each is now in components
                        after the rule it overrides, the calendar's and
                        the matrix's raised to the specificity of the
                        rules they beat, so nothing wins that did not win
                        before. Sections 7 (print) and 8 (forced colours)
                        stay outside on purpose, each with an
                        ak-unlayered comment saying why;
                        tools/ak-contract.mjs fails any other.
     2.15.3 12 Oct 2026 The contract made true; no screen changes. The
                        breakpoint list (12) now names every width this
                        file uses, what it is for and who uses it, grouped
                        under sm/md/lg/xl where a width is an off-by-one
                        partner (479/480, 767/768, 1023/1024, 1279);
                        tools/ak-contract.mjs fails a width not on it.
                        Sections 20-23 have headings, and a contents list
                        below names all twenty-three. Removed a dead rule:
                        .ak-app[data-rail="collapsed"] .ak-rail__list
                        [hidden]{display:flex!important} (18.5) never
                        applied, because base's [hidden]{display:none
                        !important} wins (between !important rules the
                        earlier layer wins); a group the person folded
                        stays folded on a folded rail, as it already did.
                        Card tables (15.5) measured: Chromium keeps
                        table, row, columnheader and cell for
                        .ak-table--cards at 320px; noted there and in the
                        design book (Table, and Breakpoints).
     2.15.2 12 Oct 2026 Fix. On paper the bare frame's brand panel
                        (.ak-auth__brand, 18.7) lost its words: light ink
                        on a navy that browsers do not print. In print the
                        panel and everything in it have no background and
                        are set in --ak-ink, dark on white; the chrome's
                        ring is cleared (owner, 12 Oct 2026). Specimen: the
                        Sign-in section of the design book.
     2.15.1 11 Oct 2026 Fix. A menu (.ak-menu) opened from a button partway
                        across a narrow screen ran off one edge whichever way
                        it opened (Bhandar 2.1, the Items Actions menu at
                        320px: 300px wide from a button 193px in). A menu
                        with data-fit="content" is as wide as its words,
                        never wider than the screen less its gutters; a
                        page's menu script sets it when neither side fits.
     2.15.0 11 Oct 2026 The phone (Bhandar 1.7), each with a specimen in the
                        design book. The bottom tab bar (23.1): nav.ak-tabbar
                        of button.ak-tabbar__item[aria-current], a count
                        beside a label, and a More menu that opens upward;
                        shown at 640px and below, where the page pads itself
                        so nothing hides behind it, and the action bar and
                        toasts sit above it. The floating action (23.2):
                        .ak-fab, the page's one primary action, a labelled
                        pill fixed bottom-right, above the tab bar when there
                        is one. Two utilities (23.3): data-phone="only" and
                        data-phone="hide" show or hide an element at 640px
                        and below; they are !important in the utilities
                        layer so they also hold over a page's own rules
                        (an earlier layer's !important wins over a later
                        layer's normal declaration).
     2.14.0 11 Oct 2026 Two new components (Bhandar 1.8), each with a
                        specimen in the design book. The edit-in-place
                        grid (22.1): table.ak-table.ak-table--grid
                        [role=grid] whose cells are plain text; one Tab
                        stop into it, arrow keys move cell to cell, Enter,
                        F2 or typing opens the cell's field, Enter or Tab
                        keeps it, Escape undoes it, a click opens it. Its
                        behaviour is vendor/ak-grid.js. A cell has a least
                        and a most width (--ak-grid-cell, -wide, -max) and
                        wraps rather than cutting a word off; a changed cell
                        carries a rule and weight, the row says so in words.
                        Two frozen columns (22.2): .ak-table--stickycol2
                        holds the first two columns while the rest scroll
                        sideways; the first is a set width
                        (--ak-sticky-first) so the second knows where to sit.
     2.13.2 11 Oct 2026 The masthead search (.ak-masthead__right >
                        .ak-search, 18.x) is at least 15rem (240px) wide
                        above 900px: a crowded masthead let it shrink to
                        8rem, too short for a GRN or challan number
                        (Bhandar 1.2, the owner's call). From 900px down it
                        narrows and becomes a button as before. To make the
                        room, the chip in the masthead's right group (the
                        role and company scope) now leaves at 1365px, not
                        900px; the person menu still says the same. Measured
                        on Bhandar: with the chip, the page's name in the
                        trail is squeezed out at 1024 and 1280px (the
                        brand's words return above 1200px) and reads whole
                        from 1366px.
     2.13.1 11 Oct 2026 Fix. A sortable header (button.ak-sort in a table
                        head) meets the target floor again: its all:unset
                        also unset the 24px floor, and the touch rule did
                        not name it, so under a finger it was 18px. The
                        floor is now on the component's own rule and the
                        touch rule raises it to 44px. The same all:unset
                        took away its focus ring (as 2.0.3 found for
                        .ak-tab); it is given back. Found by Bhandar 1.6
                        (item-editor.html). Specimen: the Table section of
                        the design book now sorts.
     2.13.0 11 Oct 2026 One office, one menu (Aapurti audit, wave 3), each
                        with a specimen in the design book. Tabs that are
                        links (21.1): a.ak-tab with aria-current="page" is
                        drawn as the selected tab, for views kept at their
                        own addresses. Chips of words (21.2):
                        .ak-chipgroup--words sets the chip group (19.6) in
                        the reading face, for filters named in words.
                        .ak-calendar (21.3): days, Monday first, each
                        saying in words what falls on it, late days marked
                        and today ringed. .ak-matrix (21.4): two judgements
                        crossed, each cell a count with its risk written
                        in it. A strip of exactly six KPI tiles (21.5) is
                        two rows of three from 768px up. No change to any
                        page that does not use them, except six-tile strips.
     2.12.1 11 Oct 2026 Fix. A card table (.ak-table--cards, 15.5) names
                        its values again from 375 to 767px: 2.2.2 had put
                        the label rule inside the 374px block, so on most
                        phones a card showed bare values. Below 375px the
                        label still sits above its value.
     2.12.0 11 Oct 2026 Office polish (Aapurti audit, wave 1), each with a
                        specimen in the design book. The masthead trail
                        (2.6) stays on one line: each part keeps to its
                        line and the last one ends in an ellipsis, so a
                        long office name never stacks under 1,100px. The
                        masthead search keeps room for its words (8rem
                        above 900px; its placeholder is now "Search…"), and
                        below 1280px the trail drops its leading "Home /",
                        which the masthead's Home button already says, and
                        the brand mark keeps its monogram only (its words
                        were aria-hidden; the link keeps its name). .ak-tablescroll--viewport (4.6) holds
                        a long register to the height of the window, so its
                        header row stays in view while the rows scroll. A
                        row picked by the radio in its first cell is
                        highlighted like an aria-selected one (4.6).
                        .ak-disclosure (20.1): a <details> that opens to
                        say what a screen is for ("About this screen"),
                        closed by default. .ak-tag--legacy (20.2): a
                        short tag whose full meaning is in its title and
                        for a screen reader. A strip of exactly four KPI
                        tiles (20.1b) is one row of four from 768px up,
                        never three and an orphan. .ak-table--wraphead
                        (20.1c) lets a long column name take two lines.
                        No change to any page
                        that does not use them, except the trail, the
                        search and four-tile strips, which now behave so
                        on every page.
     2.11.1 11 Oct 2026 Below 768px the tab strip (4.8) bleeds into the
                        page gutter, which a drawer (4.11) does not have:
                        a drawer's tabs ran 12px past it at 320px, so the
                        drawer scrolled sideways (Anusandhan's project file;
                        Aapurti's enquiry drawer the same). In a drawer the
                        strip now keeps to the drawer's edge.
     2.11.0 10 Oct 2026 Two things the quotation journey (Bhav) lacked,
                        each with a specimen in the design book. The
                        search list (4.23): .ak-combobox around a search
                        box and .ak-listbox, the list it opens, fixed to
                        the box in the dialog's own layer so a table or a
                        sticky footer never clips it, opening upward when
                        there is no room below; options are
                        .ak-listbox__option (role="option",
                        aria-selected), with __name, __meta and __note,
                        and the typed letters in <mark>; a busy mark while
                        the search reads. The entry table on a phone
                        (4.18): .ak-table--entry.ak-table--cards becomes
                        one card per line below 768px, each field under
                        its column name from data-label, no field held to
                        a minimum width. No change to any page that does
                        not use them.
     2.10.0 9 Oct 2026  Audit Wave 4 (G-01, G-18). Three things the
                        system lacked, each with a specimen in the
                        design book. .ak-btn--lg (4.3), the third button
                        size, for the one primary step of a wizard or a
                        phone screen: token --ak-control-h-lg, 44px at
                        the default density, 38px compact, 48px
                        comfortable, never under the touch target where
                        the pointer is coarse. No text under 12px:
                        --ak-fs-micro (10.5px) and --ak-fs-tiny
                        (11.5px) are both 12px, the step dot's 9px figure
                        and the chart's 11.5px labels now ask for a
                        token, and .ak-num and .ak-ref, which were .94em
                        of their parent, never fall below 12px. Column
                        heads, chips and eyebrows are half a pixel
                        larger; --ak-ls-wide goes from .06em to .04em so a
                        column head is no wider than it was. Skeletons (4.14a): .ak-skeleton was one
                        bar whose sweep was invisible in the light theme
                        and a pale flash in the dark; it is now drawn in
                        the line colour in both, with --text, --label,
                        --title, --figure and --short sizes,
                        tr.ak-skeleton-row for a loading .ak-table,
                        .ak-kpi--skeleton, .ak-card--skeleton and
                        .ak-skeleton-lines. Still under reduced motion,
                        outlined in forced colours. The behaviour
                        (aria-busy, a hidden sentence, one polite
                        status) is vendor/ak-skeleton.js.
     2.9.2  9 Oct 2026  A select or number field straight in the filter
                        bar (4.5) was as wide as its longest option and,
                        below 768px, could not shrink: the conformity
                        page's retention filter ("Not deletable through
                        the ERP, no guard") was 339px and pushed the page
                        to 364px at 320px. Below 768px it now fits the
                        bar and the browser shortens the shown option.
                        The header of a page not yet on the system
                        (18.8) let a long module name keep its width
                        below 900px, so the person menu was pushed off
                        the screen (Product profiles, 328px at 320px):
                        its trail now truncates first, as 3.1 says.
                        No change wherever there was room.
     2.9.1  8 Oct 2026  Two narrow-screen defects found at 320px (RFQ
                        fix Block 4). The dialog head (4.11) let a long
                        unbroken title, an RFQ number, push its close
                        button off the screen: what sits beside the
                        close button may now shrink and a title breaks
                        inside a long word. A document-list row (4.15)
                        never wrapped, so a name with two buttons beside
                        it was squeezed to a letter a line: the row now
                        wraps, its buttons dropping below the name. The
                        steps (4.13) wrapped with their links left
                        pointing at nothing: under 640px the links are
                        not drawn and the numbered steps read in order.
                        No change wherever there was room.
     2.9.0  8 Oct 2026  .ak-tokenbox and .ak-token (13.9), a picked
                        value kept inside its field with a button that
                        removes it (RFQ fix Block 3: the vendor on a new
                        requisition). The status chip (4.7) says what
                        state a record is in and has no remove; this
                        says what was chosen and can be undone. The box
                        is the height of a control, so choosing and
                        removing never move the form. Works in both
                        themes and every density, by keyboard, at 320px
                        and in forced colours. Specimen in the design
                        book.
     2.8.0  8 Oct 2026  [data-ak-buildnote] (5 · STATES), audit G-02 and
                        the owner's decision: a note written for the
                        people building the ERP (why a screen is not
                        built, which page a door opens, a design note)
                        stays in the page but is shown only when a
                        Director turns on "Show build notes" in the
                        account menu, which sets data-build-notes="on"
                        on the root. Off by default, for everyone else
                        always. Specimen in the design book.
     2.7.1  8 Oct 2026  No visual change. The design-migration branch
                        merged into main: this changelog now carries its
                        2.6.1 line beside main's 2.7.0, and the design
                        book names the version it renders (it had said
                        2.6.0 on main and 2.6.1 on the branch).
     2.7.0  3 Oct 2026  .ak-board--fit and .ak-board__stack (4.17), for
                        the leads pipeline (owner: the board scrolled
                        sideways and left too much white space). From
                        1024px the lanes of a fit board share the width
                        instead of scrolling; a lane marked data-empty
                        keeps only its name and count, set upright; a
                        .ak-board__stack holds several lanes in one
                        column (Won, Lost and Dormant). Below 1024px it is
                        the ordinary board, which scrolls on its own.
                        Token --ak-board-lane-min. Specimen in the design
                        book. Numbered past 2.6.1, which the
                        design-migration branch has already used.
     2.6.1  3 Oct 2026  No visual change. Brought over from the
                        design-migration branch, where it was numbered 2.2.1
                        and then 2.4.1. The system now enforces itself in
                        CI: tools/ak-lint.mjs is a gate (a ratchet against
                        tools/ak-lint-baseline.json; it also reads the
                        markup scripts build), tools/ak-sweep.js draws every
                        page at 320px and runs axe-core as a floor, never a
                        pass, and tools/ak-bookshot.js compares the design
                        book base against head and refuses a change to this
                        file that moves the book without a version and a
                        CHANGELOG line.
     2.6.0  3 Oct 2026  Section 19, the working home, from the owner's home
                        prompt pack (Block 1). The pack was written against
                        2.0.0 and numbered itself 2.1.0 and "section 18";
                        this line is past both, so it is 2.6.0 and section
                        19 (18 is the frame). Not pasted verbatim: every
                        rule was checked against what 2.5.0 already has.
                        New, each with a specimen in the design book:
                        .ak-measures/.ak-measure (19.1, a tablist of
                        headline figures); .ak-wgrid/.ak-widget (19.2,
                        head, grip, title, links, body, scroll, foot,
                        resize, spans 4-12) and .ak-stamp; .ak-actions/
                        .ak-action (19.3, data-severity OVERDUE, DUE_TODAY,
                        DUE_SOON, OPEN on the existing status hues);
                        .ak-split (19.5); .ak-chipgroup/.ak-chiptog (19.6);
                        .ak-metrics/.ak-metric (19.7, with .ak-metric--wide,
                        a cell across the whole grid for a money figure);
                        .ak-tier (19.8);
                        .ak-greet (19.9); button.ak-chip (19.10);
                        .ak-avatar (19.11); .ak-filterbar--bare (19.13).
                        The menu (18.4) is extended, not redefined: a
                        menu without a modifier draws exactly as before;
                        .ak-menu--grouped and .ak-menu--kebab are the
                        list form, with __search, __group, __sep, a
                        disabled item, a trailing .ak-stamp and
                        data-align; .ak-menu--flow draws one in place.
                        Masthead (19.12): the entity picker's narrowing
                        written against .ak-select (the 2.0.0 rule named
                        select.ak-input and matched nothing; removed from
                        3.1), data-shed="900|480" on a control, and a
                        search that becomes a button below 640px. Tokens
                        --ak-measure-min, --ak-menu-min, --ak-menu-max,
                        --ak-menu-kebab-min, --ak-menu-max-h,
                        --ak-widget-h-sm/-md/-lg, --ak-tier-mark,
                        --ak-tier-step-min. Where the pack put responsive
                        rules in layout and column counts in utilities,
                        they are in components here: in layout they lose
                        to the component (section 1, rule 5) and in
                        utilities the phone's column count lost to them.
                        Where it used all:unset on a button, the reset is
                        written out, so the focus ring stays.
                        Fixes still needed in 2.5.0, made in place:
                        data-rail="collapsed" below 1024px is the drawer
                        shut, not a 56px column the main area was squeezed
                        into (3.1, pack 18.13b); a dimming scrim behind the
                        open drawer, which lets a tap through to the page's
                        own close handler (3.1, 18.20); the rail's foot
                        clears a phone's home bar (3.1, 18.18); a bare
                        .ak-select or .ak-input--num in a filter bar is as
                        wide as its content, not the whole row (4.5,
                        18.19); .ak-banner > p carries no paragraph margin
                        (4.9, 18.19). Already fixed in 2.x, not repeated:
                        the rail folded to icons (2.2.0, 18.5), the
                        masthead chip shed below 900px (2.0.1), the filter
                        bar stacking below 768px (2.0.1), the rail's foot
                        itself (2.2.0). Not applicable: 18.21 (the bar is a
                        column below 768px, and .ak-push here sits on a
                        real control, so hiding it would hide the control).
     2.5.0  3 Oct 2026  Four components for the access register, each
                        with a specimen in the design book:
                        .ak-permtable (4.19), a matrix of one radio per
                        level on a ladder, a level not offered shown as a
                        dash and a changed row marked in words as well as
                        a tint; .ak-grpset (4.20), pills on a group header
                        that set the whole group; .ak-actionbar (4.21), a
                        sticky bar in the flow with a change count and the
                        reason a button cannot act yet, which stays in its
                        place while there is nothing to act on
                        (data-idle); .ak-preset (4.22), a named starting
                        point that fills an editor and saves nothing. Tokens --ak-perm-level,
                        --ak-actionbar-reserve, --ak-preset-min and
                        --ak-shadow-rise (both themes). Fix: .ak-check
                        and .ak-radio are 44px tall under a finger; their
                        own rule, later in the same layer, undid the touch
                        rule (the trap .ak-switch fell into in 2.4.0).
     2.4.0  2 Oct 2026  Brought over with the Orders page from the
                        design-migration branch, where it was numbered 2.2.0
                        (the two lines numbered independently; this is the
                        same change). New component: .ak-table--entry (4.18),
                        a table whose cells are typed into, such as an
                        order's item lines: a field in a cell keeps a minimum
                        width (tokens --ak-entry-cell, --ak-entry-cell-wide
                        for the cell marked .ak-entry-wide), so the table
                        scrolls sideways in its own region instead of
                        squeezing a field to three letters. Specimen in the
                        design book. .ak-fieldset takes min-inline-size:0: a
                        browser's own min-content width let a wide table
                        inside a fieldset push the page sideways. .ak-switch
                        is 44px tall under a finger: its own rule, later in
                        the same layer, undid the touch rule.
     2.3.0  2 Oct 2026  New state: .ak-btn[aria-pressed="true"], a button
                        that stays on (a choice, a filter, a mode): the
                        action tint and a tick, the tick hidden from screen
                        readers. New layout: .ak-choices, a wrapping row of
                        them. Specimen in the design book (Buttons). First
                        used by sampark.html's forms, replacing its own
                        "chip" buttons. Fix: a stack's children keep their
                        height; inside a dialog's body the tab strip, which
                        scrolls sideways on its own, shrank to nothing.
     2.2.2  2 Oct 2026  Fixes. A button in .ak-td-actions keeps its label on
                        one line: the cell is nowrap, and a label that may
                        wrap made the table under-measure the column, so the
                        last action spilled past the table's edge. .ak-linkbtn
                        starts its text (a button centres by default; a lead
                        title that wrapped was centred in a scanned column).
                        In .ak-table--cards below 768px a cell's height is its
                        content's: the row height still applied, and a value
                        that wrapped ran over the next field. Below 375px a
                        card's label sits above its value, not beside it. A
                        card's actions line up (the table's between-button
                        margin no longer offsets the second one).
     2.2.1  2 Oct 2026  .ak-progress also styles a native <progress> (value
                        and max are properties a screen reader announces,
                        no width in a style). Specimen in the design book.
                        First used by vikray.html's target. .ak-formgrid--2's
                        280px track minimum is min(280px,100%), as the grids
                        already were: inside a card at 320px it pushed the
                        page sideways.
     2.2.0  2 Oct 2026  The group's own colours (owner's decision: "keep the
                        colours same as it is right now"): chrome and every
                        action in navy #0F2044, gold #C9A227 as the chrome's
                        one accent (--ak-accent, -soft, -ink, never a status),
                        warm neutrals on #F2F1ED paper. Dark theme on a navy
                        night, actions in light gold. Status hues unchanged.
                        Contrast computed: ink 15.3:1, muted 5.7:1 on paper,
                        gold 6.6:1 on navy, accent ink 5.4:1 on pale gold.
                        The masthead is now the chrome's navy across the full
                        width, and the focus ring on the rail and masthead is
                        white. New components, specimens in the design book
                        (section 18): .ak-brandmark, .ak-who, .ak-rolebadge,
                        .ak-menu, .ak-tiles and .ak-tile (arrangeable), .ak-auth
                        (the sign-in page), .ak-shellfoot, .ak-linkbtn; a
                        foldable rail (button.ak-rail__group, .ak-rail__list,
                        data-rail="collapsed"); data-frame="bare" on .ak-app.
                        Tokens are declared on :host as well as :root so the
                        shared header can draw them inside a shadow root on
                        pages not yet on the system.
     2.1.1  2 Oct 2026  The coordinating session's changes, made in parallel
                        and numbered v2.0.1 and v2.0.2 on its branch, folded
                        in under one number: complete, failed and the other
                        status chips read in a darker ink of their own hue
                        (--ak-*-ink, 5.5:1 or more), found on
                        site/compliance.html; .ak-tab's focus ring given back
                        in the components layer; a destructive button reads
                        in --ak-failed-ink (5:1 or more in both themes),
                        found on site/stores.html. Where both branches fixed
                        the same thing (muted ink, the rail's group labels,
                        ink on a filled button) the measured values of 2.0.1
                        below stand.
     2.1.0  2 Oct 2026  New component: .ak-board (4.17) - named lanes side by
                        side in a strip that scrolls sideways on its own,
                        each with a head, cards and an add box; lane width
                        is a token, --ak-board-lane. Specimen in the design
                        book. Owner's decision, for the Director's yearly
                        planner (its to-do board had no system component).
     2.0.5  2 Oct 2026  .ak-card__head wraps: a title, a chip and an aside
                        button pushed a 320px screen sideways under a
                        reader's text spacing. Found migrating Adhyaksh
                        screen 19.
     2.0.4  2 Oct 2026  .ak-btn wraps its label when there is no room
                        (white-space:normal, line-height 1.2, 4px block
                        padding) instead of pushing the page sideways: a
                        long action ("Accept an exception — CFO only") was
                        wider than a 320px screen under a reader's text
                        spacing. Found migrating Vitta screen 16.
     2.0.3  2 Oct 2026  .ak-tab and .ak-sort restore box-sizing:border-box
                        after all:unset, which had reset it to content-box
                        and beaten the base layer's border-box rule. A page's
                        own * rule had hidden it until Vikray was stripped.
     2.0.2  2 Oct 2026  .ak-modal works on a native <dialog> (owner's
                        decision): border and padding reset, a backdrop in
                        --ak-overlay, hidden while closed, a <form> inside
                        carries head/body/foot. The browser then supplies
                        the focus trap, Escape and focus return. Specimen:
                        site/design-book.html.
                        Contrast, found by the design book's own axe run:
                        --ak-complete #008A62 -> #007856 (3.75:1 on its
                        chip, now 4.72); --ak-failed #C8351A -> #C2321A
                        (4.43 -> 4.68); dark --ak-failed #E25640 -> #E25E48
                        (4.40 -> 4.63 on its chip, 4.49 -> 4.72 as negative
                        ink on a card). Lightness only; the hues stand.
     2.0.1  2 Oct 2026  --ak-focus and --ak-focus-w defined: section 13
                        used them and nothing declared them, so the focus
                        ring on checkboxes, radios, switches, selects,
                        steppers and read-only inputs drew nothing.
                        .ak-rail__item drops the link underline: a rail
                        of links is the commonest rail there is.
                        .ak-grid--2/--3/--kpi/--detail track minimums are
                        capped at 100%, so a grid never forces the page
                        sideways at 320px (WCAG 2.2 · 1.4.10).
                        Below 900px the masthead trail has flex-basis 0, so
                        it truncates before the masthead's controls overflow.
                        .ak-step__link left the target-size list: it is the
                        1px connector between steps, not a control, and the
                        24px floor drew it as a grey block.
                        The coarse-pointer 44px target rule moved from the
                        layout layer to components: in layout it lost to
                        .ak-btn--sm. The 24px floor stays in layout.
                        Contrast, measured with axe-core and by formula:
                        --ak-ink-muted (light) n-500 -> n-600 (3.71:1 on
                        --ak-bg, now 5.72:1); new --ak-on-fill for ink on a
                        filled hue, near-black in dark (white on the dark
                        info hue was 3.22:1, now 5.82:1); rail group label
                        opacity .62 -> .72 (dark 4.16:1, now 5.15:1).
                        .ak-kpi__value steps down to --ak-fs-h2 below
                        480px, so a money figure fits at 320px with raised
                        text spacing.
                        The filter bar's stacking rules below 768px moved
                        from layout to components (in layout, stretch lost
                        to the component's align-items:center), and the
                        search sizes to its content there (its 260px basis
                        had become a 260px-tall box).
     2.0.0  2 Oct 2026  Layered rewrite (tokens, base, layout,
                        components, states, utilities).
   -------------------------------------------------------------------
   One stylesheet. Every ERP screen imports this and adds nothing of
   its own except layout composition. A module that writes a colour,
   a font size or a spacing value by hand has broken the system.

   Traceability (see the Brand Book for the full map):
     ISO 9241-110  interaction principles  — self-descriptiveness,
                   conformity with expectations, error robustness
     ISO 9241-11   usability measures      — effectiveness, efficiency,
                   satisfaction
     ISO 9241-210  human-centred design    — the process that produced it
     WCAG 2.2 AA   accessibility           — contrast, focus, targets,
                   keyboard, status messages
   None of the ISO standards above is a certification scheme. WCAG 2.2
   Level AA conformance is claimable only from a recorded evaluation.

   CASCADE: everything lives in @layer. Later layers win regardless of
   selector specificity, which is what stops module CSS from fighting
   system CSS. A media query adds no specificity: a responsive override
   sits in the same layer as the rule it overrides, or it is dead.

   CONTENTS (tools/ak-contract.mjs checks each has its heading)
      1 Tokens                       13 Form controls
      2 Base                         14 States, the matrix
      3 Layout                       15 Table patterns
      4 Components                   16 Charts
      5 States                       17 Format
      6 Utilities                    18 The frame, the home, sign-in
      7 Print                        19 The working home
      8 Forced colours               20 Office polish
      9 Alignment                    21 One office, one menu
     10 Attention                    22 Editing in place
     11 Space and white space        23 The phone
     12 Responsive, the breakpoints  24 The tree
                                    25 People and the launcher
   =================================================================== */

@layer tokens, base, layout, components, states, utilities;

/* ===================================================================
   1 · TOKENS
   =================================================================== */
@layer tokens {

:root,:host{
  /* ---- 1.1 Brand -------------------------------------------------
     The ERP has NO decorative colour. Every colour carries meaning.
     The brand lives in the chrome, the typeface and the logotype —
     not in an ornamental accent. This is deliberate: on a dense
     screen, a colour that means nothing steals attention from one
     that means something. */
  /* 2.2.0: the group's own navy and gold (owner, 2 Oct 2026: "keep the
     colours same as it is right now"). Navy is the chrome and every
     action; gold is the chrome's one accent and never carries a status. */
  --ak-brand-900:#0A1630;   /* deepest chrome, rail on dark          */
  --ak-brand-800:#0F2044;   /* primary chrome — rail, masthead       */
  --ak-brand-700:#17305F;   /* chrome hover                          */
  --ak-brand-600:#1B3A63;   /* chrome active / selected rail item    */
  --ak-brand-100:#E4E8F1;   /* chrome tint on light surfaces         */
  --ak-accent:#C9A227;      /* gold: on the chrome only (6.6:1 on navy) */
  --ak-accent-soft:#F3E6B8; /* pale gold: a role or scope badge       */
  --ak-accent-ink:#7E510D;  /* text on pale gold (5.4:1)              */

  /* ---- 1.2 Neutrals ----------------------------------------------
     2.2.0: warm, like the paper the group's pages have always been on,
     so the greys read as chosen rather than inherited. */
  --ak-n-0:#FFFFFF;
  --ak-n-25:#FBFAF7;
  --ak-n-50:#F2F1ED;
  --ak-n-100:#E9E6DE;
  --ak-n-200:#E2DED5;
  --ak-n-300:#BDB6A8;
  --ak-n-400:#A39E92;
  --ak-n-500:#8A8478;
  --ak-n-600:#625E55;
  --ak-n-700:#45423B;
  --ak-n-800:#2A2925;
  --ak-n-900:#131B26;
  --ak-n-950:#0B1020;

  /* ---- 1.3 Status ------------------------------------------------
     Five semantic hues. Validated for colour-vision separation,
     lightness band, chroma floor and contrast against the surface —
     computed, not eyeballed. Separation and contrast are computed by
     tools/ak-palette.mjs, in CI; its floors are at the top of it.

     THERE IS NO SIXTH HUE FOR "OVERDUE". Overdue is a TIME dimension,
     not a state: red and magenta cannot be told apart reliably even
     with full colour vision. Overdue renders as the record's existing
     state chip plus an age badge — "Approval required · 6 days late" —
     which tells the reader what is late AND by how much. A colour
     never could. */
  --ak-info:#0F6CBD;
  --ak-warning:#4F3500;    /* 2.16.0: was #8A6400, 2.0 from failed under deuteranopia */
  --ak-approval:#6B46C6;
  --ak-complete:#007856;   /* 2.0.2: was #008A62, 3.75:1 on its chip */
  --ak-failed:#C2321A;     /* 2.0.2: was #C8351A, 4.43:1 on its chip */
  --ak-neutral:#54636E;          /* draft, inactive, not started     */

  --ak-info-bg:#E6F0FA;
  --ak-warning-bg:#F8F0DC;
  --ak-approval-bg:#EEEAFA;
  --ak-complete-bg:#DFF2EB;
  --ak-failed-bg:#FBE7E2;
  --ak-neutral-bg:#EDF0F2;

  /* Text on a status tint. The hue itself is for dots, bars and
     borders; on its own pale tint at chip size two hues fell under
     4.5:1, so their text is one step darker. Same hue, same word. */
  --ak-info-ink:var(--ak-info);
  --ak-warning-ink:var(--ak-warning);
  --ak-approval-ink:var(--ak-approval);
  --ak-complete-ink:#006B4C;
  --ak-failed-ink:#A82A12;

  /* Interaction is the chrome's navy (2.2.0), so a button reads as the
     group's own and the information hue is left to mean information. */
  --ak-action:var(--ak-brand-800);
  --ak-action-hover:var(--ak-brand-700);
  --ak-action-bg:var(--ak-brand-100);

  /* ---- 1.4 Semantic surfaces ------------------------------------- */
  --ak-bg:var(--ak-n-50);
  --ak-surface:var(--ak-n-0);
  --ak-surface-2:var(--ak-n-25);
  --ak-sunk:var(--ak-n-100);
  --ak-line:var(--ak-n-200);
  --ak-line-strong:var(--ak-n-300);
  --ak-line-control:var(--ak-n-500);  /* a field's edge: 3.72:1 on surface, 3.29 on bg (n-300 was 2.02) */
  --ak-line-control-hover:var(--ak-n-600);
  --ak-ink:var(--ak-n-900);
  --ak-ink-2:var(--ak-n-700);
  --ak-ink-muted:var(--ak-n-600);   /* n-500 was 3.71:1 on --ak-bg; n-600 is 5.72 */
  --ak-ink-inverse:var(--ak-n-0);
  /* Ink on a filled status hue (primary and approve buttons, a complete
     step's dot). White on the light hues; near-black on the lighter dark-
     theme hues, where white measured 3.2:1. */
  --ak-on-fill:#FFFFFF;
  --ak-chrome:var(--ak-brand-800);
  --ak-chrome-ink:#D8D3C6;
  --ak-chrome-ink-strong:#FFFFFF;
  --ak-overlay:rgba(11,16,32,.46);
  /* 2.2.0: the chrome's own hairline, hover wash and field fill, used
     only on the navy masthead and rail. */
  --ak-chrome-line:rgba(255,255,255,.12);
  --ak-chrome-hover:rgba(255,255,255,.08);
  --ak-chrome-field:rgba(255,255,255,.07);

  /* ---- 1.5 Type --------------------------------------------------
     One family, three roles. IBM Plex was drawn for technical and
     enterprise interfaces: it holds up at 12–13px, its figures are
     properly tabular, and IBM Plex Sans Devanagari covers the group's
     Sanskrit office names in the same voice. A display serif was
     considered and rejected — on an ERP it slows scanning and buys
     nothing. */
  --ak-font-ui:"IBM Plex Sans","IBM Plex Sans Devanagari",system-ui,
               -apple-system,"Segoe UI",Roboto,sans-serif;
  --ak-font-mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,
               Consolas,monospace;

  /* Scale — a 1.167 ratio from a 14px UI base. Deliberately shallow:
     ERP screens need many close sizes, not a few dramatic ones. */
  /* 2.10.0: nothing is set below 12px (audit G-01). micro and tiny were
     10.5 and 11.5; both are now the floor. The names stay, so no rule
     that asks for them has to change. */
  --ak-fs-micro:12px;     /* legal lines, table footnotes            */
  --ak-fs-tiny:12px;      /* eyebrows, column heads, chips           */
  --ak-fs-small:12.5px;   /* secondary cell text, helper text        */
  --ak-fs-table:13px;     /* table body — the most-read size here    */
  --ak-fs-base:14px;      /* UI default                              */
  --ak-fs-body:15px;      /* reading text, descriptions              */
  --ak-fs-h4:16px;
  --ak-fs-h3:18px;
  --ak-fs-h2:21px;
  --ak-fs-h1:25px;
  --ak-fs-kpi:30px;       /* KPI tile figure                         */
  --ak-fs-kpi-lg:38px;    /* single hero figure                      */

  --ak-fw-regular:400;
  --ak-fw-medium:500;
  --ak-fw-semibold:600;
  --ak-fw-bold:700;

  --ak-lh-tight:1.2;
  --ak-lh-snug:1.35;
  --ak-lh-normal:1.5;
  --ak-lh-relaxed:1.62;

  --ak-ls-tight:-.012em;  /* headings                                */
  --ak-ls-normal:0;
  /* 2.10.0: .06em to .04em as column heads went from 11.5px to 12px, so
     a head is no wider than it was and the columns beside it keep room */
  --ak-ls-wide:.04em;     /* eyebrows, column heads                  */
  --ak-ls-caps:.08em;     /* uppercase labels                        */

  /* ---- 1.6 Space — 4px base -------------------------------------- */
  --ak-s-0:0;
  --ak-s-1:4px;
  --ak-s-2:8px;
  --ak-s-3:12px;
  --ak-s-4:16px;
  --ak-s-5:20px;
  --ak-s-6:24px;
  --ak-s-7:32px;
  --ak-s-8:40px;
  --ak-s-9:48px;
  --ak-s-10:64px;

  /* ---- 1.7 Density ------------------------------------------------
     Desktop ERP default. Set data-density on <html> to change it
     globally, or on a container to change one region. */
  --ak-row-h:36px;
  --ak-row-pad-y:7px;
  --ak-row-pad-x:12px;
  --ak-control-h:34px;
  /* The large button (4.3, 2.10.0): one step up from a control in every
     density, and at the default it clears the 44px touch target. */
  --ak-control-h-lg:44px;
  --ak-section-gap:var(--ak-s-6);

  /* ---- 1.8 Shape and depth --------------------------------------- */
  --ak-r-xs:3px;
  --ak-r-sm:5px;
  --ak-r-md:7px;
  --ak-r-lg:10px;
  --ak-r-pill:999px;
  --ak-border:1px;

  /* Shadow is spent sparingly: it means "this floats above the page",
     and almost nothing in an ERP does. */
  --ak-shadow-raised:0 1px 2px rgba(20,28,34,.07);
  --ak-shadow-overlay:0 2px 4px rgba(20,28,34,.08),
                      0 12px 32px -10px rgba(20,28,34,.26);
  --ak-shadow-sticky:0 4px 10px -8px rgba(20,28,34,.5);
  /* The same edge cast upward, for a bar that sticks to the bottom (4.21). */
  --ak-shadow-rise:0 -4px 10px -8px rgba(20,28,34,.5);

  /* ---- 1.9 Motion -------------------------------------------------
     Short, and only where it explains a change of state. An ERP that
     animates is an ERP that feels slow. */
  --ak-dur-instant:80ms;
  --ak-dur-fast:140ms;
  --ak-dur-base:200ms;
  --ak-ease-out:cubic-bezier(.2,.8,.3,1);
  --ak-ease-in-out:cubic-bezier(.4,0,.2,1);

  /* ---- 1.9a Focus -------------------------------------------------
     The one focus ring (base 2.1) in token form, for the controls that
     draw their own outline. Reserved: never reused for emphasis. */
  --ak-focus:var(--ak-action);
  --ak-focus-w:2px;

  /* ---- 1.10 Layers ------------------------------------------------ */
  --ak-z-base:0;
  --ak-z-sticky:20;
  --ak-z-rail:40;
  --ak-z-masthead:50;
  --ak-z-dropdown:60;
  --ak-z-drawer:70;
  --ak-z-modal:80;
  --ak-z-toast:90;

  /* ---- 1.11 Frame ------------------------------------------------- */
  --ak-rail-w:236px;
  --ak-rail-w-collapsed:56px;
  --ak-masthead-h:52px;
  --ak-content-max:1680px;
  --ak-reading-max:72ch;
  /* A board lane (4.17): wide enough for a short note to read in two or
     three lines, narrow enough that four lanes show at 1280. */
  --ak-board-lane:232px;
  --ak-board-lane-min:9rem;     /* 2.7.0: the least a lane of a fit board narrows to */
  /* A field typed into inside a table cell (4.18): a quantity or a unit
     fits the narrow width; a name or a search fits the wide one. */
  --ak-entry-cell:4.5rem;
  --ak-entry-cell-wide:12rem;
  /* An edit-in-place grid's cell (22.1): the least a cell narrows to, the
     least a name's cell narrows to, and the most a cell grows before its
     words wrap. The first of two frozen columns (22.2) is a set width. */
  --ak-grid-cell:6rem;
  --ak-grid-cell-wide:14rem;
  --ak-grid-cell-max:20rem;
  --ak-sticky-first:9rem;
  /* The bottom tab bar (23.1): one height, so the page, the action bar,
     the toasts and the floating action all know where it ends. */
  --ak-tabbar-h:3.5rem;
  /* A permission matrix (4.19): one level column, wide enough for the
     word "Chief" over a radio. */
  --ak-perm-level:4.25rem;
  /* The room a sticky action bar (4.21) keeps clear at the bottom of the
     page when focus moves, so a focused row is never hidden under it. */
  --ak-actionbar-reserve:7.5rem;
  /* A preset card (4.22): the narrowest it may be before the row wraps. */
  --ak-preset-min:15rem;
  /* The working home (19). A measure cell (19.1) is wide enough for an
     office's name in capitals over a six-figure count. A list menu
     (19.4) is at least wide enough for a screen's name and at most a
     comfortable line; it scrolls past --ak-menu-max-h. A widget that
     scrolls (19.2) is one of three heights. A tier mark (19.8) holds a
     single figure or a tick; a stage is never narrower than its name. */
  --ak-measure-min:9rem;
  --ak-menu-min:16rem;
  --ak-menu-max:26rem;
  --ak-menu-kebab-min:12.5rem;
  --ak-menu-max-h:26rem;
  --ak-widget-h-sm:13.5rem;
  --ak-widget-h-md:18.75rem;
  --ak-widget-h-lg:26.25rem;
  --ak-tier-mark:1.375rem;
  --ak-tier-step-min:5rem;
  /* 2.20.0: a launcher tile (25.1) is never narrower than a two-word name
     under its icon; a drawer (25.3) is never narrower than a form. The
     skin's mark (1.14) is the ink of an icon; outside a skin it is the
     action colour. */
  --ak-launcher-min:8.5rem;
  --ak-drawer-w:32.5rem;
  --ak-skin-mark:var(--ak-action);

  color-scheme:light dark;
}

/* ---- 1.12 Dark theme -----------------------------------------------
   Selected, not inverted. Status hues are re-stepped for the dark
   surface and re-validated; the light values would fail contrast. */
@media (prefers-color-scheme:dark){ :root:not([data-theme="light"]),:host(:not([data-theme="light"])){
  --ak-bg:var(--ak-n-950);
  --ak-surface:#131A2B;
  --ak-surface-2:#18213A;
  --ak-sunk:#0E1424;
  --ak-line:#26304A;
  --ak-line-strong:#34405E;
  --ak-line-control:#6B7AA0;
  --ak-line-control-hover:#8E9BBD;
  --ak-ink:#E8E6E0;
  --ak-ink-2:#C4C0B5;
  --ak-ink-muted:#9A968C;
  --ak-ink-inverse:var(--ak-n-950);
  --ak-on-fill:var(--ak-n-950);
  --ak-chrome:#0A1630;
  --ak-chrome-ink:#C9C4B6;
  --ak-chrome-ink-strong:#FFFFFF;
  --ak-overlay:rgba(3,6,14,.66);

  --ak-info:#3E95DB;
  --ak-warning:#CF9B00;    /* 2.16.0: was #B88C1E, 4.9 from failed under deuteranopia */
  --ak-approval:#9A80E6;
  --ak-complete:#1FA189;
  --ak-failed:#E25E48;
  --ak-neutral:#9A968C;

  --ak-info-bg:#13283A;
  --ak-warning-bg:#2E2512;
  --ak-approval-bg:#231E3D;
  --ak-complete-bg:#0E2B27;
  --ak-failed-bg:#331813;
  --ak-neutral-bg:#1C2336;
  --ak-info-ink:var(--ak-info);
  --ak-warning-ink:var(--ak-warning);
  --ak-approval-ink:var(--ak-approval);
  --ak-complete-ink:var(--ak-complete);
  --ak-failed-ink:#EE6B55;

  --ak-action:#D9B84A;
  --ak-action-hover:#E8CB6A;
  --ak-action-bg:#2A2716;
  --ak-brand-100:#1C2A4A;
  --ak-accent-soft:#3A3115;
  --ak-accent-ink:#E8CB6A;

  --ak-shadow-raised:0 1px 2px rgba(0,0,0,.5);
  --ak-shadow-overlay:0 2px 4px rgba(0,0,0,.5),
                      0 14px 36px -12px rgba(0,0,0,.8);
  --ak-shadow-sticky:0 4px 12px -8px rgba(0,0,0,.9);
  --ak-shadow-rise:0 -4px 12px -8px rgba(0,0,0,.9);
}}
:root[data-theme="dark"],:host([data-theme="dark"]){
  --ak-bg:var(--ak-n-950);
  --ak-surface:#131A2B;
  --ak-surface-2:#18213A;
  --ak-sunk:#0E1424;
  --ak-line:#26304A;
  --ak-line-strong:#34405E;
  --ak-line-control:#6B7AA0;
  --ak-line-control-hover:#8E9BBD;
  --ak-ink:#E8E6E0;
  --ak-ink-2:#C4C0B5;
  --ak-ink-muted:#9A968C;
  --ak-ink-inverse:var(--ak-n-950);
  --ak-on-fill:var(--ak-n-950);
  --ak-chrome:#0A1630;
  --ak-chrome-ink:#C9C4B6;
  --ak-chrome-ink-strong:#FFFFFF;
  --ak-overlay:rgba(3,6,14,.66);
  --ak-info:#3E95DB;
  --ak-warning:#CF9B00;    /* 2.16.0: was #B88C1E, 4.9 from failed under deuteranopia */
  --ak-approval:#9A80E6;
  --ak-complete:#1FA189;
  --ak-failed:#E25E48;
  --ak-neutral:#9A968C;
  --ak-info-bg:#13283A;
  --ak-warning-bg:#2E2512;
  --ak-approval-bg:#231E3D;
  --ak-complete-bg:#0E2B27;
  --ak-failed-bg:#331813;
  --ak-neutral-bg:#1C2336;
  --ak-info-ink:var(--ak-info);
  --ak-warning-ink:var(--ak-warning);
  --ak-approval-ink:var(--ak-approval);
  --ak-complete-ink:var(--ak-complete);
  --ak-failed-ink:#EE6B55;
  --ak-action:#D9B84A;
  --ak-action-hover:#E8CB6A;
  --ak-action-bg:#2A2716;
  --ak-brand-100:#1C2A4A;
  --ak-accent-soft:#3A3115;
  --ak-accent-ink:#E8CB6A;
  --ak-shadow-raised:0 1px 2px rgba(0,0,0,.5);
  --ak-shadow-overlay:0 2px 4px rgba(0,0,0,.5),0 14px 36px -12px rgba(0,0,0,.8);
  --ak-shadow-sticky:0 4px 12px -8px rgba(0,0,0,.9);
  --ak-shadow-rise:0 -4px 12px -8px rgba(0,0,0,.9);
}

/* ---- 1.13 Density modes ------------------------------------------- */
[data-density="compact"]{
  --ak-row-h:30px; --ak-row-pad-y:4px; --ak-row-pad-x:10px;
  --ak-control-h:30px; --ak-section-gap:var(--ak-s-5);
  --ak-control-h-lg:38px;
  --ak-fs-table:12.5px;
}
[data-density="comfortable"]{
  --ak-row-h:44px; --ak-row-pad-y:11px; --ak-row-pad-x:14px;
  --ak-control-h:40px; --ak-section-gap:var(--ak-s-7);
  --ak-control-h-lg:48px;
}

/* ---- 1.14 The Manav skin (2.20.0) ----------------------------------
   Owner, 17-18 Oct 2026: the HR pages look like Darwinbox, in the
   group's system. A skin changes tokens and nothing else: the same
   components, the same five status colours, the same type (IBM Plex),
   the same focus ring. Set data-skin="manav" on <html> of an HR page
   (chro, manav, attendance, unnati, bharti, appraisal and the Manav
   pages; not payroll or vetan), or on any element to show it in place.
   Darwinbox's own blue #1E7BE6 is 4.17:1 on white (3.82 on the page),
   under the 4.5 words need: it is --ak-skin-mark, the ink of an icon
   only. Text and buttons take #1769C9 (5.38 on white, 4.93 on the page);
   the header is that blue with white ink (5.38), its quieter ink 5.0.
   Dark: #5AA2F0 is 6.50 on the surface. Measured by WCAG relative
   luminance, 18 Oct 2026.
   The chrome stays a filled band: a white header would put the white
   focus ring and washes of 2.1 and 3.1 on white. */
[data-skin="manav"]{
  --ak-brand-900:#0D3B78;
  --ak-brand-800:#1769C9;
  --ak-brand-700:#125AA8;
  --ak-brand-600:#0F4F9E;
  --ak-brand-100:#E8F1FC;
  --ak-accent:#FFFFFF;
  --ak-accent-soft:#E8F1FC;
  --ak-accent-ink:#0B4A96;
  --ak-action:#1769C9;
  --ak-action-hover:#125AA8;
  --ak-action-bg:#E8F1FC;
  --ak-focus:var(--ak-action);
  --ak-skin-mark:#1E7BE6;
  --ak-chrome:#1769C9;
  --ak-chrome-ink:#F2F7FE;
  --ak-chrome-ink-strong:#FFFFFF;
  --ak-bg:#F3F5F8;
  --ak-surface:#FFFFFF;
  --ak-surface-2:#F8FAFC;
  --ak-sunk:#E9EDF3;
  --ak-line:#DDE3EA;
  --ak-line-strong:#B4BDC8;
  --ak-line-control:#7D8794;
  --ak-line-control-hover:#5B6472;
  --ak-ink:#1A2230;
  --ak-ink-2:#3B4452;
  --ak-ink-muted:#5B6472;
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"])[data-skin="manav"],
  :root:not([data-theme="light"]) [data-skin="manav"]{
    --ak-brand-900:#071A33;
    --ak-brand-800:#0E2D57;
    --ak-brand-700:#133B70;
    --ak-brand-600:#174A8A;
    --ak-brand-100:#13233E;
    --ak-accent:#FFFFFF;
    --ak-accent-soft:#13233E;
    --ak-accent-ink:#9CC6F6;
    --ak-action:#5AA2F0;
    --ak-action-hover:#7DB6F4;
    --ak-action-bg:#13233E;
    --ak-focus:var(--ak-action);
    --ak-skin-mark:#5AA2F0;
    --ak-chrome:#0E2D57;
    --ak-chrome-ink:#C9D8EE;
    --ak-chrome-ink-strong:#FFFFFF;
    --ak-bg:var(--ak-n-950);
    --ak-surface:#131A2B;
    --ak-surface-2:#18213A;
    --ak-sunk:#0E1424;
    --ak-line:#26304A;
    --ak-line-strong:#34405E;
    --ak-line-control:#6B7AA0;
    --ak-line-control-hover:#8E9BBD;
    --ak-ink:#E8E6E0;
    --ak-ink-2:#C4C0B5;
    --ak-ink-muted:#9A968C;
  }
}
:root[data-theme="dark"][data-skin="manav"],
:root[data-theme="dark"] [data-skin="manav"]{
  --ak-brand-900:#071A33;
  --ak-brand-800:#0E2D57;
  --ak-brand-700:#133B70;
  --ak-brand-600:#174A8A;
  --ak-brand-100:#13233E;
  --ak-accent:#FFFFFF;
  --ak-accent-soft:#13233E;
  --ak-accent-ink:#9CC6F6;
  --ak-action:#5AA2F0;
  --ak-action-hover:#7DB6F4;
  --ak-action-bg:#13233E;
  --ak-focus:var(--ak-action);
  --ak-skin-mark:#5AA2F0;
  --ak-chrome:#0E2D57;
  --ak-chrome-ink:#C9D8EE;
  --ak-chrome-ink-strong:#FFFFFF;
  --ak-bg:var(--ak-n-950);
  --ak-surface:#131A2B;
  --ak-surface-2:#18213A;
  --ak-sunk:#0E1424;
  --ak-line:#26304A;
  --ak-line-strong:#34405E;
  --ak-line-control:#6B7AA0;
  --ak-line-control-hover:#8E9BBD;
  --ak-ink:#E8E6E0;
  --ak-ink-2:#C4C0B5;
  --ak-ink-muted:#9A968C;
}

} /* end layer tokens */

/* ===================================================================
   2 · BASE — reset, typography, focus, scrolling
   =================================================================== */
@layer base {

*,*::before,*::after{box-sizing:border-box}

html{
  -webkit-text-size-adjust:100%;
  /* Smooth in-page jumps, but never for someone who asked for less
     motion. WCAG 2.2 / 2.3.3. */
  scroll-behavior:smooth;
  /* Hash navigation must not land under the sticky masthead. */
  scroll-padding-top:calc(var(--ak-masthead-h) + var(--ak-s-4));
}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
}

body{
  margin:0;
  background:var(--ak-bg);
  color:var(--ak-ink);
  font-family:var(--ak-font-ui);
  font-size:var(--ak-fs-base);
  line-height:var(--ak-lh-normal);
  font-feature-settings:"cv05" 1,"ss01" 1;   /* plex: single-storey a, cleaner l */
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  text-rendering:optimizeLegibility;
}

/* 2.2.0: the shared header (vendor/globalnav.js) renders inside a shadow
   root on pages not yet on the system. Its host carries what body gives
   a system page, and nothing of the page around it gets in or out. */
:host{
  display:block;color:var(--ak-ink);font-family:var(--ak-font-ui);
  font-size:var(--ak-fs-base);line-height:var(--ak-lh-normal);
  -webkit-font-smoothing:antialiased;
}

h1,h2,h3,h4{
  margin:0;font-weight:var(--ak-fw-semibold);
  line-height:var(--ak-lh-tight);letter-spacing:var(--ak-ls-tight);
  text-wrap:balance;
}
h1{font-size:var(--ak-fs-h1)}
h2{font-size:var(--ak-fs-h2)}
h3{font-size:var(--ak-fs-h3)}
h4{font-size:var(--ak-fs-h4);letter-spacing:var(--ak-ls-normal)}
p{margin:0 0 var(--ak-s-3)}
p.ak-read{max-width:var(--ak-reading-max);line-height:var(--ak-lh-relaxed);
  font-size:var(--ak-fs-body)}

/* Every figure, code, identifier and quantity is monospaced with
   tabular figures so columns of numbers line up and a changing value
   does not make the row jump. */
.ak-num,.ak-code,code,kbd,samp{
  font-family:var(--ak-font-mono);
  font-variant-numeric:tabular-nums;
  font-feature-settings:"zero" 1;   /* slashed zero — 0 vs O matters */
}
.ak-num{font-size:max(var(--ak-fs-micro),.94em)}   /* never under 12px (2.10.0) */

a{color:var(--ak-action);text-decoration-thickness:1px;text-underline-offset:2px}
a:hover{color:var(--ak-action-hover)}

img,svg,video,canvas{max-width:100%;height:auto;display:block}
hr{border:0;border-top:var(--ak-border) solid var(--ak-line);margin:var(--ak-s-5) 0}
[hidden]{display:none!important}

/* ---- 2.1 Focus — WCAG 2.2 · 2.4.7, 2.4.11 ------------------------
   One focus treatment everywhere. Two rings so it survives on both a
   light control and a dark chrome without being re-specified. */
:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:2px solid var(--ak-action);
  outline-offset:2px;
  border-radius:var(--ak-r-xs);
  box-shadow:0 0 0 4px color-mix(in srgb,var(--ak-action) 22%,transparent);
}
.ak-chrome :where(a,button,[tabindex]):focus-visible,
.ak-rail :where(a,button,[tabindex]):focus-visible,
.ak-masthead :where(a,button,input,select,[tabindex]):focus-visible{
  outline-color:#FFFFFF;
  box-shadow:0 0 0 4px rgba(255,255,255,.26);
}
:focus:not(:focus-visible){outline:none}

::selection{background:color-mix(in srgb,var(--ak-action) 24%,transparent)}

/* ---- 2.2 Scroll surfaces ------------------------------------------
   Scrolling feels smooth when the browser is not asked to re-layout
   or repaint more than it must. Four rules do most of the work:
     · give every scroller its own containment,
     · stop scroll chaining out of panels,
     · let the browser skip off-screen work,
     · never animate a property that forces layout. */
.ak-scroll{
  overflow:auto;
  overscroll-behavior:contain;      /* no scroll chaining to the page */
  scrollbar-gutter:stable;          /* no width jump when bars appear */
  contain:layout paint;             /* isolate from the page's layout */
  -webkit-overflow-scrolling:touch;
}
.ak-scroll-x{overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain}

/* Long lists: let the browser skip rendering what is off screen.
   contain-intrinsic-size keeps the scrollbar honest while it does. */
.ak-virtual > *{
  content-visibility:auto;
  contain-intrinsic-size:auto var(--ak-row-h);
}

/* Scrollbars, styled so they read as part of the system rather than
   the operating system. Width is left alone on touch devices. */
@media (pointer:fine){
  .ak-scroll::-webkit-scrollbar,.ak-scroll-x::-webkit-scrollbar{width:11px;height:11px}
  .ak-scroll::-webkit-scrollbar-track,.ak-scroll-x::-webkit-scrollbar-track{
    background:transparent}
  .ak-scroll::-webkit-scrollbar-thumb,.ak-scroll-x::-webkit-scrollbar-thumb{
    background:var(--ak-n-300);border-radius:var(--ak-r-pill);
    border:3px solid transparent;background-clip:content-box}
  .ak-scroll::-webkit-scrollbar-thumb:hover,.ak-scroll-x::-webkit-scrollbar-thumb:hover{
    background:var(--ak-n-400);background-clip:content-box}
  .ak-scroll,.ak-scroll-x{scrollbar-width:thin;
    scrollbar-color:var(--ak-n-300) transparent}
}

/* Anchored sections clear the masthead when jumped to. */
[id]{scroll-margin-top:calc(var(--ak-masthead-h) + var(--ak-s-4))}

/* ---- 2.3 Skip link — WCAG 2.2 · 2.4.1 ---------------------------- */
.ak-skip{
  position:absolute;left:var(--ak-s-2);top:var(--ak-s-2);z-index:var(--ak-z-toast);
  transform:translateY(-200%);
  background:var(--ak-surface);color:var(--ak-ink);
  padding:var(--ak-s-2) var(--ak-s-4);border-radius:var(--ak-r-sm);
  box-shadow:var(--ak-shadow-overlay);font-weight:var(--ak-fw-semibold);
  transition:transform var(--ak-dur-fast) var(--ak-ease-out);
}
.ak-skip:focus{transform:translateY(0)}

/* ---- 2.4 Screen-reader-only ------------------------------------- */
.ak-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}

} /* end layer base */

/* ===================================================================
   3 · LAYOUT — the app frame and the screen template
   =================================================================== */
@layer layout {

/* ---- 3.1 App shell ------------------------------------------------
   Rail left, masthead top, one scrolling main. The rail and masthead
   never scroll; only main does. That single decision is most of why
   the ERP feels steady under the hand. */
.ak-app{
  display:grid;
  grid-template-columns:var(--ak-rail-w) minmax(0,1fr);
  grid-template-rows:var(--ak-masthead-h) minmax(0,1fr);
  grid-template-areas:"masthead masthead" "rail main";
  height:100dvh;
}
/* 2.2.0: the masthead runs the full width in the chrome's navy and
   carries the brand, so the rail's own brand row shows only when the
   rail is a drawer. A bare frame (signed out) has neither bar. */
.ak-app[data-frame="bare"]{grid-template-columns:minmax(0,1fr);
  grid-template-rows:minmax(0,1fr);grid-template-areas:"main"}
.ak-app[data-frame="bare"] > .ak-rail,.ak-app[data-frame="bare"] > .ak-masthead{display:none}
.ak-app[data-frame="bare"] > .ak-main{padding:0}
.ak-app[data-rail="collapsed"]{grid-template-columns:var(--ak-rail-w-collapsed) minmax(0,1fr)}

.ak-rail{
  grid-area:rail;background:var(--ak-chrome);color:var(--ak-chrome-ink);
  display:flex;flex-direction:column;min-height:0;
  z-index:var(--ak-z-rail);
  padding-top:env(safe-area-inset-top,0px);
}
.ak-rail__brand{
  height:var(--ak-masthead-h);display:flex;align-items:center;gap:var(--ak-s-3);
  padding-inline:var(--ak-s-4);flex:0 0 auto;
  border-bottom:var(--ak-border) solid rgba(255,255,255,.08);
}
.ak-rail__wordmark{
  font-weight:var(--ak-fw-bold);font-size:var(--ak-fs-h4);
  letter-spacing:var(--ak-ls-tight);color:var(--ak-chrome-ink-strong);
}
.ak-rail__nav{flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain;
  padding:var(--ak-s-3) var(--ak-s-2);scrollbar-width:thin}
.ak-rail__group{
  font-size:var(--ak-fs-tiny);text-transform:uppercase;
  letter-spacing:var(--ak-ls-caps);color:var(--ak-chrome-ink);opacity:.72;
  padding:var(--ak-s-3) var(--ak-s-3) var(--ak-s-1);font-weight:var(--ak-fw-semibold);
}
/* 2.2.0: a group label may be a button that folds its group away. */
button.ak-rail__group{display:flex;align-items:center;gap:var(--ak-s-2);width:100%;
  background:none;border:0;cursor:pointer;font-family:inherit;text-align:left;
  border-radius:var(--ak-r-sm)}
button.ak-rail__group:hover{opacity:1;color:var(--ak-chrome-ink-strong)}
button.ak-rail__group::after{content:"\25BE";margin-left:auto;
  transition:transform var(--ak-dur-fast) var(--ak-ease-out)}
button.ak-rail__group[aria-expanded="false"]::after{transform:rotate(-90deg)}
.ak-rail__list{display:flex;flex-direction:column;gap:2px}
.ak-rail__icon{flex:0 0 auto;inline-size:var(--ak-s-5);text-align:center}
.ak-rail__label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ak-rail__foot{flex:0 0 auto;padding:var(--ak-s-2);
  border-top:var(--ak-border) solid var(--ak-chrome-line);
  /* 2.6.0: the foot is the rail's last row, so in the drawer on a phone it
     clears the home bar. Zero wherever there is no inset. */
  padding-bottom:calc(var(--ak-s-2) + env(safe-area-inset-bottom,0px))}
.ak-rail__item{
  display:flex;align-items:center;gap:var(--ak-s-3);width:100%;
  padding:6px var(--ak-s-3);border-radius:var(--ak-r-sm);
  color:var(--ak-chrome-ink);background:none;border:0;cursor:pointer;
  font:inherit;font-size:var(--ak-fs-base);text-align:left;text-decoration:none;
  transition:background var(--ak-dur-instant) var(--ak-ease-out);
}
.ak-rail__item:hover{background:rgba(255,255,255,.07);color:var(--ak-chrome-ink-strong)}
.ak-rail__item[aria-current="page"],.ak-rail__item.is-on{
  background:var(--ak-brand-600);color:var(--ak-chrome-ink-strong);
  font-weight:var(--ak-fw-medium);
}
.ak-rail__count{margin-left:auto;font-family:var(--ak-font-mono);
  font-size:var(--ak-fs-tiny);opacity:.8;font-variant-numeric:tabular-nums}

.ak-masthead{
  grid-area:masthead;background:var(--ak-chrome);color:var(--ak-chrome-ink);
  border-bottom:var(--ak-border) solid var(--ak-chrome-line);
  display:flex;align-items:center;gap:var(--ak-s-3);
  padding-inline:var(--ak-s-4);z-index:var(--ak-z-masthead);position:relative;
}
.ak-masthead__trail{font-size:var(--ak-fs-small);color:var(--ak-chrome-ink);
  display:flex;align-items:center;gap:var(--ak-s-2);min-width:0}
/* 2.12.0: one line at every width. Each part keeps to its line; the
   parts shrink, and the last ends in an ellipsis (its full text stays
   in the page for a screen reader). */
.ak-masthead__trail{flex:0 1 auto;flex-wrap:nowrap;overflow:hidden}
/* Beside the rail the masthead's own Home button says where home is, so
   the trail's first "Home /" gives its room to the screen's name. */
@media (max-width:1279px){
  .ak-masthead__trail > a:first-child[href="./index.html"],
  .ak-masthead__trail > a:first-child[href="./index.html"] + [aria-hidden="true"]{display:none}
}
.ak-masthead__trail > *{white-space:nowrap;flex:0 0 auto}
.ak-masthead__trail > :last-child{flex:0 1 auto;min-width:0;
  overflow:hidden;text-overflow:ellipsis}
.ak-masthead__trail > b:nth-last-child(2){flex:0 1 auto;min-width:0;
  overflow:hidden;text-overflow:ellipsis}
.ak-masthead__trail b{color:var(--ak-chrome-ink-strong);font-weight:var(--ak-fw-semibold);
  font-size:var(--ak-fs-base)}
.ak-masthead__trail a{color:var(--ak-chrome-ink)}
.ak-masthead__trail a:hover{color:var(--ak-chrome-ink-strong)}
.ak-masthead__nav{display:flex;align-items:center;gap:var(--ak-s-1);
  padding-inline:var(--ak-s-2);border-inline:var(--ak-border) solid var(--ak-chrome-line)}
.ak-masthead__right{margin-left:auto;display:flex;align-items:center;gap:var(--ak-s-2)}

.ak-main{
  grid-area:main;min-width:0;min-height:0;
  overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;
  contain:layout paint;
  padding:var(--ak-s-6) var(--ak-s-6) var(--ak-s-10);
}
.ak-page{max-width:var(--ak-content-max);margin-inline:auto;
  display:flex;flex-direction:column;gap:var(--ak-section-gap)}

/* Responsive: the rail becomes an overlay drawer below 1024px.
   Desktop-first for power users, but never broken on a tablet. */
@media (min-width:1024px){
  .ak-app:not([data-frame="bare"]) .ak-rail__brand{display:none}
}
@media (max-width:1023px){
  .ak-app{grid-template-columns:minmax(0,1fr);
    grid-template-areas:"masthead" "main"}
  .ak-rail{position:fixed;inset:0 auto 0 0;width:var(--ak-rail-w);
    transform:translateX(-100%);
    transition:transform var(--ak-dur-base) var(--ak-ease-out);
    box-shadow:var(--ak-shadow-overlay)}
  .ak-app[data-rail="open"] .ak-rail{transform:translateX(0)}
  .ak-main{padding:var(--ak-s-4) var(--ak-s-4) var(--ak-s-9)}
  /* 2.6.0: below 1024px "collapsed" means the drawer is shut, not a
     column. The collapsed rule above is (0,2,0) and sits outside any
     media query; the single-column rule here is (0,1,0), and a media
     query adds no specificity, so collapsed won and re-made a 56px
     column the grid had no area for: the main area was squeezed into
     it (measured: 56px wide at 800px). Restated here at equal weight,
     later in the same layer. */
  .ak-app[data-rail="collapsed"]{grid-template-columns:minmax(0,1fr)}
  /* 2.6.0: the open drawer dims what is now out of reach. The scrim lets
     a tap through (pointer-events:none) so the page's own handler, which
     listens on .ak-main, still closes the drawer; a scrim that swallowed
     the tap would leave it open with nothing listening. Below the rail
     and the masthead, so the menu button that closes it stays lit. */
  .ak-app[data-rail="open"]::after{content:"";position:fixed;inset:0;
    background:var(--ak-overlay);z-index:calc(var(--ak-z-rail) - 1);
    pointer-events:none}
}
@media (max-width:640px){
  .ak-main{padding:var(--ak-s-4) var(--ak-s-3) var(--ak-s-9)}
}
/* The masthead sheds its secondary items before it ever forces the page
   sideways. An ERP masthead that overflows takes the whole layout with
   it, so the shedding order is fixed here rather than per module:
   identity chip first, then the entity picker narrows, then the trail
   truncates. The trail and the menu button never go. */
@media (max-width:900px){
  .ak-masthead{padding-inline:var(--ak-s-3);gap:var(--ak-s-2)}
  /* Basis 0: the trail takes only the space the controls leave, so it is
     the trail that truncates, as the shedding order above says, and never
     the buttons that overflow. */
  .ak-masthead__trail{flex:1 1 0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
  .ak-masthead__right{min-width:0}
}
/* 2.6.0: the entity picker's narrowing (written here against
   select.ak-input, which matched no control: the system's select is
   .ak-select) is now 19.12, beside data-shed. */

/* ---- 3.2 The eleven-section screen template -----------------------
   Every module renders through this grammar, in this order. Sections
   6–10 are the shared control spine surfacing in the UI: workflow and
   approval come from the approval engine, activity from the message
   record, documents from the document store, audit from the audit log.
   If a module needs custom code for sections 6–10, the spine is wrong,
   not the screen. */
.ak-section{display:flex;flex-direction:column;gap:var(--ak-s-3)}
.ak-section__head{display:flex;align-items:baseline;gap:var(--ak-s-3);flex-wrap:wrap}
.ak-section__head h2,.ak-section__head h3{margin:0}
.ak-section__head .ak-section__aside{margin-left:auto;display:flex;
  align-items:center;gap:var(--ak-s-2)}
.ak-eyebrow{
  font-size:var(--ak-fs-tiny);text-transform:uppercase;
  letter-spacing:var(--ak-ls-caps);font-weight:var(--ak-fw-semibold);
  color:var(--ak-ink-muted);
}

/* Page header — identical on every screen in every module. */
.ak-pagehead{display:flex;flex-direction:column;gap:var(--ak-s-2)}
.ak-pagehead__row{display:flex;align-items:flex-start;gap:var(--ak-s-4);flex-wrap:wrap}
.ak-pagehead__actions{margin-left:auto;display:flex;gap:var(--ak-s-2);flex-wrap:wrap}
.ak-pagehead__intro{color:var(--ak-ink-2);font-size:var(--ak-fs-body);
  max-width:var(--ak-reading-max);margin:0}

/* Column grids used by dashboards and detail screens. */
.ak-grid{display:grid;gap:var(--ak-s-4)}
.ak-grid--kpi{grid-template-columns:repeat(auto-fit,minmax(min(180px,100%),1fr))}
/* min(…,100%): a track minimum wider than the container forces the page
   sideways. At 320px wide the content box is 296px, so a bare 320px
   minimum broke the 320 guarantee on every --2 grid. */
.ak-grid--2{grid-template-columns:repeat(auto-fit,minmax(min(320px,100%),1fr))}
.ak-grid--3{grid-template-columns:repeat(auto-fit,minmax(min(260px,100%),1fr))}
.ak-grid--detail{grid-template-columns:minmax(0,2fr) minmax(min(280px,100%),1fr)}
@media (max-width:1100px){.ak-grid--detail{grid-template-columns:minmax(0,1fr)}}

} /* end layer layout */

/* ===================================================================
   4 · COMPONENTS
   =================================================================== */
@layer components {

/* ---- 4.1 Surfaces -------------------------------------------------- */
.ak-card{
  background:var(--ak-surface);border:var(--ak-border) solid var(--ak-line);
  border-radius:var(--ak-r-md);box-shadow:var(--ak-shadow-raised);
}
.ak-card__head{
  display:flex;align-items:center;flex-wrap:wrap;gap:var(--ak-s-3);
  padding:var(--ak-s-3) var(--ak-s-4);
  border-bottom:var(--ak-border) solid var(--ak-line);
}
.ak-card__head h3{font-size:var(--ak-fs-h4)}
.ak-card__head .ak-card__aside{margin-left:auto;display:flex;gap:var(--ak-s-2)}
.ak-card__body{padding:var(--ak-s-4)}
.ak-card__foot{padding:var(--ak-s-3) var(--ak-s-4);
  border-top:var(--ak-border) solid var(--ak-line);
  background:var(--ak-surface-2);font-size:var(--ak-fs-small);
  color:var(--ak-ink-muted);border-radius:0 0 var(--ak-r-md) var(--ak-r-md)}

/* Border, fill, radius and shadow each say "separate object". Spend
   them by role. A card inside a card is almost always a mistake. */
.ak-panel{background:var(--ak-sunk);border-radius:var(--ak-r-sm);
  padding:var(--ak-s-4)}

/* ---- 4.2 KPI tile --------------------------------------------------
   Lead with these only when the figures ARE the point of the screen. */
.ak-kpi{
  background:var(--ak-surface);border:var(--ak-border) solid var(--ak-line);
  border-radius:var(--ak-r-md);padding:var(--ak-s-4);
  display:flex;flex-direction:column;gap:var(--ak-s-1);min-width:0;
  container-type:inline-size;   /* 2.20.3: the figure sizes to its tile */
}
.ak-kpi__label{font-size:var(--ak-fs-tiny);text-transform:uppercase;
  letter-spacing:var(--ak-ls-caps);color:var(--ak-ink-muted);
  font-weight:var(--ak-fw-semibold)}
.ak-kpi__value{font-family:var(--ak-font-mono);font-size:clamp(var(--ak-fs-body),10.5cqi,var(--ak-fs-kpi));
  font-weight:var(--ak-fw-semibold);line-height:1.05;
  font-variant-numeric:tabular-nums;letter-spacing:var(--ak-ls-tight)}
.ak-kpi__note{font-size:var(--ak-fs-small);color:var(--ak-ink-muted)}
.ak-kpi[data-state="failed"] .ak-kpi__value{color:var(--ak-failed)}
.ak-kpi[data-state="warning"] .ak-kpi__value{color:var(--ak-warning)}
.ak-kpi[data-state="complete"] .ak-kpi__value{color:var(--ak-complete)}
/* At the smallest breakpoint a figure steps down a size: a money figure
   at 30px mono cannot fit a 296px column once a reader raises letter-
   spacing (WCAG 2.2 · 1.4.12), and a figure must never be clipped. */
@media (max-width:479px){.ak-kpi__value{font-size:clamp(var(--ak-fs-body),10.5cqi,var(--ak-fs-h2))}}

/* ---- 4.3 Buttons ---------------------------------------------------
   Four roles, never more. A screen with six button styles has no
   hierarchy. Minimum target 24×24 CSS px (WCAG 2.2 · 2.5.8); our
   control height of 34px clears it with room. */
.ak-btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--ak-s-2);
  height:var(--ak-control-h);padding-inline:var(--ak-s-4);
  border-radius:var(--ak-r-sm);border:var(--ak-border) solid transparent;
  font:inherit;font-size:var(--ak-fs-base);font-weight:var(--ak-fw-medium);
  line-height:1;cursor:pointer;white-space:nowrap;text-decoration:none;
  transition:background var(--ak-dur-instant) var(--ak-ease-out),
             border-color var(--ak-dur-instant) var(--ak-ease-out),
             color var(--ak-dur-instant) var(--ak-ease-out);
}
.ak-btn:disabled,.ak-btn[aria-disabled="true"]{
  opacity:.45;cursor:not-allowed;pointer-events:none}
.ak-btn--primary{background:var(--ak-action);color:var(--ak-on-fill)}
.ak-btn--primary:hover{background:var(--ak-action-hover)}
.ak-btn--secondary{background:var(--ak-surface);color:var(--ak-ink);
  border-color:var(--ak-line-control)}
.ak-btn--secondary:hover{background:var(--ak-sunk)}
.ak-btn--ghost{background:transparent;color:var(--ak-ink-2)}
.ak-btn--ghost:hover{background:var(--ak-sunk);color:var(--ak-ink)}
/* Destructive is outlined, not filled. A red wall of buttons trains
   people to ignore red. */
.ak-btn--destructive{background:var(--ak-surface);color:var(--ak-failed-ink);
  border-color:color-mix(in srgb,var(--ak-failed) 48%,transparent)}
.ak-btn--destructive:hover{background:var(--ak-failed-bg)}
/* Approval is its own role because it is its own decision. */
.ak-btn--approve{background:var(--ak-approval);color:var(--ak-on-fill)}
.ak-btn--approve:hover{filter:brightness(1.08)}
.ak-btn--sm{height:26px;padding-inline:var(--ak-s-3);font-size:var(--ak-fs-small)}
/* The large button (2.10.0, audit G-01): the one primary step of a wizard,
   the single action of a phone screen. Three sizes and no fourth. It is a
   size, not a role: it takes primary, secondary or approve like any other.
   One per region (CLAUDE.md section 3: attention is a budget). */
.ak-btn--lg{height:var(--ak-control-h-lg);padding-inline:var(--ak-s-5);
  font-size:var(--ak-fs-body);gap:var(--ak-gap-inside)}
/* A button that stays on (aria-pressed="true"): one of a few choices, a
   filter that narrows, a mode. The fill says it and so does a tick, so the
   state survives greyscale and forced colours; the tick is hidden from a
   screen reader, which hears "pressed" (v2.3.0). A row of them is
   .ak-choices: none on, or one, or several, as the field allows. */
.ak-btn[aria-pressed="true"]{background:var(--ak-action-bg);color:var(--ak-ink);
  border-color:var(--ak-action)}
.ak-btn[aria-pressed="true"]::before{content:"\2713";content:"\2713" / "";
  font-weight:var(--ak-fw-semibold)}
.ak-choices{display:flex;flex-wrap:wrap;gap:var(--ak-gap-inside);margin:0;padding:0;border:0}
@media (forced-colors:active){.ak-btn[aria-pressed="true"]{border-color:Highlight}}
.ak-btn--icon{padding-inline:0;width:var(--ak-control-h)}

/* ---- 4.4 Form controls --------------------------------------------
   Every control has a visible label. Placeholder is never the label
   (WCAG 2.2 · 3.3.2). Help text sits under the control; an error
   replaces the help text and is tied to the field by aria-describedby. */
.ak-field{display:flex;flex-direction:column;gap:var(--ak-s-1);min-width:0}
.ak-label{font-size:var(--ak-fs-small);font-weight:var(--ak-fw-medium);
  color:var(--ak-ink-2)}
.ak-label .ak-req{color:var(--ak-failed);margin-left:2px}
.ak-input,.ak-select,.ak-textarea{
  width:100%;height:var(--ak-control-h);
  padding:0 var(--ak-s-3);
  background:var(--ak-surface);color:var(--ak-ink);
  border:var(--ak-border) solid var(--ak-line-control);
  border-radius:var(--ak-r-sm);
  font:inherit;font-size:var(--ak-fs-base);
  transition:border-color var(--ak-dur-instant) var(--ak-ease-out);
}
.ak-textarea{height:auto;min-height:84px;padding:var(--ak-s-2) var(--ak-s-3);
  line-height:var(--ak-lh-snug);resize:vertical}
.ak-input:hover,.ak-select:hover,.ak-textarea:hover{border-color:var(--ak-line-control-hover)}
.ak-input::placeholder,.ak-textarea::placeholder{color:var(--ak-ink-muted);opacity:1}
.ak-input[readonly]{background:var(--ak-sunk);color:var(--ak-ink-2)}
.ak-input[aria-invalid="true"]{border-color:var(--ak-failed);
  box-shadow:0 0 0 3px var(--ak-failed-bg)}
.ak-help{font-size:var(--ak-fs-small);color:var(--ak-ink-muted)}
.ak-error{font-size:var(--ak-fs-small);color:var(--ak-failed);
  display:flex;align-items:flex-start;gap:var(--ak-s-1);font-weight:var(--ak-fw-medium)}
/* Numbers, codes and quantities are entered monospaced and right-aligned
   so a mistyped digit is visible. */
.ak-input--num{font-family:var(--ak-font-mono);text-align:right;
  font-variant-numeric:tabular-nums}

/* ---- 4.5 Filter bar — identical position in every module ---------- */
.ak-filterbar{
  display:flex;align-items:center;gap:var(--ak-s-2);flex-wrap:wrap;
  padding:var(--ak-s-3);background:var(--ak-surface);
  border:var(--ak-border) solid var(--ak-line);border-radius:var(--ak-r-md);
}
.ak-search{position:relative;flex:1 1 260px;min-width:200px}
.ak-search .ak-input{padding-left:var(--ak-s-8)}
.ak-search__icon{position:absolute;left:var(--ak-s-3);top:50%;
  transform:translateY(-50%);color:var(--ak-ink-muted);pointer-events:none}
.ak-filterbar__right{margin-left:auto;display:flex;gap:var(--ak-s-2);align-items:center}
.ak-filtercount{font-size:var(--ak-fs-small);color:var(--ak-ink-muted);
  font-variant-numeric:tabular-nums}
/* 2.6.0: a select or a number field placed straight in the bar is as wide
   as its content. Its own rule is inline-size:100%, right in a form field,
   so in the bar each one took a whole row of its own (stores, compliance,
   lab). Direct children only: one wrapped in .ak-field already sized to
   its content. Below 768px the bar is a column and stretches it. */
.ak-filterbar > :is(.ak-select,.ak-input--num){inline-size:auto;
  min-inline-size:9rem;flex:0 0 auto}
/* Below 768px the filter bar stacks. These rules sit here, in components,
   because they override component properties: in the layout layer
   (where they were) align-items:stretch lost to .ak-filterbar's own
   align-items:center, so the search shrank to its content and centred.
   In a column the search's 260px flex-basis would become its HEIGHT, so
   it sizes to its content instead. */
@media (max-width:767px){
  .ak-filterbar{flex-direction:column;align-items:stretch}
  .ak-filterbar__right{flex-wrap:wrap}
  .ak-search{flex:0 0 auto;min-width:0}
  /* 2.9.2: stretched, but never wider than the bar (a long option) */
  .ak-filterbar > :is(.ak-select,.ak-input--num){min-inline-size:0;max-inline-size:100%}
}

/* ---- 4.6 Data table ------------------------------------------------
   The most-used object in the system. Sticky head, zebra off by
   default (borders are enough and zebra fights status tinting),
   tabular figures, keyboard-operable sort, and a row that can carry a
   state without becoming a colour block. */
.ak-tablewrap{
  background:var(--ak-surface);border:var(--ak-border) solid var(--ak-line);
  border-radius:var(--ak-r-md);overflow:hidden;
  display:flex;flex-direction:column;min-height:0;
}
.ak-tablescroll{
  overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;
  contain:layout paint;max-height:var(--ak-table-max,none);
}
/* 2.12.0: a register longer than the window scrolls inside a box the
   height of the window, so its sticky header row is always in view
   (a sticky head can only stick inside its own scroller). */
.ak-tablescroll--viewport{
  --ak-table-max:calc(100dvh - var(--ak-masthead-h) - var(--ak-s-10) - var(--ak-s-10))}
.ak-table{border-collapse:separate;border-spacing:0;width:100%;
  font-size:var(--ak-fs-table)}
.ak-table thead th{
  position:sticky;top:0;z-index:var(--ak-z-sticky);
  background:var(--ak-sunk);color:var(--ak-ink-muted);
  font-size:var(--ak-fs-tiny);font-weight:var(--ak-fw-semibold);
  text-transform:uppercase;letter-spacing:var(--ak-ls-wide);
  text-align:left;white-space:nowrap;
  padding:var(--ak-s-2) var(--ak-row-pad-x);
  border-bottom:var(--ak-border) solid var(--ak-line-strong);
}
/* The shadow only appears once the body has scrolled under the head,
   so a short table does not carry a line it has not earned. */
.ak-tablescroll[data-scrolled="true"] .ak-table thead th{
  box-shadow:var(--ak-shadow-sticky)}
.ak-table th button.ak-sort{
  all:unset;box-sizing:border-box;cursor:pointer;display:inline-flex;align-items:center;gap:4px;
  font:inherit;color:inherit;text-transform:inherit;letter-spacing:inherit;
  min-height:var(--ak-target-min)}   /* 2.13.1: all:unset had taken the floor away */
/* the focus ring all:unset removed, given back (the reserved ring, never emphasis) */
.ak-table th button.ak-sort:focus-visible{outline:var(--ak-focus-w) solid var(--ak-focus);outline-offset:2px}
.ak-table th[aria-sort] button.ak-sort{color:var(--ak-ink)}
.ak-table tbody td{
  padding:var(--ak-row-pad-y) var(--ak-row-pad-x);
  border-bottom:var(--ak-border) solid var(--ak-line);
  vertical-align:middle;height:var(--ak-row-h);
}
.ak-table tbody tr:last-child td{border-bottom:0}
.ak-table tbody tr{transition:background var(--ak-dur-instant) var(--ak-ease-out)}
.ak-table tbody tr:hover{background:var(--ak-surface-2)}
.ak-table tbody tr[aria-selected="true"],
.ak-table tbody tr:has(> td > .ak-radio > input:checked){background:var(--ak-action-bg)}
/* A row's state is a 3px left rule plus its chip — never a filled row.
   A filled row makes the text in it harder to read, which is the
   opposite of what a status is for. */
.ak-table tbody tr[data-state]{box-shadow:inset 3px 0 0 0 var(--ak-neutral)}
.ak-table tbody tr[data-state="information"]{box-shadow:inset 3px 0 0 0 var(--ak-info)}
.ak-table tbody tr[data-state="warning"]{box-shadow:inset 3px 0 0 0 var(--ak-warning)}
.ak-table tbody tr[data-state="approval"]{box-shadow:inset 3px 0 0 0 var(--ak-approval)}
.ak-table tbody tr[data-state="complete"]{box-shadow:inset 3px 0 0 0 var(--ak-complete)}
.ak-table tbody tr[data-state="failed"]{box-shadow:inset 3px 0 0 0 var(--ak-failed)}
.ak-td-num{font-family:var(--ak-font-mono);text-align:right;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.ak-td-main{display:flex;flex-direction:column;gap:1px;min-width:0}
.ak-td-main b{font-weight:var(--ak-fw-semibold)}
/* 2.22.0: a lead title. The table gives a column at least its widest
   unbreakable run, so a title on one line keeps its column wide enough to
   read beside a long list. Below 768px a card table lets it wrap. */
.ak-td-main--lead > b{white-space:nowrap}
.ak-td-sub{font-size:var(--ak-fs-small);color:var(--ak-ink-muted)}
.ak-td-actions{text-align:right;white-space:nowrap}
.ak-td-actions > *{vertical-align:middle}
.ak-td-actions > * + *{margin-left:var(--ak-s-1)}
/* Masked, not absent. A column that vanishes makes people believe the
   data does not exist; a masked cell tells the truth. */
.ak-masked{color:var(--ak-ink-muted);font-style:italic;font-size:var(--ak-fs-small)}
.ak-tablefoot{
  display:flex;align-items:center;gap:var(--ak-s-3);
  padding:var(--ak-s-2) var(--ak-s-3);
  border-top:var(--ak-border) solid var(--ak-line);
  background:var(--ak-surface-2);font-size:var(--ak-fs-small);
  color:var(--ak-ink-muted);
}
.ak-tablefoot__right{margin-left:auto;display:flex;align-items:center;gap:var(--ak-s-2)}

/* ---- 4.7 Status chip ----------------------------------------------
   Colour + icon + word. Never colour alone — it must survive a
   greyscale print and a colour-blind reader (WCAG 2.2 · 1.4.1). */
.ak-chip{
  display:inline-flex;align-items:center;gap:var(--ak-s-1);
  padding:2px var(--ak-s-2);border-radius:var(--ak-r-pill);
  font-size:var(--ak-fs-tiny);font-weight:var(--ak-fw-semibold);
  white-space:nowrap;line-height:1.5;
  background:var(--ak-neutral-bg);color:var(--ak-neutral);
}
.ak-chip::before{content:"";width:6px;height:6px;border-radius:50%;
  background:currentColor;flex:0 0 auto}
.ak-chip[data-state="information"]{background:var(--ak-info-bg);color:var(--ak-info-ink)}
.ak-chip[data-state="warning"]{background:var(--ak-warning-bg);color:var(--ak-warning-ink)}
.ak-chip[data-state="approval"]{background:var(--ak-approval-bg);color:var(--ak-approval-ink)}
.ak-chip[data-state="complete"]{background:var(--ak-complete-bg);color:var(--ak-complete-ink)}
.ak-chip[data-state="failed"]{background:var(--ak-failed-bg);color:var(--ak-failed-ink)}
/* Layer discipline: a chip's display belongs to the components layer, so
   its responsive hiding must live here too. A rule in the layout layer
   would lose to the base .ak-chip rule no matter how specific it was —
   that is the cascade layers doing their job, not a bug. */
@media (max-width:1365px){   /* 2.13.2: was 900px; it makes room for the 240px search */
  .ak-masthead__right > .ak-chip{display:none}
}

/* Overdue is an age badge beside the state chip, not a sixth colour. */
.ak-age{
  display:inline-flex;align-items:center;gap:3px;
  font-family:var(--ak-font-mono);font-size:var(--ak-fs-tiny);
  font-weight:var(--ak-fw-semibold);padding:2px 6px;
  border-radius:var(--ak-r-xs);background:var(--ak-failed-bg);
  color:var(--ak-failed-ink);font-variant-numeric:tabular-nums;
}
.ak-age[data-late="soon"]{background:var(--ak-warning-bg);color:var(--ak-warning)}

/* ---- 4.8 Tabs — the detail screen's spine -------------------------- */
.ak-tabs{border-bottom:var(--ak-border) solid var(--ak-line);
  display:flex;gap:2px;overflow-x:auto;scrollbar-width:none}
.ak-tabs::-webkit-scrollbar{display:none}
.ak-tab{
  all:unset;box-sizing:border-box;cursor:pointer;flex:0 0 auto;
  padding:var(--ak-s-3) var(--ak-s-3);font-size:var(--ak-fs-base);
  font-weight:var(--ak-fw-medium);color:var(--ak-ink-muted);
  border-bottom:2px solid transparent;white-space:nowrap;
  display:inline-flex;align-items:center;gap:var(--ak-s-2);
}
.ak-tab:hover{color:var(--ak-ink)}
/* all:unset above takes the base focus ring with it, and this layer
   beats base whatever the specificity: so the ring is given back here. */
.ak-tab:focus-visible{outline:2px solid var(--ak-action);outline-offset:-2px;
  box-shadow:0 0 0 4px color-mix(in srgb,var(--ak-action) 22%,transparent)}
.ak-tab[aria-selected="true"]{color:var(--ak-action);
  border-bottom-color:var(--ak-action);font-weight:var(--ak-fw-semibold)}
.ak-tab__count{font-family:var(--ak-font-mono);font-size:var(--ak-fs-tiny);
  background:var(--ak-sunk);padding:1px 5px;border-radius:var(--ak-r-pill);
  font-variant-numeric:tabular-nums}

/* ---- 4.9 Banner / alert ------------------------------------------- */
.ak-banner{
  display:flex;gap:var(--ak-s-3);padding:var(--ak-s-3) var(--ak-s-4);
  border-radius:var(--ak-r-sm);border-left:3px solid var(--ak-neutral);
  background:var(--ak-neutral-bg);font-size:var(--ak-fs-base);
  color:var(--ak-ink);align-items:flex-start;
}
.ak-banner b{font-weight:var(--ak-fw-semibold)}
/* 2.6.0: a banner is a row of an icon and one block of text. A paragraph
   as that block keeps no margin of its own (base gives every p a bottom
   margin, which sat inside the banner as uneven padding). */
.ak-banner > p{margin:0;min-width:0}
.ak-banner[data-state="information"]{border-left-color:var(--ak-info);background:var(--ak-info-bg)}
.ak-banner[data-state="warning"]{border-left-color:var(--ak-warning);background:var(--ak-warning-bg)}
.ak-banner[data-state="approval"]{border-left-color:var(--ak-approval);background:var(--ak-approval-bg)}
.ak-banner[data-state="complete"]{border-left-color:var(--ak-complete);background:var(--ak-complete-bg)}
.ak-banner[data-state="failed"]{border-left-color:var(--ak-failed);background:var(--ak-failed-bg)}

/* ---- 4.10 Refusal --------------------------------------------------
   An ERP that refuses well is worth more than one that never refuses.
   A refusal always says three things: what was refused, why, and what
   to do next (ISO 9241-110 error robustness; WCAG 2.2 · 3.3.3). */
.ak-refusal{
  border:var(--ak-border) solid color-mix(in srgb,var(--ak-failed) 36%,transparent);
  background:var(--ak-failed-bg);border-radius:var(--ak-r-md);
  padding:var(--ak-s-4);display:flex;flex-direction:column;gap:var(--ak-s-2);
}
.ak-refusal__what{font-weight:var(--ak-fw-semibold);color:var(--ak-ink)}
.ak-refusal__why{color:var(--ak-ink-2);font-size:var(--ak-fs-base);margin:0}
.ak-refusal__next{font-size:var(--ak-fs-small);color:var(--ak-ink-2)}

/* ---- 4.11 Modal, drawer, confirmation ------------------------------
   Focus moves in, is trapped while open, and returns to the trigger on
   close. The page behind does not scroll. */
.ak-overlay{position:fixed;inset:0;background:var(--ak-overlay);
  z-index:var(--ak-z-modal);display:grid;place-items:center;padding:var(--ak-s-4)}
.ak-modal{
  background:var(--ak-surface);border-radius:var(--ak-r-lg);
  box-shadow:var(--ak-shadow-overlay);width:min(560px,100%);
  max-height:min(84dvh,760px);display:flex;flex-direction:column;overflow:hidden;
}
.ak-modal--wide{width:min(880px,100%)}
/* The same modal on a native <dialog>. The browser gives a modal dialog
   its focus trap, Escape to close, the inert page behind and focus back
   to the trigger, so a page should prefer this to a div overlay. A closed
   dialog must stay hidden: .ak-modal's display:flex would otherwise beat
   the browser's own dialog:not([open]){display:none}. */
dialog.ak-modal{border:0;padding:0;color:var(--ak-ink);
  max-width:calc(100% - var(--ak-s-4) * 2)}
dialog.ak-modal:not([open]){display:none}
dialog.ak-modal::backdrop{background:var(--ak-overlay)}
.ak-modal > form{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;margin:0}
/* The full sheet (2.17.0): for work that needs the whole screen, such as
   a voucher's lines. It fills the screen less the page gutter, its head
   and foot stay where they are and only the body scrolls; on a phone
   (max 640) it is the whole screen, square-cornered. Everything else is
   the modal's: focus, Escape, the backdrop. */
dialog.ak-modal--sheet{width:100%;height:calc(100dvh - var(--ak-gutter) * 2);
  max-width:calc(100% - var(--ak-gutter) * 2);max-height:none}
.ak-modal--sheet .ak-modal__body{flex:1 1 auto;min-height:0}
@media (max-width:640px){
  dialog.ak-modal--sheet{max-width:100%;height:100dvh;border-radius:0}
}
.ak-modal__head{padding:var(--ak-s-4) var(--ak-s-5);
  border-bottom:var(--ak-border) solid var(--ak-line);
  display:flex;align-items:center;gap:var(--ak-s-3)}
.ak-modal__head > *{min-width:0}
.ak-modal__head :is(h1,h2,h3){overflow-wrap:anywhere}
.ak-modal__body{padding:var(--ak-s-5);overflow:auto;overscroll-behavior:contain}
.ak-modal__foot{padding:var(--ak-s-3) var(--ak-s-5);
  border-top:var(--ak-border) solid var(--ak-line);
  display:flex;gap:var(--ak-s-2);justify-content:flex-end;background:var(--ak-surface-2)}
.ak-drawer{
  position:fixed;inset:0 0 0 auto;width:min(520px,100%);
  background:var(--ak-surface);box-shadow:var(--ak-shadow-overlay);
  z-index:var(--ak-z-drawer);display:flex;flex-direction:column;
  animation:ak-slide-in var(--ak-dur-base) var(--ak-ease-out);
}
@keyframes ak-slide-in{from{transform:translateX(24px);opacity:0}to{transform:none;opacity:1}}
/* A confirmation names the thing, the amount and the consequence.
   "Are you sure?" is not a confirmation. */
.ak-confirm__subject{font-family:var(--ak-font-mono);
  background:var(--ak-sunk);padding:var(--ak-s-3);border-radius:var(--ak-r-sm);
  font-size:var(--ak-fs-small);display:flex;flex-direction:column;gap:2px}
.ak-confirm__consequence{color:var(--ak-failed);font-weight:var(--ak-fw-medium)}

/* ---- 4.12 Activity timeline ---------------------------------------- */
.ak-timeline{list-style:none;margin:0;padding:0;
  display:flex;flex-direction:column}
.ak-timeline li{position:relative;padding:0 0 var(--ak-s-4) var(--ak-s-6);
  border-left:var(--ak-border) solid var(--ak-line);margin-left:7px}
.ak-timeline li:last-child{border-left-color:transparent;padding-bottom:0}
.ak-timeline li::before{content:"";position:absolute;left:-5px;top:4px;
  width:9px;height:9px;border-radius:50%;background:var(--ak-n-400);
  box-shadow:0 0 0 3px var(--ak-surface)}
.ak-timeline li[data-state="complete"]::before{background:var(--ak-complete)}
.ak-timeline li[data-state="failed"]::before{background:var(--ak-failed)}
.ak-timeline li[data-state="approval"]::before{background:var(--ak-approval)}
.ak-timeline__when{font-family:var(--ak-font-mono);font-size:var(--ak-fs-tiny);
  color:var(--ak-ink-muted)}
.ak-timeline__who{font-weight:var(--ak-fw-semibold);font-size:var(--ak-fs-small)}
.ak-timeline__what{font-size:var(--ak-fs-small);color:var(--ak-ink-2)}

/* ---- 4.13 Workflow stepper ----------------------------------------- */
.ak-steps{display:flex;align-items:center;gap:0;flex-wrap:wrap}
.ak-step{display:inline-flex;align-items:center;gap:var(--ak-s-2);
  padding:var(--ak-s-2) var(--ak-s-3);font-size:var(--ak-fs-small);
  color:var(--ak-ink-muted)}
.ak-step__dot{width:18px;height:18px;border-radius:50%;flex:0 0 auto;
  border:2px solid var(--ak-line-strong);display:grid;place-items:center;
  font-size:var(--ak-fs-micro);font-weight:var(--ak-fw-bold);line-height:1}
.ak-step[data-state="complete"]{color:var(--ak-complete)}
.ak-step[data-state="complete"] .ak-step__dot{border-color:var(--ak-complete);
  background:var(--ak-complete);color:var(--ak-on-fill)}
.ak-step[data-state="approval"]{color:var(--ak-approval);font-weight:var(--ak-fw-semibold)}
.ak-step[data-state="approval"] .ak-step__dot{border-color:var(--ak-approval)}
.ak-step[data-state="failed"]{color:var(--ak-failed)}
.ak-step[data-state="failed"] .ak-step__dot{border-color:var(--ak-failed)}
.ak-step__link{width:20px;height:var(--ak-border);background:var(--ak-line-strong);flex:0 0 auto}
/* narrow: the steps wrap, and a link left at a line's end points nowhere */
@media (max-width:640px){.ak-step__link{display:none}}

/* ---- 4.14 Empty, loading, error ------------------------------------
   An empty state says what would be here, why it is not, and the one
   action that changes it. A spinner alone tells nobody anything. */
.ak-empty{
  display:flex;flex-direction:column;align-items:center;gap:var(--ak-s-2);
  padding:var(--ak-s-9) var(--ak-s-5);text-align:center;color:var(--ak-ink-muted);
}
.ak-empty b{color:var(--ak-ink);font-size:var(--ak-fs-h4);font-weight:var(--ak-fw-semibold)}
.ak-empty p{max-width:46ch;margin:0;font-size:var(--ak-fs-small)}
/* ---- 4.14a Skeletons (2.10.0, audit G-18) --------------------------
   While a register or a figure is being read, its shape is drawn in
   place, so the page does not jump when the rows arrive and nobody reads
   "Loading…" where a table will be. A skeleton is never the only signal:
   the region that is loading carries aria-busy="true" and a visually
   hidden sentence saying what is being read, and the status is spoken
   once, politely, without moving focus (vendor/ak-skeleton.js does all
   three). An error or an empty answer replaces it with the ordinary
   refusal or empty state (4.14); a skeleton never stands for either.
   Markup:
     span.ak-skeleton                         one bar, 1em high
       --text --title --label --figure --short  sized from the type scale
     tr.ak-skeleton-row > td > span.ak-skeleton  a row of a loading .ak-table
     div.ak-kpi.ak-kpi--skeleton               a KPI tile while its figure is read
     div.ak-card.ak-card--skeleton             a card while its contents are read
     .ak-skeleton-lines                        a stack of text lines, the last short
   The bar is the line colour with a lighter sweep: it reads in both themes
   and in greyscale; in forced colours it is an outline; under reduced
   motion it does not move. */
.ak-skeleton{
  display:block;inline-size:100%;block-size:1em;
  background:linear-gradient(90deg,var(--ak-line) 25%,
    var(--ak-surface-2) 37%,var(--ak-line) 63%);
  background-size:400% 100%;border-radius:var(--ak-r-xs);
  animation:ak-shimmer 1.3s ease-in-out infinite;
}
@keyframes ak-shimmer{from{background-position:100% 50%}to{background-position:0 50%}}
.ak-skeleton--text{block-size:var(--ak-fs-base)}
.ak-skeleton--label{block-size:var(--ak-fs-tiny);inline-size:55%}
.ak-skeleton--title{block-size:var(--ak-fs-h4);inline-size:45%}
.ak-skeleton--figure{block-size:var(--ak-fs-kpi);inline-size:65%}
.ak-skeleton--short{inline-size:40%}
.ak-skeleton-lines{display:flex;flex-direction:column;gap:var(--ak-gap-inside)}
.ak-skeleton-lines > .ak-skeleton:last-child{inline-size:60%}

/* A row of a loading table: as tall as a real row in every density, so
   the rows that replace it do not move the page. Bar lengths vary by row
   and column, the way real words do; a figure column's bar ends. */
.ak-table tbody tr.ak-skeleton-row:hover{background:transparent}
.ak-skeleton-row .ak-skeleton{block-size:var(--ak-fs-table);inline-size:80%}
.ak-skeleton-row td:first-child .ak-skeleton{inline-size:64%}
.ak-skeleton-row:nth-child(3n+2) td .ak-skeleton{inline-size:56%}
.ak-skeleton-row:nth-child(3n) td .ak-skeleton{inline-size:72%}
.ak-skeleton-row td.ak-td-num .ak-skeleton{inline-size:60%;margin-inline-start:auto}
.ak-skeleton-row th .ak-skeleton,
.ak-table thead th .ak-skeleton{block-size:var(--ak-fs-tiny);inline-size:50%}
.ak-table thead th.ak-th-num .ak-skeleton{margin-inline-start:auto}

/* A KPI tile and a card while they load: the real component, with bars
   where its words and figure will be, so the grid keeps its shape. */
/* the figure steps down with the real one below 480px (4.2) */
@media (max-width:479px){.ak-skeleton--figure{block-size:var(--ak-fs-h2)}}
.ak-card--skeleton .ak-card__body{display:flex;flex-direction:column;gap:var(--ak-gap-inside)}

@media (prefers-reduced-motion:reduce){
  .ak-skeleton{animation:none;background:var(--ak-line)}
}
@media (forced-colors:active){
  .ak-skeleton{background:Canvas;border:var(--ak-border) solid GrayText;animation:none}
}

/* ---- 4.15 Document list and audit trail ---------------------------- */
.ak-doclist{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.ak-doclist li{display:flex;align-items:center;flex-wrap:wrap;gap:var(--ak-s-3);
  padding:var(--ak-s-2) 0;border-bottom:var(--ak-border) solid var(--ak-line)}
.ak-doclist li:last-child{border-bottom:0}
.ak-doc__name{font-weight:var(--ak-fw-medium);min-width:0}
.ak-doc__meta{font-size:var(--ak-fs-small);color:var(--ak-ink-muted)}
.ak-doc__ver{font-family:var(--ak-font-mono);font-size:var(--ak-fs-tiny);
  background:var(--ak-sunk);padding:1px 6px;border-radius:var(--ak-r-xs)}
.ak-audit{font-family:var(--ak-font-mono);font-size:var(--ak-fs-small)}
.ak-audit__row{display:grid;
  grid-template-columns:148px 140px minmax(0,1fr);gap:var(--ak-s-3);
  padding:var(--ak-s-2) 0;border-bottom:var(--ak-border) solid var(--ak-line)}
@media (max-width:720px){.ak-audit__row{grid-template-columns:minmax(0,1fr)}}

/* ---- 4.16 Toast ----------------------------------------------------
   Status messages are announced to assistive technology without
   stealing focus (WCAG 2.2 · 4.1.3). Mark the region role="status". */
.ak-toasts{position:fixed;right:var(--ak-s-4);
  max-inline-size:calc(100vw - 2 * var(--ak-s-4));  /* 2.16.1: never wider than the screen less its gutters */
  bottom:calc(var(--ak-s-4) + env(safe-area-inset-bottom,0px));
  z-index:var(--ak-z-toast);display:flex;flex-direction:column;gap:var(--ak-s-2)}
.ak-toast{
  background:var(--ak-surface);border:var(--ak-border) solid var(--ak-line);
  border-left:3px solid var(--ak-complete);
  border-radius:var(--ak-r-sm);box-shadow:var(--ak-shadow-overlay);
  padding:var(--ak-s-3) var(--ak-s-4);max-width:min(380px,100%);font-size:var(--ak-fs-small);
  overflow-wrap:anywhere;
  animation:ak-toast-in var(--ak-dur-base) var(--ak-ease-out);
}
.ak-toast[data-state="failed"]{border-left-color:var(--ak-failed)}
.ak-toast[data-state="warning"]{border-left-color:var(--ak-warning)}
@keyframes ak-toast-in{from{transform:translateY(8px);opacity:0}to{transform:none;opacity:1}}

/* ---- 4.17 Board ----------------------------------------------------
   Named lanes side by side, each holding cards and an add box: a to-do
   board, a pipeline. The lanes sit in one strip that scrolls sideways on
   its own (the page never does); every lane starts at the top, so a long
   lane never pushes another lane's heading down. Lane width is a token.
   Markup: .ak-board (a focusable region: tabindex="0", role="region",
   aria-label) > .ak-board__lane > .ak-board__head (the lane's name, often
   a button that renames it) + .ak-board__cards > .ak-board__card, and an
   add box (.ak-textarea + .ak-btn) at the foot of the lane.
   Added 2 Oct 2026 for the Director's yearly planner (v2.1.0). */
.ak-board{
  display:grid;grid-auto-flow:column;grid-auto-columns:var(--ak-board-lane);
  gap:var(--ak-gap-between);align-items:start;
  overflow-x:auto;overscroll-behavior-x:contain;
  padding-block-end:var(--ak-s-2);
  /* The containing block for anything absolutely placed inside (a .ak-sr
     label): without it, those escape the strip's scroll and push the
     page sideways. */
  position:relative;
}
.ak-board__lane{
  display:flex;flex-direction:column;gap:var(--ak-gap-inside);min-width:0;
  background:var(--ak-sunk);border-radius:var(--ak-r-md);padding:var(--ak-s-3);
}
.ak-board__head{
  display:flex;align-items:center;gap:var(--ak-gap-inside);min-height:var(--ak-control-h);
  font-size:var(--ak-fs-small);font-weight:var(--ak-fw-semibold);color:var(--ak-ink-2);
}
.ak-board__head .ak-btn{justify-content:flex-start;text-align:start;inline-size:100%}
.ak-board__cards{display:flex;flex-direction:column;gap:var(--ak-gap-inside);
  list-style:none;margin:0;padding:0}
.ak-board__card{
  display:flex;flex-direction:column;gap:var(--ak-gap-inside);
  background:var(--ak-surface);border:var(--ak-border) solid var(--ak-line);
  border-radius:var(--ak-r-sm);padding:var(--ak-s-3);overflow-wrap:anywhere;
}
/* A note keeps the line breaks its writer typed. */
.ak-board__text{white-space:pre-line}
/* 2.7.0: a fit board. From 1024px its lanes share the width (a lane
   never narrows below --ak-board-lane-min; past that the strip scrolls as
   before), an empty lane is only its name and count, set upright, and a
   stack holds several lanes in one column. */
.ak-board__stack{display:flex;flex-direction:column;gap:var(--ak-gap-inside);min-inline-size:0}
@media (min-width:1024px){
  .ak-board--fit{display:flex;align-items:flex-start}
  .ak-board--fit > .ak-board__lane,.ak-board--fit > .ak-board__stack{flex:1 1 0;min-inline-size:var(--ak-board-lane-min)}
  .ak-board--fit > .ak-board__lane[data-empty]{flex:0 0 auto;min-inline-size:0}
  .ak-board--fit > .ak-board__lane[data-empty] > .ak-board__head{writing-mode:vertical-rl;min-height:0}
  .ak-board--fit > .ak-board__lane[data-empty] > :not(.ak-board__head){display:none}
}
@media (forced-colors:active){
  .ak-board__lane,.ak-board__card{border:1px solid CanvasText}
}

/* ---- 4.18 Entry table ----------------------------------------------
   A table whose cells are typed into: an order's item lines, a price
   list. Every field in a cell keeps a minimum width, so a narrow screen
   scrolls the table sideways inside its .ak-tablescroll region instead
   of squeezing a field down to three letters. Mark the one cell that
   holds a name or a search .ak-entry-wide. Alignment is the ordinary
   table rule: a quantity or money field is .ak-input--num in a cell
   whose header is .ak-th-num.
   Markup: table.ak-table.ak-table--entry > tbody > tr > td > .ak-input
   (or .ak-select), and td.ak-entry-wide for the wide one.
   Added 2 Oct 2026 for the Orders page (built as 2.2.0 on the
   design-migration branch; 2.4.0 in this line). */
.ak-table--entry td{vertical-align:top}
/* A field brings its own inner padding, so the cell needs little: the
   header keeps the same inset so it still lines up with its column. */
.ak-table--entry{--ak-row-pad-x:var(--ak-s-1)}
.ak-table--entry tr > :first-child{padding-inline-start:var(--ak-s-3)}
.ak-table--entry tr > :last-child{padding-inline-end:var(--ak-s-3)}
.ak-table--entry td :where(.ak-input,.ak-select){min-inline-size:var(--ak-entry-cell)}
/* A field's message under it (2.17.0) is as wide as the wide cell and
   wraps inside it, and its words start, even under a figure: a refusal
   under a quantity neither runs across the table on one line nor stands
   one word to a line in a narrow column. */
.ak-table--entry td .ak-error{white-space:normal;text-align:start;margin:0;
  inline-size:var(--ak-entry-cell-wide);min-inline-size:100%}
.ak-table--entry td.ak-entry-wide :where(.ak-input,.ak-select){min-inline-size:var(--ak-entry-cell-wide)}
/* An entry table that is also .ak-table--cards (2.11.0): below 768px each
   line is a card and each field sits under its column name, read from the
   cell's data-label, at any width (a register's card labels only appear at
   320px; a form cannot leave its fields unnamed). Fields fill the card. */
@media (max-width:767px){
  .ak-table--entry.ak-table--cards td{grid-template-columns:minmax(0,1fr);gap:var(--ak-s-1)}
  .ak-table--entry.ak-table--cards td::before{content:attr(data-label);color:var(--ak-ink-muted);
    font-size:var(--ak-fs-small);font-weight:var(--ak-fw-medium)}
  .ak-table--entry.ak-table--cards td :where(.ak-input,.ak-select){min-inline-size:0}
  .ak-table--entry.ak-table--cards td.ak-td-num{text-align:start}
  .ak-table--entry.ak-table--cards td.ak-td-actions{justify-content:end}
  .ak-table--entry.ak-table--cards td.ak-td-actions::before{content:none}
}

/* ---- 4.19 Permission matrix ----------------------------------------
   One row per thing that can be granted, one radio per level, the
   levels a ladder (none < view < add < edit < chief). A ladder cannot
   express "Edit without View", which four independent ticks could.
   Used with .ak-table inside .ak-tablescroll.
   - Rows are grouped: each group is its own <tbody> whose first row is
     tr.ak-permtable__group > th[scope=rowgroup][colspan] carrying the
     group's name, its count and its .ak-grpset.
   - A level the row does not offer is .ak-permtable__na: an em dash,
     with "not offered" for a screen reader. Never a disabled radio: a
     greyed radio says "switched off", a blank says "does not exist".
   - A changed row is tr[data-changed] — a left rule and a tint — AND
     .ak-permtable__change, written out under the name ("None → View"):
     the tint is never the only sign.
   - Each level cell holds label.ak-radio.ak-permtable__pick > input
     plus .ak-permtable__lvlname, the level's word, shown only when the
     table becomes cards below 640px and hidden from screen readers
     (the radio is named by its column and row through aria-labelledby).
   Added 3 Oct 2026 for the access register (2.5.0). */
.ak-permtable th.ak-permtable__lvl,.ak-permtable td.ak-permtable__lvl{
  inline-size:var(--ak-perm-level);text-align:start;
  padding-inline:var(--ak-s-2)}
.ak-permtable td.ak-permtable__lvl{vertical-align:top}
.ak-permtable td.ak-permtable__name{vertical-align:top}
/* The pick is a .ak-radio (13.2) — the same native radio as everywhere
   — given a square target so a column of them lines up. */
.ak-permtable__pick{align-items:center;gap:var(--ak-s-1);
  min-inline-size:var(--ak-target-min)}
@media (pointer:coarse){.ak-permtable__pick{min-inline-size:var(--ak-target-touch)}}
.ak-permtable__pick > input{margin-block-start:0}
.ak-permtable__lvlname{display:none;font-size:var(--ak-fs-small);color:var(--ak-ink-2)}
.ak-permtable__na{display:inline-flex;align-items:center;
  min-block-size:var(--ak-target-min);color:var(--ak-ink-muted)}
.ak-permtable__na::before{content:"\2014";content:"\2014" / ""}
.ak-permtable__change{font-size:var(--ak-fs-small);font-weight:var(--ak-fw-semibold);
  color:var(--ak-ink)}
.ak-permtable tbody tr[data-changed]{background:var(--ak-action-bg);
  box-shadow:inset 3px 0 0 0 var(--ak-action)}
.ak-permtable tbody tr[data-changed]:hover{background:var(--ak-action-bg)}
.ak-permtable tbody tr.ak-permtable__group:hover{background:none}
.ak-permtable tbody tr.ak-permtable__group > th{
  text-align:start;font-weight:var(--ak-fw-regular);
  padding:var(--ak-s-3) var(--ak-row-pad-x);background:var(--ak-sunk);
  border-block:var(--ak-border) solid var(--ak-line-strong)}
.ak-permtable tbody:first-of-type tr.ak-permtable__group > th{border-block-start:0}
.ak-permtable__grouphead{display:flex;flex-wrap:wrap;align-items:center;
  gap:var(--ak-gap-inside) var(--ak-gap-between)}
.ak-permtable__groupname{font-size:var(--ak-fs-base);font-weight:var(--ak-fw-semibold);
  color:var(--ak-ink)}
.ak-permtable__groupcount{font-size:var(--ak-fs-small);color:var(--ak-ink-muted);
  font-variant-numeric:tabular-nums}
.ak-permtable__grouphead > .ak-grpset{margin-inline-start:auto}
/* Below 640px a row becomes a card: the name across the top, the five
   levels under it, each with its word, so nothing scrolls sideways. */
@media (max-width:640px){
  .ak-permtable thead{position:absolute;inline-size:1px;block-size:1px;
    overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .ak-permtable tbody tr:not(.ak-permtable__group){display:grid;
    grid-template-columns:repeat(5,minmax(0,1fr));
    border-bottom:var(--ak-border) solid var(--ak-line)}
  .ak-permtable tbody tr:not(.ak-permtable__group) > td{border-bottom:0;height:auto}
  .ak-permtable tbody tr:not(.ak-permtable__group) > td.ak-permtable__name{grid-column:1/-1}
  .ak-permtable td.ak-permtable__lvl{inline-size:auto;padding-block-start:0}
  .ak-permtable__pick,.ak-permtable__na{flex-direction:column;align-items:flex-start;gap:0}
  .ak-permtable__lvlname{display:block}
  .ak-permtable__grouphead > .ak-grpset{margin-inline-start:0}
}
@media (forced-colors:active){
  .ak-permtable tbody tr[data-changed]{box-shadow:none;
    outline:2px dashed CanvasText;outline-offset:-2px}
}

/* ---- 4.20 Group setter -----------------------------------------------
   A row of pill buttons on a group's header that sets every row in the
   group to one value at once ("Set all of Sales to View"). Each pill is
   .ak-btn.ak-btn--sm with aria-pressed: pressed when every row in the
   group already holds that value. It changes the rows on the page and
   saves nothing. Markup: div.ak-grpset[role=group][aria-label] > .ak-btn.
   Added 3 Oct 2026 for the access register (2.5.0). */
.ak-grpset{display:flex;flex-wrap:wrap;align-items:center;gap:var(--ak-s-1)}
.ak-grpset > .ak-btn{border-radius:var(--ak-r-pill)}
.ak-grpset__label{font-size:var(--ak-fs-small);color:var(--ak-ink-muted);
  margin-inline-end:var(--ak-s-1)}

/* ---- 4.21 Action bar -------------------------------------------------
   The bar under a long editor whose changes are saved together: how
   many rows changed and what kind, and the buttons that act on them.
   It sticks to the bottom of the page while there is more above it,
   but it is in the flow, so it keeps its own room at the end and never
   sits over the last rows; and the page keeps --ak-actionbar-reserve
   clear when focus moves, so a focused row is never hidden under it
   (WCAG 2.2 · 2.4.11). A button that cannot act yet is aria-disabled
   (still focusable) and aria-describedby .ak-actionbar__why, which says
   why. Markup: div.ak-actionbar > .ak-actionbar__count,
   .ak-actionbar__detail, .ak-actionbar__actions > .ak-btn,
   .ak-actionbar__why. With nothing to act on it is
   .ak-actionbar[data-idle] and stays at the end. Added 3 Oct 2026 for
   the access register (2.5.0). */
.ak-actionbar{position:sticky;bottom:0;z-index:var(--ak-z-sticky);
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--ak-gap-inside) var(--ak-gap-between);
  padding:var(--ak-s-3) var(--ak-s-4);background:var(--ak-surface);
  border:var(--ak-border) solid var(--ak-line-strong);border-radius:var(--ak-r-md);
  box-shadow:var(--ak-shadow-rise)}
.ak-actionbar__count{font-weight:var(--ak-fw-semibold);font-variant-numeric:tabular-nums}
.ak-actionbar__detail{font-size:var(--ak-fs-small);color:var(--ak-ink-muted);
  font-variant-numeric:tabular-nums}
.ak-actionbar__actions{margin-inline-start:auto;display:flex;flex-wrap:wrap;gap:var(--ak-s-2)}
.ak-actionbar__why{flex-basis:100%;font-size:var(--ak-fs-small);color:var(--ak-ink-muted)}
.ak-actionbar__why:empty{display:none}
/* With nothing to act on, the bar keeps its place at the end and does
   not follow the reader over the rows: .ak-actionbar[data-idle]. */
.ak-actionbar[data-idle]{position:static;box-shadow:none}
.ak-main:has(.ak-actionbar){scroll-padding-block-end:var(--ak-actionbar-reserve)}
@media (max-width:640px){
  .ak-actionbar{padding:var(--ak-s-2) var(--ak-s-3)}
  .ak-actionbar__actions{margin-inline-start:0;inline-size:100%}
}

/* ---- 4.22 Preset card ------------------------------------------------
   A named starting point ("Accounts executive") that fills an editor
   with a set of values the person can then adjust. Applying it changes
   the editor and saves nothing; the card says so. Cards sit in
   .ak-presets, a wrapping grid. The card last applied is
   .ak-preset[data-applied] — a left rule and the words "Applied", never
   the rule alone. Markup: div.ak-presets > article.ak-preset >
   h3.ak-preset__name, p.ak-preset__what, div.ak-preset__foot > .ak-btn.
   Added 3 Oct 2026 for the access register (2.5.0). */
.ak-presets{display:grid;gap:var(--ak-gap-between);
  grid-template-columns:repeat(auto-fill,minmax(min(var(--ak-preset-min),100%),1fr))}
.ak-preset{display:flex;flex-direction:column;gap:var(--ak-gap-inside);
  padding:var(--ak-s-3) var(--ak-s-4);background:var(--ak-surface);
  border:var(--ak-border) solid var(--ak-line);border-radius:var(--ak-r-md)}
.ak-preset__name{margin:0;font-size:var(--ak-fs-base);font-weight:var(--ak-fw-semibold)}
.ak-preset__what{margin:0;font-size:var(--ak-fs-small);color:var(--ak-ink-muted)}
.ak-preset__foot{margin-block-start:auto;display:flex;flex-wrap:wrap;align-items:center;
  gap:var(--ak-gap-inside)}
.ak-preset[data-applied]{border-color:var(--ak-action);
  box-shadow:inset 3px 0 0 0 var(--ak-action)}
@media (forced-colors:active){.ak-preset[data-applied]{border-width:2px}}

/* ---- 4.23 Search list (2.11.0) --------------------------------------
   The list a search box opens: customers, enquiries, items. The box is
   input.ak-input[role="combobox"] inside .ak-combobox; the list is
   div.ak-listbox[role="listbox"], one per dialog, placed by its script from
   the box's rectangle through --ak-listbox-x, -y (or -b to open upward),
   -w and -h. It is fixed, so a scrolling table or a sticky footer never
   clips it, and it lives in the dialog itself, so a modal keeps it on top.
   At least 420px wide where the screen allows. Keyboard: Down and Up move
   (aria-activedescendant on the box), Enter picks, Tab picks and moves on,
   Esc closes the list and only the list. A row is .ak-listbox__option
   (aria-selected when highlighted) with __name, wrapping in full, and
   __meta: code, place, unit, history. The letters typed are in <mark>.
   A note (no match, how many more) is .ak-listbox__note. While the search
   reads, the combobox carries data-busy and draws a small turning mark
   in the box. Added 10 Oct 2026 for the quotation journey (Bhav). */
.ak-combobox{position:relative;min-inline-size:0}
.ak-combobox[data-busy]::after{content:"";position:absolute;inset-inline-end:var(--ak-s-3);
  inset-block-start:50%;inline-size:var(--ak-s-4);block-size:var(--ak-s-4);
  margin-block-start:calc(var(--ak-s-4) / -2);border-radius:50%;
  border:2px solid var(--ak-line);border-block-start-color:var(--ak-action);
  animation:ak-turn .8s linear infinite}
@keyframes ak-turn{to{transform:rotate(360deg)}}
.ak-listbox{position:fixed;z-index:var(--ak-z-dropdown);margin:0;
  inset-inline-start:var(--ak-listbox-x,0);inset-block-start:var(--ak-listbox-y,auto);
  inset-block-end:var(--ak-listbox-b,auto);inline-size:var(--ak-listbox-w,26.25rem);
  max-block-size:var(--ak-listbox-h,20rem);overflow-y:auto;overscroll-behavior:contain;
  padding-block:var(--ak-s-1);background:var(--ak-surface);color:var(--ak-ink);
  border:var(--ak-border) solid var(--ak-line-strong);border-radius:var(--ak-r-md);
  box-shadow:var(--ak-shadow-overlay)}
.ak-listbox__option{display:flex;flex-direction:column;gap:2px;cursor:pointer;
  padding:var(--ak-s-2) var(--ak-s-3);border-inline-start:3px solid transparent}
.ak-listbox__option + .ak-listbox__option{border-block-start:var(--ak-border) solid var(--ak-line)}
.ak-listbox__option:hover,.ak-listbox__option[aria-selected="true"]{background:var(--ak-sunk);
  border-inline-start-color:var(--ak-action)}
.ak-listbox__name{font-weight:var(--ak-fw-medium);overflow-wrap:anywhere}
.ak-listbox__meta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--ak-s-1) var(--ak-s-3);
  font-size:var(--ak-fs-small);color:var(--ak-ink-muted)}
.ak-listbox__note{padding:var(--ak-s-2) var(--ak-s-3);font-size:var(--ak-fs-small);color:var(--ak-ink-muted)}
.ak-listbox mark{background:var(--ak-action-bg);color:inherit;font-weight:var(--ak-fw-semibold)}
/* .ak-listbox--flow draws one in place, as the design book shows it. */
.ak-listbox.ak-listbox--flow{position:static;inline-size:auto;max-block-size:none;box-shadow:none}
@media (pointer:coarse){.ak-listbox__option{min-block-size:var(--ak-target-touch);justify-content:center}}
@media (prefers-reduced-motion:reduce){.ak-combobox[data-busy]::after{animation:none}}
@media (forced-colors:active){
  .ak-listbox{border:1px solid CanvasText}
  .ak-listbox__option[aria-selected="true"]{outline:2px solid Highlight;outline-offset:-2px}
  .ak-listbox mark{background:Mark;color:MarkText}
}

} /* end layer components */

/* ===================================================================
   5 · STATES
   =================================================================== */
@layer states {
.ak-is-loading{cursor:progress}
.ak-is-busy{opacity:.55;pointer-events:none}
[data-state="overdue"]{/* reserved: never a colour. Use .ak-age. */}
/* 2.8.0: a build note shows only while a Director has build notes on */
:root:not([data-build-notes="on"]) [data-ak-buildnote]{display:none}
} /* end layer states */

/* ===================================================================
   6 · UTILITIES — a small, closed set. If you need a seventh, the
   component is missing, not the utility.
   =================================================================== */
@layer utilities {
.ak-stack{display:flex;flex-direction:column;gap:var(--ak-s-3)}
.ak-row{display:flex;align-items:center;gap:var(--ak-s-2);flex-wrap:wrap}
.ak-push{margin-left:auto}
.ak-muted{color:var(--ak-ink-muted)}
.ak-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.ak-nowrap{white-space:nowrap}
} /* end layer utilities */

/* ===================================================================
   7 · PRINT — an ERP prints. Invoices, COAs, picking lists, audit
   packs. Printed output is a brand touchpoint, not an afterthought.
   =================================================================== */
/* ak-unlayered: paper must win over the screen. In a layer, :root here
   (0,1,0) would lose to the dark theme's :root[data-theme="dark"] and
   :root:not([data-theme="light"]) (0,2,0) in tokens, so a page printed
   in the dark theme would print dark; and its !important would outrank a
   page's own unlayered !important, which it does not today. */
@media print{
  :root,:host{--ak-bg:#FFF;--ak-surface:#FFF;--ak-ink:#000;--ak-line:#999}
  .ak-rail,.ak-masthead,.ak-toasts,.ak-filterbar,.ak-btn,.ak-tabs{display:none!important}
  .ak-app{display:block;height:auto}
  .ak-main{overflow:visible;padding:0}
  .ak-card{border:1px solid #999;box-shadow:none;break-inside:avoid}
  .ak-table{font-size:10pt}
  .ak-table thead{display:table-header-group}  /* repeat head per page */
  .ak-table tr{break-inside:avoid}
  .ak-chip{border:1px solid currentColor;background:none!important}
  a[href^="http"]::after{content:" (" attr(href) ")";font-size:9pt;color:#555}
  /* 2.18.0: while a dialog is open only the dialog prints. Everything that
     is neither the open dialog, inside it, nor holding it is left off; the
     dialog prints as a plain block with its whole body (a sheet's fixed
     height and a body's scroll are screen things). Its buttons go with the
     .ak-btn rule above. */
  body:has(dialog[open]) *:not(dialog[open], dialog[open] *, :has(dialog[open])){display:none!important}
  dialog[open]{position:static;inset:auto;margin:0;inline-size:auto;max-inline-size:none;
    block-size:auto;max-block-size:none;overflow:visible;border:0;box-shadow:none;transform:none}
  dialog[open]::backdrop{display:none}
  dialog[open] .ak-modal__body{overflow:visible;max-block-size:none;flex:none}
}

/* ===================================================================
   8 · FORCED COLOURS — Windows high contrast. Status must survive
   when the OS throws our palette away (WCAG 2.2 · 1.4.1).
   =================================================================== */
/* ak-unlayered: the last word in forced colours, across components. In
   components these borders would lose to the states layer
   (.ak-input[readonly] and [aria-invalid] border colours) and to
   .ak-banner[data-state] (0,2,0); in base the 3px Highlight focus ring
   would lose to the components' own 2px rings (.ak-tab, .ak-sort,
   .ak-select ...). The three rules stay together: a focused row with a
   tabindex takes the row's 1px outline, which a split would reverse. */
@media (forced-colors:active){
  .ak-chip,.ak-banner,.ak-btn,.ak-card,.ak-input,dialog.ak-modal{border:1px solid CanvasText}
  .ak-table tbody tr[data-state]{box-shadow:none;outline:1px solid CanvasText;
    outline-offset:-1px}
  :where(a,button,input,select,textarea,[tabindex]):focus-visible{
    outline:3px solid Highlight;box-shadow:none}
}

/* ===================================================================
   9 · ALIGNMENT
   -------------------------------------------------------------------
   Alignment is not decoration. On a screen carrying four hundred
   numbers it is the difference between reading and hunting.

   Designed against ISO 9241-112 (principles for the presentation of
   information: detectability, discriminability, conciseness,
   consistency, legibility, comprehensibility) and ISO 9241-125
   (guidance on the visual presentation of information). Both are
   GUIDANCE — neither is a certification scheme.

   Two WCAG 2.2 criteria bind here and are testable:
     1.4.8 Visual presentation (AAA) — text is never justified.
           We adopt the no-justification rule at every level because
           it costs nothing and helps most the readers who struggle.
     1.4.12 Text spacing (AA)        — the layout must survive a
           reader overriding line-height to 1.5, paragraph spacing to
           2x, letter-spacing to 0.12em and word-spacing to 0.16em.
           That is why no text container in this system has a fixed
           height; controls use min-height so they grow instead of
           clipping.
   =================================================================== */
@layer base {

/* Logical, never physical. start/end flip with writing direction, so
   Devanagari today and any right-to-left rendering later need no
   second stylesheet and no overrides. */
body{text-align:start}
p,li,dd,dt,figcaption,blockquote{text-align:start}

/* Justified text is banned outright. Forcing both edges flush opens
   rivers of white space that the eye follows DOWN the page instead of
   across the line, and it hurts dyslexic readers most. There is no
   case for it in an ERP. */
/* Nothing in this system sets justify. This is the safety net for
   pasted or imported markup that arrives carrying it. */
[align="justify"],[style*="justify"]{text-align:start!important}

/* Centring kills the return sweep: the eye needs a hard start edge to
   fall back to at the end of each line. Centre a single heading or a
   number in an empty state — never a block of running text. */
.ak-center{text-align:center}
.ak-center > p{max-width:52ch;margin-inline:auto}

/* The measure. Beyond roughly 75 characters the eye loses the line it
   was on when it sweeps back. Below about 45 it sweeps too often. */
.ak-read,.ak-pagehead__intro,.ak-help,.ak-empty p{max-width:var(--ak-reading-max)}

} /* end layer base — alignment */

@layer components {

/* ---- 9.0 Controls grow, never clip --------------------------------
   WCAG 2.2 · 1.4.12 lets a reader push letter-spacing to 0.12em and
   line-height to 1.5. A control with a fixed height clips its own
   label when they do. Height becomes a floor here, not a ceiling.
   These rules sit in the components layer deliberately: the heights
   they override are declared here, and a later layer always wins over
   an earlier one regardless of specificity. */
.ak-btn{height:auto;min-height:var(--ak-control-h)}
/* …and a label wraps rather than push the page sideways (v2.0.4). */
.ak-btn{white-space:normal;line-height:var(--ak-lh-tight);padding-block:var(--ak-s-1)}
/* …except in a row's actions (v2.2.2). The cell is nowrap so the buttons
   sit on one line; a label that may still wrap tells the table the column
   is narrower than it is, and the last button spills past the table's
   edge instead of the table scrolling. */
.ak-td-actions .ak-btn{white-space:nowrap}
.ak-btn--sm{height:auto;min-height:26px}
.ak-btn--lg{height:auto;min-height:var(--ak-control-h-lg)}
.ak-btn--icon{min-width:var(--ak-control-h)}
.ak-input,.ak-textarea{height:auto;min-height:var(--ak-control-h)}
.ak-chip,.ak-tab{height:auto}

/* ---- 9.1 Table alignment — by what the column HOLDS ---------------
   The rule is mechanical, so nobody has to have an opinion:

     words, names, codes read as words  -> start
     quantities, money, counts, percent -> end, monospace, tabular
     dates shown for comparison         -> end, monospace
     dates shown as prose               -> start
     status, chips, icons               -> start
     row actions                        -> end

   And the header ALWAYS matches its column. A left-aligned header over
   right-aligned figures is the single commonest table defect in
   enterprise software: the eye anchors on the header and then has to
   re-find the column. */
.ak-table th[data-align="end"],
.ak-table td[data-align="end"]{text-align:end}
.ak-table th[data-align="start"],
.ak-table td[data-align="start"]{text-align:start}
/* Numeric cells carry their own header alignment automatically when the
   header is marked. Mark the header; never the other way round.

   The selector is deliberately as specific as the rule it has to beat:
   `.ak-table thead th` is (0,1,2) and a bare `.ak-th-num` is (0,1,0),
   so the bare class silently lost and every numeric header stayed
   start-aligned — the exact defect this section exists to prevent.
   Same layer, later in the file, still lost: source order only breaks
   ties at EQUAL specificity. */
.ak-table thead th.ak-th-num{text-align:end}

/* Figures line up by place value or they are not comparable. Fixed
   decimal places are part of the contract: 0 is written 0.00 in a
   column of money, because a ragged decimal point defeats the column.
   CSS cannot align on a decimal character, so the discipline is
   tabular figures plus a fixed number of decimals, formatted before
   the value ever reaches the cell. */
.ak-td-num,.ak-num,.ak-th-num{font-variant-numeric:tabular-nums}

/* Units belong in the header, not repeated down the column. A column
   of "12,400.000 kg" is 40% noise and breaks the digit alignment. */
.ak-unit{font-size:var(--ak-fs-tiny);font-weight:var(--ak-fw-regular);
  color:var(--ak-ink-muted);text-transform:none;letter-spacing:0;margin-inline-start:4px}

/* A column of codes reads as words, not numbers: start-aligned, but
   monospaced so a transposed character is visible. */
.ak-td-code{font-family:var(--ak-font-mono);text-align:start}

/* ---- 9.2 Form label alignment ------------------------------------
   Top-aligned labels by default: the label and its field sit on one
   vertical axis, so the eye makes one movement per field instead of
   two. They are the fastest to complete and the only arrangement that
   survives long labels and translated labels without re-layout.

   End-aligned labels are permitted ONLY in a dense read-mostly review
   block, where the label-value pairs form a tight two-column list and
   the values are what is being scanned. */
.ak-field{align-items:stretch}
.ak-field--inline{display:grid;grid-template-columns:minmax(0,10rem) minmax(0,1fr);
  gap:var(--ak-s-2) var(--ak-s-4);align-items:baseline}
.ak-field--inline > .ak-label{text-align:end;color:var(--ak-ink-muted);
  margin:0;white-space:normal}
@media (max-width:640px){
  .ak-field--inline{grid-template-columns:minmax(0,1fr)}
  .ak-field--inline > .ak-label{text-align:start}
}

/* A required mark sits after the label text, never before it, so the
   label still starts at the column edge. */
.ak-label .ak-req{color:var(--ak-failed);margin-inline-start:2px}

/* ---- 9.3 Vertical rhythm in a row --------------------------------
   Everything in a table row shares one baseline band. A chip, a figure
   and a two-line name cell all centre on the same axis, so the row
   scans as one line rather than three. */
.ak-table tbody td{vertical-align:middle}
.ak-table tbody td.ak-td-top{vertical-align:top}

} /* end layer components — alignment */


/* ===================================================================
   10 · ATTENTION — where the eye goes first, and why
   -------------------------------------------------------------------
   The eye resolves a handful of attributes BEFORE conscious search:
   colour, size, weight, position, enclosure, isolation and motion.
   These are the only levers that genuinely draw attention; everything
   else is read, not seen.

   THE RULE THAT MATTERS: one attribute per level of importance.
   Bold AND red AND boxed AND iconned does not make an item four times
   more visible — it makes the screen loud, and a loud screen has no
   hierarchy at all. Spend one attribute, keep the rest in reserve.

   THE BUDGET, per screen region:
     1  focal element   — the one thing that must be seen
     2-3 second tier    — the things that should be found quickly
     everything else    — found by reading, which is fine

   THE TEST: squint at the screen until the text blurs. What is still
   distinguishable should be exactly what matters. If three things
   survive the squint and only one matters, the screen is wrong.
   =================================================================== */
@layer utilities {

/* ---- 10.1 Ink tiers — hierarchy with no colour at all -------------
   Three levels of ink carry most of the hierarchy in this system.
   They work in both themes, survive greyscale printing and forced
   colours, and cost nothing. Reach for these before reaching for a
   hue. */
.ak-ink-1{color:var(--ak-ink)}          /* the datum                   */
.ak-ink-2{color:var(--ak-ink-2)}        /* supporting                  */
.ak-ink-3{color:var(--ak-ink-muted)}    /* context, labels, metadata   */

/* ---- 10.2 The focal element ---------------------------------------
   At most ONE per region. Isolation and weight, not colour — so it
   still reads when the region already carries a status hue, and so it
   never competes with a refusal or an approval. */
.ak-focal{
  font-weight:var(--ak-fw-semibold);
  color:var(--ak-ink);
  font-variant-numeric:tabular-nums;
}
/* A focal FIGURE is sized, not coloured. Size is the strongest
   pre-attentive attribute that carries meaning on its own: bigger
   genuinely means more important, which colour never does. */
.ak-focal-num{
  font-family:var(--ak-font-mono);font-size:var(--ak-fs-kpi);
  font-weight:var(--ak-fw-semibold);line-height:var(--ak-lh-tight);
  font-variant-numeric:tabular-nums;letter-spacing:var(--ak-ls-tight);
  color:var(--ak-ink);display:block;
}
/* Isolation: the cheapest attention device there is. White space costs
   no ink, adds no colour and cannot clash with anything. Use it before
   anything else. */
.ak-isolate{margin-block:var(--ak-s-6)}
.ak-isolate--tight{margin-block:var(--ak-s-4)}

/* ---- 10.3 Deliberate quiet -----------------------------------------
   Attention is zero-sum. The reliable way to make one thing louder is
   to make its neighbours quieter. These exist so that de-emphasis is a
   decision somebody made, not an accident of defaults. */
.ak-quiet{color:var(--ak-ink-muted);font-weight:var(--ak-fw-regular)}
.ak-quiet-num{font-weight:var(--ak-fw-regular);color:var(--ak-ink-muted)}
/* A zero that means "nothing to do here" should not shout like a zero
   that means "the balance is nil". Mark the first one. */
.ak-nil{color:var(--ak-ink-muted);font-weight:var(--ak-fw-regular)}

/* ---- 10.4 Enclosure, used sparingly --------------------------------
   A box says "this is a separate object". Boxing something that is not
   a separate object spends the strongest grouping signal on nothing,
   and the next real box reads as ordinary. One enclosure per idea. */
.ak-callout{
  border-inline-start:3px solid var(--ak-action);
  background:var(--ak-action-bg);
  padding:var(--ak-s-3) var(--ak-s-4);
  border-radius:0 var(--ak-r-md) var(--ak-r-md) 0;
}

/* ---- 10.5 Attention is not focus ----------------------------------
   Attention is a design decision about what a reader should notice.
   Focus is a machine state about where the keyboard is. They must
   never be expressed the same way: a focal element that looks focused
   teaches people that the focus ring means nothing. The focus ring in
   this system is reserved, always visible, and never reused for
   emphasis. */
/* ---- 10.6 Scan anchors ---------------------------------------------
   In a list, the eye reads the first two or three words of each line
   and nothing else until something stops it. So the information-
   carrying word goes first: "Overdue 41 days — ABC Agrochemicals",
   never "ABC Agrochemicals has a payment that is 41 days overdue".
   This class marks the anchor so it survives translation and
   re-ordering. */
.ak-anchor{font-weight:var(--ak-fw-semibold);color:var(--ak-ink)}

} /* end layer utilities — attention */

/* ===================================================================
   11 · SPACE AND WHITE SPACE
   -------------------------------------------------------------------
   White space is not what is left over. It is the only device that
   says "these things belong together" without drawing anything.

   THE PROXIMITY RULE — the one rule the rest of this section serves:

       space INSIDE a group must be smaller than space AROUND it.

   If the gap between a label and its field equals the gap between two
   fields, the eye has no grouping to read and the form becomes a list
   of twenty equal things. Most "cluttered" screens are not too dense;
   they are evenly spaced.

   Four levels, and nothing in between. A value that is not one of
   these four is a value somebody guessed.

     INSIDE   4-8px    label to field, chip to text, icon to label
     BETWEEN  12-16px  one field to the next, card to card
     GROUP    24-32px  one group of fields to the next group
     SECTION  40-64px  one section of a screen to the next

   Designed against ISO 9241-125 (guidance on visual presentation) and
   the Gestalt proximity principle it rests on. Guidance, not a
   certification scheme.
   =================================================================== */
@layer tokens {
:root,:host{
  /* The four proximity levels, named by what they mean rather than by
     size — so a component asks for the relationship, not the number. */
  --ak-gap-inside:var(--ak-s-2);     /* 8  — within one thing          */
  --ak-gap-between:var(--ak-s-4);    /* 16 — thing to sibling thing    */
  --ak-gap-group:var(--ak-s-7);      /* 32 — group to group           */
  --ak-gap-section:var(--ak-s-9);    /* 48 — section to section       */

  /* The page gutter. One value per breakpoint, used by every screen,
     so the left edge of the content never moves between modules.
     The 16px floor holds at 320px, which is the WCAG 2.2 reflow
     width (1.4.10) — not 375, not 390. */
  --ak-gutter:var(--ak-s-6);         /* desktop                        */

  /* Target sizes. WCAG 2.2 · 2.5.8 (AA) requires 24x24 CSS px with a
     spacing exception. 2.5.5 (AAA) asks for 44x44. We take 24 as the
     absolute floor anywhere, and 44 as the rule for anything a person
     taps rather than clicks — which is cheap on a phone and free on a
     desktop, because a desktop control is already larger. */
  --ak-target-min:24px;
  --ak-target-touch:44px;
}
/* Compact loses the group and section steps proportionally, not
   absolutely — otherwise compact density destroys grouping, which is
   the thing that made the screen readable in the first place.

   The selector is deliberately element-level, not :root — v1 declared
   these on :root only, which silently broke the documented promise
   that a single region can be set to its own density. Custom
   properties inherit, so this works on any container. */
[data-density="compact"]{
  --ak-gap-inside:var(--ak-s-1);
  --ak-gap-between:var(--ak-s-3);
  --ak-gap-group:var(--ak-s-6);
  --ak-gap-section:var(--ak-s-7);
  --ak-gutter:var(--ak-s-4);
}
[data-density="comfortable"]{
  --ak-gap-inside:var(--ak-s-3);
  --ak-gap-between:var(--ak-s-5);
  --ak-gap-group:var(--ak-s-8);
  --ak-gap-section:var(--ak-s-10);
  --ak-gutter:var(--ak-s-7);
}
}

@layer layout {
/* The four levels as layout primitives. Use these instead of writing
   a margin: a margin is a number, a stack is a relationship. */
.ak-stack-inside{display:flex;flex-direction:column;gap:var(--ak-gap-inside)}
.ak-stack-between{display:flex;flex-direction:column;gap:var(--ak-gap-between)}
.ak-stack-group{display:flex;flex-direction:column;gap:var(--ak-gap-group)}
.ak-stack-section{display:flex;flex-direction:column;gap:var(--ak-gap-section)}
/* A stack's children keep their height (v2.3.0). Inside a container of
   fixed height (a dialog's body) a flex child that scrolls on its own —
   tabs, a table — was allowed to shrink to nothing; the container scrolls
   instead. Zero specificity, so a component may still say otherwise. */
:where(.ak-stack-inside,.ak-stack-between,.ak-stack-group,.ak-stack-section) > *{flex-shrink:0}
.ak-inline{display:flex;align-items:center;gap:var(--ak-gap-inside);flex-wrap:wrap}
.ak-inline-between{display:flex;align-items:center;gap:var(--ak-gap-between);flex-wrap:wrap}

/* Spacing lives on the PARENT as a gap, never on children as margins.
   Gaps do not collapse, do not double up, and do not leave a stray
   margin behind when the last child is removed by a permission check —
   which in this system happens on every screen. */
.ak-page{gap:var(--ak-gap-section)}
.ak-section{gap:var(--ak-gap-between)}

/* The gutter, applied once. Both the main region and any full-bleed
   bar take the same value, so nothing is ever 3px out. */
.ak-main{padding-inline:var(--ak-gutter)}
.ak-masthead{padding-inline:var(--ak-gutter)}

/* Breathing room at the end of a scroll region. Without it the last
   row sits against the viewport edge and reads as cut off. */
.ak-main{padding-block-end:var(--ak-s-10)}
}

/* ===================================================================
   12 · RESPONSIVE — one system, two postures
   -------------------------------------------------------------------
   Desktop-first for the register screens a power user lives in;
   genuinely designed, not merely survivable, on a phone.

   BREAKPOINTS. Four are named. The other widths are a component's own,
   each kept because it does one job; folding them into the four would
   move screens, and nobody has asked for that (owner, 12 Oct 2026).
   Every @media width in this file is on the list below and nothing
   else is: tools/ak-contract.mjs fails a change that uses a width not
   on it, or keeps a line here for a width no longer used. To add a
   width, add its line here, saying what it does and who uses it.
   "max 767" is (max-width:767px); "min 768" is (min-width:768px).

   NAMED, with their off-by-one partners
     sm   480px   large phone
       max  479  below sm: 12px gutter, one KPI a row, figures step down
                 (12; .ak-kpi__value, .ak-metric__value, .ak-measure,
                 .ak-skeleton--figure, .ak-tile__blurb)
       max  480  the masthead sheds [data-shed="480"] (19)
     md   768px   tablet portrait
       max  767  touch posture: 44px rows and controls, card tables,
                 stacked filter bar, one-column widgets (12, 15.5;
                 .ak-filterbar, .ak-table--entry, .ak-measure,
                 .ak-wgrid, .ak-metrics, .ak-table--stickycol2)
       min  768  six KPI tiles keep one row; four go two by two (20.1b,
                 21.5)
     lg  1024px   the rail becomes a drawer below this
       max 1023  the rail is a drawer; 16px gutter (3, 12)
       min 1024  the rail's brand shows; a fitted board (.ak-board--fit)
     xl  1280px   full desktop
       max 1279  the trail drops "Home /", the brand keeps its mark,
                 home widgets go half or whole (3, 19, 20.1a)

   A COMPONENT'S OWN WIDTH
       max  374  narrowest phones: a card's label goes above its value
                 (15.5, .ak-table--cards)
       max  640  phone chrome: masthead buttons to icons, the action
                 bar, inline fields stack, the tab bar and floating
                 action, .ak-calendar, .ak-matrix, .ak-permtable,
                 .ak-modal--sheet, .ak-facts (a label over its value), the
                 main's bottom pad, data-phone="hide" (3, 4, 9, 18,
                 19, 21, 23)
       min  641  data-phone="only" hides above the phone (23.3)
       max  720  an audit row stacks (.ak-audit__row)
       max  899  the sign-in's brand panel goes above the form (.ak-auth)
       max  900  the masthead compacts: the trail truncates, search
                 becomes a button, [data-shed="900"] (3, 18, 19)
       max 1100  the detail grid goes to one column (.ak-grid--detail)
       max 1180  the masthead search narrows (18)
       min 1200  a strip of four KPI tiles goes four across (2.20.3;
                 768-1199 is two by two)
       max 1365  the masthead's role-and-company chip leaves (2.13.2)

   THE FLOOR IS 320px, not 375 and not 390. WCAG 2.2 · 1.4.10 (Reflow,
   AA) requires content to work at 320 CSS px wide without scrolling in
   two directions — which is also what a 1280px desktop looks like at
   400% zoom. Test at 320; a phone is the easy case.
   =================================================================== */
@layer layout {

@media (max-width:1023px){
  :root,:host{--ak-gutter:var(--ak-s-4)}
}
@media (max-width:767px){
  :root,:host{
    --ak-gutter:var(--ak-s-4);
    /* Touch posture: rows and controls grow, grouping grows with them
       so the proximity rule still holds. */
    --ak-row-h:44px; --ak-control-h:44px;
    --ak-gap-group:var(--ak-s-7);
  }
  .ak-page{gap:var(--ak-s-7)}
  .ak-pagehead__actions{width:100%}
  .ak-pagehead__actions .ak-btn{flex:1 1 auto}
  .ak-grid--kpi{grid-template-columns:repeat(2,minmax(0,1fr))}
  .ak-tabs{margin-inline:calc(var(--ak-gutter) * -1);padding-inline:var(--ak-gutter)}
  /* 2.11.1: a drawer has no gutter to bleed into */
  .ak-drawer .ak-tabs{margin-inline:0}
}
@media (max-width:479px){
  :root,:host{--ak-gutter:var(--ak-s-3)}   /* 12px — still clear of the edge at 320 */
  .ak-grid--kpi{grid-template-columns:minmax(0,1fr)}
}

/* The AA floor, everywhere: 24px. Every component already clears it, so
   it sits in layout as a floor beneath them. The touch rule, which must
   RAISE component heights, is in the components layer (section 12a). */
.ak-btn,.ak-tab,.ak-rail__item,.ak-input,.ak-select,.ak-textarea,
.ak-sort,.ak-pager button{min-height:var(--ak-target-min)}

/* Safe areas — a phone with a notch or a home bar. The app frame already
   pads the rail; these cover the two bars that sit at the very edges. */
.ak-masthead{padding-top:env(safe-area-inset-top,0px)}
.ak-main{padding-bottom:calc(var(--ak-s-10) + env(safe-area-inset-bottom,0px))}

/* The 320 guarantee: nothing may force the page wider than the screen.
   Long unbroken strings — a GSTIN, a document number, an email — are
   the usual culprit. */
.ak-app,.ak-main,.ak-page{max-width:100%}
.ak-break{overflow-wrap:anywhere}
}

@layer components {
/* Every interactive thing meets the AA floor, everywhere, and the
   touch rule where a finger is the pointer. This is a guarantee, so it
   is written once rather than per component.

   12a · The touch rule lives in the COMPONENTS layer, not layout: it
   raises component heights, and .ak-btn--sm's min-height is declared in
   components, so in the layout layer it silently lost and a small button
   stayed 26px under a finger (CLAUDE.md section 1, rule 6). The 24px
   floor stays in layout (section 12). */
@media (pointer:coarse){
  .ak-btn,.ak-tab,.ak-rail__item,.ak-pager button,.ak-check,.ak-radio,.ak-switch{
    min-height:var(--ak-target-touch)}
  /* 2.13.1: named at its own specificity, or the component's rule wins */
  .ak-table th button.ak-sort{min-height:var(--ak-target-touch)}
  .ak-btn--icon{min-width:var(--ak-target-touch)}
  /* the large button keeps its own height when that is taller (comfortable) */
  .ak-btn--lg{min-height:max(var(--ak-control-h-lg),var(--ak-target-touch))}
  /* Where a control must stay visually small, the HIT AREA grows
     instead of the control — the 2.5.8 spacing exception, done
     properly rather than by making everything huge. */
  .ak-hit{position:relative}
  .ak-hit::after{content:"";position:absolute;inset:50% auto auto 50%;
    width:var(--ak-target-touch);height:var(--ak-target-touch);
    transform:translate(-50%,-50%)}
}
}

/* ===================================================================
   13 · FORM CONTROLS — the ones v1 was missing
   =================================================================== */
@layer components {

/* ---- 13.1 The form itself -----------------------------------------
   A form is groups of fields, not a list of fields. The fieldset
   carries the group gap; the field carries the inside gap. That is the
   proximity rule expressed as markup. */
.ak-form{display:flex;flex-direction:column;gap:var(--ak-gap-group)}
.ak-fieldset{border:0;margin:0;padding:0;display:flex;flex-direction:column;
  gap:var(--ak-gap-between);
  /* A browser gives a fieldset min-inline-size:min-content, so a wide
     table inside one pushed the page sideways instead of scrolling in
     its own region (v2.4.0). */
  min-inline-size:0}
.ak-fieldset > legend{padding:0;font-size:var(--ak-fs-h4);
  font-weight:var(--ak-fw-semibold);margin-bottom:var(--ak-gap-inside)}
.ak-fieldset__hint{font-size:var(--ak-fs-small);color:var(--ak-ink-muted);
  margin:calc(var(--ak-gap-inside) * -1) 0 0;max-width:var(--ak-reading-max)}
.ak-formgrid{display:grid;gap:var(--ak-gap-between);
  grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}
.ak-formgrid--2{grid-template-columns:repeat(auto-fit,minmax(min(280px,100%),1fr))}  /* 2.2.1: min(), as the grids */
.ak-field--wide{grid-column:1/-1}
/* Actions sit at the end and stick on a long form, so a person never
   scrolls to find Save. */
.ak-form__actions{display:flex;gap:var(--ak-gap-between);flex-wrap:wrap;
  padding-block:var(--ak-s-4);border-top:var(--ak-border) solid var(--ak-line);
  position:sticky;bottom:0;background:var(--ak-surface);z-index:var(--ak-z-sticky)}
.ak-form__actions .ak-push{margin-inline-start:auto}

/* ---- 13.2 Checkbox and radio --------------------------------------
   Native input, styled. Never a div pretending to be a checkbox: the
   native one is announced correctly, works in forms, and survives
   forced colours without any help. */
.ak-check,.ak-radio{display:inline-flex;align-items:flex-start;
  gap:var(--ak-gap-inside);cursor:pointer;font-size:var(--ak-fs-base);
  line-height:var(--ak-lh-normal);min-height:var(--ak-target-min)}
/* Under a finger the whole label is a 44px target. Said again here
   because this rule, later in the same layer, undid the touch rule in
   12.x and left a radio or a tick box 24px tall (v2.5.0; the same trap
   as .ak-switch in 2.4.0). */
@media (pointer:coarse){.ak-check,.ak-radio{min-height:var(--ak-target-touch)}}
.ak-check > input,.ak-radio > input{
  appearance:none;margin:0;flex:0 0 auto;
  inline-size:18px;block-size:18px;margin-block-start:2px;
  border:2px solid var(--ak-line-control);background:var(--ak-surface);
  display:grid;place-content:center;cursor:pointer;
  transition:border-color var(--ak-dur-instant) var(--ak-ease-out),
             background var(--ak-dur-instant) var(--ak-ease-out);
}
.ak-check > input{border-radius:var(--ak-r-xs)}
.ak-radio > input{border-radius:50%}
.ak-check > input::before,.ak-radio > input::before{
  content:"";inline-size:10px;block-size:10px;transform:scale(0);
  transition:transform var(--ak-dur-instant) var(--ak-ease-out);
  background:var(--ak-ink-inverse)}
.ak-check > input::before{
  clip-path:polygon(14% 44%,0 65%,40% 100%,100% 16%,84% 0,39% 68%)}
.ak-radio > input::before{border-radius:50%;inline-size:8px;block-size:8px}
.ak-check > input:checked,.ak-radio > input:checked{
  background:var(--ak-action);border-color:var(--ak-action)}
.ak-check > input:checked::before,.ak-radio > input:checked::before{transform:scale(1)}
.ak-check > input:indeterminate{background:var(--ak-action);border-color:var(--ak-action)}
.ak-check > input:indeterminate::before{
  transform:scale(1);clip-path:none;inline-size:10px;block-size:2px}
.ak-check > input:hover:not(:disabled),.ak-radio > input:hover:not(:disabled){
  border-color:var(--ak-action)}
.ak-check > input:focus-visible,.ak-radio > input:focus-visible{
  outline:var(--ak-focus-w) solid var(--ak-focus);outline-offset:2px}
.ak-check > input:disabled,.ak-radio > input:disabled{
  border-color:var(--ak-line);background:var(--ak-sunk);cursor:not-allowed}
.ak-check:has(> input:disabled),.ak-radio:has(> input:disabled){
  color:var(--ak-ink-muted);cursor:not-allowed}
.ak-checkgroup{display:flex;flex-direction:column;gap:var(--ak-gap-inside)}
.ak-checkgroup--inline{flex-direction:row;flex-wrap:wrap;gap:var(--ak-gap-between)}

/* ---- 13.3 Switch --------------------------------------------------
   A switch is for a setting that takes effect immediately. A checkbox
   is for something that takes effect when the form is saved. If the
   control sits in a form with a Save button, it is a checkbox. */
.ak-switch{display:inline-flex;align-items:center;gap:var(--ak-gap-inside);
  cursor:pointer;min-height:var(--ak-target-min)}
/* Under a finger the whole label is a 44px target. Said again here
   because this rule, later in the same layer, undid the touch rule in
   12.x and left the switch 24px tall (v2.4.0). */
@media (pointer:coarse){.ak-switch{min-height:var(--ak-target-touch)}}
.ak-switch > input{
  appearance:none;margin:0;flex:0 0 auto;inline-size:38px;block-size:22px;
  border-radius:var(--ak-r-pill);background:var(--ak-n-300);
  border:0;position:relative;cursor:pointer;
  transition:background var(--ak-dur-fast) var(--ak-ease-out)}
.ak-switch > input::before{
  content:"";position:absolute;inset-block-start:3px;inset-inline-start:3px;
  inline-size:16px;block-size:16px;border-radius:50%;background:#FFF;
  transition:transform var(--ak-dur-fast) var(--ak-ease-out)}
.ak-switch > input:checked{background:var(--ak-complete)}
.ak-switch > input:checked::before{transform:translateX(16px)}
.ak-switch > input:focus-visible{outline:var(--ak-focus-w) solid var(--ak-focus);outline-offset:2px}
.ak-switch > input:disabled{background:var(--ak-line);cursor:not-allowed}
/* The state is in the label too, never in the colour alone. */
.ak-switch__state{font-size:var(--ak-fs-small);color:var(--ak-ink-muted);
  font-variant-numeric:tabular-nums}

/* ---- 13.4 Select ---------------------------------------------------
   Native select, styled to match the input. The native control gives
   the phone its own picker, keyboard type-ahead and screen-reader
   behaviour for free — all of which a custom listbox has to rebuild
   and usually rebuilds badly. */
.ak-select{
  inline-size:100%;min-height:var(--ak-control-h);
  padding-inline:var(--ak-s-3);padding-block:0;
  padding-inline-end:var(--ak-s-8);
  border:var(--ak-border) solid var(--ak-line-control);
  border-radius:var(--ak-r-sm);background:var(--ak-surface);
  color:var(--ak-ink);font:inherit;font-size:var(--ak-fs-base);
  appearance:none;cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),
                   linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-position:calc(100% - 18px) calc(50% + 1px),calc(100% - 13px) calc(50% + 1px);
  background-size:5px 5px,5px 5px;background-repeat:no-repeat;
}
.ak-select:hover:not(:disabled){border-color:var(--ak-line-control-hover)}
.ak-select:focus-visible{outline:var(--ak-focus-w) solid var(--ak-focus);outline-offset:1px}
.ak-select:disabled{background:var(--ak-sunk);color:var(--ak-ink-muted);cursor:not-allowed}

/* ---- 13.5 Number stepper ------------------------------------------- */
.ak-stepper{display:inline-flex;align-items:stretch;
  border:var(--ak-border) solid var(--ak-line-control);border-radius:var(--ak-r-sm);
  overflow:hidden;background:var(--ak-surface)}
.ak-stepper > button{
  appearance:none;border:0;background:var(--ak-sunk);color:var(--ak-ink);
  inline-size:var(--ak-control-h);min-height:var(--ak-control-h);
  cursor:pointer;font-size:16px;line-height:1}
.ak-stepper > button:hover:not(:disabled){background:var(--ak-n-200)}
.ak-stepper > button:disabled{color:var(--ak-ink-muted);cursor:not-allowed}
.ak-stepper > input{
  border:0;inline-size:7ch;text-align:center;background:transparent;
  font-family:var(--ak-font-mono);font-variant-numeric:tabular-nums;
  color:var(--ak-ink);font-size:var(--ak-fs-base);min-height:var(--ak-control-h)}
.ak-stepper > input:focus-visible{outline:var(--ak-focus-w) solid var(--ak-focus);
  outline-offset:-2px}

/* ---- 13.6 File upload ---------------------------------------------
   A drop target that is also a button, because dropping is not
   available to a keyboard and must never be the only route. */
.ak-drop{
  display:flex;flex-direction:column;align-items:center;gap:var(--ak-gap-inside);
  padding:var(--ak-s-6);text-align:center;
  border:2px dashed var(--ak-line-strong);border-radius:var(--ak-r-md);
  background:var(--ak-surface-2);color:var(--ak-ink-2);font-size:var(--ak-fs-small)}
.ak-drop[data-over="true"]{border-color:var(--ak-action);background:var(--ak-action-bg)}
.ak-drop__rules{color:var(--ak-ink-muted);font-size:var(--ak-fs-tiny)}
.ak-fileitem{display:flex;align-items:center;gap:var(--ak-gap-inside);
  padding:var(--ak-s-2) var(--ak-s-3);border:var(--ak-border) solid var(--ak-line);
  border-radius:var(--ak-r-sm);background:var(--ak-surface);font-size:var(--ak-fs-small)}
.ak-fileitem__name{font-weight:var(--ak-fw-medium);min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.ak-fileitem__meta{margin-inline-start:auto;color:var(--ak-ink-muted);
  font-family:var(--ak-font-mono);font-size:var(--ak-fs-tiny);white-space:nowrap}

/* ---- 13.7 Read-only display field -----------------------------------
   Not a disabled input. A disabled input says "you could change this
   but not now"; a read-only field says "this is a fact". They must not
   look the same, and today they usually do. */
.ak-readonly{display:flex;flex-direction:column;gap:2px}
.ak-readonly > .ak-label{color:var(--ak-ink-muted)}
.ak-readonly > .ak-readonly__v{font-weight:var(--ak-fw-medium);
  min-height:var(--ak-control-h);display:flex;align-items:center;
  border-bottom:var(--ak-border) solid var(--ak-line)}

/* ---- 13.8 Progress --------------------------------------------------
   Determinate only. An indeterminate bar that runs for forty seconds
   tells a person nothing except that something might be happening. */
.ak-progress{inline-size:100%;block-size:6px;border-radius:var(--ak-r-pill);
  background:var(--ak-sunk);overflow:hidden}
.ak-progress > span{display:block;block-size:100%;background:var(--ak-action);
  border-radius:inherit;transition:inline-size var(--ak-dur-base) var(--ak-ease-out)}
.ak-progress[data-state="failed"] > span{background:var(--ak-failed)}
.ak-progress[data-state="complete"] > span{background:var(--ak-complete)}
/* 2.2.1: the same bar as a native <progress>, so its value is a property
   a screen reader announces, not a width written into a style. */
progress.ak-progress{appearance:none;-webkit-appearance:none;display:block;border:0;
  color:var(--ak-action);background:var(--ak-sunk)}
progress.ak-progress::-webkit-progress-bar{background:var(--ak-sunk);border-radius:var(--ak-r-pill)}
progress.ak-progress::-webkit-progress-value{background:var(--ak-action);border-radius:var(--ak-r-pill)}
progress.ak-progress::-moz-progress-bar{background:var(--ak-action);border-radius:var(--ak-r-pill)}
progress.ak-progress[data-state="complete"]::-webkit-progress-value{background:var(--ak-complete)}
progress.ak-progress[data-state="complete"]::-moz-progress-bar{background:var(--ak-complete)}

/* ---- 13.9 Picked value (2.9.0) ----------------------------------------
   One value chosen from a search (a vendor, a customer, an item), kept in
   the box where it was searched for, with a button that takes it back
   out. The box is exactly a control's height: picking swaps the search
   input for the box in the same place, and removing swaps it back, so
   nothing below moves. The remove button names what it removes, and
   focus goes back to the search when it is pressed. Not a status chip:
   a chip (4.7) is a state and never has a remove. */
.ak-tokenbox{display:flex;align-items:center;gap:var(--ak-gap-inside);
  inline-size:100%;min-block-size:var(--ak-control-h);min-inline-size:0;
  padding:0 var(--ak-s-1);
  background:var(--ak-surface);
  border:var(--ak-border) solid var(--ak-line-control);border-radius:var(--ak-r-sm)}
.ak-token{display:inline-flex;align-items:center;gap:var(--ak-s-1);
  min-inline-size:0;max-inline-size:100%;
  padding-inline:var(--ak-s-2) 0;border-radius:var(--ak-r-xs);
  background:var(--ak-sunk);color:var(--ak-ink);
  font-size:var(--ak-fs-base);font-weight:var(--ak-fw-medium)}
.ak-token__label{min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ak-token__sub{font-family:var(--ak-font-mono);font-size:var(--ak-fs-small);
  font-weight:var(--ak-fw-regular);color:var(--ak-ink-muted);white-space:nowrap}
.ak-token__x{flex:0 0 auto;display:inline-grid;place-items:center;
  inline-size:calc(var(--ak-control-h) - var(--ak-s-2));
  block-size:calc(var(--ak-control-h) - var(--ak-s-2));
  padding:0;border:0;border-radius:var(--ak-r-xs);
  background:none;color:var(--ak-ink-2);font:inherit;line-height:1;cursor:pointer}
.ak-token__x:hover{background:var(--ak-line);color:var(--ak-ink)}
@media (pointer:coarse){
  .ak-token__x{inline-size:var(--ak-target-touch);block-size:var(--ak-target-touch)}
}
@media (forced-colors:active){
  .ak-tokenbox,.ak-token{border:1px solid CanvasText}
}

/* ---- 13.10 A field with a button inside (2.23.0) ----------------------
   One button at the field's end edge that acts on the field itself: show
   or hide a password. The button is an ordinary ghost icon button with
   its own name (aria-label) and, for a toggle, aria-pressed with two icons,
   __off and __on, so the state shows in the shape, not only the fill. */
.ak-input-action{position:relative;display:block;min-inline-size:0}
.ak-input-action > .ak-input{padding-inline-end:calc(var(--ak-control-h) + var(--ak-s-1))}
.ak-input-action > .ak-btn{position:absolute;inset-block:0;inset-inline-end:0;
  block-size:auto;min-block-size:0;border-start-start-radius:0;border-end-start-radius:0}
.ak-input-action > .ak-btn svg{display:block;inline-size:var(--ak-s-5);block-size:var(--ak-s-5)}
/* On, the icon itself changes (the eye is struck through) and the pressed
   fill stays: the pressed tick does not fit a button this small, and the
   changed shape keeps the state readable in greyscale. */
.ak-input-action > .ak-btn[aria-pressed="true"]::before{content:none}
.ak-input-action__on{display:none}
.ak-input-action > .ak-btn[aria-pressed="true"] > .ak-input-action__on{display:block}
.ak-input-action > .ak-btn[aria-pressed="true"] > .ak-input-action__off{display:none}
@media (pointer:coarse){
  .ak-input-action > .ak-input{padding-inline-end:calc(var(--ak-target-touch) + var(--ak-s-1))}
}
}

/* ===================================================================
   14 · STATES — the matrix, declared once
   -------------------------------------------------------------------
   v1 specified hover and focus and almost nothing else. Ten states,
   applied by rule rather than per component, so a disabled button and
   a disabled tab are disabled the same way.

     default · hover · active · focus-visible · disabled · read-only
     loading · error · selected · empty
   =================================================================== */
@layer states {

/* DISABLED — one appearance, everywhere. Note aria-disabled as well as
   :disabled: a control that must stay focusable so a screen reader can
   find it and read WHY it is unavailable uses aria-disabled. */
.ak-btn:disabled,.ak-btn[aria-disabled="true"],
.ak-tab[aria-disabled="true"],.ak-rail__item[aria-disabled="true"],
.ak-select:disabled,.ak-input:disabled,.ak-textarea:disabled{
  opacity:.52;cursor:not-allowed;box-shadow:none}
.ak-btn:disabled:hover,.ak-btn[aria-disabled="true"]:hover{background:inherit;filter:none}
/* A disabled control must still say why. The rule is a markup rule and
   it is enforced in review, not in CSS: every disabled control carries
   a title or an adjacent note. CSS can only mark the ones that do not. */
.ak-btn:disabled:not([title]):not([aria-describedby]){outline:0}

/* READ-ONLY — a fact, not a withheld affordance. Flat, no border
   emphasis, full-strength ink. Deliberately unlike disabled. */
.ak-input[readonly],.ak-textarea[readonly]{
  background:var(--ak-sunk);border-color:transparent;color:var(--ak-ink);cursor:default}
.ak-input[readonly]:focus-visible{outline:var(--ak-focus-w) solid var(--ak-focus)}

/* LOADING — the element keeps its size so nothing jumps when the data
   lands. Layout shift during loading is the commonest cause of a
   mis-click in an ERP. */
[data-loading="true"]{position:relative;pointer-events:none}
[data-loading="true"] > *{opacity:.38}
[data-loading="true"]::after{
  content:"";position:absolute;inset-block-start:0;inset-inline:0;block-size:2px;
  background:linear-gradient(90deg,transparent,var(--ak-action),transparent);
  animation:ak-indet 1.1s linear infinite}
@keyframes ak-indet{from{transform:translateX(-100%)}to{transform:translateX(100%)}}
@media (prefers-reduced-motion:reduce){
  [data-loading="true"]::after{animation:none;background:var(--ak-action);opacity:.5}}

/* ERROR — on the control, and never only in colour. */
.ak-input[aria-invalid="true"],.ak-textarea[aria-invalid="true"],
.ak-select[aria-invalid="true"]{
  border-color:var(--ak-failed);
  box-shadow:inset 0 0 0 1px var(--ak-failed)}

/* SELECTED — distinct from hover and from the row's own state rule,
   which already owns the left edge. Selection uses a fill; state uses
   the edge; hover uses a lighter fill. Three signals, three places. */
.ak-table tbody tr[aria-selected="true"],
.ak-table tbody tr:has(.ak-check > input:checked){
  background:var(--ak-action-bg)}
.ak-tab[aria-selected="true"]{font-weight:var(--ak-fw-semibold)}

/* EMPTY — a value that is absent is written, never left blank, so a
   reader can tell "nothing" from "not loaded". */
.ak-none::after{content:"\2014";color:var(--ak-ink-muted)}
}

/* ===================================================================
   15 · TABLE PATTERNS — what a 2,422-row register needs
   =================================================================== */
@layer components {

/* ---- 15.1 Selection and the bulk bar -------------------------------
   The bulk bar REPLACES the table head rather than appearing above it,
   so the table does not jump down when a row is ticked. It states the
   count, because "apply to all" with an unstated count is how people
   update four hundred rows by accident. */
.ak-table th.ak-col-select,.ak-table td.ak-col-select{
  inline-size:40px;padding-inline:var(--ak-s-3)}
.ak-bulkbar{
  display:flex;align-items:center;gap:var(--ak-gap-between);flex-wrap:wrap;
  padding:var(--ak-s-2) var(--ak-row-pad-x);
  background:var(--ak-action-bg);border-bottom:var(--ak-border) solid var(--ak-line-strong);
  font-size:var(--ak-fs-small);min-height:var(--ak-row-h)}
.ak-bulkbar__count{font-weight:var(--ak-fw-semibold);font-variant-numeric:tabular-nums}
.ak-bulkbar__actions{margin-inline-start:auto;display:flex;gap:var(--ak-s-2);flex-wrap:wrap}

/* ---- 15.2 Totals row ------------------------------------------------
   A totals row is part of the table, not a paragraph under it, and it
   must say what it totals — the page, or everything. */
.ak-table tfoot td{
  position:sticky;bottom:0;background:var(--ak-sunk);
  border-top:2px solid var(--ak-line-strong);
  font-weight:var(--ak-fw-semibold);padding:var(--ak-row-pad-y) var(--ak-row-pad-x)}
.ak-table tfoot .ak-td-num{font-variant-numeric:tabular-nums}
.ak-total-scope{font-weight:var(--ak-fw-regular);color:var(--ak-ink-muted);
  font-size:var(--ak-fs-tiny)}

/* ---- 15.3 Pagination ------------------------------------------------ */
.ak-pager{display:flex;align-items:center;gap:var(--ak-s-2);flex-wrap:wrap}
.ak-pager__range{font-size:var(--ak-fs-small);color:var(--ak-ink-muted);
  font-variant-numeric:tabular-nums}
.ak-pager button{min-inline-size:var(--ak-target-min)}
.ak-pager__page{font-family:var(--ak-font-mono);font-variant-numeric:tabular-nums;
  font-size:var(--ak-fs-small);padding-inline:var(--ak-s-2)}

/* ---- 15.4 Frozen first column --------------------------------------- */
.ak-table--stickycol thead th:first-child,
.ak-table--stickycol tbody td:first-child{
  position:sticky;inset-inline-start:0;background:var(--ak-surface);z-index:1}
.ak-table--stickycol thead th:first-child{background:var(--ak-sunk);z-index:2}
.ak-tablescroll[data-scrolled-x="true"] .ak-table--stickycol td:first-child,
.ak-tablescroll[data-scrolled-x="true"] .ak-table--stickycol th:first-child{
  box-shadow:2px 0 0 0 color-mix(in srgb,var(--ak-ink) 10%,transparent)}

/* ---- 15.5 The table on a phone --------------------------------------
   Two answers, and which one is right depends on the job:

   A REGISTER scrolls sideways with its first column frozen. Somebody
   comparing two hundred rows needs them to stay rows.

   A DETAIL LIST transposes to cards, one record per card, label beside
   value. Somebody reading one record at a time does not need a grid.

   Choosing per table is the point. A system that transposes everything
   makes registers unusable; one that scrolls everything makes detail
   lists unreadable.

   A card is still a table. Measured 12 Oct 2026 (2.15.3) at 320px:
   with the boxes below set to display:block, Chromium's tree still
   reports table, caption, rowgroup, row, columnheader and cell for
   .ak-table--cards (the design book and Kartavya). So nothing is added
   here; the caption, th[scope] and each cell's data-label stay. */
@media (max-width:767px){
  .ak-table--cards,.ak-table--cards thead,.ak-table--cards tbody,
  .ak-table--cards tr,.ak-table--cards td{display:block}
  .ak-table--cards .ak-td-main--lead > b{white-space:normal}
  .ak-table--cards thead{position:absolute;inline-size:1px;block-size:1px;
    overflow:hidden;clip-path:inset(50%)}
  .ak-table--cards tr{
    border:var(--ak-border) solid var(--ak-line);border-radius:var(--ak-r-md);
    background:var(--ak-surface);padding:var(--ak-s-3);
    margin-block-end:var(--ak-gap-between)}
  .ak-table--cards tr[data-state]{border-inline-start:3px solid var(--ak-neutral)}
  .ak-table--cards tr[data-state="failed"]{border-inline-start-color:var(--ak-failed)}
  .ak-table--cards tr[data-state="warning"]{border-inline-start-color:var(--ak-warning)}
  .ak-table--cards tr[data-state="approval"]{border-inline-start-color:var(--ak-approval)}
  .ak-table--cards tr[data-state="complete"]{border-inline-start-color:var(--ak-complete)}
  .ak-table--cards tr[data-state="information"]{border-inline-start-color:var(--ak-info)}
  .ak-table--cards td{
    display:grid;grid-template-columns:minmax(0,9rem) minmax(0,1fr);
    gap:var(--ak-s-2);padding:var(--ak-s-1) 0;border:0;
    min-height:0;text-align:start}
  /* A row's fixed height belongs to the grid, not the card: as specific
     as `.ak-table tbody td` (which sets it) and later, so a value that
     wraps grows its card instead of running over the next field. */
  .ak-table--cards tbody td{height:auto}
}
/* Every card names its values, at every width below 768px (2.12.1). The
   header text comes from the cell, so there is one source of truth for a
   column name instead of two that drift apart. 2.2.2 put these rules
   inside the 374px block below, so from 375 to 767px, most phones, a
   card showed its values with no names beside them. */
@media (max-width:767px){
  .ak-table--cards td::before{
    content:attr(data-label);color:var(--ak-ink-muted);
    font-size:var(--ak-fs-small);font-weight:var(--ak-fw-medium)}
  .ak-table--cards td.ak-td-num{text-align:start}
  .ak-table--cards td.ak-td-actions{justify-content:start;
    grid-template-columns:minmax(0,1fr);padding-top:var(--ak-s-2)}
  .ak-table--cards td.ak-td-actions::before{content:none}
  .ak-table--cards td.ak-td-actions > * + *{margin-left:0}
  .ak-table--cards tfoot td{grid-template-columns:minmax(0,1fr)}
}
/* At the narrowest (320px is the reflow target) a 9rem label column
   leaves a value too little room: a chip or a button was cut off. The
   label goes above its value instead. */
@media (max-width:374px){
  .ak-table--cards td{grid-template-columns:minmax(0,1fr);gap:0}
  .ak-table--cards td.ak-td-actions{gap:var(--ak-s-2)}
}
}

/* ===================================================================
   16 · CHARTS
   -------------------------------------------------------------------
   The five status hues are reserved for meaning and may NEVER be
   reused as series colours. So the series palette is its own family,
   validated independently for both themes against lightness band,
   chroma floor, adjacent-pair separation under protanopia,
   deuteranopia and tritanopia, normal-vision separation, and contrast
   against the surface. All five checks pass in both themes.

   THERE ARE FIVE SERIES AND NO SIXTH. A sixth generated hue is never
   the answer: fold the tail into "Other", facet into small multiples,
   or ask a different question. A chart that needs nine colours is a
   table.

   Every chart carries direct labels and a table view. Colour is never
   the only way to tell two series apart.
   =================================================================== */
@layer tokens {
:root,:host{
  --ak-series-1:#1E66B0;
  --ak-series-2:#B8791F;
  --ak-series-3:#0E7F5C;
  --ak-series-4:#8F5BC4;
  --ak-series-5:#A8392A;
  --ak-chart-grid:var(--ak-n-200);
  --ak-chart-axis:var(--ak-n-400);
  --ak-chart-ink:var(--ak-ink-2);
}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]),:host(:not([data-theme="light"])){
  --ak-series-1:#4A8FD6;
  --ak-series-2:#B98629;
  --ak-series-3:#2A9871;
  --ak-series-4:#9A72D2;
  --ak-series-5:#CC5F4C;
  --ak-chart-grid:var(--ak-n-200);
  --ak-chart-axis:var(--ak-n-400);
}}
:root[data-theme="dark"],:host([data-theme="dark"]){
  --ak-series-1:#4A8FD6;
  --ak-series-2:#B98629;
  --ak-series-3:#2A9871;
  --ak-series-4:#9A72D2;
  --ak-series-5:#CC5F4C;
}
}
@layer components {
.ak-chart{display:flex;flex-direction:column;gap:var(--ak-gap-inside);min-width:0}
.ak-chart__head{display:flex;align-items:baseline;gap:var(--ak-gap-between);flex-wrap:wrap}
.ak-chart__title{font-size:var(--ak-fs-h4);font-weight:var(--ak-fw-semibold)}
.ak-chart__unit{font-size:var(--ak-fs-tiny);color:var(--ak-ink-muted);
  text-transform:uppercase;letter-spacing:var(--ak-ls-caps)}
.ak-chart__plot{min-width:0;overflow-x:auto;overscroll-behavior-x:contain}
.ak-chart svg{max-inline-size:100%;block-size:auto;color:var(--ak-chart-ink)}
.ak-chart text{font-family:var(--ak-font-ui);font-size:var(--ak-fs-tiny);fill:var(--ak-chart-ink)}
.ak-chart .ak-axis{stroke:var(--ak-chart-axis);stroke-width:1}
.ak-chart .ak-grid{stroke:var(--ak-chart-grid);stroke-width:1}
.ak-chart .ak-val{font-family:var(--ak-font-mono);font-variant-numeric:tabular-nums}
.ak-s1{fill:var(--ak-series-1);stroke:var(--ak-series-1)}
.ak-s2{fill:var(--ak-series-2);stroke:var(--ak-series-2)}
.ak-s3{fill:var(--ak-series-3);stroke:var(--ak-series-3)}
.ak-s4{fill:var(--ak-series-4);stroke:var(--ak-series-4)}
.ak-s5{fill:var(--ak-series-5);stroke:var(--ak-series-5)}
/* A legend is present whenever there are two or more series, and the
   swatch never carries the meaning alone — the name sits beside it. */
.ak-legend{display:flex;flex-wrap:wrap;gap:var(--ak-gap-between);
  font-size:var(--ak-fs-small)}
.ak-legend > span{display:inline-flex;align-items:center;gap:6px;color:var(--ak-ink-2)}
.ak-legend i{inline-size:11px;block-size:11px;border-radius:2px;display:inline-block}
.ak-nodata{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:var(--ak-gap-inside);min-block-size:140px;border:var(--ak-border) dashed var(--ak-line);
  border-radius:var(--ak-r-md);color:var(--ak-ink-muted);font-size:var(--ak-fs-small);
  text-align:center;padding:var(--ak-s-4)}
}

/* ===================================================================
   17 · FORMAT — how a number, a date and an amount are written
   -------------------------------------------------------------------
   This is a contract, not a style. Two screens that format the same
   amount differently are two screens that will be reconciled by hand.

     MONEY     Indian grouping, two decimals, always.
               18,42,500.00 — never 1,842,500.00, never 18.42L on a
               register. The symbol sits in the column header, not in
               every cell; a single figure outside a column carries it.
     NEGATIVE  A leading minus and the failed ink. Never brackets —
               brackets read as a footnote at 13px — and never colour
               alone, because the minus has to survive greyscale.
     QUANTITY  Three decimals. 12,400.000.
     RATE      Two decimals, per the unit named in the header.
     PERCENT   One decimal and the sign. 82.0%
     COUNT     No decimals, grouped. 2,422
     DATE      On screen: 02 Oct 2026. In an audit trail or an export:
               2026-10-02. The audit form sorts and never ambiguates;
               the screen form is read by a person. Both, deliberately.
     TIME      24-hour, with the date, only where the time matters.
     FY        2026-27
     NUMBERING AEC/OR/2627/0015 and NE/223/26-27 are not strings to
               re-format. They are rendered monospaced, never wrapped.

   The classes below are the enforcement: a figure that is not in one
   of them is a figure somebody formatted by hand.
   =================================================================== */
@layer utilities {
.ak-amt,.ak-qty,.ak-rate,.ak-pct,.ak-count{
  font-family:var(--ak-font-mono);font-variant-numeric:tabular-nums;
  white-space:nowrap}
.ak-neg{color:var(--ak-failed)}
.ak-neg::before{content:"\2212"}          /* true minus, not a hyphen  */
.ak-cr::after{content:" Cr";font-size:var(--ak-fs-tiny);color:var(--ak-ink-muted)}
.ak-date{font-variant-numeric:tabular-nums;white-space:nowrap}
.ak-date--sort{font-family:var(--ak-font-mono)}
.ak-ref{font-family:var(--ak-font-mono);white-space:nowrap;
  font-size:max(var(--ak-fs-micro),.94em);letter-spacing:-.01em}
/* 2.20.2: a code asked to break (.ak-ref.ak-break) wraps. .ak-break is in layout, so the nowrap above (utilities)
   beat it whatever the selector; the override lives here, in the layer of the rule it overrides (section 1, rule 6). */
.ak-ref.ak-break{white-space:normal}
}

/* ===================================================================
   18 · THE FRAME, THE HOME AND THE SIGN-IN (2.2.0)
   -------------------------------------------------------------------
   Owner's brief, 2 Oct 2026: one header on every page holding Back,
   Home, the module's name, the greeting with the person's role and
   company scope, and Sign out. A compact side menu. Small home tiles a
   person can put in their own order. A sign-in page that looks like
   the group's own.

   .ak-brandmark   the monogram and wordmark, on the chrome
   .ak-who         the greeting and role badge; opens .ak-menu
   .ak-rolebadge   role and company scope, pale gold on the chrome
   .ak-menu        a disclosure panel under a masthead button
   .ak-tiles       a grid of .ak-tile, arrangeable in place
   .ak-auth        the sign-in layout: a brand panel and a form panel
   =================================================================== */
@layer base {
/* A light panel inside the navy masthead gets the light ring back. */
.ak-masthead .ak-menu :where(a,button,input,select,[tabindex]):focus-visible{
  outline-color:var(--ak-action);
  box-shadow:0 0 0 4px color-mix(in srgb,var(--ak-action) 22%,transparent);
}
}

@layer components {
/* ---- 18.1 Controls on the chrome -----------------------------------
   The masthead is navy, so a ghost or secondary button inside it reads
   in the chrome's ink, and a chip or field sits on the chrome's wash. */
.ak-masthead .ak-btn--ghost{color:var(--ak-chrome-ink)}
.ak-masthead .ak-btn--ghost:hover{background:var(--ak-chrome-hover);color:var(--ak-chrome-ink-strong)}
.ak-masthead .ak-btn--secondary{background:transparent;color:var(--ak-chrome-ink-strong);
  border-color:var(--ak-chrome-line)}
.ak-masthead .ak-btn--secondary:hover{background:var(--ak-chrome-hover)}
.ak-masthead .ak-chip{background:var(--ak-chrome-hover);color:var(--ak-chrome-ink-strong)}
.ak-masthead .ak-muted{color:var(--ak-chrome-ink)}
.ak-masthead > .ak-search .ak-input,.ak-masthead .ak-masthead__right .ak-select{
  background:var(--ak-chrome-field);color:var(--ak-chrome-ink-strong);
  border-color:var(--ak-chrome-line)}
.ak-masthead > .ak-search .ak-input::placeholder{color:var(--ak-chrome-ink)}
.ak-masthead > .ak-search .ak-search__icon{color:var(--ak-chrome-ink)}
.ak-masthead option{background:var(--ak-surface);color:var(--ak-ink)}
.ak-masthead .ak-menu .ak-select{background:var(--ak-surface);color:var(--ak-ink);
  border-color:var(--ak-line-control)}
.ak-masthead > .ak-search{flex:0 1 18rem;min-width:0}

/* ---- 18.2 Brand mark ----------------------------------------------- */
.ak-brandmark{display:inline-flex;align-items:center;gap:var(--ak-s-2);
  color:var(--ak-chrome-ink-strong);text-decoration:none;flex:0 0 auto}
.ak-brandmark__logo{inline-size:var(--ak-s-7);block-size:var(--ak-s-7);
  display:grid;place-items:center;border-radius:var(--ak-r-sm);
  background:var(--ak-accent);color:var(--ak-brand-900);
  font-weight:var(--ak-fw-bold);font-size:var(--ak-fs-h4);line-height:1}
.ak-brandmark__text{display:flex;flex-direction:column;line-height:var(--ak-lh-tight)}
.ak-brandmark__name{font-weight:var(--ak-fw-bold);font-size:var(--ak-fs-base);
  letter-spacing:var(--ak-ls-tight)}
.ak-brandmark__sub{font-size:var(--ak-fs-micro);text-transform:uppercase;
  letter-spacing:var(--ak-ls-caps);color:var(--ak-accent);font-weight:var(--ak-fw-semibold)}

/* ---- 18.3 Who is signed in -----------------------------------------
   One button: the greeting over a role badge. It opens the person's
   own menu. Below 900px it folds to the initials alone. */
.ak-who{display:inline-flex;align-items:center;gap:var(--ak-s-2);
  background:none;border:var(--ak-border) solid transparent;border-radius:var(--ak-r-md);
  padding:var(--ak-s-1) var(--ak-s-2);cursor:pointer;font:inherit;color:inherit;
  text-align:right;min-height:var(--ak-target-min)}
.ak-who:hover{background:var(--ak-chrome-hover)}
.ak-who__text{display:flex;flex-direction:column;align-items:flex-end;gap:2px;min-width:0}
.ak-who__hello{font-size:var(--ak-fs-small);color:var(--ak-chrome-ink-strong);
  font-weight:var(--ak-fw-medium);white-space:nowrap}
.ak-who__initials{inline-size:var(--ak-s-7);block-size:var(--ak-s-7);border-radius:50%;
  display:grid;place-items:center;flex:0 0 auto;
  background:var(--ak-accent-soft);color:var(--ak-accent-ink);
  font-size:var(--ak-fs-small);font-weight:var(--ak-fw-bold)}
.ak-rolebadge{display:inline-flex;align-items:center;white-space:nowrap;
  font-size:var(--ak-fs-micro);font-weight:var(--ak-fw-semibold);
  text-transform:uppercase;letter-spacing:var(--ak-ls-wide);
  padding:1px var(--ak-s-2);border-radius:var(--ak-r-pill);
  background:var(--ak-accent-soft);color:var(--ak-accent-ink)}
@media (max-width:900px){
  .ak-who__text{display:none}
}

/* ---- 18.4 Menu ------------------------------------------------------
   A disclosure, not an ARIA menu: a button with aria-expanded and a
   panel of ordinary links, buttons and fields, tabbed through in order.
   Escape or a click elsewhere closes it and focus returns to the button. */
.ak-menuwrap{position:relative;display:inline-flex}
.ak-menu{position:absolute;inset-block-start:calc(100% + var(--ak-s-2));inset-inline-end:0;
  inline-size:min(20rem,calc(100vw - var(--ak-s-5)));
  background:var(--ak-surface);color:var(--ak-ink);
  border:var(--ak-border) solid var(--ak-line);border-radius:var(--ak-r-md);
  box-shadow:var(--ak-shadow-overlay);z-index:var(--ak-z-dropdown);
  display:flex;flex-direction:column;gap:var(--ak-gap-inside);padding:var(--ak-s-3)}
.ak-menu__head{display:flex;flex-direction:column;gap:2px;
  padding-bottom:var(--ak-s-2);border-bottom:var(--ak-border) solid var(--ak-line)}
.ak-menu__head b{font-size:var(--ak-fs-base)}
.ak-menu__head span{font-size:var(--ak-fs-small);color:var(--ak-ink-muted);overflow-wrap:anywhere}
.ak-menu__item{display:flex;align-items:center;gap:var(--ak-s-2);width:100%;
  padding:var(--ak-s-2);border-radius:var(--ak-r-sm);background:none;border:0;
  font:inherit;font-size:var(--ak-fs-base);color:var(--ak-ink);text-align:left;
  text-decoration:none;cursor:pointer;min-height:var(--ak-target-min)}
.ak-menu__item:hover{background:var(--ak-sunk)}
@media (pointer:coarse){.ak-menu__item,.ak-who,.ak-masthead .ak-brandmark{min-height:var(--ak-target-touch)}
  .ak-masthead__nav .ak-btn{min-width:var(--ak-target-touch)}}

/* ---- 18.5 Rail, folded to icons ------------------------------------
   data-rail="collapsed" on .ak-app keeps each item's icon and moves
   its name to the screen-reader layer, so the rail stays a list of
   named links. Group labels and counts are dropped while folded. A
   group the person folded (.ak-rail__list[hidden]) stays folded: no
   rule here can show it, since base's [hidden]{display:none!important}
   wins every later layer's !important (2.15.3 removed one that tried). */
.ak-app[data-rail="collapsed"] .ak-rail__label{position:absolute;width:1px;height:1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.ak-app[data-rail="collapsed"] .ak-rail__group,
.ak-app[data-rail="collapsed"] .ak-rail__count{display:none}
.ak-app[data-rail="collapsed"] .ak-rail__item{justify-content:center;padding-inline:0}
.ak-rail__foot .ak-rail__item{color:var(--ak-chrome-ink);font-size:var(--ak-fs-small)}

/* ---- 18.6 Tiles -----------------------------------------------------
   A tile is a door: a name and one line, the whole tile one link. The
   arrangement belongs to the person: in data-editing mode each tile
   shows a handle, earlier and later buttons and a hide switch, can be
   dragged, and its link stops covering the tile. */
.ak-tiles{display:grid;gap:var(--ak-s-3);
  grid-template-columns:repeat(auto-fill,minmax(min(13rem,100%),1fr))}
.ak-tile{position:relative;display:flex;flex-direction:column;gap:var(--ak-s-1);
  min-width:0;padding:var(--ak-s-3) var(--ak-s-4);
  background:var(--ak-surface);border:var(--ak-border) solid var(--ak-line);
  border-radius:var(--ak-r-md);box-shadow:var(--ak-shadow-raised);
  transition:border-color var(--ak-dur-fast) var(--ak-ease-out),
             box-shadow var(--ak-dur-fast) var(--ak-ease-out)}
.ak-tile::before{content:"";position:absolute;inset-block:var(--ak-s-3);inset-inline-start:0;
  inline-size:3px;border-radius:0 var(--ak-r-xs) var(--ak-r-xs) 0;
  background:var(--ak-accent);opacity:0;transition:opacity var(--ak-dur-fast) var(--ak-ease-out)}
.ak-tile:hover{border-color:var(--ak-line-strong);box-shadow:var(--ak-shadow-overlay)}
.ak-tile:hover::before,.ak-tile:focus-within::before{opacity:1}
.ak-tile__eyebrow{font-size:var(--ak-fs-micro);text-transform:uppercase;
  letter-spacing:var(--ak-ls-caps);font-weight:var(--ak-fw-semibold);color:var(--ak-ink-muted)}
.ak-tile__name{font-size:var(--ak-fs-base);font-weight:var(--ak-fw-semibold);
  color:var(--ak-ink);text-decoration:none;line-height:var(--ak-lh-snug)}
.ak-tile__name::after{content:"";position:absolute;inset:0;border-radius:var(--ak-r-md)}
.ak-tile__name:focus-visible{outline:0;box-shadow:none}
.ak-tile:has(.ak-tile__name:focus-visible){outline:2px solid var(--ak-action);outline-offset:2px}
.ak-tile__blurb{font-size:var(--ak-fs-small);color:var(--ak-ink-2);margin:0;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.ak-tile__tools{display:none;align-items:center;gap:var(--ak-s-1);margin-top:var(--ak-s-1)}
.ak-tile__handle{cursor:grab;color:var(--ak-ink-muted);padding-inline:var(--ak-s-1);
  font-size:var(--ak-fs-h4);line-height:1;user-select:none}
.ak-tiles[data-editing] .ak-tile{border-style:dashed;border-color:var(--ak-line-strong);cursor:grab}
.ak-tiles[data-editing] .ak-tile__tools{display:flex}
.ak-tiles[data-editing] .ak-tile__name::after{display:none}
.ak-tiles[data-editing] .ak-tile[data-off]{background:var(--ak-sunk);box-shadow:none}
.ak-tiles[data-editing] .ak-tile[data-off] .ak-tile__name,
.ak-tiles[data-editing] .ak-tile[data-off] .ak-tile__blurb{color:var(--ak-ink-muted)}
.ak-tile.is-dragging{opacity:.4}
.ak-tile.is-target{outline:2px dashed var(--ak-action);outline-offset:2px}
.ak-tiles:not([data-editing]) .ak-tile[data-off]{display:none}
@media (max-width:479px){.ak-tile__blurb{-webkit-line-clamp:1}}

/* ---- 18.7 Sign-in ---------------------------------------------------
   Two panels side by side from 900px: the group's own navy with the
   mark and what the system is, and the form on paper. Stacked below,
   the brand panel shrinks to a band. */
.ak-auth{min-block-size:100%;display:grid;
  grid-template-columns:minmax(0,5fr) minmax(0,6fr);background:var(--ak-bg)}
.ak-auth__brand{background:var(--ak-chrome);color:var(--ak-chrome-ink);
  display:flex;flex-direction:column;justify-content:space-between;gap:var(--ak-s-7);
  padding:var(--ak-s-9) var(--ak-s-8);position:relative;overflow:hidden}
.ak-auth__brand::after{content:"";position:absolute;inset-inline-end:calc(var(--ak-s-10) * -1);
  inset-block-end:calc(var(--ak-s-10) * -1);inline-size:calc(var(--ak-s-10) * 4);
  block-size:calc(var(--ak-s-10) * 4);border-radius:50%;
  border:var(--ak-s-6) solid var(--ak-chrome-hover);pointer-events:none}
.ak-auth__brand .ak-brandmark__logo{inline-size:var(--ak-s-9);block-size:var(--ak-s-9);
  font-size:var(--ak-fs-h2)}
.ak-auth__brand .ak-brandmark__name{font-size:var(--ak-fs-h3)}
.ak-auth__headline{font-size:var(--ak-fs-kpi);line-height:var(--ak-lh-tight);
  letter-spacing:var(--ak-ls-tight);color:var(--ak-chrome-ink-strong);
  font-weight:var(--ak-fw-semibold);max-inline-size:18ch;margin:0}
.ak-auth__rule{inline-size:var(--ak-s-9);block-size:3px;background:var(--ak-accent);border:0;margin:0}
.ak-auth__lede{font-size:var(--ak-fs-body);max-inline-size:40ch;margin:0;color:var(--ak-chrome-ink)}
.ak-auth__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;
  gap:var(--ak-gap-inside);font-size:var(--ak-fs-small)}
.ak-auth__list li{display:flex;align-items:center;gap:var(--ak-s-2)}
.ak-auth__list li::before{content:"";inline-size:6px;block-size:6px;border-radius:50%;
  background:var(--ak-accent);flex:0 0 auto}
.ak-auth__panel{display:flex;align-items:center;justify-content:center;
  padding:var(--ak-s-9) var(--ak-s-6)}
.ak-auth__card{inline-size:min(26rem,100%);display:flex;flex-direction:column;gap:var(--ak-s-5)}
.ak-auth__card h1{font-size:var(--ak-fs-h1);margin:0}
.ak-auth__card .ak-btn--primary{inline-size:100%;min-height:calc(var(--ak-control-h) + var(--ak-s-2))}
.ak-auth__or{display:flex;align-items:center;gap:var(--ak-s-3);color:var(--ak-ink-muted);
  font-size:var(--ak-fs-small)}
.ak-auth__or::before,.ak-auth__or::after{content:"";flex:1 1 auto;
  border-top:var(--ak-border) solid var(--ak-line)}
.ak-auth__foot{font-size:var(--ak-fs-small);color:var(--ak-ink-muted)}
.ak-linkbtn{background:none;border:0;padding:0;font:inherit;color:var(--ak-action);
  text-decoration:underline;text-underline-offset:2px;cursor:pointer;text-align:start}
.ak-linkbtn:hover{color:var(--ak-action-hover)}
@media (max-width:899px){
  .ak-auth{grid-template-columns:minmax(0,1fr);grid-template-rows:auto 1fr}
  .ak-auth__brand{padding:var(--ak-s-6) var(--ak-s-4);gap:var(--ak-s-4)}
  .ak-auth__brand::after,.ak-auth__list,.ak-auth__lede{display:none}
  .ak-auth__headline{font-size:var(--ak-fs-h2)}
  .ak-auth__panel{align-items:flex-start;padding:var(--ak-s-6) var(--ak-s-4)}
}
/* 2.15.2: paper does not print the navy, so on paper the brand panel is
   ink on white. In this layer, after 18.2, so it beats the brand mark's
   own colours; the page's print rules (section 7) put the rest away. */
@media print{
  .ak-auth__brand,.ak-auth__brand :where(*){background:none;color:var(--ak-ink);
    --ak-chrome-hover:transparent}
}

/* ---- 18.8 The header on a page not yet on the system ---------------
   vendor/globalnav.js renders the masthead in a shadow root at the top of
   such a page, and a slim footer at its end. A link the page kept in its
   old header (an import, a print) is slotted into the masthead. */
.ak-masthead--solo{min-block-size:var(--ak-masthead-h)}
.ak-masthead--solo .ak-masthead__trail{flex:1 1 auto}
/* 2.9.2: below 900px the solo trail truncates first, as 3.1's shedding
   order says. Its flex:1 1 auto above, more specific than 3.1's basis 0,
   let a long module name squeeze the person menu off the screen. */
@media (max-width:900px){
  .ak-masthead--solo .ak-masthead__trail{flex:1 1 0}
}
.ak-masthead ::slotted(a){color:var(--ak-chrome-ink);font-size:var(--ak-fs-small);
  text-decoration:none;padding:var(--ak-s-1) var(--ak-s-2);border-radius:var(--ak-r-sm)}
.ak-masthead ::slotted(a:hover){color:var(--ak-chrome-ink-strong);background:var(--ak-chrome-hover)}
.ak-shellfoot{display:flex;flex-wrap:wrap;align-items:center;gap:var(--ak-gap-between);
  margin-top:var(--ak-s-7);padding:var(--ak-s-4) var(--ak-gutter);
  border-top:var(--ak-border) solid var(--ak-line);background:var(--ak-surface-2);
  font-size:var(--ak-fs-small);color:var(--ak-ink-muted)}
.ak-shellfoot a{color:var(--ak-action)}

/* ---- 18.9 The masthead sheds, in a fixed order ---------------------
   Brand wordmark, then the module's sub-line, then the search. Back,
   Home, the module name, the person and Sign out never go. */
@media (max-width:1180px){
  .ak-masthead > .ak-search{display:none}
}
@media (max-width:900px){
  .ak-masthead .ak-brandmark__text{display:none}
  .ak-masthead__trail > span{display:none}
}
@media (max-width:640px){
  .ak-masthead .ak-btn__text{position:absolute;width:1px;height:1px;overflow:hidden;
    clip:rect(0 0 0 0);white-space:nowrap}
  .ak-masthead__nav{padding-inline:0;border-inline:0}
  /* "All screens" and Sign out are also in the person menu, so the bar
     keeps only what has no other door. */
  .ak-masthead .ak-masthead__wide,.ak-masthead .ak-brandmark{display:none}
  .ak-masthead{gap:var(--ak-s-1);padding-inline:var(--ak-s-2)}
}
}

/* ===================================================================
   19 · THE WORKING HOME (2.6.0)
   -------------------------------------------------------------------
   The owner's home prompt pack, Block 1 (it calls this "section 18"
   and the version 2.1.0; this line was past both). The home page must
   answer "what do I do now", which needs (a) a headline figure per
   office that can be switched between — the measure strip; (b) a queue
   of things wanting a decision, each carrying its own weight — the
   action card; (c) framed, self-contained blocks a person can reorder
   and resize — the widget; (d) a way to reach any of 140 screens
   without a wall of links — the grouped menu; (e) small supporting
   parts: split button, chip group, metric grid, stamp, tier rail,
   greeting band, avatar, a chip that is a button.

   Read against 2.5.0 rather than pasted: the menu (18.4), the rail's
   fold (18.5) and the rail's foot (3.1) already existed, so they are
   extended, not redefined. Responsive rules sit in components, beside
   the rules they change: in the layout layer they lose to the
   component whatever their specificity (section 1, rule 5).
   =================================================================== */
@layer components {

/* ---- 19.1 Measure strip --------------------------------------------
   A row of switchable headline figures. ONE is selected; selecting
   changes what the widgets below show. It is a tablist, not a link row,
   because nothing navigates: div.ak-measures[role=tablist][aria-label]
   > button.ak-measure[role=tab][aria-selected], arrow keys, Home and
   End move and select. A strip that changes nothing is decoration.

   Reading order inside a cell is fixed: WHAT (__cat, the office), then
   the QUALIFIER (__sub, the period or the unit), then the FIGURE
   (__val). The figure is last because it is what the eye returns to.
   The reset is written out rather than all:unset, which would take the
   focus ring with it (the .ak-tab trap, 2.1.1). */
.ak-measures{
  display:flex;gap:0;overflow-x:auto;overscroll-behavior-x:contain;
  scrollbar-width:none;
  border:var(--ak-border) solid var(--ak-line);
  border-radius:var(--ak-r-md);background:var(--ak-surface);
}
.ak-measures::-webkit-scrollbar{display:none}
.ak-measure{
  appearance:none;margin:0;font:inherit;color:inherit;text-align:start;
  background:none;border:0;border-radius:0;cursor:pointer;box-sizing:border-box;
  flex:1 1 0;min-width:var(--ak-measure-min);
  display:flex;flex-direction:column;gap:var(--ak-s-1);
  padding:var(--ak-s-4) var(--ak-s-4) calc(var(--ak-s-4) - 3px);
  border-bottom:3px solid transparent;
  border-right:var(--ak-border) solid var(--ak-line);
  transition:background var(--ak-dur-instant) var(--ak-ease-out);
}
.ak-measure:last-child{border-right:0}
.ak-measure:hover{background:var(--ak-sunk)}
.ak-measure[aria-selected="true"]{
  border-bottom-color:var(--ak-action);background:var(--ak-action-bg)}
/* The strip scrolls, so a ring drawn outside a cell would be clipped:
   it is drawn inside instead. */
.ak-measure:focus-visible{outline-offset:calc(var(--ak-focus-w) * -1);box-shadow:none}
.ak-measure__cat{
  font-size:var(--ak-fs-tiny);font-weight:var(--ak-fw-semibold);
  text-transform:uppercase;letter-spacing:var(--ak-ls-caps);
  color:var(--ak-ink-muted);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;
}
.ak-measure[aria-selected="true"] .ak-measure__cat{color:var(--ak-action)}
.ak-measure__sub{
  font-size:var(--ak-fs-tiny);color:var(--ak-ink-muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.ak-measure__val{
  font-family:var(--ak-font-mono);font-size:var(--ak-fs-h2);
  font-weight:var(--ak-fw-semibold);line-height:1.1;
  font-variant-numeric:tabular-nums;letter-spacing:var(--ak-ls-tight);
  color:var(--ak-ink);
}
/* Semantic colour on the figure, never on the cell: a tinted cell would
   compete with the selected state, which is the only thing the strip is
   for. The word that says why is in __sub. The hue's text ink (--ak-*-ink)
   is used, and a selected cell's figure reads in plain ink: on the
   selected tint the warning hue measured 4.38:1 (light) and the failed
   hue 4.23:1 (dark), under 4.5 for a 21px figure. */
.ak-measure[data-state="failed"]   .ak-measure__val{color:var(--ak-failed-ink)}
.ak-measure[data-state="warning"]  .ak-measure__val{color:var(--ak-warning-ink)}
.ak-measure[data-state="complete"] .ak-measure__val{color:var(--ak-complete-ink)}
.ak-measure[aria-selected="true"]  .ak-measure__val{color:var(--ak-ink)}
.ak-measure__val .ak-unit{font-size:var(--ak-fs-small);font-weight:var(--ak-fw-regular)}
@media (max-width:767px){.ak-measure{min-width:46%}}
@media (max-width:479px){.ak-measure{min-width:62%}}

/* ---- 19.2 Widget -----------------------------------------------------
   A framed block of one subject. It owns its head, its controls, its own
   scroll and its freshness stamp. Four things distinguish it from
   .ak-card: it can be reordered, it can be resized, it states when it
   last read the database, and its body scrolls on its own.
   Markup: div.ak-wgrid > section.ak-widget[data-span] >
     div.ak-widget__head > button.ak-widget__grip, h*.ak-widget__title,
       an optional count chip, span.ak-widget__links > a…, .ak-stamp
       (with a <time datetime>), .ak-menuwrap holding the kebab;
     div.ak-widget__body or .ak-widget__body--flush (a table or a metric
       grid takes the full width), optionally also .ak-widget__scroll
       with .ak-wh-sm/-md/-lg (then tabindex="0", role="region" and an
       aria-label, so a keyboard can scroll it);
     an optional div.ak-widget__foot; span.ak-widget__resize[aria-hidden].
   The grip and the resize handle show only in arrange mode
   (data-arrange="on" on the grid): an affordance always visible is an
   affordance always in the way. Dragging is never the only way: the grip
   moves its block with the arrow keys, and "Change the height" in the
   kebab does what the resize handle does.
   align-items:start, not stretch: a widget is as tall as what it holds;
   stretching it to a taller neighbour buys dead space inside a block. */
.ak-wgrid{
  display:grid;gap:var(--ak-gap-between);
  grid-template-columns:repeat(12,minmax(0,1fr));
  align-items:start;
}
.ak-widget{
  grid-column:span 12;
  display:flex;flex-direction:column;min-width:0;
  background:var(--ak-surface);
  border:var(--ak-border) solid var(--ak-line);
  border-radius:var(--ak-r-md);
  position:relative;
}
.ak-widget[data-span="4"]{grid-column:span 4}
.ak-widget[data-span="5"]{grid-column:span 5}
.ak-widget[data-span="6"]{grid-column:span 6}
.ak-widget[data-span="7"]{grid-column:span 7}
.ak-widget[data-span="8"]{grid-column:span 8}
.ak-widget[data-span="12"]{grid-column:span 12}
.ak-widget__head{
  display:flex;align-items:center;gap:var(--ak-s-2);flex-wrap:wrap;
  padding:var(--ak-s-3) var(--ak-s-4);
  border-bottom:var(--ak-border) solid var(--ak-line);
  flex:0 0 auto;min-width:0;
}
.ak-widget__grip{
  display:none;cursor:grab;color:var(--ak-ink-muted);
  background:none;border:0;padding:0 var(--ak-s-1);font:inherit;line-height:1;
  flex:0 0 auto;align-items:center;justify-content:center;
  min-inline-size:var(--ak-target-min);min-block-size:var(--ak-target-min);
}
.ak-widget__title{
  margin:0;font-size:var(--ak-fs-h4);font-weight:var(--ak-fw-semibold);
  color:var(--ak-ink);min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
/* The head wraps at any width: when the title, its chip and the links do
   not fit, the links take a second line at the end rather than squeeze
   the title to a letter (a span-6 block at 1280px did). */
.ak-widget__links{
  margin-inline-start:auto;display:flex;align-items:center;gap:var(--ak-s-3);
  flex:0 0 auto;font-size:var(--ak-fs-small);
}
.ak-widget__links a{color:var(--ak-action);text-decoration:none}
.ak-widget__links a:hover{text-decoration:underline}
.ak-widget__body{
  padding:var(--ak-s-4);min-width:0;min-height:0;
  display:flex;flex-direction:column;gap:var(--ak-gap-between);
}
.ak-widget__body--flush{padding:0;min-width:0;min-height:0}
.ak-widget__scroll{
  overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;
  contain:layout paint;
  max-height:var(--ak-widget-h,none);
}
.ak-widget__foot{
  padding:var(--ak-s-2) var(--ak-s-4);
  border-top:var(--ak-border) solid var(--ak-line);
  background:var(--ak-surface-2);
  font-size:var(--ak-fs-small);color:var(--ak-ink-muted);
  display:flex;align-items:center;flex-wrap:wrap;gap:var(--ak-s-3);
  border-radius:0 0 var(--ak-r-md) var(--ak-r-md);
}
.ak-widget__resize{
  display:none;position:absolute;inset-inline-end:var(--ak-s-1);inset-block-end:var(--ak-s-1);
  inline-size:var(--ak-s-4);block-size:var(--ak-s-4);cursor:nwse-resize;
  color:var(--ak-ink-muted);line-height:1;font-size:var(--ak-fs-tiny);
  align-items:center;justify-content:center;
}
.ak-wgrid[data-arrange="on"] .ak-widget{border-color:var(--ak-action);border-style:dashed}
.ak-wgrid[data-arrange="on"] .ak-widget__grip,
.ak-wgrid[data-arrange="on"] .ak-widget__resize{display:inline-flex}
.ak-widget[aria-grabbed="true"],.ak-widget.is-dragging{opacity:.5}
@media (pointer:coarse){
  .ak-widget__grip{min-inline-size:var(--ak-target-touch);min-block-size:var(--ak-target-touch)}
  .ak-widget__links a{display:inline-flex;align-items:center;min-block-size:var(--ak-target-touch)}
}
/* Spans fold at the documented breakpoints: 12 columns, then 6 at a
   tablet (4, 5 and 7 become half, 8 becomes whole), then 1 on a phone.
   Nothing is hidden: a widget that disappears on a phone is a widget
   someone stops trusting on a desktop. (The pack put these in the layout
   layer, where every one of them lost to the spans above.) */
@media (max-width:1279px){
  .ak-widget[data-span="4"],.ak-widget[data-span="5"],
  .ak-widget[data-span="7"]{grid-column:span 6}
  .ak-widget[data-span="8"]{grid-column:span 12}
}
@media (max-width:767px){
  .ak-wgrid{grid-template-columns:minmax(0,1fr)}
  .ak-widget,.ak-widget[data-span]{grid-column:1 / -1}
  /* Title, a count, two links, a stamp and a kebab do not fit in 375px.
     None of them may be dropped (the links are the way out of the
     block, the kebab the way to act on it), so the head wraps: the
     links group takes its own line, at the end, and the title truncates
     rather than push anything sideways (pack 18.17). */
  .ak-widget__links{flex:1 0 100%;margin-inline-start:0;justify-content:flex-end;flex-wrap:wrap;
    column-gap:var(--ak-s-2)}
  .ak-widget__title{flex:1 1 0}
}

/* The freshness stamp. Mono, micro, muted: findable, never loud. It holds
   a <time datetime="…">, so the moment is machine-readable and a screen
   reader can be given the real timestamp. */
.ak-stamp{
  font-family:var(--ak-font-mono);font-size:var(--ak-fs-micro);
  color:var(--ak-ink-muted);font-variant-numeric:tabular-nums;
  white-space:nowrap;
}

/* ---- 19.3 Action card ------------------------------------------------
   One thing that wants a decision: a severity chip, a title, the two or
   three figures that make the case, and the one control that acts. It is
   NOT a card inside a card: inside a widget it is a bordered row.
   Markup: div.ak-actions > article.ak-action[data-severity] >
     div.ak-action__head > .ak-chip[data-state] (the word) and
       h*.ak-action__title; div.ak-action__lines > span ("Items
       affected <b>5</b>"); div.ak-action__foot > .ak-btn.
   The vocabulary is darpan's own — OVERDUE, DUE_TODAY, DUE_SOON, OPEN —
   because that is what darpan.my_tasks() returns and severity_rank()
   orders by. It paints the left rule only, on the status hues already
   here (failed, failed, warning, information): no new word, no sixth
   hue. The chip carries the word, so the rule is never the only sign. */
.ak-actions{display:flex;flex-direction:column;gap:var(--ak-s-3)}
.ak-action{
  border:var(--ak-border) solid var(--ak-line);
  border-inline-start:3px solid var(--ak-neutral);
  border-radius:var(--ak-r-sm);
  padding:var(--ak-s-3);
  display:flex;flex-direction:column;gap:var(--ak-s-2);
  background:var(--ak-surface);
}
.ak-action[data-severity="OVERDUE"],
.ak-action[data-severity="DUE_TODAY"]{border-inline-start-color:var(--ak-failed)}
.ak-action[data-severity="DUE_SOON"]{border-inline-start-color:var(--ak-warning)}
.ak-action[data-severity="OPEN"]{border-inline-start-color:var(--ak-info)}
.ak-action__head{display:flex;align-items:flex-start;flex-wrap:wrap;gap:var(--ak-s-2)}
.ak-action__title{
  margin:0;font-size:var(--ak-fs-base);font-weight:var(--ak-fw-semibold);
  line-height:var(--ak-lh-snug);min-width:0;flex:1 1 12rem;
}
.ak-action__lines{
  display:flex;flex-direction:column;gap:2px;
  font-size:var(--ak-fs-small);color:var(--ak-ink-2);
}
/* The figures are mono and bold; the sentence around them is not. */
.ak-action__lines b{
  font-family:var(--ak-font-mono);font-weight:var(--ak-fw-semibold);
  font-variant-numeric:tabular-nums;color:var(--ak-ink);
}
.ak-action__foot{display:flex;align-items:center;gap:var(--ak-s-2);flex-wrap:wrap}

/* ---- 19.4 Menu: the list form (extends 18.4) -------------------------
   The disclosure in 18.4 is unchanged: a menu with no modifier draws
   exactly as before (the person menu in the masthead). The list form is
   a modifier, because it is denser and scrolls:
     .ak-menu--grouped  the way to 140 screens or every report: bold
                        group names, indented items, a body that scrolls
                        under a search that stays put.
     .ak-menu--kebab    a block's own options, and the account menu:
                        the same object, narrower, items not indented.
     .ak-menu--flow     drawn in the flow of the page instead of over it
                        (a list inside a panel or a drawer, a specimen).
     data-align="start" opens from the button's start edge; "end" (the
                        default) from its end. Anchored, never fixed: it
                        travels with its button. CSS cannot know which
                        side has room, so the page sets it when it opens
                        the menu: toward the side the panel fits (a 16rem
                        panel opened toward the start from a button near
                        the start edge runs off a 320px screen). The
                        design book's script shows the measurement.
   Still a disclosure, not an ARIA menu: a button with aria-expanded and
   aria-controls, a panel of ordinary buttons and links tabbed through in
   order; Escape or a click elsewhere closes it and focus returns to the
   button; one open at a time. aria-expanded is the state, hidden the
   consequence. A search inside it would be invalid in role="menu".
   Parts: div.ak-menu__search > label.ak-sr + input.ak-input; a group is
   div[role=group][aria-labelledby] > div.ak-menu__group[id] + its items
   (a flat run of __group and __item also draws); hr.ak-menu__sep; an
   item that cannot act is aria-disabled="true" with a title saying why,
   and a trailing .ak-stamp carries a count ("Who changed what · 10,537").
   No item in any menu deletes anything. */
.ak-menu[data-align="start"]{inset-inline-start:0;inset-inline-end:auto}
.ak-menu[data-align="end"]{inset-inline-end:0;inset-inline-start:auto}
.ak-menu[data-fit="content"]{inline-size:max-content;max-inline-size:calc(100vw - 2 * var(--ak-gutter))}
.ak-menu__group{
  font-size:var(--ak-fs-tiny);font-weight:var(--ak-fw-bold);
  text-transform:uppercase;letter-spacing:var(--ak-ls-caps);
  color:var(--ak-ink-muted);
}
.ak-menu__sep{border:0;border-block-start:var(--ak-border) solid var(--ak-line);
  block-size:0;margin:0}
.ak-menu__item[aria-disabled="true"]{color:var(--ak-ink-muted);cursor:not-allowed}
.ak-menu__item[aria-disabled="true"]:hover{background:none}
.ak-menu__item .ak-stamp{margin-inline-start:auto}
.ak-menu__item{text-align:start}

.ak-menu:is(.ak-menu--grouped,.ak-menu--kebab){
  /* As wide as its longest item, within the two limits: anchored to a
     narrow button, auto would shrink it to the button's box. */
  inline-size:max-content;
  min-inline-size:min(var(--ak-menu-min),calc(100vw - var(--ak-s-5)));
  max-inline-size:min(var(--ak-menu-max),calc(100vw - var(--ak-s-5)));
  max-block-size:min(60vh,var(--ak-menu-max-h));
  overflow:auto;overscroll-behavior:contain;
  border-color:var(--ak-line-strong);
  gap:0;padding:var(--ak-s-2) 0;
}
/* As specific as the rule above and later, so it wins. */
.ak-menu.ak-menu--kebab{min-inline-size:min(var(--ak-menu-kebab-min),calc(100vw - var(--ak-s-5)))}
.ak-menu:is(.ak-menu--grouped,.ak-menu--kebab) .ak-menu__group{
  padding:var(--ak-s-3) var(--ak-s-4) var(--ak-s-1)}
/* The first group name after the top edge or the search sits closer. */
.ak-menu:is(.ak-menu--grouped,.ak-menu--kebab) > .ak-menu__group:first-child,
.ak-menu:is(.ak-menu--grouped,.ak-menu--kebab) > :first-child > .ak-menu__group:first-child,
.ak-menu:is(.ak-menu--grouped,.ak-menu--kebab) > .ak-menu__search + .ak-menu__group,
.ak-menu:is(.ak-menu--grouped,.ak-menu--kebab) > .ak-menu__search + * > .ak-menu__group:first-child{
  padding-block-start:var(--ak-s-1)}
.ak-menu:is(.ak-menu--grouped,.ak-menu--kebab) .ak-menu__item{
  border-radius:0;padding-block:var(--ak-s-2);
  padding-inline:var(--ak-s-6) var(--ak-s-4)}
.ak-menu.ak-menu--kebab .ak-menu__item{padding-inline-start:var(--ak-s-4)}
.ak-menu:is(.ak-menu--grouped,.ak-menu--kebab) .ak-menu__item:focus-visible{
  background:var(--ak-sunk);
  /* The body scrolls, so a ring outside a full-width item is clipped. */
  outline-offset:calc(var(--ak-focus-w) * -1);box-shadow:none}
.ak-menu:is(.ak-menu--grouped,.ak-menu--kebab) .ak-menu__sep{margin-block:var(--ak-s-2)}
/* The search stays put while the body scrolls under it. The negative
   top cancels the menu's own top padding, so it sticks to the edge. */
.ak-menu__search{
  position:sticky;inset-block-start:calc(var(--ak-s-2) * -1);z-index:1;
  margin-block:calc(var(--ak-s-2) * -1) var(--ak-s-2);
  padding:var(--ak-s-2);background:var(--ak-surface);
  border-block-end:var(--ak-border) solid var(--ak-line);
}
.ak-menu.ak-menu--flow{position:static;box-shadow:none;inline-size:auto}

/* ---- 19.5 Split button ----------------------------------------------
   The primary act on the start side, its variants behind the caret on
   the end side. Two buttons, one object: the seam is one border, never a
   gap. Markup: div.ak-menuwrap > div.ak-split > .ak-btn (acts) +
   .ak-btn (the caret: aria-label naming what it opens, aria-expanded,
   aria-controls), then the .ak-menu after the split. The menu anchors to
   the whole split, not the caret: from a caret near the middle of a
   320px screen a 16rem panel fits on neither side. (A caret in its own
   .ak-menuwrap inside the split also draws.) */
.ak-split{display:inline-flex;align-items:stretch}
.ak-split > .ak-btn:first-child{border-start-end-radius:0;border-end-end-radius:0}
.ak-split > .ak-btn:last-child:not(:first-child),
.ak-split > .ak-menuwrap:last-child > .ak-btn{
  border-start-start-radius:0;border-end-start-radius:0;
  padding-inline:var(--ak-s-3);
  border-inline-start-color:color-mix(in srgb,var(--ak-on-fill) 32%,transparent);
  margin-inline-start:calc(var(--ak-border) * -1);
}
.ak-split > .ak-btn--secondary:last-child:not(:first-child),
.ak-split > .ak-menuwrap:last-child > .ak-btn--secondary{
  border-inline-start-color:var(--ak-line-control)}
@media (pointer:coarse){
  .ak-split > .ak-menuwrap:last-child > .ak-btn,
  .ak-split > .ak-btn:last-child:not(:first-child){min-inline-size:var(--ak-target-touch)}
}

/* ---- 19.6 Chip group ------------------------------------------------
   Multi-select toggles that read as one control: the entities in view,
   "AKS AEI AGT". Markup: div.ak-chipgroup[role=group][aria-label] >
   button.ak-chiptog[aria-pressed]. The pressed state is aria-pressed,
   never a class. A group that must keep one on refuses the last one and
   says why in a status line; it never goes empty silently. */
.ak-chipgroup{
  display:inline-flex;align-items:center;flex-wrap:wrap;gap:var(--ak-s-1);
  padding:var(--ak-s-1);border:var(--ak-border) solid var(--ak-line-strong);
  border-radius:var(--ak-r-sm);background:var(--ak-surface);
}
.ak-chiptog{
  appearance:none;margin:0;border:0;background:none;cursor:pointer;
  box-sizing:border-box;display:inline-flex;align-items:center;
  padding:var(--ak-s-1) var(--ak-s-2);border-radius:var(--ak-r-xs);
  font-family:var(--ak-font-mono);font-size:var(--ak-fs-tiny);
  font-weight:var(--ak-fw-semibold);letter-spacing:.02em;line-height:1.2;
  color:var(--ak-ink-muted);min-height:var(--ak-target-min);
}
.ak-chiptog:hover{background:var(--ak-sunk);color:var(--ak-ink)}
.ak-chiptog[aria-pressed="true"]{background:var(--ak-action);color:var(--ak-on-fill)}
@media (pointer:coarse){.ak-chiptog{min-height:var(--ak-target-touch);min-width:var(--ak-target-touch);
  justify-content:center}}

/* ---- 19.7 Metric grid -----------------------------------------------
   Label over figure, in a grid with hairline dividers; two columns by
   default, .ak-metrics--3 or --4 on a wide widget, two again on a phone.
   The dividers are borders on the cells; the grid is pulled one border
   past its own box and clips, so the last column and the last row never
   leave a dangling line, for any column count. Use it flush
   (.ak-widget__body--flush), so the pulled edge lands on the frame.
   Markup: div.ak-metrics > div.ak-metric[data-state] >
   span.ak-metric__label, span.ak-metric__value, span.ak-metric__note.
   div.ak-metric.ak-metric--wide spans every column. */
.ak-metrics{
  display:grid;gap:0;
  grid-template-columns:repeat(var(--ak-metrics-cols,2),minmax(0,1fr));
  overflow:hidden;
  margin-inline-end:calc(var(--ak-border) * -1);
  margin-block-end:calc(var(--ak-border) * -1);
}
.ak-metrics--3{--ak-metrics-cols:3}
.ak-metrics--4{--ak-metrics-cols:4}
.ak-metric{
  padding:var(--ak-s-3) var(--ak-s-4);
  border-inline-end:var(--ak-border) solid var(--ak-line);
  border-block-end:var(--ak-border) solid var(--ak-line);
  display:flex;flex-direction:column;gap:2px;min-width:0;
}
/* A cell that spans the whole grid, for a figure that will not fit half
   the width (a money figure such as 18,42,500.00 on a phone). */
.ak-metric--wide{grid-column:1 / -1}
.ak-metric__label{
  font-size:var(--ak-fs-tiny);text-transform:uppercase;
  letter-spacing:var(--ak-ls-caps);color:var(--ak-ink-muted);
  font-weight:var(--ak-fw-semibold);
  display:flex;align-items:center;gap:var(--ak-s-1);
}
.ak-metric__value{
  font-family:var(--ak-font-mono);font-size:var(--ak-fs-h3);
  font-weight:var(--ak-fw-semibold);font-variant-numeric:tabular-nums;
  line-height:1.15;overflow-wrap:anywhere;
}
.ak-metric[data-state="failed"] .ak-metric__value{color:var(--ak-failed-ink)}
.ak-metric[data-state="warning"] .ak-metric__value{color:var(--ak-warning-ink)}
.ak-metric[data-state="complete"] .ak-metric__value{color:var(--ak-complete-ink)}
.ak-metric__note{font-size:var(--ak-fs-tiny);color:var(--ak-ink-muted)}
/* Later than the modifiers and as specific, so a phone gets two columns
   whatever the desktop asked for. (The pack put the modifiers in the
   utilities layer, which beat this rule on every phone.) */
@media (max-width:767px){
  .ak-metrics,.ak-metrics--3,.ak-metrics--4{--ak-metrics-cols:2}
}
@media (max-width:479px){.ak-metric__value{font-size:var(--ak-fs-h4)}}

/* ---- 19.8 Tier rail -------------------------------------------------
   Horizontal progress through named stages, for things that have a
   standing rather than a status: a vendor's band, an entity's compliance
   tier, a person's training level. Past stages are joined by a solid
   line, future ones by a dashed line. It scrolls sideways in its own box
   on a narrow screen, so give the list tabindex="0" and an aria-label.
   Markup: ol.ak-tier > li.ak-tier__step[data-done="true"] (past) or
   [aria-current="step"] (now) > span.ak-tier__mark[aria-hidden] (a tick
   or the number), span.ak-tier__name, span.ak-tier__note. Say "done"
   in words for a screen reader (.ak-sr); the tick is hidden from it. */
.ak-tier{display:flex;align-items:flex-start;gap:0;min-width:0;
  list-style:none;margin:0;padding:0;
  overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:thin}
.ak-tier__step{
  flex:1 1 0;min-width:var(--ak-tier-step-min);display:flex;flex-direction:column;
  align-items:center;gap:var(--ak-s-1);text-align:center;position:relative;
  padding-inline:var(--ak-s-2);
}
.ak-tier__step::before,.ak-tier__step::after{
  content:"";position:absolute;inset-block-start:calc(var(--ak-tier-mark) / 2 - 1px);
  border-top:2px dashed var(--ak-line-strong);
}
.ak-tier__step::before{inset-inline:0 50%}
.ak-tier__step::after{inset-inline:50% 0}
.ak-tier__step:first-child::before,.ak-tier__step:last-child::after{display:none}
.ak-tier__step[data-done="true"]::before,
.ak-tier__step[data-done="true"]::after{border-top-style:solid;border-top-color:var(--ak-complete)}
.ak-tier__mark{
  inline-size:var(--ak-tier-mark);block-size:var(--ak-tier-mark);
  border-radius:50%;flex:0 0 auto;z-index:1;
  display:grid;place-items:center;font-size:var(--ak-fs-tiny);
  font-weight:var(--ak-fw-bold);line-height:1;
  background:var(--ak-surface);color:var(--ak-ink-muted);
  border:2px solid var(--ak-line-strong);
}
.ak-tier__step[data-done="true"] .ak-tier__mark{
  background:var(--ak-complete);border-color:var(--ak-complete);color:var(--ak-on-fill)}
.ak-tier__step[aria-current="step"] .ak-tier__mark{
  border-color:var(--ak-action);color:var(--ak-action)}
.ak-tier__name{font-size:var(--ak-fs-small);font-weight:var(--ak-fw-medium)}
.ak-tier__step[aria-current="step"] .ak-tier__name{
  font-weight:var(--ak-fw-semibold);color:var(--ak-action)}
.ak-tier__note{font-size:var(--ak-fs-micro);color:var(--ak-ink-muted)}

/* ---- 19.9 Greeting band ---------------------------------------------
   The one place in the ERP that addresses the person by name. A band,
   not a hero: a hero pushes the work below the fold, the opposite of
   what a home page is for. Its height is its content's.
   Markup: div.ak-greet > h*.ak-greet__hi, span.ak-greet__sub (the date
   and a .ak-stamp), div.ak-greet__right (the split button, the reports
   menu, Arrange). */
.ak-greet{display:flex;align-items:baseline;gap:var(--ak-s-3);flex-wrap:wrap}
.ak-greet__hi{
  margin:0;font-size:var(--ak-fs-h2);font-weight:var(--ak-fw-semibold);
  letter-spacing:var(--ak-ls-tight);
}
.ak-greet__sub{font-size:var(--ak-fs-small);color:var(--ak-ink-muted)}
.ak-greet__right{margin-inline-start:auto;display:flex;align-items:center;
  gap:var(--ak-s-2);flex-wrap:wrap}

/* ---- 19.10 A chip that is also a control ----------------------------
   Some chips state a fact you can act on: "Data health · 3 to fix". A
   <button class="ak-chip"> says so honestly; this stops the browser's
   button chrome showing through. A chip that is not a control stays a
   <span>. */
button.ak-chip{
  border:0;font-family:inherit;cursor:pointer;
  min-height:var(--ak-target-min);
}
button.ak-chip:hover{filter:brightness(.96)}
@media (pointer:coarse){button.ak-chip{min-height:var(--ak-target-touch)}}

/* ---- 19.11 Avatar ---------------------------------------------------
   Initials, not a photograph: a 30px photograph of a colleague is
   unreadable; two letters are not. It is a button, because it opens the
   account menu, the one menu every person has. The visible initials
   start its name: "AR" + .ak-sr ", Asha Rao, your account". Under a
   finger its hit area is 44px while the circle stays small. */
.ak-avatar{
  appearance:none;margin:0;border:0;padding:0;cursor:pointer;
  box-sizing:border-box;flex:0 0 auto;position:relative;
  inline-size:var(--ak-s-7);block-size:var(--ak-s-7);border-radius:50%;
  display:inline-grid;place-items:center;
  background:var(--ak-brand-700);color:var(--ak-chrome-ink-strong);
  font:inherit;font-size:var(--ak-fs-tiny);font-weight:var(--ak-fw-bold);
  letter-spacing:.02em;line-height:1;
}
.ak-avatar:hover{background:var(--ak-brand-600)}
@media (pointer:coarse){
  .ak-avatar::after{content:"";position:absolute;inset:50% auto auto 50%;
    inline-size:var(--ak-target-touch);block-size:var(--ak-target-touch);
    transform:translate(-50%,-50%)}
}

/* ---- 19.12 Masthead: the entity picker, data-shed, the search toggle -
   The shedding order is declared ON the control, not guessed at by a
   selector that has to know what each control is:
     data-shed="900"   leaves the masthead at 900px and below
     data-shed="480"   leaves it at 480px and below
   Whatever is shed must have a home in the account menu: nothing just
   disappears. The trail, the menu button, the entity picker and the
   avatar never shed. The order, with what 2.2.0 already does (18.9):
     1. the identity chip and a data-health chip go        (900)
     2. the entity picker narrows                          (900, 640)
     3. a search in the right group narrows                (900)
     4. that search becomes a button and opens over the masthead (640)
   The picker is a .ak-select placed straight in the masthead or its
   right group (one inside the person menu is not touched). The search
   is .ak-masthead__right > .ak-search, with
   button.ak-masthead__searchtoggle[aria-expanded] beside it; the page
   sets data-search="on" on .ak-app while it is open, and Escape closes
   it and returns focus to the button. */
.ak-masthead > .ak-select,.ak-masthead__right > .ak-select{
  inline-size:auto;max-inline-size:15rem;flex:0 1 auto;min-inline-size:0}
.ak-masthead > .ak-select{background-color:var(--ak-chrome-field);
  color:var(--ak-chrome-ink-strong);border-color:var(--ak-chrome-line)}
.ak-masthead__right > .ak-search .ak-input{background:var(--ak-chrome-field);
  color:var(--ak-chrome-ink-strong);border-color:var(--ak-chrome-line)}
.ak-masthead__right > .ak-search .ak-input::placeholder{color:var(--ak-chrome-ink)}
.ak-masthead__right > .ak-search .ak-search__icon{color:var(--ak-chrome-ink)}
.ak-masthead__right > .ak-search{flex:0 1 16rem;min-width:15rem}   /* 2.13.2: was 8rem */
.ak-masthead__searchtoggle{display:none}
@media (max-width:900px){
  .ak-masthead > .ak-select,.ak-masthead__right > .ak-select{max-inline-size:9.5rem}
  .ak-masthead__right > .ak-search{flex:0 1 10rem;min-width:7rem}
  .ak-masthead [data-shed="900"]{display:none}
}
@media (max-width:640px){
  .ak-masthead > .ak-select,.ak-masthead__right > .ak-select{max-inline-size:6.5rem}
  .ak-masthead__searchtoggle{display:inline-flex}
  /* The field slides over the masthead instead of out of existence. */
  .ak-masthead__right > .ak-search{
    position:absolute;inset:0 0 auto 0;block-size:var(--ak-masthead-h);
    margin-block-start:env(safe-area-inset-top,0px);
    max-inline-size:none;min-inline-size:0;
    background:var(--ak-chrome);z-index:2;
    display:none;align-items:center;gap:var(--ak-s-2);
    padding-inline:var(--ak-s-3);
  }
  .ak-app[data-search="on"] .ak-masthead__right > .ak-search{display:flex}
  .ak-app[data-search="on"] .ak-masthead__right > .ak-search .ak-input{inline-size:100%}
}
@media (max-width:480px){
  .ak-masthead [data-shed="480"]{display:none}
}

/* ---- 19.13 A filter bar inside a widget ------------------------------
   A widget's own controls (its period, its entities) sit in its body,
   never in its head: the head is for identity, the body for the work.
   Inside the widget's frame the bar must not draw a second frame. */
.ak-filterbar--bare{padding:0;border:0;background:none;border-radius:0}

} /* end layer components — the working home */

/* ---- 19.14 Home utilities ------------------------------------------ */
@layer utilities {
.ak-wh-sm{--ak-widget-h:var(--ak-widget-h-sm)}
.ak-wh-md{--ak-widget-h:var(--ak-widget-h-md)}
.ak-wh-lg{--ak-widget-h:var(--ak-widget-h-lg)}
}

/* ---- 19.15 Motion ---------------------------------------------------
   A list menu settles in from its button. Only the list form: the person
   menu (18.4) opens as it always has. Reduced motion stops it (2). */
@layer states {
@media (prefers-reduced-motion:no-preference){
  .ak-menu:is(.ak-menu--grouped,.ak-menu--kebab):not(.ak-menu--flow){
    animation:ak-menu-in var(--ak-dur-fast) var(--ak-ease-out)}
}
@keyframes ak-menu-in{from{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:none}}
}

/* ---- 19.16 Forced colours -------------------------------------------
   Where a state was drawn by fill alone, the operating system's palette
   would erase it. In the components layer, after each component's own
   rule, which it overrides (CLAUDE.md §1 rule 6); unlayered until 2.16.0. */
@layer components {
@media (forced-colors:active){
  .ak-measure{border-bottom-color:Canvas}
  .ak-measure[aria-selected="true"]{border-bottom-color:Highlight}
  .ak-chiptog[aria-pressed="true"]{forced-color-adjust:none;
    background:Highlight;color:HighlightText}
  .ak-chiptog{border:1px solid CanvasText}
  .ak-avatar,button.ak-chip{border:1px solid CanvasText}
  .ak-tier__step[data-done="true"] .ak-tier__mark{border-color:Highlight}
}
}

/* ===================================================================
   20 · OFFICE POLISH (2.12.0)
   -------------------------------------------------------------------
   Aapurti audit, wave 1: what a screen is for (a disclosure), a
   legacy tag, four KPI tiles on one row, headers that may wrap, the
   brand mark beside the rail. Also 2.12.0: the masthead trail (18) and
   the long register held to the window (4.6).
   =================================================================== */

/* ---- 20.1 Disclosure ------------------------------------------------
   A <details> that opens to say more: "About this screen" (what comes
   in, what goes out, who may do what, the documents kept), closed by
   default so the work comes first. The summary is a real button to a
   keyboard and a screen reader (the browser's own); its marker turns
   when open. Markup: details.ak-disclosure > summary.ak-disclosure__head
   + div.ak-disclosure__body. Added 11 Oct 2026 (2.12.0). */
@layer components {
.ak-disclosure{background:var(--ak-surface);border:var(--ak-border) solid var(--ak-line);
  border-radius:var(--ak-r-md)}
.ak-disclosure__head{display:flex;align-items:center;gap:var(--ak-s-2);
  min-height:var(--ak-target-min);padding:var(--ak-s-2) var(--ak-s-4);
  cursor:pointer;font-weight:var(--ak-fw-semibold);color:var(--ak-ink);
  list-style:none;border-radius:var(--ak-r-md)}
.ak-disclosure__head::-webkit-details-marker{display:none}
.ak-disclosure__head::before{content:"";inline-size:var(--ak-s-2);block-size:var(--ak-s-2);
  border-inline-end:var(--ak-border) solid currentColor;
  border-block-end:var(--ak-border) solid currentColor;
  transform:rotate(-45deg);transition:transform var(--ak-dur-fast) var(--ak-ease-out);flex:none}
.ak-disclosure[open] > .ak-disclosure__head::before{transform:rotate(45deg)}
.ak-disclosure__head:hover{background:var(--ak-surface-2)}
.ak-disclosure__note{font-weight:var(--ak-fw-regular);font-size:var(--ak-fs-small);
  color:var(--ak-ink-muted)}
.ak-disclosure__body{padding:0 var(--ak-s-4) var(--ak-s-4);
  display:flex;flex-direction:column;gap:var(--ak-gap-between)}
@media (pointer:coarse){.ak-disclosure__head{min-height:var(--ak-target-touch)}}
@media (forced-colors:active){.ak-disclosure{border-color:CanvasText}}
}

/* ---- 20.1a Brand mark beside the rail -----------------------------
   Below 1280px the masthead's brand mark keeps its monogram only, so the
   trail has room for the screen's name. Its words were aria-hidden; the
   link keeps its accessible name. In the brand mark's own layer (CLAUDE.md
   section 1, rule 6). */
@layer components {
@media (max-width:1279px){.ak-masthead .ak-brandmark__text{display:none}}
}

/* ---- 20.1b Four figures, one row ----------------------------------
   A strip of exactly four KPI tiles is one row of four from 768px up,
   never three and an orphan (auto-fit dropped the fourth tile to a row
   of its own between about 1,000 and 1,300px). Narrower, the system's
   own two-up and one-up rules stand. */
@layer components {
@media (min-width:768px){
  .ak-grid--kpi:has(> :nth-child(4):last-child){grid-template-columns:repeat(2,minmax(0,1fr))}
}
/* 2.20.3: four across only where four tiles have room for their figures */
@media (min-width:1200px){
  .ak-grid--kpi:has(> :nth-child(4):last-child){grid-template-columns:repeat(4,minmax(0,1fr))}
}
}

/* ---- 20.1c Headers that may wrap ----------------------------------
   .ak-table--wraphead lets a long column name ("Avg daily demand") take
   two lines, so a register of short figures under long names fits its
   box instead of scrolling sideways. A header still sits over its own
   column, aligned as its column is. */
@layer components {
.ak-table--wraphead thead th{white-space:normal;vertical-align:bottom;
  min-inline-size:var(--ak-s-9)}
}

/* ---- 20.2 Legacy tag ------------------------------------------------
   A short tag standing for a long, repeated phrase ("All · legacy" for
   "All categories, supplier on file before 4 Oct 2026"), so a register
   row stays one line. The full phrase is its title and, for a screen
   reader, .ak-sr text inside it. Added 11 Oct 2026 (2.12.0). */
@layer components {
.ak-tag--legacy{display:inline-flex;align-items:center;gap:var(--ak-s-1);
  padding:0 var(--ak-s-2);border:var(--ak-border) dashed var(--ak-line-strong);
  border-radius:var(--ak-r-sm);font-size:var(--ak-fs-small);color:var(--ak-ink-muted);
  white-space:nowrap;cursor:help}
}

/* ===================================================================
   21 · ONE OFFICE, ONE MENU (2.13.0)
   -------------------------------------------------------------------
   Aapurti audit, wave 3: tabs that are links, chips of words, a
   calendar of days, a risk matrix, six KPI tiles in two rows.
   =================================================================== */

/* ---- 21.1 Tabs that are links ---------------------------------------
   Views kept at their own addresses (a merged entry's Approval ·
   Scorecard · Alternates; the three pages of Requisitions & POs) are a
   strip of links, not a tablist: each is a page a person can bookmark,
   and the one they are on carries aria-current="page", drawn as the
   selected tab. Markup: nav.ak-tabs[aria-label] > a.ak-tab, one with
   aria-current="page". Added 11 Oct 2026 (2.13.0). */
@layer components {
.ak-tab[aria-current="page"]{color:var(--ak-action);
  border-bottom-color:var(--ak-action);font-weight:var(--ak-fw-semibold)}
@media (forced-colors:active){.ak-tab[aria-current="page"]{border-bottom-color:Highlight}}
}

/* ---- 21.2 Chips of words --------------------------------------------
   The chip group (19.6) set in the reading face, for filters named in
   words ("Approved list", "Under qualification") rather than codes. One
   is pressed at a time where the group is a choice of views. Markup:
   div.ak-chipgroup.ak-chipgroup--words. Added 11 Oct 2026 (2.13.0). */
@layer components {
.ak-chipgroup--words .ak-chiptog{font-family:var(--ak-font-ui);
  font-size:var(--ak-fs-small);font-weight:var(--ak-fw-medium);letter-spacing:0}
.ak-chipgroup--words .ak-chiptog[aria-pressed="true"]{font-weight:var(--ak-fw-semibold)}
}

/* ---- 21.3 Calendar of days ------------------------------------------
   What falls due on which day (the procurement plan's order-by dates),
   Monday first, a few weeks at a time. A real table: the day names are
   its column heads. A day with something on it says how many in words;
   a day with something late carries data-state="failed" and says
   "late", so the state never rests on the tint. Today is
   aria-current="date". Days outside the range are data-out.
   Markup: table.ak-calendar > thead th + tbody td >
   span.ak-calendar__day + span.ak-calendar__what. Added 11 Oct 2026
   (2.13.0). Where the words are long, __what holds
   span.ak-calendar__short (aria-hidden) + span.ak-calendar__long, and a
   list beside the month says the same in full (2.24.0). */
@layer components {
.ak-calendar{inline-size:100%;border-collapse:separate;border-spacing:var(--ak-s-1);
  table-layout:fixed}
.ak-calendar th{font-size:var(--ak-fs-tiny);font-weight:var(--ak-fw-semibold);
  color:var(--ak-ink-muted);text-transform:uppercase;letter-spacing:var(--ak-ls-caps);
  text-align:start;padding:0 var(--ak-s-1)}
.ak-calendar td{vertical-align:top;block-size:var(--ak-s-9);
  padding:var(--ak-s-1) var(--ak-s-2);background:var(--ak-surface);
  border:var(--ak-border) solid var(--ak-line);border-radius:var(--ak-r-sm);
  overflow:hidden}
.ak-calendar td[data-out]{background:var(--ak-sunk);border-color:transparent}
.ak-calendar td[data-state="failed"]{background:var(--ak-failed-bg);border-color:var(--ak-failed)}
.ak-calendar td[data-state="warning"]{background:var(--ak-warning-bg);border-color:var(--ak-warning)}
.ak-calendar td[aria-current="date"]{border-color:var(--ak-action);
  box-shadow:inset 0 0 0 var(--ak-border) var(--ak-action)}
.ak-calendar__day{display:block;font-size:var(--ak-fs-tiny);color:var(--ak-ink-muted);
  font-variant-numeric:tabular-nums}
.ak-calendar__what{display:block;font-size:var(--ak-fs-small);
  font-weight:var(--ak-fw-semibold);color:var(--ak-ink);overflow-wrap:anywhere}
/* __long: words a phone cannot fit, kept for screen readers there;
   __short: what a phone shows instead (a dot, aria-hidden). (2.24.0) */
.ak-calendar__short{display:none}
@media (max-width:640px){
  .ak-calendar{border-spacing:2px}
  .ak-calendar td{padding:var(--ak-s-1);block-size:var(--ak-s-8)}
  .ak-calendar__what{font-size:var(--ak-fs-tiny)}
  .ak-calendar__long{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
    overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
  .ak-calendar__short{display:inline}
}
/* Forced colours. The second selector is as specific as the td[data-out]
   and td[data-state] rules above (0,2,1), so in this layer it still wins
   over them, as it did when it sat outside every layer (until 2.16.0). */
@media (forced-colors:active){
  .ak-calendar td,.ak-calendar td:is([data-out],[data-state]){border-color:CanvasText}
  .ak-calendar td[aria-current="date"]{border-color:Highlight;box-shadow:none}
}
}

/* ---- 21.4 Risk matrix -----------------------------------------------
   Two judgements crossed, each cell the count of things that sit there:
   how much of an item comes from one supplier, against how ready an
   alternate is. A real table with row and column heads. A cell's risk
   is its data-state (failed, warning, complete) and is written in the
   cell; an empty cell's count is quiet (data-zero). Markup:
   table.ak-matrix > thead th + tbody th + td > span.ak-matrix__n +
   span.ak-matrix__word. Added 11 Oct 2026 (2.13.0). */
@layer components {
.ak-matrix{inline-size:100%;border-collapse:separate;border-spacing:var(--ak-s-1);
  table-layout:fixed}
.ak-matrix th{font-size:var(--ak-fs-small);font-weight:var(--ak-fw-semibold);
  color:var(--ak-ink-2);text-align:start;padding:var(--ak-s-1) var(--ak-s-2);
  vertical-align:bottom}
.ak-matrix tbody th{vertical-align:middle}
.ak-matrix td{vertical-align:top;padding:var(--ak-s-2) var(--ak-s-3);
  background:var(--ak-surface);border:var(--ak-border) solid var(--ak-line);
  border-radius:var(--ak-r-sm)}
.ak-matrix td[data-state="failed"]{background:var(--ak-failed-bg);border-color:var(--ak-failed)}
.ak-matrix td[data-state="warning"]{background:var(--ak-warning-bg);border-color:var(--ak-warning)}
.ak-matrix td[data-state="complete"]{background:var(--ak-complete-bg);border-color:var(--ak-complete)}
.ak-matrix td[data-zero]{background:var(--ak-surface);border-color:var(--ak-line)}
.ak-matrix thead td{background:none;border:0}
.ak-matrix__n{display:block;font-family:var(--ak-font-mono);font-variant-numeric:tabular-nums;
  font-size:var(--ak-fs-h4);font-weight:var(--ak-fw-semibold);color:var(--ak-ink)}
.ak-matrix td[data-zero] .ak-matrix__n{color:var(--ak-ink-muted);font-weight:var(--ak-fw-regular)}
.ak-matrix__word{display:block;font-size:var(--ak-fs-tiny);color:var(--ak-ink-2)}
@media (max-width:640px){
  .ak-matrix{border-spacing:2px}
  .ak-matrix th,.ak-matrix td{padding:var(--ak-s-1)}
  .ak-matrix th{font-size:var(--ak-fs-tiny)}
}
/* Forced colours. The extra selectors are as specific as thead td (0,1,2)
   and td[data-state], td[data-zero] (0,2,1) above, so in this layer it
   still wins over them, as it did outside every layer (until 2.16.0). */
@media (forced-colors:active){
  .ak-matrix td,.ak-matrix thead td,.ak-matrix td:is([data-state],[data-zero]){border-color:CanvasText}
}
}

/* ---- 21.5 Six figures, two rows of three ----------------------------
   A strip of exactly six KPI tiles is two rows of three from 768px up,
   never five and an orphan (the Purchase desk). As 20.1b does for four.
   Added 11 Oct 2026 (2.13.0). */
@layer components {
@media (min-width:768px){
  .ak-grid--kpi:has(> :nth-child(6):last-child){grid-template-columns:repeat(3,minmax(0,1fr))}
}
}

/* ===================================================================
   22 · EDITING IN PLACE (2.14.0)
   -------------------------------------------------------------------
   Bhandar 1.8: a register edited where it stands (the grid; its
   behaviour is vendor/ak-grid.js) and two frozen columns.
   =================================================================== */

/* ---- 22.1 Edit-in-place grid (2.14.0, Bhandar 1.8) ----------------
   A register many rows long whose cells are edited where they stand,
   without a field in every cell (a field in every cell is a Tab stop in
   every cell: 900 of them on a page of 50 items).
   Markup: table.ak-table.ak-table--grid[role=grid] > tbody > tr >
   th[scope=row] (the record's code) + td[role=gridcell][tabindex]
   [data-field]; a cell that may not be changed carries
   aria-readonly="true". vendor/ak-grid.js gives it its keyboard: one Tab
   stop into the grid (the cell last on), arrow keys, Home and End along
   the row, Ctrl+Home and Ctrl+End; Enter, F2 or a typed character opens
   the cell's field (the page draws it, a system .ak-input or .ak-select)
   and sets data-editing; Enter or Tab keeps it, Escape puts it back. A
   click opens it. The page marks a changed cell with data-changed, and
   says so in words in the row (colour is never the only sign). */
@layer components {
.ak-table--grid tbody td[role="gridcell"]{
  min-inline-size:var(--ak-grid-cell);max-inline-size:var(--ak-grid-cell-max);
  white-space:normal;overflow-wrap:break-word;cursor:default}
/* the record's code, the row's header: a cell like the others, never wrapped */
.ak-table--grid tbody th[scope="row"]{padding:var(--ak-row-pad-y) var(--ak-row-pad-x);
  border-bottom:var(--ak-border) solid var(--ak-line);text-align:start;white-space:nowrap;
  font-weight:var(--ak-fw-regular);height:var(--ak-row-h)}
.ak-table--grid tbody tr:last-child th[scope="row"]{border-bottom:0}
.ak-table--grid tbody td.ak-grid-wide{min-inline-size:var(--ak-grid-cell-wide)}
.ak-table--grid tbody td[role="gridcell"]:not([aria-readonly="true"]){cursor:text}
.ak-table--grid tbody td[role="gridcell"]:not([aria-readonly="true"]):hover{
  box-shadow:inset 0 0 0 var(--ak-border) var(--ak-line-control)}
.ak-table--grid tbody :is(td,th):focus-visible{
  outline:var(--ak-focus-w) solid var(--ak-focus);outline-offset:calc(-1 * var(--ak-focus-w))}
.ak-table--grid tbody td[data-editing]{padding:var(--ak-s-1)}
.ak-table--grid tbody td[data-editing] :where(.ak-input,.ak-select){
  inline-size:100%;min-inline-size:var(--ak-grid-cell)}
.ak-table--grid tbody td[data-changed]{
  box-shadow:inset 3px 0 0 0 var(--ak-info);font-weight:var(--ak-fw-semibold)}
/* a cell's note ("Locked: has stock") keeps to one line and widens its column,
   rather than making its row three lines tall */
.ak-table--grid tbody td .ak-td-sub{display:block;white-space:nowrap}
@media (pointer:coarse){
  .ak-table--grid tbody td[role="gridcell"]{block-size:var(--ak-target-touch)}
}
@media (forced-colors:active){
  .ak-table--grid tbody td[data-changed]{outline:1px solid Highlight;outline-offset:-1px}
}
}

/* ---- 22.2 Two frozen columns (2.14.0, Bhandar 1.8) ----------------
   .ak-table--stickycol2: the first two columns (a code and a name) stay
   while the rest scroll sideways. The first is a set width, so the second
   knows where to sit. The shadow shows once the table has been scrolled
   sideways (data-scrolled-x on its .ak-tablescroll, set by ak-grid.js). */
@layer components {
.ak-table--stickycol2 :is(thead th,tbody td,tbody th):nth-child(-n+2){
  position:sticky;background:var(--ak-surface);z-index:1}
.ak-table--stickycol2 thead th:nth-child(-n+2){background:var(--ak-sunk);z-index:2}
.ak-table--stickycol2 :is(thead th,tbody td,tbody th):first-child{
  inset-inline-start:0;box-sizing:border-box;
  inline-size:var(--ak-sticky-first);min-inline-size:var(--ak-sticky-first);max-inline-size:var(--ak-sticky-first)}
.ak-table--stickycol2 :is(thead th,tbody td,tbody th):nth-child(2){inset-inline-start:var(--ak-sticky-first)}
.ak-tablescroll[data-scrolled-x="true"] .ak-table--stickycol2 :is(thead th,tbody td,tbody th):nth-child(2){
  box-shadow:2px 0 0 0 color-mix(in srgb,var(--ak-ink) 10%,transparent)}
.ak-tablescroll[data-scrolled-x="true"] .ak-table--stickycol2 tbody td[data-changed]:nth-child(2){
  box-shadow:inset 3px 0 0 0 var(--ak-info),2px 0 0 0 color-mix(in srgb,var(--ak-ink) 10%,transparent)}
/* on a phone two frozen columns would be the whole screen: only the first stays */
@media (max-width:767px){
  .ak-table--stickycol2 :is(thead th,tbody td,tbody th):nth-child(2){position:static}
  .ak-tablescroll[data-scrolled-x="true"] .ak-table--stickycol2 :is(thead th,tbody td,tbody th):nth-child(2){box-shadow:none}
  .ak-tablescroll[data-scrolled-x="true"] .ak-table--stickycol2 :is(tbody td,tbody th):first-child{
    box-shadow:2px 0 0 0 color-mix(in srgb,var(--ak-ink) 10%,transparent)}
}
}

/* ===================================================================
   23 · THE PHONE (2.15.0)
   -------------------------------------------------------------------
   Bhandar 1.7: the bottom tab bar, the floating action, and the two
   phone-only utilities. Their width is 640px (12).
   =================================================================== */

/* ---- 23.1 Bottom tab bar (2.15.0, Bhandar 1.7) --------------------
   On a phone a screen's views move from the top of the page to a bar at
   the bottom, under the thumb. Markup: nav.ak-tabbar[aria-label] >
   button.ak-tabbar__item (aria-current="page" on the one shown), each a
   word and, if it has one, a count (span.ak-tabbar__count); the last may
   be div.ak-menuwrap.ak-tabbar__more holding a More button and an
   .ak-menu, which opens upward. Shown at 640px and below only; the page
   is padded by its height so nothing hides behind it, and an action bar
   and the toasts rise above it. The page keeps its own views at the top
   for wider screens and hides them on a phone (data-phone="hide"). */
@layer components {
.ak-tabbar{display:none}
@media (max-width:640px){
  .ak-tabbar{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);
    position:fixed;inset-inline:0;inset-block-end:0;z-index:var(--ak-z-masthead);
    min-block-size:var(--ak-tabbar-h);padding-block-end:env(safe-area-inset-bottom,0px);
    background:var(--ak-surface);border-block-start:var(--ak-border) solid var(--ak-line-strong);
    box-shadow:var(--ak-shadow-rise)}
  body:has(.ak-tabbar:not([data-static])){padding-block-end:calc(var(--ak-tabbar-h) + env(safe-area-inset-bottom,0px))}
  body:has(.ak-tabbar:not([data-static])) .ak-actionbar{inset-block-end:calc(var(--ak-tabbar-h) + env(safe-area-inset-bottom,0px))}
  body:has(.ak-tabbar:not([data-static])) .ak-toasts{inset-block-end:calc(var(--ak-tabbar-h) + var(--ak-s-3) + env(safe-area-inset-bottom,0px))}
}
.ak-tabbar__item,.ak-tabbar__more > button{
  all:unset;box-sizing:border-box;cursor:pointer;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  min-block-size:var(--ak-tabbar-h);min-inline-size:var(--ak-target-touch);padding-inline:var(--ak-s-1);
  font:inherit;font-size:var(--ak-fs-small);font-weight:var(--ak-fw-medium);line-height:1.2;
  color:var(--ak-ink-muted);text-align:center;overflow-wrap:anywhere}
.ak-tabbar__more{display:flex}
.ak-tabbar__more > button{inline-size:100%}
.ak-tabbar__item[aria-current="page"]{color:var(--ak-action);font-weight:var(--ak-fw-semibold);
  box-shadow:inset 0 3px 0 0 var(--ak-action)}
.ak-tabbar__item:hover,.ak-tabbar__more > button:hover{color:var(--ak-ink)}
.ak-tabbar__item:focus-visible,.ak-tabbar__more > button:focus-visible{
  outline:var(--ak-focus-w) solid var(--ak-focus);outline-offset:calc(-1 * var(--ak-focus-w))}
.ak-tabbar__count{font-family:var(--ak-font-mono);font-size:var(--ak-fs-tiny);
  font-variant-numeric:tabular-nums;padding:0 var(--ak-s-1);border-radius:var(--ak-r-pill);
  background:var(--ak-sunk);color:var(--ak-ink)}
.ak-tabbar .ak-menu{inset-block-start:auto;inset-block-end:calc(100% + var(--ak-s-2));inset-inline-end:var(--ak-s-2)}
/* data-static draws it in place at any width (the design book's specimen) */
.ak-tabbar[data-static]{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);position:relative;
  min-block-size:var(--ak-tabbar-h);background:var(--ak-surface);
  border:var(--ak-border) solid var(--ak-line-strong);border-radius:var(--ak-r-md)}
@media (forced-colors:active){
  .ak-tabbar{border-block-start:1px solid CanvasText}
  .ak-tabbar__item[aria-current="page"]{forced-color-adjust:none;color:Highlight;box-shadow:inset 0 3px 0 0 Highlight}
}
}

/* ---- 23.2 Floating action (2.15.0, Bhandar 1.7) -------------------
   The page's one primary action, kept in reach while a long list scrolls
   on a phone. Markup: button.ak-btn.ak-btn--primary.ak-fab with its words
   (never an icon alone). Fixed bottom-right, above the bottom tab bar when
   the page has one. A page shows it on a phone only with data-phone="only"
   and hides the same action in its header there with data-phone="hide":
   one action, one place at a time. */
@layer components {
.ak-fab{position:fixed;inset-inline-end:var(--ak-s-4);
  inset-block-end:calc(var(--ak-s-4) + env(safe-area-inset-bottom,0px));z-index:var(--ak-z-sticky);
  min-block-size:var(--ak-target-touch);padding-inline:var(--ak-s-5);
  border-radius:var(--ak-r-pill);box-shadow:var(--ak-shadow-rise)}
.ak-fab[data-static]{position:static}
@media (max-width:640px){
  body:has(.ak-tabbar:not([data-static])) .ak-fab:not([data-static]){inset-block-end:calc(var(--ak-tabbar-h) + var(--ak-s-3) + env(safe-area-inset-bottom,0px))}
}
}

/* ---- 23.3 On a phone only, or not on a phone (2.15.0) -------------
   data-phone="only" shows an element at 640px and below, data-phone="hide"
   hides it there. !important in the utilities layer holds over a page's
   own (later-layer, normal) display rule: the cascade decides, not a
   selector race. */
@layer utilities {
@media (min-width:641px){ [data-phone="only"]{display:none!important} }
@media (max-width:640px){ [data-phone="hide"]{display:none!important} }
}

/* ===================================================================
   24 · THE TREE (2.19.0, Yojana)
   =================================================================== */
/* ---- 24.1 A navigation tree -----------------------------------------
   Nested records picked one at a time: in Yojana, the company, its
   verticals, their segments and channels. Disclosure navigation, not the
   ARIA tree role: every row is a plain button reached with Tab and
   pressed with Enter or Space; a branch opens and closes with its own
   toggle (button, aria-expanded, aria-controls the branch's list, and an
   aria-label that names the branch); the row on show carries
   aria-current="true". Markup:
     nav.ak-tree[aria-label] > ul.ak-tree__list > li.ak-tree__node >
       div.ak-tree__row > (button.ak-tree__toggle | span.ak-tree__spacer)
                          + button.ak-tree__item > span.ak-tree__label
                                                  + span.ak-tree__count?
       + ul.ak-tree__list (the branch; hidden while closed)
   Each level indents from its own list, so depth needs no class. A long
   name wraps rather than being cut. The row on show is tinted and set in
   semibold; in forced colours it is Highlight. The focus ring stays the
   focus ring. */
@layer components {
.ak-tree{display:block;min-width:0}
.ak-tree__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--ak-s-0)}
.ak-tree__list .ak-tree__list{padding-inline-start:var(--ak-s-4)}
.ak-tree__list[hidden]{display:none}
.ak-tree__row{display:flex;align-items:center;gap:var(--ak-s-1);min-width:0}
.ak-tree__toggle,.ak-tree__spacer{flex:none;inline-size:var(--ak-control-h);min-block-size:var(--ak-control-h)}
.ak-tree__toggle{display:inline-flex;align-items:center;justify-content:center;padding:0;
  border:0;border-radius:var(--ak-r-sm);background:transparent;color:var(--ak-ink-muted);cursor:pointer}
.ak-tree__toggle::before{content:"";inline-size:var(--ak-s-2);block-size:var(--ak-s-2);
  border-inline-end:var(--ak-border) solid currentColor;border-block-end:var(--ak-border) solid currentColor;
  transform:rotate(-45deg);transition:transform var(--ak-dur-fast) var(--ak-ease-out)}
.ak-tree__toggle[aria-expanded="true"]::before{transform:rotate(45deg)}
.ak-tree__toggle:hover{background:var(--ak-surface-2);color:var(--ak-ink)}
.ak-tree__item{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:var(--ak-s-2);
  min-block-size:var(--ak-control-h);padding:var(--ak-s-1) var(--ak-s-2);
  border:0;border-radius:var(--ak-r-sm);background:transparent;color:var(--ak-ink-2);
  font:inherit;font-size:var(--ak-fs-base);line-height:var(--ak-lh-snug);text-align:start;cursor:pointer}
.ak-tree__item:hover{background:var(--ak-surface-2);color:var(--ak-ink)}
.ak-tree__item[aria-current="true"]{background:var(--ak-action-bg);color:var(--ak-ink);font-weight:var(--ak-fw-semibold)}
.ak-tree__label{min-width:0;overflow-wrap:anywhere}
.ak-tree__count{margin-inline-start:auto;flex:none;font-family:var(--ak-font-mono);font-size:var(--ak-fs-tiny);
  font-variant-numeric:tabular-nums;color:var(--ak-ink-muted);font-weight:var(--ak-fw-regular)}
@media (pointer:coarse){
  .ak-tree__item,.ak-tree__toggle,.ak-tree__spacer{min-block-size:var(--ak-target-touch)}
  .ak-tree__toggle,.ak-tree__spacer{inline-size:var(--ak-target-touch)}
}
@media (forced-colors:active){
  .ak-tree__item[aria-current="true"]{forced-color-adjust:none;background:Highlight;color:HighlightText}
}
}

/* ---- 24.2 A tree beside its detail -----------------------------------
   .ak-grid--tree: the tree in a first column as wide as --ak-tree-w, what
   it shows in all the rest. Below 900px the two stack, the tree first. The
   override sits in the layout layer with the rule it overrides (1, rule 7). */
@layer layout {
.ak-grid--tree{grid-template-columns:min(var(--ak-tree-w),100%) minmax(0,1fr);align-items:start}
@media (max-width:900px){.ak-grid--tree{grid-template-columns:minmax(0,1fr)}}
}
@layer tokens {
:root{--ak-tree-w:15rem}
}

/* ===================================================================
   25 · PEOPLE AND THE LAUNCHER (2.20.0, Manav Wave 1)
   -------------------------------------------------------------------
   .ak-tiles--launcher  a grid of doors, an icon over a name (Darwinbox's
                        "My Access"); the icon is one ink, never colour
                        for its own sake (owner, 18 Oct 2026)
   .ak-person           initials, a name and one line under it: the
                        person in a table cell, a drawer, a chain
   .ak-initials         two letters in a circle that is not a button
                        (.ak-avatar, 19.11, is the button that opens a menu)
   dialog.ak-drawer     the drawer of 4.11 on a native <dialog>, and
                        --half, half the screen and never under a form's
                        width: Task Box's "Act" panel
   .ak-orgchain         a person and their managers, upward, joined by a
                        line; the person themself is aria-current
   .ak-moodpicker       five answers as large radio buttons, a face and a
                        word each: the Pulse check
   .ak-facts            labels and their values in two columns, every
                        value starting on one line (2.21.0): a record's
                        facts, a profile
   The approval flow is the activity timeline (4.12) with a status chip
   in each step: no new component.
   =================================================================== */
@layer components {
/* ---- 25.1 Launcher tiles -------------------------------------------- */
.ak-tiles--launcher{grid-template-columns:repeat(auto-fill,minmax(min(var(--ak-launcher-min),100%),1fr))}
.ak-tiles--launcher .ak-tile{align-items:center;text-align:center;gap:var(--ak-gap-inside);
  padding:var(--ak-s-4) var(--ak-s-3)}
.ak-tiles--launcher .ak-tile::before{background:var(--ak-action)}
.ak-tiles--launcher .ak-tile__name{font-size:var(--ak-fs-small)}
.ak-tile__icon{display:block;flex:0 0 auto;inline-size:var(--ak-s-8);block-size:var(--ak-s-8);
  color:var(--ak-skin-mark)}
.ak-tile__icon svg{display:block;inline-size:100%;block-size:100%}
.ak-tile__count{position:absolute;inset-block-start:var(--ak-s-2);inset-inline-end:var(--ak-s-2);
  min-inline-size:var(--ak-s-5);padding:0 var(--ak-s-1);border-radius:var(--ak-r-pill);
  background:var(--ak-action);color:var(--ak-on-fill);
  font-size:var(--ak-fs-micro);font-weight:var(--ak-fw-bold);line-height:var(--ak-s-5);
  font-variant-numeric:tabular-nums}

/* ---- 25.2 A person, and their initials ------------------------------ */
.ak-initials{display:inline-grid;place-items:center;flex:0 0 auto;
  inline-size:var(--ak-s-7);block-size:var(--ak-s-7);border-radius:50%;
  background:var(--ak-action-bg);color:var(--ak-action);
  font-size:var(--ak-fs-tiny);font-weight:var(--ak-fw-bold);line-height:1;letter-spacing:.02em}
.ak-initials--lg{inline-size:var(--ak-s-10);block-size:var(--ak-s-10);font-size:var(--ak-fs-h3)}
.ak-person{display:flex;align-items:center;gap:var(--ak-gap-inside);min-inline-size:0}
.ak-person__text{display:flex;flex-direction:column;min-inline-size:0}
.ak-person__name{font-weight:var(--ak-fw-semibold);color:var(--ak-ink);overflow-wrap:anywhere}
.ak-person__meta{font-size:var(--ak-fs-small);color:var(--ak-ink-muted);overflow-wrap:anywhere}

/* ---- 25.3 The drawer on a dialog ------------------------------------ */
dialog.ak-drawer{inset:0 0 0 auto;margin:0 0 0 auto;border:0;padding:0;
  inline-size:min(var(--ak-drawer-w),100%);block-size:100dvh;
  max-inline-size:100%;max-block-size:100dvh;color:var(--ak-ink)}
dialog.ak-drawer:not([open]){display:none}
dialog.ak-drawer::backdrop{background:var(--ak-overlay)}
.ak-drawer > form{display:flex;flex-direction:column;flex:1 1 auto;min-block-size:0;margin:0}
.ak-drawer .ak-modal__body{flex:1 1 auto;min-block-size:0}
dialog.ak-drawer--half{inline-size:clamp(min(var(--ak-drawer-w),100%),50vw,100%)}

/* ---- 25.4 Reporting chain ------------------------------------------- */
.ak-orgchain{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.ak-orgchain > li{position:relative;padding-block:var(--ak-s-2)}
.ak-orgchain > li + li::before{content:"";position:absolute;
  inset-inline-start:calc(var(--ak-s-7) / 2 - var(--ak-border) / 2);
  inset-block-start:calc(var(--ak-s-2) * -1);
  inline-size:var(--ak-border);block-size:calc(var(--ak-s-2) * 2);
  background:var(--ak-line-control)}
.ak-orgchain > li[aria-current="true"] .ak-initials{background:var(--ak-action);color:var(--ak-on-fill)}
.ak-orgchain > li[aria-current="true"] .ak-person__name{color:var(--ak-action)}

/* ---- 25.5 Mood picker ----------------------------------------------- */
.ak-moodpicker{display:grid;gap:var(--ak-gap-inside);margin:0;padding:0;border:0;min-inline-size:0;
  grid-template-columns:repeat(auto-fit,minmax(min(var(--ak-s-10),100%),1fr))}
.ak-moodpicker > legend{grid-column:1 / -1;padding:0;margin-block-end:var(--ak-gap-inside)}
.ak-mood{position:relative;display:flex;flex-direction:column;align-items:center;gap:var(--ak-s-1);
  min-block-size:var(--ak-target-touch);padding:var(--ak-s-2) var(--ak-s-1);
  border:var(--ak-border) solid var(--ak-line-control);border-radius:var(--ak-r-md);
  background:var(--ak-surface);color:var(--ak-ink-2);cursor:pointer;
  font-size:var(--ak-fs-small);line-height:var(--ak-lh-snug);text-align:center}
.ak-mood > input{position:absolute;inset:0;margin:0;opacity:0;cursor:pointer}
.ak-mood__face{display:block;inline-size:var(--ak-s-7);block-size:var(--ak-s-7);color:var(--ak-ink-muted)}
.ak-mood:hover{border-color:var(--ak-line-control-hover)}
.ak-mood:has(> input:checked){border-color:var(--ak-action);border-width:2px;
  padding:calc(var(--ak-s-2) - var(--ak-border)) calc(var(--ak-s-1) - var(--ak-border));
  background:var(--ak-action-bg);color:var(--ak-ink);font-weight:var(--ak-fw-semibold)}
.ak-mood:has(> input:checked) .ak-mood__face{color:var(--ak-action)}
.ak-mood:has(> input:focus-visible){outline:var(--ak-focus-w) solid var(--ak-focus);outline-offset:2px}
/* ---- 25.7 Facts: labels and their values (2.21.0) ------------------ */
.ak-facts{display:grid;grid-template-columns:fit-content(40%) minmax(0,1fr);
  column-gap:var(--ak-gap-between);row-gap:var(--ak-gap-inside);margin:0}
.ak-facts > div{display:grid;grid-column:1 / -1;grid-template-columns:subgrid;align-items:baseline}
.ak-facts dt{color:var(--ak-ink-muted)}
.ak-facts dd{margin:0;min-inline-size:0;overflow-wrap:anywhere}
@media (max-width:640px){
  .ak-facts{grid-template-columns:minmax(0,1fr)}
  .ak-facts > div{display:flex;flex-direction:column;gap:var(--ak-s-1)}
}
@media (forced-colors:active){
  .ak-mood:has(> input:checked){border-color:Highlight}
  .ak-orgchain > li + li::before{background:CanvasText}
}
}

/* ---- 25.6 The rail in the Manav skin (2.20.1) -----------------------
   The rail is layout (3.1), so its override is too (CLAUDE.md §1, rule 6).
   Group names and counts take full ink on the Manav blue: at 3.1's .72
   and .8 opacity they measure 3.37:1 and 3.80:1. */
@layer layout {
[data-skin="manav"] .ak-rail__group,
[data-skin="manav"] .ak-rail__count{opacity:1}
}

