/*
 * AURA field CRM: its own stylesheet (ADR-161). Hand-written, no build step
 * (ADR-002), no web fonts, no imports, no url(): the system font stack is the
 * real thing and costs no request. The portal's aura.css is not loaded on the
 * CRM, and nothing here is loaded on the portal. Shared look, separate file.
 *
 * The look is iOS 26's (ADR-218, the owner, 2026-10-26): inset grouped cards
 * on a softly dotted grouped background, capsule buttons, a large title, and
 * Liquid Glass on the navigation layer only: the phone's floating tab bar and
 * the wider screen's top bar. Content never sits on glass.
 *
 * Every colour on the CRM is a token defined in this block and its dark
 * sibling below. CrmDesignTokensTest measures each one (WCAG contrast, and the
 * chart palette's colour-vision separation) and fails on any colour written
 * outside a token block, so the palette here is the whole palette. The glass
 * tint is never measured as a raw token. Its tones run from its composite
 * over pure black to its composite over pure white; text on it must lie
 * entirely outside that range (ADR-218 D2), and only then are those two
 * composites the worst a blur can put behind it.
 */

/* ---------------------------------------------------------------- tokens: light */
:root {
  color-scheme: light;

  /* Surfaces. Depth is a layered background plus one soft shadow. */
  --bg: #F2F2F7;               /* page: iOS systemGroupedBackground, which cards sit on */
  --surface: #FFFFFF;          /* inset grouped card, sheet, modal; also the chart surface */
  --surface-2: #F2F2F7;        /* inset fill inside a card: fields, table header */
  --dot: #FAFAFC;              /* the page's dot texture: lighter than --bg, so text over a dot only gains */

  /* The navigation layer (ADR-218). The only #rrggbbaa token: the bars'
     translucent tint. The rule (D2): text on it must lie entirely outside
     the range of tones it can take, #D1D1D1 (over black) to #FFFFFF (over
     white), and only then are the ends its worst case. Over black --text
     is 11.69:1 and --accent 5.05:1; AA holds down to an alpha of C6. */
  --glass: #FFFFFFD1;
  --glass-solid: #FFFFFF;      /* the bars' opaque form: no backdrop-filter, Increase Contrast, Reduce Transparency */

  /* Text. Each is >= 4.5:1 on --bg, --surface, --surface-2, --dot and --glass-solid. */
  --text: #0F172A;             /* the portal's --ink: 16.0:1 on --bg */
  --text-secondary: #5F6E86;   /* the portal's --ink-soft: 4.63:1 on --bg. Never on glass. */

  /* The one accent: interactive things and nothing else. */
  --accent: #5B3FA8;           /* the portal's --vitality-text: 6.92:1 on --bg */
  --accent-strong: #4A3291;    /* hover and pressed fill */
  --on-accent: #FFFFFF;        /* text on an accent fill */
  --accent-soft: #EEEAFB;      /* tinted button, active tab, info note; --accent text on it */
  --accent-edge: #8A73D8;      /* a tinted capsule's edge: 3.41:1 on --surface-2, 3.22:1 on --accent-soft */

  /* Lines. A control's edge must be seen (>= 3:1); a separator need not be. */
  --control-border: #7C879A;   /* field outline: 3.25:1 on --bg */
  --separator: #E5E5EA;        /* hairline between grouped rows: DECORATIVE ONLY */

  /* Status: reserved meanings, never a chart series, always with a label. */
  --success: #256B55;
  --success-soft: #E5F2EC;
  --warning: #8A5300;
  --warning-soft: #FBF0DC;
  --danger: #A1392B;
  --danger-soft: #FBEAE6;

  /* Fixed white in both modes: a QR code must scan, so its quiet zone stays white. */
  --qr-bg: #FFFFFF;

  /* Charts. Drawn on --surface only. Categorical slots are assigned in this
     order and never cycled; a sixth series is not a new hue (ADR-161). */
  --chart-1: #026FD7;          /* blue */
  --chart-2: #8F6B09;          /* gold */
  --chart-3: #10A49E;          /* teal */
  --chart-4: #EB681D;          /* orange */
  --chart-5: #BC3577;          /* rose */
  /* Sequential: one hue (blue), light to dark = less to more. */
  --seq-1: #87BAFD;
  --seq-2: #5FA1F3;
  --seq-3: #4384D5;
  --seq-4: #2769B7;
  --seq-5: #024E9A;
  --chart-grid: #E5E5EA;       /* gridline: DECORATIVE ONLY, recessive */
  --chart-axis: #7C879A;       /* baseline and axis: >= 3:1 */
  --chart-suppressed: #6B7588; /* hatch ink of a suppressed cell: >= 3:1 */

  /* Type: the system font stack, so nothing is fetched. -apple-system is SF
     Pro on Apple devices, with its optical sizes. Sizes follow iOS Dynamic
     Type at its default size (ADR-218). */
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --text-xs: .75rem;           /* 12px  caption 1: tab label, chart tick */
  --text-sm: .8125rem;         /* 13px  footnote, secondary label */
  --text-subhead: .9375rem;    /* 15px  subhead: a phone's lede, a wide screen's tab */
  --text-base: 1.0625rem;      /* 17px  body, headline */
  --text-lg: 1.25rem;          /* 20px  title 3: card title */
  --text-xl: 1.375rem;         /* 22px  title 2: section title */
  --text-2xl: 1.75rem;         /* 28px  title 1 */
  --text-large-title: 2.125rem; /* 34px  the large title: a page's h1 */
  --text-display: 2.5rem;      /* 40px  stat-tile figure */
  --leading-tight: 1.2;
  --leading-normal: 1.5;
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;          /* the large title only */

  /* Spacing: a 4px base. */
  --space-1: .25rem;           /*  4px */
  --space-2: .5rem;            /*  8px */
  --space-3: .75rem;           /* 12px */
  --space-4: 1rem;             /* 16px  the side gutter at 390px */
  --space-5: 1.5rem;           /* 24px */
  --space-6: 2rem;             /* 32px */
  --space-7: 3rem;             /* 48px */
  --space-8: 4rem;             /* 64px */

  /* Radius: five values, one job each. Nothing is rounded outside this scale.
     Corners are concentric: a card's 28px is a field's 12px plus the card's
     16px padding. */
  --radius-control: 12px;      /* field, select, textarea, QR frame */
  --radius-card: 28px;         /* inset grouped card, tile, notice */
  --radius-sheet: 32px;        /* the wide screen's glass top bar */
  --radius-modal: 36px;        /* modal dialog: reserved */
  --radius-pill: 999px;        /* capsule: every button, badge and tab, the phone's tab bar */

  /* Two shadows: a card lifted off --bg, and the floating glass layer with its rim. */
  --shadow: 0 1px 2px rgba(15, 23, 42, .06), 0 4px 16px rgba(15, 23, 42, .06);
  --shadow-glass: 0 8px 24px rgba(15, 23, 42, .12), inset 0 1px 0 rgba(255, 255, 255, .7);
  --glass-filter: blur(20px) saturate(160%);

  /* Motion: short and eased. Reduced motion sets every duration to zero. */
  --duration-fast: 150ms;
  --duration-base: 200ms;
  --duration-slow: 250ms;
  --ease: cubic-bezier(.2, 0, 0, 1);

  /* A field CRM is used one-handed on a phone. */
  --hit-min: 44px;

  /* Layout. */
  --content-max: 72rem;        /* the page at its widest */
  --measure-narrow: 28rem;     /* a form screen's column, gutters included */
  --tile-row: 8rem;            /* the size grid's row: a 1x1 tile is at least this tall */
  --tabbar-height: 4rem;       /* the phone's tab bar; the page keeps this clear beneath its content */
  --topbar-clear: 5.5rem;      /* a wide screen's sticky bar: its one 64px row, its 12px offset and a 12px gap; focus and the skip link scroll clear of it */
}

/* ---------------------------------------------------------------- tokens: dark
   A sibling, not a filter: each value chosen and measured against the dark
   surfaces. Apple's neutral base and elevated greys (ADR-218), not a tinted
   navy. Two copies, the OS setting and an explicit data-theme="dark";
   data-theme="light" on <html> beats an OS in dark mode. CrmDesignTokensTest
   holds the copies identical and the token names the same as light's. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #000000;
    --surface: #1C1C1E;
    --surface-2: #2C2C2E;
    --dot: #1C1C1E;
    --glass: #242426E6;
    --glass-solid: #242426;
    --text: #F5F5F7;
    --text-secondary: #A1A1A8;
    --accent: #B9A6FF;
    --accent-strong: #CBBDFF;
    --on-accent: #1A1033;
    --accent-soft: #2A2350;
    --accent-edge: #8571D6;
    --control-border: #7C7C85;
    --separator: #38383A;
    --success: #5CC8A5;
    --success-soft: #102E26;
    --warning: #F0B44C;
    --warning-soft: #33260C;
    --danger: #FF8F80;
    --danger-soft: #3B1B17;
    --qr-bg: #FFFFFF;
    --chart-1: #308CF6;
    --chart-2: #A8831F;
    --chart-3: #04A19B;
    --chart-4: #E8692A;
    --chart-5: #CF4B89;
    --seq-1: #0C54A0;
    --seq-2: #3072C1;
    --seq-3: #4F91E2;
    --seq-4: #73B1FF;
    --seq-5: #ADD1FF;
    --chart-grid: #2C2C2E;
    --chart-axis: #7C7C85;
    --chart-suppressed: #8A93A6;
    --shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 4px 16px rgba(0, 0, 0, .35);
    --shadow-glass: 0 8px 24px rgba(0, 0, 0, .5), inset 0 1px 0 rgba(255, 255, 255, .12);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #000000;
  --surface: #1C1C1E;
  --surface-2: #2C2C2E;
  --dot: #1C1C1E;
  --glass: #242426E6;
  --glass-solid: #242426;
  --text: #F5F5F7;
  --text-secondary: #A1A1A8;
  --accent: #B9A6FF;
  --accent-strong: #CBBDFF;
  --on-accent: #1A1033;
  --accent-soft: #2A2350;
  --accent-edge: #8571D6;
  --control-border: #7C7C85;
  --separator: #38383A;
  --success: #5CC8A5;
  --success-soft: #102E26;
  --warning: #F0B44C;
  --warning-soft: #33260C;
  --danger: #FF8F80;
  --danger-soft: #3B1B17;
  --qr-bg: #FFFFFF;
  --chart-1: #308CF6;
  --chart-2: #A8831F;
  --chart-3: #04A19B;
  --chart-4: #E8692A;
  --chart-5: #CF4B89;
  --seq-1: #0C54A0;
  --seq-2: #3072C1;
  --seq-3: #4F91E2;
  --seq-4: #73B1FF;
  --seq-5: #ADD1FF;
  --chart-grid: #2C2C2E;
  --chart-axis: #7C7C85;
  --chart-suppressed: #8A93A6;
  --shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 4px 16px rgba(0, 0, 0, .35);
  --shadow-glass: 0 8px 24px rgba(0, 0, 0, .5), inset 0 1px 0 rgba(255, 255, 255, .12);
}

/* ---------------------------------------------------------------- base */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background-color: var(--bg);
  /* The soft dotted backdrop (the owner's screenshots): 1px dots on a 20px
     pitch, 1.07:1 on --bg, lighter than it, so text over a dot only gains.
     The one gradient in this file; Increase Contrast and forced colours drop it. */
  background-image: radial-gradient(var(--dot) 1px, transparent 1.5px);
  background-size: 20px 20px;
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  /* Every figure is tabular, so columns align and numbers do not jitter. */
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  /* A long address breaks rather than pushing a 390px page sideways. Not
     `anywhere`: inherited, that also shrinks every flex item's and table
     cell's min-content to one character, so a squeezed table would split a
     figure mid-digit. An element that must break inside a flex row (a row's
     value) sets `anywhere` itself. */
  overflow-wrap: break-word;
}
/* SF's optical sizes track themselves, so no heading sets letter-spacing. */
h1, h2, h3 { margin: 0 0 var(--space-2); line-height: var(--leading-tight); font-weight: var(--weight-semibold); }
h1 { font-size: var(--text-large-title); font-weight: var(--weight-bold); } /* the large title */
h2 { font-size: var(--text-xl); }
h3 { font-size: var(--text-lg); }
p { margin: 0 0 var(--space-4); }
a { color: var(--accent); }
ol, ul { margin: 0 0 var(--space-4); padding-left: var(--space-5); }
li + li { margin-top: var(--space-1); }
code, kbd, samp { font-family: var(--font-mono); }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; } /* the one focus ring; nothing removes it */

label { display: block; font-size: var(--text-sm); font-weight: var(--weight-medium); margin-bottom: var(--space-1); }
input, select, textarea {
  width: 100%;
  min-height: var(--hit-min);
  font: inherit;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--control-border);
  border-radius: var(--radius-control);
  padding: var(--space-2) var(--space-3);
  transition: border-color var(--duration-fast) var(--ease);
}
/* A field keeps the global focus ring (an --accent outline, >= 3:1 on every
   surface). The ring is never swapped for an --accent-soft glow: that is
   1.07:1 on light --bg, so a focused field would look unfocused, and an
   inline border on a view would also beat a border-colour change. */
input:focus-visible, select:focus-visible, textarea:focus-visible { border-color: var(--accent); }
::placeholder { color: var(--text-secondary); opacity: 1; }
button { font: inherit; }

/* ---------------------------------------------------------------- layout
   The masthead and the page column. A form screen is narrow; anything else
   uses the content width. Views choose with the layout's `width`. The
   viewport is `viewport-fit=cover`, so every gutter is at least the safe
   area's inset: in landscape on a notched iPhone, text never sits under the
   sensor housing. */
.masthead {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--space-4);
  padding-top: max(var(--space-4), env(safe-area-inset-top));
  padding-right: max(var(--space-4), env(safe-area-inset-right));
  padding-left: max(var(--space-4), env(safe-area-inset-left));
}
.masthead--narrow { max-width: var(--measure-narrow); } /* lines the wordmark up with a form column */
.masthead__brand { min-width: 0; }
.masthead__user { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.masthead__name { color: var(--text); font-size: var(--text-sm); }
.wordmark { margin: 0; font-size: var(--text-base); font-weight: var(--weight-semibold); letter-spacing: .5em; }
.wordmark-descriptor { margin: 0; font-size: var(--text-sm); color: var(--text-secondary); }
/* On the signed-in screens the masthead is the glass bar on a wide screen, and glass carries --text and --accent only. */
.masthead--app .wordmark-descriptor { color: var(--text); }
.page {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--space-2) var(--space-4) var(--space-8);
  padding-right: max(var(--space-4), env(safe-area-inset-right));
  padding-left: max(var(--space-4), env(safe-area-inset-left));
}
.page--narrow { max-width: var(--measure-narrow); }

/* Skip to content: the navigation comes first in the source, on every width. Hidden until it has focus, then a capsule. */
.skip-link {
  position: absolute;
  z-index: 20;
  top: var(--space-2);
  left: var(--space-4);
  display: inline-flex;
  align-items: center;
  min-height: var(--hit-min);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--on-accent);
  font-weight: var(--weight-semibold);
  text-decoration: none;
  transform: translateY(-200%);
}
.skip-link:focus-visible { transform: none; }

/* The navigation (ADR-218). One <nav> of real links in the masthead, never
   duplicated: on a phone it is the floating glass tab bar at the bottom of
   the screen (four sections and More), and on a wider screen text capsules
   in the glass top bar (every section, no More). Which links show at each
   width is display: none on the others, so a screen reader is given one set.
   The current section wears an accent capsule with an accent edge, so it is
   not told by its fill alone. Each bar's 1px transparent edge (drawn in
   forced-colours mode) is set at the width where it is the bar, so the
   other is not outlined as a box. */
.tabbar, .masthead--app {
  background: var(--glass-solid); /* the bar where backdrop-filter is unsupported: opaque, measured */
}
.tabbar { display: flex; align-items: center; }
.tab {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  min-height: var(--hit-min);
  min-width: var(--hit-min);
  padding: var(--space-2) var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  color: var(--text);
  font-size: var(--text-subhead);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  text-align: center;
  text-decoration: none;
  transition: background-color var(--duration-fast) var(--ease), border-color var(--duration-fast) var(--ease);
}
.tab:hover { border-color: var(--control-border); }
.tab[aria-current] { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }
.tab .icon { width: 1.5rem; height: 1.5rem; }
.tab__label { min-width: 0; }

/* Type roles beyond the headings. */
.lede { color: var(--text-secondary); margin-bottom: var(--space-5); }
.footnote { color: var(--text-secondary); font-size: var(--text-sm); }
form + form { margin-top: var(--space-4); }

/* ---------------------------------------------------------------- primitives (ADR-161, PR 2)
   Button, field, card, row, badge, empty state, notice. Each is a Blade
   component in resources/views/crm/components with a closed vocabulary;
   CrmPrimitivesTest renders every screen and holds them to this file. */

/* Button. One size: every variant is at least the 44px hit target, and every
   one is a capsule (ADR-218). Pressing scales it a touch, as iOS does; reduced
   motion takes the transition to zero, so it is instant. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--hit-min);
  min-width: var(--hit-min);
  padding: var(--space-2) var(--space-5);
  border: 1px solid transparent; /* invisible, but drawn in forced-colours mode */
  border-radius: var(--radius-pill);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease), border-color var(--duration-fast) var(--ease), transform var(--duration-fast) var(--ease);
}
.btn:active { transform: scale(.97); }
/* Prominent: the accent on the background, as the HIG asks. At most one a screen. */
.btn--primary { background: var(--accent); color: var(--on-accent); }
.btn--primary:hover, .btn--primary:active { background: var(--accent-strong); }
/* Tinted: an accent wash with an edge that reaches 3:1. */
.btn--secondary { background: var(--accent-soft); color: var(--accent); border-color: var(--accent-edge); }
.btn--secondary:hover, .btn--secondary:active { border-color: var(--accent); }
/* Pressed and waiting (public/js/crm-submit-once.js, ADR-211): the label says
   so; the cursor agrees. No fade, so the label keeps its contrast. */
.btn[aria-disabled="true"] { cursor: progress; }
/* A text button: no fill, still 44px tall and wide, underlined so it is not
   told apart by colour alone. No side padding, so its text lines up with the
   content edge; the min-height and min-width keep the hit target. */
.btn--plain {
  justify-content: flex-start;
  padding: var(--space-2) 0;
  background: none;
  color: var(--accent);
  font-weight: var(--weight-regular);
  text-align: start;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.btn--block { display: flex; width: 100%; }

/* Field: a label above a full-width input. The input itself is the base rule. */
.field { margin-bottom: var(--space-4); }
.field__hint { margin: var(--space-1) 0 0; font-size: var(--text-sm); color: var(--text-secondary); }
.field__input--code {
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-xl);
  letter-spacing: .3em;
  text-align: center;
  text-indent: .3em; /* balances the trailing letter-space, so six digits sit centred */
}
/* A select is drawn by this file, not the platform: Safari's native control
   ignores min-height and the radius (25px tall, 5px corners beside a 44px
   field). <x-crm::select> wraps it so the chevron, the cue that it opens a
   list, can be drawn: the record row's chevron turned down, in a text colour
   (>= 4.5:1, well over a graphic's 3:1), and never in the way of a tap. */
.field__select { position: relative; }
.field__select > select { -webkit-appearance: none; appearance: none; padding-inline-end: var(--space-7); }
.field__select::after {
  content: "";
  position: absolute;
  top: 50%;
  inset-inline-end: var(--space-4);
  padding: var(--space-1);
  border-right: 2px solid var(--text-secondary);
  border-bottom: 2px solid var(--text-secondary);
  transform: translateY(-75%) rotate(45deg);
  pointer-events: none;
}
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] { border-color: var(--danger); }
/* A field's own error, under it and tied to it (aria-describedby); its icon says "error" without colour. */
.field__error { display: flex; align-items: flex-start; gap: var(--space-1); margin: var(--space-1) 0 0; font-size: var(--text-sm); color: var(--danger); }
.field__error .icon { margin-top: var(--space-1); }

/* Card: an inset grouped surface on --bg, one soft shadow, no heavy border.
   Header: a title (--text-lg, semibold), an optional secondary line and
   optional trailing actions. The header and its actions wrap, so a long
   title and two badges fit a nested card at 390px. The padding steps up
   once, at 48rem. */
.card {
  min-width: 0;
  margin: 0 0 var(--space-4);
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid transparent; /* a shadow vanishes in forced-colours mode; this edge does not */
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
}
.card__header { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-3); }
.card__title { margin: 0; font-size: var(--text-lg); font-weight: var(--weight-semibold); line-height: var(--leading-tight); }
.card__subtitle { margin: var(--space-1) 0 0; font-size: var(--text-sm); color: var(--text-secondary); }
.card__actions { flex: 0 1 auto; display: flex; flex-wrap: wrap; gap: var(--space-2); }
.card__body > :last-child { margin-bottom: 0; }

/* The size grid. Cards are placed on it by size, in source order (never
   `dense`, which would put focus order and reading order out of step).
   Two columns on a phone, four from 48rem; a row is at least --tile-row
   tall and grows with its content. A layout engine sets a card's size and
   order and nothing else. */
.grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: minmax(var(--tile-row), auto);
  gap: var(--space-4);
  margin: 0 0 var(--space-4);
}
.grid > .card { margin: 0; }
.card--1x1 { grid-column: span 1; }
.card--2x1 { grid-column: span 2; }
.card--2x2 { grid-column: span 2; grid-row: span 2; }
.card--full { grid-column: 1 / -1; }

/* Rows: the grouped list (label and value), 44px tall, hairline between. A
   data table uses the same row metrics; its first use is a chart's table (PR 4). */
.rows { margin: 0; }
.row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-1) var(--space-3);
  min-height: var(--hit-min);
  padding: var(--space-2) 0;
}
.row + .row { border-top: 1px solid var(--separator); }
.row__label { margin: 0; color: var(--text-secondary); }
.row__value { margin: 0; text-align: end; overflow-wrap: anywhere; }
/* Stacked rows: a name over its description, both from the start edge, for
   text too long to share a phone's line with its label. The name is the
   primary text here and the description the secondary (PR 5). */
.rows--stacked .row { display: block; padding: var(--space-3) 0; }
.rows--stacked .row__label { color: var(--text); font-weight: var(--weight-medium); }
.rows--stacked .row__value { margin-top: var(--space-1); text-align: start; color: var(--text-secondary); font-size: var(--text-sm); }
.rows + .footnote { margin: var(--space-3) 0 0; } /* a note under a grouped list, e.g. how you sign in on home */
.rows + form { margin-top: var(--space-4); } /* sign-out under who is signed in, on More */
.table { width: 100%; border-collapse: collapse; }
.table th, .table td { height: var(--hit-min); padding: var(--space-2) var(--space-3); text-align: start; vertical-align: middle; }
.table th { background: var(--surface-2); color: var(--text-secondary); font-size: var(--text-sm); font-weight: var(--weight-medium); }
.table tbody tr + tr td, .table tbody tr + tr th { border-top: 1px solid var(--separator); }
.table .num { text-align: end; }

/* Badge: a capsule label, never colour alone. A status badge also carries its icon. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 0 var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  white-space: nowrap;
}
.badge--success { background: var(--success-soft); color: var(--success); }
.badge--warning { background: var(--warning-soft); color: var(--warning); }
.badge--danger { background: var(--danger-soft); color: var(--danger); }
.icon { flex: none; width: 1em; height: 1em; }

/* Notice: a flash message or the form's errors. */
.notice {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius-card);
}
.notice .icon { margin-top: var(--space-1); }
.notice__body { flex: 1; min-width: 0; }
.notice__body > * { margin: 0; }
.notice__body > * + * { margin-top: var(--space-1); }
.notice--info { background: var(--accent-soft); color: var(--text); }
.notice--info .icon { color: var(--accent); }
.notice--success { background: var(--success-soft); color: var(--success); }
.notice--warning { background: var(--warning-soft); color: var(--warning); }
.notice--danger { background: var(--danger-soft); color: var(--danger); }

/* Empty state: says what will be here, quietly. */
.empty { padding: var(--space-6) var(--space-4); text-align: center; color: var(--text-secondary); }
.empty__title { margin: 0 0 var(--space-1); font-size: var(--text-base); font-weight: var(--weight-semibold); color: var(--text); }
.empty__body { max-width: var(--measure-narrow); margin: 0 auto; font-size: var(--text-sm); }
.empty__action { margin-top: var(--space-4); }

/* Your team (ADR-169): a list of people's cards, each followed by the list of
   those who report to them. A nested list is indented for two levels (no
   rule down its edge: --separator is a row's hairline, not an edge); deeper
   lists stop indenting, so a deep tree still fits a 390px phone, and each
   card's "Reports to" says who is above in words. */
.team { margin: 0; padding: 0; list-style: none; }
.team__member + .team__member { margin-top: 0; }
.team .team { padding-inline-start: var(--space-5); }
.team .team .team .team { padding-inline-start: 0; }

/* Accounts and contacts (ADR-170). A list of records: each a link (the 44px
   plain button) or a heading, over a line of what it is, with the row's
   hairline between. A page's actions sit in a wrapping row above its cards;
   a search's fields stack above the list it filters; previous and next
   wrap round where you are. Nothing here sets a width, so all of it fits a
   390px phone. */
.actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0 0 var(--space-4); }
.filters { margin: 0 0 var(--space-4); }
.records { margin: 0; padding: 0; list-style: none; }
.record { padding: var(--space-2) 0; }
.record + .record { margin-top: 0; border-top: 1px solid var(--separator); }
/* A record's link is an iOS list row (ADR-218): the row's full width, primary
   text, and a chevron at its end. The chevron is the cue that it opens
   something, so the row needs no underline; it is drawn in --text-secondary,
   a text colour, so it reaches 4.5:1, well over 3:1. */
.record > .btn--plain {
  display: flex;
  width: 100%;
  justify-content: flex-start;
  align-items: center;
  gap: var(--space-3);
  color: var(--text);
  font-weight: var(--weight-semibold);
  text-decoration: none;
}
.record > .btn--plain::after {
  content: "";
  flex: none;
  margin-inline-start: auto;
  padding: var(--space-1);
  border-top: 2px solid var(--text-secondary);
  border-right: 2px solid var(--text-secondary);
  transform: rotate(45deg);
}
.record > .btn--plain .icon { font-size: var(--text-xl); color: var(--accent); } /* 22px: an icon is 1em square */
.record__title { margin: var(--space-2) 0 0; font-size: var(--text-base); font-weight: var(--weight-semibold); }
.record__meta { margin: 0; font-size: var(--text-sm); color: var(--text-secondary); }
.pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2) var(--space-4); margin: var(--space-4) 0 0; }
.pager__status { margin: 0; font-size: var(--text-sm); color: var(--text-secondary); }
/* A contact's phone (ADR-215): the number, then its "Text" link (the 44px
   plain button), wrapping under it on a narrow line. Sets no width. */
.phone { display: inline-flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 0 var(--space-3); }

/* A list to tick (the route planner's stops, ADR-219): each row a label at
   least a hit target tall, so the whole row toggles its box, with the
   row's hairline between. The fieldset is told it may shrink (min-width 0),
   since its default is its content's width, which would scroll a phone. */
.choices { min-width: 0; margin: 0 0 var(--space-4); padding: 0; border: 0; }
.choices__legend { margin: 0 0 var(--space-1); padding: 0; font-size: var(--text-sm); font-weight: var(--weight-medium); }
.choice { display: flex; align-items: center; gap: var(--space-3); min-height: var(--hit-min); margin: 0; padding: var(--space-2) 0; font-size: var(--text-base); font-weight: var(--weight-regular); cursor: pointer; }
.choice + .choice { border-top: 1px solid var(--separator); }
/* The box keeps the fields' 44px height and is as wide, so it is a hit target on its own. */
.choice input { flex: none; width: var(--hit-min); margin: 0; padding: 0; accent-color: var(--accent); }
.choice__text { display: flex; flex-direction: column; min-width: 0; overflow-wrap: anywhere; }
.choice__meta { font-size: var(--text-sm); color: var(--text-secondary); }

/* Numbered steps (TOTP enrolment): the number is a quiet secondary label. */
.steps { margin: 0 0 var(--space-5); padding-left: var(--space-5); }
.steps li + li { margin-top: var(--space-2); }
.steps li::marker { color: var(--text-secondary); font-weight: var(--weight-semibold); }

/* The QR code: on white in both modes, so it scans. */
.qr { text-align: center; }
.qr > * { margin: 0; }
.qr > * + * { margin-top: var(--space-3); }
.qr-frame { display: inline-block; padding: var(--space-3); background: var(--qr-bg); border-radius: var(--radius-control); }
.qr-frame svg { display: block; max-width: 100%; height: auto; }
.secret {
  font-family: var(--font-mono);
  font-size: var(--text-base);
  letter-spacing: .1em;
  word-break: break-all;
  text-wrap: balance; /* four groups a line, not seven and one */
  -webkit-user-select: all; /* one tap selects the whole key, for copying into an app */
  user-select: all;
}
/* A group of four never breaks inside itself; the gap between groups is a margin, not a space, so a copy is still the bare key. */
.secret > span { display: inline-block; }
.secret > span + span { margin-inline-start: var(--space-2); }

/* ---------------------------------------------------------------- charts (ADR-162, PR 4)
   Inline SVG drawn on the server from a published set: a stat tile, a
   grouped bar chart and a line or area chart. Drawn on --surface only (in a
   card): the chart slots are measured against it. No hover layer, no
   tooltip, no animation: a chart shows what the publication shows and
   nothing on demand. Series n always wears --chart-n; there is no sixth. */
.chart { margin: 0; }
.chart__title { margin: 0 0 var(--space-2); font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text); }
.chart__legend { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); margin: 0 0 var(--space-3); padding: 0; list-style: none; font-size: var(--text-sm); color: var(--text-secondary); }
.chart__legend li + li { margin-top: 0; }
.chart__key { display: inline-flex; align-items: center; gap: var(--space-2); }
.chart__swatch { flex: none; width: .75rem; height: .75rem; }
.chart__plot { margin: 0 0 var(--space-3); }
.chart__group + .chart__group { margin-top: var(--space-3); }
.chart__label { margin: 0 0 var(--space-1); font-size: var(--text-sm); color: var(--text); }
/* Every SVG of a chart shares one width, so groups and axis line up; it scales down to any phone and stops growing at the narrow measure. */
.chart__svg { display: block; width: 100%; max-width: var(--measure-narrow); height: auto; overflow: visible; }
.chart__grid { stroke: var(--chart-grid); stroke-width: 1; vector-effect: non-scaling-stroke; shape-rendering: crispEdges; }
.chart__axis { stroke: var(--chart-axis); stroke-width: 1; vector-effect: non-scaling-stroke; shape-rendering: crispEdges; }
.chart__tick { fill: var(--text-secondary); font-size: var(--text-xs); }
.chart__value { fill: var(--text); font-size: var(--text-xs); font-weight: var(--weight-medium); }
.chart__value--suppressed { fill: var(--text-secondary); font-weight: var(--weight-regular); }
.chart__bar--1, .chart__dot--1 { fill: var(--chart-1); }
.chart__bar--2, .chart__dot--2 { fill: var(--chart-2); }
.chart__bar--3, .chart__dot--3 { fill: var(--chart-3); }
.chart__bar--4, .chart__dot--4 { fill: var(--chart-4); }
.chart__bar--5, .chart__dot--5 { fill: var(--chart-5); }
.chart__line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart__line--1 { stroke: var(--chart-1); }
.chart__line--2 { stroke: var(--chart-2); }
.chart__line--3 { stroke: var(--chart-3); }
.chart__line--4 { stroke: var(--chart-4); }
.chart__line--5 { stroke: var(--chart-5); }
.chart__dot { stroke: var(--surface); stroke-width: 2; } /* the surface ring keeps a marker legible where it meets a line */
.chart__area { fill: var(--chart-1); fill-opacity: .1; } /* a wash, one series only */
/* A suppressed cell: the hatch (its fill is the pattern, set on the element) and nothing else. */
.chart__hatch { stroke: var(--chart-suppressed); stroke-width: 1.5; }
/* The table twin: a native disclosure, 44px tall, no script. */
.chart__figures { margin: 0; }
.chart__toggle { display: flex; align-items: center; min-height: var(--hit-min); color: var(--accent); cursor: pointer; }
.chart__table-wrap { overflow-x: auto; }
.table tbody th { background: none; color: var(--text); font-size: inherit; font-weight: var(--weight-regular); }

/* Stat tile: one published figure, large; type carries it. */
.stat { margin: 0; }
.stat__label { margin: 0 0 var(--space-1); font-size: var(--text-sm); color: var(--text-secondary); }
.stat__value { margin: 0; font-size: var(--text-display); font-weight: var(--weight-semibold); line-height: var(--leading-tight); color: var(--text); }
/* --text-base, so the word and its hatch fit a 1x1 tile at 390px (139px of content). */
.stat__value--suppressed { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-base); color: var(--text-secondary); }
.stat__value--long { font-size: var(--text-xl); }     /* 6-7 characters: 99,999 to 999,999 */
.stat__value--longer { font-size: var(--text-lg); }   /* 8-11 characters: up to 999,999,999 */
.stat__value--suppressed .chart__swatch { width: 1rem; height: 1rem; }
.stat__note { margin: var(--space-1) 0 0; font-size: var(--text-sm); color: var(--text-secondary); }
.stat__caption { margin: var(--space-1) 0 0; font-size: var(--text-sm); color: var(--text-secondary); }

@media (min-width: 48rem) {
  .card { padding: var(--space-5); }
  .page--narrow { padding-top: var(--space-6); } /* a form screen breathes on a wide display */
  .grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ---------------------------------------------------------------- Liquid Glass (ADR-218)
   The regular variant only, on the navigation layer only. Where
   backdrop-filter is unsupported the bars keep --glass-solid (above). Both
   spellings, always together: iOS 17 and earlier know only the prefixed one.
   --text and --accent lie entirely outside the range of tones the tint can
   take (its composites over pure black and pure white, ADR-218 D2), so those
   two composites bound their contrast, and both are AA: whatever the blur
   puts behind it, the text on it stays legible. */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .tabbar, .masthead--app {
    background: var(--glass);
    -webkit-backdrop-filter: var(--glass-filter);
    backdrop-filter: var(--glass-filter);
    box-shadow: var(--shadow-glass);
  }
}

/* ---------------------------------------------------------------- a phone: the floating tab bar
   Fixed over the bottom of the screen, inside the safe area, over the home
   indicator's zone as iOS 26's is. The masthead above is a plain row in the
   content layer, not glass. The page keeps the bar's height clear beneath
   its last row, so the bar never covers content. Four sections and More;
   the rest of the sections are on More. */
@media (max-width: 43.75rem) {
  .masthead--app { background: none; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
  .tabbar {
    position: fixed;
    z-index: 10;
    left: max(var(--space-4), env(safe-area-inset-left));
    right: max(var(--space-4), env(safe-area-inset-right));
    bottom: max(var(--space-3), calc(env(safe-area-inset-bottom) - var(--space-3)));
    justify-content: space-between;
    gap: 0;
    min-height: var(--tabbar-height);
    padding: var(--space-1);
    border: 1px solid transparent; /* drawn in forced-colours mode */
    border-radius: var(--radius-pill);
  }
  .tab {
    flex: 1 1 auto;
    flex-direction: column;
    gap: 0;
    padding: var(--space-1) var(--space-2);
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
  }
  .tab[aria-current] { font-weight: var(--weight-semibold); }
  .tab--overflow { display: none; }
  .page--app {
    padding-bottom: var(--space-8);
    padding-bottom: calc(var(--tabbar-height) + var(--space-6) + env(safe-area-inset-bottom));
  }
  .lede { font-size: var(--text-subhead); }
  /* Focus moved by the keyboard, and a link to a fragment, stop above the bar, never under it. */
  html { scroll-padding-bottom: calc(var(--tabbar-height) + var(--space-6) + env(safe-area-inset-bottom)); }
}
@media (max-width: 25.9375rem) {
  .masthead__name { display: none; } /* home's "Signed in as" says who you are */
}
@media (max-width: 22.4375rem) {
  .tab { padding: var(--space-1); } /* five labels fit a 320px phone */
}
/* Narrower than a 320px phone: a 390px iPhone at 150% page zoom or more, or
   a larger default text size (the breakpoints are in rem, so they follow
   it). Five 44px tabs and their labels no longer fit one floating row, so
   the bar goes back into the masthead's flow at the top of the page: the
   same links, wrapping, each its icon beside its label, scrolling away
   with the page. Nothing floats over the content, so the page keeps no room
   for it. */
@media (max-width: 19.9375rem) {
  html { scroll-padding-bottom: 0; }
  .tabbar {
    position: static;
    flex: 1 1 100%;
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: var(--space-1);
    padding: 0;
    background: none;
    box-shadow: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    border-style: none;
  }
  .tab { flex: 0 1 auto; flex-direction: row; gap: var(--space-1); padding: var(--space-1) var(--space-3); }
  .page--app { padding-bottom: var(--space-8); }
}

/* ---------------------------------------------------------------- a wider screen: the glass top bar
   iPadOS's tab bar near the top: the masthead floats as a glass bar and the
   sections are text capsules in it, every one shown, with no More. The tab
   bar's own glass is off at this width: the bar it sits in is the glass. */
@media (min-width: 43.8125rem) {
  .tabbar { position: static; flex-wrap: wrap; gap: var(--space-1); background: none; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
  .masthead--app {
    width: calc(100% - 2 * max(var(--space-3), env(safe-area-inset-left), env(safe-area-inset-right)));
    max-width: var(--content-max); /* a form screen's narrow column is too narrow for the bar's sections */
    margin: var(--space-3) auto 0;
    padding: var(--space-2) var(--space-4);
    gap: var(--space-2) var(--space-4);
    border: 1px solid transparent; /* drawn in forced-colours mode */
    border-radius: var(--radius-sheet);
  }
  .tab { padding: var(--space-2) var(--space-3); }
  .page--app { padding-top: var(--space-5); } /* the large title clears the floating bar */
  .tab .icon { display: none; }
  .tab--more { display: none; }
  .lede { font-size: var(--text-base); }
}
@media (min-width: 43.8125rem) and (max-width: 74.9375rem) {
  .masthead__name { display: none; } /* the bar keeps to one row on an iPad in landscape; home's "Signed in as" says who you are */
}
@media (min-width: 75rem) {
  /* A long name or email address is cut short rather than wrapping the bar. */
  .masthead__name { max-width: 8rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}
/* The bar stays at the top of the screen only where it is one row and the
   screen is tall enough to spare it: from 64rem wide (an iPad in landscape)
   and 37.5rem tall. Narrower, its sections wrap it to two or three rows
   (169px to 217px), and on a phone in landscape (844x390) or an iPad in
   portrait a sticky bar that tall would cover up to half the screen and the
   focused control under it (WCAG 2.4.11), so there it scrolls away with the
   page. Where it does stay, focus and the skip link scroll clear of it.
   A bar with more than the eight sections every role has (.masthead--long:
   a manager's team, an admin's People and Settings) is not one row at any
   width up to --content-max (re-measured in the merge of main: nine
   sections 115px tall, eleven 167px to 215px), so it scrolls away too. */
@media (min-width: 64rem) and (min-height: 37.5rem) {
  html { scroll-padding-top: var(--topbar-clear); }
  .masthead--app { position: sticky; z-index: 10; top: var(--space-3); }
  .masthead--long { position: static; }
}

/* ---------------------------------------------------------------- Increase Contrast, Reduce Transparency
   The glass goes solid with a visible edge, at each width on the bar that is
   glass there. Safari does not support prefers-reduced-transparency (any
   version), which is acceptable only because the translucent bar already
   meets the glass rule (ADR-218 D2): its text lies outside the range of tones
   the tint can take, so no backdrop brings it below AA. Increase Contrast,
   which Safari does support, gives the solid bar. Then the rest of Increase Contrast: cards and
   hairlines take a control's edge, the tinted button's edge darkens to the
   accent, and the dots go. No token is rebound. Forced colours takes the
   solid bar too: it keeps a colour's alpha, so the glass would stay see-through. */
@media (prefers-contrast: more) and (max-width: 43.75rem), (prefers-reduced-transparency: reduce) and (max-width: 43.75rem), (forced-colors: active) and (max-width: 43.75rem) {
  .tabbar { background: var(--glass-solid); -webkit-backdrop-filter: none; backdrop-filter: none; border-color: var(--control-border); }
}
@media (prefers-contrast: more) and (min-width: 43.8125rem), (prefers-reduced-transparency: reduce) and (min-width: 43.8125rem), (forced-colors: active) and (min-width: 43.8125rem) {
  .masthead--app { background: var(--glass-solid); -webkit-backdrop-filter: none; backdrop-filter: none; border-color: var(--control-border); }
}
@media (prefers-contrast: more) {
  body { background-image: none; }
  .card { border-color: var(--control-border); }
  .row + .row, .record + .record, .table tbody tr + tr td, .table tbody tr + tr th { border-top-color: var(--control-border); }
  .btn--secondary { border-color: var(--accent); }
}

/* ---------------------------------------------------------------- forced colours
   Cards, notices, buttons and each width's bar keep their 1px transparent
   border, which this mode draws. The dots go. A tab and a text button are
   links, not boxes: outlined, every tab looks like the current one (this
   mode takes away its fill and accent), and a capsule's curve cuts through
   a text button's first and last letters. So they lose the edge, and the
   current tab alone has one, twice as thick, and its label underlined. */
@media (forced-colors: active) {
  body { background-image: none; }
  .tab, .btn--plain { border-style: none; }
  .tab[aria-current] { border-style: solid; border-width: 2px; }
  .tab[aria-current] .tab__label { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 3px; }
}

/* ---------------------------------------------------------------- reduced motion */
@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-fast: 0ms;
    --duration-base: 0ms;
    --duration-slow: 0ms;
  }
  *, *::before, *::after {
    animation-duration: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0ms !important;
    scroll-behavior: auto !important;
  }
}
