/* ============================================================
   LYKHA BMS — Design System (CSS3, no build step)
   v2 · teal/petrol · Work Sans / Inter · soft elevation
   Hand-written CSS3 per ADR-02. Link directly: <link rel="stylesheet" href="/css/lykha.css">
   ============================================================ */

: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: #008571;
  --primary-bright: #009D85;   /* the reference exactly. FILL ONLY: 3.41:1. */
  --primary-deep: #05574B;
  --on-primary: #FFFFFF;
  /* Teal accents */
  --teal: #30A694;
  --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: #F2F8F7;
  /* 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: #CCEAE6;
  --mint-200: #CFE7E4;
  --mint-300: #B3DBD5;
  /* Text ramp */
  --ink: #16272B;
  --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: #1F7A5F;  --success-bg: #C6ECDF;
  --warning: #B9781F;  --warning-text: #96590F;  --warning-bg: #F9E1B8;
  --danger:  #C6413D;  --danger-text:  #B0362F;  --danger-bg:  #F7D1CF;
  --link: #008571;

  /* 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-deep);
  /* 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(--jade);
  /* 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;
}

/* ---------- 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%; }

/* ---------- 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; }
.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; }
.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: 12px; line-height: 1.4; letter-spacing: .2px; }
.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; }
@media (max-width: 480px) { 
    .t-heading-sm { font-size: 9.5px;} .t-caption {margin-top:4px !important; font-size:8px !important; text-transform: uppercase;} 
    .t-display-lg { font-size: 25px;}
}

/* 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);}
.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 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)); }
.row { display: flex; align-items: center; }
.row-top { display: flex; align-items: flex-start; }
.between { justify-content: space-between; }
.wrap { flex-wrap: wrap; }
.t-right { text-align: right; }
.t-center { text-align: center; }
.gap-sm { gap: 8px; } .gap-md { gap: 14px; } .gap-lg { gap: 16px; } .gap-xl { gap: 24px; }
.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;}
.full { width: 100%; }
/* 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. */
@media (max-width: 900px) { .grid-3 { grid-template-columns: 1fr; } .grid-2 { grid-template-columns: 1fr; } .grid-4 { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); } }

/* ---------- 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: 36px; padding: 8px 16px; font-size: 13px; }
.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); }

/* ---------- 6. Inputs ---------- */
.field { margin-bottom: 16px; }
.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;
}
.textarea { height: auto; min-height: 110px; resize: vertical; }
.input::placeholder { color: var(--stone); }
.input:focus, .select:focus, .textarea:focus { outline: none; border-color: var(--teal); }
.field-error { margin-top: 6px; font-size: 13px; color: var(--danger-text); }
.req { color: var(--danger-text); }

/* ---------- 7. Cards ---------- */
/* A quiet inset surface and its hover. Four rules used these as raw hex, one of
   them outside .dash, so a surface change reached none of them. Kept in their own
   block rather than merged into the token list above, which is hand-maintained. */
:root {
  --surface-tint:       #FBFBFA;
  --surface-tint-hover: #F4F4F2;
}

.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-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; }

/* ---------- 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; }
.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); }

/* ---------- 9. Metric figure ---------- */
.metric { font-family: var(--font); color: var(--primary); font-size: 28px;
          line-height: 1.05; letter-spacing: -.5px; }
@media (max-width: 480px) { .metric { font-size: 20px; } }

/* ---------- 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; font-size: 14px; }
.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; }

/* ---------- 11. App shell (PMS-style sidebar + header) ---------- */
.app-layout { display: flex; min-height: 100vh; }

.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; }
.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; }

.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; }

.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-dark-mute); border-left: 3px solid transparent;
            transition: background .15s, color .15s, border-color .15s; text-transform:capitalize; }
.nav-item:hover { background: rgba(255,255,255,.06); color: #fff; text-decoration: none; }
.nav-item.active { background: rgba(63,167,165,.16); color: var(--teal-soft); border-left-color: var(--teal); }
.nav-item i { width: 18px; text-align: center; font-size: 14px; flex-shrink: 0; }

.sidebar-footer { padding: 16px; border-top: 1px solid rgba(255,255,255,.06); }
.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; }

.main-content { flex: 1; margin-left: 260px; display: flex; flex-direction: column; min-height: 100vh; min-width: 0; }
.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; }
.content-area { padding: 24px; }

@media (max-width: 900px) {
  .sidebar { transform: translateX(-100%); transition: transform .3s ease; box-shadow: var(--shadow-lift); }
  .sidebar.open { transform: translateX(0); }
  .main-content { margin-left: 0; }
  .mobile-toggle { display: block; }
}

/* Round icon chip */
.chip { width: 44px; height: 44px; border-radius: var(--r-sm); background: #fff;
        box-shadow: var(--shadow-soft); display: inline-flex; align-items: center; justify-content: center;
        color: var(--teal); }

/* 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); }

/* ============================================================
   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); }

/* Stack gap modifiers (sibling spacing) */
.stack-xs > * + * { margin-top: 8px; }
.stack-sm > * + * { margin-top: 12px; }

/* White pill button for teal/dark surfaces */
.btn-white { background: #fff; color: var(--primary); }
.btn-white:hover { background: var(--mint-100); }

/* Metric suffix + price figure */
.metric-unit { font-size: 22px; font-weight: 400; color: var(--stone); }
.price       { font-family: var(--font); font-size: 44px; line-height: 1; font-weight: 400; }

/* Centered error screen */
.error-screen { max-width: 520px; margin: 0 auto; padding: 120px 24px 0; }

/* ============================================================
   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: 24px; }
.auth-head   { margin-bottom: 24px; }
.auth-foot   { margin-top: 20px; text-align: center; }
.auth-slug   { display: flex; align-items: center; border: 1px solid var(--hairline);
               border-radius: var(--r-sm); overflow: hidden; height: 52px; background: #fff; }
.auth-slug .prefix { padding: 0 12px; color: var(--stone); font-size: 15px; background: var(--surface-soft);
                     height: 100%; display: flex; align-items: center; border-right: 1px solid var(--hairline); }
.auth-slug input { border: 0; height: 100%; padding: 0 14px; font-size: 15px; width: 100%; color: var(--ink); }
.auth-slug input:focus { outline: none; }

/* ============================================================
   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(--mint-100); color: var(--primary); }

/* ============================================================
   15. Plan selection grid
   ============================================================ */
.plan-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.plan-option { display: flex; flex-direction: column; gap: 6px; text-align: left; cursor: pointer;
               border-radius: var(--r-sm); background: var(--surface-card); padding: 24px;
               border: 1px solid var(--hairline); transition: border-color .15s, box-shadow .15s; }
.plan-option:hover { box-shadow: var(--shadow-card); }
.plan-option.is-featured { border-color: var(--primary); }
.plan-price { font-size: 34px; font-weight: 400; line-height: 1; }
.plan-unit  { font-size: 13px; color: var(--mute); }
@media (max-width: 900px) { .plan-grid { grid-template-columns: 1fr; } }

/* Plan selection polish (BILLING-UI) */
.plan-head { max-width: 720px; }
.plan-option { position: relative; }
.plan-option input[type="radio"] { position: absolute; opacity: 0; width: 0; height: 0; }
.plan-option-head { padding-right: 28px; }
.plan-check { position: absolute; top: 22px; right: 22px; width: 20px; height: 20px; border: 2px solid var(--hairline);
  border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; transition: border-color .15s, background .15s; }
.plan-option:has(input:checked) { border-color: var(--primary); box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 22%, transparent); }
.plan-option:has(input:checked) .plan-check { border-color: var(--primary); background: var(--primary); }
.plan-option:has(input:checked) .plan-check::after { content: '✓'; color: #fff; font-size: 12px; font-weight: 700; }
.plan-price-unit { font-size: 13px; color: var(--muted); font-weight: 400; margin-left: 4px; }
.plan-cap { font-size: 13px; color: var(--muted); }
.plan-features { list-style: none; margin: 14px 0 0; padding: 14px 0 0; border-top: 1px solid var(--hairline);
  display: flex; flex-direction: column; gap: 9px; }
.plan-features li { position: relative; padding-left: 24px; font-size: 13px; color: var(--ink); }
.plan-features li::before { content: '✓'; position: absolute; left: 0; top: -1px; color: var(--primary); font-weight: 700; }

/* ============================================================
   16. Lists, toolbars, forms (module CRUD)
   ============================================================ */
.toolbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.input-search { max-width: 320px; }
.empty { text-align: center; padding: 48px 24px; color: var(--mute); }

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

.pill.disabled { opacity: .5; pointer-events: none; }

/* Compact inline select (task status in a row) */
.select-inline { height: 36px; padding: 6px 10px; font-size: 13px; width: auto; }

/* Active pill (report period filter) */
.pill-active { background: var(--primary); color: #fff; }
.pill-active:hover { background: var(--primary-bright); color: #fff; }

/* 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; } }

/* 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; }

/* 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; }

/* Print (payslips, etc.) — hide chrome, show only content */
@page { margin: 1in; }
@media print {
  .sidebar, .top-header, .no-print { display: none !important; }
  .main-content { margin-left: 0 !important; }
  .content-area { padding: 0 !important; }
  .card, .card-flat { box-shadow: none !important; border: 1px solid #ddd; }
}

/* 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; }

/* Receipt image */
.receipt-image { display: block; max-width: 100%; max-height: 480px; border-radius: var(--r-sm); border: 1px solid var(--hairline); }

/* Employee photo */
.emp-photo { width: 64px; height: 64px; border-radius: var(--r-sm); object-fit: cover; border: 1px solid var(--hairline); flex-shrink: 0; }
.emp-photo-fallback { width: 64px; height: 64px; border-radius: var(--r-sm); font-size: 20px; }

/* 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; }

/* 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; }

/* Project message board (chat) */
.chat { max-height: 460px; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; padding: 4px; }
.chat-row { display: flex; align-items: flex-end; gap: 8px; max-width: 78%; }
.chat-row.mine { align-self: flex-end; flex-direction: row-reverse; }
.chat-bubble { background: var(--surface-soft); border: 1px solid var(--hairline); border-radius: var(--r-md);
               padding: 8px 12px; }
.chat-row.mine .chat-bubble { background: var(--mint-100); border-color: var(--mint-200); }
.chat-bubble.retracted { opacity: .6; font-style: italic; }
.chat-author { font-size: 12px; font-weight: 600; color: var(--charcoal); margin-bottom: 2px; }
.chat-text { font-size: 14px; color: var(--body); white-space: pre-wrap; word-break: break-word; }
.chat-time { font-size: 11px; color: var(--mute); margin-top: 4px; display: flex; align-items: center; gap: 8px; }
.chat-retract { display: inline; }
.link-btn { background: none; border: 0; color: var(--link); font-size: 11px; cursor: pointer; padding: 0; }
.chat-compose { display: flex; gap: 8px; }
.chat-compose .input { flex: 1; }

/* Project updates feed */
.ql-editor { height:auto; min-height:100px; }
.ql-container { font-size:15px !important; }
.quill-host { background: #fff; border-radius: 0 0 var(--r-sm) var(--r-sm); height:auto !important; }
.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; }
.user-avatar-sm { width: 28px; height: 28px; font-size: 10px; }

/* Project workflow board (phase columns of draggable tasks) */
.board { display: flex; gap: 14px; overflow-x: auto; padding: 20px; align-items: flex-start; background:var(--teal-grad); border-radius:var(--r-sm); }
.board-col { flex: 0 0 260px; background: var(--surface-soft); border: 1px solid var(--hairline);
             border-radius: var(--r-sm); padding: 12px; }
.board-col-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.board-col-name { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--charcoal); }
.board-col-count { font-size: 12px; color: var(--mute); background: #fff; border-radius: var(--r-sm); padding: 1px 8px; }
.board-col-tasks { min-height: 24px; }
.task-card { background: #fff; border: 1px solid var(--hairline); border-radius: var(--r-sm);
             padding: 10px 12px; margin-bottom: 8px; cursor: grab; box-shadow: var(--shadow-soft); }
.task-card.dragging { opacity: .5; }
.task-title { display: block; font-weight: 600; font-size: 15px; line-height:1.3; font-family:var(--font-heading); margin-bottom: 8px; color: var(--primary); }
.task-title:hover { color: var(--charcoal); }
.task-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.task-chip { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; }
.task-chip i { font-size: 11px; }
.task-actions { display: flex; align-items: center; gap: 6px; margin-top: 8px; }
.task-cover-lg { display: block; max-width: 100%; max-height: 240px; border-radius: var(--r-sm);
                 border: 1px solid var(--hairline); margin-bottom: 16px; }
.board-col-add { display: flex; gap: 6px; margin-top: 8px; }
.board-col-add-link { display: block; margin-top: 8px; padding: 8px 10px; border: 1px dashed var(--hairline); border-radius: var(--r-sm);
  color: var(--mute); font-size: 13px; text-align: center; text-decoration: none; transition: color .15s, border-color .15s, background .15s; }
.board-col-add-link:hover { color: var(--primary); border-color: var(--primary); background: #fff; }
.input-sm { height: 36px; padding: 6px 10px; font-size: 13px; }
.mb-0 { margin-bottom: 0; }

/* Workflow phase rows (drag to reorder) */
.phase-row { display: flex; align-items: center; gap: 12px; padding: 10px 12px; margin-bottom: 8px;
             background: var(--surface-soft); border: 1px solid var(--hairline); border-radius: var(--r-sm); }
.phase-row .phase-handle { color: var(--stone); cursor: grab; }
.phase-row .phase-num { width: 22px; height: 22px; border-radius: var(--r-sm); background: var(--mint-100);
                        color: var(--primary); font-size: 12px; font-weight: 600; display: inline-flex;
                        align-items: center; justify-content: center; flex-shrink: 0; }
.phase-row .phase-name { flex: 1; font-weight: 500; }
.phase-row.dragging { opacity: .5; }

/* Project workspace sub-navigation (tabs) */
.subnav { display: flex; gap: 2px; flex-wrap: wrap; border-bottom: 1px solid var(--hairline); }
.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; }
.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; }

/* Calendar date chip */
.cal-date { width: 48px; height: 48px; border-radius: var(--r-sm); background: var(--surface-soft);
            display: flex; flex-direction: column; align-items: center; justify-content: center; flex-shrink: 0; }
.cal-day { font-size: 17px; font-weight: 600; color: var(--primary); line-height: 1; }
.cal-mon { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--mute); }

/* Loan sample-computation preview */
.preview-summary { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.preview-figure { display: flex; flex-direction: column; gap: 4px; padding: 12px 14px;
                  background: var(--surface-soft); border-radius: var(--r-sm); }
@media (max-width: 700px) { .preview-summary { grid-template-columns: 1fr; } }

/* 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; } }

/* Detail page description list */
.dl { display: grid; grid-template-columns: 160px 1fr; gap: 10px 16px; }

/* 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; } }
.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; } }

/* ---------- Super Admin (platform console) ---------- */
.admin-body { background: var(--mint-50); min-height: 100vh; margin: 0; }
.admin-topbar { display: flex; align-items: center; justify-content: space-between; gap: 16px;
  background: var(--primary); color: var(--on-primary); padding: 0 24px; height: 56px; }
.admin-brand { color: var(--on-primary); font-family: var(--font-heading); font-size: 15px; text-decoration: none;
  display: inline-flex; align-items: center; gap: 10px; }
.admin-nav { display: flex; align-items: center; gap: 18px; }
.admin-nav a { color: #cfe6e6; text-decoration: none; font-size: 14px; }
.admin-nav a.active, .admin-nav a:hover { color: var(--on-primary); }
.admin-logout { background: transparent; border: 1px solid rgba(255,255,255,.4); color: var(--on-primary);
  border-radius: var(--r-sm); padding: 5px 12px; font-size: 13px; cursor: pointer; }
.admin-main { max-width: 1100px; margin: 0 auto; padding: 28px 24px; }
.admin-auth { max-width: 380px; margin: 8vh auto; }

/* ---------- Document viewer (thumbnails + details modal) ---------- */
.is-hidden { display: none !important; }
.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); }

/* ---------- Auth: verification code input ---------- */
.btn-block { display: block; width: 100%; }
.input-code { font-size: 24px; letter-spacing: 8px; text-align: center; font-family: var(--font-heading); }

/* ---------- Onboarding wizard ---------- */
.onboard-card { max-width: 620px; width: 100%; }
.wizard-dots { display: flex; gap: 8px; margin: 4px 0 20px; }
.wizard-dot { flex: 1; text-align: center; font-size: 12px; color: var(--mute); padding-bottom: 8px;
  border-bottom: 3px solid var(--hairline); }
.wizard-dot.active { color: var(--primary); border-bottom-color: var(--teal); font-weight: 600; }
.input-color { padding: 4px; height: 44px; width: 80px; }
.onboard-actions { display: flex; flex-direction: column; }

/* ---------- Accounting statements & report links (AR1) ---------- */
.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%; }
.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 {
  .no-print { display: none !important; }
  .statement { max-width: none; box-shadow: none; border: none; padding: 0; }
  .stmt-head { border-bottom-color: #000; }
}

/* ---------- General journal entry separation (CAS-BOOKS) ---------- */
.je-note td { padding-top: 2px; padding-bottom: 12px; border-bottom: 1px solid var(--hairline); }

/* ---------- Journal reversal control (CAS-CTRL) ---------- */
.je-note form { display: inline; margin-left: 8px; }
.je-note .badge { margin-left: 8px; }

/* ---------- Numbering register (CAS-CTRL) ---------- */
.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); }

/* ---------- Attendance filter bar (TA1c) ---------- */
.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: 4px; 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; }
.filter-tab:hover { color: var(--ink); }
.filter-tab.active { background: var(--surface-card); 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; }
.attend-photo { width: 40px; height: 40px; object-fit: cover; border-radius: var(--r-xs); border: 1px solid var(--hairline); }

/* ---------- Announcements (ANN1) ---------- */
.announcement-body { white-space: pre-line; }

/* ---------- ESS home: the single announcement strip ----------
   NOT .dash-announce. That class restyles a card whole — teal gradient, white text,
   underlined links — which suits a tall sidebar panel and shouts as a full-width
   band above someone every morning. The staff dashboard keeps it; this page does
   not. A left rule carries the emphasis instead, which is enough for one item. */
.ess-note { display: flex; align-items: flex-start; gap: 14px; }
.ess-note-icon { display: grid; place-items: center; width: 34px; height: 34px;
                 border-radius: 10px; flex: none; font-size: 13px;
                 background: var(--mint-100); color: var(--primary); }
.ess-note-body { min-width: 0; }
.ess-note-title { font-weight: 600; color: var(--ink); }
.ess-note-excerpt { font-size: 13px; color: var(--stone); margin-top: 3px; }
.ess-note-more { border: 0; background: none; padding: 0; font: inherit;
                 color: var(--link); cursor: pointer; text-decoration: underline; }

/* 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; }

/* ---------- Project cover ----------
   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); }

/* 250px of decoration is a lot of a phone screen before anybody reaches a figure. */
@media (max-width: 700px) {
    .project-cover img { height: 125px; }
}

/* ---------- ESS home tiles (ESS1) ---------- */
.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; }

/* ---------- Workflow task status colors (DEALS-c) ---------- */
.task-status-done { border-left: 3px solid var(--success); background: color-mix(in srgb, var(--success) 8%, var(--surface-card)); }
.task-status-in_progress { border-left: 3px solid #E0A458; }
.task-status-todo { border-left: 3px solid var(--hairline); }
.board-col-add-full { display: flex; flex-direction: column; gap: 6px; }
.board-col-add-full textarea { resize: vertical; }

/* ---------- Brand logos (BRAND1) ---------- */
.auth-brand { text-align: center; }
.auth-logo { height: 46px; width: auto; display: inline-block; }
.brand-icon-img { background: none; padding: 0; }
.brand-icon-img img { width: 100%; height: 100%; object-fit: contain; border-radius: var(--r-sm); }

/* ---------- Active statutory table (STAT-MGMT) ---------- */
.stat-active { border-color: var(--success); box-shadow: 0 0 0 1px var(--success) inset; }

/* ---------- Grouped datatable header row (PAY-RUN) ---------- */
.tbl-group td { background: var(--surface-soft); font-weight: 600; color: var(--ink); font-size: 13px; text-transform: uppercase; letter-spacing: .03em; }

/* ---------- Header: universal search (HDR) ---------- */
.hsearch { position: relative; }
.hsearch-icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--muted); 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(--muted); 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(--muted); }
.hsearch-empty { padding: 14px 10px; color: var(--muted); font-size: 13px; text-align: center; }

/* ---------- Header: plan badge spacing (HDR) ---------- */
.plan-badge { display: inline-flex; align-items: center; gap: 6px; padding: 10px 12px; white-space: nowrap; }
.plan-badge-dot { opacity: .5; }
@media (max-width: 480px) { .plan-badge { display: none; } }

/* ---------- Header: user menu (HDR) ---------- */
.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(--muted); }
.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(--muted); }
@media (max-width: 640px) { .usermenu-name { display: none; } .hsearch-input { width: 180px; } }

/* ---------- Invoice single-page form (INV-UX-d) ---------- */
/* 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; }
@media (max-width: 640px) { .inv-totals { width: 100%; } }
.l-detail { margin-top: 6px; font-size: 13px; color: var(--muted); }
.select-sm { height: 32px; padding: 0 8px; font-size: 13px; }
/* Invoice details read-only line description */
.inv-line-detail { color: var(--muted); font-size: 13px; margin-top: 2px; }
.inv-cust-card dt { color: var(--muted); font-size: 12px; }
.inv-cust-card dd { margin: 0 0 10px; font-size: 14px; }

/* ---------- Multi-select (PROJ-MULTI) ---------- */
.select-multi { height: auto; min-height: 120px; padding: 6px; }
.select-multi option { padding: 4px 6px; border-radius: var(--r-sm); }

/* ---------- Schedule employee checkboxes (SCHED2 fix) ---------- */
.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; }

/* ---------- Contact picker (CATP) ---------- */
.contact-picker { position: relative; }
.contact-search { position: relative; }
.contact-search-icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--muted); font-size: 13px; }
.contact-search-input { padding-left: 34px; }
.contact-search-results { position: absolute; top: calc(100% + 4px); left: 0; right: 0; background: #fff; border: 1px solid var(--hairline);
  border-radius: var(--r-sm); box-shadow: var(--shadow-soft); z-index: 40; max-height: 240px; overflow-y: auto; }
.contact-result { display: block; width: 100%; text-align: left; padding: 9px 12px; border: 0; background: none; font-size: 14px; color: var(--ink); cursor: pointer; }
.contact-result:hover { background: var(--surface-soft); }
.contact-result-empty { padding: 10px 12px; color: var(--muted); font-size: 13px; }
.contact-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.contact-chip { display: inline-flex; align-items: center; gap: 6px; padding: 5px 8px 5px 10px; border: 1px solid var(--hairline);
  border-radius: 999px; background: var(--surface-soft); font-size: 13px; }
.contact-chip.is-primary { border-color: var(--primary); }
.chip-primary { background: var(--primary); color: #fff; font-size: 10px; text-transform: uppercase; letter-spacing: .04em; padding: 2px 6px; border-radius: 999px; }
.chip-name { font-weight: 500; }
.chip-btn { border: 0; background: none; cursor: pointer; color: var(--muted); font-size: 13px; line-height: 1; padding: 0 2px; }
.chip-make:hover { color: var(--primary); }
.chip-remove:hover { color: var(--danger-text); }

/* ---------- Dashboard v2 (DASH2) ---------- */
.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; }

/* Announcements banner (POLISH1) — pinned announcement, shown prominently. */
.announce-banner { display: flex; gap: 14px; align-items: flex-start; text-decoration: none; color: var(--ink);
  background: var(--mint-100); border: 1px solid color-mix(in srgb, var(--primary) 30%, var(--hairline));
  border-radius: var(--r-md, 12px); padding: 16px 18px; margin-bottom: 20px; transition: box-shadow .15s, transform .15s; }
.announce-banner:hover { box-shadow: var(--shadow-soft); transform: translateY(-1px); }
.announce-banner-icon { width: 38px; height: 38px; flex-shrink: 0; border-radius: 50%; background: var(--primary); color: #fff;
  display: inline-flex; align-items: center; justify-content: center; font-size: 15px; }
.announce-banner-meta { color: color-mix(in srgb, var(--primary) 75%, var(--ink)); }
.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); }
.dash-activity { display: flex; gap: 10px; align-items: flex-start; padding: 6px 0; border-top: 1px solid var(--hairline); }
.dash-activity:first-of-type { border-top: 0; }
.dash-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--primary); margin-top: 6px; flex-shrink: 0; }
.task-pip { width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
.pip-done { background: var(--success); }
.pip-in_progress { background: #E0A458; }
.pip-todo { background: #fff; border: 1px solid var(--muted); }

/* ---------- Bulk seat activation (EMP-CSV) ---------- */
.bulk-seats summary { cursor: pointer; list-style: none; }
.bulk-seats summary::-webkit-details-marker { display: none; }

/* ---------- Super Admin: danger zone + danger button (SA-UI) ---------- */
.btn-danger { background: var(--danger); color: #fff; border: 1px solid var(--danger); }
.btn-danger:hover { filter: brightness(0.94); color: #fff; }
.danger-zone { border-color: color-mix(in srgb, var(--danger) 45%, var(--hairline)); }
.danger-zone code { background: var(--surface-soft); padding: 1px 6px; border-radius: 4px; font-size: 12px; }

/* ---------- Super Admin plan cards (POLISH6) ---------- */
.plan-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 16px; }
.plan-adm.is-inactive { opacity: .65; }
.plan-adm-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.plan-code { font-size: 12px; color: var(--muted); background: var(--surface-soft); padding: 1px 7px; border-radius: 4px; display: inline-block; margin-top: 4px; }
.plan-adm-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px 16px; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--hairline); }
.plan-adm-edit { margin-top: 14px; }
.plan-adm-edit summary { list-style: none; }
.plan-adm-edit summary::-webkit-details-marker { display: none; }
.plan-adm-edit[open] summary { margin-bottom: 4px; }

/* ---------- Permission matrix (PERM) ---------- */
.perm-matrix th.num, .perm-matrix td.num { text-align: center; width: 84px; }
.perm-matrix input[type="checkbox"] { width: 17px; height: 17px; cursor: pointer; }

/* ---------- Reports hub cards (REPORTS) ---------- */
.report-card { display: block; text-decoration: none; color: var(--ink); transition: box-shadow .15s, transform .15s; }
.report-card:hover { box-shadow: var(--shadow-soft); transform: translateY(-2px); }
.report-card-icon { width: 40px; height: 40px; border-radius: var(--r-sm); background: var(--mint-100); color: var(--primary);
  display: inline-flex; align-items: center; justify-content: center; font-size: 18px; margin-bottom: 12px; }

/* ---------- Employee avatar in tables (EMP-AVATAR) ---------- */
.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; }

/* ---------- Shift templates + scalable assignment (SCHED3) ---------- */
.shift-card { display: flex; flex-direction: column; gap: 12px; text-decoration: none; color: var(--ink);
  transition: box-shadow .15s, transform .15s; }
.shift-card:hover { box-shadow: var(--shadow-soft); transform: translateY(-2px); }
.shift-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.shift-accent { width: 10px; height: 10px; border-radius: 3px; background: var(--primary); flex-shrink: 0; margin-top: 6px; }
.shift-headcount { display: inline-flex; align-items: baseline; gap: 5px; }
.shift-headcount b { font-size: 22px; line-height: 1; }
.shift-days { display: flex; flex-wrap: wrap; gap: 5px; }
.shift-day { font-size: 11px; padding: 2px 7px; border-radius: 999px; border: 1px solid var(--hairline);
  color: var(--muted); background: var(--surface-soft); }
.shift-day.on { color: #fff; background: var(--primary); border-color: var(--primary); }
.shift-inactive { opacity: .6; }

.weekday-toggle { display: flex; flex-wrap: wrap; gap: 8px; }
.weekday-toggle input { position: absolute; opacity: 0; pointer-events: none; }
.weekday-toggle label { cursor: pointer; padding: 7px 12px; border: 1px solid var(--hairline); border-radius: 999px;
  font-size: 13px; background: #fff; user-select: none; }
.weekday-toggle input:checked + span,
.weekday-toggle label:has(input:checked) { }
.weekday-pill { cursor: pointer; padding: 7px 13px; border: 1px solid var(--hairline); border-radius: 999px;
  font-size: 13px; background: #fff; user-select: none; }
.weekday-pill.on { color: #fff; background: var(--primary); border-color: var(--primary); }

.picker-filters { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 10px; align-items: end; }
@media (max-width: 900px) { .picker-filters { grid-template-columns: 1fr 1fr; } }
.picker-list { margin-top: 12px; border: 1px solid var(--hairline); border-radius: var(--r-sm);
  max-height: 340px; overflow-y: auto; }
.picker-row { display: flex; align-items: center; gap: 12px; padding: 9px 14px; border-top: 1px solid var(--hairline); font-size: 14px; }
.picker-row:first-child { border-top: 0; }
.picker-row:hover { background: var(--surface-soft); }
.picker-row input[type="checkbox"] { width: 17px; height: 17px; cursor: pointer; flex-shrink: 0; }
.picker-row-meta { color: var(--muted); font-size: 12px; }
.picker-row-current { margin-left: auto; font-size: 11px; color: var(--muted); white-space: nowrap; }
.picker-empty { padding: 22px 14px; text-align: center; color: var(--muted); font-size: 13px; }
.picker-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 12px; flex-wrap: wrap; }
.picker-pager { display: flex; align-items: center; gap: 8px; }
.picker-selectall { font-size: 13px; }

/* ── Filter bar refinements (Aug 2026) ─────────────────────────────────────────────
   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; }
.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; }

/* ── Password show/hide (Aug 2026) ─────────────────────────────────────────────────
   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); }

/* ── Legal pages (Aug 2026) ────────────────────────────────────────────────────────
   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; }

/* ── Dashboard 70/30 (Aug 2026) ────────────────────────────────────────────────────
   Metrics carry the width; announcements hold a fixed column so they are always in
   the same place. Breakpoint kept alongside .split-2575 above for consistency. */
.split-7030 { display: grid; grid-template-columns: 7fr 3fr; gap: 20px; align-items: start; }
@media (max-width: 900px) { .split-7030 { grid-template-columns: 1fr; } }
.dash-announce { align-self: stretch; }
.announce-item { display: block; width: 100%; text-align: left; cursor: pointer;
  border: 0; border-bottom: 1px solid var(--hairline); background: transparent;
  padding: 12px 0; color: var(--body); font: inherit; }
.announce-item:last-child { border-bottom: 0; }
.announce-item:hover { color: var(--ink); }
.announce-item:hover .fw-500 { color: var(--link); }

/* ── Title-as-trigger (Aug 2026) ───────────────────────────────────────────────────
   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; }

/* ── Admin plan listing: grid / rows toggle (Aug 2026) ─────────────────────────────
   The index is a listing only; create and edit are their own pages. The toggle is a
   pair of links carrying the current query string, so the choice survives filtering
   without any client-side state. */
.view-toggle { display: inline-flex; margin-left: auto; border: 1px solid var(--hairline);
  border-radius: 8px; overflow: hidden; }
.view-toggle-btn { padding: 6px 14px; font-size: 13px; color: var(--muted);
  text-decoration: none; background: transparent; }
.view-toggle-btn + .view-toggle-btn { border-left: 1px solid var(--hairline); }
.view-toggle-btn:hover { color: var(--ink); }
.view-toggle-btn.is-on { background: var(--primary); color: #fff; }

/* ── Filter control sizing: -md (Aug 2026) ─────────────────────────────────────────
   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; }
.select-md { height: 44px; padding: 0 12px; font-size: 14px; }
.filter-dates .select-md { max-width: 200px; }
.filter-dates .input-search { max-width: 260px; }

/* ── Filter control sizing: buttons join the row (Aug 2026) ────────────────────────
   .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; }

/* ── QR Ph payment block (Aug 2026) ────────────────────────────────────────────────
   Manual payment for now: a STATIC QR Ph code, which carries no amount, so the code
   sits beside the written details rather than replacing them — the payer still needs
   the figure and the invoice number. Appended; nothing above is touched. */
.pay-split { display: grid; grid-template-columns: auto 1fr; gap: 24px; align-items: start; }
.pay-qr { text-align: center; }
.qr-img { width: 180px; height: 180px; object-fit: contain; border: 1px solid var(--hairline);
  border-radius: var(--r-sm); background: #fff; padding: 8px; }

/* ── Setup checklist (Nov 2026) ────────────────────────────────────────────────────
   A guide, not a gate: it sits above the dashboard, dismisses to nothing and never
   blocks a route. Done steps stay listed rather than disappearing, so the owner can
   see what the workspace already has — much of it filled in at registration. */
.setup-card { border-left: 3px solid var(--primary); }
.setup-focus { display: flex; flex-wrap: wrap; gap: 8px; }
.setup-steps { list-style: none; margin: 0; padding: 0; }
.setup-step { display: flex; align-items: center; gap: 12px; padding: 10px 0;
  border-bottom: 1px solid var(--hairline); }
.setup-step:last-child { border-bottom: 0; }
.setup-step-num { flex: 0 0 28px; height: 28px; border-radius: 50%; display: inline-flex;
  align-items: center; justify-content: center; font-size: 12px; font-weight: 600;
  background: var(--mint-200); color: var(--ink); }
.setup-step.is-done .setup-step-num { background: var(--primary); color: #fff; }
.setup-step.is-done .setup-step-body { opacity: .6; }
.setup-step-body { display: flex; flex-direction: column; flex: 1; }

/* ── Organisation mix, super admin (Nov 2026) ─────────────────────────────────────
   Chips double as filters: seeing that 14 workspaces are cooperatives is only half
   the answer, the other half is looking at them. */
.type-mix { display: flex; flex-wrap: wrap; gap: 8px; }
.type-chip { display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px;
  border: 1px solid var(--hairline); border-radius: 999px; text-decoration: none;
  color: var(--ink); font-size: 13px; }
.type-chip:hover { border-color: var(--primary); }
.type-chip.is-on { background: var(--primary); color: #fff; border-color: var(--primary); }
.type-chip.is-on .c-mute { color: rgba(255,255,255,.75); }

/* ── Platform console (Nov 2026) ───────────────────────────────────────────────────
   The admin console reuses the workspace shell wholesale; these are the few pieces it
   needs that the workspace has no equivalent for. */
.admin-attention { border-left: 3px solid var(--warning, #b45309); }
.attention-item { display: inline-flex; align-items: center; gap: 10px; padding: 10px 14px;
  border: 1px solid var(--hairline); border-radius: var(--r-sm); text-decoration: none;
  color: var(--ink); font-size: 14px; }
.attention-item:hover { border-color: var(--primary); }
.attention-num { font-size: 20px; font-weight: 600; color: var(--primary); }
.usermenu-meta { padding: 10px 14px; border-bottom: 1px solid var(--hairline); }
/* ── Employee home: grids that fit the 70% column (Dec 2026) ─────────────────── */
/* 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. */
.dash-kpis { display: grid; gap: 20px; align-items: stretch; }
.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; }
.kpi { display: flex; flex-direction: column; justify-content: flex-start; }

/* 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; }
.leave-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 20px 16px; }

/* The clock's buttons wrapped awkwardly at this width. */
.ess-clock .row { flex-wrap: wrap; }

@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-3 > .ess-clock { grid-column: auto; }
    .dash-kpis.kpis-1 { max-width: none; }
}
/* ── Error pages (Dec 2026) ───────────────────────────────────────────────────── */
.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; }

/* A plan you cannot pick yet: visibly there, visibly not an option (Dec 2026). */
.plan-option.is-unavailable { opacity: .55; cursor: not-allowed; }
.plan-option.is-unavailable .plan-check { visibility: hidden; }

/* Project progress: one track that fills, phases named underneath (Dec 2026). */
.proj-progress { padding: 16px 20px; margin-bottom: 16px; background:var(--success-bg); border:1px solid var(--faint); }
.proj-track { height: 10px; border-radius: 999px; background: var(--mint-2, white); overflow: hidden; }
.proj-fill { height: 100%; background: var(--teal, #14707f); border-radius: 999px; transition: width .3s ease; }
.proj-phases { display: flex; flex-wrap: wrap; gap: 6px; }
.proj-phases form { display: inline; }
.proj-phase { font-size: 12px; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--line, #dde3e5);
              background: #fff; color: var(--mute, #6b7280); cursor: default; }
button.proj-phase { cursor: pointer; }
button.proj-phase:hover { border-color: var(--teal, #14707f); color: var(--teal, #14707f); }
.proj-phase.is-done { background: var(--mint, #eaf4f5); border-color: var(--teal, #14707f); color: var(--teal-d, #0d5561); font-weight: 600; }

/* The foldable post-a-note form (Dec 2026). */
.note-form { padding: 16px 20px; }
.note-form summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 8px; }
.note-form summary::-webkit-details-marker { display: none; }
.note-form summary::before { content: "+"; font-weight: 700; color: var(--teal, #14707f); }
.note-form[open] summary::before { content: "\2013"; }


/* ============================================================================
   Merged from lykha-responsive.css (Sep 2026)
   ----------------------------------------------------------------------------
   That file stopped being about responsiveness: 28 selectors existed only in
   it, and it had become where every new class landed. Two stylesheets, one of
   them misnamed, was harder to reason about than one long file.

   EVERYTHING BELOW LOADED SECOND, AND STILL MUST. These rules deliberately
   override the ones above — .task-status-* drops a border-left, .mobile-toggle
   forces display with !important, .dash-announce restyles a card whole, and 28
   more selectors are overridden from inside @media blocks. Moving any of this
   above the base rules, or "tidying" a duplicate away, changes what renders.

   Appended byte for byte, in its original order. If a rule here looks like it
   contradicts one above, that is not a mistake to clean up — it is the point.
   ============================================================================ */
/* ============================================================================
   Lykha — responsive polish + collapsible navigation.

   Loaded AFTER lykha.css. Kept as a SEPARATE file on purpose so hand-edits made
   to lykha.css (e.g. via cPanel) are never overwritten by app updates.
   ============================================================================ */

/* ---------- Data tables: scroll horizontally instead of squishing ---------- */
@media (max-width: 820px) {
  .table {
    display: block;
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    white-space: nowrap;
    border-radius: 0;
  }
  .table th, .table td { padding: 12px 14px; }
}

/* ---------- General small-screen breathing room ---------- */
@media (max-width: 640px) {
  .toolbar { flex-direction: column; align-items: flex-start; gap: 12px; }
  .content-area { padding: 16px; }
  .card-flat, .card { padding: 16px; }
  .grid-4 { grid-template-columns: 1fr 1fr; }
  .picker-filters { grid-template-columns: 1fr; }
  .split-2575 { grid-template-columns: 1fr; }
  .stack { width:100%; }
  .grid-3 { grid-template-columns: repeat(auto-fit, minmax(150px,2fr)); }
  .notif-panel { width:250px; }
}

/* ============================================================================
   Collapsible sidebar
   ============================================================================ */

/* 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; }

@media (min-width: 901px) {
  .sidebar { transition: width .2s ease; }
  .main-content { transition: margin-left .2s ease; }

  .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; }
}

/* ============================================================================
   Mobile drawer scrim (tap outside to close)
   ============================================================================ */
.nav-scrim {
  position: fixed;
  inset: 0;
  background: rgba(15, 30, 32, .42);
  z-index: 90;
  opacity: 0;
  visibility: hidden;
  transition: opacity .25s ease;
}
@media (max-width: 900px) {
  .app-layout.nav-open .nav-scrim { opacity: 1; visibility: visible; }
  body.nav-locked { overflow: hidden; }
}
@media (min-width: 901px) {
  .nav-scrim { display: none; }
}

/* ============================================================================
   Small utilities (EWT invoice + tax settings) — kept here so the protected
   lykha.css is never touched.
   ============================================================================ */
.u-pointer     { cursor: pointer; }
.u-self-center { align-self: center; }
.ewt-rate-input { max-width: 78px; }
.settings-divider { border-top: 1px solid var(--hairline); padding-top: 20px; margin-top: 24px; }
.field-narrow  { max-width: 280px; }

/* Admin plan listing toggle (Aug 2026) — the toggle drops below the filters on narrow
   screens rather than squeezing the search field. */
@media (max-width: 700px) {
  .view-toggle { margin-left: 0; width: 100%; }
  .view-toggle-btn { flex: 1; text-align: center; }
}

/* 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. */
@media (max-width: 700px) {
  .filter-dates .input-search { max-width: 100%; }
  .filter-dates .select-md { max-width: 100%; }
}

/* QR Ph payment block (Aug 2026) — the code stacks above the details on narrow screens. */
@media (max-width: 700px) {
  .pay-split { grid-template-columns: 1fr; }
  .pay-qr { justify-self: center; }
}
/* ============================================================================
   Announcements on the dashboard (Aug 2026).

   Both rules live here rather than in lykha.css, which this file's own header
   asks to leave alone — and this file loads second, so anything put in the
   other one would lose to it anyway and look like a change that silently
   failed.
   ============================================================================ */

/* Prominent enough to be read. --teal-grad is a gradient, so it belongs in
   background rather than background-color, and the text has to be set light
   with it: dark type on a dark gradient is unreadable, and easy to miss when
   you are checking on a bright screen. */
.dash-announce {
  background: var(--teal-grad);
  color: var(--on-dark, #fff);
  border: 0;
}
.dash-announce .t-heading-sm,
.dash-announce .announce-item,
.dash-announce .t-body-sm,
.dash-announce .t-caption,
.dash-announce p { color: var(--on-dark, #fff); }
.dash-announce .c-mute { color: rgba(255, 255, 255, .72); }
.dash-announce a,
.dash-announce .c-teal { color: #fff; text-decoration: underline; }
.dash-announce .announce-item {
  border-color: rgba(255, 255, 255, .22);
}
.dash-announce .announce-item:hover { background: transparent; }

/* On a phone the columns stack, and the announcements sat below every metric
   card — the one thing somebody is told to read, last. order flips the pair
   without touching the markup, so the desktop layout is untouched.

   Scoped to the dashboard's own split: other pages use this class and reversing
   all of them would be a much larger change than the one asked for. */
@media (max-width: 900px) {
}
/* The payment QR, enlarged (Aug 2026). The thumbnail is unscannable, and somebody paying is
   usually holding another phone up to it. */
.qr-open { border: 0; background: none; padding: 0; cursor: zoom-in; display: block; }
.qr-open:hover .qr-img { outline: 2px solid var(--teal, #14707f); outline-offset: 3px; }
.qr-modal { max-width: 420px; }
.qr-modal-body { text-align: center; }
.qr-modal-body img { width: 100%; max-width: 340px; height: auto; }

/* ============================================================================
   PRINTING (Aug 2026)
   ----------------------------------------------------------------------------
   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.

   In lykha-responsive.css, which loads second and whose header asks for
   lykha.css to be left alone.
   ============================================================================ */

@media print {
  @page { margin: 14mm; }

  body { background: #fff !important; color: #000; font-size: 9pt; line-height: 1.35; }

  /* 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;
  }

  /* 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 { page-break-inside: auto; }

  table thead { display: table-header-group; }
  table tfoot { display: table-footer-group; }
  table tr    { page-break-inside: avoid; }

  /* 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; }

  /* 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; }
  .t-display-md { font-size: 9pt !important; }
  .t-heading-sm { font-size: 8pt !important; }
  .t-body-lg, .t-body-sm, .t-caption { font-size: 7.5pt !important; }
  .metric { font-size: 9pt !important; }

  /* 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;
  }

  .btn, .pill, .filter-bar, .subnav, .pagination, form.toolbar,
  .notif, .usermenu { display: none !important; }

  a { color: #000 !important; text-decoration: none !important; }

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

  /* Two columns of a balance sheet side by side are a squeeze on A4. */
  .grid-2, .grid-3, .grid-4, .split-7030, .split-2575 { display: block !important; }
  .grid-2 > *, .grid-3 > *, .grid-4 > * { margin-bottom: 4mm; }

  /* A trailing empty element is enough to produce one more sheet. */
  .content-area > *:last-child { margin-bottom: 0 !important; }
  .app-layout, .main-content, .content-area { overflow: visible !important; height: auto !important; }
}

/* The progress cell on the projects index (Aug 2026). Deliberately small: a table row is
   scanned, not read, and a full bar with phase names would outweigh everything beside it. */
.mini-track { width: 64px; height: 6px; border-radius: 999px; background: var(--mint-2, #e6eef0);
              overflow: hidden; align-self: center; }
.mini-fill { height: 100%; background: var(--teal, #14707f); border-radius: 999px; }
/* ============================================================================
   Task cards: no status stripe (Aug 2026)
   ----------------------------------------------------------------------------
   A coloured bar down the left of every card is on every dashboard template
   ever generated, and here it carries nothing: the card already shows a status
   badge, and on the board the column it sits in says the same thing a third
   time.

   Overridden here rather than deleted from lykha.css, whose own header asks to
   be left alone. This file loads second, so it wins.

   The done tint stays. That one is not decoration — a finished card reading
   differently at a glance is the whole point of a board.
   ============================================================================ */

.task-status-done,
.task-status-in_progress,
.task-status-todo { border-left: 0; }
/* ============================================================================
   Board columns, tinted by phase colour (Aug 2026)
   ----------------------------------------------------------------------------
   The colour is set on the workflow and copied to each project's phases, so a
   board looks the same every time that workflow is used.

   38% behind the column, full strength as a line on top: enough to tell lanes
   apart at a glance without turning the cards into something you have to read
   through. color-mix means one stored hex produces both.
   ============================================================================ */

.board-col-tinted {
  background: color-mix(in srgb, var(--phase-color) 38%, var(--surface-soft));
  border-top: 3px solid var(--phase-color);
}

/* The picker in the workflow editor. */
.phase-color { width: 28px; height: 28px; padding: 0; border: 1px solid var(--mute);
               border-radius: var(--r-xs); background: none; cursor: pointer; flex: none; }
.phase-color::-webkit-color-swatch-wrapper { padding: 2px; }
.phase-color::-webkit-color-swatch { border: 0; border-radius: 3px; }
/* The per-column picker on a board — smaller than the one in the workflow editor, because it
   sits in a column header rather than a settings row. */
.phase-color-sm { width: 20px; height: 20px; }
/* ============================================================================
   Latest note preview (Aug 2026)
   ----------------------------------------------------------------------------
   Three lines of a real note — bold, lists and links intact — then it fades.
   The whole note is in the DOM and only three lines are shown, which is why
   nothing has to be truncated and no tag can be left open.
   ============================================================================ */

.note-preview {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  max-height: 4.5em;
}

/* A note's own margins would push the clamp around, and a heading pasted into
   one would tower over the card. Neutralised for the preview only. */
.note-preview > *:first-child { margin-top: 0; }
.note-preview > *:last-child { margin-bottom: 0; }
.note-preview h1, .note-preview h2, .note-preview h3 { font-size: 1em; font-weight: 600; margin: 0; }
.note-preview ul, .note-preview ol { margin: 0; padding-left: 1.2em; }

/* An image in a three-line preview is either invisible or the entire card. The
   note itself is one click away. */
.note-preview img { display: none; }
/* Project finance figures (Aug 2026): a rule between what came in and what went out, so the
   last figure reads as a conclusion rather than a sixth measurement. */
.fin-figures { align-items: flex-start; }
.fin-rule { width: 1px; align-self: stretch; min-height: 40px; background: var(--hairline); }

/* On a phone the row wraps and a vertical rule between wrapped items is meaningless. */
@media (max-width: 700px) {
  .fin-rule { width: 100%; height: 1px; min-height: 0; }
}
/* ============================================================================
   Pagination (Aug 2026)
   ----------------------------------------------------------------------------
   Paired with resources/views/vendor/pagination/. Laravel's default view is
   Tailwind markup, and without Tailwind its SVG arrows had no width and took
   their intrinsic size — which is what filled the page.
   ============================================================================ */

.pagination { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }

.page-link {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 32px; height: 32px; padding: 0 10px;
  border: 1px solid var(--hairline); border-radius: var(--r-xs);
  background: var(--surface-card); color: var(--mute);
  font-size: 13px; line-height: 1; text-decoration: none;
}
.page-link:hover { color: var(--ink); border-color: var(--primary); }
.page-link.is-current { background: var(--primary); border-color: var(--primary); color: #fff; font-weight: 600; }
.page-link.is-disabled { opacity: .45; pointer-events: none; }
.page-link.is-gap { border: 0; background: none; min-width: 16px; padding: 0; }

/* Pushed to the far end: it is a description of the list, not one of its controls. */
.page-count { margin-left: auto; font-size: 12px; color: var(--mute); }

@media (max-width: 700px) {
  /* On a phone the count belongs under the controls rather than squeezed beside them. */
  .page-count { margin-left: 0; width: 100%; padding-top: 6px; }
}
/* ============================================================================
   Removal affordance (Aug 2026)
   ----------------------------------------------------------------------------
   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(--mute);
  border-color: var(--hairline);
}
.pill-remove:hover {
  color: var(--danger, #b42318);
  border-color: var(--danger, #b42318);
  background: color-mix(in srgb, var(--danger, #b42318) 6%, transparent);
}

/* Permanent, and there is no Trash behind it. Red before the cursor arrives. */
.btn-danger {
  background: var(--danger, #b42318);
  border-color: var(--danger, #b42318);
  color: #fff;
}
.btn-danger:hover { filter: brightness(1.08); }
/* Dashboard: finance grouped, projects with progress (Aug 2026) */
.dash-finance .fin-row { display: flex; gap: 20px; flex-wrap: wrap; justify-content:space-between; }
.dash-finance .fin-row > div { min-width: 110px; }
.metric-sm { font-size: 20px; font-weight: 600; line-height: 1.2; }

.dash-recent-row { padding: 10px 0; border-bottom: 1px solid var(--hairline); }
.dash-recent-row:last-child { border-bottom: 0; padding-bottom: 0; }
.dash-recent-row:first-child { padding-top: 0; }
/* Dashboard project progress: full width (Aug 2026) */
.dash-track {
  width: 100%;
  height: 8px;
  border-radius: 999px;
  background: var(--surface-soft);
  overflow: hidden;
}
.dash-track-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--primary);
  transition: width .2s ease;
}
/* ============================================================================
   Dashboard reflow (Aug 2026)
   ----------------------------------------------------------------------------
   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. */
.dash-kpis {
  grid-template-columns: repeat(auto-fit, minmax(225px, 1fr));
}

/* Finance is the wider of the two — four figures against one number. */
.dash-kpis > .dash-finance { grid-column: span 2; }

@media (max-width: 700px) {
  .dash-kpis > .dash-finance { grid-column: auto; }
}

/* Landing: a section that leads with a label rather than a heading.
   The flow strip below it carries the point, so the type above it should step back and let it —
   a second h2 there was competing with the one in the next section for the same claim. */
.landing .section-head-sm { margin-bottom: 2rem; }
.landing .section-head-sm .eyebrow {
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--brand, #6b46c1);
    margin: 0 0 .5rem;
}
.landing .section-head-sm > p:not(.eyebrow) {
    font-size: 1.05rem;
    max-width: 46rem;
    margin: 0 auto;
}

/* ---------- Expense breakdown ("Where it went") ---------- */
/* 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; }
}

/* Tabs without JavaScript. Radios sit before the panels so :has() can reach
   them; hidden with position/opacity rather than display:none, which would
   drop them out of the tab order and off screen readers. */
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--hairline);
        margin-bottom: var(--sp-lg); }
.tabs input { position: absolute; opacity: 0; width: 0; height: 0; }
.tabs label { padding: 10px 16px; cursor: pointer; font-weight: 500;
              color: var(--c-mute); border-bottom: 2px solid transparent;
              margin-bottom: -1px; }
.tabs label:hover { color: var(--c-text); }

.tab-panel { display: none; }
.tab-host:has(#tab-invoices:checked) #panel-invoices,
.tab-host:has(#tab-payments:checked) #panel-payments { display: block; }
.tab-host:has(#tab-invoices:checked) label[for="tab-invoices"],
.tab-host:has(#tab-payments:checked) label[for="tab-payments"] {
    color: var(--c-text); border-bottom-color: var(--c-accent); }

/* Focus must be visible, since the radio itself is not. */
.tabs input:focus-visible + label { outline: 2px solid var(--c-accent);
                                    outline-offset: -2px; border-radius: 4px; }

/* No :has() support — show every panel stacked rather than none at all. */
@supports not selector(:has(*)) { .tab-panel { display: block; } }

/* "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; }

/* Needs your attention.

   The figure leads: every item here is a quantity, and the number is what
   the eye wants first. Severity is weight and scale, not a stripe — an
   urgent row is simply bigger and darker, which survives a screenshot,
   a printout, and anyone for whom red and amber look the same. */

.attn { margin-bottom: var(--s-xl); }
.attn-heading { font-size: 13px; font-weight: 600; letter-spacing: .06em;
                text-transform: uppercase; color: var(--c-mute);
                margin: 0 0 12px; }

.attn-list { display: grid; gap: 2px; }

.attn-item { display: flex; align-items: baseline; gap: 16px;
             padding: 14px 16px; text-decoration: none; color: inherit;
             background: #fff; border-radius: var(--r-sm);
             transition: background .12s ease; }
.attn-item:hover { background: var(--surface-tint); }

.attn-figure { font-variant-numeric: tabular-nums; line-height: 1;
               white-space: nowrap; letter-spacing: -.02em; }
.attn-body { display: flex; flex-direction: column; gap: 2px; }
.attn-what { line-height: 1.3; }
.attn-when { font-size: 12px; color: var(--c-mute); }

/* Urgent is bigger and darker. Quiet is smaller and greyer. That difference
   is the whole signal; the colour below only reinforces it. */
.attn-urgent .attn-figure { font-size: 30px; font-weight: 700; color: #a93226; }
.attn-urgent .attn-what   { font-size: 15px; font-weight: 600; }

.attn-soon .attn-figure { font-size: 22px; font-weight: 600; color: var(--c-text); }
.attn-soon .attn-what   { font-size: 14px; color: #555; }
.attn-soon .attn-item   { padding-top: 11px; padding-bottom: 11px; }


/* ---- Dashboard: work figures --------------------------------------------
   The work card sits beside finance in the KPI band and borrows its layout,
   so the two read as one row rather than two designs. A figure that links
   somewhere stays a figure: same size and weight, underlined only on hover,
   because turning it blue would make the number look like navigation
   instead of information. */
.dash-work .work-metric { color: inherit; text-decoration: none;
                          border-bottom: 1px solid transparent; }
.dash-work .work-metric:hover { border-bottom-color: currentColor; }

/* ---- Dashboard: the main column -----------------------------------------
   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; }

/* 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 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }

/* 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; }

/* ==========================================================================
   Dashboard — visual pass
   --------------------------------------------------------------------------
   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; }

/* --- Sections ------------------------------------------------------------
   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); }

/* --- Cards ---------------------------------------------------------------
   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); }

/* --- The KPI band --------------------------------------------------------
   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 .dash-finance { background: var(--surface-card);
                      box-shadow: var(--shadow-card); border-color: transparent; }

/* Figures lead. This is the principle the attention panel already uses and
   nothing else on the page did: the number is what the eye wants, and the
   label explains it afterwards rather than announcing it. */
.dash .fin-row > div { display: flex; flex-direction: column-reverse;
                       align-items: flex-start; gap: 2px; }
.dash .fin-row .t-caption { font-size: 12px; color: var(--stone); }
.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; }

/* --- Density -------------------------------------------------------------
   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; }
.dash .card,
.dash .card-flat { padding: 20px; }
.dash .dash-quiet .card-flat { padding: 16px; }
.dash .dash-quiet .t-body-sm { font-size: 13px; }

/* --- The chart -----------------------------------------------------------
   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; }

/* --- Tables inside the dashboard ----------------------------------------
   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; }

/* --- Spacing between sections -------------------------------------------- */
.dash > * + * { margin-top: var(--dash-gap); }

@media (max-width: 900px) {
    .dash { --dash-gap: 20px; }
    .dash .dash-kpis { grid-template-columns: 1fr; }
    .dash .metric-sm { font-size: 22px; }
}
/* ==========================================================================
   Dashboard — after the cull
   --------------------------------------------------------------------------
   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; }

/* .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; }

/* People closes the page now. As four small equal cards it read as an
   afterthought; given the width and a little more type it reads as a
   statement about the team, which is what it is. */
.dash .dash-people { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.dash .dash-people .card { padding: 22px 20px; }
.dash .dash-people .metric { font-size: 34px; }

/* The last section carries no bottom margin — the page should end, not trail
   off into empty space. */
.dash > *:last-child { margin-bottom: 0; }

/* ==========================================================================
   Dashboard — hero and figures
   --------------------------------------------------------------------------
   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.
   ========================================================================== */

/* --- The hero ------------------------------------------------------------
   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. */
.dash .hero { display: flex; flex-wrap: wrap; align-items: flex-end;
              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); }

.dash .hero.hero-alert { background-image:url(../img/bg-hero.webp); 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:var(--primary-deep); }

/* 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; }

.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; }
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); }

/* The next few items sit BESIDE the headline. Stacked underneath they would
   turn the band back into the list this replaced. */
.dash .hero-rest { display: flex; gap: 28px; flex-wrap: wrap; }
.dash .hero-rest-item { display: flex; flex-direction: column; gap: 2px;
                        text-decoration: none; color: inherit; opacity: .85;
                        min-width: 90px; }
.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); }

/* --- The figures strip ---------------------------------------------------
   Hairlines, not cards. Eight numbers in eight boxes is eight frames around
   nothing; as one band they read as a single statement about the business. */
.dash .figures { display: flex; flex-wrap: wrap;
                 background: var(--surface-card); border: 1px solid var(--hairline);
                 border-radius: var(--r-sm); overflow: hidden; }

.dash .figure { flex: 1 1 auto; min-width: 150px; padding: 18px 22px;
                border-left: 1px solid var(--hairline); }
.dash .figure:first-child { border-left: 0; }

.dash .figure-value { display: block; font-size: 26px; font-weight: 600;
                      letter-spacing: -.02em; line-height: 1.15; color: var(--ink);
                      font-variant-numeric: tabular-nums;
                      text-decoration: none; border-bottom: 1px solid transparent; }
.dash a.figure-value:hover { border-bottom-color: currentColor; }
.dash .figure-value.is-down { color: var(--danger-text); }

.dash .figure-label { font-size: 12px; color: var(--stone); margin-top: 3px;
                      line-height: 1.35; }

@media (max-width: 900px) {
    .dash .hero { padding: 22px 20px; gap: 20px; }
    .dash .hero-figure { font-size: 38px; }
    .dash .figure { min-width: 50%; border-left: 0;
                    border-top: 1px solid var(--hairline); }
    .dash .figure:first-child,
    .dash .figure:nth-child(2) { border-top: 0; }
}
/* ---- Hero: the right side always carries something -----------------------
   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 { align-items: center; }
.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); }

@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); }
}

/* ==========================================================================
   Dashboard — grouped cards
   --------------------------------------------------------------------------
   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; }

/* 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. */
@media (max-width: 900px) {
    .dash .cards-3 { grid-template-columns: 1fr; }
}

.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(--mint-100); color: var(--primary); }

.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; }

/* 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. */
@media (max-width: 700px) {
    .dash .pcard-foot-meta { white-space: normal; }
}
.dash .pcard-foot-plain { color: var(--stone); }

@media (max-width: 900px) {
    .dash .pcard-value { font-size: 28px; }
}
/* ==========================================================================
   Dashboard — chart panel
   --------------------------------------------------------------------------
   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); }

@media (max-width: 700px) {
    .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); }
}

@media (max-width: 900px) {
    .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; }
}
/* ---- Payables table ------------------------------------------------------
   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); }
/* ---- Latest projects table -----------------------------------------------
   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; }
.dash .dash-progress-col { width: 180px; }

/* 180px is a reasonable share of a wide table and 46% of a 390px screen, where it
   forces .table-wrap to scroll even though the other columns would have fit. The
   bar keeps its own min-width, so it stays readable rather than collapsing. */
@media (max-width: 700px) {
    .dash .dash-progress-col { width: auto; }
    .dash .dash-progress .dash-track { min-width: 48px; }
}

/* Bar and number together: the bar is comparable at a glance, the number is
   exact, and either alone makes somebody do the other half in their head. */
.dash .dash-progress { display: flex; align-items: center; gap: 10px; }
.dash .dash-progress .dash-track { flex: 1; min-width: 70px; margin: 0; }
.dash .dash-pct { font-size: 12px; font-weight: 600; color: var(--stone);
                  font-variant-numeric: tabular-nums; min-width: 34px; text-align: right; }
