/* ==========================================================================
   MKS BMS: lykha.css
   Hand-written CSS3, no build step. Tokens live in :root; everything else reads them.

   Contents
    1. Design tokens
    2. Base elements
    3. Typography and colour
    4. Layout
    5. Spacing
    6. Buttons
    7. Forms
    8. Cards, badges and chips
    9. Figures
   10. Tables, lists and pagination
   11. Alerts
   12. Tabs and filters
   13. Modal and progress
   14. App shell: sidebar and header
   15. Header tools: search, notifications, user menu
   16. Sign-in, legal and error pages
   17. Dashboard
   18. Employee home
   19. News, updates and comments
   20. People, documents and settings
   21. Accounting and invoices
   22. Helpers
   23. Order-dependent overrides

   Each section holds a component's base rules first, then its responsive and
   print overrides (desktop min-width, then max-width from wide to narrow, then
   print), so a class is defined in one place. The last section holds the few
   rules that must come after a rule in a later section: both can style the same
   element at the same specificity, so moving them would change which one wins.
   ========================================================================== */

/* ==========================================================================
   1. Design tokens
   ========================================================================== */

:root {
  /* Hue 171 at full saturation — the reference emerald. #009D85 itself is
     --primary-bright below: white on it is 3.37:1, and --primary carries white
     text on every button and the sidebar, so the base is one step darker. */
  --primary: #1e8cce;
  --primary-bright: #f59d2e;   /* the reference exactly. FILL ONLY: 3.41:1. */
  --primary-deep: #086d9e;
  --on-primary: #FFFFFF;
  /* Teal accents */
  --teal: #004e7a;
  --teal-bright: #2FBCA7;
  --teal-soft: #86CBC1;
  /* Not for dashboard surfaces — a gradient behind flat bars competes with them. */
  --teal-grad: linear-gradient(150deg, #2FDAC1 0%, #009D85 45%, #05574B 100%);
  --teal-orange-grad: linear-gradient(150deg, #F09C4E 0%, #009D85 45%, #05574B 100%);
  /* --jade is no longer the second chart series — --accent is. Kept because
     removing a token is not the same as removing its users. FILL ONLY. */
  --jade: #4FC79A;
  --jade-soft: #A9E5CE;
  /* Tints, at the new hue. Still misnamed — there is no mint in them — and renaming
     is a find-and-replace pass rather than a token edit. */
  --mint-50: #d7f0ff;
  /* Strengthened Sep 2026. These were 1.13-1.19:1 against a white card — a badge
     you had to look for rather than see. Now 1.27-1.40, with their text still
     above 4.1:1. .badge-tag takes --primary-deep with it: --primary is 3.59 here. */
  --mint-100: #cbecff;
  --mint-200: #c0e7ff;
  --mint-300: #aee1ff;
  /* Text ramp */
  --ink: #16222b;
  --body: #2C3D42;
  --charcoal: #425055;
  --mute: #5F6E72;        /* CHANGED from #6B7A7E — was 3.93:1 on --canvas-app, now 4.67 */
  --ash: #83908F;
  --stone: #9AA7AA;
  --faint: #C4CFD1;
  --on-dark: #FFFFFF;
  --on-dark-mute: rgba(255,255,255,0.78);
  --coolgray: #E2E7E8;
  /* Surfaces */
  --canvas-light: #FFFFFF;
  --canvas-app: #EEF1F1;
  --surface-soft: #F1F6F5;
  --surface-card: #FFFFFF;
  /* Hairlines */
  --hairline: #E3E9E9;
  --hairline-strong: #16272B;
  /* Status — the fill and the type are different colours. -bg for tints,
     the base for dots/bars/icons, -text for anything read as words. */
  --success: #2E9E7B;  --success-text: #29975f;  --success-bg: #C6ECDF;
  --warning: #B9781F;  --warning-text: #96590F;  --warning-bg: #F9E1B8;
  --danger:  #C6413D;  --danger-text:  #B0362F;  --danger-bg:  #F7D1CF;
  --link: #29a6f1;

  /* Orange accent. A FILL, like --jade before it: 2.17:1 on white, never type.
     --accent-text is the one that carries words, at 5.29:1.

     Note it sits at hue 29 and --warning at hue 35. Warning MEANS overdue in this
     product; accent means nothing in particular. Keep them apart on a page, or a
     decorative card will read as a problem. */
  --accent:      #FE9738;
  --accent-text: #A5570D;
  --accent-bg:   #FCDDC0;
  /* Chart series */
  --chart-1: var(--primary);
  /* Expenses in orange rather than jade. Separated from --chart-1 by HUE, not
     lightness — 2.11:1 between them — so the pair alone will not distinguish for a
     red-green colour-blind reader. Bar height and the labelled legend carry it. */
  --chart-2: var(--primary-bright);
  /* Radii */
  --r-xs: 5px; --r-sm: 10px; --r-md: 14px; --r-lg: 20px; --r-xl: 28px; --r-2xl: 32px; --r-full: 9999px;
  /* Spacing */
  --s-xxs: 4px; --s-xs: 6px; --s-sm: 8px; --s-md: 14px; --s-lg: 16px;
  --s-xl: 24px; --s-xxl: 32px; --s-xxxl: 48px;
  /* Elevation (cool-tinted, soft) */
  --shadow-soft: 0 1px 2px rgba(18,76,91,.04), 0 8px 24px rgba(18,76,91,.06);
  --shadow-card: 0 2px 4px rgba(18,76,91,.04), 0 12px 32px rgba(18,76,91,.07);
  --shadow-lift: 0 8px 30px rgba(18,76,91,.12);
  /* Type */
  /* Inter FIRST, and actually linked now. It sat fourth in this list behind two fonts that
     always resolve, so it never once rendered — every page has been Helvetica Neue or Arial
     while the stack claimed otherwise. Ordering a webfont after a system font is the same as
     not having it. */
  --font: 'Inter', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;
  --font-heading: 'Work Sans', 'Inter', system-ui, -apple-system, Arial, sans-serif;
  --surface-tint:       #FBFBFA;
  --surface-tint-hover: #F4F4F2;
}

/* ==========================================================================
   2. Base elements
   ========================================================================== */

/* 2. Reset / base */
*,
*::before,
*::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink);
  background: var(--canvas-app);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
/* 600, because Work Sans and Inter are both neutral grotesques and sit close together — weight
   is what separates a heading from body text now that a display face is not doing it.

   letter-spacing was a flat -1px !important, tuned by eye for Krona One's wide letterforms. At
   1px it is imperceptible on a 44px price and crushing on a 14px label, because it does not
   scale. -0.02em does, and Work Sans does not need the same correction. */
h1,
h2,
h3,
h4,
h5,
h6 { margin: 0; font-family: var(--font-heading); font-weight: 600; letter-spacing: -0.02em; line-height: 1.3; }
p { margin: 0; }
a { color: var(--link); text-decoration: none; }
img { max-width: 100%; display: block; }
table { border-collapse: collapse; width: 100%; }
@media print {
  body { background: #fff !important; color: #000; font-size: 9pt; line-height: 1.35; }
  a { color: #000 !important; text-decoration: none !important; }
  /* The accounting statements and reports print from the browser rather than
     through DomPDF: they reuse the page already rendered, so a printout cannot
     drift from what was on screen, and one stylesheet covers all twelve.
     Invoices keep their server-side PDF — that file leaves the building.

     Second pass. The first added a border to every card, which framed each
     statement in a rounded box that belonged on a screen, and told cards not to
     break across pages — which for a ledger taller than a sheet of paper meant
     the browser pushed the whole thing down and printed a blank page first. */
  @page { margin: 14mm; }
  table thead { display: table-header-group; }
  table tfoot { display: table-footer-group; }
  table tr { page-break-inside: avoid; }
  /* Headings were sized for a screen and ate a third of the first page. */
  h1,
  .t-display-lg { font-size: 10pt !important; margin: 0 0 1mm !important; }
}

/* ==========================================================================
   3. Typography and colour
   ========================================================================== */

/* 3. Typography scale (headings use Work Sans 600) */
.t-display-xl,
.t-display-lg,
.t-display-md,
.t-heading-lg,
.t-heading-md,
.t-heading-sm { font-family: var(--font-heading); font-weight: 600; letter-spacing: -0.01em; }
.t-display-xl { font-size: 35px; line-height: 1.15; }
.t-display-lg { font-size: 28px; line-height: 1.2; }
.t-display-md { font-size: 22px; line-height: 1.25; }
@media (max-width: 480px) {
  .t-display-lg { font-size: 25px; }
}

@media print {
  .t-display-md { font-size: 9pt !important; }
}

.t-heading-lg { font-size: 18px; line-height: 1.3; }
.t-heading-md { font-size: 16px; line-height: 1.35; }
.t-heading-sm { font-size: 13px; line-height: 1.4; }
.t-heading-xs { font-size: 10px; line-height: 1.2; }
@media (max-width: 480px) {
  .t-heading-sm { font-size: 9.5px; }
}

@media print {
  .t-heading-sm { font-size: 8pt !important; }
}

.t-body-lg { font-size: 17px; line-height: 1.55; }
.t-body { font-size: 15px; line-height: 1.55; }
.t-body-sm { font-size: 13px; line-height: 1.5; }
.t-caption { font-size: 11px; line-height: 1.4; letter-spacing: .2px; }
@media (max-width: 480px) {
  .t-caption { margin-top:4px !important; font-size:8px !important; text-transform: uppercase; }
}

@media print {
  .t-body-lg,
  .t-body-sm,
  .t-caption { font-size: 7.5pt !important; }
}

.t-right { text-align: right; }
.t-center { text-align: center; }
.fw-400 { font-weight: 400; }
.fw-500 { font-weight: 500; }
.fw-600 { font-weight: 600; }
.fw-700 { font-weight: 700; }
.fw-900 { font-weight: 900; }
/* Colour helpers */
.c-primary { color:var(--primary); }
.c-teal { color:var(--teal); }
.c-ink { color:var(--ink); }
.c-mute { color:var(--mute); }
.c-stone { color:var(--stone); }
.c-white { color:#fff; }
.c-danger { color:var(--danger-text); }
.c-success { color:var(--success-text); }
/* 12. Utilities & components that replace inline styles */
/* Text on teal / primary surfaces */
.c-on-dark { color: var(--on-dark); }
.c-on-dark-mute { color: var(--on-dark-mute); }
.bg-app { background:var(--canvas-app); }
.bg-white { background:#fff; }
.bg-mint { background:var(--mint-100); }
.bg-teal-grad { background:var(--teal-grad); }

/* ==========================================================================
   4. Layout
   ========================================================================== */

/* 4. Layout helpers (lean, purposeful) */
.container { max-width: 1240px; margin: 0 auto; padding: 0 24px; }
.stack > * + * { margin-top: var(--s-lg); }
.grid { display: grid; gap: 20px; }
/* * auto-fit, not a fixed count. These grids hold cards that are conditionally rendered — the
   * dashboard shows finance, invoices and projects only to somebody permitted each — so a fixed
   * repeat(3, 1fr) left an admin with one permitted module looking at one third-width card and two
   * empty columns.
   *
   * auto-fit rather than auto-fill: auto-fill keeps the empty tracks, which is the bug. auto-fit
   * collapses them, so whatever cards exist stretch to fill the row.
   *
   * The minimums are what stop two cards becoming two absurdly wide ones on a large screen, and
   * they are the widths at which each card's contents stay readable. */
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
@media (max-width: 900px) {
  .grid-2 { grid-template-columns: 1fr; }
  /* Below the minimums above, auto-fit already gives a single column; these keep the previous
     behaviour explicit rather than relying on the minmax floor to do it. */
  .grid-3 { grid-template-columns: 1fr; }
  .grid-4 { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
}

@media (max-width: 640px) {
  .grid-4 { grid-template-columns: 1fr 1fr; }
  .grid-3 { grid-template-columns: repeat(auto-fit, minmax(150px,2fr)); }
}

/* Four across inside a 70% column gave each tile about 150px, which truncated the labels.
   auto-fit keeps them readable and simply wraps to two rows when the column narrows. */
.tile-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 20px; }
/* Two-column form grid; .col-full spans both */
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 20px; }
.form-grid .col-full { grid-column: 1 / -1; }
@media (max-width: 700px) {
  .form-grid { grid-template-columns: 1fr; }
}

/* Grid span helper (e.g. documents file panel over a 3-col grid) */
.col-span-2 { grid-column: span 2; }
@media (max-width: 900px) {
  .col-span-2 { grid-column: auto; }
}

/* Project overview 25/75 split (POLISH1) */
.split-2575 { display: grid; grid-template-columns: 1fr 3fr; gap: 20px; align-items: start; }
@media (max-width: 900px) {
  .split-2575 { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  .split-2575 { grid-template-columns: 1fr; }
}

.row { display: flex; align-items: center; }
.row-top { display: flex; align-items: flex-start; }
.between { justify-content: space-between; }
.wrap { flex-wrap: wrap; }
.gap-sm { gap: 8px; }
.gap-md { gap: 14px; }
.gap-lg { gap: 16px; }
.gap-xl { gap: 24px; }
.full { width: 100%; }
/* 16. Lists, toolbars, forms (module CRUD) */
.toolbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
@media (max-width: 640px) {
  .toolbar { flex-direction: column; align-items: flex-start; gap: 12px; }
}

@media print {
  /* Keep the heading with the table it introduces. */
  .toolbar { page-break-after: avoid; margin-bottom: 3mm !important; }
}

/* ==========================================================================
   5. Spacing
   ========================================================================== */

.mt-sm { margin-top:8px; }
.mt-md { margin-top:14px; }
.mt-lg { margin-top:16px; }
.mt-xl { margin-top:24px; }
.mb-sm { margin-bottom:8px; }
.mb-md { margin-bottom:14px; }
.mb-lg { margin-bottom:16px; }
.mb-xl { margin-bottom:24px; }
/* Stack gap modifiers (sibling spacing) */
.stack-xs > * + * { margin-top: 8px; }
.stack-sm > * + * { margin-top: 12px; }
/* "Needs your attention" rows. The level is carried by a WORD as well as
   colour; red/amber is the commonest pair to be indistinguishable, and this
   is the one place where urgent-versus-later is the whole message. */
.stack-sm { display: flex; flex-direction: column; gap: 6px; }

/* ==========================================================================
   6. Buttons
   ========================================================================== */

/* 5. Buttons (pill, min 46px) */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 46px; padding: 12px 24px;
  border: 0; border-radius: var(--r-sm);
  font-family: var(--font); font-size: 15px; font-weight: 500; line-height: 1;
  cursor: pointer; transition: background-color .15s, opacity .15s, box-shadow .15s;
}
.btn:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(63,167,165,.4); }
.btn:disabled { opacity: .5; pointer-events: none; }
.btn-primary { background: var(--primary); color: var(--on-primary); }
.btn-primary:hover { background: var(--primary-bright); }
.btn-primary:active { background: var(--primary-deep); }
.btn-teal { background: var(--teal-grad); color: #fff; }
.btn-teal:hover { opacity: .93; }
.btn-soft { background: var(--mint-100); color: var(--primary); }
.btn-soft:hover { background: var(--mint-200); }
.btn-outline { background: #fff; color: var(--ink); border: 1px solid var(--hairline); }
.btn-outline:hover { background: var(--surface-soft); }
.btn-sm,
.pill { height: 32px; padding: 5px 12px; font-size: 12px; }
/* White pill button for teal/dark surfaces */
.btn-white { background: #fff; color: var(--primary); }
.btn-white:hover { background: var(--mint-100); }
.btn-block { display: block; width: 100%; }
/* Permanent, and there is no Trash behind it. Red before the cursor arrives. */
.btn-danger {
  border: 1px solid var(--danger);
  background: var(--danger, #b42318);
  border-color: var(--danger, #b42318);
  color: #fff;
}
.btn-danger:hover {
  color: #fff;
  filter: brightness(1.08);
}
/* .input-md/.select-md moved the fields to 44px but left Apply/Clear on .btn-sm at
   36px, which widened the very misalignment that change was meant to remove. Every
   control on a filter row is now one height. */
.btn-md { height: 44px; padding: 10px 20px; font-size: 14px; }
.link-btn { background: none; border: 0; color: var(--link); font-size: 11px; cursor: pointer; padding: 0; }
button.link-btn { font-size: 14px; font-weight: bold;text-align: left; }

/* ==========================================================================
   7. Forms
   ========================================================================== */

/* 6. Inputs */
.field { margin-bottom: 16px; }
.field-error { margin-top: 6px; font-size: 13px; color: var(--danger-text); }
.field-narrow { max-width: 280px; }
.label { display: block; font-size: 13px; font-weight: 500; color: var(--charcoal); margin-bottom: 6px; }
.input,
.select,
.textarea {
  width: 100%; height: 52px; padding: 13px 16px;
  border: 1px solid var(--hairline); border-radius: var(--r-sm);
  background: #fff; color: var(--ink); font-family: var(--font); font-size: 15px;
  transition: border-color .15s;
}
.input::placeholder { color: var(--stone); }
.input:focus,
.select:focus,
.textarea:focus { outline: none; border-color: var(--teal); }
/* Index filters sit on one row. The search box was competing with the selects for
   width, and the date range only appears when Period is set to Custom.
   Appended rather than edited in place so existing rules above stay untouched. */
.input-search {  max-width: 160px;}
.input-sm { height: 36px; padding: 6px 10px; font-size: 13px; }
.input-code { font-size: 24px; letter-spacing: 8px; text-align: center; font-family: var(--font-heading); }
.input-color { padding: 4px; height: 44px; width: 80px; }
/* Filter rows used .input-sm (36px) beside .select-sm (32px), so the search box and
   the dropdowns on the same row were four pixels apart and visibly misaligned. -md is
   one size: 44px for both, between the 36px small controls and the 52px form fields.
   Appended, never edited in place, so every rule above survives untouched. */
.input-md { height: 44px; padding: 10px 14px; font-size: 14px; }
/* Compact inline select (task status in a row) */
.select-inline { height: 36px; padding: 6px 10px; font-size: 13px; width: auto; }
.select-sm { height: 32px; padding: 0 8px; font-size: 13px; }
.select-md { height: 44px; padding: 0 12px; font-size: 14px; }
.textarea { height: auto; min-height: 110px; resize: vertical; }
.req { color: var(--danger-text); }
/* The toggle sits inside the field rather than beside it, so the input keeps full width. */
.pw-wrap { position: relative; display: block; }
.pw-wrap .input { padding-right: 64px; }
.pw-toggle {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  border: 0; background: transparent; cursor: pointer; padding: 4px 8px;
  color: var(--link); font-size: 13px; font-weight: 500; border-radius: var(--r-xs);
}
.pw-toggle:hover { background: var(--mint-100); }
.quill-host { background: #fff; border-radius: 0 0 var(--r-sm) var(--r-sm); height:auto !important; }
/* Project updates feed */
.ql-editor { height:auto; min-height:100px; }
.ql-container { font-size:15px !important; }
/* Structured tax-bracket editor — each bracket is its own labeled card */
.bracket-group {
  border: 1px solid var(--hairline); border-radius: var(--r-sm); padding: 16px;
  margin-bottom: 12px; background: var(--surface-soft);
}
.bracket-fields { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0 14px; }
@media (max-width: 700px) {
  .bracket-fields { grid-template-columns: 1fr; }
}

.emp-check-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 8px 16px; }
.emp-check { display: flex; align-items: center; gap: 8px; font-size: 14px; }

/* ==========================================================================
   8. Cards, badges and chips
   ========================================================================== */

.card { border-radius: var(--r-sm); background: var(--surface-card); padding: 24px; box-shadow: var(--shadow-card); }
.card-flat { border-radius: var(--r-sm); background: var(--surface-card); padding: 24px; border: 1px solid var(--hairline); }
.card-flat .t-caption { font-size:13px; }
.empty { text-align: center; padding: 48px 24px; color: var(--mute); }
.card-teal { border-radius: var(--r-sm); background: var(--teal-grad); color: var(--on-dark); padding: 24px; box-shadow: var(--shadow-lift); }
.card-elevated { border-radius: var(--r-sm); background: var(--primary); color: var(--on-dark); padding: 24px; }
@media print {
  /* Deliberately NOT page-break-inside: avoid. A general ledger is taller than
     a page, and telling the browser to keep it whole makes it start on the
     next one — which is the blank first page. Rows avoid splitting; the
     container must be free to flow. */
  .card,
  .card-flat {
    box-shadow: none !important; border: 1px solid #ddd;
    page-break-inside: auto;
  }
  /* No frame. On screen a card is a container; on paper the page is the
     container, and a rounded border around a statement reads as a screenshot
     of a website rather than a document. */
  .card,
  .card-flat,
  .statement {
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    padding: 0 !important;
    margin: 0 0 6mm 0 !important;
    background: transparent !important;
  }
}

/* 8. Badges */
.badge {
  display: inline-flex; align-items: center; padding: 4px 12px; border-radius: var(--r-sm);
  font-size: 12px; font-weight: 500; line-height: 1.4; gap:5px;
}
.badge-tag { background: var(--coolgray);   color: var(--primary-deep); }
.badge-feature { background: var(--primary);     color: var(--on-primary); }
.badge-success { background: var(--success-bg);  color: var(--success-text); }
.badge-warning { background: var(--warning-bg);  color: var(--warning-text); }
.badge-danger { background: var(--danger-bg);   color: var(--danger-text); }
@media print {
  /* Browsers print backgrounds off by default, so a coloured badge arrives as
     an empty rectangle. A border keeps the word readable — the status is why
     somebody printed the page. */
  .badge {
    background: transparent !important;
    border: 1px solid #666 !important;
    border-radius: 4px !important;
    color: #000 !important;
    padding: 2px 4px !important;
    font-size: 7.5pt;
  }
}

.pill {
  display: inline-flex; align-items: center; border: 0; border-radius: var(--r-sm);
  background: var(--mint-100); color: var(--primary); font-weight: 500; cursor: pointer;
}
.pill:hover { background: var(--mint-200); }
.pill.disabled { opacity: .5; pointer-events: none; }
/* Shape for the 50-odd reversible removals, colour for the three that are not.

   Reddening every delete would have made the one control that destroys a
   workspace look exactly like the one that removes a tag from a project. These
   removals are soft — they land in Trash — so they read as removals by shape
   and turn red only under the cursor, at the moment somebody is about to. */
.pill-remove {
  color: var(--danger-text);
  border-color: var(--hairline);
  background: var(--danger-bg);
}
.pill-remove:hover {
  color: var(--danger, #b42318);
  border-color: var(--danger, #b42318);
  background: color-mix(in srgb, var(--danger, #b42318) 6%, transparent);
}

/* ==========================================================================
   9. Figures
   ========================================================================== */

/* 9. Metric figure */
.metric {
  font-family: var(--font); font-size: 28px; font-weight: bold;
  line-height: 1.05; letter-spacing: -.5px;
}
/* Metric suffix + price figure */
.metric-unit { font-size: 22px; font-weight: 400; color: var(--stone); }
.metric-sm { font-size: 20px; font-weight: 600; line-height: 1.2; }
@media (max-width: 480px) {
  .metric { font-size: 20px; }
}

@media print {
  .metric { font-size: 9pt !important; }
}

.kpi { display: flex; flex-direction: column; justify-content: flex-start; }
.stat-active { border-color: var(--success); box-shadow: 0 0 0 1px var(--success) inset; }

/* ==========================================================================
   10. Tables, lists and pagination
   ========================================================================== */

/* 10. Data table */
.table { background: #fff; border-radius: var(--r-sm); overflow: hidden; box-shadow: var(--shadow-card); }
.table th,
.table td { text-align: left; padding: 14px 20px; }
.table td .t-caption { font-size:11px; }
.table thead th { color: var(--mute); font-weight: 500; border-bottom: 1px solid var(--hairline); }
.table tbody tr + tr td { border-top: 1px solid var(--hairline); }
.table .num { text-align: right; }
/* A table cannot scroll itself: overflow-x on <table> is ignored, so the base
   overflow:hidden simply clipped anything too wide. The wrapper is the scroll
   container; the table inside keeps its own width. */
.table-wrap {
  width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch;
  border-radius: var(--r-sm); box-shadow: var(--shadow-card);
}
.table-wrap .table { box-shadow: none; border-radius: 0; min-width: 225px; }
@media (max-width: 820px) {
  .table {
    display: block;
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    white-space: nowrap;
    border-radius: 0;
  }
}

@media print {
  /* Smaller, so more of a statement reaches one sheet. Figures stay legible at
     8pt in a table; below that a column of pesos becomes hard to scan. */
  .table,
  table { font-size: 8pt; width: 100% !important; }
  .table th,
  .table td,
  table th,
  table td { padding: 7.5px 15px !important; font-size:8pt !important; }
  .table th,
  table th { border-bottom: 1px solid #000; font-size: 7.5pt; }
}

.tbl-group td { background: var(--surface-soft); font-weight: 600; color: var(--ink); font-size: 13px; text-transform: uppercase; letter-spacing: .03em; }
.row-link { color: var(--ink); font-weight: 600; }
.row-link:hover { color: var(--primary); }
/* Data-table titles link to the record. Where the detail is a modal the title is a
   <button>, which needs the browser chrome stripped to read as the same link. */
button.row-link {
  border: 0; background: transparent; padding: 0; margin: 0;
  font: inherit; cursor: pointer; text-align: left;
}
/* Laravel's plain pagination view (pagination::default): one list item per page. */
.pagination { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
/* Detail page description list */
.dl { display: grid; grid-template-columns: 160px 1fr; gap: 10px 16px; }
.dl-stack { display: flex; flex-direction: column; gap: 10px; }
.dl-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding-top: 10px; border-top: 1px solid var(--hairline); }
.dl-row:first-child { border-top: 0; padding-top: 0; }
.dl dt { color: var(--mute); font-size: 14px; }
.dl dd { margin: 0; font-size: 15px; }
@media (max-width: 600px) {
  .dl { grid-template-columns: 1fr; gap: 2px 0; }
  .dl dd { margin-bottom: 10px; }
}

/* Activity log rows */
.activity-row { display: flex; align-items: flex-start; gap: 12px; padding: 12px 4px; border-bottom: 1px solid var(--hairline); }
.activity-row:last-child { border-bottom: 0; }
.activity-body { flex: 1; }

/* ==========================================================================
   11. Alerts
   ========================================================================== */

/* 14. Alerts / flash notices */
.alert { border-radius: var(--r-sm); padding: 12px 16px; font-size: 14px; margin-bottom: 16px; }
.alert-danger { background: var(--danger-bg); color: var(--danger-text); }
.alert-notice { background: var(--warning-bg); color: var(--warning-text); }
/* Undo alert (soft-delete) */
.undo-alert { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.undo-form { display: inline; }
.undo-alert .link-btn { color: var(--primary); font-weight: 600; font-size: 13px; }

/* ==========================================================================
   12. Tabs and filters
   ========================================================================== */

/* Project workspace sub-navigation (tabs) */
/* The page sub-navigation (client pages, the client portal, accounting) wrapped onto two or three
   lines on a phone; it scrolls in one line, like the tabs above. */
.subnav {
  display: flex;
  gap: 2px;
  border-bottom: 1px solid var(--hairline);
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.subnav a {
  display: inline-flex; align-items: center; gap: 8px; padding: 12px 14px; font-size: 14px;
  color: var(--charcoal); border-bottom: 2px solid transparent; transition: color .15s, border-color .15s; font-weight:600;
  flex: 0 0 auto; white-space: nowrap;
}
.subnav a i { font-size: 13px; }
.subnav a:hover { color: var(--ink); }
.subnav a.active { color: var(--primary); border-bottom-color: var(--primary); font-weight: 700; }
.subnav::-webkit-scrollbar { display: none; }
@media (max-width: 700px) {
  .subnav a { padding: 10px 12px; }
}

.filter-bar { display: flex; justify-content: space-between; align-items: flex-end; gap: 16px; flex-wrap: wrap; }
.filter-tabs { display: inline-flex; gap: 4px; background: var(--surface-soft); padding: 8px; border-radius: var(--r-sm); }
.filter-tab {
  display: inline-flex; align-items: center; gap: 6px; padding: 7px 16px; border-radius: var(--r-xs);
  color: var(--mute); font-size: 14px; font-weight: 500; text-decoration: none; border:0 !important; background:none !important;
  flex: 0 0 auto; white-space: nowrap; scroll-snap-align: start;
}
.filter-tab:hover { color: var(--ink); cursor:pointer; }
.filter-tab.active { background: var(--surface-card) !important; color: var(--ink); box-shadow: var(--shadow-card); }
.filter-tab .badge { margin-left: 2px; }
.filter-dates { display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap; }
.filter-dates .field { margin-bottom: 0; }
.filter-bar > .filter-dates { flex: 1; align-items: flex-end; }
.filter-dates .select-sm { max-width: 180px; }
.filter-range { display: inline-flex; align-items: flex-end; gap: 6px; }
.filter-range .field { margin-bottom: 0; }
.filter-sep { color: var(--mute); padding-bottom: 8px; }
.filter-dates .select-md { max-width: 200px; }
.filter-dates .input-search { max-width: 260px; }
.filter-tabs::-webkit-scrollbar { display: none; }
.filter-tabs,
.subnav { position: relative; }
@media (max-width: 700px) {
  .filter-tabs { display: flex; width: 100%; padding: 6px; }
  .filter-tab { padding: 7px 12px; }
  .filter-dates .select-md { max-width: 100%; }
  /* Filter controls (Aug 2026) — the search box gives up width first on narrow screens;
     the selects need their labels readable more than the search box needs the room. */
  .filter-dates .input-search { max-width: 100%; }
}

/* ==========================================================================
   13. Modal and progress
   ========================================================================== */

/* Modal dialog (native <dialog>) */
/* * A dialog opened with showModal() sits at the top of the viewport by default — margin: auto
   * only centres it horizontally. The inset/margin pair centres it both ways.
   *
   * max-height with a scrolling body as well: a long announcement centred with no limit runs off
   * both edges at once, and there is no way to reach either end of it. */
.modal {
  border: 0; border-radius: var(--r-sm); padding: 0; width: 92%; max-width: 640px;
  inset: 0; margin: auto; max-height: 88vh;
  box-shadow: var(--shadow-lift); color: var(--ink); background: #fff;
}
.modal::backdrop { background: rgba(16,39,47,.45); }
.modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px; border-bottom: 1px solid var(--hairline);
}
.modal-body { padding: 20px; max-height: calc(88vh - 64px); overflow-y: auto; }
/* Progress bar — native <progress>, value comes from attributes (no inline width) */
progress.progress {
  -webkit-appearance: none; appearance: none; width: 100%; height: 12px;
  border: 0; border-radius: var(--r-sm); background: var(--mint-100); overflow: hidden;
}
progress.progress::-webkit-progress-bar { background: var(--mint-100); border-radius: var(--r-sm); }
progress.progress::-webkit-progress-value { background: linear-gradient(90deg, #2FDAC1, #05574B); border-radius: var(--r-sm); }
progress.progress::-moz-progress-bar { background: linear-gradient(90deg, #2FDAC1, #05574B); border-radius: var(--r-sm); }

/* ==========================================================================
   14. App shell: sidebar and header
   ========================================================================== */

/* 11. App shell (PMS-style sidebar + header) */
.app-layout { display: flex; min-height: 100vh; }
@media (min-width: 901px) {
  .app-layout.nav-collapsed .sidebar { width: 72px; }
  .app-layout.nav-collapsed .main-content { margin-left: 72px; }
  .app-layout.nav-collapsed .brand-name,
  .app-layout.nav-collapsed .nav-item span,
  .app-layout.nav-collapsed .nav-label,
  .app-layout.nav-collapsed .user-details { display: none; }
  .app-layout.nav-collapsed .sidebar-header { justify-content: center; padding-left: 8px; padding-right: 8px; }
  .app-layout.nav-collapsed .sidebar-logo { gap: 0; }
  .app-layout.nav-collapsed .nav-item { justify-content: center; padding: 11px 0; gap: 0; border-left-width: 0; }
  .app-layout.nav-collapsed .nav-item i { width: auto; font-size: 16px; }
  .app-layout.nav-collapsed .nav-section { margin-bottom: 2px; }
  .app-layout.nav-collapsed .user-info { justify-content: center; }
  .app-layout.nav-collapsed .sidebar-footer { padding: 12px 6px; }
}

@media (max-width: 900px) {
  .app-layout.nav-open .nav-scrim { opacity: 1; visibility: visible; }
}

@media print {
  .app-layout,
  .main-content,
  .content-area { overflow: visible !important; height: auto !important; }
}

.sidebar {
  width: 260px; background: var(--primary-deep); color: var(--on-dark-mute);
  display: flex; flex-direction: column; position: fixed; top: 0; left: 0; bottom: 0;
  z-index: 100; overflow-x: hidden;
}
.sidebar-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 16px; border-bottom: 1px solid rgba(255,255,255,.06);
}
.sidebar-logo { display: flex; align-items: center; gap: 10px; }
.sidebar-nav { flex: 1; overflow-y: auto; padding: 12px 0; }
.sidebar-nav::-webkit-scrollbar { width: 4px; }
.sidebar-nav::-webkit-scrollbar-thumb { background: rgba(255,255,255,.12); border-radius: 2px; }
.sidebar-footer { padding: 16px; border-top: 1px solid rgba(255,255,255,.06); }
@media (min-width: 901px) {
  .sidebar { transition: width .2s ease; }
}

@media (max-width: 900px) {
  .sidebar { transform: translateX(-100%); transition: transform .3s ease; box-shadow: var(--shadow-lift); }
  .sidebar.open { transform: translateX(0); }
}

@media print {
  .sidebar,
  .top-header,
  .no-print { display: none !important; }
}

.brand-icon {
  width: 44px; height: 44px; background: var(--teal-grad); border-radius: var(--r-sm);
  display: flex; align-items: center; justify-content: center; color: #fff; font-size: 18px; flex-shrink: 0;
}
.brand-name {
  color: #fff; font-weight: 600; font-size: 16px; line-height: 1.15; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; max-width: 160px;
}
.brand-name_builder {
  font-weight: 500; font-size: 8px; color: var(--on-dark-mute);
  text-transform: uppercase; letter-spacing: 1px; margin-top: 2px;
}
.brand-icon-img { background: none; padding: 0; }
.brand-icon-img img { width: 100%; height: 100%; object-fit: contain; border-radius: var(--r-sm); }
.nav-section { margin-bottom: 4px; }
.nav-label {
  display: block; font-size: 10px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .08em; color: rgba(255,255,255,.35); padding: 12px 20px 4px;
}
.nav-item {
  display: flex; align-items: center; gap: 12px; padding: 10px 20px; font-size: 13.5px;
  color: var(--on-primary); border-left: 4px solid transparent;
  transition: background .15s, color .15s, border-color .15s; text-transform:capitalize; font-weight:500;
}
.nav-item:hover { background: var(--primary-bright); color: #fff; text-decoration: none; }
.nav-item.active { background: var(--primary-bright); color: white; border-left-color: #a25a00; }
.nav-item i { width: 18px; text-align: center; font-size: 14px; flex-shrink: 0; }
.nav-scrim {
  position: fixed;
  inset: 0;
  background: rgba(15, 30, 32, .42);
  z-index: 90;
  opacity: 0;
  visibility: hidden;
  transition: opacity .25s ease;
}
@media (min-width: 901px) {
  .nav-scrim { display: none; }
}

@media (max-width: 900px) {
  body.nav-locked { overflow: hidden; }
}

.user-info { display: flex; align-items: center; gap: 10px; }
.user-avatar {
  width: 36px; height: 36px; background: var(--teal-grad); border-radius: var(--r-sm);
  display: flex; align-items: center; justify-content: center; color: #fff; font-weight: 600; font-size: 12px; flex-shrink: 0;
}
.user-details { flex: 1; min-width: 0; }
.user-name { color: #fff; font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-role { color: var(--on-dark-mute); font-size: 11px; }
.user-avatar-sm { width: 28px; height: 28px; font-size: 10px; }
.main-content { flex: 1; margin-left: 260px; display: flex; flex-direction: column; min-height: 100vh; min-width: 0; }
@media (min-width: 901px) {
  .main-content { transition: margin-left .2s ease; }
}

@media (max-width: 900px) {
  .main-content { margin-left: 0; }
}

@media print {
  .main-content { margin-left: 0 !important; }
}

.top-header {
  height: 64px; background: #fff; border-bottom: 1px solid var(--hairline);
  display: flex; align-items: center; justify-content: space-between; padding: 0 24px;
  position: sticky; top: 0; z-index: 50; box-shadow: var(--shadow-soft);
}
.header-left { display: flex; align-items: center; gap: 12px; }
.header-right { display: flex; align-items: center; gap: 12px; }
.page-title { font-size: 18px; font-weight: 600; color: var(--ink); }
.mobile-toggle { display: none; background: none; border: 0; color: var(--mute); font-size: 18px; cursor: pointer; padding: 4px; }
@media (max-width: 900px) {
  .mobile-toggle { display: block; }
}

.content-area { padding: 24px; }
@media (max-width: 640px) {
  .content-area { padding: 16px; }
}

@media print {
  .content-area { padding: 0 !important; }
  /* A trailing empty element is enough to produce one more sheet. */
  .content-area > *:last-child { margin-bottom: 0 !important; }
}

/* ==========================================================================
   15. Header tools: search, notifications, user menu
   ========================================================================== */

.hsearch { position: relative; }
.hsearch-icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--mute); font-size: 13px; pointer-events: none; }
.hsearch-input {
  width: 340px; max-width: 46vw; height: 38px; padding: 0 12px 0 34px; border: 1px solid var(--hairline);
  border-radius: var(--r-sm); background: var(--surface-soft); color: var(--ink); font-size: 14px; outline: none;
}
.hsearch-input:focus { border-color: var(--primary); background: #fff; box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 14%, transparent); }
.hsearch-results {
  position: absolute; top: calc(100% + 6px); left: 0; width: 380px; max-width: 90vw; max-height: 66vh; overflow-y: auto;
  background: #fff; border: 1px solid var(--hairline); border-radius: var(--r-sm); box-shadow: var(--shadow-soft); z-index: 60; padding: 6px;
}
.hsearch-group { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--mute); font-weight: 600; padding: 8px 10px 4px; }
.hsearch-item { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px; border-radius: var(--r-sm); color: var(--ink); text-decoration: none; }
.hsearch-item:hover { background: var(--surface-soft); }
.hsearch-item-label { font-weight: 500; font-size: 14px; }
.hsearch-item-sub { font-size: 12px; color: var(--mute); }
.hsearch-empty { padding: 14px 10px; color: var(--mute); font-size: 13px; text-align: center; }
@media (max-width: 640px) {
  .hsearch-input { width: 180px; }
}

/* Notification bell (topbar dropdown) */
.notif { position: relative; }
.notif > summary { list-style: none; cursor: pointer; }
.notif > summary::-webkit-details-marker { display: none; }
.notif-btn {
  position: relative; width: 38px; height: 38px; border-radius: var(--r-sm);
  display: inline-flex; align-items: center; justify-content: center; color: var(--mute);
  background: var(--surface-soft);
}
.notif-btn:hover { color: var(--primary); }
.notif-badge {
  position: absolute; top: -2px; right: -2px; min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: var(--r-sm); background: var(--danger); color: #fff; font-size: 10px;
  font-weight: 600; display: inline-flex; align-items: center; justify-content: center;
}
.notif-panel {
  position: absolute; right: 0; top: 46px; width: 320px; background: #fff;
  border: 1px solid var(--hairline); border-radius: var(--r-sm); box-shadow: var(--shadow-card);
  z-index: 60; overflow: hidden;
}
.notif-head {
  display: flex; align-items: center; justify-content: space-between; padding: 12px 14px;
  border-bottom: 1px solid var(--hairline);
}
.notif-list { max-height: 360px; overflow-y: auto; }
.notif-item { display: block; padding: 10px 14px; border-bottom: 1px solid var(--hairline); }
.notif-item:hover { background: var(--surface-soft); }
.notif-item.unread { background: var(--mint-50); }
.notif-title { font-size: 13px; font-weight: 500; color: var(--ink); }
.notif-msg { font-size: 12px; color: var(--mute); margin-top: 2px; }
.notif-time { font-size: 11px; color: var(--stone); margin-top: 3px; }
.notif-empty { padding: 24px 14px; text-align: center; color: var(--mute); font-size: 13px; }
.notif-foot { display: block; text-align: center; padding: 10px; font-size: 13px; color: var(--primary); }
.notif-foot:hover { background: var(--surface-soft); }
/* Notifications page rows */
.notif-row { display: flex; gap: 12px; padding: 14px 4px; border-bottom: 1px solid var(--hairline); }
.notif-row:last-child { border-bottom: 0; }
.notif-row-dot { width: 8px; height: 8px; border-radius: var(--r-sm); background: transparent; margin-top: 6px; flex-shrink: 0; }
.notif-row.unread .notif-row-dot { background: var(--teal); }
.notif-row-body { flex: 1; }
@media (max-width: 640px) {
  .notif-panel { width:250px; }
}

.usermenu { position: relative; }
.usermenu > summary { list-style: none; cursor: pointer; }
.usermenu > summary::-webkit-details-marker { display: none; }
.usermenu-btn { display: inline-flex; align-items: center; gap: 8px; padding: 4px 8px 4px 4px; border-radius: var(--r-sm); border: 1px solid var(--hairline); background: #fff; }
.usermenu-btn:hover { background: var(--surface-soft); }
.usermenu-avatar {
  width: 30px; height: 30px; border-radius: var(--r-sm); background: var(--primary); color: #fff; font-size: 12px; font-weight: 600;
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.usermenu-name { font-size: 14px; font-weight: 500; color: var(--ink); max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.usermenu-caret { font-size: 11px; color: var(--mute); }
.usermenu-panel {
  position: absolute; top: calc(100% + 6px); right: 0; min-width: 208px; background: #fff; border: 1px solid var(--hairline);
  border-radius: var(--r-sm); box-shadow: var(--shadow-soft); z-index: 60; padding: 6px;
}
.usermenu-item {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 12px; border-radius: var(--r-sm); border: 0; background: none;
  color: var(--ink); font-size: 14px; text-align: left; text-decoration: none; cursor: pointer;
}
.usermenu-item:hover { background: var(--surface-soft); }
.usermenu-item i { width: 16px; color: var(--mute); }
img.usermenu-avatar { object-fit: cover; padding: 0; background: var(--surface-soft); }
@media (max-width: 640px) {
  .usermenu-name { display: none; }
}

/* ==========================================================================
   16. Sign-in, legal and error pages
   ========================================================================== */

/* 13. Auth screens */
.auth-screen {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 40px 24px; background: var(--canvas-app);
}
.auth-card { width: 100%; max-width: 440px; }
.auth-brand {
  font-size: 20px; font-weight: 500; letter-spacing: -0.01em; margin-bottom: 15px;
  text-align: center;
}
.auth-head { margin-bottom: 24px; }
.auth-foot { margin-top: 20px; text-align: center; }
.auth-logo { height: 100px; width: auto; display: inline-block; border-radius:5px; }
/* Long-form documents: a readable measure matters more than filling the viewport. */
.legal-page { max-width: 760px; margin: 0 auto; padding: 32px 24px 64px; }
.legal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 24px; }
.legal-body { padding: 32px; }
.legal-body h2 { color: var(--ink); }
.legal-body ul { margin: 8px 0 0 20px; }
.legal-body li { margin-bottom: 6px; }
.legal-foot { margin-top: 24px; text-align: center; }
.err-wrap { max-width: 560px; margin: 8vh auto; padding: 0 24px; text-align: center; }
/* 700 at 64px: the one place a heavier weight reads as deliberate rather than shouty. */
.err-code { font-family: var(--font-heading); font-weight: 700; font-size: 64px; line-height: 1; color: var(--hairline); }
.err-actions { justify-content: center; flex-wrap: wrap; }

/* ==========================================================================
   17. Dashboard
   ========================================================================== */

.dash-chart { width: 100%; height: 176px; display: block; }
.dash-chart-wrap { position: relative; }
.dash-bar { cursor: default; }
.dash-bar:hover rect { opacity: .85; }
.dash-tip {
  position: absolute; z-index: 30; pointer-events: none; background: var(--ink, #1d2b2c); color: #fff;
  border-radius: var(--r-sm); padding: 8px 10px; font-size: 12px; line-height: 1.5; box-shadow: var(--shadow-soft);
  min-width: 150px;
}
.dash-tip-title { font-weight: 600; margin-bottom: 2px; }
.dash-tip .legend-dot { margin-right: 5px; }
/* dash-kpis and kpi were used on the dashboard but never defined — inert classes that
   inherited plain .grid-3 and .card. Defined here so the employee home lays out on its own
   terms: the time clock is a much taller card than a metric tile, and a fixed three-up left a
   ragged row inside the narrower column. */
/* Making the announcements panel conditional left a 30% column of nothing
   behind it — half a change, and worse than what it replaced, because an empty
   column reads as something that failed to load.

   Both rules are about the same idea: the layout should describe what is
   actually on the page rather than what was expected to be. */
/* The KPI row was grid-3 holding two cards, so it had a hole in it before the
   announcements panel was ever conditional. auto-fit means the row describes
   however many cards a person's permissions actually produce: an admin sees
   Finance and Team, somebody scoped to projects alone sees one card filling the
   width rather than a third of it. */
/* The KPI band gets the width it was always short of. Three across on a
   wide screen, two on a laptop, one on a phone — driven by the cards'
   own minimum rather than a breakpoint guess. */
.dash-kpis {
  display: grid;
  gap: 20px;
  align-items: stretch;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.dash-kpis.kpis-3 { grid-template-columns: minmax(240px, 1.4fr) repeat(2, minmax(150px, 1fr)); }
.dash-kpis.kpis-1 { grid-template-columns: minmax(240px, 1fr); max-width: 420px; }
.dash-kpis > * { min-width: 0; }
/* Replaces the 70/30 split that used to open this page. Both children —
   the stack of figures and the announcements panel — now run the full
   width in source order, which is also reading order: what the numbers
   say, what is being worked on, then the noticeboard.

   A grid rather than plain block flow, so the gap between sections is one
   declaration instead of a margin on every child. */
.dash-main { display: grid; grid-template-columns: 1fr; gap: var(--s-xl); }
/* A grid item will not shrink below its content unless told it may, so without
   this the widest descendant inflates this column — the projects table pushed
   .stack wide, .stack pushed .dash-main wide, and every sibling inherited it.
   .table-wrap then computed 100% of an already-too-wide parent, so its
   overflow-x never engaged: the table did not scroll, the page did.
   Same rule as .dash-kpis > * and .chart-main, which hit this before. */
.dash-main > * { min-width: 0; }
/* Announcements read as a quiet panel now, not a sidebar. Capped so a
   workspace with forty notices does not push everything else off the
   page; the list scrolls inside its own card. */
.dash-main > .stack + * { max-height: 460px; overflow-y: auto; }
/* Everything here is scoped to .dash, which wraps the dashboard's content and
   nothing else. The page shares .card, .grid and .metric with the rest of the
   app; those stay exactly as they are, and only their appearance INSIDE the
   dashboard changes. No other screen can shift.

   The problem being fixed: .card and .card-flat were the same box with the
   same 24px padding, so twelve sections read as twelve identical containers
   and nothing on the page looked more important than anything else. Order was
   fixed in an earlier pass; this is hierarchy. */
.dash { --dash-gap: 28px; }
/* A heading that sits ABOVE its card rather than inside it. Inside, every
   heading is another line of content competing with the figures; above, it
   becomes a label you skip when you already know where you are. */
.dash .t-heading-sm {
  font-size: 12px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--primary-deep);
}
/* Quieter than before: a hairline instead of a shadow, so a page of twelve
   does not look like twelve floating objects. Depth is reserved for the one
   card that earns it, below. */
.dash .card,
.dash .card-flat {
  box-shadow: none; border: 1px solid var(--hairline);
  background: var(--surface-card);
  padding: 20px;
}
/* Finance carries four figures, Work three, Team one. As equal-weight cards
   they read as three things of equal importance, which is not true — money is
   the headline and the rest is supporting. Finance gets the room. */
.dash .dash-kpis {
  grid-template-columns: minmax(340px, 1.6fr) repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px; align-items: stretch;
}
.dash .metric-sm {
  font-size: 26px; font-weight: 600; letter-spacing: -.02em;
  line-height: 1.1; font-variant-numeric: tabular-nums;
}
.dash .metric {
  font-size: 32px; font-weight: 600; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
/* The quiet sections get less room, which is the cheapest way to say they
   matter less. Announcements and activity are reference, not news. */
.dash .grid { gap: 16px; }
/* Full width and unboxed. A chart inside a card with a heading above it is
   two frames around one picture; the figures beside the title carry the
   context the box was pretending to add. */
.dash .dash-chart { border: 0; padding: 0; background: transparent; }
/* Lighter than a full data table: this is a glance, not a workspace. */
.dash .table { box-shadow: none; }
.dash .table th {
  font-size: 11px; letter-spacing: .05em; text-transform: uppercase;
  color: var(--charcoal); font-weight: 600;
}
.dash .table td { padding-top: 10px; padding-bottom: 10px; }
/* .dash-main held the figures and the announcements panel side by side, then
   stacked. With announcements gone it has one child, so the container and the
   height cap that pointed at the second one are both pointless. */
.dash .dash-main > .stack + * { max-height: none; overflow-y: visible; }
/* The last section carries no bottom margin — the page should end, not trail
   off into empty space. */
.dash > *:last-child { margin-bottom: 0; }
/* Replaces the attention panel and the three-card KPI row.

   The page had ONE visual weight: everything was a white card with a small
   heading, so nothing looked more important than anything else and the panel
   meant to grab attention did not. It has three now — a dark band carrying the
   single most urgent figure, a light strip of plain numbers, and white cards
   for the things that genuinely want a frame (tables, charts).

   The team card is gone. Its entire contents was one number, and a box around
   one number is what made that row look cramped while saying nothing. */
/* Dark, full width, and the largest type on the page. This is where the teal
   finally earns its keep: one saturated element on an otherwise white page
   reads as importance without any label saying so. */
/* It used to hold only leftover attention items, and there are often none —
   so the band showed one figure on the left and a void beside it, which is
   the opposite of what a full-width element is for. .hero-side always has
   content now, so the two halves can be given real proportions. */
.dash .hero {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 32px;
  background: var(--success-bg);
  color: var(--primary-deep);
  border-radius: var(--r-sm);
  padding: 28px 32px;
  box-shadow: var(--shadow-lift);
  border: 1px solid var(--primary);
  align-items: center;
}
.dash .hero.hero-alert { background:linear-gradient(45deg,var(--primary-deep),var(--primary-bright)); background-repeat:no-repeat; background-size:cover; background-position: center; }
.dash .hero-label {
  font-size: 12px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; opacity: .75; color:whitesmoke;
}
/* Big enough that it cannot be scrolled past. This is the whole point of the
   band: the old panel said the same thing in 15px and nobody looked. */
.dash .hero-figure {
  font-size: 44px; font-weight: 700; letter-spacing: -.03em;
  line-height: 1.05; margin: 6px 0 4px; color:white;
}
.dash .hero-what {
  font-size: 10px; opacity: .9; text-decoration: none;
  color: inherit; display: inline-flex; align-items: center; gap: 10px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color:whitesmoke;
}
a.dash .hero-what:hover,
.dash a.hero-what:hover { text-decoration: underline; }
.dash .hero-tag {
  font-size: 10px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; padding: 3px 9px; border-radius: 999px;
  background: rgba(255,255,255,.18);
}
.dash .hero-rest-item {
  display: flex; flex-direction: column; gap: 2px;
  text-decoration: none; color: inherit; opacity: .85;
  min-width: 90px; color:whitesmoke;
}
.dash .hero-rest-item:hover { opacity: 1; }
.dash .hero-rest-figure {
  font-size: 22px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.dash .hero-rest-text { font-size: 12px; opacity: .8; line-height: 1.3; }
/* Calm state. Same band, same position, no alarm — a dashboard that changes
   shape depending on the day is disorienting, and "nothing needs attention"
   is worth saying out loud. */
.dash .hero:not(.hero-alert) {
  background: var(--surface-card); color: var(--ink);
  border: 1px solid var(--hairline); box-shadow: none;
}
.dash .hero:not(.hero-alert) .hero-label { opacity: 1; color: var(--stone); }
.dash .hero:not(.hero-alert) .hero-figure { font-size: 40px; }
.dash .hero:not(.hero-alert) .hero-what { color: var(--stone); }
.dash .hero-main { flex: 1 1 320px; }
.dash .hero-side {
  display: flex; gap: 32px; flex-wrap: wrap;
  flex: 0 1 auto; padding-left: 32px;
  border-left: 1px solid rgba(255,255,255,.18);
}
.dash .hero:not(.hero-alert) .hero-side { border-left-color: var(--hairline); }
/* Replaces the figures strip, which put eight unrelated numbers in one
   undifferentiated row: a spreadsheet line, not a design.

   They are three questions, so they are three cards — where the money is,
   what work is open, who is here. Each has an icon tile, one lead figure
   large enough to read at a glance, supporting rows beneath it, and a footer
   that links somewhere useful. */
.dash .cards-3 {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
/* The cards are grid items too, and a card whose content will not shrink keeps
   .cards-3 wide however few columns it has. */
.dash .cards-3 > * { min-width: 0; }
.dash .pcard {
  display: flex; flex-direction: column;
  background: var(--surface-card); border: 1px solid var(--hairline);
  border-radius: var(--r-sm); padding: 22px 22px 0;
}
/* --- Head: an icon tile earns its place by being recognisable before the
   words are read. Muted tints, not brand colour — three saturated tiles
   in a row would compete with the hero above them. */
.dash .pcard-head { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; }
.dash .pcard-icon {
  display: grid; place-items: center; width: 38px; height: 38px;
  border-radius: 10px; font-size: 15px; flex: none;
}
.dash .pcard-icon-money,
.dash .pcard-icon-work,
.dash .pcard-icon-people { background: var(--primary-bright); color: white; }
.dash .pcard-title { font-size: 14px; font-weight: 600; color: var(--ink); }
.dash .pcard-sub { font-size: 12px; color: var(--stone); margin-top: 1px; }
/* --- The lead figure. One per card, large. Everything else supports it. */
.dash .pcard-lead { margin-bottom: 16px; }
.dash .pcard-value {
  font-size: 34px; font-weight: 700; letter-spacing: -.03em;
  line-height: 1.05; color: var(--primary-deep);
  font-variant-numeric: tabular-nums;
}
.dash .pcard-of { font-size: 20px; font-weight: 500; color: var(--stone); margin-left: 4px; }
.dash .pcard-caption {
  font-size: 13px; font-weight: 600; color: var(--primary-deep); margin-top: 5px;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
/* --- Supporting rows. Label left, figure right, hairline between — the shape
   a reader already knows from every statement they have ever read. */
.dash .pcard-rows { display: flex; flex-direction: column; }
.dash .pcard-row {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px; padding: 9px 0; border-top: 1px solid var(--hairline);
}
.dash .pcard-row-label { font-size: 13px; color: var(--ink); }
.dash .pcard-row-value {
  font-size: 15px; font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.dash .pcard-row-value a {
  color: inherit; text-decoration: none;
  border-bottom: 1px solid transparent;
}
.dash .pcard-row-value a:hover { border-bottom-color: currentColor; }
/* A loss reads as a loss. "₱-13,746" is a minus sign wearing a currency
   symbol; this is a number somebody can act on. */
.dash .pcard-row-value.is-loss { color: var(--danger-text); }
.dash .pcard-row-value.is-due { color: var(--warning-text); }
/* --- Foot: flush to the card edge, so the card ends on an action rather
   than trailing off into padding. */
.dash .pcard-foot {
  margin-top: auto; display: flex; justify-content: space-between;
  align-items: center; gap: 10px;
  margin-left: -22px; margin-right: -22px; padding: 14px 22px;
  border-top: 1px solid var(--hairline);
  font-size: 13px; color: var(--ink); text-decoration: none;
  background: var(--surface-tint); border-radius: 0 0 var(--r-sm) var(--r-sm);
}
.dash a.pcard-foot:hover { background: var(--surface-tint-hover); }
.dash .pcard-foot-meta { color: var(--stone); white-space: nowrap; }
.dash .pcard-foot-plain { color: var(--stone); }
/* The chart used to sit alone in a card. A chart on its own makes somebody
   read shapes to answer "how much"; the summary column answers that in words,
   and the picture then shows how it got there. */
.dash .chart-panel {
  display: grid; gap: 0;
  grid-template-columns: minmax(0, 1fr) 260px;
  background: var(--surface-card); border: 1px solid var(--hairline);
  border-radius: var(--r-sm); overflow: hidden;
}
.dash .chart-main { padding: 22px; min-width: 0; }
.dash .chart-side {
  display: flex; flex-direction: column; justify-content: center;
  gap: 22px; padding: 22px;
  border-left: 1px solid var(--hairline); background: var(--surface-tint);
}
.dash .chart-stat { display: flex; align-items: flex-start; gap: 12px; }
.dash .chart-stat-icon {
  display: grid; place-items: center; width: 34px; height: 34px;
  border-radius: 10px; font-size: 13px; flex: none;
}
.dash .chart-stat-in { background: var(--success-bg); color: var(--success-text); }
.dash .chart-stat-out { background: var(--danger-bg);  color: var(--danger-text); }
.dash .chart-stat-label { font-size: 12px; color: var(--primary-deep); font-weight:600; }
.dash .chart-stat-value {
  font-size: 24px; font-weight: 700; letter-spacing: -.02em;
  line-height: 1.15; color: var(--primary-deep);
  font-variant-numeric: tabular-nums;
}
.dash .chart-stat-value.is-loss { color: var(--danger-text); }
.dash .chart-stat-meta { font-size: 12px; color: var(--stone); margin-top: 2px; }
/* Kept is the conclusion, so it is separated from the two figures it follows. */
.dash .chart-stat-net { padding-top: 20px; border-top: 1px solid var(--hairline); }
/* The cash panel is horizontal where the chart summary is vertical, but the shape
   of the idea is the same: two figures, then the conclusion they produce. So the
   conclusion is pushed right and separated by a rule rather than sitting third in
   a row of equals, which is how .grid-3 had it. */
.dash .cash-row { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 32px; }
.dash .cash-row > .chart-stat { flex: 0 1 auto; min-width: 0; }
.dash .chart-stat-hold { background: var(--mint-100); color: var(--primary); }
.dash .cash-stat-net {
  margin-left: auto; padding-left: 32px;
  border-left: 1px solid var(--hairline);
}
/* Payee and due date were sub-lines under the name. That reads fine for one
   row and badly for six: comparing two dates meant hopping down and across.
   As columns they scan in one movement. */
.dash .pay-table td { vertical-align: middle; }
.dash .pay-table .num { font-variant-numeric: tabular-nums; }
/* The word as well as the colour. A date in red says nothing to somebody who
   cannot see red, and "late" is the whole point of the row. */
.dash .pay-late {
  display: inline-block; margin-left: 6px; font-size: 10px;
  font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  padding: 2px 6px; border-radius: 999px;
  background: var(--danger-bg); color: var(--danger-text);
}
/* Was a stacked block per project — name and percentage on one line, a bar
   below, dates below that. Three projects meant three blocks and no way to
   compare them without reading each in turn. Side by side, the column of
   percentages answers "which is furthest along" at a glance. */
.dash .proj-table td { vertical-align: middle; }
@media (max-width: 1200px) {
  .dash-kpis.kpis-3 { grid-template-columns: 1fr 1fr; }
  .dash-kpis.kpis-3 > .ess-clock { grid-column: 1 / -1; }
}

@media (max-width: 900px) {
  .dash-kpis.kpis-3 { grid-template-columns: 1fr; }
  .dash-kpis.kpis-1 { max-width: none; }
  .dash-kpis.kpis-3 > .ess-clock { grid-column: auto; }
  .dash { --dash-gap: 20px; }
}

/* Four sections were removed: recent activity and recent invoices (both had
   better pages of their own), billing and seats (settings material, not daily
   material), and announcements. Six remain, and all six are things somebody
   acts on.

   Removing content changes the page, so these rules follow it rather than
   leaving the survivors sitting in spacing tuned for twelve sections. */
/* Six sections, not twelve — they can breathe. Tight spacing on a long page
   stops it sprawling; on a short one it just looks cramped. */
.dash { --dash-gap: 36px; }
@media (max-width: 900px) {
  .dash .dash-kpis { grid-template-columns: 1fr; }
  .dash .metric-sm { font-size: 22px; }
  .dash .hero { padding: 22px 20px; gap: 20px; }
  .dash .hero-figure { font-size: 38px; }
  /* auto-fit resolves to TWO columns between about 560 and 840px, so three cards
     render as 2 + 1 with the orphan spanning the full width. One column below 900,
     which is what .dash-kpis already does. */
  .dash .cards-3 { grid-template-columns: 1fr; }
  .dash .pcard-value { font-size: 28px; }
  .dash .chart-panel { grid-template-columns: 1fr; }
  /* justify-content is center on the base rule, which is right for a vertical
     column beside the chart and wrong the moment this becomes a row — the stats
     centred while everything else on the page stayed left-aligned. */
  .dash .chart-side {
    flex-direction: row; flex-wrap: wrap; gap: 24px;
    justify-content: flex-start;
    border-left: 0; border-top: 1px solid var(--hairline);
  }
  .dash .chart-stat-net { padding-top: 0; border-top: 0; }
}

@media (max-width: 780px) {
  .dash .hero-side {
    padding-left: 0; border-left: 0; padding-top: 20px;
    border-top: 1px solid rgba(255,255,255,.18); width: 100%;
  }
  .dash .hero:not(.hero-alert) .hero-side { border-top-color: var(--hairline); }
}

@media (max-width: 700px) {
  /* nowrap keeps the foot on one line, which is right on a wide card and is one of
     the things raising its intrinsic minimum on a narrow one. */
  .dash .pcard-foot-meta { white-space: normal; }
  .dash .cash-row { gap: 20px; }
  .dash .cash-stat-net {
    width: 100%; margin-left: 0; padding-left: 0;
    padding-top: 20px; border-left: 0;
    border-top: 1px solid var(--hairline);
  }
}

.legend-dot { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 4px; vertical-align: middle; }
.legend-rev { background: var(--chart-1); }
.legend-exp { background: var(--chart-2); }
/* Replaced a stack of <progress> elements. Two things were wrong with those: the browser styles
   progress as a LOADING bar, which people read as "how far along is this" rather than "how much
   of the whole"; and they were scaled to the grand total, so with eight categories the longest
   bar filled a fifth of the width and every difference lived in that fifth.

   One accent colour throughout, deliberately. A different colour per category implies the
   colours mean something, and the reader spends effort looking for a key that does not exist. */
.spend { display: flex; flex-direction: column; gap: 14px; }
.spend-row { display: flex; flex-direction: column; gap: 6px; }
.spend-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.spend-name {
  font-size: 14px; color: var(--body); min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.spend-figs { display: flex; align-items: baseline; gap: 10px; flex: none; }
.spend-amt { font-size: 14px; font-weight: 500; font-variant-numeric: tabular-nums; }
/* Fixed width and tabular figures so the percentages form a column the eye can run down,
   instead of drifting left and right with the amount beside them. */
.spend-pct {
  font-size: 12px; color: var(--mute); font-variant-numeric: tabular-nums;
  min-width: 44px; text-align: right;
}
.spend-track { height: 8px; border-radius: 999px; background: var(--surface-soft); overflow: hidden; }
/* min-width, not a floor on the computed percentage: a minimum applied to the NUMBER would draw
   a ₱50 category the same length as a ₱5,000 one. This keeps a hairline visible without
   overstating it. */
.spend-fill { height: 100%; border-radius: 999px; background: var(--primary); min-width: 2px; }
.spend-fill-rest { background: var(--hairline); }
@media (max-width: 560px) {
  .spend-head { flex-direction: column; align-items: flex-start; gap: 2px; }
  .spend-name { white-space: normal; }
  .spend-figs { gap: 8px; }
  .spend-pct { min-width: 0; }
}

/* ==========================================================================
   18. Employee home
   ========================================================================== */

/* The payslip figure. NOT .chart-stat — every rule for that is scoped `.dash
   .chart-stat` and this page has no .dash wrapper, so reusing it rendered the
   figure unstyled. Same shape, its own class. */
.ess-pay { display: flex; align-items: flex-start; gap: 12px; }
.ess-pay-icon {
  display: grid; place-items: center; width: 34px; height: 34px;
  border-radius: 10px; flex: none; font-size: 13px;
  background: var(--success-bg); color: var(--success-text);
}
.ess-pay-label { font-size: 12px; color: var(--stone); }
.ess-pay-value {
  font-size: 24px; font-weight: 700; letter-spacing: -.02em;
  line-height: 1.15; color: var(--ink); font-variant-numeric: tabular-nums;
}
.ess-pay-meta { font-size: 12px; color: var(--stone); margin-top: 2px; }
.ess-tile { align-items: center; color: var(--ink); text-decoration: none; }
.ess-tile:hover { box-shadow: var(--shadow-card); }
.ess-tile i { font-size: 20px; }
/* The clock's buttons wrapped awkwardly at this width. */
.ess-clock .row { flex-wrap: wrap; }

/* ==========================================================================
   19. News, updates and comments
   ========================================================================== */

/* A card: image on top in the desk grid; image on the left on a phone and on the home pages
   (news-card--row). The featured story (news-card--lead) puts the image beside the story on a
   desk and above it on a phone. */
.news-card {
  display: flex; flex-direction: column; min-width: 0; overflow: hidden; color: inherit; text-decoration: none;
  background: var(--surface-card); border: 1px solid var(--hairline); border-radius: var(--r-md);
  transition: box-shadow .15s ease, transform .15s ease;
}
.news-card:hover { box-shadow: var(--shadow-card); transform: translateY(-1px); text-decoration: none; }
.news-card:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.news-media { position: relative; flex-shrink: 0; aspect-ratio: 16 / 9; background: var(--mint-50); }
.news-media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.news-media-ph {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: var(--primary); font-size: 28px; opacity: .55;
}
.news-body { display: flex; flex-direction: column; gap: var(--s-xs); min-width: 0; padding: var(--s-lg); }
.news-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 12px; color: var(--mute); }
.news-title {
  font-family: var(--font-heading); font-size: 17px; font-weight: 600; line-height: 1.3; color: var(--ink);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.news-grid { display: grid; gap: var(--s-lg); grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.news-card--lead { flex-direction: row; }
.news-card--lead .news-media { flex: 0 0 58%; aspect-ratio: auto; min-height: 280px; }
.news-card--lead .news-body { justify-content: center; gap: var(--s-sm); padding: var(--s-xl); }
.news-card--lead .news-title { font-size: 24px; -webkit-line-clamp: 3; }
.news-card--lead .news-excerpt { font-size: 15px; -webkit-line-clamp: 5; }
.news-card--row { flex-direction: row; }
.news-card--row .news-media { flex: 0 0 120px; aspect-ratio: auto; min-height: 96px; }
.news-card--row .news-body { justify-content: center; padding: var(--s-md); }
.news-card--row .news-title { font-size: 15px; }
.news-card--row .news-excerpt { font-size: 13px; -webkit-line-clamp: 2; }
.news-article { max-width: 780px; }
.news-article-media { display: block; width: 100%; max-height: 460px; object-fit: cover; border-radius: var(--r-md); }
.news-article-body { font-size: 16px; line-height: 1.7; }
.news-form-preview { display: block; width: 100%; max-width: 320px; aspect-ratio: 16 / 9; object-fit: cover; border-radius: var(--r-sm); }
@media (max-width: 900px) {
  .news-card--lead { flex-direction: column; }
  .news-card--lead .news-media { flex-basis: auto; aspect-ratio: 16 / 9; min-height: 0; }
  .news-card--lead .news-body { padding: var(--s-lg); }
  .news-card--lead .news-title { font-size: 20px; }
}

@media (max-width: 700px) {
  .news-grid { grid-template-columns: 1fr; gap: var(--s-sm); }
  .news-card:not(.news-card--lead) { flex-direction: row; }
  .news-card:not(.news-card--lead) .news-media { flex: 0 0 104px; aspect-ratio: auto; min-height: 104px; }
  .news-card:not(.news-card--lead) .news-body { justify-content: center; padding: var(--s-md); gap: 4px; }
  .news-card:not(.news-card--lead) .news-title { font-size: 15px; }
  .news-card:not(.news-card--lead) .news-excerpt { font-size: 13px; -webkit-line-clamp: 2; }
}

.announcement-body { white-space: pre-line; }
.update-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.update-body { font-size: 15px; line-height: 1.5; color: var(--body); }
.update-body p { margin-bottom: 8px; }
.update-body ul,
.update-body ol { margin: 8px 0 8px 10px; }
.update-image {
  display: block; max-width: 100%; max-height: 360px; border-radius: var(--r-sm);
  border: 1px solid var(--hairline); margin-top: 12px;
}
.update-comments { border-top: 1px solid var(--hairline); margin-top: 14px; padding-top: 14px; }
.comment { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 10px; }
.comment-body { flex: 1; }
.comment-add { display: flex; gap: 8px; margin-top: 8px; }
/* 250px matches the fallback image (1132x250), so the default shows uncropped and
   an upload crops to the same band — the page keeps its shape whatever anybody
   uploads. object-fit does the cropping; without it a portrait image is squashed. */
.project-cover { margin-bottom: var(--s-xl); }
.project-cover img {
  display: block; width: 100%; height: 225px;
  object-fit: cover; border-radius: var(--r-sm);
}
@media (max-width: 700px) {
  /* 250px of decoration is a lot of a phone screen before anybody reaches a figure. */
  .project-cover img { height: 125px; }
}

/* ==========================================================================
   20. People, documents and settings
   ========================================================================== */

/* Employee photo */
.emp-photo { width: 100px; height: 100px; border-radius: var(--r-sm); object-fit: cover; border: 1px solid var(--hairline); flex-shrink: 0; margin:0 auto; }
.emp-photo-fallback { width: 64px; height: 64px; border-radius: var(--r-sm); font-size: 20px; margin:0 auto; }
.emp-row { display: flex; align-items: center; gap: 10px; }
.emp-row-avatar { width: 32px; height: 32px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
.emp-row-initials {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--primary); color: #fff; font-size: 12px; font-weight: 600;
}
img.emp-row-avatar { background: var(--surface-soft); }
.perm-matrix th.num,
.perm-matrix td.num { text-align: center; width: 84px; }
.perm-matrix input[type="checkbox"] { width: 17px; height: 17px; cursor: pointer; }
.doc-thumb-cell { width: 52px; }
.doc-thumb {
  width: 40px; height: 40px; border-radius: var(--r-sm); object-fit: cover; display: inline-flex;
  align-items: center; justify-content: center; border: 1px solid var(--hairline); background: var(--mint-50);
}
.doc-thumb-icon { color: var(--mute); font-size: 15px; }
.doc-open { cursor: pointer; }
.doc-preview-wrap { margin-bottom: 16px; text-align: center; }
.doc-preview-img { max-width: 100%; max-height: 320px; border-radius: var(--r-sm); border: 1px solid var(--hairline); }
/* Receipt image */
.receipt-image { display: block; max-width: 100%; max-height: 480px; border-radius: var(--r-sm); border: 1px solid var(--hairline); }
/* Settings logo preview */
.settings-logo { max-height: 80px; max-width: 220px; border: 1px solid var(--hairline); border-radius: var(--r-sm); padding: 6px; background: #fff; }

/* ==========================================================================
   21. Accounting and invoices
   ========================================================================== */

.report-link {
  display: flex; align-items: center; gap: 12px; padding: 14px 16px; border: 1px solid var(--hairline);
  border-radius: var(--r-sm); text-decoration: none; color: var(--ink); background: var(--surface-card);
}
.report-link:hover { border-color: var(--teal); box-shadow: var(--shadow-soft); }
.report-link i { font-size: 18px; width: 22px; text-align: center; }
.statement { max-width: 100%; }
@media print {
  .statement { max-width: none; box-shadow: none; border: none; padding: 0; }
}

.stmt-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  padding-bottom: 16px; margin-bottom: 12px; border-bottom: 2px solid var(--primary);
}
.stmt-org-name { font-family: var(--font-heading); font-size: 16px; color: var(--primary); }
.stmt-title { text-align: right; }
.stmt-table td { padding: 7px 10px; }
.stmt-section td { font-weight: 600; color: var(--primary); border-bottom: 1px solid var(--hairline); padding-top: 14px; }
.stmt-indent { padding-left: 28px !important; }
.stmt-subtotal td { border-top: 1px solid var(--hairline); font-weight: 500; }
.stmt-total td { border-top: 2px solid var(--ink); border-bottom: 2px solid var(--ink); }
@media print {
  .stmt-head { border-bottom-color: #000; }
}

.je-note td { padding-top: 2px; padding-bottom: 12px; border-bottom: 1px solid var(--hairline); }
.je-note form { display: inline; margin-left: 8px; }
.je-note .badge { margin-left: 8px; }
.reg-void td { color: var(--mute); text-decoration: line-through; }
.reg-void td .badge { text-decoration: none; }
.reg-gap td { background: color-mix(in srgb, var(--danger) 8%, transparent); }
/* Guaranteed spacing between the stacked cards on the invoice create/edit form. */
.inv-form > .card-flat { margin-bottom: 20px; }
.inv-form > .row { margin-top: 4px; }
.inv-totals {
  width: 300px; max-width: 100%; margin-left: auto; padding: 16px 18px;
  background: var(--surface-soft); border: 1px solid var(--hairline); border-radius: var(--r-sm);
}
.inv-totals .row { padding: 3px 0; }
.inv-totals .inv-total-line { padding-top: 10px; margin-top: 6px; border-top: 1px solid var(--hairline); font-size: 15px; }
.inv-disc-row { align-items: center; }
.inv-disc-label { margin: 0; }
.inv-disc-input { max-width: 120px; }
/* Invoice details read-only line description */
.inv-line-detail { color: var(--mute); font-size: 13px; margin-top: 2px; }
.inv-cust-card dt { color: var(--mute); font-size: 12px; }
.inv-cust-card dd { margin: 0 0 10px; font-size: 14px; }
@media (max-width: 640px) {
  .inv-totals { width: 100%; }
}

.l-detail { margin-top: 6px; font-size: 13px; color: var(--mute); }
.ewt-rate-input { max-width: 78px; }

/* ==========================================================================
   22. Helpers
   ========================================================================== */

.mb-0 { margin-bottom: 0; }
.u-pointer { cursor: pointer; }
.u-self-center { align-self: center; }
.is-hidden { display: none !important; }
@media print {
  .no-print { display: none !important; }
}

/* ==========================================================================
   23. Order-dependent overrides
   ========================================================================== */

@media (max-width: 820px) {
  /* After .je-note td (Accounting and invoices). */
  .table th,
  .table td { padding: 12px 14px; }
}

@media (max-width: 640px) {
  /* After .legal-body (Sign-in, legal and error pages). */
  .card-flat,
  .card { padding: 16px; }
  /* After .inv-totals (Accounting and invoices). */
  .stack { width:100%; }
}

/* After .is-hidden (Helpers). */
/* The menu button is shown on ALL sizes: on mobile it opens the drawer, on
   desktop it collapses the sidebar to an icon rail. */
.mobile-toggle { display: inline-flex !important; align-items: center; justify-content: center; }
/* After .card-flat (Cards, badges and chips). */
.settings-divider { border-top: 1px solid var(--hairline); padding-top: 20px; margin-top: 24px; }
@media print {
  /* After .no-print (Helpers). */
  .btn,
  .pill,
  .filter-bar,
  .subnav,
  .pagination,
  form.toolbar,
  .notif,
  .usermenu { display: none !important; }
  /* After .no-print (Helpers). */
  /* Two columns of a balance sheet side by side are a squeeze on A4. */
  .grid-2,
  .grid-3,
  .grid-4,
  .split-2575 { display: block !important; }
  /* After .project-cover (News, updates and comments). */
  .grid-2 > *,
  .grid-3 > *,
  .grid-4 > * { margin-bottom: 4mm; }
}

/* After .emp-photo-fallback (People, documents and settings). */
.dash > * + * { margin-top: var(--dash-gap); }
/* After .dash-main > * (Dashboard). */
/* The base rule makes the row an inline-flex with no overflow handling, so on a phone a long row
   pushed past the screen and widened the whole page. */
.filter-tabs {
  max-width: 100%; min-width: 0; overflow-x: auto; overflow-y: hidden; flex-wrap: nowrap;
  scrollbar-width: none; -webkit-overflow-scrolling: touch; scroll-snap-type: x proximity;
}
/* After .dash > * + * (Dashboard). */
.news-excerpt {
  margin: 0; font-size: 14px; line-height: 1.5; color: var(--charcoal);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}

/* photo-time-v1 */
/* Clock-in form: the photo picker and the clock's own camera. */
.clock-photo-input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.clock-photo-target { display: block; padding: 16px; }
.clock-photo-preview { display: block; width: 100%; max-height: 260px; object-fit: cover; border-radius: 12px; margin-bottom: 10px; }
.clock-photo-hint { display: block; margin-top: 6px; }
/* Mirrored on screen, as a phone's selfie camera is; the photo itself is not. */
.clock-camera-view { display: block; width: 100%; max-height: 320px; object-fit: cover; border-radius: 12px; background: #111; transform: scaleX(-1); }
.clock-tabular { font-variant-numeric: tabular-nums; }

/* attendance-table-v1 */
/* Data tables: a column heading never breaks over two lines ("In – Out"). */
.table thead th { white-space: nowrap; }
/* Rows whose cells hold several lines read from the top, not centred against each other. */
.table-top td { vertical-align: top; }
/* A date, a time range, a figure: kept on one line. */
.nowrap { white-space: nowrap; }
/* Small chips under a cell's main line: a shift, a flag. */
.badge-sm { padding: 2px 8px; font-size: 11px; gap: 4px; }
.cell-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
/* A row's action buttons, on one line at the row's end. */
.cell-actions { display: flex; flex-wrap: nowrap; gap: 8px; justify-content: flex-end; }
/* A cell of short wrapping text (a client name) never narrower than a few words. */
.cell-min { min-width: 10rem; }

/* attendance-table-v2 */
/* Read by screen readers, not shown. */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.mt-xs { margin-top: 4px; }

/* A table whose rows become cards when its box is narrow — a laptop beside the sidebar, a
   tablet, a phone — instead of a table to scroll sideways. Its cells are marked by role:
   .c-check .c-who .c-when .c-hours .c-status .c-acts. Browsers without container queries keep
   the table (and the sideways scroll) as before. */
.table-wrap-stack { container-type: inline-size; }
.table-stack th,
.table-stack td { padding: 14px 14px; }
.table-stack .c-check,
.table-stack .c-hours,
.table-stack .c-status,
.table-stack .c-acts { width: 1%; }
.table-stack .c-who { min-width: 12rem; }
@container (max-width: 880px) {
  .table-wrap .table-stack { display: block; min-width: 0; white-space: normal; overflow: visible; }
  .table-stack thead { display: none; }
  .table-stack tbody { display: block; }
  .table-stack tr {
    display: grid; grid-template-columns: 18px minmax(0, 1fr) auto;
    grid-template-areas: "chk who status" "chk when hours" "chk acts acts";
    column-gap: 14px; row-gap: 10px; padding: 16px;
  }
  .table-stack.no-check tr {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "who status" "when hours" "acts acts";
  }
  .table-stack tbody tr + tr { border-top: 1px solid var(--hairline); }
  .table-stack tbody tr + tr td { border-top: 0; }
  .table-stack td { display: block; padding: 0; width: auto; min-width: 0; }
  .table-stack .c-check { grid-area: chk; padding-top: 2px; }
  .table-stack .c-who { grid-area: who; }
  .table-stack .c-status { grid-area: status; text-align: right; }
  .table-stack .c-when { grid-area: when; }
  .table-stack .c-hours { grid-area: hours; text-align: right; }
  .table-stack .c-acts { grid-area: acts; }
  .table-stack .c-acts .cell-actions { justify-content: flex-start; }
}

/* The pager under every paged list: "26–50 of 115", then page buttons. */
.pager { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-top: 16px; }
.pager-info { margin: 0; color: var(--mute); font-size: 13px; font-variant-numeric: tabular-nums; }
.pager-list { display: flex; align-items: center; gap: 4px; list-style: none; margin: 0; padding: 0; flex-wrap: wrap; }
.pager-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-width: 36px; height: 36px; padding: 0 10px; border-radius: var(--r-sm);
  border: 1px solid var(--hairline); background: #fff; color: var(--ink);
  font-size: 14px; font-weight: 500; line-height: 1; text-decoration: none; font-variant-numeric: tabular-nums;
}
a.pager-btn:hover { background: var(--mint-50); border-color: var(--mint-200); color: var(--primary-deep); }
.pager-btn.is-current { background: var(--primary); border-color: var(--primary); color: var(--on-primary); }
.pager-btn.is-disabled { opacity: .4; }
.pager-btn i { font-size: 12px; }
.pager-gap { display: inline-flex; align-items: center; height: 36px; padding: 0 4px; color: var(--mute); }
@media (max-width: 600px) {
  .pager-list .pager-num:not(.is-current) { display: none; }
}
@media print {
  .pager { display: none !important; }
}

/* people-picker-v1 */
/* Type-to-search dropdown (core::partials.combobox): a text box over the real <select>. */
.combo { position: relative; }
.combo::after {
  content: ''; position: absolute; right: 16px; top: 50%; width: 7px; height: 7px; pointer-events: none;
  border-right: 2px solid var(--mute); border-bottom: 2px solid var(--mute); transform: translateY(-70%) rotate(45deg);
}
.combo-input { padding-right: 40px; }
.combo-native { position: absolute; left: 0; bottom: 0; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.combo-list {
  position: absolute; z-index: 60; left: 0; right: 0; top: calc(100% + 4px);
  max-height: 300px; overflow-y: auto; margin: 0; padding: 6px; list-style: none;
  background: #fff; border: 1px solid var(--hairline); border-radius: var(--r-sm); box-shadow: var(--shadow-card);
}
.combo-option { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px; border-radius: 8px; cursor: pointer; color: var(--ink); font-size: 14px; }
.combo-option.is-active { background: var(--mint-50); }
.combo-option[aria-selected="true"] { font-weight: 600; }
.combo-hint { font-size: 12px; font-weight: 400; color: var(--mute); }
.combo-group { padding: 10px 10px 4px; font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--mute); }
.combo-empty { padding: 10px; font-size: 13px; color: var(--mute); }
