/* ==========================================================================
   HD Holding Staff Portal - the one stylesheet
   --------------------------------------------------------------------------
   Every page and sub-page in this portal is styled from this file alone. There
   are no page-specific stylesheets and no inline styles: if something needs a
   new look, it gets a class here so it looks the same everywhere it appears.

   Design language: warm institutional. Paper-toned canvas, ink text, a single
   gold accent taken from the HD Holding mark, hairline rules instead of heavy
   shadows, and a short gold underline that marks every page title.

   Contents
     1. Fonts
     2. Design tokens (light + dark)
     3. Reset and base
     4. Typography
     5. App shell: sidebar, topbar, main
     6. Page header and section furniture
     7. Cards and statistics
     8. Tables
     9. Forms
    10. Buttons
    11. Status pills, badges, dots
    12. Alerts and flash messages
    13. Tabs, filters, pagination
    14. Calendar
    15. Timeline and approval trail
    16. Meters and progress
    17. Empty states, avatars, misc
    18. Sign-in page
    19. Motion
    20. Responsive
    21. Print
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Fonts - self-hosted so no employee's browser calls a third party
   -------------------------------------------------------------------------- */
/* Relative paths on purpose: collectstatic rewrites them to the hashed
   filenames, so a font swap busts the cache like everything else. */
@font-face {
  font-family: 'Fraunces';
  src: url("../fonts/fraunces-var.5d2835174326.woff2") format('woff2-variations');
  font-weight: 300 900;
  font-display: swap;
}
@font-face {
  font-family: 'Archivo';
  src: url("../fonts/archivo-var.92895abae7c5.woff2") format('woff2-variations');
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: 'PlexMono';
  src: url("../fonts/plex-mono-regular.814fe1615d4d.woff2") format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'PlexMono';
  src: url("../fonts/plex-mono-medium.6708425c446b.woff2") format('woff2');
  font-weight: 500;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   2. Design tokens
   -------------------------------------------------------------------------- */
:root {
  /* Type */
  --font-display: 'Fraunces', 'Iowan Old Style', Georgia, 'Times New Roman', serif;
  /* The welcome line with the person's name, desktop and phone (owner,
     28/09/2026: "let us use Georgia always for the welcome name"): Fraunces
     draws a short, hooked j that read as a broken letter in "Saja". */
  --font-welcome: Georgia, 'Times New Roman', serif;
  --font-body: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --font-mono: 'PlexMono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  --text-xs:   0.75rem;
  --text-sm:   0.8125rem;
  --text-base: 0.9375rem;
  --text-md:   1.0625rem;
  --text-lg:   1.375rem;
  --text-xl:   1.75rem;
  --text-2xl:  2.25rem;
  --text-3xl:  3rem;

  /* Surfaces - warm paper */
  --canvas:        #F6F3ED;
  --surface:       #FFFFFF;
  --surface-2:     #FBF9F5;
  --surface-sunk:  #F1EDE5;
  --sidebar:       #211E1A;
  --sidebar-2:     #2B2721;

  /* Ink */
  --ink:        #1B1815;
  --ink-2:      #4A443C;
  --ink-3:      #7A7268;
  --ink-4:      #A79E92;
  --on-dark:    #F3EFE7;
  --on-dark-2:  #ADA495;

  /* Accent - the HD Holding gold */
  --gold:        #B49C54;
  --gold-strong: #8E7838;
  --gold-soft:   #E8DFC6;
  --gold-wash:   #F5F0E1;

  /* Status */
  --ok:          #3F7D53;
  --ok-wash:     #E7F1E9;
  --warn:        #B07A1E;
  --warn-wash:   #FAF0DC;
  --danger:      #A93B32;
  --danger-wash: #F8E9E7;
  --info:        #3A6B8A;
  --info-wash:   #E7EFF4;
  --muted-wash:  #EFEBE3;

  /* Lines and shape */
  --line:        #E2DACE;
  --line-strong: #CFC4B3;
  --radius-sm: 4px;
  --radius:    7px;
  --radius-lg: 12px;

  /* Depth - used sparingly */
  --shadow-sm: 0 1px 2px rgba(33, 30, 26, .05);
  --shadow:    0 2px 10px rgba(33, 30, 26, .07);
  --shadow-lg: 0 12px 34px rgba(33, 30, 26, .16);

  /* Rhythm */
  --gap-1: 4px;  --gap-2: 8px;  --gap-3: 12px; --gap-4: 16px;
  --gap-5: 24px; --gap-6: 32px; --gap-7: 48px; --gap-8: 64px;

  --sidebar-w: 246px;
  --topbar-h: 60px;
  --content-max: 1440px;

  --ease: cubic-bezier(.4, 0, .2, 1);
  --fast: 130ms;
  --slow: 260ms;
}

:root[data-theme="dark"] {
  --canvas:       #17150F;
  --surface:      #201D17;
  --surface-2:    #262218;
  --surface-sunk: #12100C;
  --sidebar:      #100E0A;
  --sidebar-2:    #1C1913;

  --ink:    #EFE9DC;
  --ink-2:  #C3BBAA;
  --ink-3:  #948B7B;
  --ink-4:  #6E6659;
  --on-dark:   #EFE9DC;
  --on-dark-2: #9B9284;

  --gold:        #CDB268;
  --gold-strong: #E0C67F;
  --gold-soft:   #4A3F22;
  --gold-wash:   #2A2417;

  --ok:          #7FB98F;
  --ok-wash:     #1E2A21;
  --warn:        #DBAA55;
  --warn-wash:   #2E2515;
  --danger:      #E08379;
  --danger-wash: #2E1B18;
  --info:        #85B2CD;
  --info-wash:   #182530;
  --muted-wash:  #262218;

  --line:        #322C22;
  --line-strong: #47402F;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow:    0 2px 12px rgba(0, 0, 0, .45);
  --shadow-lg: 0 14px 38px rgba(0, 0, 0, .6);
}

/* --------------------------------------------------------------------------
   3. Reset and base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

/* The browser hides [hidden] with `display: none` at its own low priority, so
   ANY display of ours beats it. .alert is display:flex, which is how twelve
   leave-type rule blocks - every one of them marked hidden - all rendered
   down the page at once, and how the script toggling `.hidden` on them
   appeared to do nothing.
   Once here, for every element that will ever be given the attribute. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.55;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* A whisper of paper grain over the canvas, so large empty areas are not flat. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  opacity: .5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.035'/%3E%3C/svg%3E");
}
:root[data-theme="dark"] body::before { opacity: .35; }

img, svg { max-width: 100%; height: auto; vertical-align: middle; }

a { color: var(--gold-strong); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 2px; }

hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: var(--gap-5) 0;
}

::selection { background: var(--gold-soft); color: var(--ink); }

:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* --------------------------------------------------------------------------
   4. Typography
   -------------------------------------------------------------------------- */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -.012em;
  color: var(--ink);
  margin: 0 0 var(--gap-3);
  font-variation-settings: 'SOFT' 0, 'WONK' 0, 'opsz' 32;
}
h1 { font-size: var(--text-xl); }
h2 { font-size: var(--text-lg); }
h3 { font-size: var(--text-md); }
h4 { font-size: var(--text-base); font-family: var(--font-body); font-weight: 600; }

p { margin: 0 0 var(--gap-3); }
p:last-child { margin-bottom: 0; }

small, .small { font-size: var(--text-sm); }

.muted   { color: var(--ink-3); }
.muted-2 { color: var(--ink-4); }
.strong  { font-weight: 600; }
.mono    { font-family: var(--font-mono); font-size: .95em; letter-spacing: -.01em; }
.nowrap  { white-space: nowrap; }
.center  { text-align: center; }
.right   { text-align: right; }

.eyebrow {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.numeral {
  font-family: var(--font-display);
  font-variation-settings: 'SOFT' 0, 'WONK' 0, 'opsz' 40;
  font-weight: 600;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums lining-nums;
}

/* --------------------------------------------------------------------------
   5. App shell
   -------------------------------------------------------------------------- */
.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  min-height: 100vh;
  position: relative;
  z-index: 1;
}

/* The scrim behind the mobile menu. Hidden by default and given its size and
   colour in the mobile block below: it lives inside .app, which is a grid, so
   an unstyled one would sit in the layout as a stray column. */
.sidebar-scrim { display: none; }

/* --- Sidebar --- */
.sidebar {
  background: var(--sidebar);
  color: var(--on-dark);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--sidebar-2) transparent;
}

.sidebar__brand {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  padding: var(--gap-5) var(--gap-4) var(--gap-4);
  border-bottom: 1px solid rgba(255, 255, 255, .07);
}
.sidebar__logo {
  width: 34px; height: 34px;
  flex: none;
  border-radius: var(--radius-sm);
  background: var(--gold);
  color: #16130F;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: -.02em;
}
.sidebar__logo img { width: 100%; height: 100%; object-fit: contain; border-radius: inherit; }
/* The HD mark is already gold artwork, so it sits on the dark bar unboxed. */
.sidebar__logo--mark { background: transparent; }
.sidebar__logo--mark img { object-fit: contain; }
.sidebar__name {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  color: var(--on-dark);
  line-height: 1.2;
}
.sidebar__tag {
  font-size: 10.5px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--on-dark-2);
}

.sidebar__nav { padding: var(--gap-4) var(--gap-3); flex: 1; }

.nav-group { margin-bottom: var(--gap-5); }
.nav-group__label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #6E6459;
  padding: 0 var(--gap-3) var(--gap-2);
}
/* The heading folds its group (base.html). Folded groups sit close together
   and say what is waiting inside them. */
.nav-group__head {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  width: 100%;
  min-height: 28px;
  padding: 4px var(--gap-3);
  margin-bottom: var(--gap-1);
  background: none;
  border: 0;
  border-radius: var(--radius);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: color var(--fast) var(--ease);
}
.nav-group__head:hover { color: var(--on-dark-2); }
.nav-group__head:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }
.nav-group__name { flex: 1; }
.nav-group__head::after {
  content: '';
  width: 5px;
  height: 5px;
  margin-right: 3px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform var(--fast) var(--ease);
}
.nav-group.is-folded { margin-bottom: var(--gap-1); }
.nav-group.is-folded .nav-group__head::after { transform: rotate(-45deg); }
.nav-group.is-folded .nav-link { display: none; }
.nav-group__count {
  background: var(--gold);
  color: #16130F;
  font-size: 9.5px;
  letter-spacing: 0;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  display: grid;
  place-items: center;
}
.nav-group:not(.is-folded) .nav-group__count { display: none; }
@media (prefers-reduced-motion: reduce) {
  .nav-group__head, .nav-group__head::after { transition: none; }
}

.nav-link {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  padding: 8px var(--gap-3);
  margin-bottom: 1px;
  border-radius: var(--radius);
  color: var(--on-dark-2);
  font-size: var(--text-sm);
  font-weight: 500;
  position: relative;
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}
.nav-link:hover { background: var(--sidebar-2); color: var(--on-dark); text-decoration: none; }
.nav-link.is-active { background: var(--sidebar-2); color: #FFF; }
.nav-link.is-active::before {
  content: '';
  position: absolute;
  left: -var(--gap-3);
  left: -12px;
  top: 50%;
  transform: translateY(-50%);
  width: 3px; height: 18px;
  border-radius: 0 2px 2px 0;
  background: var(--gold);
}
/* Drawn, not typed. The sidebar used text glyphs and four of them were
   codepoints the OS renders as colour emoji, so the same menu looked different
   on a Mac, a PC and an iPhone. These inherit the link's colour, so selected,
   hover and dark mode all follow for free. */
.nav-link__icon {
  width: 17px;
  height: 17px;
  flex: none;
  opacity: .85;
  stroke-width: 1.7;
  overflow: visible;
}
.nav-link.is-active .nav-link__icon { opacity: 1; }
.nav-link__count {
  margin-left: auto;
  background: var(--gold);
  color: #16130F;
  font-size: 10.5px;
  font-weight: 700;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  font-family: var(--font-body);
}

.sidebar__foot {
  padding: var(--gap-3) var(--gap-4) var(--gap-4);
  border-top: 1px solid rgba(255, 255, 255, .07);
  font-size: var(--text-xs);
  color: #6E6459;
}

/* --- Topbar --- */
.topbar {
  height: var(--topbar-h);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: var(--gap-4);
  padding: 0 var(--gap-6);
  position: sticky;
  top: 0;
  z-index: 40;
}
.topbar__title { font-size: var(--text-sm); color: var(--ink-3); font-weight: 500; }
.topbar__spacer { flex: 1; }
.topbar__actions { display: flex; align-items: center; gap: var(--gap-2); }

.icon-btn {
  width: 34px; height: 34px;
  display: grid;
  place-items: center;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: transparent;
  color: var(--ink-2);
  cursor: pointer;
  font-size: 15px;
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.icon-btn:hover { background: var(--surface-sunk); border-color: var(--line); }

.usermenu { position: relative; }
.usermenu__btn {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 4px 10px 4px 4px;
  cursor: pointer;
  color: var(--ink);
  font-family: inherit;
  font-size: var(--text-sm);
  transition: border-color var(--fast) var(--ease);
}
.usermenu__btn:hover { border-color: var(--line-strong); }
.usermenu__panel {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  min-width: 232px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--gap-2);
  display: none;
  z-index: 60;
}
.usermenu__panel.is-open { display: block; animation: pop var(--fast) var(--ease); }
.usermenu__head { padding: var(--gap-3); border-bottom: 1px solid var(--line); margin-bottom: var(--gap-2); }
.usermenu__item {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  width: 100%;
  padding: 8px var(--gap-3);
  border-radius: var(--radius);
  color: var(--ink-2);
  font-size: var(--text-sm);
  background: none;
  border: 0;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
}
.usermenu__item:hover { background: var(--surface-sunk); color: var(--ink); text-decoration: none; }

/* --- Main --- */
.main { min-width: 0; display: flex; flex-direction: column; }
.content {
  padding: var(--gap-6);
  max-width: var(--content-max);
  width: 100%;
  margin: 0 auto;
  flex: 1;
}
/* One rhythm down every page (owner, 28/09/2026: "spacing between cards and
   sections inside each page"). Each block after the first starts one gutter
   below the one before, whether it sits in the page or in a plain wrapper
   such as a form: the same 16px as between cards side by side in a grid, so
   a page's cards line up both ways. No weight of its own, so the page head's
   larger gap, a section heading's and the tabs' still win - and blocks carry
   no spacing of their own. */
:where(.content > :not(script, template, dialog, style, input) ~ *,
       .content > :is(form, div, section):not([class]) > :not(script, template, dialog, style, input) ~ *) {
  margin-top: var(--gap-4);
}

/* --------------------------------------------------------------------------
   6. Page header
   -------------------------------------------------------------------------- */
.page-head {
  display: flex;
  align-items: flex-end;
  gap: var(--gap-4);
  flex-wrap: wrap;
  margin-bottom: var(--gap-5);
}
.page-head__text { flex: 1; min-width: 260px; }
.page-head h1 { margin-bottom: var(--gap-2); }

/* The signature: a short gold rule under every page title. */
.page-head h1::after {
  content: '';
  display: block;
  width: 42px;
  height: 3px;
  margin-top: var(--gap-3);
  background: var(--gold);
  border-radius: 2px;
}
.page-head__sub { color: var(--ink-3); font-size: var(--text-sm); margin: 0; }
/* "Good to see you, Saja" on the dashboard: Georgia, not the display face. */
.page-head h1.welcome { font-family: var(--font-welcome); font-variation-settings: normal; }
.page-head__actions { display: flex; gap: var(--gap-2); align-items: center; flex-wrap: wrap; }

.section-head {
  display: flex;
  align-items: baseline;
  gap: var(--gap-3);
  margin: var(--gap-6) 0 var(--gap-3);
}
.section-head:first-child { margin-top: 0; }
/* A heading sits close to what it heads, and the breadcrumb to the title. */
:is(.section-head, .breadcrumb) + * { margin-top: 0; }
/* A second page head further down starts a section, with a section's gap. */
.content > .page-head ~ .page-head { margin-top: var(--gap-6); }
.section-head h2, .section-head h3 { margin: 0; }
.section-head__rule { flex: 1; height: 1px; background: var(--line); }

.breadcrumb {
  display: flex;
  gap: var(--gap-2);
  align-items: center;
  font-size: var(--text-xs);
  color: var(--ink-4);
  margin-bottom: var(--gap-2);
}
.breadcrumb a { color: var(--ink-3); }
.breadcrumb span::after { content: '/'; margin-left: var(--gap-2); color: var(--line-strong); }
.breadcrumb span:last-child::after { content: ''; }

/* --------------------------------------------------------------------------
   7. Cards and statistics
   -------------------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.card + .card { margin-top: var(--gap-4); }
/* Not in a grid or a stack: their own gap spaces them, and the margin pushed
   the second card of every two-column row 16px below the first. */
:is(.grid, .stack) > .card + .card { margin-top: 0; }
.card__head {
  padding: var(--gap-4) var(--gap-5);
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  flex-wrap: wrap;
}
.card__head h2, .card__head h3 { margin: 0; font-size: var(--text-md); }
.card__head .spacer { flex: 1; }
.card__body { padding: var(--gap-5); }
.card__body--flush { padding: 0; }
.card__foot {
  padding: var(--gap-3) var(--gap-5);
  border-top: 1px solid var(--line);
  background: var(--surface-2);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  font-size: var(--text-sm);
  color: var(--ink-3);
  display: flex;
  align-items: center;
  gap: var(--gap-3);
}
.card--accent { border-top: 3px solid var(--gold); }
.card--sunk { background: var(--surface-2); box-shadow: none; }

.grid { display: grid; gap: var(--gap-4); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid--sidebar { grid-template-columns: minmax(0, 1fr) 340px; align-items: start; }
.grid--halves { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }

.stat {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--gap-4) var(--gap-5);
  box-shadow: var(--shadow-sm);
  position: relative;
  overflow: hidden;
}
.stat__label {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--gap-2);
  display: block;
}
.stat__value {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -.025em;
  color: var(--ink);
  font-variation-settings: 'SOFT' 0, 'WONK' 0, 'opsz' 40;
  font-variant-numeric: tabular-nums lining-nums;
}
.stat__unit { font-size: var(--text-sm); color: var(--ink-3); font-family: var(--font-body); font-weight: 500; margin-left: 3px; }
.stat__meta { font-size: var(--text-xs); color: var(--ink-3); margin-top: var(--gap-2); }
.stat--gold { background: var(--gold-wash); border-color: var(--gold-soft); }
.stat--gold .stat__value { color: var(--gold-strong); }
.stat--ok .stat__value { color: var(--ok); }
.stat--warn .stat__value { color: var(--warn); }
.stat--danger .stat__value { color: var(--danger); }

/* --------------------------------------------------------------------------
   8. Tables
   -------------------------------------------------------------------------- */
.table-wrap {
  overflow-x: auto;
  border-radius: var(--radius-lg);
  -webkit-overflow-scrolling: touch;
}
.card__body--flush .table-wrap { border-radius: 0 0 var(--radius-lg) var(--radius-lg); }

table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  min-width: 560px;
}
/* A two-column list inside half a card: the 560px floor is for full tables and
   only makes a short one scroll sideways for nothing. */
table.data.data--narrow { min-width: 0; }
table.data th {
  text-align: left;
  font-weight: 600;
  font-size: var(--text-xs);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding: var(--gap-3) var(--gap-4);
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 2;
}
table.data td {
  padding: var(--gap-3) var(--gap-4);
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
  color: var(--ink-2);
}
table.data tbody tr:last-child td { border-bottom: 0; }
table.data tbody tr { transition: background var(--fast) var(--ease); }
table.data tbody tr:hover { background: var(--surface-2); }
table.data td.num, table.data th.num { text-align: right; font-family: var(--font-mono); }
table.data td.tight { width: 1%; white-space: nowrap; }
table.data .primary-cell { color: var(--ink); font-weight: 600; }
table.data tr.is-flagged { background: var(--danger-wash); }
table.data tr.is-flagged:hover { background: var(--danger-wash); filter: brightness(.98); }
table.data tfoot td {
  background: var(--surface-2);
  font-weight: 700;
  color: var(--ink);
  border-top: 2px solid var(--line-strong);
}
table.data--compact td, table.data--compact th { padding: 6px var(--gap-3); }
/* Tables of the same kind on one page, with the same <colgroup>: their
   columns line up card under card (leave rules). */
table.data--aligned { table-layout: fixed; }
table.data--aligned th { white-space: normal; }

/* Tables in cards, one format (owner, 28/09/2026: "cards table, format
   should be all similar and aligned to each others"). A table reaches the
   card's edges, as the flush ones always did - also one sharing a padded body
   with text - and its first and last columns sit one card padding in, in line
   with the card's title, its text and the filters above it. A small table in
   a column inside a card stays where the column puts it. */
.card__body:not(.card__body--flush) > .table-wrap { margin-inline: calc(-1 * var(--gap-5)); }
.card__body:not(.card__body--flush) > table.data {
  width: calc(100% + 2 * var(--gap-5));
  margin-inline: calc(-1 * var(--gap-5));
  /* No scroller around it, so it fits the card rather than hang out of a
     half-width one. */
  min-width: 0;
}
:is(.card, .card__body, .card > form, .card__body > form) > .table-wrap > table.data :is(th, td):first-child,
.card__body > table.data :is(th, td):first-child { padding-left: var(--gap-5); }
:is(.card, .card__body, .card > form, .card__body > form) > .table-wrap > table.data :is(th, td):last-child,
.card__body > table.data :is(th, td):last-child { padding-right: var(--gap-5); }

.row-link { color: var(--ink); font-weight: 600; }

/* ---- Filter, sort and page (static/js/tables.js; core.tables for the four
   lists paged on the server) --------------------------------------------- */
.th-sort {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  text-align: inherit;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  cursor: pointer;
  text-decoration: none;
}
th.num .th-sort { flex-direction: row-reverse; }
.th-sort:hover, .th-sort:focus-visible { color: var(--ink); text-decoration: none; }
.th-sort:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: 2px; }
/* Two faint chevrons; the one pointing the way it is sorted turns gold. */
/* The arrow hangs in the heading's padding, so a heading keeps the width it
   had: nothing wraps or runs into its neighbour for the sake of an arrow. */
.th-sort__arrow {
  display: inline-grid;
  gap: 2px;
  opacity: .45;
  margin-right: -11px;
}
th.num .th-sort__arrow { margin-right: 0; margin-left: -11px; }
.th-sort__arrow::before, .th-sort__arrow::after {
  content: '';
  width: 0; height: 0;
  border-left: 3.5px solid transparent;
  border-right: 3.5px solid transparent;
}
.th-sort__arrow::before { border-bottom: 4px solid currentColor; }
.th-sort__arrow::after { border-top: 4px solid currentColor; }
.th-sort:hover .th-sort__arrow { opacity: .8; }
.th-sort.is-asc, .th-sort.is-desc { color: var(--ink); }
.th-sort.is-asc .th-sort__arrow, .th-sort.is-desc .th-sort__arrow { opacity: 1; }
.th-sort.is-asc .th-sort__arrow::before { border-bottom-color: var(--gold-strong); }
.th-sort.is-asc .th-sort__arrow::after { opacity: .25; }
.th-sort.is-desc .th-sort__arrow::after { border-top-color: var(--gold-strong); }
.th-sort.is-desc .th-sort__arrow::before { opacity: .25; }

table.data tr.tt-out, table.data tr.tt-off { display: none; }
/* One design for pages, the browser's and the server's: at the foot of the
   table's card, numbered, with where you are in the list. */
.card .pagination, .tt-pager { border-top: 1px solid var(--line); flex-wrap: wrap; }
.pagination button {
  padding: 6px 11px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  color: var(--ink-2);
  background: var(--surface);
  font: inherit;
  cursor: pointer;
}
.pagination button:hover:not(:disabled) { border-color: var(--gold); color: var(--gold-strong); }
.pagination button.is-current { background: var(--gold-strong); border-color: var(--gold-strong); color: #FFF; font-weight: 600; }
.pagination button:disabled { opacity: .4; cursor: default; }
.pagination .pagination__gap, .pagination .pagination__range { border: 0; background: none; padding-inline: 2px; color: var(--ink-3); }
.pagination__size { width: auto; min-height: 32px; padding: 4px 28px 4px 8px; font-size: var(--text-xs); }
/* The row count at the end of a filter bar the tables made. */
.tt-count { font-size: var(--text-xs); color: var(--ink-3); white-space: nowrap; align-self: center; }
@media print {
  .tt-bar, .tt-pager { display: none !important; }
  table.data tr.tt-off { display: table-row !important; }
}
.row-link:hover { color: var(--gold-strong); }

/* --------------------------------------------------------------------------
   9. Forms
   -------------------------------------------------------------------------- */
.form-grid { display: grid; gap: var(--gap-4); grid-template-columns: repeat(2, minmax(0, 1fr)); }
.form-grid--1 { grid-template-columns: minmax(0, 1fr); }
.form-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.field--wide { grid-column: 1 / -1; }

.field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.field > label, .label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-2);
}
.field__hint { font-size: var(--text-xs); color: var(--ink-3); }
.field__error { font-size: var(--text-xs); color: var(--danger); font-weight: 500; }
.required::after { content: ' *'; color: var(--danger); font-weight: 700; }

input[type="text"], input[type="email"], input[type="password"], input[type="number"],
input[type="date"], input[type="time"], input[type="tel"], input[type="url"],
input[type="search"], input[type="datetime-local"], select, textarea {
  width: 100%;
  font-family: inherit;
  font-size: var(--text-base);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  padding: 9px var(--gap-3);
  transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
  appearance: none;
}
textarea { min-height: 92px; resize: vertical; line-height: 1.5; }

input:hover:not(:disabled), select:hover:not(:disabled), textarea:hover:not(:disabled) {
  border-color: var(--ink-4);
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px var(--gold-soft);
}
input:disabled, select:disabled, textarea:disabled {
  background: var(--surface-sunk);
  color: var(--ink-3);
  cursor: not-allowed;
}
input::placeholder, textarea::placeholder { color: var(--ink-4); }

select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%237A7268' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--gap-3) center;
  padding-right: var(--gap-6);
}
/* A list you pick several from is a box of rows, not a dropdown: no arrow. */
select[multiple] { background-image: none; padding-right: 10px; }

input[type="file"] {
  width: 100%;
  font-size: var(--text-sm);
  padding: var(--gap-3);
  background: var(--surface-2);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  color: var(--ink-2);
  cursor: pointer;
}
input[type="file"]:hover { border-color: var(--gold); background: var(--gold-wash); }

.check {
  display: flex;
  align-items: flex-start;
  gap: var(--gap-3);
  font-size: var(--text-sm);
  color: var(--ink-2);
  cursor: pointer;
  padding: 3px 0;
}
.check input[type="checkbox"], .check input[type="radio"] {
  width: 17px; height: 17px;
  margin: 2px 0 0;
  accent-color: var(--gold-strong);
  cursor: pointer;
  flex: none;
}

/* The role permission matrix: one card per part of the menu, four columns of
   tick boxes down the right.

   Fixed columns and a fixed width per verb, because the point of a matrix is
   reading DOWN a column - and each card is its own table, so left to itself
   every card puts View somewhere different and the eye has to start again at
   each heading. */
.permtable { table-layout: fixed; }
.permtable__verb {
  width: 84px;
  text-align: center;
}
.permtable__verb input[type="checkbox"] {
  width: 17px;
  height: 17px;
  accent-color: var(--gold-strong);
  margin: 0;
}
.permtable__verb input[type="checkbox"]:disabled { opacity: .55; }
.permtable td:first-child { min-width: 0; }
@media (max-width: 720px) { .permtable__verb { width: 62px; } }

/* Radio/checkbox presented as selectable cards - used for leave types */
/* A pop-up that says one thing and waits for an OK: an invoice older than 7
   days on a claim (owner, 01/10/2026). A native <dialog>, so the phone and the
   browser both give it a backdrop and the keyboard its Escape. */
.notice {
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  margin: auto;                /* the page's reset would pin it to the top */
  padding: 0;
  background: var(--surface);
  color: var(--ink);
  width: min(24rem, calc(100vw - 2rem));
  box-shadow: var(--shadow-lg);
}
.notice::backdrop { background: rgba(27, 24, 21, .55); }
.notice__body { margin: 0; padding: var(--gap-4); display: grid; gap: var(--gap-3); }
.notice__title { margin: 0; font-family: var(--font-display); font-size: var(--text-md); }
.notice__text { margin: 0; color: var(--ink-2); line-height: 1.5; font-size: var(--text-base); }
/* The choices on a pop-up that asks which way (invoice-source.js). */
.notice__choices { display: grid; gap: var(--gap-2); }
.notice__choice {
  font: inherit;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  padding: .8rem 1rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: var(--surface-2);
  color: var(--ink);
}
.notice__choice--primary { background: var(--gold); border-color: var(--gold); color: #241E0C; }
.notice__choice--quiet { background: transparent; border-color: transparent; color: var(--ink-2); }

.choice-grid { display: grid; gap: var(--gap-3); grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
/* Exactly two, side by side even in a narrow sidebar card. */
.choice-grid--two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* One under another: accounting's how-it-is-paid card, in the sidebar. */
.choice-grid--one { grid-template-columns: minmax(0, 1fr); gap: var(--gap-2); margin-bottom: var(--gap-4); }

/* Today on My attendance: the phone's time card, on the desktop. The three
   stamps, then the check-in beside them once there is room. */
.today .card__head { gap: var(--gap-3); }
.today__stamps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gap-3);
  margin-bottom: var(--gap-5);
}
.today__stamp {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
  padding: var(--gap-3) var(--gap-4);
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.today__k {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.today__v {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.today__v.is-blank { color: var(--ink-4); font-weight: 500; font-size: var(--text-md); }
.today__punch {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--gap-3) var(--gap-4);
  align-items: end;
}
.today__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap-3); }
.today__clock {
  font-variant-numeric: tabular-nums;
  opacity: .8;
  margin-left: 4px;
}
/* Picking a kind of leave: one panel per heading, side by side.

   Fourteen radio buttons down a single column is a list nobody reads to the
   end, and headings alone did not separate them enough - the sets sit in
   their own boxes now, next to one another, so the whole choice is one
   glance. Used by the request, record and amend pages alike.

   The boxes are all one size (owner, 23/09/2026): equal columns from the
   1fr track, equal rows from grid-auto-rows, and the sets stretch to fill
   them instead of each shrinking onto its own contents. Five boxes of
   different heights read as five unrelated things; five of one size read as
   one choice. Only once there is more than one column - on a narrow screen
   they stack, and matching a two-option box to a four-option one would be
   nothing but scrolling. */
.typepick {
  display: grid;
  gap: var(--gap-3);
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
@media (min-width: 560px) { .typepick { grid-auto-rows: 1fr; } }
.typepick__set {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
  padding: var(--gap-3);
}
.typepick__head {
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-bottom: var(--gap-2);
  margin-bottom: var(--gap-2);
  border-bottom: 1px solid var(--line);
}
.typepick__opt {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 6px;
  margin: 0 -6px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background var(--fast) var(--ease);
}
.typepick__opt:hover { background: var(--gold-wash); }
.typepick__opt input { accent-color: var(--gold-strong); flex: none; margin: 0; }
.typepick__opt:has(input:checked) { background: var(--gold-wash); font-weight: 600; }
.typepick__opt:focus-within { outline: 2px solid var(--gold); outline-offset: 1px; }
.choice {
  position: relative;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  padding: var(--gap-3) var(--gap-4);
  cursor: pointer;
  background: var(--surface);
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
  display: block;
}
.choice:hover { border-color: var(--gold); background: var(--gold-wash); }
.choice input { position: absolute; opacity: 0; pointer-events: none; }
.choice__title { font-weight: 600; font-size: var(--text-sm); color: var(--ink); display: flex; align-items: center; gap: var(--gap-2); }
.choice__desc { font-size: var(--text-xs); color: var(--ink-3); margin-top: 2px; }
.choice:has(input:checked) {
  border-color: var(--gold);
  background: var(--gold-wash);
  box-shadow: inset 0 0 0 1px var(--gold);
}
.choice__swatch { width: 9px; height: 9px; border-radius: 50%; flex: none; }

.form-actions {
  display: flex;
  gap: var(--gap-3);
  align-items: center;
  padding-top: var(--gap-5);
  margin-top: var(--gap-5);
  border-top: 1px solid var(--line);
  flex-wrap: wrap;
}
.form-actions .spacer { flex: 1; }
/* In a stack the stack's own gap is part of the space above: still 24px. */
.stack > .form-actions { margin-top: var(--gap-2); }

fieldset { border: 0; padding: 0; margin: 0 0 var(--gap-6); }
legend {
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--ink);
  padding: 0 0 var(--gap-3);
  width: 100%;
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--gap-4);
}

/* --------------------------------------------------------------------------
   10. Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap-2);
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1;
  padding: 10px var(--gap-4);
  border-radius: var(--radius);
  border: 1px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease),
              color var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn:disabled, .btn.is-disabled { opacity: .5; cursor: not-allowed; pointer-events: none; }

.btn--primary { background: var(--gold-strong); color: #FFF; border-color: var(--gold-strong); }
.btn--primary:hover { background: #7A6530; border-color: #7A6530; color: #FFF; }
:root[data-theme="dark"] .btn--primary { color: #16130F; }

.btn--secondary { background: var(--surface); color: var(--ink); border-color: var(--line-strong); }
.btn--secondary:hover { background: var(--surface-sunk); border-color: var(--ink-4); }

.btn--ghost { background: transparent; color: var(--ink-2); border-color: transparent; }
.btn--ghost:hover { background: var(--surface-sunk); color: var(--ink); }

.btn--danger { background: var(--danger); color: #FFF; border-color: var(--danger); }
.btn--danger:hover { filter: brightness(.92); color: #FFF; }

.btn--ok { background: var(--ok); color: #FFF; border-color: var(--ok); }
.btn--ok:hover { filter: brightness(.92); color: #FFF; }

.btn--sm { padding: 6px var(--gap-3); font-size: var(--text-xs); }
.btn--lg { padding: 13px var(--gap-5); font-size: var(--text-base); }
.btn--block { width: 100%; }

.btn-group { display: inline-flex; gap: var(--gap-2); flex-wrap: wrap; }

/* --------------------------------------------------------------------------
   11. Status pills, badges, dots
   -------------------------------------------------------------------------- */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--text-xs);
  font-weight: 600;
  padding: 3px 9px;
  border-radius: 20px;
  background: var(--muted-wash);
  color: var(--ink-2);
  white-space: nowrap;
  line-height: 1.5;
}
.pill::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
  opacity: .8;
}
.pill--plain::before { display: none; }
.pill--ok      { background: var(--ok-wash);     color: var(--ok); }
.pill--warn    { background: var(--warn-wash);   color: var(--warn); }
.pill--danger  { background: var(--danger-wash); color: var(--danger); }
.pill--info    { background: var(--info-wash);   color: var(--info); }
.pill--gold    { background: var(--gold-wash);   color: var(--gold-strong); }
.pill--muted   { background: var(--muted-wash);  color: var(--ink-3); }

.tag {
  display: inline-block;
  font-size: var(--text-xs);
  padding: 2px 7px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  color: var(--ink-3);
  background: var(--surface);
}

/* --------------------------------------------------------------------------
   12. Alerts
   -------------------------------------------------------------------------- */
.alert {
  display: flex;
  gap: var(--gap-3);
  /* Text one card padding in, level with the cards around it. */
  padding: var(--gap-3) var(--gap-5);
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--ink-2);
  font-size: var(--text-sm);
  margin-bottom: var(--gap-4);
  align-items: flex-start;
}
.alert__icon { flex: none; font-size: 15px; line-height: 1.4; }
.alert__body { flex: 1; min-width: 0; }
.alert__title { font-weight: 700; color: var(--ink); margin-bottom: 2px; }
.alert--ok     { background: var(--ok-wash);     border-color: color-mix(in srgb, var(--ok) 30%, transparent);     color: var(--ok); }
.alert--warn   { background: var(--warn-wash);   border-color: color-mix(in srgb, var(--warn) 30%, transparent);   color: var(--warn); }
.alert--danger { background: var(--danger-wash); border-color: color-mix(in srgb, var(--danger) 30%, transparent); color: var(--danger); }
.alert--info   { background: var(--info-wash);   border-color: color-mix(in srgb, var(--info) 30%, transparent);   color: var(--info); }
.alert--ok .alert__title, .alert--warn .alert__title,
.alert--danger .alert__title, .alert--info .alert__title { color: inherit; }

.flash-stack {
  position: fixed;
  top: calc(var(--topbar-h) + 12px);
  right: var(--gap-5);
  z-index: 200;
  display: flex;
  flex-direction: column;
  gap: var(--gap-2);
  max-width: 400px;
}
.flash {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--gold);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: var(--gap-3) var(--gap-4);
  font-size: var(--text-sm);
  display: flex;
  gap: var(--gap-3);
  align-items: flex-start;
  animation: slide-in var(--slow) var(--ease);
}
.flash--success { border-left-color: var(--ok); }
.flash--error   { border-left-color: var(--danger); }
.flash--warning { border-left-color: var(--warn); }
.flash__close { margin-left: auto; background: none; border: 0; cursor: pointer; color: var(--ink-4); font-size: 16px; line-height: 1; padding: 0; }

/* --------------------------------------------------------------------------
   13. Tabs, filters, pagination
   -------------------------------------------------------------------------- */
.tabs {
  display: flex;
  gap: var(--gap-1);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--gap-5);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  padding: var(--gap-3) var(--gap-4);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-3);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  white-space: nowrap;
  transition: color var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.tab:hover { color: var(--ink); text-decoration: none; }
.tab.is-active { color: var(--gold-strong); border-bottom-color: var(--gold); }
.tab__count {
  display: inline-block;
  margin-left: 5px;
  font-size: 10.5px;
  background: var(--muted-wash);
  color: var(--ink-3);
  padding: 1px 6px;
  border-radius: 10px;
  font-weight: 700;
}
.tab.is-active .tab__count { background: var(--gold-soft); color: var(--gold-strong); }

/* The Attendance section's three tabs (owner, 01/10/2026): a switch above the
   page's own title, so Today, Report and Needs attention read as one place. */
.section-switch {
  position: relative;
  display: inline-flex;
  gap: 2px;
  max-width: 100%;
  margin-bottom: var(--gap-4);
  padding: 3px;
  background: var(--surface-sunk);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow-x: auto;
  scrollbar-width: none;
}
.section-switch::-webkit-scrollbar { display: none; }
.section-switch__tab {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-2);
  padding: 7px var(--gap-4);
  border-radius: calc(var(--radius) - 2px);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-3);
  white-space: nowrap;
  transition: color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.section-switch__tab:hover { color: var(--ink); text-decoration: none; }
.section-switch__tab.is-active {
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-sm);
}
.section-switch__tab:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }
/* One tab is not a switch: the queues' strip says nothing to somebody with a single queue. */
.section-switch:has(> .section-switch__tab:only-child) { display: none; }
.section-switch__count {
  min-width: 20px;
  padding: 1px 6px;
  border-radius: 10px;
  background: var(--danger-wash);
  color: var(--danger);
  font-size: 10.5px;
  font-weight: 700;
  text-align: center;
}

.filters {
  display: flex;
  gap: var(--gap-3);
  flex-wrap: wrap;
  align-items: flex-end;
  /* One card padding in at the sides, like the cards and tables below it. */
  padding: var(--gap-4) var(--gap-5);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  margin-bottom: var(--gap-4);
}
.filters .field { flex: 1; min-width: 145px; }
.filters .field > label { font-size: var(--text-xs); text-transform: uppercase; letter-spacing: .05em; color: var(--ink-3); }
.filters__actions { display: flex; gap: var(--gap-2); }

.pagination {
  display: flex;
  gap: var(--gap-2);
  align-items: center;
  justify-content: center;
  padding: var(--gap-4);
  font-size: var(--text-sm);
}
.pagination a, .pagination span {
  padding: 6px 11px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  color: var(--ink-2);
  background: var(--surface);
}
.pagination a:hover { border-color: var(--gold); color: var(--gold-strong); text-decoration: none; }
.pagination .is-current { background: var(--gold-strong); border-color: var(--gold-strong); color: #FFF; font-weight: 600; }
.pagination .is-disabled { opacity: .4; pointer-events: none; }

/* ---- Walking a list of files, one at a time -----------------------------
   Previous and Next on a staff file. Three columns rather than a flex row so
   the count sits dead centre whatever length the two names are, and so a long
   name on one side does not shove the other button off its edge. */
.filewalk {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--gap-2);
  margin-bottom: var(--gap-4);
}
/* The tracks are 1fr so the count lands dead centre; the buttons inside them
   size to their own name and sit at the outer edges, rather than stretching
   into two wide empty cards when the names are short. */
.filewalk > :first-child { justify-self: start; }
.filewalk > :last-child { justify-self: end; }
.filewalk__step { max-width: 100%; }
.filewalk__step {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  min-width: 0;
  padding: 7px var(--gap-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink-2);
  text-decoration: none;
  transition: border-color var(--fast) var(--ease), color var(--fast) var(--ease);
}
.filewalk__step--right { justify-content: flex-end; text-align: right; }
a.filewalk__step:hover {
  border-color: var(--gold);
  color: var(--gold-strong);
  text-decoration: none;
}
.filewalk__step.is-disabled { opacity: .45; }
.filewalk__arrow { font-size: 1.25rem; line-height: 1; flex: none; }
/* The name can be long and the button must not grow: min-width 0 lets a grid
   child shrink below its content, which is what makes the ellipsis possible. */
.filewalk__text { min-width: 0; }
.filewalk__label {
  display: block;
  font-size: .64rem;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.filewalk__name {
  display: block;
  font-size: var(--text-sm);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.filewalk__count {
  display: flex;
  align-items: center;
  padding: 0 var(--gap-3);
  font-size: var(--text-sm);
  color: var(--ink-3);
  white-space: nowrap;
}
@media (max-width: 640px) {
  .filewalk__label { display: none; }
  .filewalk__count { padding: 0 var(--gap-2); font-size: .75rem; }
}

/* ---- Intake rail: the steps a joiner is set up in ------------------------ */
.rail {
  display: flex; list-style: none; margin: 0 0 var(--gap-5); padding: 0;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden;
}
.rail__step { flex: 1 1 0; min-width: 0; border-right: 1px solid var(--line); }
.rail__step:last-child { border-right: none; }
.rail__step > a, .rail__step > b {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--gap-3) var(--gap-4); text-decoration: none; color: inherit;
}
.rail__step > a { transition: background var(--fast) var(--ease); }
.rail__step > a:hover { background: var(--surface-2); }
.rail__step b {
  font-family: var(--font-mono); font-size: var(--text-xs);
  color: var(--ink-4); font-weight: 500;
}
.rail__step span {
  font-size: var(--text-sm); font-weight: 600; color: var(--ink-3);
  line-height: 1.25;
}
.rail__step--done { background: var(--surface-2); }
.rail__step--done b, .rail__step--done span { color: var(--ok); }
.rail__step--now { background: var(--gold-wash); box-shadow: inset 0 -3px 0 var(--gold); }
.rail__step--now b { color: var(--gold-strong); }
.rail__step--now span { color: var(--ink); }
@media (max-width: 720px) {
  .rail { flex-wrap: wrap; }
  .rail__step { flex: 1 1 45%; }
}

/* ---- A field in two languages ------------------------------------------- */
.pair {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap-4);
  padding: var(--gap-3) 0; border-bottom: 1px dashed var(--line);
}
.pair:last-of-type { border-bottom: none; }
.field--ar input, .field--ar textarea {
  direction: rtl; text-align: right;
  background: var(--gold-wash); border-color: var(--gold-soft);
}
.tag--auto { background: var(--gold-wash); color: var(--gold-strong); }
.req { color: var(--danger); font-weight: 700; }
@media (max-width: 640px) { .pair { grid-template-columns: 1fr; gap: var(--gap-2); } }

/* --------------------------------------------------------------------------
   14. Calendar
   -------------------------------------------------------------------------- */
.calendar {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.calendar__dow {
  background: var(--surface-2);
  padding: var(--gap-2);
  text-align: center;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.calendar__cell {
  background: var(--surface);
  /* Three two-line chips, the date above them and a "+N more" below: that is
     what a cell has to hold without the grid reflowing on a busy week. */
  min-height: 128px;
  padding: 6px;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.calendar__cell--muted { background: var(--surface-2); }
.calendar__cell--weekend { background: var(--surface-sunk); }
.calendar__cell--today { box-shadow: inset 0 0 0 2px var(--gold); }
/* The day number opens the day. A cell fits four chips and a busy day runs to
   a dozen, so the date has to be a way in or the rest is unreachable. */
.calendar__daynum {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--ink-3);
  font-family: var(--font-mono);
  text-decoration: none;
  align-self: flex-start;
  padding: 1px 4px;
  margin: -1px 0 0 -4px;
  border-radius: 3px;
}
a.calendar__daynum:hover,
a.calendar__daynum:focus-visible {
  background: var(--gold-wash);
  color: var(--gold-strong);
}
.calendar__cell--today .calendar__daynum { color: var(--gold-strong); }
.calendar__cell--muted .calendar__daynum { color: var(--ink-4); }

/* A chip carries a name over what that person is on, the same way every other
   list of people in this portal sets person__name over person__role. One line
   could not hold both: "Gebran Bou Sleiman - Work from home (morning)" is cut
   to about its first word in a cell this narrow. */
.cal-chip {
  font-size: 10.5px;
  font-weight: 600;
  line-height: 1.3;
  padding: 2px 5px;
  border-radius: 3px;
  background: var(--gold-wash);
  color: var(--gold-strong);
  border-left: 2px solid var(--gold);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: block;
}
.cal-chip--holiday { background: var(--danger-wash); color: var(--danger); border-left-color: var(--danger); }
.cal-chip--event   { background: var(--info-wash);   color: var(--info);   border-left-color: var(--info); }
.cal-chip--leave   { background: var(--ok-wash);     color: var(--ok);     border-left-color: var(--ok); }
.cal-chip--pending { background: var(--warn-wash);   color: var(--warn);   border-left-color: var(--warn); }

.cal-chip__who,
.cal-chip__what {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cal-chip__what {
  font-weight: 500;
  font-size: 9.5px;
  opacity: .72;
  letter-spacing: .01em;
}

/* "+3 more" is the overflow, so it reads as a control rather than an entry:
   no colour bar, and it says out loud that it opens. */
.cal-chip--more {
  background: transparent;
  color: var(--ink-3);
  border-left: 2px solid transparent;
  font-weight: 700;
}
a.cal-chip { text-decoration: none; cursor: pointer; }
a.cal-chip:hover,
a.cal-chip:focus-visible { filter: brightness(0.96); text-decoration: underline; }
a.cal-chip--more:hover,
a.cal-chip--more:focus-visible { background: var(--surface-2); color: var(--ink-2); }

.legend { display: flex; gap: var(--gap-4); flex-wrap: wrap; font-size: var(--text-xs); color: var(--ink-3); }
.legend__item { display: flex; align-items: center; gap: 6px; }
.legend__swatch { width: 11px; height: 11px; border-radius: 3px; flex: none; }
/* A legend that filters (the calendar's): each kind is a link, the one being
   shown is marked. */
.legend__item--link {
  color: inherit; text-decoration: none;
  padding: 3px 10px; border: 1px solid var(--line); border-radius: 999px;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.legend__item--link:hover { text-decoration: none; border-color: var(--gold-soft); background: var(--surface-2); }
.legend__item--link:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.legend__item--link.is-active { border-color: var(--gold); background: var(--gold-wash); color: var(--ink); font-weight: 600; }

/* ---- The shared calendar page (owner, 03/10/2026) -----------------------
   A bar of controls, the grid, and a pane beside it listing who is off on the
   day clicked. The pane can sit left, right or at the bottom, be dragged wider,
   and have its cards reordered or folded. What a person chose is kept on their
   account and drawn from the first byte (the classes and the two custom
   properties on .cal), so nothing jumps when the script arrives. */
.cal { --cal-pw: clamp(300px, 34%, 460px); position: relative; }
.cal__bar {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--gap-2) var(--gap-3); margin-bottom: var(--gap-3); position: relative;
}
.cal__nav { display: inline-flex; gap: var(--gap-1); }
.cal__grow { flex: 1; }
.cal__bar .section-switch { margin-bottom: 0; }
.cal__company select { width: auto; min-width: 170px; padding-top: 6px; padding-bottom: 6px; font-size: var(--text-sm); }
.cal__compact[aria-pressed="true"] { background: var(--gold-wash); border-color: var(--gold); color: var(--gold-strong); }
.cal > .legend { margin-bottom: var(--gap-3); }

.cal-pick { position: relative; }
.cal-pick__summary {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-display); font-size: var(--text-md); font-weight: 600;
  padding: 6px 10px; border-radius: var(--radius); border: 1px solid transparent;
}
.cal-pick__summary::-webkit-details-marker { display: none; }
.cal-pick__summary:hover, .cal-pick[open] > .cal-pick__summary { background: var(--surface-sunk); border-color: var(--line); }
.cal-pick__panel {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 30; width: 260px;
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: var(--gap-3);
}
.cal-pick__year { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--gap-2); }
.cal-pick__year a { padding: 2px 10px; border-radius: var(--radius-sm); color: var(--ink-2); }
.cal-pick__year a:hover { background: var(--surface-sunk); text-decoration: none; }
.cal-pick__months { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gap-1); }
.cal-pick__months a {
  text-align: center; padding: 8px 0; border-radius: var(--radius-sm);
  font-size: var(--text-sm); font-weight: 600; color: var(--ink-2);
}
.cal-pick__months a:hover { background: var(--surface-sunk); text-decoration: none; }
.cal-pick__months a.is-current { background: var(--gold-wash); color: var(--gold-strong); box-shadow: inset 0 0 0 1px var(--gold-soft); }

.cal__stage {
  position: relative; display: flex; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm); overflow: hidden; overflow: clip; min-height: 480px;
}
.cal--dock-left .cal__stage { flex-direction: row-reverse; }
.cal--dock-bottom .cal__stage { flex-direction: column; }
.cal__main { flex: 1; min-width: 0; padding: var(--gap-4); display: flex; flex-direction: column; }
/* Beside the pane the calendar keeps one height whichever day is clicked and
   however long that day's list is: it is not stretched to the pane (which can be
   several screens tall), and holds the stage's own minimum itself. */
.cal--dock-left .cal__main, .cal--dock-right .cal__main { align-self: flex-start; min-height: 478px; }
/* The divider runs the whole height of the stage, which can be several screens
   tall, so its handle follows the window (overflow: clip on the stage keeps that
   working) and is always where a hand can find it. */
.cal__split {
  flex: 0 0 10px; display: flex; align-items: flex-start; justify-content: center;
  cursor: col-resize; touch-action: none; background: var(--surface);
}
.cal__split::before {
  content: ""; width: 3px; height: 44px; border-radius: 2px; background: var(--line-strong);
  position: sticky; top: 45vh; transition: background var(--fast) var(--ease);
}
.cal__split:hover::before, .cal__split:focus-visible::before, .cal__split.is-dragging::before { background: var(--gold); }
/* The pane is as tall as what is in it, so every person is on the page and none
   sits behind a scroll box. Beside it the calendar keeps its own height (see
   .cal__main); under it the pane has the whole width. */
.cal__pane {
  flex: 0 0 var(--cal-pw); min-width: 0; background: var(--surface-2);
  border-left: 1px solid var(--line);
}
.cal--dock-left .cal__pane { border-left: 0; border-right: 1px solid var(--line); }
.cal--dock-bottom .cal__pane { flex: 0 0 auto; border-left: 0; border-top: 1px solid var(--line); }
.cal--dock-bottom .cal__split { display: none; }
.cal__panebody {
  padding: 0 var(--gap-3) var(--gap-3);
  display: flex; flex-direction: column; gap: var(--gap-3);
}
.cal.is-dragging { user-select: none; }

.cal__panehead {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap-1) var(--gap-2);
  padding: var(--gap-3) 0 var(--gap-1);
}
.cal__label { font-family: var(--font-display); font-size: var(--text-md); white-space: nowrap; }
.cal__docks { margin-left: auto; display: inline-flex; gap: 2px; }
.cal__docks button, .cal__reset {
  width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid transparent; border-radius: var(--radius-sm);
  color: var(--ink-3); cursor: pointer; font-size: 15px; line-height: 1; padding: 0;
}
.cal__docks button:hover, .cal__reset:hover { background: var(--surface-sunk); color: var(--ink); }
.cal__docks button[aria-pressed="true"] { background: var(--gold-wash); color: var(--gold-strong); border-color: var(--gold-soft); }
.cal-dk { position: relative; display: inline-block; width: 16px; height: 13px; border: 1.5px solid currentColor; border-radius: 2px; }
.cal-dk::after { content: ""; position: absolute; background: currentColor; }
.cal-dk--l::after { left: 0; top: 0; bottom: 0; width: 5px; }
.cal-dk--r::after { right: 0; top: 0; bottom: 0; width: 5px; }
.cal-dk--b::after { left: 0; right: 0; bottom: 0; height: 4px; }
.cal-grip { display: inline-flex; color: var(--ink-4); cursor: grab; touch-action: none; padding: 2px; }
.cal-grip svg { fill: currentColor; }
.cal-grip:hover { color: var(--gold-strong); }
.cal-grip:active { cursor: grabbing; }

.cal-cards { display: flex; flex-direction: column; gap: var(--gap-3); }
.cal-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--gap-3); }
.cal-card.is-lifted { border-color: var(--gold); box-shadow: var(--shadow); }
.cal-card__head { display: flex; align-items: center; gap: var(--gap-2); }
.cal-card__head h3 { margin: 0; font-size: var(--text-base); flex: 1; }
.cal-card__body { margin-top: var(--gap-3); }
.cal-card.is-shut .cal-card__body { display: none; }
.cal-card__fold {
  width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 0; border-radius: var(--radius-sm); color: var(--ink-3); cursor: pointer; padding: 0;
}
.cal-card__fold:hover { background: var(--surface-sunk); color: var(--ink); }
.cal-card__fold::before {
  content: ""; width: 7px; height: 7px; border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor; transform: translateY(-2px) rotate(45deg);
  transition: transform var(--fast) var(--ease);
}
.cal-card.is-shut .cal-card__fold::before { transform: translateX(-2px) rotate(-45deg); }

.cal-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap-2); }
.cal-tile {
  text-align: left; background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--radius); padding: var(--gap-2) var(--gap-3); cursor: pointer;
  font: inherit; color: inherit; display: flex; flex-direction: column; gap: 2px;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.cal--dock-bottom .cal-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.cal-tile:hover { border-color: var(--gold-soft); background: var(--gold-wash); }
.cal-tile[aria-pressed="true"] { background: var(--gold-wash); border-color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold); }
.cal-tile__n { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 600; line-height: 1.1; color: var(--ink); }
.cal-tile__k { font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-3); line-height: 1.25; }

.cal-find { margin-bottom: var(--gap-2); padding: 6px var(--gap-3); font-size: var(--text-sm); }
.cal--dock-bottom .cal-find { max-width: 360px; }
.cal-group {
  display: flex; justify-content: space-between; align-items: baseline;
  font-family: var(--font-body); font-size: var(--text-xs); font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3);
  margin: var(--gap-3) 0 var(--gap-1);
}
.cal-group span { font-weight: 600; color: var(--ink-4); }
/* A list of people takes as many columns as fit: one in the side pane, several
   under the calendar. Each row draws its own top line, pulled up a pixel so the
   list cuts off the first row's and the rows meet as one line whatever the number
   of columns. A name, a company tag or a leave type wraps; it is never cut. */
.cal-people, .cal-fxlist {
  list-style: none; margin: 0; padding: 0; overflow: hidden;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  column-gap: var(--gap-5);
}
.cal-person {
  display: flex; align-items: center; gap: var(--gap-2); padding: var(--gap-2) 0;
  border-top: 1px solid var(--line); margin-top: -1px;
}
.cal-person__text { flex: 1; min-width: 0; }
.cal-person__name { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 6px; min-width: 0; }
.cal-person .person__name, .cal-person .person__role { white-space: normal; overflow: visible; }
.cal-person__co {
  flex: none; font-size: 10px; font-weight: 700; letter-spacing: .05em; color: var(--ink-4);
  border: 1px solid var(--line-strong); border-radius: 3px; padding: 0 4px; line-height: 1.5;
}
.cal-fixed {
  padding: var(--gap-2) var(--gap-3); border-radius: var(--radius); margin-bottom: var(--gap-2);
  display: flex; flex-direction: column; font-size: var(--text-sm);
}
.cal-fixed--holiday { background: var(--danger-wash); color: var(--danger); }
.cal-fixed--event { background: var(--info-wash); color: var(--info); }
.cal-fixed span { font-size: var(--text-xs); opacity: .85; }
.cal-empty { font-size: var(--text-sm); margin: var(--gap-2) 0 0; }
.cal-fullday { display: inline-block; margin-top: var(--gap-3); font-size: var(--text-sm); font-weight: 600; }
.cal-fx { display: flex; gap: var(--gap-2); align-items: flex-start; padding: var(--gap-2) 0; border-top: 1px solid var(--line); color: inherit; text-decoration: none; }
.cal-fx:first-child { border-top: 0; }
.cal-fxlist .cal-fx, .cal-fxlist .cal-fx:first-child { border-top: 1px solid var(--line); margin-top: -1px; }
.cal-fx:hover { text-decoration: none; }
.cal-fx:hover .cal-fx__title { color: var(--gold-strong); }
.cal-fx .legend__swatch { margin-top: 4px; }
.cal-fx__text { min-width: 0; display: flex; flex-direction: column; }
.cal-fx__title { font-weight: 600; font-size: var(--text-sm); }
.cal-fx__meta { font-size: var(--text-xs); color: var(--ink-3); }

.cal .calendar { box-shadow: none; flex: 1 1 auto; grid-template-rows: auto; grid-auto-rows: minmax(96px, 1fr); }
/* The grid's rows decide the height; the base cell's own 128px would overlap them. */
.cal .calendar__cell { cursor: pointer; min-height: 0; }
.calendar__cell--selected { background: var(--gold-wash); box-shadow: inset 0 0 0 2px var(--gold-strong); }
.calendar__off {
  margin-top: auto; display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--text-xs); font-weight: 600; color: var(--ink-3);
}
.calendar__off svg { flex: none; stroke: currentColor; fill: none; }
/* Away and on a trip, side by side at the foot of the day. */
.calendar__counts { margin-top: auto; display: flex; flex-wrap: wrap; gap: 2px 10px; }
.calendar__counts .calendar__off { margin-top: 0; }

.cal-week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--gap-2); flex: 1 1 auto; }
.cal-week__day {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: var(--gap-2); min-height: 150px; display: flex; flex-direction: column; gap: 4px;
  cursor: pointer; min-width: 0;
}
.cal-week__day.is-weekend { background: var(--surface-sunk); }
.cal-week__day.is-today { box-shadow: inset 0 0 0 2px var(--gold); }
.cal-week__day.is-selected { background: var(--gold-wash); box-shadow: inset 0 0 0 2px var(--gold-strong); }
.cal-week__head {
  display: flex; justify-content: space-between; align-items: baseline; color: var(--ink-3);
  font-size: var(--text-xs); font-weight: 700; letter-spacing: .07em; text-transform: uppercase; text-decoration: none;
}
.cal-week__head:hover { text-decoration: none; color: var(--gold-strong); }
.cal-week__head strong { font-family: var(--font-display); font-size: var(--text-md); color: var(--ink); letter-spacing: 0; text-transform: none; }
.cal-chip--wrap, .cal-chip--wrap .cal-chip__who { white-space: normal; }

.cal-day__meta { display: flex; gap: var(--gap-2); margin-bottom: var(--gap-3); }
.cal-day .alert { margin-bottom: var(--gap-2); }
.cal-day__next { margin: var(--gap-4) 0 var(--gap-2); font-size: var(--text-base); }

.cal--compact .cal__main { padding: var(--gap-3); }
.cal--compact .cal__stage { min-height: 400px; }
.cal--compact.cal--dock-left .cal__main, .cal--compact.cal--dock-right .cal__main { min-height: 398px; }
.cal--compact .calendar { flex: 0 0 auto; grid-auto-rows: 58px; }
.cal--compact .calendar__cell { padding: 3px 4px; gap: 2px; }
.cal--compact .cal-chip { height: 5px; padding: 0; border-left-width: 0; font-size: 0; border-radius: 3px; }
.cal--compact .cal-chip--holiday { background: var(--danger); }
.cal--compact .cal-chip--event { background: var(--info); }
.cal--compact .cal-chip--more { height: auto; font-size: var(--text-xs); background: transparent; }
.cal--compact .cal-chip__who { display: none; }
.cal--compact .cal-week__day { min-height: 84px; }
.cal--compact .cal-tiles { gap: var(--gap-1); }
.cal--compact .cal-tile { padding: 4px var(--gap-2); }
.cal--compact .cal-tile__n { font-size: var(--text-md); }
.cal--compact .cal-person { padding: 4px 0; }

/* Dragging the pane: where it will land. */
.cal__zone {
  position: absolute; border: 2px dashed var(--gold); background: var(--gold-wash);
  border-radius: var(--radius); opacity: 0; pointer-events: none;
  transition: opacity var(--fast) var(--ease);
}
.cal__zone.is-on { opacity: .8; }
.cal__zone--left { left: 0; top: 0; bottom: 0; width: 33%; }
.cal__zone--right { right: 0; top: 0; bottom: 0; width: 33%; }
.cal__zone--bottom { left: 0; right: 0; bottom: 0; height: 30%; }

@media (max-width: 900px) {
  .cal .calendar { grid-auto-rows: minmax(72px, 1fr); }
}
/* A phone has no room to drag anything: the pane goes under the calendar, the
   divider, the docks and the grips go, and a chip is a bar as in compact. */
@media (max-width: 760px) {
  .cal__stage, .cal--dock-left .cal__stage, .cal--dock-bottom .cal__stage { flex-direction: column; min-height: 0; }
  .cal--dock-left .cal__main, .cal--dock-right .cal__main, .cal--compact.cal--dock-left .cal__main,
  .cal--compact.cal--dock-right .cal__main { align-self: stretch; min-height: 0; }
  .cal__split, .cal__zone, .cal__docks, .cal__reset, .cal-grip { display: none; }
  .cal__pane, .cal--dock-left .cal__pane, .cal--dock-bottom .cal__pane {
    flex: 0 0 auto; border: 0; border-top: 1px solid var(--line);
  }
  .cal--dock-bottom .cal-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cal__main { padding: var(--gap-3); }
}
@media (max-width: 620px) {
  .cal .calendar { grid-auto-rows: minmax(52px, 1fr); }
  .cal-week { gap: 3px; }
  .cal-week__day { padding: 4px; min-height: 84px; }
  .cal-week .cal-chip { height: 5px; padding: 0; border-left-width: 0; font-size: 0; border-radius: 3px; }
  .cal-week .cal-chip--holiday { background: var(--danger); }
  .cal-week .cal-chip--event { background: var(--info); }
  .cal-week .cal-chip__who { display: none; }
  .cal-week__head { flex-direction: column; align-items: center; }
  .cal__bar .section-switch { order: 5; width: 100%; }
}

/* --------------------------------------------------------------------------
   15. Timeline
   -------------------------------------------------------------------------- */
.timeline { list-style: none; margin: 0; padding: 0 0 0 var(--gap-5); position: relative; }
.timeline::before {
  content: '';
  position: absolute;
  left: 6px; top: 6px; bottom: 6px;
  width: 1px;
  background: var(--line);
}
.timeline__item { position: relative; padding-bottom: var(--gap-4); }
.timeline__item:last-child { padding-bottom: 0; }
.timeline__item::before {
  content: '';
  position: absolute;
  left: calc(-1 * var(--gap-5) + 2px);
  top: 5px;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--line-strong);
}
.timeline__item--ok::before     { border-color: var(--ok);     background: var(--ok); }
.timeline__item--danger::before { border-color: var(--danger); background: var(--danger); }
.timeline__item--gold::before   { border-color: var(--gold);   background: var(--gold); }
.timeline__title { font-size: var(--text-sm); font-weight: 600; color: var(--ink); }
.timeline__meta { font-size: var(--text-xs); color: var(--ink-3); }
.timeline__note {
  font-size: var(--text-sm);
  color: var(--ink-2);
  margin-top: var(--gap-2);
  padding: var(--gap-2) var(--gap-3);
  background: var(--surface-2);
  border-radius: var(--radius);
  border-left: 2px solid var(--line-strong);
}

/* Checklist used by joiner and leaver workflows */
.checklist { list-style: none; margin: 0; padding: 0; }
.checklist__item {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  padding: var(--gap-3) 0;
  border-bottom: 1px solid var(--line);
}
.checklist__item:last-child { border-bottom: 0; }
.checklist__mark {
  width: 22px; height: 22px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 700;
  flex: none;
  background: var(--muted-wash);
  color: var(--ink-4);
  border: 1px solid var(--line-strong);
}
.checklist__item--done .checklist__mark { background: var(--ok); color: #FFF; border-color: var(--ok); }
.checklist__text { flex: 1; min-width: 0; }
.checklist__title { font-size: var(--text-sm); font-weight: 600; color: var(--ink); }
.checklist__meta { font-size: var(--text-xs); color: var(--ink-3); }

/* --------------------------------------------------------------------------
   16. Meters and progress
   -------------------------------------------------------------------------- */
.meter {
  height: 7px;
  background: var(--surface-sunk);
  border-radius: 4px;
  overflow: hidden;
  display: flex;
}
.meter__fill { background: var(--gold); height: 100%; transition: width var(--slow) var(--ease); }
.meter__fill--ok     { background: var(--ok); }
.meter__fill--warn   { background: var(--warn); }
.meter__fill--danger { background: var(--danger); }
.meter__fill--pending { background: repeating-linear-gradient(
    45deg, var(--gold-soft), var(--gold-soft) 4px, var(--surface-sunk) 4px, var(--surface-sunk) 8px); }

.balance-card {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--gap-4);
  background: var(--surface);
  display: flex;
  flex-direction: column;
  gap: var(--gap-3);
}
.balance-card__top { display: flex; align-items: baseline; gap: var(--gap-2); }
.balance-card__name { font-size: var(--text-sm); font-weight: 600; color: var(--ink); flex: 1; }
.balance-card__value {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -.02em;
  font-variation-settings: 'SOFT' 0, 'WONK' 0, 'opsz' 36;
}
.balance-card__of { font-size: var(--text-sm); color: var(--ink-3); }
/* Today's three times side by side (owner, 30/09/2026): checked in, checked out
   and the hours worked, each a number with its name under it, parted by a
   hairline like the columns of a time card. The figures shrink with the card
   (a container query) so all three keep one line even in the narrowest one; a
   time still to come is a dash in the quietest ink. */
.balance-card--stamps { container-type: inline-size; }
.balance-card__stamps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: var(--gap-1);
}
.balance-card__stamp {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  padding-left: var(--gap-3);
  border-left: 1px solid var(--line);
}
.balance-card__stamp:first-child { padding-left: 0; border-left: 0; }
.balance-card__stamp .balance-card__value {
  font-size: var(--text-lg);
  font-size: clamp(1.1rem, 6.4cqi, var(--text-xl));
  line-height: 1.1;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.balance-card__stamp .balance-card__of { line-height: 1.25; }
.balance-card__value--blank { color: var(--ink-4); }
/* Today is the card the day starts with: two columns wide wherever the row has
   room, so its figures keep their full size. In a narrow card (a small window,
   a tablet) the columns size to what is in them instead of sharing the width
   equally, so the longest figure never runs into the card's edge. */
@media (min-width: 1000px) { .grid--fit > .balance-card--stamps { grid-column: span 2; } }
@container (max-width: 300px) {
  .balance-card__stamps {
    grid-template-columns: repeat(3, auto);
    justify-content: space-between;
    column-gap: var(--gap-2);
  }
  .balance-card__stamp { padding-left: var(--gap-2); }
  .balance-card__stamp .balance-card__value { font-size: clamp(0.9rem, 6.6cqi, 1.1rem); }
}
.balance-card__split { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 2px var(--gap-2); font-size: var(--text-xs); color: var(--ink-3); }
/* When the days lapse. Quiet until it is close, then it is the line on the
   card that matters most: unused days are gone on that date. */
.balance-card__expiry {
  margin-top: var(--gap-2);
  padding-top: var(--gap-2);
  border-top: 1px solid var(--line);
  font-size: var(--text-xs);
  color: var(--ink-3);
  display: flex;
  justify-content: space-between;
  gap: var(--gap-2);
}
.balance-card__expiry--soon { color: var(--danger); font-weight: 600; }
.balance-card__days { white-space: nowrap; }
a.balance-card__expiry { color: var(--gold-strong); font-weight: 600; }

/* As many equal columns as the cards fill, so a row never ends in a hole:
   the dashboard's today, month and leave cards, and its shortcuts. The
   last line of each card sits on the bottom edge, level across the row. */
.grid--fit { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.grid--fit > .balance-card > .balance-card__expiry { margin-top: auto; }

/* The dashboard's shortcuts (owner, 29/09/2026): the phone's tiles at desk
   size - what it is, and what of yours is on its way. Upright, like the
   phone's, so a title keeps one line on a 1366 laptop. */
.shortcut {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--gap-3);
  padding: var(--gap-4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  color: var(--ink);
  transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.shortcut:hover { text-decoration: none; border-color: var(--gold-soft); box-shadow: var(--shadow); }
.shortcut:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.shortcut__icon {
  width: 36px;
  height: 36px;
  border-radius: var(--radius);
  background: var(--gold-wash);
  color: var(--gold-strong);
  display: grid;
  place-items: center;
}
.shortcut__icon svg { width: 20px; height: 20px; }
.shortcut__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.shortcut__title { font-size: var(--text-sm); font-weight: 600; }
.shortcut__meta { font-size: var(--text-xs); color: var(--ink-3); }
.shortcut__go {
  position: absolute;
  top: var(--gap-4);
  right: var(--gap-4);
  width: 16px;
  height: 16px;
  color: var(--ink-3);
  transform: scaleX(-1);          /* the back chevron, pointing on */
  transition: transform var(--fast) var(--ease), color var(--fast) var(--ease);
}
.shortcut:hover .shortcut__go { color: var(--gold-strong); transform: scaleX(-1) translateX(-2px); }
@media (prefers-reduced-motion: reduce) {
  .shortcut, .shortcut__go { transition: none; }
}

/* --------------------------------------------------------------------------
   17. Empty states, avatars, misc
   -------------------------------------------------------------------------- */
.empty {
  text-align: center;
  padding: var(--gap-8) var(--gap-5);
  color: var(--ink-3);
}
.empty__icon { font-size: 30px; opacity: .35; margin-bottom: var(--gap-3); }
.empty__title { font-family: var(--font-display); font-size: var(--text-md); color: var(--ink-2); margin-bottom: var(--gap-2); }
.empty__text { font-size: var(--text-sm); max-width: 380px; margin: 0 auto var(--gap-4); }

.avatar {
  width: 34px; height: 34px;
  border-radius: 50%;
  background: var(--gold-wash);
  color: var(--gold-strong);
  display: grid;
  place-items: center;
  font-size: var(--text-xs);
  font-weight: 700;
  flex: none;
  overflow: hidden;
  border: 1px solid var(--gold-soft);
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar--sm { width: 26px; height: 26px; font-size: 10px; }
.avatar--lg { width: 62px; height: 62px; font-size: var(--text-md); }

.person { display: flex; align-items: center; gap: var(--gap-3); min-width: 0; }
.person__text { min-width: 0; }
.person__name { font-weight: 600; color: var(--ink); font-size: var(--text-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.person__role { font-size: var(--text-xs); color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* The label column was a flat 165px. In the 340px sidebar that leaves the
   value 109px once the card padding and column gap are taken out, and an
   address like a.gerges@itworksme.com wants about 145 - so it pushed the whole
   grid wider than the card and the text sat outside the box.

   Two separate causes, both fixed here. The track was fixed rather than sized
   to the content, and the longest label actually in use is "Transport
   allowance" at about 125px, so 40px was being held back from every value on
   all thirteen pages that use this. And a grid item defaults to
   min-width: auto, which means it refuses to shrink below its content instead
   of wrapping - that is what turns "too narrow" into "overflows the card".

   auto rather than max-content on purpose: both size to the content, but auto
   can still shrink when the container is tight. */
.kv { display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr); gap: var(--gap-3) var(--gap-4); font-size: var(--text-sm); }
.kv__k { color: var(--ink-3); }
.kv__v { color: var(--ink); font-weight: 500; min-width: 0; overflow-wrap: anywhere; }
.kv__v--empty { color: var(--ink-4); font-weight: 400; font-style: italic; }

.stack { display: flex; flex-direction: column; gap: var(--gap-4); }
.row { display: flex; gap: var(--gap-3); align-items: center; flex-wrap: wrap; }
.row--tight { gap: var(--gap-2); }
.spacer { flex: 1; }
.divider { height: 1px; background: var(--line); margin: var(--gap-4) 0; }

/* --------------------------------------------------------------------------
   18. Sign-in page
   -------------------------------------------------------------------------- */
.auth {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  position: relative;
  z-index: 1;
}

/* The brand panel is deliberately light. The group lockup carries dark text for
   three of the four companies, so it would disappear on a dark ground. */
.auth__aside {
  background: var(--surface);
  color: var(--ink);
  padding: var(--gap-8) var(--gap-7);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--gap-6);
  position: relative;
  overflow: hidden;
  border-right: 1px solid var(--line);
}
.auth__aside::after {
  content: '';
  position: absolute;
  right: -180px; bottom: -180px;
  width: 460px; height: 460px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(180, 156, 84, .13), transparent 70%);
  pointer-events: none;
}

.auth__lockup {
  width: 100%;
  max-width: 520px;
  margin: 0 auto;
  display: block;
}

/* The group lockup exists twice: three of the four wordmarks are near-black
   and disappear on the dark canvas, so a reversed copy carries lightened ink
   and untouched brand colours. Light is the default and dark replaces it. */
.auth__lockup--dark { display: none; }
:root[data-theme="dark"] .auth__lockup--light { display: none; }
:root[data-theme="dark"] .auth__lockup--dark { display: block; }

/* Without JavaScript data-theme never moves off its server-rendered value, so
   the operating system decides directly. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .auth__lockup--light { display: none; }
  :root:not([data-theme="light"]) .auth__lockup--dark { display: block; }
}

/* The copy inside the sign-in panel, for when the aside that normally carries
   the lockup is hidden. Off by default so the two are never on together. */
.auth__lockup-small { display: none; }
.auth__lockup-small .auth__lockup { max-width: 260px; }
.auth__lockup-caption {
  text-align: center;
  font-size: var(--text-xs);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin-top: var(--gap-4);
}
.auth__rule {
  width: 46px;
  height: 3px;
  background: var(--gold);
  border-radius: 2px;
  margin: var(--gap-5) auto var(--gap-4);
}

.auth__mark {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  letter-spacing: -.03em;
  line-height: 1.1;
  color: var(--ink);
  max-width: 14ch;
  margin: 0 auto;
  text-align: center;
}
.auth__mark em { color: var(--gold-strong); font-style: normal; }
.auth__blurb {
  color: var(--ink-3);
  font-size: var(--text-base);
  max-width: 40ch;
  margin: var(--gap-3) auto 0;
  text-align: center;
}
.auth__foot {
  font-size: var(--text-xs);
  color: var(--ink-4);
  position: relative;
  text-align: center;
}

.auth__panel {
  display: grid;
  place-items: center;
  padding: var(--gap-7) var(--gap-6);
  background: var(--canvas);
}
.auth__box { width: 100%; max-width: 380px; }
/* The privacy and account deletion pages: the sign-in frame, wide enough
   to read (29/09/2026). */
.auth__box--read { max-width: 68ch; }
.legal { line-height: 1.6; }
.legal h2 { font-size: var(--text-md); margin: var(--gap-5) 0 var(--gap-2); }
.legal p, .legal ul, .legal ol { margin: 0 0 var(--gap-3); }
.legal ul, .legal ol { padding-left: 1.2em; }
.legal li { margin-bottom: var(--gap-2); }
.legal__meta { font-size: var(--text-sm); color: var(--ink-3); }
.auth__box h1 { font-size: var(--text-xl); margin-bottom: var(--gap-2); }
.auth__box h1::after { content: ''; display: block; width: 42px; height: 3px; margin-top: var(--gap-3); background: var(--gold); border-radius: 2px; }
.auth__sub { color: var(--ink-3); font-size: var(--text-sm); margin-bottom: var(--gap-6); }

.btn--sso {
  width: 100%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  color: var(--ink);
  padding: 13px var(--gap-4);
  font-size: var(--text-base);
}
.btn--sso:hover { border-color: var(--gold); background: var(--gold-wash); }
/* The vendor mark keeps its own colours in both themes, which is the whole
   point of it: people recognise the four squares, not our gold. */
.btn__logo { flex: 0 0 auto; margin-right: var(--gap-2); }

/* The administrator password route, folded away on /admin. It is a control,
   not a bare browser triangle, so it looks like something you may click. */
.auth__fallback {
  margin-top: var(--gap-4);
  border-top: 1px solid var(--line);
  padding-top: var(--gap-4);
}
.auth__fallback > summary {
  cursor: pointer;
  list-style: none;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-3);
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  padding: var(--gap-2) 0;
  min-height: 36px;
}
.auth__fallback > summary::-webkit-details-marker { display: none; }
.auth__fallback > summary::before {
  content: "\25B8";
  transition: transform var(--fast) var(--ease);
  color: var(--ink-4);
}
.auth__fallback[open] > summary::before { transform: rotate(90deg); }
.auth__fallback > summary:hover { color: var(--gold-strong); }

.auth__or {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  margin: var(--gap-5) 0;
  color: var(--ink-4);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .1em;
}
.auth__or::before, .auth__or::after { content: ''; flex: 1; height: 1px; background: var(--line); }

/* --------------------------------------------------------------------------
   19. Motion
   -------------------------------------------------------------------------- */
@keyframes fade-up { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }
@keyframes slide-in { from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: none; } }
@keyframes pop { from { opacity: 0; transform: translateY(-4px) scale(.98); } to { opacity: 1; transform: none; } }

.reveal { animation: fade-up var(--slow) var(--ease) backwards; }
.reveal:nth-child(1) { animation-delay: 0ms; }
.reveal:nth-child(2) { animation-delay: 45ms; }
.reveal:nth-child(3) { animation-delay: 90ms; }
.reveal:nth-child(4) { animation-delay: 135ms; }
.reveal:nth-child(5) { animation-delay: 180ms; }
.reveal:nth-child(6) { animation-delay: 225ms; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* --------------------------------------------------------------------------
   20. Responsive
   -------------------------------------------------------------------------- */
@media (max-width: 1180px) {
  .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid--sidebar { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 900px) {
  .app { grid-template-columns: 1fr; }
  .sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    width: 84vw;
    max-width: var(--sidebar-w);
    transform: translateX(-100%);
    transition: transform var(--slow) var(--ease);
    z-index: 100;
    box-shadow: var(--shadow-lg);
  }
  .sidebar.is-open { transform: none; }
  .sidebar-scrim {
    position: fixed;
    inset: 0;
    background: rgba(20, 17, 13, .45);
    z-index: 90;
    display: none;
  }
  .sidebar-scrim.is-open { display: block; }
  .menu-toggle { display: grid !important; }
  .content { padding: var(--gap-4); }
  .topbar { padding: 0 var(--gap-4); }
  .grid--2, .grid--3, .grid--4 { grid-template-columns: minmax(0, 1fr); }
  .form-grid, .form-grid--3 { grid-template-columns: minmax(0, 1fr); }
  .auth { grid-template-columns: 1fr; }
  .auth__aside { display: none; }
  /* The aside goes, so its lockup goes with it. This is the replacement. */
  .auth__lockup-small { display: block; margin-bottom: var(--gap-5); }
  .kv { grid-template-columns: 1fr; gap: var(--gap-1); }
  .kv__k { font-size: var(--text-xs); text-transform: uppercase; letter-spacing: .05em; }
  .kv__v { margin-bottom: var(--gap-3); }
  .flash-stack { left: var(--gap-3); right: var(--gap-3); max-width: none; }
  .calendar__cell { min-height: 72px; }
}

.menu-toggle { display: none; }

@media (max-width: 620px) {
  .page-head__actions { width: 100%; }
  .page-head__actions .btn { flex: 1; }
  .calendar { font-size: 10px; }
  .calendar__cell { min-height: 56px; padding: 3px; }
  .cal-chip { font-size: 9px; padding: 1px 3px; }
  /* No room for two lines on a phone. The name is the half that matters -
     which leave it is, and which half of the day, is a tap away. */
  .cal-chip__what { display: none; }
}

/* --------------------------------------------------------------------------
   21. Report catalogue
   --------------------------------------------------------------------------
   Forty-odd reports is too many to read as a list, so they are tiles: an icon
   to aim at, the name, and one line saying what comes out. Grouped by subject,
   with a quick find that narrows every group at once. The ones people reach
   for most carry a marker rather than being repeated in a second list.
   -------------------------------------------------------------------------- */
.report-find {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  flex-wrap: wrap;
}
.report-find input[type="search"] {
  flex: 1;
  min-width: 240px;
  font-size: var(--text-base);
}
.report-find__count {
  font-size: var(--text-sm);
  color: var(--ink-3);
  white-space: nowrap;
}

.report-grid {
  display: grid;
  gap: var(--gap-3);
  grid-template-columns: repeat(auto-fill, minmax(272px, 1fr));
}

.report-tile {
  display: flex;
  gap: var(--gap-3);
  align-items: flex-start;
  padding: var(--gap-3) var(--gap-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  text-decoration: none;
  color: inherit;
  transition: border-color var(--fast) var(--ease),
              background var(--fast) var(--ease),
              box-shadow var(--fast) var(--ease);
}
.report-tile:hover,
.report-tile:focus-visible {
  border-color: var(--gold);
  background: var(--gold-wash);
  box-shadow: var(--shadow-sm);
  text-decoration: none;
}

.report-tile__icon {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--gold-wash);
  border: 1px solid var(--gold-soft);
  color: var(--gold-strong);
}
.report-tile__icon svg { width: 17px; height: 17px; }
.report-tile:hover .report-tile__icon { background: var(--surface); }

.report-tile__body { min-width: 0; display: block; }
.report-tile__title {
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  flex-wrap: wrap;
}
.report-tile__desc {
  display: block;
  font-size: var(--text-xs);
  color: var(--ink-3);
  line-height: 1.5;
  margin-top: 3px;
}

/* A quiet marker on the everyday reports, and on the ones only payroll or an
   administrator can open, so the restriction is visible before the click. */
.report-flag {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--gold-wash);
  color: var(--gold-strong);
  border: 1px solid var(--gold-soft);
}
.report-flag--role {
  background: var(--muted-wash);
  color: var(--ink-3);
  border-color: var(--line);
}

.report-group + .report-group { margin-top: var(--gap-5); }
.report-group__head {
  display: flex;
  align-items: baseline;
  gap: var(--gap-3);
  margin-bottom: var(--gap-3);
}
.report-group__head h3 {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
}
.report-group__rule {
  flex: 1;
  height: 1px;
  background: var(--line);
}
.report-group__count { font-size: var(--text-xs); color: var(--ink-4); }

.report-empty { display: none; }
.report-catalogue.is-searching .report-group:not(.has-match) { display: none; }
.report-catalogue.is-empty .report-empty { display: block; }

@media (max-width: 700px) {
  .report-grid { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------------------
   22. The phone app  (/m/)
   --------------------------------------------------------------------------
   Same tokens, same fonts, same gold as every other page. What changes is the
   shape: one thing per screen, a thumb-height primary action, and a tab bar
   instead of the sidebar.

   The recurring object is the time card. Attendance is the thing people open
   this for several times a day, so the stamped card with its torn edge is the
   first thing on the screen and the anchor for everything else.
   -------------------------------------------------------------------------- */
:root {
  /* The bars' own heights, and the space they actually occupy.
     --------------------------------------------------------------------
     These are separate on purpose. The viewport meta carries
     viewport-fit=cover, so the page runs under the status bar and the
     notch and env(safe-area-inset-*) is non-zero in mobile Safari, not
     only once the app is on a home screen. A bar therefore stands taller
     than its own height by the inset, and the body has to reserve that
     same total or the first screenful of content hides underneath it.
     Everything that positions against a bar uses the *-total value, so
     the two can never drift apart again. */
  --m-top: 54px;
  --m-tab: 62px;
  --m-top-total: calc(var(--m-top) + env(safe-area-inset-top));
  --m-tab-total: calc(var(--m-tab) + env(safe-area-inset-bottom));
  --m-gutter: 15px;
}

.m-body {
  background: var(--canvas);
  min-height: 100dvh;
  /* Room for the fixed chrome at both ends, insets included. */
  padding-top: var(--m-top-total);
  padding-bottom: var(--m-tab-total);
  /* So jumping to an anchor clears the header rather than landing behind it. */
  scroll-padding-top: var(--m-top-total);
}

/* ---- top bar ---- */
.m-top {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: var(--m-top-total);
  padding: env(safe-area-inset-top) var(--m-gutter) 0;
  background: var(--sidebar);
  color: var(--on-dark);
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  z-index: 60;
}

.m-top__mark {
  width: 26px; height: 26px;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
}
.m-top__mark img { width: 100%; height: 100%; object-fit: contain; }

.m-top__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-md);
  letter-spacing: -.01em;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.m-top__act {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--on-dark-2);
  font: inherit;
  font-size: 1.05rem;
  line-height: 1;
  padding: 9px;
  margin: -9px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-decoration: none;
  position: relative;
}
.m-top__act:hover, .m-top__act:focus-visible { color: var(--on-dark); }

.m-top__dot {
  position: absolute;
  top: 4px; right: 4px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--gold);
  border: 1.5px solid var(--sidebar);
}

/* ---- scrolling content ---- */
.m-main {
  padding: var(--gap-4) var(--m-gutter) var(--gap-6);
  display: flex;
  flex-direction: column;
  gap: var(--gap-4);
  max-width: 620px;
  margin: 0 auto;
}

.m-section-label {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink-3);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-3);
}
.m-section-label a { color: var(--gold-strong); text-decoration: none; font-weight: 600; }
/* A running total is a value, not a label, so it keeps its own case: the
   uppercase treatment was turning "19h 14m" into "19H 14M". */
.m-section-label .m-worked { text-transform: none; letter-spacing: 0; }

/* ---- the time card ---- */
.m-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--gap-4);
}

.m-daycard {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.m-daycard__head {
  padding: var(--gap-4) var(--gap-4) var(--gap-3);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--gap-3);
}

.m-daycard__date {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-lg);
  letter-spacing: -.015em;
}

.m-daycard__dow {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--ink-3);
  font-weight: 600;
}

/* The torn edge. A time card, not a rounded rectangle with a shadow. */
.m-daycard__perf {
  height: 1px;
  background-image: repeating-linear-gradient(
    to right, var(--line-strong) 0 5px, transparent 5px 10px);
}

.m-stamps {
  display: grid;
  grid-template-columns: 1fr 1px 1fr;
  align-items: stretch;
}

.m-stamp {
  padding: var(--gap-4);
  display: flex;
  flex-direction: column;
  gap: 3px;
  text-align: center;
}

.m-stamp__label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--ink-3);
  font-weight: 600;
}

.m-stamp__time {
  font-family: var(--font-mono);
  font-size: 1.7rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
  line-height: 1.1;
}
/* Empty says so in words. Digits drawn out of dashes read as a broken value. */
.m-stamp__time.is-blank {
  color: var(--ink-4);
  font-family: var(--font-body);
  font-size: var(--text-md);
  font-weight: 500;
  letter-spacing: 0;
  padding-top: 5px;
}

.m-stamp__rule { background: var(--line); }

.m-daycard__foot {
  border-top: 1px solid var(--line);
  padding: var(--gap-3) var(--gap-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-3);
  background: var(--surface-2);
  font-size: var(--text-sm);
  color: var(--ink-2);
}

.m-worked {
  font-family: var(--font-mono);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* ---- the primary action ---- */
.m-punch {
  appearance: none;
  width: 100%;
  border: 0;
  border-radius: var(--radius);
  padding: 17px var(--gap-4);
  font-family: var(--font-body);
  font-size: var(--text-md);
  font-weight: 600;
  letter-spacing: .01em;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap-3);
  min-height: 56px;
  transition: transform var(--fast) var(--ease), filter var(--fast) var(--ease);
}
.m-punch:active { transform: scale(.985); }

.m-punch--in  { background: var(--gold); color: #241E0C; }
.m-punch--out { background: var(--sidebar); color: var(--on-dark); }
.m-punch[disabled] { opacity: .55; cursor: default; }

.m-punch__time {
  font-family: var(--font-mono);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  opacity: .8;
}

/* ---- leave balance meters ---- */
.m-bal {
  display: flex;
  flex-direction: column;
  gap: var(--gap-2);
  padding: var(--gap-3) 0;
}
.m-bal + .m-bal { border-top: 1px solid var(--line); }

.m-bal__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--gap-3);
}

.m-bal__name { font-weight: 600; font-size: var(--text-base); }

.m-bal__nums {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-sm);
  white-space: nowrap;
}
.m-bal__left { font-size: var(--text-md); font-weight: 500; color: var(--ink); }
.m-bal__of { color: var(--ink-3); }

.m-meter {
  height: 7px;
  border-radius: 4px;
  background: var(--surface-sunk);
  overflow: hidden;
  display: flex;
}
.m-meter__used    { background: var(--gold); }
.m-meter__pending { background: var(--gold-soft); }

.m-bal__note {
  font-size: var(--text-xs);
  color: var(--ink-3);
}
.m-bal__note--warn { color: var(--danger); font-weight: 600; }

/* ---- rows ---- */
.m-list { display: flex; flex-direction: column; }

.m-row {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  padding: var(--gap-3) 0;
  border-bottom: 1px solid var(--line);
  text-decoration: none;
  color: inherit;
  min-height: 52px;
}
.m-row:last-child { border-bottom: 0; }

.m-row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.m-row__title { font-weight: 600; font-size: var(--text-base); }
.m-row__sub { font-size: var(--text-sm); color: var(--ink-3); }
.m-row__end { text-align: right; display: flex; flex-direction: column; gap: 3px; align-items: flex-end; }

.m-row__date {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-sm);
  color: var(--ink-2);
  white-space: nowrap;
}

.m-daymark {
  /* Wide enough for "16/09" over "2026": the date reads dd/mm/yyyy even as a
     badge, wrapped at the second slash. */
  width: 46px;
  flex: 0 0 auto;
  text-align: center;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}
.m-daymark__d { font-size: var(--text-sm); font-weight: 500; }
.m-daymark__m { font-size: 10px; color: var(--ink-3); letter-spacing: .04em; }

/* ---- approval cards ---- */
.m-appr {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--gold);
  border-radius: var(--radius);
  padding: var(--gap-4);
  display: flex;
  flex-direction: column;
  gap: var(--gap-3);
}

.m-appr__who {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
}

.m-appr__name { font-weight: 600; }
.m-appr__meta { font-size: var(--text-sm); color: var(--ink-3); }

.m-appr__facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-2) var(--gap-4);
  font-size: var(--text-sm);
  color: var(--ink-2);
}
.m-appr__facts b { font-weight: 600; color: var(--ink); }

.m-appr__actions { display: flex; gap: var(--gap-2); }
.m-appr__actions form { flex: 1; display: flex; }

.m-btn {
  appearance: none;
  flex: 1;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 600;
  padding: 12px;
  min-height: 46px;
  cursor: pointer;
  text-align: center;
  text-decoration: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap-2);
}
.m-btn--yes { background: var(--ok); border-color: var(--ok); color: #FFF; }
.m-btn--no  { background: var(--surface); border-color: var(--line-strong); color: var(--danger); }
.m-btn--gold { background: var(--gold); border-color: var(--gold); color: #241E0C; }
.m-btn--ghost { background: transparent; }
.m-btn:active { filter: brightness(.96); }

/* ---- reason chips ---- */
.m-chips { display: flex; flex-wrap: wrap; gap: var(--gap-2); }

.m-chip {
  appearance: none;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink-2);
  border-radius: 100px;
  padding: 9px 14px;
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 500;
  cursor: pointer;
  min-height: 38px;
}
.m-chip.is-on {
  background: var(--gold-wash);
  border-color: var(--gold);
  color: var(--gold-strong);
  font-weight: 600;
}

/* ---- bottom sheet ---- */
/* The screen, clipping what is outside it (mobile/_punch_sheet.html): the
   closed sheet below the screen is never counted as page. */
.m-sheet-layer {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 80;
}
.m-sheet-scrim {
  position: absolute;
  inset: 0;
  background: rgba(20, 17, 13, .5);
  z-index: 80;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--slow) var(--ease);
}
.m-sheet-scrim.is-open { opacity: 1; pointer-events: auto; }

.m-sheet {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 81;
  pointer-events: auto;
  background: var(--surface);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  border-top: 1px solid var(--line);
  padding: var(--gap-3) var(--m-gutter)
           calc(var(--gap-5) + env(safe-area-inset-bottom));
  transform: translateY(101%);
  transition: transform var(--slow) var(--ease);
  display: flex;
  flex-direction: column;
  gap: var(--gap-4);
  max-height: 88dvh;
  overflow-y: auto;
}
.m-sheet.is-open { transform: none; }

.m-sheet__grip {
  width: 38px; height: 4px;
  border-radius: 3px;
  background: var(--line-strong);
  margin: 2px auto var(--gap-2);
}

.m-sheet__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-md);
}

/* ---- tab bar ---- */
.m-tabs {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 70;
  height: var(--m-tab-total);
  padding-bottom: env(safe-area-inset-bottom);
  background: var(--surface);
  border-top: 1px solid var(--line);
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
}

.m-tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  text-decoration: none;
  color: var(--ink-3);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .02em;
  position: relative;
  padding-top: 3px;
}
.m-tab__icon { font-size: 1.1rem; line-height: 1; }
.m-tab.is-on { color: var(--gold-strong); }
.m-tab.is-on::before {
  content: "";
  position: absolute;
  top: 0;
  width: 26px; height: 2px;
  background: var(--gold);
  border-radius: 0 0 2px 2px;
}

.m-tab__count {
  position: absolute;
  top: 2px;
  margin-left: 20px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--danger);
  color: #FFF;
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}

/* ---- forms on a phone ---- */
.m-field { display: flex; flex-direction: column; gap: 6px; }
.m-field__label {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.m-field__help { font-size: var(--text-xs); color: var(--ink-3); }
/* A tick box on a phone: the box beside its words on a thumb-sized row, the
   size of a tick box rather than the width of the card (owner, 26/09/2026:
   "the box in mobile view should be smaller"). */
.m-check {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  min-height: 44px;
  font-size: 16px;
  color: var(--ink);
  cursor: pointer;
}
.m-check input[type="checkbox"] {
  width: 22px;
  height: 22px;
  margin: 0;
  flex: none;
  accent-color: var(--gold-strong);
  cursor: pointer;
}
.m-check input[type="checkbox"]:disabled { opacity: .75; cursor: default; }
.m-field__error { font-size: var(--text-sm); color: var(--danger); font-weight: 500; }

/* Colleagues on a claim, as tick boxes under one fold (owner, 05/10/2026): a
   <select multiple> opens a dimming half-screen sheet on an iPhone. */
.m-colleagues { border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--surface); }
.m-colleagues > summary {
  list-style: none; cursor: pointer; min-height: 46px; padding: 0 var(--gap-3);
  display: flex; align-items: center; justify-content: space-between;
  font-size: var(--text-base); color: var(--ink);
}
.m-colleagues > summary::-webkit-details-marker { display: none; }
.m-colleagues > summary::after {
  content: ""; flex: none; width: 7px; height: 7px; margin-left: var(--gap-2);
  border-right: 2px solid var(--ink-3); border-bottom: 2px solid var(--ink-3);
  transform: translateY(-2px) rotate(45deg);
}
.m-colleagues[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
.m-colleagues__list {
  border-top: 1px solid var(--line); padding: var(--gap-1) var(--gap-3);
  max-height: 15rem; overflow-y: auto;
}

.m-input,
.m-body input[type="text"], .m-body input[type="date"], .m-body input[type="number"],
.m-body input[type="email"], .m-body input[type="password"], .m-body input[type="file"],
.m-body select, .m-body textarea {
  width: 100%;
  /* 16px exactly: anything smaller makes iOS zoom the page on focus. */
  font-size: 16px;
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: 12px 13px;
  min-height: 48px;
}
.m-body textarea { min-height: 84px; resize: vertical; }
.m-body select { appearance: none; background-image: none; }
.m-input:focus, .m-body select:focus, .m-body textarea:focus {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
  border-color: var(--gold);
}

/* ---- misc ---- */
.m-empty {
  text-align: center;
  padding: var(--gap-6) var(--gap-4);
  color: var(--ink-3);
  display: flex;
  flex-direction: column;
  gap: var(--gap-2);
}
.m-empty__mark { font-size: 1.6rem; color: var(--ink-4); }
.m-empty__title { font-weight: 600; color: var(--ink-2); }

.m-seg {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  background: var(--surface-sunk);
  border-radius: var(--radius-sm);
  padding: 3px;
  gap: 3px;
}
.m-seg a {
  text-align: center;
  padding: 9px 6px;
  border-radius: 4px;
  text-decoration: none;
  color: var(--ink-2);
  font-size: var(--text-sm);
  font-weight: 600;
  min-height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
}
.m-seg a.is-on { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-sm); }
/* More tabs than fit a phone: they scroll sideways rather than crush the words. */
.m-seg--scroll {
  grid-auto-columns: max-content;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.m-seg--scroll::-webkit-scrollbar { display: none; }
.m-seg--scroll a { padding: 9px 14px; white-space: nowrap; }
/* The same control as a choice that posts with the form: a radio inside each
   label instead of a link. Overtime or travel, on the phone. */
.m-seg label {
  position: relative;
  text-align: center;
  padding: 9px 6px;
  border-radius: 4px;
  color: var(--ink-2);
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.25;
  min-height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.m-seg label input { position: absolute; opacity: 0; pointer-events: none; }
.m-seg label.is-on,
.m-seg label:has(input:checked) { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-sm); }
.m-seg label:focus-within { outline: 2px solid var(--gold); outline-offset: 1px; }

.m-note {
  font-size: var(--text-sm);
  color: var(--ink-2);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: var(--gap-3);
}

.m-flash-stack {
  position: fixed;
  top: calc(var(--m-top-total) + 8px);
  left: var(--m-gutter);
  right: var(--m-gutter);
  z-index: 75;
  display: flex;
  flex-direction: column;
  gap: var(--gap-2);
  pointer-events: none;
}
.m-flash {
  pointer-events: auto;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-left: 3px solid var(--ink-3);
  border-radius: var(--radius-sm);
  padding: 11px 13px;
  font-size: var(--text-sm);
  box-shadow: var(--shadow);
}
.m-flash--success { border-left-color: var(--ok); }
.m-flash--error   { border-left-color: var(--danger); }
.m-flash--warning { border-left-color: var(--warn); }

.m-switchview {
  text-align: center;
  padding: var(--gap-4) 0 0;
  font-size: var(--text-sm);
}
.m-switchview a { color: var(--ink-3); }

/* Nothing in the phone app should ever print. */
@media print { .m-top, .m-tabs, .m-sheet, .m-sheet-scrim, .m-punch { display: none !important; } }

/* --------------------------------------------------------------------------
   21. Print - payroll sheets and attendance reports get printed a lot
   -------------------------------------------------------------------------- */
@media print {
  body::before, .sidebar, .topbar, .page-head__actions, .filters,
  .form-actions, .flash-stack, .pagination, .no-print { display: none !important; }
  .app { grid-template-columns: 1fr; }
  .content { padding: 0; max-width: none; }
  .card { border-color: #CCC; box-shadow: none; break-inside: avoid; }
  table.data { font-size: 10.5px; }
  table.data th { background: #F2F2F2 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  a { color: inherit; text-decoration: none; }
  h1, h2, h3 { break-after: avoid; }
  tr, .stat { break-inside: avoid; }
}

/* Day and month balance: over is a credit, short is a debt. Colour alone must
   not carry the meaning, so the sign is always printed too. */
.is-over  { color: var(--ok); font-weight: 600; }
.is-short { color: var(--danger); font-weight: 600; }
.stat--plain { background: transparent; border-color: transparent; padding-left: 0; }

/* Compact table. Same type scale, less air, for day-by-day and audit-style
   tables where the number of rows on screen is the point. */
table.data--compact th { padding-top: var(--gap-2); padding-bottom: var(--gap-2); }
table.data--compact td { padding: var(--gap-2) var(--gap-3); }
table.data--compact th.num, table.data--compact td.num { padding-right: var(--gap-3); }
table.data--compact td { font-size: var(--text-sm); }
table.data--compact .sub {
  display: block;
  font-size: var(--text-xs);
  color: var(--ink-4);
  font-family: var(--font-body);
  margin-top: 1px;
}

/* A disclosure for explanation nobody needs on every visit. Folded by default
   so the figure leads and the reasoning is one click away. */
.explain { margin-top: var(--gap-4); }
.explain > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-3);
  min-height: 32px;
}
.explain > summary::-webkit-details-marker { display: none; }
.explain > summary::before {
  content: "\25B8";
  color: var(--ink-4);
  transition: transform var(--fast) var(--ease);
}
.explain[open] > summary::before { transform: rotate(90deg); }
.explain > summary:hover { color: var(--gold-strong); }
.explain__body {
  font-size: var(--text-sm);
  color: var(--ink-3);
  line-height: 1.65;
  padding: var(--gap-2) 0 0 calc(var(--gap-2) + 1ch);
}

/* A stat tile that is also a link. The next thing anybody does after reading
   "7 not checked in" is ask which seven. */
.stat--link { text-decoration: none; display: block; transition: border-color var(--fast) var(--ease); }
.stat--link:hover { border-color: var(--gold-soft); }

/* A field that shows a value rather than accepting one, so a derived number
   sits in the form grid without pretending to be editable. */
.field__static {
  min-height: 40px;
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  color: var(--ink-2);
  font-size: var(--text-sm);
}

/* A table whose columns are set by a colgroup rather than by whatever the rows
   happen to contain.
 *
 * Without this the employee list changed shape between pages: page two carries
 * a fifty-character job title where page three's longest is twenty-five, the
 * browser hands that column the space, and everything else is squeezed. Same
 * table, same screen, different layout, which reads as a bug.
 *
 * Long values are cut with an ellipsis and carry the whole thing in a title,
 * so hovering shows the rest. Wrapping was tried first and was worse: rows
 * grew to three lines and the table still did not sit still between pages. */
table.data--fixed {
  table-layout: fixed;
  /* Ten columns need room. Below this the percentages crush every one of them
     to a few characters, which is worse than scrolling: .table-wrap already
     scrolls horizontally, so a narrow screen gets a usable table it can pan
     rather than a full one it cannot read. Above it, 100% fits exactly and no
     scrollbar appears at all. */
  min-width: 1100px;
}
/* Only the CELLS truncate. A header cut to "INTERNAL COM..." or "S..." tells
   the reader nothing about the column beneath it, so headers wrap onto a
   second line instead — a slightly taller header row costs nothing and is
   paid once, not per row. */
table.data--fixed th { white-space: normal; overflow: visible; }
table.data--fixed td {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The name cell holds two stacked lines, each truncating on its own. */
table.data--fixed .person { min-width: 0; }
table.data--fixed .person__text { min-width: 0; overflow: hidden; }
table.data--fixed .person__name,
table.data--fixed .person__role {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The avatar must not be squeezed to nothing by a long name beside it. */
table.data--fixed .avatar { flex: 0 0 auto; }

/* Org chart. One tree per company, drawn top-down with pure CSS connectors:
   every <li> paints a stub up to a shared rail, the rail is the ul::before,
   and the first and last child round their corners so the rail reads as a
   bracket rather than a line that overshoots. Cards are ranked by title -
   C-level, manager, team lead - and the rank is a coloured top edge, not a
   different card, so the eye still reads one kind of thing. Folding a team
   hides its <ul>; zoom is a transform on the canvas so the scrollable size
   follows it. */
.oc-shell { overflow: hidden; }
.oc-toolbar {
  display: flex; flex-wrap: wrap; gap: var(--gap-3); align-items: center;
  padding: var(--gap-3) var(--gap-4); border-bottom: 1px solid var(--line);
  background: var(--surface-2);
}
.oc-toolbar__group { display: flex; align-items: center; gap: var(--gap-2); }
.oc-search { min-width: 220px; }
.oc-zoom__value { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--ink-3); min-width: 40px; text-align: center; }
.oc-legend { margin-left: auto; gap: var(--gap-3); font-size: var(--text-xs); color: var(--ink-3); }
.oc-legend__item { display: inline-flex; align-items: center; gap: 5px; }
.oc-swatch { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: var(--ink-2); }
.oc-swatch--r0 { background: var(--gold-strong); }
.oc-swatch--r1 { background: var(--gold); }
.oc-swatch--r2 { background: var(--ok); }

.oc-viewport {
  overflow: auto; max-height: 72vh; min-height: 320px; cursor: grab;
  background:
    radial-gradient(circle, var(--line) 1px, transparent 1px) 0 0 / 22px 22px;
}
.oc-viewport.is-dragging { cursor: grabbing; user-select: none; }
.oc-canvas { display: inline-block; padding: var(--gap-5) var(--gap-6) var(--gap-6); transform-origin: 0 0; }

.oc, .oc ul { display: flex; justify-content: center; padding: 26px 0 0; margin: 0; position: relative; list-style: none; }
.oc { padding-top: 0; }
/* --c is where a card's centre sits within its column and --drop where the
   descent to a team starts, both set by the page script once a parent has
   been centred over its children's cards. Without the script they are the
   column's middle, which is where the card is anyway. */
.oc ul::before {
  content: ''; position: absolute; top: 0; left: var(--drop, 50%); height: 26px;
  border-left: 1.5px solid var(--line-strong, var(--ink-4));
}
.oc-node { position: relative; padding: 26px 8px 0; text-align: center; }
.oc > .oc-node { padding-top: 0; }
.oc-node::before, .oc-node::after {
  content: ''; position: absolute; top: 0; height: 26px;
  border-top: 1.5px solid var(--line-strong, var(--ink-4));
}
.oc-node::before { left: 0; width: var(--c, 50%); }
.oc-node::after { left: var(--c, 50%); right: 0; border-left: 1.5px solid var(--line-strong, var(--ink-4)); }
/* The rail is drawn per card, half on each side of its centre. The first
   card has no rail to its left and the last has none to its right - and the
   last card's right half must drop its BORDER-TOP, not only its descent, or
   the rail keeps going to the edge of that card's column, which is wide
   whenever the card has a team beneath it: a line into empty space. */
.oc-node:first-child::before { border-top: 0; }
.oc-node:last-child::after { border-top: 0; border-left: 0; }
.oc-node:last-child::before { border-right: 1.5px solid var(--line-strong, var(--ink-4)); border-radius: 0 8px 0 0; }
.oc-node:first-child::after { border-radius: 8px 0 0 0; }
.oc-node:only-child::before, .oc-node:only-child::after { border-top: 0; border-radius: 0; }
.oc-node:only-child::before { border-right: 0; }
.oc-node:only-child::after { border-left: 1.5px solid var(--line-strong, var(--ink-4)); }
.oc > .oc-node::before, .oc > .oc-node::after { display: none; }
.oc-node.is-collapsed > ul { display: none; }
.oc-node.is-collapsed > .oc-card .oc-toggle__chev { transform: rotate(-90deg); }
.oc-node.is-dim > .oc-card { opacity: .35; }
.oc-node.is-hit > .oc-card { box-shadow: 0 0 0 3px var(--gold-soft); }

.oc-card {
  position: relative; display: block; width: 184px; height: 176px; margin: 0 auto;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm, 0 1px 2px rgba(0,0,0,.06));
  text-align: center; transition: box-shadow var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.oc-card:hover { box-shadow: var(--shadow-md, 0 6px 18px rgba(0,0,0,.12)); transform: translateY(-1px); }
/* The rank is the badge on the card's top edge and nothing else. A coloured
   top border was tried and read as a stray line running into the badge. */
/* Every card is the same box: the body is a column with fixed rows, the name
   and the code get one line, the title gets two, and the footer is always
   there whether or not it holds a tag. Content that does not fit is cut with
   an ellipsis and carried in a title, so a long name never makes one card
   taller than its neighbours. */
.oc-card__body {
  display: flex; flex-direction: column; align-items: center; height: 100%;
  padding: var(--gap-3) var(--gap-3) var(--gap-2); color: inherit; text-decoration: none; min-width: 0;
}
.oc-card__avatar { flex: 0 0 auto; width: 38px; height: 38px; margin: 0 0 6px; font-size: var(--text-xs); }
.oc-card__name {
  display: block; width: 100%; font-weight: 600; color: var(--ink); font-size: var(--text-sm); line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.oc-card__role {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  width: 100%; height: 2.6em; font-size: var(--text-xs); color: var(--ink-2); margin-top: 3px; line-height: 1.3;
}
.oc-card__meta {
  display: block; width: 100%; font-size: 10px; color: var(--ink-4); margin-top: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.oc-card__meta .mono { font-family: var(--font-mono); }
.oc-card__foot { display: flex; align-items: center; justify-content: center; height: 24px; width: 100%; margin-top: auto; }
.oc-card__level {
  position: absolute; top: -1px; right: 8px; transform: translateY(-50%);
  font-size: 9.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  padding: 1px 6px; border-radius: 10px; color: var(--surface); background: var(--ink-2);
}
.oc-card--r0 .oc-card__level { background: var(--gold-strong); }
.oc-card--r1 .oc-card__level { background: var(--gold); }
.oc-card--r2 .oc-card__level { background: var(--ok); }
.oc-card__tag {
  display: inline-block; max-width: 100%; font-size: 10px; line-height: 1.3;
  padding: 2px 7px; border-radius: 10px; background: var(--gold-wash); color: var(--gold-strong);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.oc-card__tag--dotted { background: transparent; border: 1px dashed var(--ink-4); color: var(--ink-3); }
.oc-card__tag--ghost { background: var(--surface-2); border: 1px solid var(--line); color: var(--ink-3); }
/* A manager from another company: present because the line runs through
   them, drawn faint because they are not this company's. */
.oc-card--ghost { background: var(--surface-2); border-style: dashed; box-shadow: none; }
.oc-card--ghost .oc-card__name { color: var(--ink-2); }
.oc-card--ghost .oc-card__avatar { opacity: .7; }
/* The same person under their second manager: a dashed copy, never with a
   team of its own, so the tree does not draw one team twice. */
.oc-card--secondary { border-style: dashed; }
.oc-node--secondary::after, .oc-node--secondary::before { border-top-style: dashed; }
.oc-node--secondary::after { border-left-style: dashed; }
.oc-swatch--ghost { background: var(--surface-2); border: 1px dashed var(--ink-4); }
.oc-swatch--dotted { background: transparent; border: 1px dashed var(--ink-4); border-radius: 3px; }
.oc-toggle {
  position: absolute; left: 50%; bottom: -13px; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 3px; height: 24px; padding: 0 9px;
  border-radius: 12px; border: 1px solid var(--line); background: var(--surface);
  color: var(--ink-2); font: 600 11px var(--font-body); cursor: pointer;
  box-shadow: var(--shadow-sm, 0 1px 2px rgba(0,0,0,.06));
}
.oc-toggle:hover { border-color: var(--gold); color: var(--gold-strong); }
.oc-toggle__chev { display: inline-block; transition: transform var(--fast) var(--ease); font-size: 12px; }
.oc-foot { border-top: 1px solid var(--line); }
.tab__count { margin-left: 5px; font-size: var(--text-xs); color: var(--ink-4); font-family: var(--font-mono); }

.oc-unplaced { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--gap-2); }
.oc-chip {
  display: flex; align-items: center; gap: var(--gap-2); padding: 6px 8px;
  border: 1px solid var(--line); border-radius: var(--radius); text-decoration: none; color: inherit; min-width: 0;
}
.oc-chip:hover { border-color: var(--gold); }
.oc-chip__text { min-width: 0; }
.oc-chip__name { display: block; font-size: var(--text-sm); font-weight: 600; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.oc-chip__role { display: block; font-size: var(--text-xs); color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

@media print {
  .oc-viewport { max-height: none; overflow: visible; background: none; }
  .oc-canvas { transform: none !important; }
  .oc-node.is-collapsed > ul { display: flex; }
  .oc-toggle { display: none; }
}
.oc-card { transition: box-shadow var(--fast) var(--ease), transform var(--fast) var(--ease), translate .25s var(--ease); }

/* Hours settlement. Nine columns that have to fit without panning, because
   the decision buttons live in the last one and a button off-screen is a
   decision nobody makes. Fixed layout with declared widths; the name cell
   truncates with a title rather than wrapping, and the secondary figures sit
   under the main one as .sub lines so each row stays two or three lines
   tall instead of six. */
table.data--settle { table-layout: fixed; }
table.data--settle th { white-space: normal; }
table.data--settle td { vertical-align: top; }
table.data--settle .name {
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
table.data--settle .sub {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
table.data--settle td.num .sub { text-align: right; }
table.data--settle .pill { padding: 1px 7px; }
.settle-actions { display: flex; flex-direction: column; gap: 4px; }
.settle-actions .btn { padding: 3px 7px; font-size: var(--text-xs); width: 100%; white-space: nowrap; }

/* A card that starts folded. Same head, same body, same foot as every other
   card on the page: the only difference is that the head is clickable and the
   rest is not drawn until it is. Worth having for a section that reports a
   problem nobody has asked about yet, where a screenful every visit trains
   people to scroll past it. */
.card--foldable > summary { cursor: pointer; list-style: none; }
.card--foldable > summary::-webkit-details-marker { display: none; }
.card--foldable > summary:hover { background: var(--gold-wash); }
.card--foldable:not([open]) > summary { border-bottom: 0; }

/* The word is in CSS rather than the markup so it follows the state without
   any script, and says what a click will do rather than what state it is in. */
.card__fold {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-4);
  white-space: nowrap;
}
.card__fold::after { content: "show \25B8"; }
.card--foldable[open] .card__fold::after { content: "hide \25BE"; }

/* The bell sits with the other topbar controls and shares their shape. It is a
   link rather than a button, so it needs the anchor's colour reset too. */
a.icon-btn { text-decoration: none; }
a.icon-btn.is-active { background: var(--surface-sunk); border-color: var(--line); color: var(--ink); }

/* =========================================================================
   Map pin picker (staff file, joiner, head office)
   Leaflet draws the map; these rules only dress it and the search around it.
   ========================================================================= */
.mappin { grid-column: 1 / -1; display: grid; gap: var(--gap-3); }
.mappin__search { position: relative; display: flex; gap: var(--gap-2); flex-wrap: wrap; align-items: center; }
.mappin__q { flex: 1 1 260px; min-width: 0; }
.mappin__results {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 40; margin-top: 4px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); max-height: 280px; overflow: auto;
}
.mappin__result, .mappin__hint {
  display: block; width: 100%; text-align: left; padding: 9px 12px;
  background: none; border: 0; border-bottom: 1px solid var(--line);
  font: inherit; font-size: var(--text-sm); color: var(--ink); cursor: pointer;
}
.mappin__result:last-child, .mappin__hint:last-child { border-bottom: 0; }
.mappin__result:hover, .mappin__result:focus-visible { background: var(--surface-2); outline: none; }
.mappin__hint { color: var(--ink-3); cursor: default; }
.mappin__map {
  height: 360px; border-radius: var(--radius); border: 1px solid var(--line);
  overflow: hidden; background: var(--surface-sunk); isolation: isolate;
}
.mappin__readout { font-size: var(--text-sm); color: var(--ink-3); min-height: 1.4em; }
.mappin__readout strong { color: var(--ink); }
.leaflet-container { font-family: var(--font-body); font-size: var(--text-xs); }
.leaflet-container a { color: var(--ink-2); }
.mappin__pin {
  border-radius: 50%; background: var(--ok); border: 2px solid #fff;
  box-shadow: 0 0 0 2px var(--ink), 0 2px 6px rgba(0,0,0,.35);
}
.mappin__pin--office { background: var(--gold); box-shadow: 0 0 0 2px var(--gold-strong), 0 2px 6px rgba(0,0,0,.3); }
.mappin__pin--reference { background: var(--ink-4); opacity: .8; box-shadow: 0 0 0 1px var(--ink-3); }
.leaflet-tooltip.mappin__tip {
  background: var(--surface); border: 1px solid var(--gold); color: var(--ink);
  font-size: var(--text-xs); font-weight: 600; padding: 2px 7px; border-radius: 4px;
  box-shadow: none; white-space: nowrap;
}
.leaflet-tooltip.mappin__tip::before { border-top-color: var(--gold); }
[data-theme="dark"] .leaflet-tile { filter: brightness(.72) saturate(.75) contrast(1.05); }
[data-theme="dark"] .leaflet-control-attribution { background: rgba(0,0,0,.55); color: var(--ink-3); }
[data-theme="dark"] .leaflet-control-attribution a { color: var(--ink-2); }
[data-theme="dark"] .leaflet-bar a { background: var(--surface); color: var(--ink); border-bottom-color: var(--line); }
@media (max-width: 640px) { .mappin__map { height: 280px; } }

/* =========================================================================
   Where a check in was taken: the button in a row, and the map it opens.
   ========================================================================= */
.map-point {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 8px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink-2);
  font: inherit; font-size: var(--text-xs); cursor: pointer;
  white-space: nowrap;
}
.map-point:hover, .map-point:focus-visible {
  border-color: var(--gold); color: var(--ink); background: var(--gold-wash);
  outline: none;
}
.map-point__icon { width: 14px; height: 14px; flex: none; }
.map-point__acc { color: var(--ink-4); }
.map-point:hover .map-point__acc { color: var(--gold-strong); }

.mapview {
  width: min(680px, calc(100vw - 2 * var(--gap-4)));
  padding: 0; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink);
  box-shadow: 0 24px 60px rgba(0, 0, 0, .28);
}
.mapview::backdrop { background: rgba(20, 17, 12, .55); }
.mapview__head {
  display: flex; align-items: flex-start; gap: var(--gap-3);
  padding: var(--gap-4) var(--gap-4) var(--gap-3);
  border-bottom: 1px solid var(--line);
}
.mapview__who { font-weight: 600; }
.mapview__when { font-size: var(--text-sm); color: var(--ink-3); margin-top: 2px; }
.mapview__close {
  margin-left: auto; border: 0; background: none; cursor: pointer;
  font-size: 24px; line-height: 1; color: var(--ink-3); padding: 0 2px;
}
.mapview__close:hover { color: var(--ink); }
.mapview__canvas {
  height: min(420px, 55vh); background: var(--surface-sunk);
  display: flex; align-items: center; justify-content: center;
}
.mapview__failed {
  margin: 0; padding: var(--gap-5); text-align: center;
  font-size: var(--text-sm); color: var(--ink-3);
}
.mapview__foot {
  display: flex; align-items: center; gap: var(--gap-3);
  padding: var(--gap-3) var(--gap-4);
  border-top: 1px solid var(--line);
}
.mapview__note { font-size: var(--text-xs); color: var(--ink-3); }
@media (max-width: 640px) {
  .mapview__note { display: none; }
  .mapview__canvas { height: 50vh; }
}

/* A note typed straight into an approval row, beside the two buttons. */
.input--sm {
  width: 100%; padding: 5px var(--gap-2); font: inherit;
  font-size: var(--text-xs); color: var(--ink);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.input--sm::placeholder { color: var(--ink-4); }
.input--sm:focus-visible { border-color: var(--gold); outline: none; }

/* =========================================================================
   Today, second edition. The hero time card, the strips and the tiles.
   ========================================================================= */
.m-hero {
  position: relative;
  overflow: hidden;
  background: var(--sidebar);
  color: var(--on-dark);
  border-radius: var(--radius-lg);
  padding: var(--gap-4) var(--gap-4) var(--gap-4);
  display: flex;
  flex-direction: column;
  gap: var(--gap-3);
}
/* A faint gold sweep in the corner: warmth, not decoration for its own sake. */
.m-hero::before {
  content: "";
  position: absolute;
  top: -55%; right: -25%;
  width: 75%; height: 130%;
  background: radial-gradient(closest-side, rgba(180, 156, 84, .22), transparent 72%);
  pointer-events: none;
}
.m-hero > * { position: relative; }

.m-hero__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--gap-3);
}
.m-hero__greet {
  font-family: var(--font-welcome);        /* "Good morning, Saja": Georgia */
  font-weight: 600;
  font-size: var(--text-lg);
  letter-spacing: -.015em;
  line-height: 1.15;
}
.m-hero__date {
  margin-top: 3px;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .09em;
  font-weight: 600;
  color: var(--on-dark-2);
}
.m-hero__pill { flex: none; padding-top: 2px; }

.m-hero__clock {
  display: flex;
  align-items: baseline;
  gap: var(--gap-3);
  font-family: var(--font-mono);
  font-size: 2.75rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.035em;
  line-height: 1;
  margin: var(--gap-2) 0 0;
}
.m-hero__clock small {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 500;
  letter-spacing: 0;
  color: var(--on-dark-2);
}

.m-hero__stamps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--gap-2);
  padding-top: var(--gap-3);
  /* The torn edge again, in the hero's own colours. */
  background-image: repeating-linear-gradient(
    to right, rgba(243, 239, 231, .28) 0 5px, transparent 5px 10px);
  background-size: 100% 1px;
  background-repeat: no-repeat;
}
.m-hero__stamp { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.m-hero__k {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .09em;
  font-weight: 600;
  color: var(--on-dark-2);
}
.m-hero__v {
  font-family: var(--font-mono);
  font-size: var(--text-md);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.m-hero__v.is-blank {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  color: var(--on-dark-2);
}

/* The button inside the dark card: gold to go in, pale to go out. */
.m-hero .m-punch { margin-top: var(--gap-1); }
.m-hero .m-punch--out { background: var(--on-dark); color: var(--sidebar); }

.m-hero__wait {
  display: flex;
  gap: var(--gap-2);
  align-items: flex-start;
  font-size: var(--text-sm);
  color: var(--on-dark-2);
  line-height: 1.4;
}
.m-hero__wait b { color: var(--gold); font-weight: 600; }
/* Exempt from attendance: where the check-in button would be, a line saying
   there is nothing to check in (owner, 28/09/2026). */
.m-hero__exempt, .m-exempt-note {
  margin: 0;
  padding: 14px var(--gap-4);
  border-radius: var(--radius);
  font-size: var(--text-sm);
  text-align: center;
}
.m-hero__exempt { background: rgba(243, 239, 231, .08); color: var(--on-dark-2); }
.m-exempt-note { background: var(--surface-2); color: var(--ink-3); border: 1px solid var(--line); }

/* ---- needs your decision ---- */
/* One box per Approve tab: up to four in a row, then three. */
.m-needs { display: grid; grid-template-columns: repeat(var(--cols, 3), 1fr); gap: var(--gap-2); }
.m-need {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--gap-3);
  text-decoration: none;
  color: inherit;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-height: 66px;
  padding-inline: var(--gap-2);
}
.m-need__n {
  font-family: var(--font-mono);
  font-size: var(--text-lg);
  font-weight: 500;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--ink-4);
}
.m-need__k { font-size: var(--text-xs); font-weight: 600; color: var(--ink-3); }
.m-need.is-hot { border-color: var(--gold); background: var(--gold-wash); }
.m-need.is-hot .m-need__n { color: var(--gold-strong); }
.m-need.is-hot .m-need__k { color: var(--ink-2); }

/* ---- three small figures in a card ---- */
.m-kpis { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap-3); }
.m-kpi { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.m-kpi__v {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-md);
  font-weight: 500;
  white-space: nowrap;
}
.m-kpi__k { font-size: var(--text-xs); color: var(--ink-3); }
.m-kpis__foot {
  margin: var(--gap-3) 0 0;
  padding-top: var(--gap-3);
  border-top: 1px solid var(--line);
  font-size: var(--text-xs);
  color: var(--ink-3);
}

/* ---- the payslip line ---- */
.m-pay { display: flex; align-items: center; justify-content: space-between; gap: var(--gap-3); }
.m-pay__label { font-size: var(--text-xs); color: var(--ink-3); }
.m-pay__net {
  font-family: var(--font-mono);
  font-size: var(--text-lg);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
  margin: 2px 0;
}
.m-pay__net small { font-family: var(--font-body); font-size: var(--text-sm); color: var(--ink-3); }
.m-pay__net--sm { font-size: var(--text-md); margin: 0; }

/* ---- tiles ---- */
.m-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap-2); }
.m-tile {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--gap-3);
  text-decoration: none;
  color: inherit;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-height: 86px;
}
.m-tile:active { background: var(--surface-2); }
/* An odd number of tiles leaves no gap: the last one takes the whole row. */
.m-tiles > .m-tile:last-child:nth-child(odd) { grid-column: 1 / -1; }

/* My team (owner, 03/10/2026): a lead who has people under them folds open. */
.m-team > summary { list-style: none; cursor: pointer; }
.m-team > summary::-webkit-details-marker { display: none; }
.m-team > summary::after {
  content: ""; flex: none; width: 7px; height: 7px; margin: 0 var(--gap-1) 0 var(--gap-2);
  border-right: 2px solid var(--ink-3); border-bottom: 2px solid var(--ink-3);
  transform: translateY(-2px) rotate(45deg); transition: transform var(--fast) var(--ease);
}
.m-team[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
.m-team__count { font-size: var(--text-sm); color: var(--ink-3); font-variant-numeric: tabular-nums; }
.m-team__people { padding-left: 44px; border-bottom: 1px solid var(--line); }
.m-tile__icon { width: 20px; height: 20px; color: var(--gold-strong); }
.m-tile__t { font-weight: 600; font-size: var(--text-sm); }
.m-tile__s { font-size: var(--text-xs); color: var(--ink-3); line-height: 1.35; }

/* ---- small variants used by the new screens ---- */
.m-card--flush { padding: 0 var(--gap-4); }
.m-btn--block { width: 100%; margin-top: var(--gap-3); }
.m-btn--fit { flex: none; padding: 10px 14px; min-height: 40px; }
.m-form { display: flex; flex-direction: column; gap: var(--gap-4); }
.m-form__pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap-3); }
.m-mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* ---- the sections rise in turn on load ---- */
@keyframes m-rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
.m-reveal {
  animation: m-rise .45s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 60ms);
}
@media (prefers-reduced-motion: reduce) {
  .m-reveal { animation: none; }
}
/* A tab swaps the page's content inside the same page (soft-nav.js): the
   content fades in, quickly, and the sections do not rise in turn a second
   time - they did once, when the app opened. */
@keyframes m-swap { from { opacity: 0; } to { opacity: 1; } }
.m-main.is-swapped { animation: m-swap 140ms ease-out both; }
html.m-soft .m-reveal { animation: none; }
@media (prefers-reduced-motion: reduce) {
  .m-main.is-swapped { animation: none; }
}

/* The one-line link in the check-in sheet that flips in and out. */
.m-sheet__flip {
  appearance: none;
  border: 0;
  background: none;
  width: 100%;
  margin-top: var(--gap-2);
  padding: 10px;
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--gold-strong);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Six tabs on a narrow phone: the labels shrink a step rather than wrap. */
@media (max-width: 360px) {
  .m-tab { font-size: 9.5px; letter-spacing: 0; }
}

/* The home-screen app on iPhone, on a page too short to scroll.

   With viewport-fit=cover the page runs under the status bar. WebKit then
   sizes a non-scrolling document to the screen LESS the top inset, and a
   bar fixed to the bottom of that document lands a status bar's height
   above the bottom of the screen, with the page background showing beneath
   it. A page that scrolls is laid out against the whole screen and the same
   bar sits where it should - which is why Today, Leave and More were right
   and Approvals and Payslips were not. Giving the root the missing inset
   makes every page exactly the height of the screen, so the bar is at the
   bottom whether or not there is anything to scroll. */
.m-root { min-height: calc(100% + env(safe-area-inset-top)); }

/* On the home screen the page does not bounce at either end, as an app does
   not. Older iOS (a member's iPhone 13 Pro, 26/09/2026) re-placed the
   fixed tab bar during that bounce and could leave it mid-screen. The
   content still scrolls exactly as before. */
@media (display-mode: standalone) {
  html.m-root { overscroll-behavior-y: none; }
}

/* The on-call planner: a month of dropdowns that has to stay readable. */
.data--roster td { padding-top: 5px; padding-bottom: 5px; }
.roster-pick {
  width: 100%;
  min-width: 150px;
  padding: 5px 8px;
  font: inherit;
  font-size: var(--text-sm);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.roster-pick:focus-visible { border-color: var(--gold); outline: none; }
.roster-pick:disabled { background: var(--surface-sunk); color: var(--ink-3); }
/* Weekend and holiday rows are tinted, so the two-shift days read as a
   block rather than as a mistake in the list. */
.data--roster tr.is-weekend > td { background: var(--surface-2); }
.data--roster tr.is-holiday > td { background: var(--gold-wash); }

/* A second person on one stretch is rare, so the row does not carry a second
   dropdown until somebody asks for one. */
.roster-second { margin-top: 4px; }
.roster-add {
  margin-top: 4px;
  padding: 0;
  font: inherit;
  font-size: var(--text-xs);
  color: var(--ink-3);
  background: none;
  border: 0;
  border-bottom: 1px dotted var(--line-strong);
  cursor: pointer;
}
.roster-add:hover { color: var(--gold-strong); border-bottom-color: var(--gold); }

/* Something asked for and not yet answered. */
.tag--warn {
  color: var(--warn);
  border-color: var(--warn);
  background: var(--warn-wash);
}

/* ---- Dates: a dd/mm/yyyy box in front of the browser's own picker ----
   static/js/dates.js. The native box stays in the form, invisible, carrying
   the ISO value the server reads; the picker opens anchored under the field. */
.dmy { position: relative; display: block; }
.dmy > input[type="text"] { width: 100%; padding-right: 2.4rem; }
.dmy__pick {
  position: absolute; top: 50%; right: .35rem; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.9rem; height: 1.9rem; padding: 0;
  border: 0; border-radius: var(--radius-sm, 6px);
  background: transparent; color: var(--ink-3); cursor: pointer;
}
.dmy__pick:hover { color: var(--gold); background: var(--gold-wash); }
.dmy__pick:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }
.dmy__pick:disabled { opacity: .45; cursor: default; background: transparent; }
/* The browser's own date box, invisible, lying exactly on the calendar
   button. A tap on the button is a tap on it, which is the one thing that
   reliably opens the picker on an iPhone: Safari ignored showPicker() on the
   1px box this used to be (owner, 25/09/2026). 16px so iOS does not zoom the
   page when it takes focus. */
.dmy__native {
  position: absolute !important;
  top: 50% !important; right: .35rem !important; left: auto !important; bottom: auto !important;
  transform: translateY(-50%);
  width: 1.9rem !important; height: 1.9rem !important;
  min-width: 0 !important; min-height: 0 !important; max-width: none !important;
  padding: 0 !important; border: 0 !important; margin: 0 !important;
  font-size: 16px !important;
  opacity: 0; z-index: 2; cursor: pointer;
}
.dmy__native:disabled, .dmy__native[readonly] { pointer-events: none; }
.dmy__native:hover + .dmy__pick { color: var(--gold); background: var(--gold-wash); }
.dmy__native:active + .dmy__pick { color: var(--gold-strong); }
.filters .dmy, .m-body .dmy { min-width: 9.5rem; }
/* A day to go to, among the small buttons of a page head (partials/
   _day_pick.html): the same height as .btn--sm beside it. */
.day-pick .dmy { width: 9.5rem; }
.day-pick .dmy > input[type="text"] { padding-block: 5px; font-size: var(--text-sm); }

/* --------------------------------------------------------------------------
   23. The LBP switch (owner, 26/09/2026)
   payroll/templatetags/money.py writes a dollar figure twice for the roles
   that have the switch - as it is, and in whole pounds at the rate under
   Settings > Currencies - and the root's data-money decides which one shows.
   Keyed off the root so a page switches as one; the head of base.html sets it
   before the first paint, so nothing flashes from dollars to pounds.
   -------------------------------------------------------------------------- */
.fx__lbp { display: none; }
html[data-money="lbp"] .fx__was { display: none; }
/* A dotted gold underline says "converted": hover it for the dollar figure
   and the rate it was converted at. */
html[data-money="lbp"] .fx__lbp {
  display: inline;
  text-decoration: underline dotted var(--gold);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  cursor: help;
}

.fx-switch {
  display: inline-flex;
  align-items: stretch;
  height: 30px;
  padding: 2px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--surface-sunk);
  color: var(--ink-3);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: .04em;
  cursor: pointer;
  transition: border-color var(--fast) var(--ease);
}
.fx-switch:hover { border-color: var(--line-strong); }
.fx-switch:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.fx-switch__opt {
  display: grid;
  place-items: center;
  padding: 0 10px;
  border-radius: 13px;
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}
.fx-switch[aria-pressed="false"] .fx-switch__opt--was,
.fx-switch[aria-pressed="true"] .fx-switch__opt--lbp {
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-sm);
}
.fx-switch[aria-pressed="true"] .fx-switch__opt--lbp { color: var(--gold-strong); }
/* A phone's top bar has no room for both codes and the name beside the
   avatar: the switch shows the one in use and a tap swaps it, and the name
   steps aside while the switch is there. Without this the bar ran 38px past
   a 375px screen and the whole page scrolled sideways. */
@media (max-width: 560px) {
  .fx-switch__opt { padding: 0 8px; }
  .fx-switch[aria-pressed="false"] .fx-switch__opt--lbp,
  .fx-switch[aria-pressed="true"] .fx-switch__opt--was { display: none; }
  .topbar__actions:has(.fx-switch:not([hidden])) .usermenu__btn > .nowrap { display: none; }
  .topbar__actions:has(.fx-switch:not([hidden])) .usermenu__btn { padding-right: 4px; }
}
@media (prefers-reduced-motion: reduce) {
  .fx-switch, .fx-switch__opt { transition: none; }
}
@media print {
  .fx-switch { display: none; }
  html[data-money="lbp"] .fx__lbp { text-decoration: none; }
}

/* --------------------------------------------------------------------------
   24. Profiles > Privacy (owner, 26/09/2026)
   Each switch on its own row with who it hides from beneath it, indented
   under the tick box it belongs to.
   -------------------------------------------------------------------------- */
.privacy-rows { display: flex; flex-direction: column; }
.privacy-row { padding: var(--gap-4) 0; border-top: 1px solid var(--line); }
.privacy-row:first-child { border-top: 0; padding-top: var(--gap-2); }
.privacy-row__who { margin: var(--gap-3) 0 0 29px; }
@media (max-width: 560px) {
  .privacy-row__who { margin-left: 0; }
}

/* --------------------------------------------------------------------------
   25. Expense claims (owner, 26/09/2026)
   An invoice row on the claim form, and the invoices shown on a claim large
   enough to read - photos contained in a frame, never cropped.
   -------------------------------------------------------------------------- */
.expense-line {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--gap-3) var(--gap-4) var(--gap-4);
  background: var(--surface-2);
}
.expense-line__head {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--gap-2);
}
.invoice-grid {
  display: grid;
  gap: var(--gap-4);
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.invoice { margin: 0; display: flex; flex-direction: column; gap: var(--gap-2); }
.invoice img {
  display: block;
  width: 100%;
  height: 320px;
  object-fit: contain;
  background: var(--surface-sunk);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.invoice__file {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--gap-1);
  height: 320px;
  background: var(--surface-sunk);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-sm);
  color: var(--ink-2);
  font-weight: 600;
  text-decoration: none;
}
.invoice__file span { font-weight: 400; font-size: var(--text-xs); color: var(--ink-3); }
.invoice figcaption { font-size: var(--text-xs); color: var(--ink-3); }
@media (max-width: 560px) {
  .invoice img, .invoice__file { height: 240px; }
}
/* A file with no picture to show - a PDF - is a small tile that opens it, not a
   frame as tall as a photo's, in a row of its own under the photos (owner,
   01/10/2026: "make them smaller icon"). */
.invoice-grid + .invoice-grid { margin-top: var(--gap-4); }
.invoice-grid--files { grid-template-columns: repeat(auto-fill, minmax(150px, 170px)); gap: var(--gap-3); }
.invoice--file .invoice__file { height: 92px; gap: 2px; font-size: var(--text-sm); }
.invoice__icon { width: 26px; height: 26px; color: var(--ink-3); }
/* The files that go with an invoice (owner, 01/10/2026): one box, then one more
   each time "Add another file" is pressed (static/js/expense-files.js). */
.extra-files { display: flex; flex-direction: column; gap: var(--gap-2); }
.extra-files__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap-2);
}
.extra-files__row input[type="file"] { flex: 1 1 9rem; min-width: 0; }
.extra-files__row [data-photo-note] { order: 3; flex: 0 0 100%; }
/* A box filled from the invoice (invoice-reader.js), marked until the
   employee types over it. */
.expense-line input.is-read,
.expense-line select.is-read {
  background: var(--gold-wash);
  border-color: var(--gold);
}

/* --------------------------------------------------------------------------
   The HD Holding app's lock screen (static/js/native-app.js): the whole page
   hidden until Face ID or the fingerprint says so. Its own colours rather
   than the theme's, so it reads the same whatever the page underneath.
   -------------------------------------------------------------------------- */
.hd-locked body > :not(.hd-lock) { visibility: hidden !important; }
.hd-lock {
  position: fixed; inset: 0; z-index: 10000;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 18px; padding: env(safe-area-inset-top, 0px) 24px env(safe-area-inset-bottom, 0px);
  background: #12100C; color: #F3EFE7; text-align: center;
}
.hd-lock[hidden] { display: none !important; }
.hd-lock__mark {
  width: 72px; height: 72px; border-radius: 16px; background: #211E1A;
  display: grid; place-items: center; color: #B49C54; font: 700 28px Georgia, serif;
}
.hd-lock__title { font: 600 20px Georgia, 'Times New Roman', serif; }
.hd-lock__btn {
  min-width: 220px; min-height: 48px; padding: 12px 24px; border: 0; border-radius: 10px;
  background: #B49C54; color: #12100C; font: 600 16px var(--font-body);
}
.hd-lock__btn:focus-visible, .hd-lock__link:focus-visible { outline: 2px solid #F3EFE7; outline-offset: 3px; }
.hd-lock__link {
  background: none; border: 0; padding: 10px; color: #BDB5A6;
  font: 500 14px var(--font-body); text-decoration: underline;
}

/* --------------------------------------------------------------------------
   26. The full portal inside the iPhone app (owner, 05/10/2026)
   --------------------------------------------------------------------------
   "The top of the app is showing under the iOS top bar, clock, signal and
   battery, so I can't click on open menu when I'm in full site mode." The
   app's shell draws every page edge to edge (capacitor.config.json,
   contentInset: never), so the top bar sat behind the clock and the Dynamic
   Island and its menu button could not be tapped. The phone view (/m/) pads
   itself; the full portal now does too, but ONLY inside the iPhone app:
   base.html adds class="ios-app" and viewport-fit=cover there (which is what
   makes env(safe-area-inset-*) non-zero), so nothing here reaches a desktop
   browser, Android or Safari. Landscape: the notch is on the left or the
   right, so the sides are padded too. */
@media screen {
  html.ios-app .topbar {
    height: calc(var(--topbar-h) + env(safe-area-inset-top));
    padding-top: env(safe-area-inset-top);
    padding-right: calc(var(--gap-6) + env(safe-area-inset-right));
  }
  html.ios-app .sidebar {
    padding-top: env(safe-area-inset-top);
    padding-bottom: env(safe-area-inset-bottom);
    padding-left: env(safe-area-inset-left);
  }
  html.ios-app .content { padding-right: calc(var(--gap-6) + env(safe-area-inset-right)); }
  html.ios-app .main { padding-bottom: env(safe-area-inset-bottom); }
  html.ios-app .flash-stack { top: calc(var(--topbar-h) + env(safe-area-inset-top) + 12px); }
}
@media screen and (max-width: 900px) {
  /* The menu is a drawer here, so the top bar and the page reach the left edge. */
  html.ios-app .topbar {
    padding-left: calc(var(--gap-4) + env(safe-area-inset-left));
    padding-right: calc(var(--gap-4) + env(safe-area-inset-right));
  }
  html.ios-app .content {
    padding-left: calc(var(--gap-4) + env(safe-area-inset-left));
    padding-right: calc(var(--gap-4) + env(safe-area-inset-right));
  }
}

/* --------------------------------------------------------------------------
   27. An address, part by part (owner, 06/10/2026)
   --------------------------------------------------------------------------
   "It's not visual knowing the street, the building, the area." One line of
   text could not say which piece was which, so every part is a labelled tile,
   in the order HR fills them in: the English as typed, the Arabic under it. An
   empty part stays as a dashed tile, so what is missing shows as plainly as
   what is there. Used on the staff file and on the joiner's page. */
.addr { display: flex; flex-direction: column; gap: var(--gap-5); }
.addr__title { display: flex; align-items: center; gap: var(--gap-3); margin-bottom: var(--gap-2); }
.addr__title h3 { margin: 0; font-size: var(--text-sm); font-weight: 600; color: var(--ink-2, var(--ink)); }
.addr__parts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--gap-2); }
.addr__part {
  min-width: 0; display: flex; flex-direction: column; gap: 2px;
  padding: var(--gap-2) var(--gap-3);
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius);
}
.addr__label { font-size: var(--text-xs); text-transform: uppercase; letter-spacing: .05em; color: var(--ink-3); }
.addr__en { font-size: var(--text-sm); font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.addr__en a { color: inherit; }
.addr__ar { font-size: var(--text-sm); color: var(--ink-3); text-align: right; overflow-wrap: anywhere; }
.addr__part--empty { background: transparent; border-style: dashed; }
.addr__part--empty .addr__en { color: var(--ink-4); font-weight: 400; }
.addr__note { margin: 0; font-size: var(--text-sm); color: var(--ink-3); }
.addr__note--empty { color: var(--ink-4); font-style: italic; }

