/* Kin OS — reusable interface patterns.
 *
 * These are the primitives every module reuses: page headers, cards, tables, forms, buttons,
 * status treatment, and the loading / empty / error states. They are brand-agnostic — every
 * colour comes from a --brand-*, --paper-* or --status-* token — so a new module inherits the
 * whole system and correct white-labelling by using the class names, without touching CSS.
 *
 * P7.1 structural rule: not everything is a card. Page headers, section headings, fact rows
 * and the hero sit directly on the pearl ground, structured by spacing and type. A card is
 * reserved for genuinely bounded working surfaces — a table, a form, a record — and carries a
 * soft shadow and hairline, never a heavy frame.
 */

/* ---- Wordmark --------------------------------------------------------------------------
 * Three treatments, chosen by the brand authority rather than by taste. See
 * KinOS.Application.Workspaces.WordmarkSource for why a brand whose logotype cannot honestly
 * be re-typeset gets the plain treatment instead of an imitation. */

.kin-wordmark {
    display: inline-flex;
    align-items: baseline;
    gap: 0;
    font-family: var(--brand-wordmark-font, var(--brand-font));
    letter-spacing: var(--brand-wordmark-tracking, 0);
    text-transform: var(--brand-wordmark-transform, none);
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
}

/* The wordmark carries its own data-workspace so it is correct outside its own workspace —
   the four rows of the selector are the case that matters.
 *
 * On a light ground it takes its OWN brand's ink. On a dark ground it is the official
 * reversed treatment — one colour, no accent half: white, or Sandstone for TalentSmith
 * (P7.2 §14). */
.kin-wordmark[data-workspace] { color: var(--brand-ink); }
.kin-wordmark[data-workspace].kin-wordmark-on-dark { color: inherit; }

.kin-wordmark-a {
    font-weight: var(--brand-wordmark-weight-a);
    font-style: var(--brand-wordmark-style-a, normal);
}

.kin-wordmark-b { font-weight: var(--brand-wordmark-weight-b); }

/* CapacityCo's mark is two words; the gap lives on the tail so tracking stays intact. */
.kin-wordmark[data-workspace="capacityco"] .kin-wordmark-b { margin-left: 0.28em; }

/* Marks whose guideline colours part of the construction (TalentCorp's slate `Corp`) take the
   accent on light grounds only — the component decides and passes it down. */
.kin-wordmark .kin-wordmark-b { color: var(--wordmark-accent, inherit); }

.kin-wordmark img { display: block; height: 100%; width: auto; }

.kin-wordmark-lg { font-size: 2rem; }
.kin-wordmark-md { font-size: 1.25rem; }
.kin-wordmark-sm { font-size: 1rem; }

/* ---- The brand highlighter ----------------------------------------------------------------
 * Each brand's own documented ground+ink pairing, used as a highlighter strip on display
 * text: Basalt on Fresh Lime, Navy on Signal Yellow, Deep Navy on Warm Sand, Midnight on
 * Sunset Coral. One Kin OS device, four approved voices — and the only way an accent like
 * lime ever meets a light page.
 *
 * The face follows the brand too: HelloKindred and TalentSmith both document Georgia Bold
 * Italic as the emphasis accent inside a headline — which is exactly this role — so their
 * highlighted phrase is set in it. TalentCorp and CapacityCo have no accent face, and their
 * tokens resolve to the brand font with no slant.
 *
 * The STRIP LEANS, and its edges are straight (P7.5). The HelloKindred guideline is specific
 * about the device — "The strip must resemble highlighter that has a slight slant" (§1.8.2) —
 * and a rounded rectangle is not that however it is tilted. P7.4 read "slant" as texture and
 * painted the accent through a wobbling SVG mask; seen on a real screen that was a smudge, not
 * a highlighter. What a marker held at an angle actually lays down is a parallelogram: clean
 * parallel edges, the whole block leaning. So the strip is skewed and the mask is gone.
 *
 * The word itself stays upright and crisp on top, unless the brand documents a slanted accent
 * face — that is --brand-hi-slant, and it is a separate thing from the strip's lean. */
.kin-hi {
    position: relative;
    z-index: 0;
    color: var(--brand-hi-ink);
    font-family: var(--brand-font-accent);
    font-style: var(--brand-hi-slant, normal);
    font-weight: var(--weight-bold);
    /* The stroke needs clear air on BOTH sides. It used to sit on a negative margin whose
       ::before then over-hung it further, so the block crowded the word before it and ran
       under the full stop after it (P7.5). */
    padding: 0.06em 0.24em;
    margin: 0 0.1em;
    box-decoration-break: clone;
    -webkit-box-decoration-break: clone;
}

/* A straight-edged highlighter, skewed rather than painted (P7.5, replacing the P7.4 brush
   mask): the edges stay clean and parallel and the whole block leans, the way a marker held
   at an angle lays down a parallelogram. The documented per-brand slant on the WORD itself is
   a separate thing — see --brand-hi-slant. */
.kin-hi::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: var(--brand-hi-bg);
    transform: skewX(-7deg);
}

/* ---- Page header — on the ground, not in a box --------------------------------------------- */

.kin-page-head {
    padding-top: var(--space-4);
    margin-bottom: var(--space-6);
}

/* The identity and the tools on one row, the tools top-aligned with the title's line. */
.kin-page-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-5);
    flex-wrap: wrap;
}

/* The title, its reference and what is true about it, on one line that wraps as whole pieces. */
.kin-page-titleline {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    margin-bottom: var(--space-2);
}

.kin-page-titleline > h1 { margin: 0; }

/* WHERE THE RECORD BELONGS, LABELLED (P40-107 rework). Label and value inline, with space rather
   than a glyph between items, wrapping as whole pairs; no container-type, so nothing here can be
   sized to zero by its contents. */
.kin-page-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-1) var(--space-5);
    margin: 0;
    font-size: var(--text-base);
}

.kin-page-meta-item {
    display: inline-flex;
    align-items: baseline;
    gap: var(--space-2);
    min-width: 0;
}

/* The same label-and-value voice as a fact (.kin-fact dt/dd): the strong name, the plain value
   (QCR-20261104-01.01). */
.kin-page-meta-item > dt {
    font-weight: var(--weight-semibold);
    color: var(--brand-ink);
    white-space: nowrap;
}

.kin-page-meta-item > dd {
    margin: 0;
    color: var(--brand-ink);
    font-weight: var(--weight-regular);
    overflow-wrap: anywhere;
}

.kin-page-meta + .kin-page-lede { margin-top: var(--space-2); }

/* ---- Summary strip (P40-107 rework, Jakes 652889824) -----------------------------------------

   THE FIGURES A RECORD ALREADY COMPUTES, LIFTED UNDER ITS HEAD. Small cards sized to their figure
   rather than stretched, so a wide screen keeps the strip compact and leaves the rest of the row
   empty, as the operational reference does. A figure never truncates. On a phone the strip becomes
   one bordered list, label left and figure right. */
.kin-page-head:has(+ .kin-summary) { margin-bottom: var(--space-4); }

.kin-summary {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin: 0 0 var(--space-5);
}

.kin-summary-item {
    flex: 0 0 auto;
    min-width: 11rem;
    padding: var(--space-3) var(--space-4);
    background: var(--brand-surface);
    border: 1px solid var(--brand-line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

/* The strong name over the plain figure, as every label and value reads (QCR-20261104-01.01).
   The figure keeps its larger size, which is what lifts it; it no longer also takes the weight. */
.kin-summary-item > dt {
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    color: var(--brand-ink);
    margin-bottom: var(--space-1);
}

.kin-summary-figure {
    margin: 0;
    font-size: var(--text-lg);
    font-weight: var(--weight-regular);
    line-height: var(--leading-tight);
    color: var(--brand-ink);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.kin-summary-note {
    margin: var(--space-1) 0 0;
    font-size: var(--text-xs);
    color: var(--brand-muted);
}

@media (max-width: 560px) {
    .kin-summary {
        flex-direction: column;
        gap: 0;
        background: var(--brand-surface);
        border: 1px solid var(--brand-line);
        border-radius: var(--radius-lg);
    }

    .kin-summary-item {
        display: grid;
        grid-template-columns: 1fr auto;
        column-gap: var(--space-3);
        align-items: baseline;
        min-width: 0;
        padding: var(--space-2) var(--space-3);
        border: 0;
        border-radius: 0;
        box-shadow: none;
    }

    .kin-summary-item + .kin-summary-item { border-top: 1px solid var(--brand-line); }
    .kin-summary-item > dt { margin: 0; }
    .kin-summary-figure { font-size: var(--text-md); text-align: right; }
    .kin-summary-note { grid-column: 1 / -1; text-align: right; }
}

/* The record's durable reference, on the title's line (P40-107 rule 1). Set in the monospace a
   code is set in everywhere else and framed by the strong line, so it reads as the thing people
   quote rather than as part of the name; never a GUID (DEC-P40-004). It wraps under the title
   as one piece on a narrow screen. */
.kin-page-ref {
    display: inline-block;
    vertical-align: 0.2em;
    margin-left: var(--space-2);
    padding: 0.05rem 0.5rem;
    border: 1px solid var(--brand-line-strong);
    border-radius: var(--radius-sm);
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    background: var(--brand-surface);
    white-space: nowrap;
}

/* THE TITLE IS THE ANCHOR AND THE LEDE IS NOT (DEC-P40-004). A lede is now at most one
   orientation sentence, set a step smaller than body text so the eye lands on the title, the
   status and the primary action first. Weight cannot carry the title any further: the packaged
   faces have no 600, so the title's semibold already renders at 700. Space and a quieter lede are
   what is left, and they are what this uses. */
.kin-page-lede {
    color: var(--brand-muted);
    font-size: var(--text-sm);
    max-width: 64ch;
    margin: 0;
}

/* The way to the deeper explanation, in Definitions and glossary. Quiet by design: present for
   the reader who wants it, and never a rival to the page's own action. */
.kin-page-learn {
    display: inline-flex;
    align-items: center;
    gap: 0.35em;
    margin-top: var(--space-2);
    font-size: var(--text-xs);
    color: var(--brand-muted);
    transition: color var(--motion-fast) var(--ease);
}

.kin-page-learn:hover,
.kin-page-learn:focus-visible { color: var(--brand-ink); }

/* THE PAGE OPENS IN ONE ORDER, EVERYWHERE (P19-102).
 *
 * What this is, then what is true about it, then what you can do about it. The two halves were
 * hand-written on all 13 detail pages and had drifted where it shows most: CurrencyDetail read
 * pill-then-Edit and RoleDetail read Edit-then-pill. KinPageHead settles it.
 *
 * THE STATUS NOW SITS ON THE TITLE'S LINE (P40-107 rework). The order stands; the pill moved out
 * of the tools group, which holds only actions, so the pill and the buttons can no longer wrap
 * independently and swap places - the defect this group was written to prevent. The tools group
 * is at least one title line tall, so a button centres on the h1 rather than on the row. */
.kin-page-identity { min-width: 0; }

.kin-page-tools {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
    min-height: calc(var(--text-xl) * var(--leading-tight));
}

.kin-page-status {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.kin-eyebrow {
    display: block;
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--brand-accent-ink);
    margin-bottom: var(--space-2);
}

/* The way out of a detail screen (P8.2 §8.2.8).
   Above the page head, not inside it, so it never competes with the record's own title for the
   reader's first glance — and phrased as an action rather than a location, because the top bar
   already says where you are and a detail page needs somewhere to go. Deliberately not styled
   as a button: it is navigation, and a primary-looking control here would draw the eye away
   from what the page is actually for. */
.kin-back {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding-top: var(--space-4);
    font-size: var(--text-sm);
    color: var(--brand-muted);
    transition: color var(--motion-fast) var(--ease);
}

.kin-back:hover { color: var(--brand-ink); }

/* The arrow leads and the words follow it, which is why the icon shifts and the text does not. */
.kin-back svg { transition: transform var(--motion-fast) var(--ease); }
.kin-back:hover svg { transform: translateX(-2px); }

/* A page head that follows a back link has already had its top padding paid for. */
.kin-back + .kin-page-head { padding-top: var(--space-3); }

/* A quiet section divider: heading + hairline, replacing a boxed card head where the content
   below is not itself a card. */
.kin-section {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    margin: var(--space-7) 0 var(--space-4);
    padding-bottom: var(--space-2);
    border-bottom: 1px solid var(--brand-line);
}

/* A step up from the base h2, so a section reads as the next level below the page title and
   above the cards inside it, with more space before it to mark where one part of the page ends
   (DEC-P40-004). Card titles keep the base size — they sit inside a section, not beside one. */
.kin-section h2 { margin: 0; font-size: var(--text-lg); }
.kin-section .kin-muted { font-size: var(--text-sm); }

/* The index onto a long single-route page (.kin-jump, P25-202) was here and is gone with the
   page it indexed. P25-305 rejected that treatment at rendered acceptance: an index over four
   stacked registers is still four stacked registers, and Jakes did not want the model even
   repaired. The four registers are four addresses now and the shell's third rail navigates
   them (DEC-UX-003, STD-04), so there is no page left with an index on it.

   Recorded rather than deleted silently, because the next reader who wants an in-page index
   should know one existed, was built carefully, and lost to the thing it was indexing. */

/* ---- Surfaces ------------------------------------------------------------------------------
 *
 * THE CARD ANATOMY, and there is exactly one (final close-out §20, §21).
 *
 *     .kin-card              the bounded white work surface
 *       .kin-card-head       title, optional subtitle, optional contextual action, including the
 *                            Add that opens the card's own editor (P40-107)
 *       .kin-card-body       the fields or data
 *       .kin-card-foot       optional business guidance, recessed, and the commit of the card's
 *                            own open editor
 *
 * ONE INSET FOR ALL THREE PARTS. They used to disagree: head 0.75/1rem, body 1rem top and
 * 1.5rem bottom, foot 0.75/1rem, .kin-panel 1rem uniform, .kin-disclose summary 1rem. Five
 * variants of the same idea, so a heading and the fields beneath it did not share a left edge
 * and no two cards agreed on their vertical rhythm. --card-inset is now the single value and
 * every part takes it, which is what makes a section recognisable as the same structure on
 * Company, Person, Work Agreement, Engagement, Tax and Settings.
 *
 * The head keeps a smaller VERTICAL inset than the body on purpose — a title bar reads as a bar
 * — but it shares the horizontal one, which is the part the eye actually lines up. */

/* One card surface, shared rather than copied: a group drawn as a card while its section is read
   (.kin-fact-cards below, P40-107) takes the same surface as every other card. */
.kin-card,
.kin-fact-cards .kin-fact-group {
    background: var(--brand-surface);
    border: 1px solid var(--brand-line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

.kin-card { margin-bottom: var(--space-4); }

/* DELIBERATE WHITESPACE BETWEEN SECTIONS (P40-107 rework): stacked cards and fact-card sections
   sit 24px apart, the gap the references keep between titled sections. Declared before
   .kin-card > .kin-card so a nested card keeps its inset margin by order. */
:is(.kin-card, .kin-fact-cards):has(+ :is(.kin-card, .kin-fact-cards)) { margin-bottom: var(--space-5); }

/* ONE HEAD HEIGHT (P40-107 rework). A head with a small tool and one without are the same 52px, so
   stacked cards have even title bars. The head's count (.kin-count) sits beside the title and
   pushes any tool to the right edge. */
.kin-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    min-height: 3.25rem;
    padding: var(--space-3) var(--card-inset);
    border-bottom: 1px solid var(--brand-line-strong);
    /* THE TITLE OWNS ITS SECTION (P40-107/108, Jakes 13 Oct 2026: "SECTION TITLES MUST CORDON OFF
       THEIR SECTION"). A white title bar on a white card left a 13% hairline to say where a
       section began. The head is now its own band, and its corners follow the card's. */
    background: var(--brand-head);
    border-radius: calc(var(--radius-lg) - 1px) calc(var(--radius-lg) - 1px) 0 0;
}

/* A card that is only its head (a section with nothing yet but its opener, P40-108) has no body
   for the rule to separate it from, so the head takes the card's whole shape. */
.kin-card > .kin-card-head:last-child {
    border-bottom: 0;
    border-radius: calc(var(--radius-lg) - 1px);
}

.kin-card-head > .kin-count { margin-right: auto; }

.kin-card-head h2, .kin-card-head h3 { margin: 0; }

.kin-card-head h2 { font-weight: var(--weight-bold); }

/* A CARD'S TITLE LEADS THE LABELS INSIDE IT (QCR-20261104-01.01, Jakes's third round). Field
   labels are --text-md, so a card title, h2 or h3, is one step above them. */
.kin-card-head :is(h2, h3) { font-size: var(--text-title); }

/* THE SUBTITLE GOES UNDER THE TITLE WHEREVER IT IS WRITTEN, not only where the markup was
 * converted (P15 §design-system-consistency#8).
 *
 * §22 below records the decision and supplies .kin-card-head-text for it, and five cards use
 * that structure. Forty-one card heads still write the subtitle as a plain sibling of the h2 —
 * and a plain sibling in a space-between row is pushed into the gap between the heading and the
 * action, which is precisely the placement Jakes objected to. Sweeping forty-one files would
 * have produced the same pixels and forty-one chances to mistype one, so the rule does it: a
 * full-width flex basis makes the subtitle take its own line, and the order keeps the card's
 * action beside the title where it was.
 *
 * Reading order is untouched — the DOM still says title, subtitle, action — and the converted
 * five are unaffected, their subtitle being inside .kin-card-head-text rather than beside the
 * heading. */
.kin-card-head > :is(h2, h3) + .kin-muted.kin-small {
    order: 1;
    flex: 1 0 100%;
    min-width: 0;
}

/* The head's 16px gap is the space between a title and an ACTION. Between a title and the line
   explaining it, the four pixels .kin-card-head-text already uses. */
.kin-card-head:has(> :is(h2, h3) + .kin-muted.kin-small) { row-gap: var(--space-1); }

/* A card head is a title, an optional line saying what the card is for, and an optional action.
 * The subtitle belongs UNDER the title rather than beside it (§22): floating explanatory text in
 * the gap between a heading and an action is the placement Jakes objected to, and it is also the
 * first thing to wrap badly on a narrow screen. */
.kin-card-head-text {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-width: 0;
}

.kin-card-head-text .kin-card-sub {
    font-size: var(--text-sm);
    font-weight: var(--weight-regular);
    color: var(--brand-muted);
    text-transform: none;
    letter-spacing: 0;
}

.kin-card-body { padding: var(--card-inset); }
.kin-card-body > :last-child { margin-bottom: 0; }

.kin-card-foot {
    padding: var(--space-3) var(--card-inset);
    border-top: 1px solid var(--brand-line);
    background: var(--brand-soft);
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
    font-size: var(--text-sm);
    color: var(--brand-muted);
}

/* THE FLUSH-FIELD DEFECT, fixed structurally rather than card by card (§21).
 *
 * Jakes reported Date of Birth sitting too close to the edge of its container while the
 * Engagement section had healthier spacing. Neither card was tuned wrongly — .kin-card declares
 * no padding and .kin-form-grid declares only a gap, so wherever a form grid is a DIRECT child
 * of a card its outer fields press against the 1px border and its labels do not line up with the
 * card title an inch above. Twelve places in the product do exactly that, which is why it looked
 * arbitrary: the cards that felt right were the ones that happened to wrap their grid in a body.
 *
 * So a card insets its own direct content whatever it is, and a .kin-card-body inside one is
 * simply the explicit form of the same thing.
 *
 * THAT SENTENCE WAS THE RULE, AND FOR THREE PROMPTS IT WAS NOT THE CODE (P19-201).
 *
 * It was a list of the six children somebody had remembered, so it stated the rule for those six
 * and stayed silent about everything else. A list cannot fail loudly: markup that is not on it
 * does not break, it simply sits against the border, on one screen, looking like that screen was
 * laid out badly. Three prompts each paid the same toll. P15 added .kin-detail-grid and found
 * seventeen cards that had been shifting sideways on every Edit and back on every Cancel. P13.1
 * could not name a shared class at all and added a seventh entry from hr.css. P19-101 measured
 * five more sites still outside it.
 *
 * THE COLLAPSIBLE CARD ALREADY HAD THE ANSWER. `.kin-disclose > *:not(summary)` insets whatever
 * it is given, and its comment records that it was written for this same defect "in the one
 * variant that hides until you open it". So Kin OS had two kinds of card, one rule and two
 * mechanisms - and the one that fails silently was the one on every other screen.
 *
 * INVERTED. A card insets every direct child, and the exceptions are named. That is a shorter
 * thing to be right about: an exception has to be argued for and each one below carries its own
 * padding, whereas an omission from a list argued for nothing. New markup is now inset by
 * default, which is the behaviour every one of those three fixes was reaching for.
 *
 * The exceptions are the parts of the anatomy that pad themselves - head, body, foot and the
 * disclosure's summary - and the table, which is the one thing that should reach the card's edges
 * because its own cells carry the inset and a scroll container inside a padded box clips at the
 * wrong place. CardInsetTests checks that every name here really does. */
.kin-card > :not(.kin-card-head):not(.kin-card-body):not(.kin-card-foot):not(.kin-table-wrap):not(summary):not(.kin-fieldset):not(.kin-panel):not(.kin-card):not(.kin-dialog) {
    padding: var(--card-inset);
}

/* A CHILD THAT CARRIES ITS OWN FRAME TAKES THE INSET AS MARGIN, so the inset falls outside the
 * frame instead of inside it. Padding a bordered box moves its contents and leaves the border
 * where it was, one pixel inside the card's own - measured on a Role with eleven stacked
 * fieldsets as two hairlines a pixel apart down both edges, which reads as a rendering fault.
 *
 * This generalises the rule .kin-disclose already had for fieldsets. A .kin-panel and a card
 * nested in a card are the same shape of thing and were both sitting flush. */
.kin-card > .kin-fieldset,
.kin-card > .kin-panel,
.kin-card > .kin-card {
    margin: var(--card-inset);
}

.kin-card > .kin-table-wrap { padding: 0; }

.kin-panel {
    background: var(--brand-soft);
    border: 1px solid var(--brand-line);
    border-radius: var(--radius);
    padding: var(--card-inset);
    margin: var(--space-3) 0;
}

.kin-panel-title {
    font-weight: var(--weight-semibold);
    margin-bottom: var(--space-3);
}

/* ---- Text ----------------------------------------------------------------------------------- */

.kin-muted { color: var(--brand-muted); }
.kin-small { font-size: var(--text-sm); }
.kin-xs { font-size: var(--text-xs); }
.kin-strong { font-weight: var(--weight-semibold); }
.kin-nowrap { white-space: nowrap; }
.kin-num { font-variant-numeric: tabular-nums; }

/* A single-glyph column: a mark that is either there or not.
   Narrow and centred, so the eye reads the pattern down the column rather than the cell. */
.kin-table-mark {
    width: 1.75rem;
    padding-right: 0 !important;
    text-align: center;
    vertical-align: middle;
}

/* The favourite star.
   Ink rather than the accent. Two of the four brand accents are bright enough that a small
   filled glyph in them all but disappears on a white table, and the mark has to be legible in
   every workspace or it is worse than nothing. Filled-versus-absent already carries the
   meaning; colour would only be decoration. */
.kin-favourite {
    display: inline-flex;
    color: var(--brand-ink);
    line-height: 0;
}

/* Facts laid out as label-over-value, directly on the ground. */
.kin-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--space-4);
    margin: 0;
}

/* A grid item will not shrink below its longest word unless it is told it may, and one of these
   values is a .NET category like Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer,
   which a browser treats as a single unbreakable word. Without both of these the track blows
   past its share and the value runs over the fact beside it — reported against the Diagnostics
   event detail on 4 September 2026, where Category, Event id and Correlation id overlapped.
   `anywhere` rather than `break-word` because only `anywhere` also shrinks the minimum the grid
   sizes the track from; `break-word` wraps the text and leaves the column just as wide. */
.kin-fact { min-width: 0; }

/* A FACT THAT IS A RECORD'S NAME AND ITS LINKS TAKES THE WHOLE ROW (P40-117 cross-slice review).
   The equal tracks above suit a date or a name; the Audit Trail detail's Record and Belongs to hold
   a record's whole name and up to three links, and in one track they broke "View the Role's own
   history" over three lines and an Engagement's name over five. */
.kin-facts > .kin-fact-full { grid-column: 1 / -1; }

/* ONE LABEL AND ONE VALUE, WHICHEVER MARKUP CARRIES THEM (P40-107 rule 3). Kin OS writes a fact
   two ways - a dt/dd pair here and .kin-detail-label/.kin-detail-value below - and the two had
   drifted to different spacing and tracking, so the same kind of fact looked different on the
   Person page and the Currency page.

   THE LABEL IS WHAT THE EYE LOOKS FOR, AND THE VALUE IS READ BESIDE IT (QCR-20261104-01.01,
   Jakes 4 Nov 2026). A reader scans for the field they want - a telephone number, say - and a
   bold value pulls the eye to whatever is boldest, so an ID number can be read before anyone
   knows it is one. The label is therefore the sentence-case name in the ink at semibold, and the
   value the ink at regular weight. This reverses the 13 Oct 2026 direction (P40-107/108: muted
   label, semibold value) at Jakes's request. Both stay sentence case: the label does not shout in
   small capitals as it did before 13 Oct.

   ONE ORDER OF SIZE, LARGEST FIRST (QCR-20261104-01.01, Jakes's second and third rounds): a box's
   title (--text-title, 19px), then the label one step below it (17px), then the value at the body
   size (15px). So the eye meets the title, then the name of the field, then its answer, and every
   value on every page is the same size. The second round set values at 13px and Jakes found them
   too small, so the whole order moved up one step. A value does not ask for a size of its own. */
.kin-fact dt,
.kin-detail-label {
    display: block;
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    letter-spacing: 0;
    text-transform: none;
    color: var(--brand-ink);
    margin-bottom: var(--space-1);
}

/* Zero specificity on purpose: a value that asks for .kin-mono or .kin-muted still gets it, as it
   did before the two patterns were joined. */
:where(.kin-fact dd, .kin-detail-value) {
    display: block;
    margin: 0;
    font-size: var(--text-base);
    font-weight: var(--weight-regular);
    color: var(--brand-ink);
    overflow-wrap: anywhere;
}

/* A SYSTEM CODE - an employee number, an Organization's or Business Unit's code, a currency's
   ISO code - is set in the monospace face, regular and at the value's size; the face is the only
   thing that sets it apart (QCR-20261104-01.03, Jakes: "only codes should have a different font,
   but same size"). An identity number, a tax or registration number, a login, an account number
   is a value, not a code, and carries no kin-mono at all (Jakes's third round). */
:where(.kin-fact dd, .kin-detail-value) .kin-mono {
    font-weight: var(--weight-regular);
    font-size: var(--mono-match);
}

/* A value that is itself the code element takes the value size by name rather than an em of the
   element around it. */
.kin-fact dd.kin-mono,
.kin-detail-value.kin-mono {
    font-weight: var(--weight-regular);
    font-size: var(--text-base);
}

/* ---- Fact groups (P40-107 rule 2) ----------------------------------------------------------

   RELATED FACTS READ AS ONE GROUP, AND UNRELATED ONES SEPARATE. A record with twenty facts in
   one grid made a reader find the passport among the email addresses. A group is a short heading
   over its own grid: the heading is stronger than a fact's label and weaker than the card's
   title, and the space between groups is larger than the space inside one, which is what makes
   them read as groups without a box or a line around each. */
.kin-fact-groups {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
}

/* Two blocks of groups in one card - Person writes its name and contact apart from the personal
   detail, because each is gated on its own permission - still read as one run of groups: the
   second block starts one group-gap below the first rather than two card insets. Margin, not
   padding: the card's inset rule outranks any selector here on padding, and the two insets it
   leaves between the blocks are what this takes back. */
.kin-card > .kin-fact-groups + .kin-fact-groups {
    margin-top: calc(var(--space-5) - 2 * var(--card-inset));
}

/* A SUMMARY FIGURE THE RECORD ALREADY HAS - a total, a bill rate, a margin - reads first among
   its neighbours (rule 6). A step up in size and weight, not a colour: nothing here is a warning,
   and nothing new is calculated. */
.kin-fact-total :where(.kin-detail-value, dd) {
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
}

/* ONE COLUMN RHYTHM DOWN THE WHOLE CARD. auto-fit stretches a three-fact group across the width
   a six-fact group shares out, so the columns of Name and Identity documents start at different
   places and the eye cannot run down them. auto-fill keeps the empty tracks, so every group in a
   card lays its facts on the same columns. */
.kin-fact-group > :is(.kin-facts, .kin-detail-grid, .kin-person-facts) {
    grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
}

/* hr.css lets a wide fact fall back to one column below 276px, which is two of ITS 130px tracks
   and a gap. In a group the tracks are 170px, so one column starts below 356px, and a two-track
   span there would force an implicit column and squeeze the facts after it. */
@container (width < 356px) {
    .kin-fact-group > .kin-person-facts > .kin-fact-wide { grid-column: auto; }
}

/* The heading is the h3 base size (15px semibold): clearly above the 11.5px small-capital label
   and one step below the 17px card title. At 13px it was barely stronger than the labels under
   it, and the hairline led the eye more than the group's name did (P40-107, Jakes 652879274). */
.kin-fact-group > h3 {
    font-size: var(--text-title);
    font-weight: var(--weight-semibold);
    color: var(--brand-ink);
    padding-bottom: var(--space-2);
    margin-bottom: var(--space-3);
    border-bottom: 1px solid var(--brand-line);
}

/* ---- Fact cards (P40-107 rule 2, read mode) ---------------------------------------------------

   A SECTION BEING READ DRAWS EACH GROUP AS ITS OWN CARD. Inside an ordinary card, groups read as
   groups by heading and space alone. A section that is nothing but groups - Person's Basic
   Information - reads better the way the reference draws it: a section title over titled cards,
   two to a row where there is room. The page switches the wrapper's class between kin-card
   (editing: the one form card it always was) and kin-fact-cards (reading), so nothing inside
   moves and no gate changes.

   AT MOST TWO COLUMNS, one below about 976px of content: each track is at least half the width
   less the gap, and never under 30rem.

   display: contents only on the role-less div.kin-fact-groups, so the two permission blocks Person
   writes feed one grid while the labelled sections stay landmarks.

   The head and the foot keep their literal classes - ContentDensityTests reads the privacy prose
   from a literal kin-card-foot - and only the padding, border, background and radius a card
   would add are taken back here.

   A group left alone in the last row spans it. That relies on DOM position inside each block:
   Name and Contact always render as a pair, so Address spans for a full reader, Identity
   documents for a reader of the tax identifier only, and Personal pairs with Address for a reader
   of the personal detail only. */
.kin-fact-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, max(30rem, calc((100% - var(--space-4)) / 2))), 1fr));
    gap: var(--space-4);
    margin-bottom: var(--space-4);
}

.kin-fact-cards > .kin-fact-groups { display: contents; }
.kin-fact-cards > :not(.kin-fact-groups) { grid-column: 1 / -1; }
.kin-fact-cards > .kin-card-head { padding: 0; border-bottom: 0; min-height: 0; background: none; border-radius: 0; }
.kin-fact-cards > .kin-card-foot { padding: 0; border-top: 0; background: none; border-radius: 0; }
.kin-fact-cards .kin-fact-group { min-width: 0; }
.kin-fact-cards .kin-fact-group:last-child:nth-child(odd) { grid-column: 1 / -1; }

/* The group's title is the card's head band: same insets, band and rule as .kin-card-head, and
   the same title weight, so a group card and any other card announce themselves alike. */
.kin-fact-cards .kin-fact-group > h3 {
    margin: 0;
    padding: var(--space-3) var(--card-inset);
    border-bottom: 1px solid var(--brand-line-strong);
    background: var(--brand-head);
    border-radius: calc(var(--radius-lg) - 1px) calc(var(--radius-lg) - 1px) 0 0;
    font-size: var(--text-title);
    font-weight: var(--weight-bold);
}

/* 13rem tracks: an email address or a date of birth with the age beside it stays on one line. */
.kin-fact-cards .kin-fact-group > :is(.kin-facts, .kin-detail-grid, .kin-person-facts) {
    padding: var(--card-inset);
    grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
}

/* Two 13rem tracks and the 1rem gap: below that a wide fact takes one column, not an implicit
   second track that squeezes the facts after it. */
@container (width < 27rem) {
    .kin-fact-cards .kin-fact-group > .kin-person-facts > .kin-fact-wide { grid-column: auto; }
}

/* ---- Search ----------------------------------------------------------------------------------- */

/* A PREFERRED WIDTH, STATED AS A WIDTH (D4, P23-204).
 *
 * This said `flex: 1 1 320px`, which reads as "320px wide, may grow, may shrink" and is exactly
 * that in the card head this control was written for. `flex-basis` is a length on the flex
 * container's MAIN axis, though, and the time zone picker stacks its search above its list in a
 * `column` container — where the main axis is vertical and 320px is therefore a HEIGHT. The
 * search box on City edit was laying out 320px tall with the field's own control floating in the
 * middle of it, which is the excessive whitespace Jakes reported around the time zone control.
 *
 * `flex-basis: auto` with an explicit `width` is the same thing in a row and harmless in a
 * column: the base size comes from the width in one and from the content in the other. The
 * max-width is what lets it sit in a form field's grid track, which is narrower than 320px on a
 * two-column form. */
.kin-search {
    position: relative;
    flex: 1 1 auto;
    width: 320px;
    max-width: 100%;
    min-width: 220px;
    display: flex;
    align-items: center;
}

.kin-search svg {
    position: absolute;
    left: var(--space-3);
    color: var(--brand-muted);
    pointer-events: none;
}

.kin-search input {
    width: 100%;
    /* The token, not the literal it happened to equal. The filter select beside this in a card
       head states the same token, which is what keeps the two boxes the same height. */
    padding: var(--space-2) var(--space-3) var(--space-2) var(--search-icon-space);
    border: 1px solid var(--brand-control-line);
    border-radius: var(--radius);
    background: var(--brand-surface);
    /* The box paints its own ground, so it states its own ink. base.css lets every input inherit
       its colour, which is right on a card and wrong in the dark top bar: there the Global Search
       box inherited the bar's light rail ink and typed text came out white on white (Bugs
       3251338821). */
    color: var(--brand-ink);
    transition: border-color var(--motion-fast) var(--ease), box-shadow var(--motion-fast) var(--ease);
}

.kin-search input:focus {
    border-color: var(--brand-focus);
    outline-offset: 0;
}

/* The clear control (P18-102). It sits inside the box on the right, and it only exists while
   there is something to clear — KinSearch does not render it for an empty box, because a control
   that does nothing reads as though the list is already filtered.

   The right padding is on the input rather than the button so the caret and the text never run
   underneath the cross. The native cross that some browsers add to type="search" is suppressed:
   two clear controls a few pixels apart, one of them unstyled and one of them not present in
   every browser, is worse than either alone. */
.kin-search input { padding-right: var(--search-icon-space); }

.kin-search input::-webkit-search-cancel-button { display: none; }

.kin-search-clear {
    position: absolute;
    right: var(--space-2);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-1);
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--brand-muted);
    cursor: pointer;
    line-height: 0;
    transition: color var(--motion-fast) var(--ease), background var(--motion-fast) var(--ease);
}

.kin-search-clear:hover {
    color: var(--brand-ink);
    background: var(--brand-hover);
}

/* How narrowed a register is, and the one way back (P18-103). Sits in the card head beside the
   search and the filter pickers, and is absent entirely when nothing is filtered — so the head
   does not carry a permanently disabled-looking control. The gap matches the head's own, and
   `margin-left: auto` pushes it to the far end so the count reads as a summary of the controls
   before it rather than as another one of them. */
.kin-filter-state {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-left: auto;
}

/* Choosing which optional columns a wide register draws (P18-105). A details/summary, so it
   needs no JavaScript, works from the keyboard for free, and closes the way a reader expects.
   The panel is positioned rather than in flow: opening it must not push the table down the page,
   because the whole point is to look at the table while changing it. */
.kin-columns { position: relative; }

.kin-columns > summary {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--brand-control-line);
    border-radius: var(--radius);
    background: var(--brand-surface);
    cursor: pointer;
    white-space: nowrap;
    list-style: none;
}

/* Safari and Chrome draw their own disclosure triangle; the icon is the affordance here. */
.kin-columns > summary::-webkit-details-marker { display: none; }
.kin-columns > summary::marker { content: ""; }

.kin-columns > summary:hover { border-color: var(--brand-line-strong); }

.kin-columns-panel {
    position: absolute;
    right: 0;
    z-index: 20;
    min-width: 15rem;
    margin-top: var(--space-2);
    padding: var(--card-inset);
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    background: var(--brand-surface);
    border: 1px solid var(--brand-line-strong);
    border-radius: var(--radius);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
}

/* A field in a card head is a FILTER, not a form field: its label reads as a prefix so every
   child of the head is one line tall and the head's own align-items: center actually lines the
   controls up. Stacked, the label pushed the select about 8px below the search box, which is
   what made the two read as unrelated controls (P8.2 §8.2.9).

   TWO VOICES ON PURPOSE (P40-107 rework). A titled card head - a settings section, Treasury's
   Bank accounts, a rate card's Rates - keeps this prefix label. A register's tool row
   (.kin-register-tools, below) stacks the label over its select and aligns every control on one
   bottom edge, which fixes the same misalignment without spending 110px per filter on a prefix:
   that is what wrapped a two-filter register onto two lines at 1600px. Do not "fix" either voice
   back to the other. */
.kin-card-head .kin-field {
    flex: 0 1 auto;
    flex-direction: row;
    align-items: center;
    gap: var(--space-2);
}

.kin-card-head .kin-field > label { white-space: nowrap; }

/* Same vertical padding as the search input beside it, stated through the same token so the two
   cannot drift. */
.kin-card-head .kin-field select {
    padding-top: var(--space-2);
    padding-bottom: var(--space-2);
}

/* space-between puts the middle child somewhere different on a two-child head than on a
   three-child one, so a register with a filter and one without read as different components.
   An auto margin absorbs the free space instead. On a register tool row it opens the right-hand
   cluster - the count, then Clear filters, then Columns at the edge - because the edge belongs to
   the view tool (P40-107 rework: tools on the right, placed predictably). */
.kin-card-head .kin-roster-count { margin-left: auto; }

/* ---- The register tool row (P40-107 rework, Jakes 652889824) ---------------------------------

   NARROWING ON THE LEFT, THE RESULT AND THE VIEW TOOLS ON THE RIGHT, ONE LINE. The search box no
   longer grows to fill the head (it took 1098px of a 1243px head at 1600, and 2073px at 2560);
   filters stack their label over the select, and every control shares one bottom edge. The
   count's auto margin is the row's only one. Equal-specificity overrides of .kin-card-head
   .kin-field, so they come after it. No select max-width: it would clip the chosen option. */
.kin-register-tools {
    justify-content: flex-start;
    align-items: flex-end;
    gap: var(--space-2) var(--space-3);
}
.kin-register-tools .kin-search { flex: 0 1 auto; width: 20rem; min-width: 12rem; }
.kin-register-tools .kin-field { flex-direction: column; align-items: stretch; gap: var(--space-1); }
.kin-register-tools .kin-roster-count { padding-block: var(--space-2); white-space: nowrap; }
.kin-register-tools .kin-filter-state { margin-left: 0; }
.kin-register-tools:has(+ .kin-table-wrap > .kin-table-register) { border-bottom-color: transparent; }

@media (max-width: 860px) {
    .kin-register-tools .kin-search { flex: 1 1 100%; width: auto; }
    .kin-register-tools .kin-field { flex: 1 1 10rem; }
    .kin-register-tools .kin-field select { width: 100%; }
}

/* ---- Tables ----------------------------------------------------------------------------------- */

.kin-table-wrap {
    overflow-x: auto;
    position: relative;
    /* Tables are the densest thing in Kin OS. Rather than let the page scroll sideways at
       narrow widths, the table scrolls inside its own card. */
}

/* EVERY FIGURE IN A TABLE IS THE SAME WIDTH (P40-107). Counts, rates, amounts and dates are read
   down a column and compared, and proportional digits make 111 narrower than 888. Tabular
   figures cost a text column nothing, so the whole table takes them rather than each cell
   remembering to. */
.kin-table { font-size: var(--text-sm); font-variant-numeric: tabular-nums; }

/* THE HEADER ROW ANCHORS THE SCAN (P40-107, Jakes 652831533 rule 4). It was muted text on the
   same white as the rows, so the eye found the first row before it found the column names. Now
   it is a band: the workspace's ink at full strength over a tint of it, closed by the strong
   line. Still small capitals, so it reads as the frame of the data rather than as data.

   ONE BAND FOR EVERY PRIMARY TABLE (P40-107/108, Jakes 13 Oct 2026: "TABLE HEADERS MUST CLEARLY
   BELONG TO THE DATA BELOW THEM"). The two tiers of the first rework - the ink band on a
   register's list, a 6% tint everywhere else - left the tint so close to the card around it that
   Visas and Bank Details read as a table with a broken top. Every table a section holds now
   carries the ink band (--brand-band), so header, rows and total read as one structure; only a
   table nested inside a row stays quiet (.kin-table-nested below), which is what keeps a
   schedule inside a Work Agreement subordinate to it. */
.kin-table th {
    text-align: left;
    font-weight: var(--weight-semibold);
    font-size: var(--text-xs);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--brand-muted);
    padding: var(--space-2) var(--space-3);
    border-bottom: 1px solid var(--brand-line-strong);
    background: var(--brand-surface);
    /* Headers wrap. A long column name forcing the whole table wider than the content area
       costs every row a sideways scroll to save one header a second line. */
    white-space: normal;
}

/* The band is the COLUMN heads only. A row's own heading (th scope="row") sits in the data and
   keeps the quiet treatment above; tinting it too would draw a stripe down the table. */
.kin-table thead th {
    color: var(--brand-band-ink);
    background: var(--brand-band);
    border-bottom-color: var(--brand-band);
}

.kin-table thead :focus-visible { outline-color: var(--brand-band-ink); }

/* COMPACT ENTERPRISE DENSITY (rule 5). 0.7rem above and below every cell made a fifteen-row
   register a screen and a half; the step below it keeps a 44px row at body size, which is still
   a comfortable target, and lets several rows be compared at once. */
.kin-table td {
    padding: var(--space-2) var(--space-3);
    border-bottom: 1px solid var(--brand-line);
    vertical-align: middle;
}

.kin-table tbody tr:last-child td { border-bottom: none; }
.kin-table tbody tr { transition: background var(--motion-fast) var(--ease); }
.kin-table tbody tr:hover td { background: var(--brand-hover); }

.kin-table td.kin-actions-cell { text-align: right; white-space: nowrap; width: 1%; }

/* Qualified with th and td on purpose. `.kin-table th` above sets text-align: left at
   specificity (0,1,1), so an unqualified `.kin-table-numeric` at (0,1,0) loses and the heading
   stays left of its own right-aligned column — the markup was correct on every register and the
   cascade discarded half of it. A column heading and the figures under it must share an edge. */
.kin-table th.kin-table-numeric,
.kin-table td.kin-table-numeric {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* A count or a sort code is two or three glyphs, and without this the column is sized by its
   own uppercase heading plus a share of the leftover width. Auto layout clamps 1% up to
   min-content and hands the surplus to the name column, which is where it is wanted. The
   heading is already allowed to wrap, which is the trade this asks for. */
.kin-table th.kin-table-numeric { width: 1%; }

/* A figure never breaks across lines (P40-107). "USD" over "5,000,000.00" in a narrow column is
   two things to read and compare instead of one; the width a figure needs is taken from the text
   columns beside it, and the table scrolls inside its card before a figure splits. */
.kin-table td.kin-table-numeric { white-space: nowrap; }

/* A TOTAL READS AS THE FOOT OF ITS COLUMNS (rule 6), the way the band reads as their head. Only
   where a table already carries its own sum - this adds no figure. Ruled off the way an accounting
   schedule is, by a 2px ink rule, on its own table's 6% band, with figures a step larger.

   ALWAYS IN TFOOT. In a tbody the row hover rule (0,2,3) repainted it and the last-row rule
   stripped its edge; outside tbody neither can. A register that ever gains a total needs its own
   decision, not an ink foot by default. */
.kin-table > tfoot > tr.kin-table-total > :is(th, td) {
    padding-top: var(--space-3);
    padding-bottom: var(--space-3);
    border-top: 2px solid var(--brand-ink);
    border-bottom: 0;
    background: var(--brand-head);
    color: var(--brand-ink);
    font-weight: var(--weight-semibold);
}

.kin-table > tfoot > tr.kin-table-total > td.kin-table-numeric {
    font-size: var(--text-base);
    white-space: nowrap;
}

/* A nested table (Engagements inside a Work Agreement) is quieter than its parent so the
   hierarchy reads at a glance. The thead rule is written out because .kin-table thead th above
   (0,1,2) outranks a plain .kin-table-nested th (0,1,1): from 97a44d2 nested schedules carried the
   full band and read as loud as the table they sit in. Same weight, declared later, so it wins. */
.kin-table-nested th { background: transparent; color: var(--brand-muted); }
.kin-table-nested thead th {
    background: transparent;
    color: var(--brand-muted);
    border-bottom: 1px solid var(--brand-line);
}
.kin-table-nested td { padding-top: var(--space-2); padding-bottom: var(--space-2); }

/* THE PLANNING REGISTER (DEV-20261108-01): a row opens in place to show its lines, each a quiet
   panel with its tags, its schedule, its dated amounts and the changes that can be made to it. The
   arrow sits before the name so a reader scanning names is not interrupted by it. */
.kin-plan-name { display: flex; align-items: baseline; gap: var(--space-2); }
.kin-plan-toggle { min-width: 1.75rem; justify-content: center; }
.kin-plan-tags { display: inline-flex; flex-wrap: wrap; gap: var(--space-1); }
.kin-plan-detail > td { background: var(--brand-sunken); }
.kin-plan-lines { display: grid; gap: var(--space-3); padding: var(--space-2) 0; }
.kin-plan-line {
    display: grid;
    gap: var(--space-2);
    padding: var(--space-3);
    background: var(--brand-surface);
    border: 1px solid var(--brand-line);
    border-radius: var(--radius);
}
.kin-plan-line-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); }

/* ONE EDGE INSET FOR A TABLE IN A CARD (P40-107 rework). A table reaches the card's edges and its
   own cells carry the inset (P19-201, the card inset rule above); the first and last cells, group
   rows and band headings take --card-inset, so the column text starts on the card title's edge
   and the band runs the full width under it. A table the body holds alone - Person's Visas, Bank
   Details, reports - reaches the edges too. Child combinators only: a table nested inside a cell
   keeps its own padding. */
:is(.kin-card > .kin-table-wrap, .kin-card-body > .kin-table-wrap:only-child) > .kin-table:not(.kin-table-nested) > :is(thead, tbody, tfoot) > tr > :is(th, td):first-child { padding-left: var(--card-inset); }
:is(.kin-card > .kin-table-wrap, .kin-card-body > .kin-table-wrap:only-child) > .kin-table:not(.kin-table-nested) > :is(thead, tbody, tfoot) > tr > :is(th, td):last-child { padding-right: var(--card-inset); }
.kin-card-body > .kin-table-wrap:only-child { margin: calc(-1 * var(--card-inset)); }
.kin-card > .kin-table-wrap:first-child {
    border-top-left-radius: calc(var(--radius-lg) - 1px);
    border-top-right-radius: calc(var(--radius-lg) - 1px);
}
.kin-card > .kin-table-wrap:last-child,
.kin-card > .kin-card-body:last-child > .kin-table-wrap:only-child {
    border-bottom-left-radius: calc(var(--radius-lg) - 1px);
    border-bottom-right-radius: calc(var(--radius-lg) - 1px);
}

/* ---- The register's own list (P40-107 rework, Jakes 652889824) ------------------------------

   THE LIST THE PAGE EXISTS TO SHOW. Its column heads carry the same ink band as every primary
   table (15.8:1 HelloKindred, 13.9:1 TalentCorp, 14.2:1 CapacityCo, 17.9:1 TalentSmith;
   BrandContrastTests measures the pair); what the register adds is its row unit.

   ONE ROW UNIT. Every row at least 2.5rem, set by the data rather than by a button that repeated
   the row's own link: the duplicate Open is gone from the registers, so the row is one way in.
   A height on a td is a minimum; nothing clips and wrapped text still grows the row. */
.kin-table-register > tbody > tr > td { height: 2.5rem; }
.kin-table-register .kin-roster-known { line-height: var(--leading-tight); }

/* A status filter strip directly above the band closes on it rather than drawing its own rule. */
.kin-card > .kin-tabs:has(> button.kin-tab):has(+ .kin-table-wrap > .kin-table-register) {
    margin-bottom: 0;
    border-bottom-color: transparent;
}

/* ONE WAY INTO A ROW, AND THE CROSS-LINKS QUIET. The record's own link - on its name, or on its
   reference where it has no name - is ink and semibold (700 in every workspace face, where medium
   falls back to regular in three of them) and underlines on hover, focus or row hover. Links to
   related records stay, thin and pale at rest, accent on hover: a register row went from three
   underlines to one quiet way in. The vertical padding grows the hit area to about 30px without
   moving the line box. */
.kin-table :is(a, button).kin-row-link {
    color: var(--brand-ink);
    font-weight: var(--weight-semibold);
    text-decoration: none;
    padding-block: 0.3125rem;
    margin-block: -0.3125rem;
}
/* A ROW THAT OPENS A DIALOG RATHER THAN A PAGE (P42-002). The same one way in, drawn the same, but a
   button, because nothing is navigated to. The resets take away the button's own chrome so it reads
   exactly as the link does. */
.kin-table button.kin-row-link {
    appearance: none;
    background: none;
    border: 0;
    padding-inline: 0;
    font: inherit;
    text-align: start;
    cursor: pointer;
    color: var(--brand-ink);
    font-weight: var(--weight-semibold);
    text-decoration: none;
    padding-block: 0.3125rem;
    margin-block: -0.3125rem;
}
.kin-table :is(a, button).kin-row-link:is(:hover, :focus-visible),
.kin-table tbody tr:hover :is(a, button).kin-row-link {
    text-decoration: underline;
    text-decoration-color: var(--brand-accent-ink);
    text-decoration-thickness: 1.5px;
}

/* THE SAME WAY IN, WHERE THE ROW OPENS A DIALOG RATHER THAN A PAGE (P40-302). A journal has no
   page of its own, so its title is a button that opens its details; it reads exactly as a row link
   does and keeps a button's semantics for a screen reader. */
.kin-table button.kin-row-link {
    background: none;
    border: 0;
    padding-inline: 0;
    font: inherit;
    font-weight: var(--weight-semibold);
    text-align: start;
    cursor: pointer;
}
.kin-table-register > tbody > tr > td > a:not(.kin-row-link, .kin-btn) {
    text-decoration-color: var(--brand-line-strong);
    text-decoration-thickness: 1px;
}
.kin-table-register > tbody > tr > td > a:not(.kin-row-link, .kin-btn):hover {
    text-decoration-color: var(--brand-accent-ink);
    text-decoration-thickness: 1.5px;
}

/* COLUMN TYPES. A reference is set as its detail-page chip is (mono, never breaking); codes,
   dates and statuses have a fixed shape and never break; only references and codes shrink to
   their content, so the remaining width is shared by the columns that can use it. nowrap is on
   the td only: a heading still wraps rather than widening a four-letter column. */
.kin-page-ref,
.kin-table td.kin-table-ref {
    font-family: var(--mono);
    letter-spacing: 0.02em;
    color: var(--brand-ink);
}
/* A code is the same size as the text in the cells beside it (QCR-20261104-01.03, Jakes 4 Nov
   2026: one size for data, the monospace face to tell codes from values). At 0.92em a register
   read as two sizes. */
.kin-table td.kin-table-ref { font-size: var(--mono-match); font-weight: var(--weight-regular); }
.kin-table :is(th, td):is(.kin-table-ref, .kin-table-code) { width: 1%; }
.kin-table td:is(.kin-table-ref, .kin-table-code, .kin-table-date, .kin-table-status) { white-space: nowrap; }

/* A status cell's pill never breaks, but a reason written under it is free text and wraps: a
   500-character status change reason on one line would widen the whole register. */
.kin-table td.kin-table-status > :is(div, p) { white-space: normal; }
.kin-table td.kin-table-code { font-family: var(--mono); font-size: var(--mono-match); }

/* WHICH ROW APPLIES TODAY, marked on the row wherever Kin OS already prints Current: a rule on
   the first cell in the signal colour, a faint tint across the row, and the word itself, which
   stays the accessible signal (status is never colour alone). The rule was the accent ink, which
   in three workspaces is the label colour and so marked nothing. */
.kin-table tr.kin-current > :is(th, td) { font-weight: var(--weight-semibold); background: var(--brand-head); }
.kin-table tr.kin-current > :first-child { box-shadow: inset 3px 0 0 var(--brand-signal); }

/* ---- A collapsible card -------------------------------------------------------------------
   A <details> that looks like a card (P12.1 §12.1.3). Native disclosure rather than a button
   and a boolean: it is keyboard-operable and findable by the browser's own in-page search
   without a line of script, and a permission list nobody can Ctrl-F through is a permission
   list nobody reads. */
.kin-disclose > summary {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-2) var(--space-3);
    padding: var(--space-3) var(--card-inset);
    cursor: pointer;
    list-style: none;
    border-radius: inherit;
}

/* The default triangle is replaced by one that follows the open state, drawn from the ink so it
   belongs to the workspace rather than to the browser. */
.kin-disclose > summary::-webkit-details-marker { display: none; }

.kin-disclose > summary::before {
    content: "";
    flex: 0 0 auto;
    width: 0.5rem;
    height: 0.5rem;
    border-right: 1.5px solid var(--brand-muted);
    border-bottom: 1.5px solid var(--brand-muted);
    transform: rotate(-45deg);
    transition: transform var(--motion-fast) var(--ease);
}

.kin-disclose[open] > summary::before { transform: rotate(45deg); }

/* An Overview's explanation, closed by default (KinExplainer, DEC-P40-004). Set apart from the
   tiles above it by space rather than by a heading, because the closed card's own title is the
   heading. */
.kin-explainer { margin-top: var(--space-6); }

/* An explanation behind one quiet line (KinMore, P40-106). Closed it is a single muted line; open
   it is the sentence, at the width a sentence reads at. */
.kin-more {
    font-size: var(--text-xs);
    color: var(--brand-muted);
}

.kin-more > summary {
    display: inline;
    cursor: pointer;
    list-style: none;
    text-decoration: underline dotted;
    text-underline-offset: 0.2em;
}

.kin-more > summary::-webkit-details-marker { display: none; }

.kin-more > summary:hover,
.kin-more > summary:focus-visible { color: var(--brand-ink); }

.kin-more > p {
    margin: var(--space-2) 0 0;
    max-width: 65ch;
    line-height: var(--leading-normal);
}

.kin-disclose > summary:hover { background: var(--brand-hover); }

.kin-disclose > summary > .kin-disclose-title {
    font-weight: var(--weight-semibold);
    color: var(--brand-ink);
}

/* THE DISCLOSURE'S FOUR INSET RULES ARE GONE, and their absence is the point (P19-201).
 *
 * A `.kin-disclose` is written `class="kin-card kin-disclose"` at both of its two usages, so it
 * IS a card and the card's own rules now reach it: everything but the summary is inset, a
 * fieldset takes that inset as margin so its frame is not drawn inside the card's, the foot pads
 * itself and the table reaches the edges. Four rules here said exactly those four things in
 * disclosure-specific language, which is how one rule came to have two implementations that could
 * drift. CardInsetTests holds the assumption this deletion rests on: a .kin-disclose that stopped
 * being a .kin-card would silently lose all four, so the test asserts the pairing at every usage
 * rather than trusting it.
 *
 * What is genuinely disclosure-specific stays. */

/* Stacked fieldsets keep the wider gap they had — a frame every 16px reads as a grid, and these
   are eleven independent questions. Adjacent margins collapse, so this is the gap, not an
   addition to it. */
.kin-disclose > .kin-fieldset + .kin-fieldset { margin-top: var(--space-5); }

/* A plain list inside a card. Bulleted, because these are genuinely items and not prose. */
.kin-list {
    margin: 0 0 var(--space-3);
    padding-left: var(--space-5);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    font-size: var(--text-sm);
    color: var(--brand-muted);
}

/* ---- The Company Tax Matrix ---------------------------------------------------------------
   A cross-product read at a glance (P11.1 §11.1.10). Fifteen Companies by six Taxes is ninety
   cells, and everything here exists to make that many cells scannable: narrow centred columns,
   a sticky first column so a row stays identifiable while reading across, and jurisdiction
   headers spanning their own taxes.

   The marks are a glyph AND a colour, never colour alone — the answer has to survive a
   colour-blind reader and a printed page. */
.kin-matrix { table-layout: auto; }

.kin-matrix th.kin-matrix-country {
    text-align: center;
    border-left: 1px solid var(--brand-line-strong);
    letter-spacing: 0.08em;
}

.kin-matrix th.kin-matrix-tax {
    text-align: center;
    font-size: var(--text-xs);
    white-space: nowrap;
    width: 1%;
}

/* The Organization column stays put while the reader scans across, because a row of dots with no
   row header is unreadable. */
.kin-matrix .kin-matrix-organization {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--brand-surface);
    text-align: left;
    white-space: nowrap;
    display: table-cell;
}

.kin-matrix .kin-matrix-organization .kin-small { display: block; font-weight: var(--weight-regular); }

.kin-matrix-cell {
    text-align: center;
    width: 1%;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* A gap in a Company's own jurisdiction. The Scheduled family, not the Cancelled one, and the
   choice is the whole message: this is something pending a look, not something wrong. Deliberately
   faint — a red cell would say the group had made a mistake, and plenty of entities legitimately
   hold no registration. */
.kin-matrix-cell.is-gap {
    background: color-mix(in srgb, var(--status-scheduled-bg) 60%, var(--brand-surface));
}

.kin-matrix-yes { color: var(--brand-accent-ink); font-size: 1.05em; }

.kin-matrix-gap { color: var(--brand-muted); font-size: 1.05em; }

/* A registration whose required number is missing. This one IS an outstanding item on a record
   that exists, so it borrows the Scheduled ink rather than the muted grey. */
.kin-matrix-warn {
    color: var(--status-scheduled-ink);
    font-weight: var(--weight-bold);
    margin-left: 0.15em;
}

.kin-matrix-key {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-4);
    margin-bottom: var(--space-2);
}

/* ---- A grouped register -------------------------------------------------------------------
   One heading row spanning the table, introducing the rows beneath it. Reusable rather than
   written into the Module register, because grouping is a register behaviour and the Core
   subrail, Home and the tax registers all group by the same kinds of thing (P10.1 §10.1.3,
   P14 §14.3).

   A row inside its own `tbody` rather than a styled div between two tables, so the columns stay
   aligned across every group — the whole point of showing the hierarchy is that the values under
   it still line up. `scope="colgroup"` is what tells a screen reader the heading governs the
   rows below rather than a column. */
.kin-table-group > th {
    /* Lighter than the table's own head, because it is a divider inside the data rather than a
       second set of column labels: the section-head tint under the ink band. */
    background: var(--brand-head);
    color: var(--brand-ink);
    text-align: left;
    text-transform: uppercase;
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: 0.08em;
    /* The cells' own inset (P40-107 rework): the group title starts on the column text's edge
       rather than 4px right of it, and the row is a divider of about 35px rather than 43. Inside
       a card the edge-inset rule gives this colspan heading --card-inset like any first cell. */
    padding: var(--space-2) var(--space-3);
    border-top: 1px solid var(--brand-line);
    border-bottom: 1px solid var(--brand-line);
}

/* The first group sits directly under the column headings and needs no second rule between. */
.kin-table thead + tbody .kin-table-group > th { border-top: 0; }

.kin-table-group-name { margin-right: var(--space-3); }

/* Sort code, counts and an archived pill, set apart from the name they qualify. */
.kin-table-group-meta {
    margin-left: var(--space-3);
    font-weight: var(--weight-regular);
    letter-spacing: 0.04em;
    text-transform: none;
    color: var(--brand-muted);
}

/* ---- Paging (P18-201) --------------------------------------------------------------------------

   Below the table, not above it. The reader arrives at the pager by finishing the page, and a
   control that offers the next page before the current one has been read is in the wrong place.

   It wraps to two lines on a narrow screen rather than shrinking: the position sentence is the
   part that has to stay readable, and the steps are the part that has to stay pressable. Nothing
   here is sticky, for the same reason KinEditBar is not — a bar pinned over the last row of a
   table hides the row it is there to help somebody leave. */
.kin-pager {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2) var(--space-4);
    margin-top: var(--space-3);
}

.kin-pager-position {
    margin: 0;
    font-size: var(--text-xs);
    color: var(--brand-muted);
    font-variant-numeric: tabular-nums;
}

.kin-pager-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-4);
    margin-left: auto;
}

.kin-pager-steps {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}

.kin-pager-size {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.kin-pager-size label {
    margin: 0;
    font-size: var(--text-xs);
    color: var(--brand-muted);
    white-space: nowrap;
}

.kin-pager-size select {
    width: auto;
    min-width: 5rem;
    font-variant-numeric: tabular-nums;
}

.kin-pager-of {
    font-size: var(--text-xs);
    color: var(--brand-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ---- Status ------------------------------------------------------------------------------------ */

.kin-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.35em;
    padding: 0.13rem 0.55rem;
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: 0.02em;
    border: 1px solid transparent;
    white-space: nowrap;
}

/* The marker is a second, non-colour signal: its shape differs by status, so the pills remain
   distinguishable in greyscale and to a colour-blind reader. */
.kin-pill::before {
    content: "";
    width: 0.5em;
    height: 0.5em;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}

.kin-pill-active     { background: var(--status-active-bg);    color: var(--status-active-ink);    border-color: var(--status-active-line); }
.kin-pill-scheduled  { background: var(--status-scheduled-bg); color: var(--status-scheduled-ink); border-color: var(--status-scheduled-line); }
.kin-pill-draft      { background: var(--status-draft-bg);     color: var(--status-draft-ink);     border-color: var(--status-draft-line); }
.kin-pill-ended      { background: var(--status-ended-bg);     color: var(--status-ended-ink);     border-color: var(--status-ended-line); }
.kin-pill-cancelled  { background: var(--status-cancelled-bg); color: var(--status-cancelled-ink); border-color: var(--status-cancelled-line); }
.kin-pill-inactive   { background: var(--status-inactive-bg);  color: var(--status-inactive-ink);  border-color: var(--status-inactive-line); }
.kin-pill-voided     { background: var(--status-voided-bg);    color: var(--status-voided-ink);    border-color: var(--status-voided-line); }

/* Draft is hollow, Scheduled is ringed, Cancelled is struck through, Ended is square.
   Four different shapes for four different meanings — five now.
 *
 * VOIDED IS THE ONLY DASHED ONE, and that is the whole point of its shape: a dashed outline is
 * the visual vocabulary for something that is not really there. Cancelled is struck through
 * because it was real and did not happen; Voided is dashed because it was never real at all.
 * Neither depends on colour, which matters here more than usual — the two sit in the same
 * neutral family and colour alone would not separate them (P7 §54, §60). */
.kin-pill-draft::before     { background: transparent; box-shadow: inset 0 0 0 1.5px currentColor; }
.kin-pill-scheduled::before { background: transparent; box-shadow: 0 0 0 1.5px currentColor; width: 0.35em; height: 0.35em; }
.kin-pill-ended::before     { border-radius: 1px; }
.kin-pill-cancelled        { text-decoration: line-through; }
.kin-pill-cancelled::before { background: transparent; box-shadow: inset 0 0 0 1.5px currentColor; border-radius: 1px; }
.kin-pill-voided           { border-style: dashed; }
.kin-pill-voided::before   { background: transparent; border: 1.5px dashed currentColor; border-radius: 1px; }

/* ---- Labels and quantities ----------------------------------------------------------------------
 * A pill is ONLY for a lifecycle status. Everything above this line is spent on making seven
 * statuses tell themselves apart without colour, and that vocabulary is worth nothing if a
 * screen borrows it for something that is not a status. Two things kept doing exactly that, so
 * they get their own patterns here:
 *
 *   - a LABEL that classifies a thing ("Sensitive", "Required", "View") is a badge, and
 *   - a QUANTITY ("142 entries", "9 permissions") is a count.
 *
 * The specific harm this replaces: "Sensitive" was drawn as kin-pill-cancelled, which strikes
 * its own text through and shows a hollow square. To anyone reading the shape rather than the
 * word - which is what the shape is there for - a sensitive permission looked like a cancelled
 * one. */

.kin-badge {
    display: inline-block;
    padding: 0.05rem 0.4rem;
    border-radius: var(--radius-sm);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: 0.05em;
    text-transform: uppercase;
    background: var(--brand-sunken);
    border: 1px solid var(--brand-line);
    color: var(--brand-muted);
}

/* The one badge that is allowed to raise its voice. It borrows the palette's existing red -
   there is no separate warning family and inventing one is not this pattern's job - but it
   takes only the colour, not Cancelled's line-through and not its marker shape. */
.kin-badge-alert {
    background: var(--status-cancelled-bg);
    border-color: var(--status-cancelled-line);
    color: var(--status-cancelled-ink);
}

/* One granted action in a read-only list of them (a Role's permissions, P40-108): the action and
   its badge stay together, and the next action starts after a gap rather than a comma, so a
   Sensitive badge can never read as belonging to its neighbour. */
.kin-grant {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    margin-right: var(--space-3);
    white-space: nowrap;
}

/* A count is a number, so it is set in tabular figures: stacked in a list, the digits line up
   and the eye can compare two rows without reading them. */
.kin-count {
    display: inline-block;
    padding: 0.05rem 0.45rem;
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    font-variant-numeric: tabular-nums;
    background: var(--brand-sunken);
    border: 1px solid var(--brand-line);
    color: var(--brand-muted);
    white-space: nowrap;
}

/* A zero is not the same news as a fourteen, and the difference should not need reading. The
   de-emphasis is weight, not colour: a lighter grey would have to be argued past the contrast
   floor, and there is no reason to spend contrast on saying "nothing here". */
.kin-count-none { font-weight: var(--weight-regular); }

/* Both modifiers are declared AFTER the pattern they modify, and both restate every property
   the base rule sets with a shorthand. They carry the same specificity as .kin-count, so a
   border-color alone would lose to the base rule's `border` shorthand and the chip would come
   out neutral with no error anywhere. */
.kin-count-alert {
    background: var(--status-cancelled-bg);
    border: 1px solid var(--status-cancelled-line);
    color: var(--status-cancelled-ink);
}

/* ---- Buttons -----------------------------------------------------------------------------------
 * Three levels, on purpose: one primary per context, secondary for the rest, quiet for the
 * ones that are available but rarely the right answer. */

.kin-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4em;
    padding: 0.44rem 0.9rem;
    border-radius: var(--radius);
    border: 1px solid var(--brand-line-strong);
    background: var(--brand-surface);
    color: var(--brand-ink);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    box-shadow: var(--shadow-sm);
    transition: background var(--motion-fast) var(--ease),
                border-color var(--motion-fast) var(--ease),
                box-shadow var(--motion-fast) var(--ease),
                transform var(--motion-fast) var(--ease);
}

.kin-btn:hover {
    background: var(--brand-hover);
    border-color: var(--brand-ink);
    text-decoration: none;
}

.kin-btn:active { transform: translateY(1px); box-shadow: none; }
.kin-btn:disabled, .kin-btn[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; box-shadow: none; }
.kin-btn:disabled:hover { background: var(--brand-surface); border-color: var(--brand-line-strong); }

/* THE PRIMARY HAS AN EDGE OF ITS OWN (P40-107/108). A fill alone made the boundary a matter of
   hue: HelloKindred's lime is 1.18:1 against white, so the button's shape depended on seeing the
   colour. The edge is the fill mixed toward its own label, which draws a visible rim in every
   workspace without introducing a colour the brand does not have. */
.kin-btn-primary {
    background: var(--brand-action);
    border-color: color-mix(in srgb, var(--brand-action) 50%, var(--brand-action-ink));
    color: var(--brand-action-ink);
    font-weight: var(--weight-semibold);
    box-shadow: var(--shadow-sm);
}

.kin-btn-primary:hover {
    background: var(--brand-action-hover);
    border-color: color-mix(in srgb, var(--brand-action-hover) 50%, var(--brand-action-ink));
    color: var(--brand-action-ink);
}

/* THE BUTTON TAXONOMY (final close-out §18). Same action, same treatment, everywhere.
 *
 *   .kin-btn                     secondary — a framed control. THE DEFAULT for Edit, Add,
 *                                Cancel changes, Archive, and anything else ordinary.
 *   .kin-btn .kin-btn-primary    one per context, and only one: Save changes, Create X, Submit.
 *   .kin-btn .kin-btn-danger     a lifecycle action that ends or voids something.
 *   .kin-btn .kin-btn-quiet      genuinely secondary chrome — never an Edit.
 *
 * WHY QUIET IS NO LONGER ALLOWED TO BE AN EDIT. Jakes reported that the Personal Detail Edit
 * appeared as unframed text while every other Edit on the product appeared as a button. He was
 * right, and it was not a one-off: four affordances were styled this way, three of them Edits.
 * kin-btn-quiet drops the border AND the background, so it reads as text until you hover it —
 * which is correct for the rail's collapse control and wrong for the action that puts a record
 * into edit mode. An Edit is a real, framed control now, and ButtonPatternTests holds it. */
.kin-btn-quiet { border-color: transparent; background: transparent; color: var(--brand-muted); box-shadow: none; }
.kin-btn-quiet:hover { background: var(--brand-hover); border-color: transparent; color: var(--brand-ink); }

/* DESTRUCTIVE IS NEVER QUIETER THAN SECONDARY (P40-107/108). Its edge was the status line
   (#eecccc, 1.48:1), fainter than an ordinary button's, so the one control a reader should notice
   before pressing was the easiest to miss. The edge is now the danger ink itself. */
.kin-btn-danger { color: var(--status-cancelled-ink); border-color: var(--status-cancelled-ink); font-weight: var(--weight-semibold); }
.kin-btn-danger:hover { background: var(--status-cancelled-bg); border-color: var(--status-cancelled-ink); }

/* The confirming half of a destructive question - "Delete Currency permanently" in its dialog -
   is filled, so the irreversible answer cannot be mistaken for the way out. Only ever beside a
   plain "Keep it" control; never on a page. */
.kin-btn-danger.kin-btn-danger-confirm {
    background: var(--status-cancelled-ink);
    color: var(--paper-0);
}

.kin-btn-danger.kin-btn-danger-confirm:hover {
    background: color-mix(in srgb, var(--status-cancelled-ink) 82%, #000000);
    color: var(--paper-0);
}

.kin-btn-sm { padding: 0.22rem 0.55rem; font-size: var(--text-xs); box-shadow: none; }
.kin-btn-block { width: 100%; }

.kin-btn-icon { padding: 0.35rem; }

.kin-actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}

.kin-actions-spaced { margin-top: var(--space-4); }

/* ---- More actions for one record (P40-117, C6, D14) ---------------------------------------------
 * KinActionMenu: a three-dot trigger and the browser's own popover. The popover is in the top
 * layer, closes on a click outside it and on Escape, and its items follow the trigger in the tab
 * order, so none of that is styled or scripted here.
 *
 * PLACED BY THE TRIGGER WHERE THE BROWSER CAN. The trigger is the panel's anchor, so the panel
 * opens under it, aligned to its far edge, and flips above or across where the window has no room.
 * Without anchor positioning the panel stays where the platform puts a popover, in the middle of
 * the window, framed and sized here, which is still a working menu. On a narrow screen it is a
 * sheet along the bottom edge either way, within reach of a thumb.
 *
 * A GROUP WITH NO ITEM IS NOT DRAWN. The page decides each item under its own gate, and a group
 * whose items were all withheld would otherwise show its label over nothing. */
.kin-action-menu { display: inline-flex; }

.kin-action-menu-trigger { min-width: 2rem; min-height: 2rem; }

.kin-action-menu-panel {
    width: max-content;
    min-width: 15rem;
    max-width: min(22rem, calc(100vw - 2 * var(--space-4)));
    max-height: min(32rem, calc(100dvh - 2 * var(--space-4)));
    overflow-y: auto;
    margin: auto;
    padding: var(--space-2);
    border: 1px solid var(--brand-line-strong);
    border-radius: var(--radius);
    background: var(--brand-surface);
    color: var(--brand-ink);
    box-shadow: var(--shadow-lg);
}

.kin-action-menu-panel:popover-open {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

@supports (position-area: block-end) {
    .kin-action-menu-panel {
        inset: auto;
        margin: var(--space-1) 0 0;
        position-area: block-end span-inline-start;
        position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
    }
}

.kin-action-menu-group:not(:has(.kin-action-menu-item)) { display: none; }

.kin-action-menu-group + .kin-action-menu-group {
    padding-top: var(--space-2);
    border-top: 1px solid var(--brand-line);
}

.kin-action-menu-label {
    margin: 0 0 var(--space-1);
    padding: 0 var(--space-2);
    color: var(--brand-muted);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
}

.kin-action-menu-items {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* An item is a whole row, left-aligned and tall enough to tap. A destructive one keeps the danger
   ink it carries everywhere else, so it reads as destructive here too, and stays confirmed by the
   dialog it opens. */
.kin-action-menu-item.kin-btn {
    justify-content: flex-start;
    width: 100%;
    min-height: 2.25rem;
    border-color: transparent;
    background: transparent;
    box-shadow: none;
    font-size: var(--text-sm);
    text-align: left;
    white-space: normal;
}

.kin-action-menu-item.kin-btn:hover { background: var(--brand-hover); border-color: transparent; }

.kin-action-menu-item.kin-btn-danger:hover { background: var(--status-cancelled-bg); }

/* The sheet's title and Close are for a narrow screen only (KinActionMenu.razor): beside its trigger
   the panel's record is in sight, and Escape or a click outside puts it away. */
.kin-action-menu-title,
.kin-action-menu-close { display: none; }

@media (max-width: 640px) {
    .kin-action-menu-panel {
        inset: auto 0 0 0;
        width: auto;
        max-width: none;
        margin: 0;
        position-area: none;
        border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    }

    .kin-action-menu-item.kin-btn { min-height: 2.75rem; }

    /* The trigger is a target a thumb has to hit, as tall and as wide as the items it opens
       (P40-117 cross-slice review, UX accessibility). */
    .kin-action-menu-trigger { min-width: 2.75rem; min-height: 2.75rem; }

    /* THE TITLE AND CLOSE STAY IN SIGHT WHILE THE ITEMS SCROLL (P40-117 cross-slice re-review,
       finding 3). The sheet is capped in height and scrolls, and an Active Engagement's menu with
       its title and Close is taller than the cap, so Close began below the sheet's edge and the
       title scrolled away with the items. Both are pinned to the sheet's edges, on the sheet's own
       surface and above the items, which scroll between them. A sticky box stops at the sheet's
       padding, and an item scrolling under it showed through that strip (measured in a static
       harness at 390 x 844, Chromium), so the title reaches up over the padding with its own
       surface, and Close covers the strip around it with a shadow of the sheet's surface. */
    .kin-action-menu-title {
        display: block;
        position: sticky;
        top: calc(-1 * var(--space-2));
        z-index: 1;
        margin: calc(-1 * var(--space-2)) 0 0;
        padding: calc(var(--space-1) + var(--space-2)) var(--space-2) var(--space-2);
        border-bottom: 1px solid var(--brand-line);
        background: var(--brand-surface);
        color: var(--brand-ink);
        font-size: var(--text-sm);
        font-weight: var(--weight-semibold);
    }

    .kin-action-menu-close {
        display: inline-flex;
        position: sticky;
        bottom: 0;
        z-index: 1;
        flex-shrink: 0;
        justify-content: center;
        width: 100%;
        min-height: 2.75rem;
        box-shadow: 0 0 0 var(--space-2) var(--brand-surface);
    }
}

/* THE ONE PLACE AN OPEN EDIT IS COMMITTED (P19-102).
 *
 * Ten of the 13 detail pages left the page-head button visible while editing and re-labelled it
 * "Cancel changes" while the card foot carried a second one, so two identical labels sat on
 * screen at once doing the same thing. The three multi-card pages had already invented the
 * shape that works: one action row, below the sections it commits.
 *
 * It is given a surface of its own rather than being a bare row, because its scope is the claim
 * it makes — everything above it — and a row floating on the page ground reads as belonging to
 * whatever card it happens to sit under. A left accent rather than a box: enough to separate it
 * from the sections without adding the fourth border in a column of cards, which is the v1
 * weight P19-002 rules out.
 *
 * NOT STICKY. A bar pinned over the content is v1 weight and nothing has asked for it. The
 * reader arrives here by finishing the form, which is the direction they are already reading. */
.kin-edit-bar {
    background: var(--paper-1);
    border: 1px solid var(--brand-line);
    border-left: 3px solid var(--brand-accent);
    border-radius: var(--radius);
    padding: var(--card-inset);
    margin-bottom: var(--space-4);
}

/* A NOTE THAT BELONGS TO THE ROW, NOT TO THE BUTTON IT HAPPENS TO FOLLOW
 * (P15 §guidance-text#4).
 *
 * Twelve sentences sat inside .kin-actions wearing .kin-field-hint or .kin-muted.kin-small,
 * which made them flex siblings of the buttons: at a comfortable width they trailed the last
 * button as though they described it, and as the row narrowed they wrapped underneath whichever
 * button they happened to follow — a different button at every width. .kin-field-hint is also
 * the wrong badge for them: that class means "the hint under THIS field", and Jakes's objection
 * to helper text has always been placement rather than existence (§7 of the recurring feedback).
 *
 * One class, and its whole job is to take the row to itself. `flex: 1 0 100%` forces a line
 * break in the wrapping row, so the note lands under the buttons at 1600px and at 375px alike,
 * which is the point: predictable is what it was not. The voice is the hint's — same size, same
 * muted ink — because it is the same register of text, just attached to the action rather than
 * to a field. */
.kin-action-note {
    flex: 1 0 100%;
    margin: 0;
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    color: var(--brand-muted);
}

/* ---- Forms ---------------------------------------------------------------------------------- */

.kin-form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--space-4) var(--space-5);
    /* A query container, so the span below can ask about the grid rather than about the window
       — see the note under .kin-field-2. Safe on a block-level grid: its inline size comes from
       its parent, never from its own contents. */
    container-type: inline-size;
}

.kin-field { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.kin-field-2 { grid-column: span 2; }

/* A field that wants the whole row. Written as `1 / -1` rather than `span 3` on purpose: in an
   auto-fit grid that has resolved to one or two columns, a span of three creates implicit tracks
   and overflows, whereas the full explicit row is the full row at every width. Six fields —
   the Description and Notes textareas on Company, HR Settings, Role detail and the Roles
   register — wore this class while no stylesheet defined it, so the longest text on those cards
   sat in the narrowest box on them (P15 §design-system-consistency#2). */
.kin-field-3 { grid-column: 1 / -1; }

/* A SPAN OF TWO IN A GRID THAT HAS ONE COLUMN IS NOT A SPAN, IT IS A SECOND COLUMN
 * (P15 §responsive-accessibility#1).
 *
 * Below about 470px of content width the auto-fit grid resolves to a single 200px track. A
 * child still asking for two tracks forces an IMPLICIT second one, sized out of whatever is
 * left, and every field after it lands in that. Measured at 375px on Person Edit: the grid
 * computed to `200px 35px`, with a 35px State / Province select and a 35px Postal code box
 * whose labels were clipped. 72 usages across 28 screens do this.
 *
 * `grid-column: 1 / -1` is the tempting one-word fix and it is wrong — on a three-column
 * desktop form it would turn every span-2 field into a full-row one. The span is right; it
 * only has to yield when the grid cannot honour it, which is a question about the GRID and not
 * about the viewport, so it is asked of the grid. 424px = two 200px minimums plus the 24px
 * column gap; both numbers are above, and this must move if either does. */
@container (width < 424px) {
    .kin-field-2 { grid-column: auto; }
}

/* A REQUIREMENT SHARED BY A GROUP OF FIELDS (KinOneOf, 3265404001).
 *
 * The whole row, because the group holds a grid of its own and a group squeezed into one track
 * would put two fields in a 200px column. The fieldset's own border, padding and margin are the
 * browser's and are removed: the group is told apart by its legend and its sentence, not by a box,
 * so the fields inside line up with every other field on the form. `min-width: 0` because a
 * fieldset's default minimum is its content's, which is the same overflow `.kin-field` avoids. */
.kin-one-of {
    grid-column: 1 / -1;
    margin: 0;
    padding: 0;
    border: 0;
    min-width: 0;
}

/* The legend speaks in the field-label voice, so the group reads as one more field name rather
 * than as a heading the form did not have before. */
.kin-one-of > legend {
    padding: 0;
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    letter-spacing: 0;
    text-transform: none;
    color: var(--brand-ink);
}

.kin-one-of > .kin-field-hint {
    display: block;
    margin: var(--space-1) 0 var(--space-2);
}

/* `:not(.kin-check)` because a checkbox's caption is a sentence, not a field label. Without it
   the uppercase, letter-spaced field voice was applied to "A company may be registered here",
   which read as shouting and — being nowrap — was wide enough to overflow its grid track. */
/* A FORM LABEL NAMES THE CONTROL UNDER IT (P40-107/108). In a focused dialog the control is the
   value, so the label is the strongest text beside it rather than the quietest: the ink at
   semibold, sentence case, on the same 13px step the read-mode label uses. It is visibly a
   different voice from a read-only fact's label, which is how a reader tells "I am editing this"
   from "I am reading this" without hunting for a border. */
.kin-field > label:not(.kin-check) {
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    letter-spacing: 0;
    text-transform: none;
    color: var(--brand-ink);
}

/* A checkbox that sits inside a form field, rather than in a `.kin-check-row`. Its caption is
   allowed to wrap and the box aligns to the first line of it. */
.kin-field > label.kin-check {
    white-space: normal;
    align-items: flex-start;
    color: inherit;
}

/* THE REQUIRED MARK (P19-104, and Jakes's final P19 acceptance note).
 *
 * IT IS THE WORD AGAIN, AND THAT IS THE POINT. The mark was an asterisk for one release. Jakes
 * accepted P19 and then said, of the form as shipped, that the asterisk is technically there and
 * too subtle to make a required field immediately obvious, and that the word this replaced was
 * clearer. A mark nobody notices is a mark that is not doing the job, whatever it measures.
 *
 * WHAT WENT WRONG THE FIRST TIME THE WORD WAS HERE was not the word, it was that the word was
 * part of the label. `content: " required"` inherited the label's uppercase, letter-spacing and
 * muted colour, so "FIRST NAME required" read as one long shouted phrase, wrapped on a narrow
 * screen and competed with the name of the field for the eye. Every one of those complaints is
 * about typography, and none of them is about saying the word.
 *
 * SO THE WORD IS A CHIP AND NOT A SUFFIX. Its own background, its own casing, its own tracking
 * and its own size, set against the label rather than inherited from it: the label is read as the
 * name of the field and the chip is read as a fact about it, because they do not look like the
 * same kind of text. The gap in front of it keeps it off the label's last letter when the two sit
 * on one line, and the chip wraps as a unit when they do not.
 *
 * `content: "Required" / "required"` keeps the alt text the asterisk needed. It matters less now
 * — the visible text is a word a screen reader would read out anyway — but stating it means the
 * announcement does not silently change with the glyph, and the plain declaration above it is
 * still the deliberate fallback: a browser that does not understand the alt-text syntax drops the
 * whole declaration, so without the first one the mark would vanish rather than degrade. Where a
 * field is built with KinField the control also carries aria-required, which is the mechanism
 * that does not depend on any of this.
 *
 * --state-stop-ink rather than --status-cancelled-ink: this is the colour Kin OS refuses in, and
 * a required mark is a refusal waiting to happen. Cancelled is a lifecycle state and means
 * something else. */
.kin-required::after {
    content: "Required";
    margin-inline-start: var(--space-1);
    padding: 0.05rem var(--space-1);
    border-radius: var(--radius-sm);
    background: var(--state-stop-bg);
    font-size: var(--text-xs);
    letter-spacing: 0;
    text-transform: none;
    color: var(--state-stop-ink);
    font-weight: var(--weight-semibold);
    line-height: 1.35;
    white-space: nowrap;
}

.kin-required::after {
    content: "Required" / "required";
}

/* The `:not()` exclusions matter more than they look. `min-width: 0` below exists so a text
   input can shrink inside its minmax(200px, 1fr) grid track; applied to a checkbox it destroys
   the flex item's automatic minimum size, and the box — the only shrinkable item in the row —
   absorbs the whole overflow and lays out at zero width. Jakes met that as a Registered Address
   checkbox that was invisible but still clickable, because the label around it was 227px wide
   and the box inside it was 0 (P8.2 §8.2.9). The padding, border and radius are equally wrong
   for a checkbox; Blink discards them and Gecko paints them over the native control. */
.kin-field input:not([type="checkbox"]):not([type="radio"]),
.kin-field select,
.kin-field textarea {
    padding: 0.48rem 0.6rem;
    /* --brand-control-line, not --brand-line-strong (P15 §responsive-accessibility#5). The
       strong line is the rule between table rows, a 26% mix that only has to be findable while
       somebody reads down a column; measured as a field's edge it is 1.68:1 on a white card and
       1.37:1 in a sunken panel. An empty text box on a white card is the same defect Jakes
       reported as an "invisible when unchecked" checkbox — the boundary is the only thing
       saying the control is there — and brands.css introduced this token for exactly that,
       then left it on the checkbox alone. */
    border: 1px solid var(--brand-control-line);
    border-radius: var(--radius);
    background: var(--brand-surface);
    min-width: 0;
    transition: border-color var(--motion-fast) var(--ease), box-shadow var(--motion-fast) var(--ease);
}

/* A COMPOSED CONTROL KEEPS ITS OWN PADDING INSIDE A FORM FIELD (D4, P23-204).
 *
 * The rule above is the generic one: a control the page wrote itself, in a form field. It is
 * also MORE SPECIFIC than `.kin-search input` — one class and two attribute negations against
 * one class — so it wins wherever a search box is composed inside a field, whatever order the
 * two rules are written in. The time zone picker is the one place that happens today, and the
 * measured result was a 0.6rem left padding on a box whose magnifier is drawn 0.75rem in and
 * 16px wide: the placeholder rendered underneath the icon, which is the overlap Jakes reported
 * on City edit.
 *
 * So this restates the search box's own gutter, and states it through the same token rather
 * than the number, so the icon's space cannot be corrected in one rule and left in another.
 * Nothing else about the control is restated: the border, radius, background and min-width the
 * rule above supplies are the ones the search box wanted anyway. */
.kin-field .kin-search input:not([type="checkbox"]):not([type="radio"]) {
    padding: var(--space-2) var(--search-icon-space);
}

/* ONE FOCUS TREATMENT EVERYWHERE, INCLUDING HERE (P15 §responsive-accessibility#4).
 *
 * base.css states the rule and every button, link, tab and rail item obeys it with a 2px ring.
 * These three rules removed the outline and replaced it with a 1px border colour change plus a
 * 3px halo in --brand-wash — 10% accent over white, which against the field it surrounds
 * measured 1.02:1 to 1.19:1 in the four workspaces. A keyboard user lost the field they were
 * about to type into. The outline is simply not taken away any more; the border colour still
 * changes, which is a second signal and not the only one. Offset zero rather than the global
 * 2px so the ring reads as the field's own edge thickening rather than as a box floating
 * around it. */
.kin-field input:not([type="checkbox"]):not([type="radio"]):focus,
.kin-field select:focus,
.kin-field textarea:focus {
    border-color: var(--brand-focus);
    outline-offset: 0;
}

.kin-field input:not([type="checkbox"]):not([type="radio"]):disabled,
.kin-field select:disabled {
    background: var(--brand-sunken);
    color: var(--brand-muted);
    cursor: not-allowed;
}

.kin-field-hint { font-size: var(--text-xs); color: var(--brand-muted); }

/* A field refusing to store what is in it. Takes the hint's place rather than appearing beside
 * it, because while a refusal stands it is the more useful of the two.
 *
 * THIS ONE IS ALLOWED TO LOOK LIKE A PROBLEM, unlike the development note: something in the box
 * genuinely cannot be saved, and the person needs to notice before they press Save. It borrows
 * the blocked status ink rather than a colour of its own, and pairs the colour with weight so it
 * does not depend on colour alone (WCAG 1.4.1). */
.kin-field-refused {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    color: var(--state-stop-ink);
}

/* And the box itself says so, for the same reason. aria-invalid is what the control sets, so the
 * selector follows the accessibility state rather than a parallel class that could disagree
 * with it. */
.kin-field input[aria-invalid="true"],
.kin-dated input[aria-invalid="true"] {
    border-color: var(--state-stop-line);
}

/* A historical date and how much of it is known, on one line (P8.2 Final §4).
   The certainty selector decides which input follows it, so the pair reads as one question
   rather than as a date with a modifier bolted on. It wraps at narrow widths rather than
   shrinking either control, because a squeezed date input is unusable on a phone. */
.kin-dated {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
}

.kin-dated-certainty { flex: 0 1 auto; }

/* The date box takes what is left, with a floor that keeps a full date visible. */
.kin-dated-value { flex: 1 1 9rem; min-width: 9rem; }

/* A year is four digits and should look like four digits — a box sized for a full date would
   read as one somebody had failed to finish filling in. */
.kin-dated-year {
    flex: 0 0 auto;
    width: 7rem;
    min-width: 0;
    font-variant-numeric: tabular-nums;
}

/* A controlled picker over a long list: a search that filters and a list that decides.
   Two controls rather than a datalist, because a datalist submits whatever was typed — it looks
   like a picker and stores like a text box, which is exactly the typo the time zone field was
   losing values to (P8.2 §8.2.6). */
.kin-picker { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }

.kin-picker-search { min-width: 0; }

/* How many the open list holds and withholds (P40-106): inside the picker, under its list. */
.kin-picker-offer {
    margin: 0;
    font-size: var(--text-xs);
    color: var(--brand-muted);
}

.kin-picker-list {
    /* A multi-row select rather than a dropdown, so the search's effect is visible as it is
       typed rather than only after the list is opened again. */
    padding: var(--space-1) 0;
    border: 1px solid var(--brand-control-line);
    border-radius: var(--radius);
    background: var(--brand-surface);
    font-size: var(--text-sm);
}

.kin-picker-list option { padding: 0.2rem var(--space-3); }

.kin-picker-list:focus {
    border-color: var(--brand-focus);
    outline-offset: 0;
}

/* The collapsed shell a large-list picker opens from (Improvement 3265077910).
   Closed, it is an ordinary field reading as its own answer; opened, it lays the search and the
   list over whatever is below rather than pushing the form apart, so choosing a City does not
   move the three fields under it down the page and back. */
.kin-combo { position: relative; min-width: 0; }

.kin-combo-trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    width: 100%;
    min-width: 0;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--brand-control-line);
    border-radius: var(--radius);
    background: var(--brand-surface);
    color: var(--brand-ink);
    font: inherit;
    font-size: var(--text-sm);
    text-align: left;
    cursor: pointer;
}

.kin-combo-trigger:focus-visible { border-color: var(--brand-focus); }

.kin-combo-trigger:disabled { cursor: not-allowed; opacity: 0.6; }

/* Truncated rather than wrapped: a City named in full with its region can be long, and a trigger
   that grows to two lines moves the form every time a different one is chosen. */
.kin-combo-value {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Nothing chosen yet reads as a prompt and not as a value, the same way an empty select option
   does. */
.kin-combo-unset { color: var(--brand-muted); }

.kin-combo-pop {
    position: absolute;
    z-index: 20;
    top: calc(100% + var(--space-1));
    left: 0;
    right: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-2);
    border: 1px solid var(--brand-control-line);
    border-radius: var(--radius);
    background: var(--brand-surface);
    box-shadow: var(--shadow-lift);
}

.kin-field-locked {
    display: flex;
    align-items: center;
    gap: 0.35em;
    font-size: var(--text-xs);
    color: var(--brand-muted);
}

/* ---- Messages ----------------------------------------------------------------------------------
 * A blocked action leads with the business reason and the resolution. The rule ID is kept —
 * it is what makes a message traceable during support and audit — but deliberately quiet. */

.kin-message {
    border: 1px solid;
    border-radius: var(--radius);
    padding: var(--space-3) var(--space-4);
    margin: var(--space-4) 0;
    font-size: var(--text-sm);
}

.kin-message-title { font-weight: var(--weight-semibold); margin-bottom: var(--space-2); }
.kin-message ul { margin: 0; padding-left: 1.1rem; }
.kin-message li + li { margin-top: var(--space-3); }

.kin-message-stop { background: var(--state-stop-bg); border-color: var(--state-stop-line); color: var(--state-stop-ink); }
.kin-message-ok   { background: var(--state-ok-bg);   border-color: var(--state-ok-line);   color: var(--state-ok-ink); }
.kin-message-note { background: var(--state-note-bg); border-color: var(--state-note-line); color: var(--state-note-ink); }

.kin-violation-message { display: block; font-weight: var(--weight-medium); }
.kin-violation-resolution { display: block; opacity: 0.85; margin-top: 2px; }

/* ---- A refused permanent delete (P40-118 A7) ------------------------------------------------
 * DeletionBlockersPanel: the delete's own refusal first, then the blockers grouped under what the
 * reader has to do. Each group is a quiet heading over the same list a refusal always uses, so the
 * panel reads as one message with sections rather than a stack of separate alerts. The records it
 * names sit on one wrapping line, linked only where their page will open. */

/* Codes and names in a refusal can be long and unbroken (a Client Engagement code, a pricing
   version); they wrap rather than push the panel wider than the page. */
.kin-deletion-blockers { overflow-wrap: anywhere; }

/* The shared delete usually sits in a card foot's row of actions. Its refusal, and the sentence
   saying the record has gone, take the whole row beneath the buttons rather than squeezing in
   beside them. */
.kin-actions > .kin-deletion-blockers,
.kin-actions > .kin-deletion-gone { flex-basis: 100%; }

.kin-deletion-refusal { margin-bottom: var(--space-3); }

.kin-deletion-group + .kin-deletion-group,
.kin-deletion-refusal + .kin-deletion-group { margin-top: var(--space-3); }

.kin-deletion-group-heading {
    margin: 0 0 var(--space-1);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
}

.kin-deletion-records {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1) var(--space-3);
    margin-top: var(--space-1);
}

.kin-deletion-record { overflow-wrap: anywhere; }

.kin-deletion-retention {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: var(--space-1) var(--space-3);
    margin: var(--space-2) 0 0;
}

.kin-deletion-retention > div { display: contents; }
.kin-deletion-retention dt { font-weight: var(--weight-semibold); }
.kin-deletion-retention dd { margin: 0; }

/* A note inside the allowed question: true, worth knowing, and not a reason to stop. */
.kin-delete-note { font-size: var(--text-sm); color: var(--brand-muted); }

.kin-rule-id {
    display: inline-block;
    margin-top: var(--space-1);
    padding: 0 0.3rem;
    font-family: var(--mono);
    font-size: var(--text-xs);
    border: 1px solid currentColor;
    border-radius: var(--radius-sm);
    /* Quiet, not faint: 0.8 is the lowest this small text stays AA on the message ground.
       The ID exists for support and audit, which is exactly when it has to be readable. */
    opacity: 0.8;
}

/* ---- Loading, empty and error --------------------------------------------------------------- */

.kin-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--space-2);
    padding: var(--space-7) var(--space-5);
    color: var(--brand-muted);
}

.kin-state-title { font-weight: var(--weight-semibold); color: var(--brand-ink); }
.kin-state-body { max-width: 46ch; margin: 0; }
.kin-state-actions { margin-top: var(--space-3); }
.kin-state svg { color: var(--brand-line-strong); }

.kin-state-inline { padding: var(--space-5) var(--space-4); }

/* Skeleton rows: the shape of what is coming, not a spinner. The animation is token-driven
   so reduced-motion flattens it with everything else. */
.kin-skeleton {
    display: block;
    height: 0.85rem;
    border-radius: var(--radius-sm);
    background: linear-gradient(90deg,
        var(--brand-sunken) 0%,
        var(--brand-hover) 50%,
        var(--brand-sunken) 100%);
    background-size: 220% 100%;
    animation: kin-shimmer var(--motion-shimmer) var(--ease) infinite;
}

.kin-skeleton + .kin-skeleton { margin-top: var(--space-3); }
.kin-skeleton-60 { width: 60%; }
.kin-skeleton-40 { width: 40%; }

@keyframes kin-shimmer {
    from { background-position: 130% 0; }
    to { background-position: -30% 0; }
}

/* ---- Module tiles ------------------------------------------------------------------------------
 * The reference treatment (P7.2 §29–30): compact DARK cards on the white workspace — the one
 * deliberate use of the chrome below the hero. An icon in the brand's highlighter chip, an
 * honest AVAILABLE / PLANNED tag, a bold white title and a two-line description. Group
 * headings run a hairline to the right so each band reads as a labelled shelf. */

.kin-tile-group + .kin-tile-group { margin-top: var(--space-5); }

.kin-tile-group-title {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--brand-muted);
    margin-bottom: var(--space-3);
}

.kin-tile-group-title::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    background: var(--brand-line);
}

.kin-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--space-3);
}

/* A card that follows a tile grid keeps the page's section beat (P15 §spacing-rhythm#3).
 *
 * Core Overview reads section 32 / tiles 16 four times over and then stops dead: the closing
 * register card has no heading above it and no top margin, so its top edge and the last tile
 * row's bottom edge are the same pixel. The card reads as part of the Application group rather
 * than as the page's own register. Stated structurally, because any page that ends a run of
 * tiles with a card wants the same 32px. */
.kin-tiles + .kin-card { margin-top: var(--space-6); }

/* Inside a module, on the white workspace, a tile is a white card (the HR reference). The
   Home dashboard re-grounds the same tile on the brand chrome — the dark cards of the Home
   reference — via the .kin-home-modules scope below. */
.kin-tile {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--space-3) var(--space-4) var(--space-4);
    background: var(--brand-surface);
    color: var(--brand-ink);
    border: 1px solid var(--brand-line);
    box-shadow: var(--shadow-sm);
    border-radius: var(--radius-lg);
    text-decoration: none;
    transition: box-shadow var(--motion-fast) var(--ease),
                border-color var(--motion-fast) var(--ease),
                transform var(--motion-fast) var(--ease);
}

a.kin-tile:hover {
    border-color: var(--brand-line-strong);
    box-shadow: var(--shadow-lift);
    transform: translateY(-2px);
    text-decoration: none;
}

.kin-tile-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}

/* The icon sits in the brand's own highlighter pairing — lime for HelloKindred, Signal Yellow
   for CapacityCo, Warm Sand for TalentCorp, Sunset Coral for TalentSmith. */
.kin-tile-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: var(--radius);
    background: var(--brand-hi-bg);
    color: var(--brand-hi-ink);
}

/* Honest availability, in words (P7.2 §29): AVAILABLE carries the brand pairing; PLANNED is a
   quiet outline. Never AVAILABLE without real functionality behind it. */
.kin-tile-tag {
    padding: 0.1rem 0.5rem;
    border-radius: var(--radius-pill);
    font-size: 0.62rem;
    font-weight: var(--weight-bold);
    letter-spacing: 0.09em;
    text-transform: uppercase;
    background: var(--brand-hi-bg);
    color: var(--brand-hi-ink);
}

.kin-tile-title { font-weight: var(--weight-semibold); font-size: var(--text-sm); }

.kin-tile-note {
    font-size: var(--text-xs);
    color: var(--brand-muted);
    line-height: 1.45;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Planned: same shelf, quieter voice. The tag says the truth; the chip goes grey. */
.kin-tile-unavailable .kin-tile-icon {
    background: var(--paper-2);
    color: var(--brand-muted);
}

.kin-tile-unavailable .kin-tile-tag {
    background: transparent;
    border: 1px solid var(--brand-line-strong);
    color: var(--brand-muted);
}

.kin-tile-unavailable .kin-tile-title { color: var(--brand-muted); }

/* ---- The Home dashboard's dark tiles (the Home reference) ------------------------------------ */

.kin-home-modules .kin-tile {
    background: var(--brand-chrome);
    color: var(--brand-chrome-ink);
    border-color: var(--brand-chrome-line);
    box-shadow: none;
}

.kin-home-modules a.kin-tile:hover { border-color: var(--brand-chrome-muted); }

.kin-home-modules .kin-tile-note { color: var(--brand-chrome-muted); }

.kin-home-modules .kin-tile-unavailable .kin-tile-icon {
    background: var(--brand-chrome-hover);
    color: var(--brand-chrome-muted);
}

.kin-home-modules .kin-tile-unavailable .kin-tile-tag {
    background: transparent;
    border-color: var(--brand-chrome-line);
    color: var(--brand-chrome-muted);
}

.kin-home-modules .kin-tile-unavailable .kin-tile-title { color: var(--brand-chrome-muted); }

/* ---- Maintenance screens (P8) ----------------------------------------------------------
 * The primitives the Core Element screens are built from. They are here rather than in a
 * core.css because none of them is about Core: a fieldset of independent switches, a pair of
 * facts under a heading, and a right-aligned row action are shapes any module maintaining a
 * shared Element will want, and the second one to want them should find them already made.
 */

/* A group of genuinely independent switches. The legend carries the question they answer, so
   each checkbox can be read on its own rather than as one of a set of alternatives. */
.kin-fieldset {
    border: 1px solid var(--brand-line);
    border-radius: var(--radius);
    padding: var(--space-4) var(--space-5) var(--space-5);
    margin: var(--space-5) 0 0;
}

.kin-fieldset legend {
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    padding: 0 var(--space-2);
    color: var(--brand-ink);
}

.kin-check-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-6);
    margin-bottom: var(--space-3);
}

.kin-check {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-sm);
    cursor: pointer;
    white-space: nowrap;
    /* 24 CSS pixels, which is the WCAG 2.5.8 minimum target. The rows measured 17.8px, and the
       whole label is the target, so this is the one property that fixes it. */
    min-height: 1.5rem;
}

/* `flex: 0 0 auto` is the load-bearing line. `.kin-check` is a flex container with a nowrap
   caption, so the box was the only item able to shrink and it shrank to nothing wherever the
   line overflowed. A control's size is not negotiable: it is 1rem, always.

   BOTH STATES ARE DRAWN HERE RATHER THAN LEFT TO THE BROWSER (§8.2.19). P8.2 kept the native
   control on the reasoning that it already distinguishes checked from unchecked without Kin OS
   drawing either. That reasoning was sound and the outcome was not: a native unchecked box is a
   white square with a hairline border, and on a white work surface Jakes could not see it —
   "the Registered Address checkbox is invisible when unchecked" is the report, and an
   unanswerable "is this ticked or is there no control here?" is a real defect rather than a
   preference.

   So the box is now Kin OS's: a definite 1px border on the unchecked state that reads against
   the surface, and the brand ink filled behind a white tick on the checked one. Drawn rather
   than tinted means the two states differ in fill, border AND glyph, so the answer survives a
   colour-blind reader, a dim screen and a printed page. */
.kin-check input[type="checkbox"] {
    cursor: pointer;
    flex: 0 0 auto;
    width: var(--space-4);
    height: var(--space-4);
    margin: 0.15rem 0 0;
    appearance: none;
    -webkit-appearance: none;
    border: 1px solid var(--brand-control-line);
    border-radius: 3px;
    background: var(--brand-surface);
    background-repeat: no-repeat;
    background-position: center;
    background-size: 0.7rem 0.7rem;
    transition: background-color var(--motion-fast) var(--ease),
                border-color var(--motion-fast) var(--ease);
}

.kin-check input[type="checkbox"]:hover { border-color: var(--brand-accent-ink); }

.kin-check input[type="checkbox"]:checked {
    background-color: var(--brand-accent-ink);
    border-color: var(--brand-accent-ink);
    /* The tick is an inline SVG rather than a font glyph or a rotated border, so it renders at
       any size without depending on a typeface being loaded. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 8.5l3.5 3.5L13 4.5'/%3E%3C/svg%3E");
}

.kin-check input[type="checkbox"]:disabled {
    cursor: not-allowed;
    /* Derived from the brand's own ink rather than a grey literal, so it stays in each
       workspace's palette and cannot smuggle another brand's colour in. */
    background-color: color-mix(in srgb, var(--brand-ink) 6%, var(--brand-surface));
    border-color: var(--brand-line);
}

.kin-check input[type="checkbox"]:disabled:checked {
    background-color: var(--brand-muted);
    border-color: var(--brand-muted);
}

/* Facts about a record that are read rather than edited. */
/* auto-fill, and the form grid's track and gap (P40-107 rework): a short card packs its facts into
   left-hand columns instead of spreading four facts across a wide screen (Currency's Identity sat
   about 375px apart, Organization's two addresses about 740px), and the read view lines up on the
   same tracks as its edit form. Phones see one column either way. */
.kin-detail-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--space-4) var(--space-5);
}

/* Same reason as .kin-fact above: a grid item holds its longest word open unless it is allowed
   not to, and the values here include exception messages and file paths. */
.kin-detail-grid > * { min-width: 0; }

/* .kin-detail-label and .kin-detail-value are styled with .kin-fact dt and dd above (P40-107):
   one fact, one look. */

/* The row's own action, held to the right so the eye can run down a column of them. As narrow
   as its buttons (P40-107 rule 8), the same as .kin-actions-cell, so the data columns take the
   width and the actions sit at one predictable right edge on every register. */
.kin-table-action { text-align: right; white-space: nowrap; width: 1%; }

/* Core Overview's element cards. Wider than a module tile because each carries a count and a
   line of detail, and a three-across grid of them reads as a summary rather than a menu. */
.kin-core-tiles { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }

/* THE LABEL LEADS AND THE COUNT SUPPORTS IT (P40-106, Jakes 652686160 point 1). The count used to
   be the loudest thing on the tile — large, bold, full ink — so the eye landed on "15" before it
   knew what there were fifteen of. Now the title is a step up and the count is a quiet figure in
   the corner: still there for the reader who wants it, no longer the first thing read.
   Scoped to tiles that carry a count, so Home's module tiles, which carry none, are unchanged. */
.kin-tile-count {
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    font-variant-numeric: tabular-nums;
    color: var(--brand-muted);
}

.kin-tile:has(.kin-tile-count) .kin-tile-title { font-size: var(--text-md); }

.kin-tile-meta {
    display: block;
    margin-top: var(--space-2);
    font-size: var(--text-xs);
    color: var(--brand-muted);
}

/* ---- The impersonation banner (P12) ----------------------------------------------------------
 *
 * Above everything, including the top bar, and it cannot be dismissed. Somebody who forgets they
 * are acting as another User is somebody about to make a change in that User's name without
 * meaning to (IMP-005).
 *
 * Deliberately NOT styled as an error. Nothing has gone wrong — this is a state the product
 * supports — and an alarming banner is one people learn to stop seeing. The note tokens give it
 * a surface that is clearly not the ordinary chrome without shouting. */

.kin-impersonation {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-4);
    background: var(--state-note-bg);
    color: var(--state-note-ink);
    border-bottom: 1px solid var(--state-note-line);
    font-size: var(--text-sm);
}

.kin-impersonation strong { font-weight: var(--weight-bold); }

.kin-impersonation .kin-btn { margin-left: auto; }

/* ---- Development guidance ------------------------------------------------------------------
 *
 * One shape for every note that explains a design rather than the business (P14 §14.1). See
 * Components/Shared/DevNote.razor for what belongs in one and what does not.
 *
 * IT MUST NOT LOOK LIKE THE RECORD, AND IT MUST NOT LOOK LIKE A PROBLEM. So it takes the note
 * tokens — the quiet, unalarmed end of the status palette, already used by the impersonation
 * banner — and adds a left rail, which is the cheapest way to say "this is an aside" without
 * borrowing a warning's colour or a card's weight.
 *
 * NO NEW COLOUR VALUES. Every value here is an existing token, so all four brands get a note
 * that belongs to them and the palette tests stay closed. */
.kin-devnote {
    margin: var(--space-4) 0;
    padding: var(--space-3) var(--space-4);
    border-left: 3px solid var(--state-note-line);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    background: var(--state-note-bg);
    color: var(--state-note-ink);
    font-size: var(--text-sm);
}

.kin-devnote-label {
    display: flex;
    align-items: center;
    gap: 0.35em;
    margin-bottom: var(--space-1);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: 0.05em;
    text-transform: uppercase;
    opacity: 0.75;
}

/* The summary is the click target, so it says so — and keeps the marker, because a disclosure
 * with no triangle is a disclosure nobody opens. */
.kin-devnote summary {
    cursor: pointer;
    font-weight: var(--weight-semibold);
}

.kin-devnote summary:focus-visible {
    outline: 2px solid var(--brand-accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

.kin-devnote-body { margin-top: var(--space-2); }

/* Prose inside a note reads as prose: a measure, and space between paragraphs. */
.kin-devnote-body > * { max-width: 78ch; }

.kin-devnote-body > * + * { margin-top: var(--space-2); }

.kin-devnote-body ul,
.kin-devnote-body ol { padding-left: 1.4em; }

.kin-devnote-body li + li { margin-top: var(--space-1); }

/* ---- Areas within one record (close-out §5) -----------------------------------------------
 *
 * Three areas of one Person, not three pages: the header above them says who you are looking
 * at and stays put, and these choose which part of the record is in front of you.
 *
 * ANCHORS, NOT BUTTONS, because each one is a URL. The tab is in the query string so refresh,
 * back and a pasted link all behave — and that only works if the control is genuinely a link,
 * which also gives middle-click and open-in-new-tab for free.
 *
 * The active tab is marked THREE ways: weight, ink, and a rule along its bottom edge. Colour is
 * never the only signal (P7 §54), and on a strip of three items the underline is what the eye
 * actually finds. */
.kin-tabs {
    display: flex;
    align-items: stretch;
    gap: var(--space-1);
    flex-wrap: wrap;
    margin: 0 0 var(--space-5);
    border-bottom: 1px solid var(--brand-line);
}

.kin-tab {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    /* The 2px sits under the container's 1px rule so an inactive tab does not shift when it
       becomes active — the space is already reserved. */
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    color: var(--brand-muted);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    text-decoration: none;
    white-space: nowrap;
    transition: color var(--motion-fast) var(--ease), border-color var(--motion-fast) var(--ease);
}

/* A BUTTON TAB DREW THE BROWSER'S BUTTON (P40-119, p119-verify M6, measured on a static page
   loading base.css and patterns.css). base.css resets only font and colour on a button, and the
   rule above sets only the bottom border, so a <button class="kin-tab"> kept the user agent's grey
   face and its top, left and right bevel: every filter strip read as a row of raised buttons, not
   tabs. The chrome is cleared here, on the element alone, and the bottom border put back so the
   active underline and the reserved 2px behave exactly as they do on an anchor tab.

   AND IT MAY WRAP INSIDE ITSELF. A button tab carries a label, a count and sometimes a mark
   ("People operations 0 of 39 Unsaved"), which at 375px is wider than the screen; held on one line
   it pushed the whole page sideways. The strip still wraps tab by tab first, because a flex item
   is laid out at its natural width before it is ever shrunk; only a tab wider than the line wraps
   its own words. */
button.kin-tab {
    appearance: none;
    background: none;
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    cursor: pointer;
    max-width: 100%;
    flex-wrap: wrap;
    white-space: normal;
    text-align: start;
}

.kin-tab:hover {
    color: var(--brand-ink);
    text-decoration: none;
}

/* The signal colour, not the accent ink: in three workspaces the accent ink is the muted label
   colour, so the active tab's underline looked like a hairline under an inactive one. */
.kin-tab.active {
    color: var(--brand-ink);
    border-bottom-color: var(--brand-signal);
}

/* A RECORD'S AREAS ARE NAVIGATION, A REGISTER'S STATUS STRIP IS A FILTER, AND THEY LOOK
   DIFFERENT (P40-107 rework, Jakes 652889824). The split rests on what Kin OS already makes them:
   areas are anchors, because each is a URL (close-out §5), and filters are buttons, because they
   are page state. A strip of anchors - KinRecordTabs, the one place it is written - closes the
   record's identity on a strong rule with a 3px indicator at body size; a button strip keeps the
   lighter look above. PresentationPatternTests holds the element split. */
.kin-tabs:has(> a.kin-tab) {
    border-bottom: 1px solid var(--brand-line-strong);
    margin: 0 0 var(--space-6);
}
.kin-tabs:has(> a.kin-tab) > .kin-tab {
    font-size: var(--text-base);
    border-bottom-width: 3px;
}

/* The product's one focus colour. The raw accent was HelloKindred's lime, 1.18:1 on white: a
   keyboard reader moving along the tabs could not see where they were. */
.kin-tab:focus-visible {
    outline: 2px solid var(--brand-focus);
    outline-offset: -2px;
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

/* A count belongs to its tab, so it takes the tab's own ink rather than a status colour: it is
 * saying how many, not how they are. */
.kin-tab-count {
    display: inline-block;
    min-width: 1.4em;
    padding: 0.02rem 0.35rem;
    border-radius: var(--radius-pill);
    background: var(--brand-soft);
    color: var(--brand-muted);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.kin-tab.active .kin-tab-count {
    background: var(--brand-hover);
    color: var(--brand-ink);
}

/* ---- Focused surfaces: KinDialog (P40-108, Jakes 13 Oct 2026) ---------------------------------

   READ MODE IS STATIC; EDITING IS FOCUSED. Every edit, create, correction and change opens in a
   native modal <dialog>, opened with showModal() by js/dialog.js. The page behind keeps its place
   as context under a scrim; the dialog is the only thing that can be operated.

   THREE PARTS AND A FOURTH ONLY WHEN NEEDED. A head band carrying the task's title (the same band
   a section title sits on, so the dialog announces itself as the section it is); a body that
   scrolls; a foot that does not, so Save changes and Cancel changes are always reachable however
   long the form. A short line under the title exists only for a consequence the reader must know
   before acting (P40-106 still holds).

   SIZED BY THE TASK. Narrow for a question, standard for one record's fields, wide for groups
   side by side, full for a whole record or an operational task. On a phone every size is the
   whole screen.

   A <dialog> that is not open is display:none in the user-agent sheet, and these rules never
   override that: the layout is declared only for [open], and for the inline fallback a page draws
   when the module could not be loaded (KinDialog fails towards the old inline editor). */
.kin-dialog {
    width: min(44rem, calc(100vw - 2 * var(--space-5)));
    max-width: none;
    max-height: calc(100dvh - 2 * var(--space-6));
    padding: 0;
    border: 0;
    border-radius: var(--radius-lg);
    background: var(--brand-surface);
    color: var(--brand-ink);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}

.kin-dialog[open],
.kin-dialog.kin-dialog-inline {
    display: flex;
    flex-direction: column;
}

.kin-dialog-narrow { width: min(30rem, calc(100vw - 2 * var(--space-5))); }
.kin-dialog-wide { width: min(64rem, calc(100vw - 2 * var(--space-5))); }
.kin-dialog-full {
    width: min(80rem, calc(100vw - 2 * var(--space-5)));
    height: calc(100dvh - 2 * var(--space-6));
}

/* The page behind is context, not competition: dimmed, not hidden. */
.kin-dialog::backdrop { background: rgba(10, 16, 26, 0.48); }

.kin-dialog-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-5);
    background: var(--brand-head);
    border-bottom: 1px solid var(--brand-line-strong);
}

.kin-dialog-title {
    margin: 0;
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
    line-height: var(--leading-tight);
    color: var(--brand-ink);
}

.kin-dialog-close {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    margin: calc(-1 * var(--space-1)) calc(-1 * var(--space-2)) 0 0;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: transparent;
    color: var(--brand-muted);
    cursor: pointer;
}

.kin-dialog-close:hover { background: var(--brand-hover); color: var(--brand-ink); border-color: var(--brand-line-strong); }
.kin-dialog-close:focus-visible { outline: 2px solid var(--brand-focus); outline-offset: 1px; }
.kin-dialog-close:disabled { opacity: 0.45; cursor: not-allowed; }

.kin-dialog-lede {
    margin: 0;
    padding: var(--space-3) var(--space-5) 0;
    font-size: var(--text-sm);
    color: var(--brand-muted);
}

.kin-dialog-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    padding: var(--space-5);
}

.kin-dialog-body > :last-child { margin-bottom: 0; }

/* A GROUP INSIDE A DIALOG: a short heading over its own fields, separated from the next group by
   more space than separates two fields. The heading is the section-title voice one step down, so a
   long form reads Name, then Contact, then Identity documents, the way the record reads them.

   AN h4 IS THE SAME GROUP ONE LEVEL DOWN (P40-117 cross-slice review, regression 3, UX m3). The
   Person's groups in the edit workspace sit under the section's own h3, so their headings are h4
   for the outline, and they lost the rule and the space under them: "Name and contact" sat on
   "Employee number" like one two-line label. The look follows the group, not the level. */
.kin-dialog-group + .kin-dialog-group { margin-top: var(--space-6); }

.kin-dialog-group > :is(h3, h4) {
    margin: 0 0 var(--space-3);
    padding-bottom: var(--space-2);
    font-size: var(--text-base);
    font-weight: var(--weight-bold);
    color: var(--brand-ink);
    border-bottom: 1px solid var(--brand-line-strong);
}

/* A GROUP WITH A CONSEQUENCE. Used sparingly: where the fields in it materially interact, or the
   reader needs to know what a change does before making it. Tinted, so it reads as set apart from
   the ordinary fields around it; its sentence, if any, is one line, not a paragraph per field. */
.kin-dialog-context {
    padding: var(--space-4);
    border-radius: var(--radius);
    background: var(--brand-head);
    border: 1px solid var(--brand-line);
}

.kin-dialog-group > .kin-fieldset:first-child,
.kin-dialog-body > .kin-fieldset:first-child { margin-top: 0; }

/* A lifecycle panel (ReasonPanel) that is the whole of a dialog's task: the dialog is its frame,
   so the panel's own border, ground and inset go, and its title is the dialog's. */
.kin-dialog-body .kin-panel {
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
}

/* THE FOOT STAYS PUT while the body scrolls. Its controls are the edit bar or the create pair,
   unchanged, so they lose the frame they wear on a page: here the foot is the frame. */
.kin-dialog-foot {
    flex: none;
    padding: var(--space-3) var(--space-5);
    border-top: 1px solid var(--brand-line-strong);
    background: var(--brand-soft);
}

.kin-dialog-foot > .kin-edit-bar {
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
}

.kin-dialog-foot > .kin-actions,
.kin-dialog-foot > .kin-edit-bar > .kin-actions { margin: 0; }

/* The discard question takes the foot's place; the question is the first thing in it. */
.kin-dialog-confirm {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3) var(--space-5);
    background: var(--state-note-bg);
    border-top-color: var(--state-note-line);
}

.kin-dialog-confirm-text {
    margin: 0;
    font-size: var(--text-sm);
    color: var(--state-note-ink);
}

/* ON A PHONE THE TASK IS THE SCREEN. Every size fills it, the corners square off, and the foot
   is still pinned to the bottom so Save is in reach of the thumb. */
@media (max-width: 640px) {
    .kin-dialog,
    .kin-dialog-narrow,
    .kin-dialog-wide,
    .kin-dialog-full {
        width: 100vw;
        height: 100dvh;
        max-height: 100dvh;
        margin: 0;
        border-radius: 0;
    }

    .kin-dialog-head,
    .kin-dialog-body,
    .kin-dialog-foot { padding-left: var(--space-4); padding-right: var(--space-4); }
}

/* THE FALLBACK: drawn in the page where the inline editor used to be, framed like a card, when the
   dialog module could not be loaded. Rare by design; it exists so an editor never vanishes. */
.kin-dialog.kin-dialog-inline {
    position: static;
    width: auto;
    max-height: none;
    margin: 0 0 var(--space-4);
    border: 1px solid var(--brand-line);
    box-shadow: var(--shadow-sm);
}
