/* ═══════════════════════════════════════════
   PYLab Premium UI Design System
   ═══════════════════════════════════════════ */
*{margin:0;padding:0;box-sizing:border-box}
:root{
  --hive-amber:#0C756F; /* Brand Teal */
  --hive-amber-light:rgba(12, 117, 111, 0.08);
  --hive-amber-dark:#054b47;
  --hive-teal:#0C756F;
  --hive-teal-light:#f0f7f6;
  --hive-teal-mid:#054b47;
  --hive-gold:#FDCF6F; /* Brand Gold accent */
  --hive-gold-light:rgba(253, 207, 111, 0.18);
  --hive-gold-dark:#E8AE3A;
  --bg-body:#F5F7FB;
  --bg-card:#ffffff;
  --bg-input:#ffffff;
  --bg-sidebar:#064340;
  --border:#EBEFF5;
  --text-title:#0F172A;
  --text-body:#334155;
  --text-muted:#64748B;
  --success:#10b981;
  --success-bg:#ecfdf5;
  --success-border:#a7f3d0;
  --danger:#ef4444;
  --danger-bg:#fef2f2;
  --danger-border:#fca5a5;
  --warning:#f59e0b;
  --warning-bg:#fffbeb;
  --warning-border:#fde68a;
  --info:#3b82f6;
  --info-bg:#eff6ff;
  --info-border:#bfdbfe;
  --radius:8px;
  --radius-lg:12px;
  --shadow:0 1px 3px 0 rgba(0,2,1,0.05), 0 1px 2px 0 rgba(0,2,1,0.03);
  --shadow-md:0 4px 6px -1px rgba(0,2,1,0.05), 0 2px 4px -1px rgba(0,2,1,0.03);
  --shadow-lg:0 10px 15px -3px rgba(0,2,1,0.05), 0 4px 6px -2px rgba(0,2,1,0.03);
  --table-header-bg:#0c756f;
  --table-header-color:#ffffff;
  --bg-greeting: linear-gradient(105deg, #ffffff 35%, #f2faf9 65%, #daf2f0 100%);
  --border-greeting: #e6f2f1;
}
/* Dark surfaces carry the same teal cast as the brand. They used to be a cold blue-grey
   (#0b0f19 / #151b2c / #232c45) while every accent stayed teal, so the page read as two
   palettes stacked on each other — and the sidebar, which is the deep teal panel that
   identifies the product in light mode, turned into an anonymous blue-black slab. */
[data-theme="dark"]{
  --bg-body:#070f10;
  --bg-card:#101d1f;
  --bg-sidebar:#0b1c1a;
  /* Fields sit *below* the card rather than level with it: on a dark card a white fill is
     impossible, so depth is what separates an input from the surface holding it. */
  --bg-input:#08191a;
  --border:#1e3134;
  --text-title:#eaf2f1;
  --text-body:#c0d1cf;
  /* #64748b was ~4.0:1 on the old card — under AA for the 11.5px labels it is mostly used on. */
  --text-muted:#8ca4a1;
  --success-bg:rgba(16,185,129,0.12);
  --success-border:rgba(16,185,129,0.25);
  --danger-bg:rgba(239,68,68,0.12);
  --danger-border:rgba(239,68,68,0.25);
  --warning-bg:rgba(245,158,11,0.12);
  --warning-border:rgba(245,158,11,0.25);
  --info-bg:rgba(59,130,246,0.12);
  --info-border:rgba(59,130,246,0.25);
  --hive-teal-light:rgba(12,117,111,0.15);
  --hive-amber-light:rgba(12,117,111,0.15);
  --hive-gold-light:rgba(253,207,111,0.15);
  --shadow:0 4px 16px rgba(0,0,0,0.4);
  --shadow-md:0 8px 32px rgba(0,0,0,0.45);
  --shadow-lg:0 12px 48px rgba(0,0,0,0.5);
  /* Full-strength brand teal is right for a header band on white. On a dark page the same
     fill becomes the brightest thing on screen and the header out-shouts the rows it labels,
     so it drops to a deep teal and the lettering carries the colour instead. */
  --table-header-bg:#0f312e;
  --table-header-color:#c2e5e0;
  --bg-greeting: linear-gradient(105deg, #101d1f 35%, #102c2c 70%, #0d3a38 100%);
  --border-greeting: rgba(12, 117, 111, 0.28);
}

/* ═══════════════════════════════════════════
   Brand themes — one laboratory, one colour
   ═══════════════════════════════════════════
   The palette above is the house teal. A laboratory can choose another, and the choice
   belongs to the organisation rather than to the browser: everyone signed in to that
   tenant sees it, on any machine. Light and dark stay a personal setting in localStorage
   and are unaffected — these blocks only move the hue, so every theme works in both.

   Each one redefines the same small set and nothing else. The brand colour is not used
   once; it is the sidebar, the table header band, every primary button, the focus ring and
   the greeting gradient, and those need different tones of one hue with white text still
   legible on the dark ones. Keeping the overrides to this list is what stops a new theme
   from having to re-check the whole stylesheet.

   Semantic colours — success, danger, warning, info — are deliberately NOT themed. Red
   means an abnormal result here and green means in range; a laboratory that recoloured
   those would be changing what the numbers say, not how the page looks.

   data-brand is written on <html> by _Layout from Organization.ThemeColor. No attribute
   means the house colour, which is what :root already holds, so an organisation that has
   never chosen one renders exactly as before. */

[data-brand="ocean"]{
  --hive-amber:#0B5FA5;      --hive-amber-light:rgba(11, 95, 165, 0.08);  --hive-amber-dark:#073F6E;
  --hive-teal:#0B5FA5;       --hive-teal-light:#eff6fc;                   --hive-teal-mid:#073F6E;
  --bg-sidebar:#06355C;      --table-header-bg:#0B5FA5;
  --bg-greeting: linear-gradient(105deg, #ffffff 35%, #f4f9fd 65%, #dceaf7 100%);
  --border-greeting:#e3eef8;
}
[data-brand="indigo"]{
  --hive-amber:#4338CA;      --hive-amber-light:rgba(67, 56, 202, 0.08);  --hive-amber-dark:#312E81;
  --hive-teal:#4338CA;       --hive-teal-light:#f2f1fe;                   --hive-teal-mid:#312E81;
  --bg-sidebar:#272257;      --table-header-bg:#4338CA;
  --bg-greeting: linear-gradient(105deg, #ffffff 35%, #f7f6fe 65%, #e6e3fb 100%);
  --border-greeting:#eceafc;
}
[data-brand="emerald"]{
  --hive-amber:#047857;      --hive-amber-light:rgba(4, 120, 87, 0.08);   --hive-amber-dark:#065F46;
  --hive-teal:#047857;       --hive-teal-light:#eefaf5;                   --hive-teal-mid:#065F46;
  --bg-sidebar:#04402F;      --table-header-bg:#047857;
  --bg-greeting: linear-gradient(105deg, #ffffff 35%, #f2fbf7 65%, #d8f3e8 100%);
  --border-greeting:#e2f5ec;
}
[data-brand="plum"]{
  --hive-amber:#7E22CE;      --hive-amber-light:rgba(126, 34, 206, 0.08); --hive-amber-dark:#581C87;
  --hive-teal:#7E22CE;       --hive-teal-light:#faf4ff;                   --hive-teal-mid:#581C87;
  --bg-sidebar:#44136B;      --table-header-bg:#7E22CE;
  --bg-greeting: linear-gradient(105deg, #ffffff 35%, #fbf6ff 65%, #f0e2fb 100%);
  --border-greeting:#f3e9fc;
}
/* Rose and Amber are the deep ends of pink and yellow, not the bright ones: white text
   sits on the fill and on the sidebar, and a true yellow cannot carry it. These two clear
   4.5:1 against white, the same bar BrandPalette holds a custom colour to. */
[data-brand="rose"]{
  --hive-amber:#BE185D;      --hive-amber-light:rgba(190, 24, 93, 0.08);  --hive-amber-dark:#8D1246;
  --hive-teal:#BE185D;       --hive-teal-light:#fdf2f7;                   --hive-teal-mid:#8D1246;
  --bg-sidebar:#6B0C34;      --table-header-bg:#BE185D;
  --bg-greeting: linear-gradient(105deg, #ffffff 35%, #fdf5f8 65%, #fae0ec 100%);
  --border-greeting:#fbe8f0;
}
[data-brand="amber"]{
  --hive-amber:#A16207;      --hive-amber-light:rgba(161, 98, 7, 0.08);   --hive-amber-dark:#774905;
  --hive-teal:#A16207;       --hive-teal-light:#fdf8ed;                   --hive-teal-mid:#774905;
  --bg-sidebar:#5A3704;      --table-header-bg:#A16207;
  --bg-greeting: linear-gradient(105deg, #ffffff 35%, #fdf9f0 65%, #f7ebd4 100%);
  --border-greeting:#f8efdd;
}
[data-brand="slate"]{
  --hive-amber:#334155;      --hive-amber-light:rgba(51, 65, 85, 0.08);   --hive-amber-dark:#1E293B;
  --hive-teal:#334155;       --hive-teal-light:#f3f5f8;                   --hive-teal-mid:#1E293B;
  --bg-sidebar:#16202E;      --table-header-bg:#334155;
  --bg-greeting: linear-gradient(105deg, #ffffff 35%, #f6f8fa 65%, #e5eaf0 100%);
  --border-greeting:#eaeef3;
}

/* In dark mode the surfaces come from [data-theme="dark"] and the hue from here. The
   sidebar is the one surface that carries the brand in both, so it is darkened again
   rather than left at its light-mode value, which would glare against a dark page. */
[data-theme="dark"][data-brand="ocean"]  { --bg-sidebar:#071d31; --hive-teal-light:#0d2438; }
[data-theme="dark"][data-brand="indigo"] { --bg-sidebar:#171433; --hive-teal-light:#1b1840; }
[data-theme="dark"][data-brand="emerald"]{ --bg-sidebar:#05251b; --hive-teal-light:#0a2b21; }
[data-theme="dark"][data-brand="plum"]   { --bg-sidebar:#290b40; --hive-teal-light:#2d1145; }
[data-theme="dark"][data-brand="rose"]   { --bg-sidebar:#3a0a1d; --hive-teal-light:#3d1226; }
[data-theme="dark"][data-brand="amber"]  { --bg-sidebar:#311e03; --hive-teal-light:#35250c; }
[data-theme="dark"][data-brand="slate"]  { --bg-sidebar:#111826; --hive-teal-light:#19212f; }
body{font-family:'Inter', sans-serif;background:var(--bg-body);color:var(--text-body);font-size:13px;min-height:100vh}

/* ── App Layout ── */
.app-layout{display:flex;min-height:100vh}

/* ── Sidebar ── */
.sidebar{width:260px;min-width:260px;background:var(--bg-sidebar);display:flex;flex-direction:column;overflow-y:auto;position:sticky;top:0;height:100vh;flex-shrink:0;z-index:100;transition:transform 0.25s ease; border-right: 1px solid rgba(255,255,255,0.05);padding-bottom:8px}
/* The line-art watermark that used to sit here is gone. It was anchored to the bottom of the
   scroll box on the assumption there would be empty space under the last menu item, but a
   full menu leaves none — so on every normal viewport its strokes ran straight through
   "Doctor List" through "Lab Settings" and read as a rendering fault rather than decoration. */
.sidebar-logo{padding:14px 16px;border-bottom:1px solid rgba(255,255,255,0.08);display:flex;align-items:center;gap:12px;position:sticky;top:0;z-index:5;background:var(--bg-sidebar);margin-bottom:6px}
/* A default light scrollbar cuts a bright stripe down the dark panel. */
.sidebar{scrollbar-width:thin;scrollbar-color:rgba(255,255,255,0.18) transparent}
.sidebar::-webkit-scrollbar{width:6px}
.sidebar::-webkit-scrollbar-track{background:transparent}
.sidebar::-webkit-scrollbar-thumb{background:rgba(255,255,255,0.14);border-radius:3px}
.sidebar::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,0.26)}
.logo-hex{flex-shrink:0}
.logo-text{flex:1}
.logo-name{font-size:17px;font-weight:800;color:#ffffff;letter-spacing:-0.5px}
.logo-tag{font-size:10px;color:rgba(255,255,255,0.5);font-weight:600;letter-spacing:1.5px;text-transform:uppercase}
.sidebar-toggle-btn{display:none;background:none;border:none;color:rgba(255,255,255,0.5);cursor:pointer;font-size:18px;padding:4px;margin-left:auto}
/* Flat, always-visible navigation: no section collapses, so the whole map of the app is
   readable at a glance. Grouping is carried by the label and the space above it. Spacing
   is tuned so all ~20 destinations fit a laptop viewport without scrolling. */
.sidebar-section{padding:0 10px}
.sidebar-section + .sidebar-section{margin-top:10px}
.section-label{font-size:9.5px;font-weight:700;color:rgba(255,255,255,0.38);letter-spacing:1.1px;text-transform:uppercase;padding:0 12px 5px;opacity:1;white-space:nowrap}
/* Tints the heading of the group holding the current page. */
.sidebar-section.in-section > .section-label{color:rgba(255,255,255,0.62)}
.nav-item{display:flex;align-items:center;gap:10px;padding:6px 12px;border-radius:8px;color:rgba(255,255,255,0.72);font-size:12.5px;font-weight:500;cursor:pointer;transition:background .15s ease,color .15s ease;text-decoration:none;margin-bottom:1px;position:relative;line-height:1.45}
.nav-item:hover{background:rgba(255,255,255,0.06);color:#ffffff}
.nav-item:focus-visible{outline:2px solid rgba(255,255,255,0.5);outline-offset:-2px}
/* The sidebar is already dark teal, so a teal fill alone reads as a slab rather than a
   selection. A lighter fill plus a left accent bar makes the current page unmistakable. */
.nav-item.active{background:rgba(255,255,255,0.13) !important;color:#ffffff !important;font-weight:600}
.nav-item.active i{color:#ffffff !important;opacity:1}
.nav-item.active::before{display:block;content:'';position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:18px;border-radius:0 3px 3px 0;background:var(--hive-gold,#FDCF6F)}
.nav-item i{font-size:17px;width:20px;text-align:center;flex-shrink:0;opacity:0.75}
.nav-badge{margin-left:auto;background:rgba(255,255,255,0.1);color:#ffffff;font-size:10px;font-weight:700;padding:2px 7px;border-radius:10px}
.nav-badge.danger{background:var(--danger-bg);color:var(--danger)}
.sidebar-divider{height:1px;background:rgba(255,255,255,0.08);margin:8px 20px}
.sidebar-footer{padding:10px 12px;border:1px solid rgba(255,255,255,0.08);border-radius:10px;margin:12px;margin-top:auto;display:flex;align-items:center;gap:12px;background:rgba(0,0,0,0.15)}
.user-avatar{width:36px;height:36px;border-radius:50%;background:#ffffff;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;color:#064340;flex-shrink:0;box-shadow:var(--shadow)}
.user-info{flex:1;min-width:0}
.user-name{font-size:12.5px;font-weight:600;color:#ffffff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.user-role{font-size:11px;color:rgba(255,255,255,0.5);margin-top:1px}
.sidebar-footer-actions{display:flex;gap:4px}

/* ── Overlay ── */
.sidebar-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,0.4);z-index:99}
.sidebar-overlay.show{display:block}

/* ── Mobile bottom navigation (hidden on desktop) ── */
.mobile-bottom-nav{display:none}

/* ── Main Area ── */
.main-area{flex:1;display:flex;flex-direction:column;min-width:0;overflow-x:hidden}

/* ── Topbar ── */
.topbar{background:var(--bg-card);border-bottom:1px solid var(--border);padding:0 24px;height:60px;display:flex;align-items:center;gap:16px;position:sticky;top:0;z-index:50;box-shadow:0 1px 2px 0 rgba(0,0,0,0.03)}
.topbar-menu-btn{display:none;background:none;border:none;color:var(--text-body);font-size:20px;cursor:pointer;padding:4px}
.breadcrumb-wrap{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--text-muted);flex:1}
.breadcrumb-wrap span{color:var(--text-title);font-weight:600}
.topbar-actions{display:flex;align-items:center;gap:12px}
.topbar-date{font-size:12px;color:var(--text-body);font-weight:500;padding:6px 12px;background:var(--bg-body);border:1px solid var(--border);border-radius:8px;display:flex;align-items:center;gap:8px}

/* ── Top-bar profile dropdown (user menu: change password / logout) ── */
.topbar-profile{position:relative;display:flex;align-items:center;gap:10px;padding:5px 8px 5px 10px;border-left:1px solid var(--border);border-radius:8px;cursor:pointer;user-select:none;transition:background 0.15s}
.topbar-profile:hover{background:var(--bg-body)}
.topbar-profile .chev{font-size:14px;color:var(--text-muted);transition:transform 0.2s}
.topbar-profile.open .chev{transform:rotate(180deg)}
.profile-menu{position:absolute;top:calc(100% + 8px);right:0;min-width:232px;background:var(--bg-card);border:1px solid var(--border);border-radius:12px;box-shadow:var(--shadow-lg);padding:8px;z-index:200;opacity:0;visibility:hidden;transform:translateY(-6px);transition:opacity .15s ease,transform .15s ease,visibility .15s}
.topbar-profile.open .profile-menu{opacity:1;visibility:visible;transform:translateY(0)}
.profile-menu-head{display:flex;align-items:center;gap:10px;padding:6px 10px 10px;border-bottom:1px solid var(--border);margin-bottom:6px}
.profile-menu-name{font-size:13px;font-weight:700;color:var(--text-title);line-height:1.2}
.profile-menu-role{font-size:11px;color:var(--text-muted);margin-top:2px}
.profile-menu-item{display:flex;align-items:center;gap:10px;width:100%;padding:9px 10px;border-radius:8px;font-size:13px;font-weight:500;color:var(--text-body);background:none;border:none;cursor:pointer;text-decoration:none;font-family:inherit;transition:background .15s,color .15s;text-align:left}
.profile-menu-item:hover{background:var(--bg-body);color:var(--text-title)}
.profile-menu-item i{font-size:17px;width:20px;text-align:center;color:var(--text-muted)}
.profile-menu-item.danger:hover{background:var(--danger-bg);color:var(--danger)}
.profile-menu-item.danger:hover i{color:var(--danger)}

/* ── Alerts ── */
.alerts-wrap{padding:0 24px;transition:all 0.3s}
.alert{display:flex;align-items:center;gap:10px;padding:12px 16px;border-radius:var(--radius);margin-top:14px;font-size:13px;font-weight:500;transition:opacity 0.3s;box-shadow:var(--shadow);border:1px solid transparent;border-left-width:4px}
.alert-success{background:var(--success-bg);color:#065f46;border-color:var(--success-border);border-left-color:var(--success) !important}
.alert-danger{background:var(--danger-bg);color:#991b1b;border-color:var(--danger-border);border-left-color:var(--danger) !important}
.alert-warning{background:var(--warning-bg);color:#92400e;border-color:var(--warning-border);border-left-color:var(--warning) !important}
.alert-close{margin-left:auto;background:none;border:none;font-size:18px;cursor:pointer;color:inherit;opacity:0.6;line-height:1;transition:opacity 0.15s}
.alert-close:hover{opacity:1}

/* ── Page Content ── */
.page-content{padding:20px;flex:1}

/* ── Cards ── */
/* The HTML `hidden` attribute must win over any component's own display value. The browser's
   default [hidden]{display:none} is a single attribute selector, so it loses to .card below —
   which sets display:flex — and to every other class that sets display. The result was that
   markup written as <div class="card" hidden> rendered anyway: the critical-value notification
   block on the result-entry screen appeared on every report rather than only on one carrying a
   panic value, which trains staff to ignore the one warning that must not be ignored.
   Declared once, here, rather than per component. */
[hidden]{display:none !important}

.card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow);display:flex;flex-direction:column;transition:box-shadow 0.25s ease}
.card:hover{box-shadow:var(--shadow-md)}
.card-header{padding:16px 24px;display:flex;align-items:center;gap:12px;border-bottom:1px solid var(--border);background:transparent}
.card-title{font-size:15px;font-weight:700;color:var(--text-title);letter-spacing:-0.2px}
.card-subtitle{font-size:12px;color:var(--text-muted);margin-top:2px}
.card-body{padding:24px}
.card-actions{margin-left:auto;display:flex;gap:8px;align-items:center}
.card-footer{padding:14px 24px;border-top:1px solid var(--border);display:flex;align-items:center;justify-content:space-between}

/* ── KPI Cards ── */
.kpi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:20px;margin-bottom:24px}
.kpi-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:24px;transition:all 0.25s cubic-bezier(0.4, 0, 0.2, 1);cursor:default;box-shadow:var(--shadow);position:relative;overflow:hidden}
.kpi-card::after{content:'';position:absolute;top:0;left:0;width:4px;height:100%;background:transparent;transition:background-color 0.25s ease}
.kpi-card:hover{box-shadow:var(--shadow-md);transform:translateY(-2px)}
.kpi-card:nth-child(1):hover{border-color:var(--hive-amber)}
.kpi-card:nth-child(1):hover::after{background-color:var(--hive-amber)}
.kpi-card:nth-child(2):hover{border-color:transparent}
.kpi-card:nth-child(2):hover::after{background-color:var(--hive-gold)}
.kpi-card:nth-child(3):hover{border-color:var(--danger)}
.kpi-card:nth-child(3):hover::after{background-color:var(--danger)}
.kpi-card:nth-child(4):hover{border-color:var(--success)}
.kpi-card:nth-child(4):hover::after{background-color:var(--success)}
.kpi-label{font-size:11.5px;color:var(--text-muted);font-weight:600;text-transform:uppercase;letter-spacing:1px;margin-bottom:12px;display:flex;align-items:center;gap:8px}
.kpi-label i{font-size:16px}
.kpi-value{font-size:32px;font-weight:800;color:var(--text-title);margin-bottom:8px;font-family:'JetBrains Mono',monospace;letter-spacing:-1px}
.kpi-footer{display:flex;align-items:center;gap:8px}
.kpi-sub{font-size:11px;color:var(--text-muted)}

/* ── Buttons ── */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:9px 18px;border-radius:var(--radius);font-size:13px;font-weight:600;cursor:pointer;transition:all 0.2s cubic-bezier(0.4, 0, 0.2, 1);font-family:inherit;text-decoration:none;border:1px solid transparent;white-space:nowrap;box-shadow:var(--shadow);outline:2px solid transparent;outline-offset:2px}
.btn:focus-visible{outline-color:var(--hive-amber)}
.btn:active{transform:scale(0.98)}
.btn:disabled{opacity:0.55;cursor:not-allowed;transform:none !important;box-shadow:none !important}
.btn-primary{background:var(--hive-amber);color:#ffffff}
.btn-primary:hover:not(:disabled){background:var(--hive-amber-dark);color:#ffffff;box-shadow:var(--shadow-md)}
.btn-teal{background:var(--hive-teal);color:#ffffff}
.btn-teal:hover:not(:disabled){background:var(--hive-teal-mid);color:#ffffff;box-shadow:var(--shadow-md)}
.btn-success{background:var(--success);color:#ffffff}
.btn-success:hover:not(:disabled){background:#059669;color:#ffffff;box-shadow:var(--shadow-md)}
.btn-danger{background:var(--danger);color:#ffffff}
.btn-danger:hover:not(:disabled){background:#dc2626;color:#ffffff;box-shadow:var(--shadow-md)}
.btn-outline{background:transparent;border:1px solid var(--border);color:var(--text-body)}
.btn-outline:hover:not(:disabled){border-color:var(--hive-amber);color:var(--hive-amber);background:var(--hive-amber-light)}
.btn-sm{padding:6px 12px;font-size:12px;border-radius:6px}
.btn-xs{padding:4px 8px;font-size:11px;border-radius:6px}
.btn-icon{padding:8px;border-radius:8px;border:1px solid var(--border);background:var(--bg-card);cursor:pointer;color:var(--text-muted);transition:all 0.15s;font-size:15px;display:inline-flex;align-items:center;justify-content:center;box-shadow:var(--shadow)}
.btn-icon:hover{border-color:var(--hive-amber);color:var(--hive-amber);background:var(--hive-amber-light)}

/* ── Badges ── */
.badge{padding:4px 10px;border-radius:20px;font-size:11px;font-weight:700;display:inline-flex;align-items:center;gap:4px;white-space:nowrap;border:1px solid transparent}
.badge-amber{background:var(--warning-bg);color:var(--warning);border-color:var(--warning-border)}
.badge-success{background:var(--success-bg);color:var(--success);border-color:var(--success-border)}
.badge-danger{background:var(--danger-bg);color:var(--danger);border-color:var(--danger-border)}
.badge-info{background:var(--info-bg);color:var(--info);border-color:var(--info-border)}
.badge-muted{background:var(--hive-teal-light);color:var(--text-muted);border-color:var(--border)}
.badge-teal{background:var(--hive-teal-light);color:var(--hive-teal);border-color:var(--border)}

/* ── Trend ── */
.trend{font-size:11px;font-weight:700;display:inline-flex;align-items:center;gap:4px;padding:3px 8px;border-radius:20px}
.trend.up{background:var(--success-bg);color:var(--success)}
.trend.down{background:var(--danger-bg);color:var(--danger)}

/* ── Tables ── */
.table-wrap{overflow-x:auto}
table.data-table{width:100%;border-collapse:collapse}
table.data-table thead th{padding:12px 14px;font-size:11.5px;font-weight:700;color:var(--table-header-color);text-transform:uppercase;letter-spacing:0.6px;background:var(--table-header-bg);border-bottom:none;text-align:left;white-space:nowrap}
table.data-table thead th:first-child{padding-left:20px;border-top-left-radius:8px}
table.data-table thead th:last-child{padding-right:20px;text-align:right;border-top-right-radius:8px}
table.data-table tbody tr{border-bottom:1px solid var(--border);transition:background 0.1s}
table.data-table tbody tr:last-child{border-bottom:none}
table.data-table tbody tr:hover{background:rgba(12,117,111,0.04)}
table.data-table tbody td{padding:12px 14px;vertical-align:middle}
table.data-table tbody td:first-child{padding-left:20px}
table.data-table tbody td:last-child{padding-right:20px;text-align:right}
.table-actions{display:flex;gap:5px;justify-content:flex-end}

/* ── Forms ── */
.form-group{margin-bottom:18px}
.form-label{display:block;font-size:12.5px;font-weight:600;color:var(--text-title);margin-bottom:6px}
.form-label .required{color:var(--danger);margin-left:2px}
.form-control{width:100%;padding:9px 14px;border:1px solid var(--border);border-radius:var(--radius);font-size:13px;color:var(--text-title);background:var(--bg-card);font-family:inherit;transition:all 0.2s ease;outline:none;box-shadow:inset 0 1px 2px rgba(0,0,0,0.02)}
.form-control:focus{border-color:var(--hive-amber);box-shadow:0 0 0 4px rgba(12,117,111,0.1)}
.form-control::placeholder{color:var(--text-muted)}
/* .input-validation-error is what jQuery unobtrusive validation adds; keep it in step with .is-invalid. */
.form-control.is-invalid,.form-control.input-validation-error{border-color:var(--danger)}
.form-control.is-invalid:focus,.form-control.input-validation-error:focus{box-shadow:0 0 0 4px rgba(239,68,68,0.1)}
.form-select{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%2364748B' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 14px center;padding-right:36px}
.field-validation-error{font-size:11.5px;color:var(--danger);margin-top:5px;display:block;font-weight:500}
.form-hint{font-size:11.5px;color:var(--text-muted);margin-top:5px}
.form-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px}
.form-check{display:flex;align-items:center;gap:10px;cursor:pointer;font-size:13px;user-select:none}
.form-check input[type=checkbox]{width:18px;height:18px;cursor:pointer;accent-color:var(--hive-amber);border-radius:4px}

/* ── Material-style floating label fields ──
   Markup: <div class="mui-field"><input class="form-control" placeholder=" "><label>Caption</label></div>
   The placeholder=" " is required: :placeholder-shown is what tells us the field is empty.
   .mui-input / .mui-select / .mui-textarea are accepted as aliases of .form-control so the
   booking screen and the settings screen share one implementation instead of two. */
.mui-field{position:relative;display:block;width:100%}
.mui-field > :is(.form-control,.mui-input,.mui-select,.mui-textarea){width:100%;height:44px;padding:0 13px;border:1px solid var(--border);border-radius:8px;font-family:inherit;font-size:13px;font-weight:500;color:var(--text-title);background:var(--bg-card);outline:none;box-shadow:none;transition:border-color .18s ease,box-shadow .18s ease}
.mui-field > :is(textarea.form-control,.mui-textarea){height:auto;min-height:60px;padding:11px 13px;line-height:1.5;resize:vertical}
.mui-field > :is(select.form-control,.mui-select){appearance:none;-webkit-appearance:none;padding-right:30px;cursor:pointer;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%2364748B' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 11px center}
.mui-field > :is(.form-control,.mui-input,.mui-select,.mui-textarea)::placeholder{color:transparent}
.mui-field > :is(.form-control,.mui-input,.mui-select,.mui-textarea):disabled{background:var(--bg-body);color:var(--text-muted);cursor:not-allowed}
/* Resting label: vertically centred inside the box, no backdrop. */
.mui-field > label{position:absolute;left:11px;top:50%;transform:translateY(-50%);padding:0 4px;font-size:12.5px;font-weight:500;color:var(--text-muted);background:transparent;pointer-events:none;transition:top .16s cubic-bezier(.4,0,.2,1),font-size .16s cubic-bezier(.4,0,.2,1),color .16s ease,background .16s ease;max-width:calc(100% - 26px);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mui-field > :is(textarea.form-control,.mui-textarea) ~ label{top:13px;transform:none}
/* Raised: the label straddles the top border (outlined variant) and paints over it with the
   card background, which is what produces the "notch" without an extra fieldset element.
   A select can never be :placeholder-shown, so it is raised unconditionally. */
.mui-field > :is(.form-control,.mui-input,.mui-select,.mui-textarea):focus ~ label,
.mui-field > :is(.form-control,.mui-input,.mui-textarea):not(:placeholder-shown) ~ label,
.mui-field > :is(select.form-control,.mui-select) ~ label,
.mui-field.mui-select-field > label,
.mui-field.is-raised > label{top:0;transform:translateY(-50%);font-size:10.5px;font-weight:700;letter-spacing:.2px;color:var(--hive-teal);background:var(--bg-card);padding:0 5px;max-width:none}
.mui-field > :is(.form-control,.mui-input,.mui-select,.mui-textarea):focus{border-color:var(--hive-teal);box-shadow:inset 0 0 0 1px var(--hive-teal)}
/* The two subtle border tints below must never mask a validation error, hence the exclusions. */
.mui-field > :is(.form-control,.mui-input,.mui-select,.mui-textarea):hover:not(:focus):not(.is-invalid):not(.input-validation-error){border-color:rgba(12,117,111,0.4)}
.mui-field > :is(.form-control,.mui-input,.mui-textarea):not(:placeholder-shown):not(:focus):not(.is-invalid):not(.input-validation-error),
.mui-field > :is(select.form-control,.mui-select):not(:focus):not(.is-invalid):not(.input-validation-error){border-color:rgba(12,117,111,0.28)}
.mui-field > :is(.form-control,.mui-input,.mui-select,.mui-textarea).is-invalid ~ label,
.mui-field > :is(.form-control,.mui-input,.mui-select,.mui-textarea).input-validation-error ~ label{color:var(--danger)}
.mui-field > :is(.form-control,.mui-input,.mui-select,.mui-textarea).is-invalid:focus,
.mui-field > :is(.form-control,.mui-input,.mui-select,.mui-textarea).input-validation-error:focus{border-color:var(--danger);box-shadow:inset 0 0 0 1px var(--danger)}
.mui-field > label .required{color:var(--danger);margin-left:2px}
.mui-hint{display:block;font-size:10px;color:var(--text-muted);margin-top:4px;padding-left:2px}
/* Two controls sharing one outlined box (e.g. Age + its unit): the trailing select is an
   adornment pinned inside the field rather than a separate box of its own. */
.mui-field.mui-combo > :is(.form-control,.mui-input){padding-right:94px}
.mui-combo-select{position:absolute;top:1px;right:1px;height:calc(100% - 2px);width:88px;border:0;border-left:1px solid var(--border);border-radius:0 7px 7px 0;background:transparent;color:var(--text-body);font-family:inherit;font-size:12.5px;font-weight:600;padding:0 24px 0 10px;outline:none;cursor:pointer;appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%2364748B' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center}
.mui-combo-select:focus{color:var(--hive-teal);border-left-color:var(--hive-teal)}

/* ── Titled form sections ──
   Grown out of the Settings page, which is where the pattern started; .form-section is the
   name to use on anything new. A long form reads as a handful of named groups instead of
   one undifferentiated column, which is what lets it widen into several columns without
   turning into a wall of boxes. */
.settings-section,.form-section{margin-bottom:20px}
.settings-section:last-of-type,.form-section:last-of-type{margin-bottom:0}
.settings-section > h5,.form-section > h5{display:flex;align-items:center;gap:8px;font-size:11px;font-weight:800;letter-spacing:.6px;text-transform:uppercase;color:var(--hive-teal);border-bottom:1px solid var(--border);padding-bottom:7px;margin-bottom:16px}
.settings-section > h5 i,.form-section > h5 i{font-size:14px}
/* Tighter than the app-wide 18px so the stacked field rows don't drift apart. */
.settings-section .form-group,.form-section .form-group{margin-bottom:14px}
/* Narrower minimum track than the app-wide 220px so a six-field row still lands on one line. */
.settings-section .form-row{gap:14px;grid-template-columns:repeat(auto-fit,minmax(165px,1fr))}
.settings-note{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;padding:11px 14px;border:1px dashed var(--border);border-radius:8px;background:var(--hive-amber-light);font-size:11.5px;color:var(--text-body)}
/* Toggle switch */
.settings-toggle{position:relative;display:flex;align-items:flex-start;gap:11px;padding:11px 14px;border:1px solid var(--border);border-radius:8px;cursor:pointer;transition:border-color .18s ease,background .18s ease}
.settings-toggle:hover{border-color:var(--hive-teal);background:var(--hive-amber-light)}
.settings-toggle input{position:absolute;opacity:0;width:0;height:0}
.settings-toggle .switch{position:relative;flex-shrink:0;width:38px;height:21px;border-radius:11px;background:#cbd5e1;transition:background .2s ease;margin-top:1px}
.settings-toggle .switch::after{content:"";position:absolute;top:2px;left:2px;width:17px;height:17px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.25);transition:transform .2s cubic-bezier(.4,0,.2,1)}
.settings-toggle input:checked ~ .switch{background:var(--hive-teal)}
.settings-toggle input:checked ~ .switch::after{transform:translateX(17px)}
.settings-toggle input:focus-visible ~ .switch{box-shadow:0 0 0 3px rgba(12,117,111,.25)}
.settings-toggle .switch-text strong{display:block;font-size:12.5px;font-weight:700;color:var(--text-title);margin-bottom:2px}
.settings-toggle .switch-text span{font-size:11.5px;color:var(--text-muted);line-height:1.45}
/* Branding upload tiles */
.brand-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:14px}
.brand-tile{display:flex;flex-direction:column;border:1px solid var(--border);border-radius:10px;overflow:hidden;transition:border-color .18s ease,box-shadow .18s ease}
.brand-tile:hover{border-color:var(--hive-teal);box-shadow:var(--shadow-md)}
.brand-tile-head{display:flex;align-items:center;gap:6px;padding:8px 12px;border-bottom:1px solid var(--border);font-size:10.5px;font-weight:800;letter-spacing:.5px;text-transform:uppercase;color:var(--text-title)}
.brand-tile-head i{font-size:13px;color:var(--hive-teal)}
.brand-preview{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;min-height:72px;padding:10px;background:repeating-conic-gradient(var(--bg-body) 0% 25%,var(--bg-card) 0% 50%) 50%/14px 14px}
.brand-preview img{max-height:52px;max-width:100%;object-fit:contain}
.brand-preview .empty{display:flex;flex-direction:column;align-items:center;gap:3px;color:var(--text-muted)}
.brand-preview .empty i{font-size:22px;opacity:.55}
.brand-preview .empty span{font-size:10px}
.brand-tile-foot{padding:10px 12px;border-top:1px solid var(--border);display:flex;flex-direction:column;gap:6px}
.brand-tile-foot input[type=file]{width:100%;font-size:10px;color:var(--text-muted);cursor:pointer}
.brand-tile-foot input[type=file]::file-selector-button{margin-right:9px;padding:4px 10px;border:1px solid var(--border);border-radius:6px;background:var(--bg-card);color:var(--text-body);font-family:inherit;font-size:10px;font-weight:600;cursor:pointer;transition:all .15s ease}
.brand-tile-foot input[type=file]::file-selector-button:hover{border-color:var(--hive-teal);color:var(--hive-teal);background:var(--hive-amber-light)}
.brand-remove{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:600;color:var(--danger);cursor:pointer;user-select:none}
.brand-remove input{width:14px;height:14px;cursor:pointer;accent-color:var(--danger)}
.settings-footer{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;margin-top:20px;padding-top:14px;border-top:1px solid var(--border)}
.settings-footer .hint{font-size:11.5px;color:var(--text-muted)}
@media (max-width:640px){
  .settings-footer{padding:14px 16px}
  .settings-footer .btn{flex:1;justify-content:center}
}

/* ── Avatar ── */
.patient-avatar{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;flex-shrink:0}
.patient-info-cell{display:flex;align-items:center;gap:10px}
.patient-name{font-size:13px;font-weight:600;color:var(--text-title)}
.patient-id{font-size:11px;color:var(--text-muted);font-family:'JetBrains Mono',monospace}

/* ── Page Header ── */
.page-header{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:20px;gap:16px}
.page-header-left h1{font-size:20px;font-weight:800;color:var(--text-title);letter-spacing:-0.5px}
.page-header-left p{font-size:13px;color:var(--text-muted);margin-top:4px}
.page-header-actions{display:flex;gap:10px;align-items:center;flex-shrink:0}

/* ── Search bar ── */
.search-bar{display:flex;align-items:center;gap:8px;background:var(--bg-card);border:1px solid var(--border);border-radius:8px;padding:8px 12px;box-shadow:var(--shadow);transition:border 0.15s ease}
.search-bar:focus-within{border-color:var(--hive-amber)}
.search-bar input{border:none;background:transparent;font-size:13px;color:var(--text-body);outline:none;width:220px;font-family:inherit}
.search-bar input::placeholder{color:var(--text-muted)}
.search-bar i{color:var(--text-muted);font-size:16px}

/* ── Mono numbers ── */
.mono{font-family:'JetBrains Mono',monospace;font-size:13px}
.amount{font-family:'JetBrains Mono',monospace;font-weight:600;color:var(--text-title)}

/* ── Report Entry ── */
.result-row{display:grid;grid-template-columns:2fr 1.5fr 1fr 1.5fr 1fr;gap:10px;padding:10px 0;border-bottom:1px solid var(--border);align-items:center}
.result-row:last-child{border-bottom:none}
.abnormal-high{color:var(--danger);font-weight:700}
.abnormal-low{color:var(--info);font-weight:700}
.flag-high{display:inline-flex;align-items:center;gap:3px;font-size:11px;font-weight:800;padding:2px 6px;border-radius:4px;background:var(--danger-bg);color:var(--danger)}
.flag-low{display:inline-flex;align-items:center;gap:3px;font-size:11px;font-weight:800;padding:2px 6px;border-radius:4px;background:var(--info-bg);color:var(--info)}

/* ── Permission Matrix ── */
.perm-table th,.perm-table td{text-align:center;padding:8px 6px}
.perm-table th:first-child,.perm-table td:first-child{text-align:left;padding-left:16px}

/* ── Status colors ── */
.status-Paid,.status-Completed,.status-Active,.status-Verified,.status-Delivered{background:var(--success-bg);color:var(--success)}
.status-Partial,.status-Pending{background:var(--warning-bg);color:var(--warning)}
/* FOC is neither settled nor owing, so it borrows neither the green nor the amber — an
   unstyled badge would otherwise render as bare text wherever a status is shown. */
.status-FOC{background:var(--info-bg);color:var(--info)}
.status-Expired,.status-Suspended{background:var(--danger-bg);color:var(--danger)}

/* ── Dashboard UI ── */
.welcome-card { background: linear-gradient(135deg, var(--bg-card) 0%, var(--hive-amber-light) 100%); border: 1px solid var(--border); border-radius: 16px; padding: 28px; display: flex; align-items: center; gap: 24px; margin-bottom: 24px; box-shadow: var(--shadow); }
.welcome-icon { width: 48px; height: 48px; background: var(--hive-amber-light); color: var(--hive-amber); border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 24px; flex-shrink: 0; }
.welcome-text { flex: 1; }
.welcome-title { font-size: 22px; font-weight: 800; color: var(--text-title); margin-bottom: 4px; display: flex; align-items: center; gap: 8px; letter-spacing: -0.5px; }
.welcome-subtitle { font-size: 13px; color: var(--text-muted); line-height: 1.5; }
.welcome-actions { display: flex; gap: 12px; }

.charts-grid { display: grid; grid-template-columns: 2fr 1fr; gap: 20px; margin-bottom: 24px; }
.dashboard-row-grid { display: grid; grid-template-columns: 2fr 1fr; gap: 20px; margin-bottom: 24px; align-items: stretch; }
.chart-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 12px; padding: 24px; box-shadow: var(--shadow); display: flex; flex-direction: column; }
.chart-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 16px; }
.chart-title { font-size: 15px; font-weight: 700; color: var(--text-title); letter-spacing: -0.2px; }
.chart-subtitle { font-size: 11.5px; color: var(--text-muted); margin-top: 2px; }
.chart-container { flex: 1; position: relative; width: 100%; min-height: 200px; }

.dashboard-grid { display: grid; grid-template-columns: 2fr 1fr; gap: 20px; }
.widget-stack { display: flex; flex-direction: column; gap: 20px; }
.widget-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; box-shadow: var(--shadow); }
.widget-header { padding: 16px 20px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 10px; font-size: 13.5px; font-weight: 750; color: var(--text-title); }
.widget-header i { font-size: 16px; color: var(--hive-amber); }
.widget-list { display: flex; flex-direction: column; }
.widget-item { padding: 12px 20px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 12px; transition: background 0.2s; }
.widget-item:last-child { border-bottom: none; }
.widget-item:hover { background: rgba(12, 117, 111, 0.03); }
.widget-icon { width: 36px; height: 36px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 16px; flex-shrink: 0; }
.widget-icon.light-amber { background: var(--hive-amber-light); color: var(--hive-amber); }
.widget-icon.light-teal { background: var(--hive-teal-light); color: var(--hive-teal); }
.widget-icon.light-success { background: var(--success-bg); color: var(--success); }
.widget-icon.light-danger { background: var(--danger-bg); color: var(--danger); }
.widget-icon.light-info { background: var(--info-bg); color: var(--info); }
.widget-info { flex: 1; min-width: 0; }
.widget-info-title { font-size: 11.5px; color: var(--text-muted); margin-bottom: 2px; }
.widget-info-val { font-size: 14px; font-weight: 700; color: var(--text-title); }
.widget-right { text-align: right; }

.activity-item { padding: 12px 20px; border-bottom: 1px dashed var(--border); position: relative; padding-left: 36px; }
.activity-item::before { content: ''; position: absolute; left: 20px; top: 18px; width: 6px; height: 6px; border-radius: 50%; background: var(--hive-teal); }
.activity-item:last-child { border-bottom: none; }
.activity-desc { font-size: 12.5px; color: var(--text-title); margin-bottom: 4px; }
.activity-desc strong { font-weight: 600; }
.activity-time { font-size: 11px; color: var(--text-muted); }

/* ── Responsive ── */
/* Mid-size laptops (incl. 14–15" panels at 125–175% Windows scaling, ~1100–1280px
   effective width): keep the sidebar visible but slimmer, tighten paddings and
   shrink fixed-width inputs so content gets room and nothing clips off-screen. */
@media(max-width:1280px){
  .sidebar{width:230px;min-width:230px}
  .page-content{padding:16px}
  .card-header{padding:14px 18px}
  .card-body{padding:18px}
  .kpi-grid{gap:14px}
  .kpi-card{padding:18px}
  .kpi-value{font-size:27px}
}
@media(max-width:1120px){
  .sidebar{width:212px;min-width:212px}
  .logo-name{font-size:15px}
  .kpi-grid{grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}
  .dataTables_wrapper .dataTables_filter .field-box{width:170px}
  .search-bar input{width:150px}
  .topbar{padding:0 16px}
}
@media(max-width:1024px){
  .dashboard-row-grid { grid-template-columns: 1fr !important; }
  .dashboard-row-grid > div:first-child:empty { display: none !important; }
}
@media(max-width:768px){
  .sidebar{position:fixed;left:0;top:0;height:100vh;transform:translateX(-100%)}
  .sidebar.open{transform:translateX(0)}
  .sidebar-toggle-btn{display:flex}
  .topbar-menu-btn{display:flex}
  .kpi-grid{grid-template-columns:1fr 1fr !important}
  .page-content{padding:14px}
  .form-row{grid-template-columns:1fr}
  
  /* Dashboard specific responsiveness */
  .charts-grid, .dashboard-grid { grid-template-columns: 1fr; }
  .welcome-card { flex-direction: column !important; align-items: flex-start !important; gap: 16px !important; padding: 20px !important; }
  .welcome-actions { width: 100% !important; flex-wrap: wrap !important; gap: 8px !important; }
  .welcome-actions .btn { flex: 1 !important; justify-content: center !important; }
  .chart-header { flex-direction: column; gap: 12px; }

  /* Page Header Responsiveness */
  .page-header { flex-direction: column !important; align-items: stretch !important; gap: 12px !important; }
  .page-header-actions { width: 100% !important; justify-content: flex-start !important; flex-wrap: wrap !important; gap: 8px !important; }
  .page-header-actions .btn { flex: 1 !important; justify-content: center !important; }

  /* Table Headers & Inline Filters Responsiveness */
  .table-top { flex-direction: column !important; align-items: stretch !important; gap: 12px !important; padding: 12px 16px !important; }
  .table-left { display: flex; justify-content: space-between; align-items: center; gap: 8px; width: 100%; }
  .dataTables_filter { display: flex !important; flex-direction: column !important; align-items: stretch !important; gap: 8px !important; width: 100% !important; }
  .dataTables_filter label { margin: 0 !important; width: 100% !important; display: block !important; }
  .dataTables_filter .field-box { width: 100% !important; margin: 0 !important; }
  .dt-inline-filters { display: flex !important; width: 100% !important; gap: 8px !important; }
  .date-filter-box { flex: 1 !important; width: auto !important; }
  .dt-inline-filters button { flex: 0 0 auto !important; }

  /* Card Header Responsiveness */
  .card-header { flex-direction: column !important; align-items: stretch !important; gap: 12px !important; padding: 12px 16px !important; }
  .card-actions { width: 100% !important; display: flex !important; gap: 8px !important; }
  .card-actions .search-bar { flex: 1 !important; }
  .card-actions .search-bar input { width: 100% !important; }
  .card > .table-wrap { overflow-x: auto !important; }
  .booking-grid {
      grid-template-columns: 1fr !important;
  }
  .booking-grid > div {
      grid-column: span 1 !important;
  }

  /* ── App-like mobile bottom navigation ── */
  .mobile-bottom-nav{
    display:flex;position:fixed;left:0;right:0;bottom:0;z-index:60;
    background:var(--bg-card);border-top:1px solid var(--border);
    padding:6px 4px calc(6px + env(safe-area-inset-bottom,0px));
    box-shadow:0 -4px 16px rgba(0,0,0,0.07);
  }
  .mnav-item{
    flex:1;display:flex;flex-direction:column;align-items:center;gap:2px;
    background:none;border:none;cursor:pointer;text-decoration:none;
    color:var(--text-muted);font-size:10px;font-weight:600;font-family:inherit;
    padding:5px 2px;border-radius:10px;transition:color 0.15s,background 0.15s;-webkit-tap-highlight-color:transparent;
  }
  .mnav-item i{font-size:22px}
  .mnav-item.active{color:var(--hive-teal)}
  .mnav-item:active{background:var(--hive-teal-light)}

  /* Keep content clear of the fixed bottom nav — and of the home indicator under it, which
     the bar already pads itself for but the content behind it does not. */
  .page-content{padding-bottom:calc(78px + env(safe-area-inset-bottom,0px)) !important}

  /* ── Touch / app-feel refinements ── */
  html,body{overscroll-behavior-y:none}
  .table-wrap,.table-scroll{-webkit-overflow-scrolling:touch}
  .topbar{padding:0 14px;height:56px}
  .btn{min-height:42px}
  .btn-sm,.btn-xs{min-height:34px}
  /* 16px inputs prevent iOS auto-zoom on focus */
  .form-control,.form-select,input[type="text"],input[type="number"],input[type="password"],input[type="email"],input[type="date"],select,textarea{font-size:16px !important}
}
@media(max-width:480px){
  /* KPI cards stay two-up down here; the compact type that makes that fit lives at the
     very end of this file, after the later .kpi-label/.kpi-value rules that would
     otherwise win the cascade over anything written in this block. */
  .topbar-date{display:none}
  .topbar-user-info { display: none !important; }
}

.highlight-revenue { background: linear-gradient(135deg, var(--hive-teal) 0%, #334155 100%); color: #ffffff; border-color: transparent; }
.highlight-revenue .kpi-label, .highlight-revenue .kpi-sub { color: rgba(255, 255, 255, 0.7); }
.highlight-revenue .kpi-value { color: #ffffff; }
.highlight-revenue .trend.up { background: rgba(255, 255, 255, 0.15); color: #ffffff; }
.highlight-revenue:hover::after { background-color: #ffffff; }

/* DataTables Override */
.dataTables_wrapper { font-size: 13px; }
.table-top { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; border-bottom: 1px solid var(--border); background: var(--bg-card); border-radius: 12px 12px 0 0; }
.table-bottom { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; background: var(--bg-card); border-radius: 0 0 12px 12px; }

.dataTables_wrapper .dataTables_length { color: var(--text-muted); }
.dataTables_wrapper .dataTables_length select { border: 1px solid var(--border); border-radius: 6px; padding: 6px 32px 6px 12px !important; margin: 0 8px; outline: none; background-color: var(--bg-body); cursor: pointer; appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%2364748B' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 10px center; min-width: 70px; }
.dataTables_wrapper .dataTables_length select:focus { border-color: var(--hive-amber); box-shadow: 0 0 0 3px var(--hive-amber-light); }

/* ---- Toolbar control box ---------------------------------------------------------
   The one shape every toolbar control uses: a bordered pill holding a leading icon and
   a borderless input. The date-range picker and the list search box both wear it, so
   they are identical by construction rather than by two sets of matching numbers. */
.field-box {
    display: flex; align-items: center; gap: 7px;
    height: 34px; padding: 0 10px; box-sizing: border-box;
    border: 1px solid var(--border); border-radius: 7px; background: var(--bg-card);
    transition: border-color .18s ease, box-shadow .18s ease;
}
.field-box > i { font-size: 15px; color: var(--text-muted); flex-shrink: 0; line-height: 1; }
.field-box > input {
    border: none; background: transparent; outline: none; padding: 0; margin: 0;
    width: 100%; min-width: 0; height: 100%;
    font-family: inherit; font-size: 12.5px; color: var(--text-title);
    appearance: none; -webkit-appearance: none;
}
/* DataTables styles its filter input as `.dataTables_wrapper .dataTables_filter input`,
   which out-ranks `.field-box > input` on specificity — load order alone cannot beat it.
   The page scripts also move the date box inside .dataTables_filter, so both controls end
   up matching it. This selector out-ranks it for anything inside a .field-box. */
.dataTables_wrapper .dataTables_filter .field-box > input,
.dataTables_wrapper .dataTables_filter .field-box > input:focus {
    border: none; border-radius: 0; background-color: transparent;
    padding: 0; margin: 0; box-shadow: none; outline: none;
}
.field-box > input::placeholder { color: var(--text-muted); }
.field-box > input::-webkit-search-cancel-button { -webkit-appearance: none; }
.field-box:focus-within { border-color: var(--hive-amber); box-shadow: 0 0 0 3px var(--hive-amber-light); }
/* The date box opens a picker, so the whole pill is the hit target. */
.field-box.is-clickable, .field-box.is-clickable > input { cursor: pointer; }
.field-box.search-box { width: 240px; }
.field-box.date-box { width: 215px; }
/* Buttons and selects that sit in the same toolbar row, sized to match the boxes. */
.btn.btn-toolbar { height: 34px; padding: 0 14px; border-radius: 7px; font-size: 12.5px; background: var(--bg-card); border: 1px solid var(--border); color: var(--text-title); box-shadow: none; }
.btn.btn-toolbar:hover:not(:disabled) { border-color: var(--hive-amber); color: var(--hive-amber); background: var(--hive-amber-light); }
.btn.btn-toolbar-primary { height: 34px; padding: 0 14px; border-radius: 7px; font-size: 12.5px; }
.form-control.select-toolbar { height: 34px; width: 150px; padding: 0 28px 0 10px; border-radius: 7px; font-size: 12.5px; box-shadow: none; }

/* initDataTable wraps the bare <input> DataTables renders into a .field-box, so the
   filter needs no styling of its own beyond placement. */
.dataTables_wrapper .dataTables_filter { color: var(--text-title); font-weight: 400; }
.dataTables_wrapper .dataTables_filter label { margin: 0; display: flex; align-items: center; }
/* Focus is drawn on the .field-box wrapper via :focus-within, so the inner input has no
   ring of its own. */

/* Full height table layout */
.main-area { height: 100vh; display: flex; flex-direction: column; overflow: hidden; }
.page-content { flex: 1; display: flex; flex-direction: column; overflow-y: auto; padding-bottom: 20px; }
/* page-content is a column flex container, so a tall card would otherwise shrink to fit the
   viewport and .card's overflow:hidden would silently clip everything below the fold
   (e.g. Lab Settings lost its Branding Assets section and Save button). Keep natural height
   and let page-content scroll instead. */
.page-content > * { flex-shrink: 0; }
/* Only an initialised DataTables list fills the viewport height, so its toolbar and pager stay
   put and only the rows scroll. The three classes below are put on by initDataTable() in
   site.js, which is the one place every list in the application goes through.

   This used to be guessed here as `.card:has(table)`, and that caught every form that happens
   to carry a table as well — the permission matrix, the test parameters editor, the result
   entry sheet. Those keep their scroll box somewhere else (inside a <form>, inside .card-body)
   or have none at all, so the card was shrunk to the viewport, .card's overflow:hidden cut off
   everything below the fold, and nothing scrolled to reach it: permission rows past the first
   screenful were unreachable and the Save button on Add/Edit Test was simply not there.
   A card is only flexed now when the element that will actually scroll has been identified. */
.page-content > .card.dt-fill { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; margin-bottom: 0; }
/* Anything between the card and the scroll box: Test Library wraps its table in a <form>, so
   the box that scrolls is not always a direct child of the card. */
.dt-fill-chain { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
.table-wrap.dt-fill-scroll { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; border-radius: 0; overflow: auto; }

.dataTables_wrapper { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.dataTables_wrapper > .table-top { flex-shrink: 0; border-radius: 0; }
.dataTables_wrapper > .table-bottom { flex-shrink: 0; border-radius: 0 0 12px 12px; }
.dataTables_wrapper > .table-scroll { flex: 1; overflow: auto; min-height: 0; position: relative; }

table.dataTable { border-collapse: separate !important; border-spacing: 0; width: 100% !important; margin: 0 !important; }
table.dataTable thead th { border-bottom: none; border-top: none; border-left: none; border-right: none; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; font-size: 11.5px; padding: 14px 20px; background-color: var(--table-header-bg) !important; position: -webkit-sticky !important; position: sticky !important; top: 0 !important; z-index: 10 !important; color: var(--table-header-color) !important; }
table.dataTable thead th:first-child { border-top-left-radius: 8px; }
table.dataTable thead th:last-child { border-top-right-radius: 8px; }
table.dataTable tbody td { padding: 14px 20px; border-bottom: 1px solid var(--border); color: var(--text-body); }
table.dataTable tbody tr:hover td { background: rgba(12, 117, 111, 0.04) !important; }

.dataTables_wrapper .dataTables_info {
    color: var(--text-muted);
    font-size: 12px;
    font-weight: 500;
    padding-top: 0;
}
.dataTables_wrapper .dataTables_paginate {
    padding-top: 0;
    display: flex;
    align-items: center;
    gap: 6px;
}
.dataTables_wrapper .dataTables_paginate .paginate_button {
    border: 1px solid var(--border) !important;
    border-radius: 6px !important;
    padding: 6px 12px !important;
    background: var(--bg-card) !important;
    color: var(--text-body) !important;
    cursor: pointer;
    transition: all 0.2s ease;
    font-weight: 500;
    font-size: 12.5px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: var(--shadow);
    margin: 0;
    text-decoration: none;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.current {
    background: var(--hive-amber) !important;
    color: #ffffff !important;
    border-color: var(--hive-amber) !important;
    font-weight: 600;
    box-shadow: 0 2px 6px rgba(12, 117, 111, 0.2) !important;
}
.dataTables_wrapper .dataTables_paginate .paginate_button:hover:not(.current):not(.disabled) {
    border-color: var(--hive-amber) !important;
    color: var(--hive-amber) !important;
    background: var(--hive-amber-light) !important;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.disabled,
.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover {
    opacity: 0.4 !important;
    cursor: not-allowed !important;
    background: var(--bg-body) !important;
    color: var(--text-muted) !important;
    border-color: var(--border) !important;
}

.daterangepicker {
    font-family: 'Inter', sans-serif;
    border-radius: 12px !important;
    box-shadow: 0 8px 24px rgba(0,0,0,0.12) !important;
    border: 1px solid var(--border) !important;
    padding: 12px !important;
    background: var(--bg-card) !important;
    display: none;

    /* The popup is appended to <body>, outside any card, and the vendor sheet paints it in
       its own blues and greys. These five tokens are the whole palette of the calendar —
       every rule below reads them, so the two themes differ by this block alone. */
    --drp-hover: rgba(12,117,111,0.10);
    --drp-range-bg: rgba(12,117,111,0.13);
    --drp-range-fg: var(--hive-amber-dark);
    --drp-selected-bg: var(--hive-amber);
    --drp-selected-fg: #ffffff;
    --drp-today: var(--hive-gold-dark);
}
/* Lighten the fill and darken the lettering on it — the same inversion the rest of dark
   mode does with the brand teal, kept here so a selected day never prints white on mint. */
[data-theme="dark"] .daterangepicker {
    --drp-hover: rgba(72,179,170,0.16);
    --drp-range-bg: rgba(72,179,170,0.18);
    --drp-range-fg: #cdeeea;
    --drp-selected-fg: #04211f;
    --drp-today: var(--hive-gold);
}
/* The little pointer is drawn with borders, hard-coded to #ccc over #fff — a white nub
   hanging off a dark popup until it follows the surface it belongs to. */
.daterangepicker:before { border-bottom-color: var(--border) !important; }
.daterangepicker:after { border-bottom-color: var(--bg-card) !important; }
.daterangepicker.drop-up:before { border-top-color: var(--border) !important; }
.daterangepicker.drop-up:after { border-top-color: var(--bg-card) !important; }
/* Calendars appear only when 'Custom' is chosen (daterangepicker adds .show-calendar).
   Gated on .drp-open (set by initDateRange on show/hide): the library closes the popup
   with an inline display:none, which a bare `display:grid !important` here would beat —
   leaving the custom-range calendar stuck open after Done. */
.daterangepicker.drp-open.show-ranges.show-calendar {
    display: grid !important;
    grid-template-columns: 150px auto !important;
    grid-template-areas:
        "ranges cal-left"
        "ranges cal-right"
        "ranges buttons" !important;
    gap: 10px 16px !important;
    max-width: 96vw !important;
}
/* Default view = compact preset list only; no empty calendar space. */
.daterangepicker.show-ranges:not(.show-calendar){padding:6px !important;min-width:170px !important}
.daterangepicker.show-ranges:not(.show-calendar) .ranges{border-right:none !important;padding-right:0 !important}
.daterangepicker.show-ranges:not(.show-calendar) .drp-buttons{display:none !important}

/* Calendars visible only in custom (show-calendar) mode */
.daterangepicker.show-calendar .drp-calendar {
    display: block !important;
    padding: 0 !important;
    margin: 0 !important;
    clear: none !important;
    float: none !important;
    max-width: none !important;
}

.daterangepicker .drp-calendar.left {
    grid-area: cal-left !important;
}

.daterangepicker .drp-calendar.right {
    grid-area: cal-right !important;
}

/* Show the month calendars so dates can be picked visually */
.daterangepicker .calendar-table {
    display: block !important;
    padding: 6px 0 0 !important;
    border: none !important;
    background: transparent !important;
}
.daterangepicker .calendar-table table { width: 100% !important; margin: 0 !important; }
.daterangepicker .calendar-table th,
.daterangepicker .calendar-table td { min-width: 30px !important; height: 30px !important; font-size: 12px !important; }
.daterangepicker .calendar-table .next span,
.daterangepicker .calendar-table .prev span { border-color: var(--text-muted) !important; }
/* The app paints every `table thead th` with the solid brand band (see "A restyle that
   cannot reach every table" further down). The month grid is a real <table>, so it took
   that band too — and the weekday letters, muted grey by the rule below, ended up grey on
   dark teal. A calendar header is not a data-table header: it labels columns on the popup
   surface and carries no fill of its own. */
.daterangepicker .calendar-table thead th {
    background: transparent !important;
    border: none !important;
    text-transform: none !important;
    letter-spacing: 0 !important;
    padding: 3px 0 !important;
}
.daterangepicker .calendar-table th { color: var(--text-muted) !important; font-weight: 700 !important; font-size: 11.5px !important; }
.daterangepicker th.month { color: var(--text-title) !important; font-weight: 700 !important; font-size: 13px !important; padding-bottom: 6px !important; }
.daterangepicker .calendar-table td { color: var(--text-body) !important; }
.daterangepicker td.available:hover { background: var(--drp-hover) !important; color: var(--text-title) !important; }
/* The arrow is a 7px span built from borders; hovering it lit only that glyph, not the
   cell the pointer is actually over. The whole header cell takes the tint instead. */
.daterangepicker .calendar-table th.available:hover { background: var(--drp-hover) !important; border-radius: 6px !important; }
/* The band between the two ends was an 8% teal wash — at that strength the one thing a
   range picker exists to show was invisible on either theme. */
.daterangepicker td.in-range { background: var(--drp-range-bg) !important; color: var(--drp-range-fg) !important; border-radius: 0 !important; }
.daterangepicker td.off, .daterangepicker td.off.in-range { color: var(--text-muted) !important; opacity: 0.4 !important; background: transparent !important; }
.daterangepicker td.disabled { color: var(--text-muted) !important; opacity: 0.35 !important; }
/* Today is marked with the brand gold, the one accent the calendar has that cannot be
   confused with "selected" — a ring, not a fill, so it survives being selected too. */
.daterangepicker td.today:not(.active) { box-shadow: inset 0 0 0 1.5px var(--drp-today) !important; border-radius: 6px !important; font-weight: 700 !important; }
.daterangepicker td.start-date, .daterangepicker td.end-date { border-radius: 6px !important; }

/* Style the custom inputs container */
.daterangepicker .drp-calendar .daterangepicker_input {
    display: block !important;
    position: relative !important;
    padding: 0 !important;
    margin: 0 !important;
}

.daterangepicker .drp-calendar .daterangepicker_input input.input-mini {
    display: block !important;
    width: 100% !important;
    padding: 8px 36px 8px 12px !important;
    border: 1px solid var(--border) !important;
    border-radius: 8px !important;
    font-size: 13px !important;
    color: var(--text-title) !important;
    background: var(--bg-card) !important;
    outline: none !important;
}
.daterangepicker .drp-calendar .daterangepicker_input input.input-mini:focus {
    border-color: var(--hive-amber) !important;
    box-shadow: 0 0 0 2px var(--hive-amber-light) !important;
}

/* Unicode Tabler icon for calendar icon */
.daterangepicker .drp-calendar .daterangepicker_input i.glyphicon-calendar,
.daterangepicker .drp-calendar .daterangepicker_input i.fa-calendar {
    position: absolute !important;
    right: 12px !important;
    top: 50% !important;
    transform: translateY(-50%) !important;
    color: var(--text-muted) !important;
    pointer-events: none !important;
    display: inline-block !important;
    font-family: "tabler-icons" !important;
    font-style: normal !important;
    font-size: 16px !important;
    line-height: 1 !important;
}
.daterangepicker .drp-calendar .daterangepicker_input i.glyphicon-calendar::before,
.daterangepicker .drp-calendar .daterangepicker_input i.fa-calendar::before {
    content: "\eb91" !important; /* ti ti-calendar unicode */
}

/* CUSTOM RANGE title & From/To labels */
.daterangepicker .drp-calendar.left::before {
    content: "CUSTOM RANGE" !important;
    display: block !important;
    font-size: 10px !important;
    font-weight: 700 !important;
    color: var(--text-muted) !important;
    text-transform: uppercase !important;
    letter-spacing: 1px !important;
    margin-bottom: 12px !important;
    text-align: left !important;
}

.daterangepicker .drp-calendar.left .daterangepicker_input::before {
    content: "From" !important;
    display: block !important;
    font-size: 12px !important;
    color: var(--text-muted) !important;
    margin-bottom: 6px !important;
    text-align: left !important;
}

.daterangepicker .drp-calendar.right .daterangepicker_input::before {
    content: "To" !important;
    display: block !important;
    font-size: 12px !important;
    color: var(--text-muted) !important;
    margin-bottom: 6px !important;
    text-align: left !important;
}

/* Preset ranges styling on the left */
.daterangepicker .ranges {
    grid-area: ranges !important;
    margin: 0 !important;
    border-right: 1px solid var(--border) !important;
    padding-right: 12px !important;
    float: none !important;
}

.daterangepicker .ranges ul {
    list-style: none !important;
    padding: 0 !important;
    margin: 0 !important;
    width: 100% !important;
}

.daterangepicker .ranges ul li {
    padding: 8px 12px !important;
    font-size: 13px !important;
    font-weight: 500 !important;
    color: var(--text-body) !important;
    border-radius: 6px !important;
    cursor: pointer !important;
    transition: all 0.15s !important;
    margin-bottom: 2px !important;
    text-align: left !important;
}

.daterangepicker .ranges ul li:hover {
    background: var(--drp-hover) !important;
    color: var(--text-title) !important;
}

.daterangepicker .ranges ul li.active {
    background: var(--drp-selected-bg) !important;
    color: var(--drp-selected-fg) !important;
}

/* Done Button and Buttons area */
.daterangepicker .drp-buttons {
    grid-area: buttons !important;
    padding: 0 !important;
    margin: 0 !important;
    border-top: none !important;
    display: flex !important;
    justify-content: flex-end !important;
    align-items: center !important;
    float: none !important;
    clear: none !important;
}

.daterangepicker .drp-buttons .cancelBtn,
.daterangepicker .drp-buttons .drp-selected {
    display: none !important;
}

.daterangepicker .drp-buttons .applyBtn {
    display: block !important;
    width: 100% !important;
    padding: 10px !important;
    background: var(--drp-selected-bg) !important;
    color: var(--drp-selected-fg) !important;
    border: none !important;
    border-radius: 8px !important;
    font-size: 14px !important;
    font-weight: 600 !important;
    text-align: center !important;
    cursor: pointer !important;
    transition: background 0.15s !important;
    margin: 0 !important;
    box-shadow: 0 2px 6px rgba(12, 117, 111, 0.2) !important;
}

.daterangepicker .drp-buttons .applyBtn:hover {
    background: var(--hive-amber-dark) !important;
}

.daterangepicker td.active, .daterangepicker td.active:hover {
    background-color: var(--drp-selected-bg) !important;
    color: var(--drp-selected-fg) !important;
    font-weight: 600 !important;
}

.daterangepicker .ranges ul li[data-range-key="Custom"] {
    display: block !important;
}

/* ── Sidebar Footer Actions Styling ── */
.sidebar-footer-actions {
    display: flex;
    gap: 6px;
    align-items: center;
}
.sidebar-footer-actions .icon-btn-sm {
    background: none !important;
    border: none !important;
    padding: 6px !important;
    margin: 0 !important;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: rgba(255, 255, 255, 0.6) !important;
    transition: color 0.15s ease, background-color 0.15s ease, transform 0.15s ease;
    text-decoration: none !important;
    border-radius: 6px;
    width: 28px;
    height: 28px;
}
.sidebar-footer-actions .icon-btn-sm i {
    font-size: 15px !important;
    color: inherit !important;
    opacity: 1 !important;
    width: auto !important;
    text-align: center;
}
.sidebar-footer-actions .icon-btn-sm:hover {
    color: #ffffff !important;
    background-color: rgba(255, 255, 255, 0.08) !important;
    transform: translateY(-1px);
}

/* ── Dark Mode UI Enhancements ── */
[data-theme="dark"] .alert-success { color: #34d399 !important; }
[data-theme="dark"] .alert-danger { color: #f87171 !important; }
[data-theme="dark"] .alert-warning { color: #fbbf24 !important; }

/* Sleek custom scrollbars for dark mode */
[data-theme="dark"] ::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}
[data-theme="dark"] ::-webkit-scrollbar-track {
    background: #0b0f19;
}
[data-theme="dark"] ::-webkit-scrollbar-thumb {
    background: #232c45;
    border-radius: 4px;
}
[data-theme="dark"] ::-webkit-scrollbar-thumb:hover {
    background: #334155;
}

/* ============================================================================
   Mobile list cards + form stacking (app-like feel on phones, <=640px)
   ============================================================================ */
@media(max-width:640px){
  /* Server-side DataTables become stacked, labelled cards */
  table.dataTable thead{display:none}
  table.dataTable,table.dataTable tbody,table.dataTable tbody tr,table.dataTable tbody td{display:block;width:auto}
  table.dataTable{border:0}
  table.dataTable tbody tr{margin:0 10px 12px;border:1px solid var(--border);border-radius:12px;background:var(--bg-card);box-shadow:var(--shadow);overflow:hidden}
  table.dataTable tbody tr:hover{background:var(--bg-card)}
  table.dataTable tbody td{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:9px 14px !important;border:0 !important;border-bottom:1px solid var(--border) !important;text-align:right;white-space:normal;min-height:0}
  table.dataTable tbody tr td:last-child{border-bottom:0 !important}
  table.dataTable tbody td::before{content:attr(data-label);font-weight:700;font-size:10.5px;text-transform:uppercase;letter-spacing:0.4px;color:var(--text-muted);text-align:left;flex:0 0 auto;margin-right:auto}
  /* hide the row-index column and unlabeled (action) header on cards */
  table.dataTable tbody td[data-label="#"]{display:none}
  table.dataTable tbody td[data-label=""]{justify-content:flex-end}
  table.dataTable tbody td[data-label=""]::before{display:none}
  table.dataTable tbody td .table-actions{gap:6px}
  /* no horizontal scroll needed once carded */
  .table-scroll{overflow-x:hidden !important}
  .table-bottom{flex-direction:column !important;gap:10px !important;text-align:center}
  .dataTables_paginate{display:flex;flex-wrap:wrap;justify-content:center;gap:4px}
  .dataTables_info{text-align:center}

  /* Booking: patient 12-column grid stacks to a single column */
  .booking-grid{grid-template-columns:1fr !important}
  .booking-grid>*{grid-column:auto !important}
}

/* ============================================================================
   Mobile hardening (<=768px): kill page-level horizontal overflow, make search
   boxes and stacked layouts full-width so nothing spills off-screen on phones.
   ============================================================================ */
@media(max-width:768px){
  /* `clip`, not `hidden`. Both stop sideways spill, but `hidden` makes the element a scroll
     container, and a scroll container with `overflow-y:visible` has that visible computed up to
     `auto` — so this one declaration quietly turned html AND body into y-scrollers nested inside
     the viewport's own. Three scrollers deep, the gesture lands on whichever one the finger is
     over, most of which have nothing to scroll, and the page reads as frozen. `clip` clips
     without ever becoming a scroll container and leaves overflow-y alone, which is what it was
     added to the spec for. `hidden` stays first as the fallback for Safari before 16. */
  html,body{overflow-x:hidden;overflow-x:clip;max-width:100%}
  .main-area,.page-content{max-width:100%;min-width:0}
  .card{max-width:100%}
  /* Two-column booking layout: columns never force a min width on phones */
  .booking-layout{flex-direction:column !important;align-items:stretch !important}
  .booking-left,.booking-right{width:100% !important;min-width:0 !important;max-width:100% !important}
  /* The billing panel is a sticky, viewport-tall scroll box on a desktop, beside the form. Stacked
     under the form on a phone it is just a panel, but it kept the sticky position, the 100vh cap
     and its own overflow — so it pinned itself over most of the screen and swallowed every drag
     that started on it. Width alone was not enough to undo the desktop layout. */
  .booking-right{position:static !important;max-height:none !important;overflow:visible !important}
  /* Search inputs (DataTables + custom) go full width, no fixed min-width */
  .dataTables_wrapper .dataTables_filter,
  .dataTables_wrapper .dataTables_filter label{width:100% !important;margin:0 !important}
  .dataTables_wrapper .dataTables_filter .field-box{width:100% !important;min-width:0 !important;margin-left:0 !important}
  .search-bar{width:100% !important}
  .search-bar input{width:100% !important}
  /* Wide tables/panels scroll inside their own box, not the page */
  .table-wrap,.table-scroll,.scrollable-table-container{max-width:100%;-webkit-overflow-scrolling:touch}
  /* Filter toolbars wrap instead of overflowing */
  .dt-inline-filters{flex-wrap:wrap !important}
  /* ── One scroller on a phone: the page ──
     The desktop layout is a 100vh shell with the content area scrolling inside it, which is
     wrong on a handset for three separate reasons: 100vh is the *tall* viewport on mobile
     Safari and Chrome, not the visible one, so the last rows of a long screen sat permanently
     under the address bar with the inner box reporting itself fully scrolled; a nested
     overflow box fights the address bar collapsing and swallows the scroll gesture; and
     `position:sticky` inside it has nothing useful to stick to. The shell grows with its
     content instead and the document scrolls, which is what a phone browser is built for. */
  .app-layout{min-height:100vh;min-height:100dvh}
  .sidebar{height:100vh;height:100dvh}
  .main-area{height:auto;min-height:100vh;min-height:100dvh;overflow:visible}
  .page-content{display:block;overflow:visible}

  /* Table cards take natural height on phones (no huge empty stretch when few rows); the
     page scrolls instead of an inner table scroll. The list still scrolls sideways inside
     its own box, because html/body are overflow-x:hidden above and a wide table would
     otherwise be cut off with no way to reach the rest of it. */
  .page-content > .card.dt-fill,
  .dt-fill-chain{display:block !important;flex:0 0 auto !important;min-height:0 !important}
  .table-wrap.dt-fill-scroll{display:block !important;flex:0 0 auto !important;
    overflow-x:auto !important;overflow-y:visible !important}
  .dataTables_wrapper{display:block !important}

  /* Now that the document is the scroller, anything sticky sticks to the viewport — and the
     top bar is sticky there too, at 56px on a phone, with a higher z-index. Without the
     offset a list header or the result-entry summary slides underneath it and disappears. */
  table.dataTable thead th{top:56px !important}
  .entry-summary{top:56px}

  /* Tables that are not DataTables lists keep every column on a phone (the permission
     matrix, the test parameters editor), so the padding is what gives way, not the content. */
  table.data-table thead th,table.data-table tbody td{padding:10px 10px}
  table.data-table thead th:first-child,table.data-table tbody td:first-child{padding-left:12px}
  table.data-table thead th:last-child,table.data-table tbody td:last-child{padding-right:12px}
}

/* ── Number inputs: no spinner arrows ──
   The little up/down arrows eat width in already narrow amount boxes and invite
   click-stepping through a discount or a payment one rupee at a time. Typing and the
   keyboard ↑/↓ keys still work; only the mouse control is gone. */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}


/* ══════════════════════════════════════════════════════════════════════════════════════
   Responsive, touch and legibility pass
   ══════════════════════════════════════════════════════════════════════════════════════ */

/* ── Dashboard KPI cards ──
   These used to carry every value inline on the element, which silently outranked the
   .kpi-card / .kpi-value rules above and the responsive overrides written for them — so
   the cards kept 24px padding and a 10px label at every width, and the sparkline collided
   with the figure beside it on a 1366px laptop. The classes own the layout now. */
.kpi-top{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;width:100%}
.kpi-ident{display:flex;gap:14px;align-items:center;min-width:0}
.kpi-icon{width:44px;height:44px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:20px;flex-shrink:0}
.kpi-icon--teal{background:#e8f4f3;color:#10b981}
.kpi-icon--amber{background:#fef6e7;color:#f59e0b}
.kpi-text{display:flex;flex-direction:column;min-width:0}
.kpi-text .kpi-label{margin-bottom:4px;letter-spacing:.6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}
.kpi-text .kpi-value{margin-bottom:0;line-height:1.05}
.kpi-link{font-size:11.5px;color:var(--hive-amber);font-weight:600;text-decoration:none}
.kpi-link:hover{text-decoration:underline}
/* Below this the four-up grid leaves the label and figure too little room to sit beside a
   sparkline. It is decoration — the trend chip underneath states the same movement in
   words — so it is what gives way. */

/* ── Toolbar date box ──
   Fixed at 215px, which is narrower than the range it displays once the phone font floor
   pushes it to 16px, so the end of "01 Aug 2026 - 24 Aug 2026" was clipped. */
@media(max-width:768px){
  .field-box.date-box{width:100% !important;min-width:0}
  .fin-filter form{display:flex;flex-wrap:wrap;gap:10px}
  .fin-filter .field-box.date-box{flex:1 1 100%}
  .fin-filter .select-toolbar{flex:1 1 140px;min-width:0}
}

/* ── Booking: the test grid on a 1366px laptop ──
   Between the point where the two columns stack (1024px) and roughly 1440px the grid is
   wider than the panel holding it, so the Action column sat outside the visible area with
   nothing to say it was there. Tighter cells close most of the gap; a scrollbar that is
   always drawn covers the rest instead of hiding it. */
@media(min-width:1025px) and (max-width:1440px){
  .scrollable-table-container table th,
  .scrollable-table-container table td{padding-left:8px !important;padding-right:8px !important}
}
.scrollable-table-container{scrollbar-width:thin;scrollbar-color:var(--border) transparent}
.scrollable-table-container::-webkit-scrollbar{height:8px}
.scrollable-table-container::-webkit-scrollbar-track{background:transparent}
.scrollable-table-container::-webkit-scrollbar-thumb{background:var(--border);border-radius:4px}
.scrollable-table-container::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}

/* ── Touch targets ──
   Keyed off pointer:coarse rather than a width, so a small laptop keeps its compact
   controls while a large tablet still gets thumb-sized ones. 44px is the floor below
   which a mis-tap stops being the user's fault. */
@media(pointer:coarse){
  .btn-icon,.icon-btn-sm,.alert-close,.sidebar-toggle-btn,.topbar-menu-btn{
    min-width:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:center;
  }
  .table-actions{gap:6px;flex-wrap:nowrap}
  .table-actions .btn-icon{min-width:40px;min-height:40px}
  .nav-item{min-height:44px;padding-top:10px;padding-bottom:10px}
  .mnav-item{min-height:52px}
  input[type=checkbox],input[type=radio]{width:20px;height:20px;accent-color:var(--hive-amber)}
  /* The permission matrix is nothing but checkboxes in a dense grid; each needs a cell big
     enough that a mis-tap cannot quietly grant the wrong right. */
  .perm-table td,.perm-matrix td{height:48px}
  .perm-table td label,.perm-matrix td label{display:flex;align-items:center;justify-content:center;min-height:44px;margin:0}
}

/* ── Legible minimum on a handset ──
   9px and 9.5px read as decoration rather than information at arm's length. */
@media(max-width:768px){
  .section-label{font-size:11px;letter-spacing:.8px}
  .mnav-item{font-size:11px}
  .overview-item span,.fin-label,.mui-hint,.brand-tile-foot small,.brand-word-tag,.empty span{font-size:11.5px}
  .mui-field label,.mui-select-field label{font-size:11.5px}
  .dataTables_wrapper table th{font-size:11.5px}
}

/* ── Form scaffolding ── */
.form-card{max-width:760px}
.form-actions{display:flex;gap:10px;align-items:center;margin-top:20px;padding-top:18px;border-top:1px solid var(--border);flex-wrap:wrap}
@media(max-width:768px){
  .form-card{max-width:100%}
  .form-actions .btn{flex:1 1 auto;justify-content:center}
}

/* ── Multi-select picker (package tests) ──
   A lab can carry hundreds of tests, so the list is filtered rather than scrolled. */
.picker-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:8px}
.picker-count{font-size:11.5px;font-weight:600;color:var(--hive-amber);background:var(--hive-amber-light);padding:3px 10px;border-radius:20px;white-space:nowrap}
.picker-toolbar{display:flex;gap:8px;margin-bottom:10px;flex-wrap:wrap}
.picker-search{position:relative;flex:1 1 220px;min-width:0}
.picker-search > i{position:absolute;left:11px;top:50%;transform:translateY(-50%);font-size:15px;color:var(--text-muted);pointer-events:none}
.picker-search input{padding-left:34px}
.picker-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:8px;max-height:340px;overflow-y:auto;padding:4px;border:1px solid var(--border);border-radius:var(--radius);background:var(--bg-body)}
.picker-option{display:flex;align-items:center;gap:10px;padding:9px 11px;border:1px solid var(--border);border-radius:7px;background:var(--bg-card);cursor:pointer;font-size:12.5px;transition:border-color .15s,background .15s}
.picker-option:hover{border-color:var(--hive-amber);background:var(--hive-amber-light)}
.picker-option:has(input:checked){border-color:var(--hive-amber);background:var(--hive-amber-light)}
.picker-option input{accent-color:var(--hive-amber);flex-shrink:0;margin:0}
.picker-option-text{display:flex;flex-direction:column;min-width:0;line-height:1.3}
.picker-option-text small{font-size:11px;color:var(--text-muted);font-weight:500}
.picker-empty{font-size:12.5px;color:var(--text-muted);margin:10px 2px 0;text-align:center}
@media(max-width:768px){
  .picker-grid{grid-template-columns:1fr;max-height:none}
  .picker-toolbar .btn{flex:1 1 auto;justify-content:center}
}

/* ── Field-level validation ── */
.field-validation-error{display:block;margin-top:5px;font-size:11.5px;font-weight:500;color:var(--danger)}

/* ── Permission matrix ──
   Ten columns of checkboxes. Each box fills its cell through a label so the target is the
   cell, not the 16px square that used to sit in the middle of it. */
.perm-table td{text-align:center;vertical-align:middle}
.perm-table td.perm-page{text-align:left;font-weight:600;color:var(--text-title);white-space:nowrap}
.perm-cell{display:flex;align-items:center;justify-content:center;min-height:34px;margin:0;cursor:pointer;border-radius:6px;transition:background .12s}
.perm-cell:hover{background:var(--hive-amber-light)}
.perm-check{width:17px;height:17px;cursor:pointer;accent-color:var(--hive-amber);margin:0}
.perm-check--danger{accent-color:var(--danger)}
.perm-check--teal{accent-color:var(--hive-teal)}
.perm-max{width:66px;text-align:center;padding:4px 6px;margin:0 auto;height:30px}
/* A right that does not apply to this page reads as an em dash rather than an unticked box
   the admin might otherwise keep trying to tick. */
.perm-na{color:var(--text-muted);opacity:.5;font-size:13px}
@media(pointer:coarse){
  .perm-cell{min-height:44px}
  .perm-check{width:20px;height:20px}
  .perm-max{height:38px;width:70px}
}
/* Ten columns of 44px targets do not fit a phone, so the matrix scrolls sideways inside its
   .table-wrap. The page name has to travel with the row, or you are ticking rights on a row
   you can no longer name. A floor on the width keeps the columns legible rather than letting
   them crush to fit; the shadow is what says the first column is pinned and not just wide. */
.perm-table{min-width:720px}
.perm-table thead th:first-child,
.perm-table tbody td:first-child{position:sticky;left:0}
.perm-table thead th:first-child{z-index:3;background:var(--table-header-bg)}
.perm-table tbody td:first-child{z-index:2;background:var(--bg-card);box-shadow:1px 0 0 var(--border)}
.perm-table tbody tr:hover td:first-child{background:var(--hive-teal-light)}

/* ── Interpretation rule editor ──
   These views were written against Bootstrap's grid and utilities, which this app does not
   ship, so the two columns stacked and the hint panel had no styling at all. Named for what
   they are instead of borrowed from a framework that is not here. */
.interp-grid{display:grid;grid-template-columns:5fr 7fr;gap:20px;align-items:start}
.interp-col{min-width:0}
.interp-template{display:flex;flex-direction:column;height:100%}
.interp-template textarea{flex:1;min-height:200px;resize:vertical}
.interp-rules{margin-top:20px}
.interp-hint{padding:14px 18px;background:var(--bg-body);border-top:1px solid var(--border);color:var(--text-muted);font-size:12.5px;margin:0;display:flex;align-items:flex-start;gap:8px}
.interp-hint i{color:var(--info);font-size:15px;flex-shrink:0;margin-top:1px}
@media(max-width:900px){.interp-grid{grid-template-columns:1fr}}

/* ── Utilities the views already ask for ──
   .text-danger is used by four views for required-field markers and inline errors and was
   never defined, so those asterisks rendered in body colour. */
.text-danger{color:var(--danger)}
.form-hint{display:block;margin-top:5px;font-size:11.5px;color:var(--text-muted);line-height:1.45}
.form-control-sm,.form-select-sm{height:32px;padding:5px 9px;font-size:12.5px}
@media(pointer:coarse){.form-control-sm,.form-select-sm{height:40px;font-size:16px}}

/* ── Floating labels on a handset ──
   The raised state is set by several selectors carrying more specificity than a plain
   `.mui-field label`, so the phone floor has to match them rather than out-order them. */
@media(max-width:768px){
  .mui-field > :is(.form-control,.mui-input,.mui-select,.mui-textarea):focus ~ label,
  .mui-field > :is(.form-control,.mui-input,.mui-textarea):not(:placeholder-shown) ~ label,
  .mui-field > :is(select.form-control,.mui-select) ~ label,
  .mui-field.mui-select-field > label,
  .mui-field.is-raised > label{font-size:11.5px}
}

/* ── The last of the small targets ──
   Everything a finger reaches for that the first pass missed: the breadcrumb's home icon,
   DataTables' own pagination (it ships its own sizing), the row kebab menus, the extra-small
   row buttons, and the day-book's quick range links. */
.breadcrumb-home{display:inline-flex;align-items:center;justify-content:center;border-radius:8px;color:var(--text-muted);text-decoration:none;transition:opacity .15s}
.breadcrumb-home:hover{opacity:.75}
@media(pointer:coarse){
  .breadcrumb-home{min-width:40px;min-height:40px;margin-left:-8px}
  .dataTables_wrapper .paginate_button{min-height:44px;min-width:44px;display:inline-flex;align-items:center;justify-content:center}
  .row-menu-btn{min-width:40px;min-height:40px;display:inline-flex;align-items:center;justify-content:center}
  .btn-xs,.btn-delete-row{min-width:40px;min-height:40px}
  .db-quick a{min-height:44px;display:inline-flex;align-items:center;padding:0 12px}
}

/* ── Three that lost on specificity ──
   Each of these is already stated above, but a longer selector elsewhere was winning: the
   preview caption is set by `.brand-preview .empty span`, DataTables sizes its own pager, and
   the permission label was only as wide as its own content rather than the cell it fills. */
@media(max-width:768px){
  .brand-preview .empty span{font-size:11.5px}
}
.perm-cell{width:100%}
@media(pointer:coarse){
  .dataTables_wrapper .dataTables_paginate .paginate_button{min-width:44px;min-height:44px;box-sizing:border-box}
}

/* ── Standalone action links and the trend range ──
   These carried their sizing inline, which no stylesheet rule could reach. As classes they
   pick up a comfortable target on touch without changing how they read on a desktop. */
.link-action{display:inline-flex;align-items:center;gap:4px;font-size:12.5px;font-weight:600;color:var(--hive-amber);text-decoration:none}
.link-action:hover{text-decoration:underline}
.link-action i{font-size:14px}
.trend-range{height:32px;font-size:12px;padding:0 8px;border-radius:6px;border:1px solid var(--border);width:118px;background:var(--bg-card);color:var(--text-title)}
@media(pointer:coarse){
  .link-action,.kpi-link{min-height:44px;padding:0 2px}
  .trend-range{height:44px;font-size:16px;width:100%;min-width:140px}
}
/* The label can only fill the cell's content box, so on touch the cell gives up its side
   padding rather than leaving a 33px target inside a 61px cell. */
@media(pointer:coarse){
  .perm-table td:not(.perm-page){padding-left:3px;padding-right:3px}
}

/* ── Native controls follow the theme ──
   Checkboxes, scrollbars, date pickers and Chrome's autofill highlight are drawn by the
   browser, not by us. Without this they stay light on a dark page. */
:root{color-scheme:light}
[data-theme="dark"]{color-scheme:dark}

/* ── Toolbar date range on a handset ──
   `flex:1` let the box shrink to 65px and swallow two thirds of "01 Aug 2026 - 24 Aug 2026"
   instead of wrapping onto its own line, which the toolbar already allows. */
@media(max-width:768px){
  .dt-inline-filters .date-filter-box{flex:1 1 100% !important;width:100% !important;min-width:0}
}

/* ══════════════════════════════════════════════════════════════════════════════════════
   Sidebar
   ══════════════════════════════════════════════════════════════════════════════════════ */

/* ── "There is more below" ──
   Eighteen destinations do not fit a 768px laptop, so the last item was being cut by the
   viewport edge with nothing to say so. A sticky fade sits over the bottom of the scroll
   box; when the menu does fit, it is a gradient from the panel colour to transparent drawn
   on the panel colour, so it disappears on its own. */
.sidebar::after{
  content:'';
  position:sticky;
  bottom:0;
  z-index:4;
  display:block;
  flex-shrink:0;
  height:26px;
  margin-top:-26px;              /* overlays the last item instead of adding height */
  background:linear-gradient(to top, var(--bg-sidebar) 30%, transparent);
  pointer-events:none;
}

/* ── Group headings ──
   9.5px at 38% opacity on a dark panel is below the point where a heading still does its
   job of separating one group from the next. */
.section-label{
  font-size:10.5px;
  color:rgba(255,255,255,0.46);
  letter-spacing:1.2px;
  padding:0 12px 6px;
}
.sidebar-section.in-section > .section-label{color:rgba(255,255,255,0.72)}
.sidebar-section + .sidebar-section{margin-top:12px}

/* ── Items ──
   The icon carries as much of the scan as the word does, so it comes up with the label on
   hover rather than staying at three-quarter strength. */
.nav-item{transition:background .15s ease,color .15s ease}
.nav-item i{opacity:0.82;transition:opacity .15s ease,color .15s ease}
.nav-item:hover{background:rgba(255,255,255,0.08)}
.nav-item:hover i{opacity:1}
.nav-item:active{background:rgba(255,255,255,0.12)}

/* The current page: a lighter slab, a gold edge, and an icon in the same gold so the row
   reads as selected from the icon column alone when the panel is scanned quickly. */
.nav-item.active{background:rgba(255,255,255,0.14) !important;box-shadow:inset 0 0 0 1px rgba(255,255,255,0.06)}
.nav-item.active i{color:var(--hive-gold,#FDCF6F) !important;opacity:1}
.nav-item.active::before{height:60%;min-height:16px;width:3px;background:var(--hive-gold,#FDCF6F)}

/* ── Header ──
   Sticky already; a hairline that only appears once the list has scrolled under it keeps
   the resting state clean. */
.sidebar-logo{border-bottom-color:transparent;transition:border-color .18s ease,box-shadow .18s ease}
.sidebar:not([data-at-top="true"]) .sidebar-logo{
  border-bottom-color:rgba(255,255,255,0.10);
  box-shadow:0 6px 12px -8px rgba(0,0,0,0.5);
}
/* Once the list is at its end there is nothing left to hint at, so the fade lifts rather
   than leaving the final item permanently dimmed under it. */
.sidebar[data-at-bottom="true"]::after{opacity:0}
.sidebar::after{transition:opacity .18s ease}
/* The sidebar block above restates .section-label unconditionally, which lands after the
   handset floor set earlier in this file — so the floor is repeated here to win on order. */
@media(max-width:768px){
  .section-label{font-size:11px}
}

/* ══════════════════════════════════════════════════════════════════════════════════════
   Dark mode
   ══════════════════════════════════════════════════════════════════════════════════════ */

/* ── Fields read as recessed, not as part of the card ──
   In light mode a white field on a grey card separates itself. Dark mode has no lighter
   fill to reach for, so the field goes darker than its card and the border does the rest. */
[data-theme="dark"] .form-control,
[data-theme="dark"] .form-select,
[data-theme="dark"] .field-box,
[data-theme="dark"] textarea,
[data-theme="dark"] input[type="text"],
[data-theme="dark"] input[type="number"],
[data-theme="dark"] input[type="password"],
[data-theme="dark"] input[type="email"],
[data-theme="dark"] input[type="date"],
[data-theme="dark"] input[type="search"]{
  background-color:var(--bg-input);
  border-color:var(--border);
  color:var(--text-title);
}
[data-theme="dark"] .form-control::placeholder,
[data-theme="dark"] textarea::placeholder{color:var(--text-muted);opacity:1}
[data-theme="dark"] .form-control:focus,
[data-theme="dark"] .form-select:focus,
[data-theme="dark"] textarea:focus{
  border-color:var(--hive-teal);
  box-shadow:0 0 0 3px rgba(12,117,111,0.28);
  background-color:#0b1f21;
}
/* Chrome paints its own near-white slab over an autofilled field otherwise. */
[data-theme="dark"] input:-webkit-autofill,
[data-theme="dark"] input:-webkit-autofill:focus{
  -webkit-text-fill-color:var(--text-title);
  -webkit-box-shadow:0 0 0 1000px var(--bg-input) inset;
  caret-color:var(--text-title);
}

/* ── Row action buttons ──
   Four bordered boxes per row, ten rows to a page: on a dark ground those outlines added up
   to more visual weight than the data. The border only appears under the pointer. */
[data-theme="dark"] .btn-icon{
  background:transparent;
  border-color:transparent;
  box-shadow:none;
  color:var(--text-body);
}
[data-theme="dark"] .btn-icon:hover{
  background:rgba(255,255,255,0.07);
  border-color:var(--border);
  color:var(--text-title);
}

/* ── Surfaces ──
   Cards lift by being lighter than the page, which is what dark elevation is; the heavy
   drop shadows only muddied the gap. */
[data-theme="dark"] .card,
[data-theme="dark"] .kpi-card,
[data-theme="dark"] .chart-card{
  box-shadow:0 1px 2px rgba(0,0,0,0.35);
  border-color:var(--border);
}
[data-theme="dark"] .card:hover,
[data-theme="dark"] .kpi-card:hover{box-shadow:0 6px 20px rgba(0,0,0,0.42)}
[data-theme="dark"] .topbar{
  background:var(--bg-card);
  border-bottom-color:var(--border);
  box-shadow:none;
}
/* Zebra striping and hover need to stay subtle against a low-contrast ground. */
[data-theme="dark"] .data-table tbody tr:hover{background:rgba(255,255,255,0.035)}
[data-theme="dark"] .table-top,
[data-theme="dark"] .table-bottom{background:var(--bg-card);border-color:var(--border)}
[data-theme="dark"] .sidebar{border-right-color:rgba(255,255,255,0.07)}
[data-theme="dark"] .interp-hint,
[data-theme="dark"] .picker-grid{background:rgba(0,0,0,0.22)}
[data-theme="dark"] .picker-option{background:var(--bg-input)}

/* ── KPI label truncation ──
   The sparkline was kept down to 1400px, but the four-up grid still gives each card only
   ~265px at 1440 — not enough for the icon, the label and a chart — so the label was being
   cut to "TODAY'S PA…". It now waits for a width where all three genuinely fit. */
/* A one-pixel light edge along the top of each surface. Dark UIs get their depth from a lit
   edge rather than from a cast shadow, which has nothing to fall on. */
[data-theme="dark"] .card,
[data-theme="dark"] .kpi-card,
[data-theme="dark"] .chart-card,
[data-theme="dark"] .topbar{
  box-shadow:inset 0 1px 0 rgba(255,255,255,0.045), 0 1px 2px rgba(0,0,0,0.35);
}

/* ── The brand teal is a fill colour, not a text colour ──
   #0C756F is right on white. On a dark page the same value lands at 3.1:1 as text, and it is
   used as text everywhere — links, floating labels, section headings, "From 16 patients →",
   invoice numbers. Both the stylesheet and the inline styles in the views read it through
   these tokens, so lifting the tokens fixes every one of them at once.

   Material's rule for dark themes applies: lighten the primary and put dark lettering on it.
   The handful of places that fill with the token and print white on top are listed below. */
[data-theme="dark"]{
  --hive-amber:#48b3aa;
  --hive-teal:#48b3aa;
  --hive-amber-dark:#6fd0c6;
  --hive-teal-mid:#6fd0c6;
}
[data-theme="dark"] .btn-primary,
[data-theme="dark"] .btn-teal{color:#04211f}
[data-theme="dark"] .btn-primary:hover,
[data-theme="dark"] .btn-teal:hover{color:#04211f}
[data-theme="dark"] .topbar-profile .user-avatar{color:#04211f !important}
[data-theme="dark"] .dataTables_wrapper .dataTables_paginate .paginate_button.current{color:#04211f !important}
[data-theme="dark"] .daterangepicker .ranges ul li.active{color:#04211f !important}
[data-theme="dark"] .daterangepicker .drp-buttons .applyBtn{color:#04211f !important}

/* â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
   Result entry â€” the technician's screen
   â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
   The markup used to carry its own fixed column widths inline and relied on a horizontal
   scrollbar below 1000px, which on a handset put the result box off-screen while the parameter
   name stayed visible â€” the one pairing that has to stay together. Below 900px each row becomes
   a card with the cell labels supplied from data-label, so nothing scrolls sideways and the
   parameter, its reference interval and its input are read as one block.
   â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â• */

.result-entry-body{padding:0;overflow-x:auto}
.result-entry-table{width:100%;border-collapse:separate;border-spacing:0}
.result-entry-table thead tr{background:var(--table-header-bg)}
.result-entry-table th{padding:10px 14px;font-size:11px;font-weight:700;text-transform:uppercase;
  letter-spacing:.3px;color:var(--table-header-color);border-bottom:2px solid var(--border);text-align:left;
  white-space:nowrap}
.result-entry-table td{padding:10px 14px;vertical-align:middle;border-bottom:1px solid var(--border)}
.result-entry-table tbody tr:last-child td{border-bottom:none}
.result-entry-row:hover{background:rgba(12,117,111,.03)}

.result-entry-table .rc-num{width:44px;font-weight:600;color:var(--text-muted)}
.result-entry-table .rc-code{width:92px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:var(--text-muted)}
.result-entry-table .rc-name{font-weight:600;color:var(--text-title)}
.result-entry-table .rc-name.is-param{padding-left:28px}
.result-entry-table .rc-unit{width:92px;color:var(--text-body);font-size:12.5px}
.result-entry-table .rc-method{width:120px}
.result-entry-table .rc-result{width:230px}
.result-entry-table .rc-range{width:130px;font-weight:600;color:var(--text-muted);font-size:12.5px}
.result-entry-table .rc-prev{width:118px;font-size:12px;white-space:nowrap}
.rc-req{color:var(--danger)}
.rc-muted{color:var(--text-muted)}
.rc-badge{font-weight:600;padding:3px 7px;border-radius:6px;font-size:10.5px;white-space:nowrap}
.rc-method-text{font-size:11.5px;color:var(--text-muted)}

.rc-group-row td.rc-group{background:var(--hive-teal-light);padding:8px 14px;font-weight:700;
  color:var(--hive-teal-mid);font-size:12px;letter-spacing:.3px}

.rc-result-wrap{display:flex;flex-direction:column;gap:6px;width:100%}
.rc-result-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.rc-input-num{height:34px;border-radius:6px;font-weight:700;width:104px;text-align:center;font-size:13.5px}
.rc-input-select{height:34px;border-radius:6px;font-weight:700;min-width:132px;font-size:13px}
.rc-input-text{border-radius:6px;min-width:220px;width:100%;font-size:12.5px}
.rc-input-num[readonly]{background:var(--table-header-bg);color:var(--text-muted);cursor:not-allowed}
.result-entry-table .comment-input{font-size:11px;height:28px;border-radius:6px;width:100%;padding:4px 8px}
.result-entry-table .toggle-comment-btn{height:34px;padding:0 8px;border-radius:6px}

/* Previous result + delta */
.rc-prev-val{font-weight:700;color:var(--text-title)}
.rc-prev-date{display:block;font-size:10.5px;color:var(--text-muted)}
.rc-delta{display:inline-block;margin-top:2px;font-size:10.5px;font-weight:700;color:var(--text-muted)}
.rc-delta.breach{color:#b45309;background:#fef3c7;border-radius:4px;padding:1px 5px}
[data-theme="dark"] .rc-delta.breach{color:#fbbf24;background:rgba(251,191,36,.14)}

.rc-hint{margin-left:auto;font-size:11px;color:var(--text-muted)}
.rc-hint kbd{font-family:inherit;font-size:10px;font-weight:700;background:var(--table-header-bg);
  border:1px solid var(--border);border-bottom-width:2px;border-radius:4px;padding:1px 5px;color:var(--text-body)}

/* â”€â”€ Live entry summary â”€â”€ */
.entry-summary{display:flex;align-items:center;gap:14px;flex-wrap:wrap;background:var(--bg-card);
  border:1px solid var(--border);border-radius:10px;padding:10px 16px;margin-bottom:14px;box-shadow:var(--shadow)}
.es-item{display:flex;align-items:baseline;gap:6px}
.es-label{font-size:10.5px;text-transform:uppercase;letter-spacing:.5px;font-weight:700;color:var(--text-muted)}
.es-value{font-size:14px;font-weight:800;color:var(--text-title);font-variant-numeric:tabular-nums}
.es-bar{flex:1;min-width:110px;height:6px;background:var(--table-header-bg);border-radius:99px;overflow:hidden}
.es-bar-fill{height:100%;width:0;background:linear-gradient(90deg,var(--hive-teal-mid),var(--hive-amber));
  border-radius:99px;transition:width .2s ease}
.es-flags{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.es-chip{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:700;
  padding:3px 9px;border-radius:99px;white-space:nowrap}
/* .es-chip[hidden] used to be declared here; the global [hidden] rule covers it now. */
.es-ok{background:var(--success-bg,#dcfce7);color:var(--success,#15803d)}
.es-abnormal{background:var(--danger-bg);color:var(--danger)}
.es-critical{background:#dc2626;color:#fff}
.es-delta{background:#fef3c7;color:#b45309}
[data-theme="dark"] .es-delta{background:rgba(251,191,36,.16);color:#fbbf24}

/* â”€â”€ Critical-value notification â”€â”€ */
.critical-notify{margin-bottom:16px;border-left:4px solid #dc2626}
.critical-notify .card-body{padding:14px 18px}
.cn-head{display:flex;align-items:flex-start;gap:12px;margin-bottom:10px}
.cn-head>i{color:#dc2626;font-size:22px;flex:none}
.cn-title{font-weight:800;color:#dc2626;font-size:13px}
.cn-sub{font-size:12px;color:var(--text-muted);margin-top:1px}
.cn-input{height:38px;border-radius:7px;font-size:13px;border-color:#fca5a5}
.cn-done{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--text-body);
  background:var(--success-bg,#dcfce7);border-radius:7px;padding:8px 12px}
.cn-done>i{color:var(--success,#15803d)}

/* â”€â”€ Entry action row â”€â”€ */
.entry-actions{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;
  margin:22px 0 40px;padding-top:16px;border-top:1px solid var(--border)}
.entry-actions-right{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.entry-actions .btn{height:38px;padding:0 20px;font-size:13px;border-radius:6px;
  display:inline-flex;align-items:center;gap:6px}
.entry-actions .btn-success{background:#0ea286;border-color:#0ea286;padding:0 22px}

/* â”€â”€â”€â”€â”€â”€â”€â”€â”€ Result entry on a tablet â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
@media(max-width:1200px){
  .result-entry-table .rc-code,
  .result-entry-table .rc-method,
  .result-entry-table thead .rc-code,
  .result-entry-table thead .rc-method{display:none}
}

/* â”€â”€â”€â”€â”€â”€â”€â”€â”€ Result entry on a phone: each row becomes a card â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
@media(max-width:900px){
  .result-entry-body{overflow-x:visible}
  .result-entry-table thead{display:none}
  .result-entry-table,
  .result-entry-table tbody,
  .result-entry-table tr,
  .result-entry-table td{display:block;width:auto}
  .result-entry-table tr.result-entry-row{
    border:1px solid var(--border);border-radius:10px;padding:10px 12px;margin:10px 12px;
    background:var(--bg-card);position:relative}
  .result-entry-table tr.result-entry-row td{border-bottom:none;padding:3px 0}
  /* The row number becomes a corner marker rather than its own line. */
  .result-entry-table .rc-num{position:absolute;top:8px;right:12px;font-size:11px;opacity:.6}
  .result-entry-table .rc-name{font-size:14px;padding-right:34px}
  .result-entry-table .rc-name.is-param{padding-left:0}
  /* Unit, interval and previous read as a labelled strip under the name. */
  .result-entry-table .rc-unit,
  .result-entry-table .rc-range,
  .result-entry-table .rc-prev{display:inline-block;width:auto;margin-right:16px;font-size:12px}
  .result-entry-table .rc-unit::before,
  .result-entry-table .rc-range::before,
  .result-entry-table .rc-prev::before{
    content:attr(data-label) ": ";font-size:10px;text-transform:uppercase;letter-spacing:.4px;
    font-weight:700;color:var(--text-muted)}
  .result-entry-table .rc-prev-date{display:inline;margin-left:4px}
  .result-entry-table .rc-result{width:auto;margin-top:8px}
  /* 16px stops iOS zooming the viewport when the box takes focus. */
  .rc-input-num{width:100%;max-width:170px;height:42px;font-size:16px}
  .rc-input-select{width:100%;height:42px;font-size:16px}
  .rc-input-text{font-size:16px}
  .result-entry-table .toggle-comment-btn{height:42px}
  .rc-group-row td.rc-group{margin:14px 12px 0;border-radius:8px}
  .rc-hint{display:none}
  .entry-summary{position:sticky;top:0;z-index:5;border-radius:0;margin:0 -16px 12px;
    padding:10px 16px;border-left:none;border-right:none}
  .entry-actions{flex-direction:column-reverse;align-items:stretch}
  .entry-actions-right{flex-direction:column-reverse;align-items:stretch}
  .entry-actions .btn{width:100%;justify-content:center;height:44px}
}


/* Age band beside a reference interval on the result-entry screen. */
.rc-band{display:block;font-size:10px;font-weight:700;color:var(--hive-teal-mid);
  text-transform:none;letter-spacing:0;margin-top:1px}
@media(max-width:900px){.result-entry-table .rc-band{display:inline;margin-left:5px}}


/* â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
   Sample collection and accessioning
   â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
   Built class-first and card-stacking below 900px, like the result-entry table: this screen is
   used standing at a rack with a scanner in one hand, often on a tablet or a phone.
   â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â• */

.sw-toolbar{display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin-bottom:12px}
.sw-scan{display:flex;align-items:center;gap:7px;background:var(--bg-card);border:1px solid var(--border);
  border-radius:10px;padding:7px 10px;box-shadow:var(--shadow)}
.sw-scan>i{font-size:20px;color:var(--hive-teal-mid)}
.sw-scan input{height:36px;width:230px;border-radius:7px;font-size:13px;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.sw-scan .btn{height:36px;padding:0 14px;border-radius:7px}
.sw-filter{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-left:auto}
.sw-filter input{height:36px;border-radius:7px;font-size:13px}
.sw-filter input[name=search]{width:200px}
.sw-filter .btn{height:36px;padding:0 14px;border-radius:7px}

.sw-overdue{display:flex;align-items:center;gap:8px;margin-bottom:12px}
.sw-overdue a{margin-left:auto;font-weight:700;color:inherit;text-decoration:underline}

.sw-tabs{display:flex;gap:4px;flex-wrap:wrap;margin-bottom:12px;border-bottom:1px solid var(--border)}
.sw-tab{display:inline-flex;align-items:center;gap:6px;padding:9px 14px;font-size:12.5px;font-weight:600;
  color:var(--text-muted);text-decoration:none;border-bottom:2px solid transparent;white-space:nowrap}
.sw-tab:hover{color:var(--text-title)}
.sw-tab.active{color:var(--hive-teal-mid);border-bottom-color:var(--hive-teal-mid)}
.sw-tab-count{font-size:11px;font-weight:800;background:var(--table-header-bg);
  border-radius:99px;padding:1px 7px;color:var(--text-body)}
.sw-tab.active .sw-tab-count{background:var(--hive-teal-light);color:var(--hive-teal-mid)}

.sw-body{padding:0;overflow-x:auto}
.sw-empty{display:flex;flex-direction:column;align-items:center;gap:10px;padding:46px 20px;
  color:var(--text-muted);font-size:13px}
.sw-empty>i{font-size:34px;opacity:.5}

.sw-table{width:100%;border-collapse:separate;border-spacing:0}
.sw-table thead tr{background:var(--table-header-bg)}
.sw-table th{padding:10px 14px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.3px;
  color:var(--table-header-color);border-bottom:2px solid var(--border);text-align:left;white-space:nowrap}
.sw-table td{padding:9px 14px;vertical-align:middle;border-bottom:1px solid var(--border);font-size:12.5px}
.sw-table tbody tr:last-child td{border-bottom:none}
.sw-table tbody tr:hover{background:rgba(12,117,111,.03)}
.sw-table tr.is-overdue{background:rgba(251,191,36,.07)}
.sw-table tr.is-rejected{opacity:.72}

.sw-table .sc-acc{width:140px}
.sw-table .sc-type{width:150px}
.sw-table .sc-stat{width:130px}
.sw-table .sc-tat{width:92px}
.sw-table .sc-act{width:230px}
.sc-code{display:block;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-weight:800;
  font-size:13px;color:var(--text-title)}
.sc-name{display:block;font-weight:700;color:var(--text-title)}
.sc-sub{display:block;font-size:10.5px;color:var(--text-muted);margin-top:1px;
  max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sc-count{display:inline-block;font-weight:800;font-size:13px;color:var(--text-title)}

.sc-status{display:inline-block;font-size:10.5px;font-weight:800;text-transform:uppercase;
  letter-spacing:.3px;padding:2px 8px;border-radius:99px}
.sc-status.s-pending{background:var(--table-header-bg);color:var(--text-muted)}
.sc-status.s-collected{background:#fef3c7;color:#b45309}
.sc-status.s-received{background:var(--hive-teal-light);color:var(--hive-teal-mid)}
.sc-status.s-rejected{background:var(--danger-bg);color:var(--danger)}
[data-theme="dark"] .sc-status.s-collected{background:rgba(251,191,36,.16);color:#fbbf24}

.sc-tatval{font-weight:800;font-variant-numeric:tabular-nums;color:var(--text-body)}
.sc-tatval.final{color:var(--text-muted)}
.sc-tatval.over{color:#b45309}
[data-theme="dark"] .sc-tatval.over{color:#fbbf24}

.sc-actions{display:flex;gap:5px;flex-wrap:wrap;align-items:center}
.sc-actions form{margin:0}
.sc-actions .btn{height:28px;padding:0 9px;border-radius:6px;font-size:11.5px;
  display:inline-flex;align-items:center;gap:4px;white-space:nowrap}

/* â”€â”€ Reject / reinstate dialog â”€â”€ */
.sc-modal{position:fixed;inset:0;z-index:2000;background:rgba(0,2,1,.45);
  display:flex;align-items:center;justify-content:center;padding:16px}
.sc-modal-card{background:var(--bg-card);border-radius:12px;width:100%;max-width:440px;
  box-shadow:0 24px 60px rgba(0,2,1,.3);overflow:hidden}
.sc-modal-head{display:flex;align-items:center;gap:9px;padding:14px 18px;font-weight:800;font-size:14px;
  color:var(--text-title);border-bottom:1px solid var(--border)}
.sc-modal-head>i{color:var(--danger);font-size:19px}
.sc-modal-body{padding:16px 18px}
.sc-modal-body .form-control{height:38px;border-radius:7px;font-size:13px;width:100%}
.sc-modal-note{margin:12px 0 0;font-size:11.5px;color:var(--text-muted);line-height:1.5}
.sc-modal-foot{display:flex;justify-content:flex-end;gap:9px;padding:12px 18px;
  border-top:1px solid var(--border);background:var(--table-header-bg)}
.sc-modal-foot .btn{height:36px;padding:0 16px;border-radius:7px;font-size:13px}

/* â”€â”€â”€â”€â”€â”€â”€â”€â”€ Accessioning on a phone: rows become cards â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
@media(max-width:900px){
  .sw-body{overflow-x:visible}
  .sw-filter{margin-left:0;width:100%}
  .sw-filter input[name=search]{flex:1;width:auto;min-width:140px}
  .sw-scan{width:100%}
  .sw-scan input{flex:1;width:auto;font-size:16px;height:42px}
  .sw-scan .btn{height:42px}

  .sw-table thead{display:none}
  .sw-table,.sw-table tbody,.sw-table tr,.sw-table td{display:block;width:auto}
  .sw-table tr{border:1px solid var(--border);border-radius:10px;padding:10px 12px;margin:10px 12px;
    background:var(--bg-card);position:relative}
  .sw-table td{border-bottom:none;padding:3px 0;width:auto !important}
  .sw-table .sc-acc{padding-right:96px}
  /* Status pinned to the corner so the card reads name-first. */
  .sw-table .sc-stat{position:absolute;top:10px;right:12px;text-align:right}
  .sw-table .sc-tat::before,
  .sw-table .sc-type::before,
  .sw-table .sc-tests::before{
    content:attr(data-label) ": ";font-size:10px;text-transform:uppercase;letter-spacing:.4px;
    font-weight:700;color:var(--text-muted)}
  .sw-table .sc-type,.sw-table .sc-tat{display:inline-block;margin-right:16px}
  .sc-sub{max-width:none;white-space:normal}
  .sc-actions{margin-top:9px}
  .sc-actions .btn{height:38px;padding:0 12px;font-size:12.5px}
}


/* Specimen strip on the result-entry screen. */
.rs-strip{display:flex;align-items:center;gap:9px;flex-wrap:wrap;background:var(--bg-card);
  border:1px solid var(--border);border-radius:10px;padding:9px 14px;margin-bottom:12px;box-shadow:var(--shadow)}
.rs-label{display:inline-flex;align-items:center;gap:5px;font-size:10.5px;font-weight:700;
  text-transform:uppercase;letter-spacing:.5px;color:var(--text-muted)}
.rs-chip{display:inline-flex;align-items:baseline;gap:7px;border:1px solid var(--border);
  border-radius:99px;padding:3px 11px;font-size:11.5px;background:var(--bg-body)}
.rs-code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-weight:800;color:var(--text-title)}
.rs-type{color:var(--text-body)}
.rs-stat{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.3px}
.rs-chip.s-pending .rs-stat{color:var(--text-muted)}
.rs-chip.s-collected{border-color:#fcd34d}
.rs-chip.s-collected .rs-stat{color:#b45309}
.rs-chip.s-received{border-color:var(--hive-teal-mid)}
.rs-chip.s-received .rs-stat{color:var(--hive-teal-mid)}
.rs-chip.s-rejected{border-color:var(--danger);background:var(--danger-bg)}
.rs-chip.s-rejected .rs-stat{color:var(--danger)}
.rs-link{margin-left:auto;font-size:11.5px;font-weight:700;color:var(--hive-teal-mid);text-decoration:none}
.rs-link:hover{text-decoration:underline}
.rs-warn{display:flex;align-items:flex-start;gap:9px;margin-bottom:12px;font-size:12.5px;line-height:1.5}
.rs-warn>i{font-size:19px;flex:none;margin-top:1px}
@media(max-width:900px){
  .rs-strip{border-radius:0;margin:0 -16px 12px;border-left:none;border-right:none}
  .rs-link{margin-left:0;width:100%}
}


/* â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
   Presentation refinement
   â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
   Loaded last so it refines what is already there rather than replacing it. Everything here is
   property-level â€” shadows, spacing, weights, borders â€” so no markup changes and nothing can
   break a screen's behaviour.

   What this is correcting, in order of how much it was costing:

     * Flat, uniformly-grey shadows on every surface. Depth was carried by borders alone, which
       makes a dense screen read as one slab. Shadows now tint towards the brand teal and get
       softer with distance, so a card sits above the page and a dialog above the card.
     * Headings, table headers and labels all competing at similar weight. A reader's eye had
       nothing to follow, which matters most on the screens that are mostly numbers.
     * Numeric columns rendered in proportional figures, so digits did not line up down a column
       and a money or result column could not be scanned. Tabular figures throughout.
   â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â• */

:root{
  /* Tinted towards the brand rather than neutral grey: a teal-cast shadow under a teal-accented
     card reads as the same material, where a grey one reads as a sticker on top of it. */
  --shadow:0 1px 2px rgba(6,67,64,.06), 0 1px 3px rgba(6,67,64,.05);
  --shadow-md:0 2px 4px rgba(6,67,64,.05), 0 6px 16px -4px rgba(6,67,64,.10);
  --shadow-lg:0 4px 8px rgba(6,67,64,.05), 0 16px 32px -8px rgba(6,67,64,.14);
  --radius:9px;
  --radius-lg:14px;
}
[data-theme="dark"]{
  --shadow:0 1px 2px rgba(0,0,0,.4), 0 1px 3px rgba(0,0,0,.3);
  --shadow-md:0 2px 4px rgba(0,0,0,.35), 0 6px 16px -4px rgba(0,0,0,.45);
  --shadow-lg:0 4px 8px rgba(0,0,0,.35), 0 16px 32px -8px rgba(0,0,0,.55);
}

/* â”€â”€ Numbers â”€â”€
   Every figure in the application lines up in its column. Proportional digits in a money or
   result column make the column impossible to scan down, which is most of what these screens
   are for. */
body{font-variant-numeric:tabular-nums}
h1,h2,h3,h4,.card-title,.page-title{letter-spacing:-.011em}

/* â”€â”€ Cards â”€â”€ */
.card{border-radius:var(--radius-lg);border-color:var(--border);transition:box-shadow .2s ease}
.card-header{background:transparent;border-bottom:1px solid var(--border)}
.card-title{font-weight:700;color:var(--text-title)}

/* â”€â”€ Tables â”€â”€
   The header was a solid teal band on every table, which is a lot of brand colour on a screen
   that is otherwise a list of facts, and it made the data itself the quietest thing present.
   A tinted header with a firm rule gives the same separation and lets the rows lead. */
.table thead th,
table thead th{
  background:var(--hive-teal-light);
  color:var(--hive-teal-mid);
  border-bottom:2px solid rgba(12,117,111,.22);
  font-weight:700;letter-spacing:.4px;text-transform:uppercase;font-size:11px}
[data-theme="dark"] .table thead th,
[data-theme="dark"] table thead th{
  background:rgba(12,117,111,.16);color:#8fd8d2;border-bottom-color:rgba(143,216,210,.28)}

/* Zebra striping is deliberately NOT used: these tables already carry status chips and flag
   colours, and a stripe underneath them competes with the one thing that must stand out. */
.table tbody tr:hover,
.dataTables_wrapper table tbody tr:hover{background:rgba(12,117,111,.035)}
[data-theme="dark"] .table tbody tr:hover{background:rgba(143,216,210,.05)}

/* â”€â”€ Buttons â”€â”€
   A touch of lift on the primary action only. Everything cannot be emphasised at once, so the
   outline and ghost variants stay flat and let the primary one carry the page's intent. */
.btn{font-weight:600;letter-spacing:.01em;transition:filter .14s, box-shadow .16s, transform .1s}
.btn:active{transform:translateY(1px)}
.btn-primary,.btn-teal{box-shadow:0 6px 14px -5px rgba(12,117,111,.55)}
.btn-primary:hover,.btn-teal:hover{filter:brightness(1.06);box-shadow:0 10px 18px -6px rgba(12,117,111,.6)}
.btn-success{box-shadow:0 6px 14px -5px rgba(14,162,134,.5)}
.btn-danger{box-shadow:0 6px 14px -5px rgba(239,68,68,.45)}
.btn-outline:hover{border-color:var(--hive-teal);color:var(--hive-teal-mid);background:var(--hive-teal-light)}

/* â”€â”€ KPI cards â”€â”€
   The figure is the content; the label is the caption. Previously both sat at similar weight,
   so a dashboard of six tiles had no reading order at all. */
.kpi-card{border-radius:var(--radius-lg);transition:box-shadow .2s ease, transform .2s ease}
.kpi-card:hover{box-shadow:var(--shadow-md)}
.kpi-value{font-weight:800;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.kpi-label{font-size:11px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--text-muted)}

/* â”€â”€ Badges and status chips â”€â”€ */
.badge{font-weight:700;letter-spacing:.2px;border-radius:99px;padding:3px 9px;font-size:10.5px}

/* â”€â”€ Forms â”€â”€ */
.form-control,.form-select{border-radius:var(--radius);transition:border-color .14s, box-shadow .14s, background .14s}
.form-control:focus,.form-select:focus{box-shadow:0 0 0 3.5px rgba(12,117,111,.13);border-color:var(--hive-teal)}
.form-label{font-weight:700;letter-spacing:.15px}

/* â”€â”€ Sidebar â”€â”€
   The active item was a flat fill. A left rule plus a soft wash marks position without painting
   a solid slab down a panel that is already a strong teal. */
.sidebar .nav-item{border-radius:0 8px 8px 0;transition:background .15s, color .15s}
.sidebar .nav-item.active{box-shadow:inset 3px 0 0 var(--hive-gold)}
.sidebar .section-label{font-size:10px;letter-spacing:1.4px;text-transform:uppercase;opacity:.62;font-weight:700}

/* â”€â”€ Topbar â”€â”€ */
.topbar{box-shadow:0 1px 0 var(--border)}
.breadcrumb-wrap{font-weight:600;color:var(--text-title)}

/* â”€â”€ Alerts â”€â”€ */
.alert{border-radius:var(--radius-lg);border-width:1px;box-shadow:var(--shadow);
  font-size:13px;line-height:1.5;align-items:flex-start}

/* â”€â”€ Page header â”€â”€ */
.page-header{margin-bottom:16px}
.page-title{font-weight:800;letter-spacing:-.02em;color:var(--text-title)}

/* â”€â”€ Empty states â”€â”€
   Reached often on a new installation, where first impressions are formed. */
.sw-empty,.empty-state{color:var(--text-muted)}

/* â”€â”€ Print â”€â”€
   Invoices and reports are printed from these screens constantly; the chrome has no business
   on the paper, and the ink-heavy table header wastes toner on every page. */
@media print{
  .sidebar,.sidebar-overlay,.topbar,.mobile-bottom-nav,.alerts-wrap,
  .btn,.sw-toolbar,.sw-tabs,.entry-actions,.no-print{display:none !important}
  .main-area,.page-content{margin:0 !important;padding:0 !important}
  .card{box-shadow:none !important;border:1px solid #ddd !important;break-inside:avoid}
  table thead th{background:#f3f4f6 !important;color:#111 !important;
    -webkit-print-color-adjust:exact;print-color-adjust:exact}
  a[href]:after{content:''}
}


/* Accessioning toolbar: the two forms were separate flex children with the filter pushed right
   by margin-auto, so at anything under a very wide screen the filter wrapped and its three
   controls spread across the full width while the scan box sat alone on the line. Laid out as
   one row that wraps as a unit instead, with the controls sized to their content. */
.sw-toolbar{align-items:stretch}
.sw-scan{flex:0 0 auto}
.sw-filter{margin-left:auto;flex:1 1 auto;justify-content:flex-end;max-width:620px}
.sw-filter input[name=search]{flex:1 1 170px;min-width:150px;max-width:240px}
.sw-filter .field-box.date-box{flex:0 0 200px;width:200px;height:36px}
@media(max-width:1180px){
  .sw-filter{margin-left:0;max-width:none;justify-content:flex-start}
}
@media(max-width:900px){
  .sw-filter .field-box.date-box{flex:1 1 180px;width:auto}
}


/* â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
   Two corrections to the refinement layer above
   â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â• */

/* â”€â”€ 1. Table headers go back to the solid brand band â”€â”€
   The refinement layer re-coloured `thead th` to a tinted background with teal text. That was
   wrong here for a reason worth recording: several tables set the dark header background on the
   <tr> inline (Booking) or with !important (DataTables, .scrollable-table-container), and a
   plain `thead th` selector cannot override those. The background therefore stayed dark teal
   while the text turned dark teal with it â€” an unreadable band, which is exactly what it looked
   like.

   A restyle that cannot reach every table does not "refine" anything, it just makes the set
   inconsistent. The solid header is the established pattern across this application; it is kept,
   and only the parts that do not fight anything are touched. */
.table thead th,
table thead th{
  background:var(--table-header-bg);
  color:var(--table-header-color);
  border-bottom:none;
  font-weight:700;letter-spacing:.5px;text-transform:uppercase;font-size:11.5px}
[data-theme="dark"] .table thead th,
[data-theme="dark"] table thead th{
  background:var(--table-header-bg);color:var(--table-header-color)}

/* â”€â”€ 2. A real token for light "inset" surfaces â”€â”€
   --table-header-bg is the dark brand band. It was being used as if it were a light neutral for
   chips, progress tracks, keyboard hints and read-only inputs, which made those elements dark
   teal blocks with muted text on them. They need a quiet surface a shade off the card, which is
   what this is. */
:root{
  --surface-muted:#F1F5F4;
  --surface-muted-border:#E3EAE9;
}
[data-theme="dark"]{
  --surface-muted:#17241f;
  --surface-muted-border:#24352f;
}

.rc-input-num[readonly]{background:var(--surface-muted);color:var(--text-muted)}
.rc-hint kbd{background:var(--surface-muted);border-color:var(--surface-muted-border);color:var(--text-body)}
.es-bar{background:var(--surface-muted)}
.sw-tab-count{background:var(--surface-muted);color:var(--text-body)}
.sc-status.s-pending{background:var(--surface-muted);color:var(--text-muted)}
.sc-modal-foot{background:var(--surface-muted)}
.es-chip.es-ok{background:var(--success-bg);color:var(--success)}

/* The entry and accessioning tables carry their own header styling; keep them on the brand band
   like every other table, and make sure the text on it is the light colour. */
.result-entry-table thead tr,
.sw-table thead tr{background:var(--table-header-bg)}
.result-entry-table th,
.sw-table th{color:var(--table-header-color);border-bottom:none}


/* â”€â”€ Column classes were colouring the header as well as the cells â”€â”€
   The column rules carry both the width and the cell's text colour:

       .result-entry-table .rc-num { width:44px; color:var(--text-muted) }

   and the header cells wear the same classes, because that is what sizes the column
   (<th class="rc-num">). So the muted cell colour landed on the <th> too â€” dark grey text on
   the dark teal band, which is why "#", "Code", "Unit" and "Bio. Ref. Interval" were invisible
   while "Parameter", "Method", "Result" and "Previous" (whose classes set no colour) were not.

   The class selector also outranks the plain `th` rule that sets the header colour, so that rule
   never got a chance. Fixed by naming the element as well as the class, which both raises the
   specificity above the column rule and says what is meant: the header is not a cell. The widths
   are deliberately left on the shared selector, since those genuinely do apply to both. */
.result-entry-table thead th.rc-num,
.result-entry-table thead th.rc-code,
.result-entry-table thead th.rc-name,
.result-entry-table thead th.rc-unit,
.result-entry-table thead th.rc-method,
.result-entry-table thead th.rc-result,
.result-entry-table thead th.rc-range,
.result-entry-table thead th.rc-prev,
.sw-table thead th.sc-acc,
.sw-table thead th.sc-pat,
.sw-table thead th.sc-type,
.sw-table thead th.sc-tests,
.sw-table thead th.sc-stat,
.sw-table thead th.sc-tat,
.sw-table thead th.sc-act{
  color:var(--table-header-color);
  font-weight:700;
  opacity:1}

/* The required-asterisk on "Result" sits on the dark band too, where the danger red is nearly
   unreadable. Gold is the brand's accent and reads cleanly against the teal. */
.result-entry-table thead th .rc-req{color:var(--hive-gold)}


/* Specimen-handling mode chooser on the Settings page. Radio cards rather than a select,
   because the difference between the three is a paragraph each, not a word â€” and this is a
   decision a laboratory makes once and lives with. */
.mode-choice{display:grid;gap:10px}
.mode-opt{display:flex;align-items:flex-start;gap:12px;padding:14px 16px;border:1.5px solid var(--border);
  border-radius:12px;cursor:pointer;background:var(--bg-card);transition:border-color .15s, background .15s, box-shadow .15s}
.mode-opt:hover{border-color:var(--hive-teal);background:var(--hive-teal-light)}
.mode-opt input{margin-top:3px;width:17px;height:17px;accent-color:var(--hive-teal);flex:none;cursor:pointer}
.mode-opt:has(input:checked){border-color:var(--hive-teal);background:var(--hive-teal-light);
  box-shadow:0 0 0 3px rgba(12,117,111,.1)}
.mode-body{display:flex;flex-direction:column;gap:4px}
.mode-title{font-weight:700;font-size:13.5px;color:var(--text-title);display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.mode-desc{font-size:12.5px;line-height:1.6;color:var(--text-muted)}
.mode-tag{font-size:9.5px;font-weight:800;text-transform:uppercase;letter-spacing:.5px;
  background:var(--hive-gold-light);color:var(--hive-gold-dark);border-radius:99px;padding:2px 8px}
.mode-tag.accredit{background:var(--hive-teal-light);color:var(--hive-teal-mid)}
@media(pointer:coarse){
  .mode-opt{padding:16px}
  .mode-opt input{width:20px;height:20px}
}


/* ── Theme picker (Settings → Theme Colour) ──
   Swatches alone make a laboratory guess what a colour will do to the page, so each
   option shows a miniature of the application instead: the sidebar slab, two lines of
   content and a primary button, drawn in that theme's own tones. The radio itself is
   hidden but still focusable, so the keyboard path and the screen-reader name are the
   native ones and only the painting is ours. */
.theme-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:12px}
.theme-opt{display:block;cursor:pointer;position:relative}
/* Radios only. This used to be `.theme-opt input`, which also caught the custom card's
   colour swatch and collapsed it to two pixels of border. */
.theme-opt input[type="radio"]{position:absolute;opacity:0;width:0;height:0}

.theme-card{display:block;border:2px solid var(--border);border-radius:12px;overflow:hidden;
  background:var(--bg-card);transition:border-color .15s ease, box-shadow .15s ease;position:relative}
.theme-opt:hover .theme-card{border-color:var(--hive-teal);box-shadow:var(--shadow-md)}
.theme-opt input[type="radio"]:checked + .theme-card{border-color:var(--hive-teal);box-shadow:0 0 0 3px var(--hive-amber-light)}
/* Focus must be visible on the card, because the input it belongs to is not. */
.theme-opt input[type="radio"]:focus-visible + .theme-card{outline:2px solid var(--hive-teal);outline-offset:2px}

.theme-mini{display:flex;height:74px;background:var(--bg-body)}
.theme-mini-side{width:26px;flex:none}
.theme-mini-body{flex:1;padding:12px 12px 0;display:flex;flex-direction:column;gap:7px}
.theme-mini-line{height:7px;border-radius:99px;display:block}
.theme-mini-btn{height:13px;width:58px;border-radius:5px;display:block;margin-top:auto;margin-bottom:12px}

.theme-meta{display:block;padding:10px 12px 12px;border-top:1px solid var(--border)}
.theme-name{display:flex;align-items:center;gap:7px;font-size:13px;font-weight:700;color:var(--text-title)}
.theme-dot{width:10px;height:10px;border-radius:50%;flex:none}
.theme-desc{display:block;font-size:11.5px;color:var(--text-muted);margin-top:2px}

.theme-tick{position:absolute;top:8px;right:8px;font-size:20px;color:var(--hive-teal);
  opacity:0;transform:scale(.7);transition:opacity .15s ease, transform .15s ease;
  background:var(--bg-card);border-radius:50%;line-height:1}
.theme-opt input[type="radio"]:checked + .theme-card .theme-tick{opacity:1;transform:scale(1)}

/* The custom card is a little taller than the presets: it carries the colour input, the
   resulting hex and a line explaining any darkening. */
.theme-custom-row{display:flex;align-items:center;gap:8px;margin-top:8px}
.theme-color-input{width:34px;height:26px;padding:0;border:1px solid var(--border);border-radius:6px;
  background:var(--bg-card);cursor:pointer;flex:none}
.theme-color-input::-webkit-color-swatch-wrapper{padding:2px}
.theme-color-input::-webkit-color-swatch{border:none;border-radius:4px}
.theme-custom-hex{font-size:11.5px;font-weight:700;color:var(--text-muted);
  font-family:ui-monospace,'Courier New',monospace;letter-spacing:.3px}
.theme-custom-note{display:block;font-size:10.5px;line-height:1.35;color:var(--warning);margin-top:6px;min-height:0}

/* ── KPI cards on a phone: two to a row ───────────────────────────────────────────
   One card per row wasted the width and pushed everything below the fold, so the
   grid stays two-up on phones and the type shrinks to match. A card is roughly
   165px wide at 375px, minus padding — about 140px of content — so the icon, the
   label and the number are all sized against that budget rather than guessed.

   This block sits at the end of the file on purpose: .kpi-label and .kpi-value are
   redefined further up (around the "KPI cards" polish block), and those later rules
   carry the same specificity, so a media query written earlier would lose. */
@media(max-width:560px){
  /* grid-auto-rows:1fr gives the second row the same height as the first, so all four
     cards match; without it a card carrying two footer lines made its whole row taller. */
  .kpi-grid{grid-template-columns:1fr 1fr !important;grid-auto-rows:1fr;gap:10px;margin-bottom:18px}
  .kpi-card{padding:13px 12px;display:flex;flex-direction:column}

  .kpi-ident{gap:9px}
  .kpi-icon{width:30px;height:30px;font-size:15px}

  /* Uppercase + letter-spacing is what makes these labels wide; both come down so
     "Today's Patients" still fits on one line instead of being clipped to an ellipsis. */
  .kpi-label{font-size:9px;letter-spacing:.2px;margin-bottom:1px}
  .kpi-value{font-size:19px;letter-spacing:-.4px}

  /* The chip and its caption no longer sit side by side in 140px — let them stack. */
  .kpi-footer{flex-wrap:wrap;gap:4px 6px;margin-top:auto;padding-top:9px}
  .trend{font-size:9.5px;padding:2px 6px;gap:3px}
  .trend i{font-size:11px}
  .kpi-sub{font-size:9.5px;line-height:1.3}
  .kpi-link{font-size:10px}
}

/* Narrow phones (up to 359px): a card is only ~117-135px of content, and at the sizes
   above three of the four labels were cut to an ellipsis. The upper bound is not a round
   number by accident — measured one pixel at a time, 9px type first fits at exactly
   360px, so anything below that needs this tier. A 345px bound left 346-359 broken. */
@media(max-width:359.98px){
  .kpi-card{padding:11px 8px}
  .kpi-ident{gap:5px}
  .kpi-icon{width:22px;height:22px;font-size:12px}
  /* 'Today's Patients' is the longest of the four and needs ~86px here; this leaves
     about 92px for it, so it stays on one line instead of ending in an ellipsis. */
  .kpi-label{font-size:8px;letter-spacing:0}
  .kpi-value{font-size:17px}
}

/* ── Dashboard on a phone ─────────────────────────────────────────────────────────
   The dashboard's own tables are hand-rolled (.data-table), not DataTables, so they
   missed the carding treatment above and were the one thing on the page that still
   scrolled sideways — with "Status" and "Amount" hidden off the right edge where
   nobody found them. Same card shape as every other list in the app, so a phone user
   sees one consistent pattern. The cells carry inline styles, hence the !important. */
@media(max-width:640px){
  .card > .table-wrap{overflow-x:hidden !important}
  table.data-table thead{display:none}
  table.data-table,
  table.data-table tbody,
  table.data-table tbody tr,
  table.data-table tbody td{display:block;width:auto}
  table.data-table{border:0}
  table.data-table tbody tr{
    margin:0 14px 12px;border:1px solid var(--border);border-radius:12px;
    background:var(--bg-card);overflow:hidden}
  table.data-table tbody tr:last-child{margin-bottom:14px}
  table.data-table tbody td{
    display:flex;align-items:center;justify-content:space-between;gap:12px;
    padding:8px 12px !important;border:0 !important;
    border-bottom:1px solid var(--border) !important;
    text-align:right !important;white-space:normal}
  table.data-table tbody td:last-child{border-bottom:0 !important}
  table.data-table tbody td::before{
    content:attr(data-label);font-weight:700;font-size:10px;text-transform:uppercase;
    letter-spacing:.4px;color:var(--text-muted);text-align:left;flex:0 0 auto;margin-right:auto}

  /* The patient cell already shows a name and a code — a "PATIENT:" label in front of
     it would be noise. It heads the card instead, on a tint, full width. */
  table.data-table tbody td.dc-pat{
    background:var(--bg-body);text-align:left !important;padding:10px 12px !important}
  table.data-table tbody td.dc-pat::before{display:none}
  table.data-table tbody td.dc-act{justify-content:flex-end}
  table.data-table tbody td.dc-act::before{display:none}

  /* The empty-state cell must not be carded into a label/value row. */
  table.data-table tbody td[colspan]{display:block;text-align:center !important}
  table.data-table tbody td[colspan]::before{display:none}

  /* .chart-container is a flex child with flex:1 and min-height:200px, so once the
     cards stacked it stretched to 300px and the donut — which follows its container,
     maintainAspectRatio is false — ate a whole screen for what is often a single
     category. Pin the height here instead of capping the canvas, which would just
     squash a circle into an ellipse. */
  .chart-container{flex:0 0 auto;min-height:0 !important;overflow:hidden}
  .chart-container--donut{height:170px !important}
  .chart-container canvas{max-width:100% !important}
}

/* The discount amount and its %/₹ unit are one decision, so they live in one cell. */
.disc-pair{display:flex;align-items:center;gap:6px}

/* ── Booking: the test grid on a phone ────────────────────────────────────────────
   This is the screen a lab runs all day, and it was the worst offender: seven columns
   on a 390px screen meant Price was clipped mid-word and the remove-row button sat off
   the right edge, reachable only by a sideways scroll nobody knew was there. Each test
   becomes a card — the picker on top, then price, discount and amount as labelled
   rows, with remove as a full-width button instead of a 30px icon. */
@media(max-width:640px){
  #servicesTable thead{display:none}
  #servicesTable,#servicesTable tbody,#servicesTable tbody tr,#servicesTable tbody td{display:block;width:auto}
  #servicesTable tbody tr.service-row{
    position:relative;margin:0 0 10px;padding:4px 0;border:1px solid var(--border);
    border-radius:12px;background:var(--bg-card);border-bottom:1px solid var(--border) !important}
  #servicesTable tbody td{
    display:flex;align-items:center;justify-content:space-between;gap:10px;
    padding:7px 12px !important;text-align:left !important;border:0 !important}
  #servicesTable tbody td::before{
    content:attr(data-label);font-weight:700;font-size:10px;text-transform:uppercase;
    letter-spacing:.4px;color:var(--text-muted);flex:0 0 auto;margin-right:auto}

  /* The row number is a desktop affordance; on a card the order is already obvious. */
  #servicesTable tbody td.row-num{display:none}

  /* The picker is the point of the row — full width, no caption, nothing competing. */
  #servicesTable tbody td.svc-pick{padding:10px 12px 4px !important;display:block}
  #servicesTable tbody td.svc-pick::before{display:none}
  #servicesTable tbody td.svc-pick .service-select{width:100%}

  /* Inputs were sized in px for a table cell; let them use the card's width instead. */
  #servicesTable tbody td .row-price,
  #servicesTable tbody td .row-net-amount{width:110px !important}
  #servicesTable tbody td .row-discount{width:90px !important;flex:1 1 auto}

  /* A 30px icon button at the edge of a card is a miss waiting to happen. */
  #servicesTable tbody td.svc-act{padding:4px 12px 10px !important}
  #servicesTable tbody td.svc-act::before{display:none}
  #servicesTable tbody td.svc-act .btn-delete-row{width:100%;height:36px !important;gap:6px}
  #servicesTable tbody td.svc-act .btn-delete-row::after{content:'Remove';font-size:12px;font-weight:600}

  .test-grid-scroll,.test-grid-wrap{overflow-x:hidden !important}
}

/* ── Row actions carry their name on a phone ──────────────────────────────────────
   In a table the icons sit under a header and in a fixed order, so an eye and a bin
   read fine. On a card that context is gone and they become four grey glyphs you have
   to tap to identify — which is a bad bet when one of them deletes a patient. Every
   one of these buttons already states its purpose for screen readers, so the label is
   simply shown. aria-label wins where both are present; title covers the rest. */
@media(max-width:640px){
  .table-actions{flex-wrap:wrap;gap:8px !important;width:100%;justify-content:flex-start !important}
  .table-actions .btn-icon,
  .table-actions form{flex:0 0 auto}
  .table-actions .btn-icon{
    width:auto !important;min-width:0;height:auto;min-height:38px;padding:0 11px;
    display:inline-flex;align-items:center;gap:6px;
    border:1px solid var(--border);border-radius:9px;background:var(--bg-card);
    font-size:12px;font-weight:600;line-height:1}
  .table-actions .btn-icon i{font-size:16px}
  .table-actions .btn-icon[title]::after{content:attr(title)}
  .table-actions .btn-icon[aria-label]::after{content:attr(aria-label)}
  .table-actions .btn-icon::after{white-space:nowrap;max-width:150px;overflow:hidden;text-overflow:ellipsis}
}

/* The spinner that replaces a submit button's icon while its form is in flight.
   See the submit guard in site.js. */
@keyframes btnSpin{to{transform:rotate(360deg)}}
.btn-spin{display:inline-block;animation:btnSpin .7s linear infinite}
button[aria-busy="true"]{cursor:progress;opacity:.82}

/* ── Wide record forms (Add/Edit Test) ──────────────────────────────────────────
   The test form was capped at 700px on a 1357px page — half the window empty while
   the form itself ran past the fold and had to be scrolled. The fields are short, so
   the answer is not to stretch each input across the screen; it is to let a section's
   fields flow into as many columns as fit. One .form-row per section does that on its
   own, because .form-row is already an auto-fit grid — the old markup just gave each
   grid only two children to place. */
.form-wide{max-width:1320px}

/* 225px rather than the app-wide 220px minimum: on a full-width card that lands five
   fields on a line, which is what lets a five-field section be one row instead of two.
   Measured against the longest label here — "Normal Range (Female)" — so nothing wraps. */
.form-section .form-row{grid-template-columns:repeat(auto-fit,minmax(225px,1fr))}

/* Section chrome is what a grouped form costs: four headings and four margins came to
   roughly 240px, which ate the whole saving from going multi-column. Trimmed to keep
   the grouping and most of the saving. */
.form-section{margin-bottom:14px}
.form-section > h5{padding-bottom:6px;margin-bottom:11px}

/* Free text takes the whole width whatever the column count; 1/-1 is safe at any. */
.fg-all{grid-column:1/-1}

/* A span would create implicit extra columns on a one- or two-column grid and push the
   form sideways, so spans only apply once there is genuinely room for them. */
@media(min-width:1100px){
  .form-section .fg-wide{grid-column:span 2}
  .form-section .fg-span3{grid-column:span 3}
}

/* ── Report page furniture ──────────────────────────────────────────────────────
   A short filter that belongs beside the page title instead of in a card of its own.
   The commission report spent 105px of vertical space on a card holding one date
   field and a button, which pushed the figures the page exists for below the fold. */
.header-filter{display:flex;gap:8px;align-items:center;flex-wrap:wrap}

/* Report tiles show a label and a figure and nothing else, so they do not need the
   room the dashboard's cards leave for a trend chip and a caption underneath. */
.stat-tiles .kpi-card{padding:14px 16px}
.stat-tiles .kpi-label{margin-bottom:5px}
.stat-tiles .kpi-value{font-size:25px;margin-bottom:0}

/* Money reads right-aligned, so the decimal points line up and a column can be scanned
   for size. Only the last column got this before, by accident of :last-child. */
table.data-table th.num,
table.data-table td.num{text-align:right}

/* The totals line. A payout report that does not add up on screen gets added up by
   hand, so the figures are repeated under the column they total. */
table.data-table tfoot td{padding:12px 14px;border-top:2px solid var(--border);font-weight:800;color:var(--text-title);background:var(--bg-body)}
table.data-table tfoot td:first-child{padding-left:20px}
table.data-table tfoot td:last-child{padding-right:20px;text-align:right}

/* ---- Appearance picker (top bar) -----------------------------------------
   A preferences button that opens a small panel, rather than a menu of three
   lines. Light, dark and follow-the-device are three answers to one question,
   and a segmented control shows the two not chosen as well as the one that is. */
.theme-picker{position:relative;display:flex;align-items:center}
.theme-picker-btn{display:flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;
  font-size:17px;color:var(--text-muted);background:var(--bg-card);border:1px solid var(--border);
  border-radius:9px;cursor:pointer;transition:background .15s,color .15s,border-color .15s}
.theme-picker-btn:hover{background:var(--bg-body);color:var(--text-title)}
.theme-picker.open .theme-picker-btn{background:var(--bg-body);color:var(--text-title);border-color:var(--hive-teal)}

.theme-menu{position:absolute;top:calc(100% + 10px);right:0;width:272px;background:var(--bg-card);
  border:1px solid var(--border);border-radius:14px;box-shadow:var(--shadow-lg);padding:16px;z-index:200;
  opacity:0;visibility:hidden;transform:translateY(-6px);
  transition:opacity .15s ease,transform .15s ease,visibility .15s}
.theme-picker.open .theme-menu{opacity:1;visibility:visible;transform:translateY(0)}

.pref-label{font-size:13px;font-weight:700;color:var(--text-title);margin-bottom:9px}
.pref-note{margin:12px 0 0;font-size:11.5px;line-height:1.5;color:var(--text-muted)}

/* The track holds the three segments; the one in force is lifted out of it with the
   card colour, a border and the house teal, which is how a selected thing reads
   everywhere else in the application. */
.segmented{display:flex;gap:3px;padding:3px;background:var(--bg-body);
  border:1px solid var(--border);border-radius:9px}
.segmented .seg{flex:1;min-width:0;display:flex;align-items:center;justify-content:center;gap:6px;
  padding:7px 4px;background:none;border:1px solid transparent;border-radius:7px;cursor:pointer;
  font-family:inherit;font-size:12px;font-weight:600;color:var(--text-muted);
  transition:background .15s,color .15s,border-color .15s}
.segmented .seg i{font-size:15px;flex:0 0 auto}
.segmented .seg span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.segmented .seg:hover:not(.is-on){color:var(--text-title)}
.segmented .seg.is-on{background:var(--bg-card);border-color:var(--border);color:var(--hive-teal);
  box-shadow:0 1px 2px rgba(0,0,0,.05)}

/* On a narrow screen the panel hangs off the viewport, not off the button: the gear
   is not the last thing in the top bar, so anchoring to it put the panel's left edge
   31px past the left of a 320px screen. The top bar is 56px tall there and sticky. */
@media (max-width: 480px){
  .theme-menu{position:fixed;top:64px;right:12px;left:auto;
    width:min(272px, calc(100vw - 24px));padding:14px}
  .segmented .seg{font-size:11.5px;gap:5px;padding:8px 3px}
}

/* ---- Theme page: default appearance -------------------------------------
   Same card shape as the colour grid beside it, so the page reads as one
   choice after another rather than two unrelated widgets. */
.appearance-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(188px,1fr));gap:12px}
.appearance-opt{position:relative;display:block;cursor:pointer}
.appearance-opt input{position:absolute;opacity:0;width:0;height:0}
.appearance-card{display:block;border:2px solid var(--border);border-radius:12px;overflow:hidden;background:var(--bg-card);transition:border-color .15s,box-shadow .15s}
.appearance-opt:hover .appearance-card{border-color:var(--hive-teal)}
.appearance-opt input:checked + .appearance-card{border-color:var(--hive-teal);box-shadow:0 0 0 3px var(--hive-amber-light)}
.appearance-opt input:focus-visible + .appearance-card{outline:2px solid var(--hive-teal);outline-offset:2px}
/* The miniature is drawn in fixed colours, not variables: it has to show what that
   mode looks like even while the page itself is in the other one. */
.appearance-mini{display:flex;flex-direction:column;gap:5px;padding:10px;height:74px}
.appearance-mini-bar{height:9px;border-radius:3px}
.appearance-mini-line{height:6px;border-radius:3px}
.appearance-mini-btn{height:11px;width:42px;border-radius:4px;margin-top:auto}
.appearance-mini-light{background:#f8fafc}
.appearance-mini-light .appearance-mini-bar{background:#e2e8f0}
.appearance-mini-light .appearance-mini-line{background:#cbd5e1}
.appearance-mini-light .appearance-mini-btn{background:var(--hive-teal)}
.appearance-mini-dark{background:#0f172a}
.appearance-mini-dark .appearance-mini-bar{background:#1e293b}
.appearance-mini-dark .appearance-mini-line{background:#334155}
.appearance-mini-dark .appearance-mini-btn{background:var(--hive-teal)}
/* "System" is the two of them, split down the middle. */
.appearance-mini-system{background:linear-gradient(100deg,#f8fafc 0 50%,#0f172a 50% 100%)}
.appearance-mini-system .appearance-mini-bar{background:linear-gradient(100deg,#e2e8f0 0 50%,#1e293b 50% 100%)}
.appearance-mini-system .appearance-mini-line{background:linear-gradient(100deg,#cbd5e1 0 50%,#334155 50% 100%)}
.appearance-mini-system .appearance-mini-btn{background:var(--hive-teal)}
.appearance-meta{display:block;padding:10px 12px 12px;border-top:1px solid var(--border)}
.appearance-name{display:flex;align-items:center;gap:7px;font-size:13px;font-weight:700;color:var(--text-title)}
.appearance-name i{font-size:15px;color:var(--hive-teal)}
.appearance-desc{display:block;margin-top:3px;font-size:11.5px;color:var(--text-muted)}
.appearance-opt .theme-tick{position:absolute;top:8px;right:8px;font-size:19px;color:var(--hive-teal);background:var(--bg-card);border-radius:50%;opacity:0;transition:opacity .15s}
.appearance-opt input:checked ~ .appearance-card .theme-tick,
.appearance-opt input:checked + .appearance-card .theme-tick{opacity:1}

/* ---- Theme page: the live preview ----------------------------------------
   One screen drawn twice, light and dark, in whichever colour is selected. The
   surfaces are literal rather than var()-driven because each half has to show
   its own mode while the page sits in the other. The brand tones arrive as
   --bp-* from the page script. */
.brand-preview-pair{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}
.brand-preview{border:1px solid var(--border);border-radius:12px;overflow:hidden;background:var(--bg-card)}
.brand-preview-label{display:flex;align-items:center;gap:6px;padding:7px 12px;font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--text-muted);border-bottom:1px solid var(--border)}
.brand-preview-label i{font-size:14px}
.bp-app{display:flex;height:186px;font-size:0}
.bp-side{flex:0 0 46px;background:var(--bp-side,#064340);display:flex;flex-direction:column;gap:7px;padding:10px 8px}
.bp-side-logo{height:14px;border-radius:4px;background:rgba(255,255,255,.85)}
.bp-side-item{height:7px;border-radius:3px;background:rgba(255,255,255,.26)}
.bp-side-on{background:rgba(255,255,255,.72)}
.bp-main{flex:1;display:flex;flex-direction:column;gap:8px;padding:10px}
.bp-top{display:flex;align-items:center;justify-content:space-between}
.bp-crumb{display:block;height:7px;width:52%;border-radius:3px}
.bp-avatar{display:block;width:15px;height:15px;border-radius:50%;background:var(--bp-base,#0C756F)}
.bp-greet{border-radius:8px;padding:9px;display:flex;flex-direction:column;gap:5px}
.bp-greet-line{display:block;height:7px;border-radius:3px;background:var(--bp-base,#0C756F)}
.bp-greet-line.bp-dim{opacity:.4}
.bp-row{display:flex;align-items:center;gap:7px}
.bp-btn{font-size:9.5px;font-weight:700;color:#fff;background:var(--bp-base,#0C756F);padding:4px 9px;border-radius:5px;line-height:1}
.bp-chip{font-size:9px;font-weight:700;color:var(--bp-base,#0C756F);background:var(--bp-light,#e3f0ef);padding:3px 7px;border-radius:999px;line-height:1}
.bp-link{font-size:9.5px;font-weight:600;color:var(--bp-base,#0C756F);line-height:1}
.bp-table{border-radius:6px;overflow:hidden;margin-top:auto}
.bp-thead,.bp-trow{display:grid;grid-template-columns:2fr 1fr 1fr;gap:6px;padding:5px 7px}
.bp-thead{background:var(--bp-base,#0C756F)}
.bp-thead span{height:5px;border-radius:2px;background:rgba(255,255,255,.75)}
.bp-trow span{height:5px;border-radius:2px}
/* light half */
.brand-preview-light .bp-main{background:#f8fafc}
.brand-preview-light .bp-crumb{background:#cbd5e1}
.brand-preview-light .bp-greet{background:var(--bp-light,#e8f3f2);border:1px solid rgba(0,0,0,.05)}
.brand-preview-light .bp-table{border:1px solid #e2e8f0}
.brand-preview-light .bp-trow{background:#fff;border-top:1px solid #eef2f6}
.brand-preview-light .bp-trow span{background:#dde3ea}
/* dark half */
.brand-preview-dark .bp-main{background:#0f172a}
.brand-preview-dark .bp-crumb{background:#334155}
.brand-preview-dark .bp-greet{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.08)}
.brand-preview-dark .bp-chip{background:rgba(255,255,255,.1)}
.brand-preview-dark .bp-table{border:1px solid #1e293b}
.brand-preview-dark .bp-trow{background:#111c31;border-top:1px solid #1b2639}
.brand-preview-dark .bp-trow span{background:#2b3a52}

/* ---- Theme page: the derived tones ---------------------------------------
   One colour becomes four. A laboratory that picks its letterhead colour should
   be able to see what the application made of it, hex and all. */
.tone-strip{display:grid;grid-template-columns:repeat(auto-fit,minmax(142px,1fr));gap:10px;margin-top:14px}
.tone{display:flex;align-items:center;gap:9px;padding:9px 11px;border:1px solid var(--border);border-radius:10px;background:var(--bg-card)}
.tone-chip{flex:0 0 26px;height:26px;border-radius:7px;border:1px solid rgba(0,0,0,.12)}
.tone-chip-pale{border-color:var(--border)}
.tone-name{flex:1;font-size:11.5px;font-weight:600;color:var(--text-title);line-height:1.2}
.tone-hex{font-family:'JetBrains Mono',ui-monospace,monospace;font-size:10px;color:var(--text-muted);letter-spacing:-.02em}

@media (max-width: 480px){
  .appearance-grid{grid-template-columns:1fr 1fr;gap:10px}
  .appearance-mini{height:62px}
  .tone-strip{grid-template-columns:1fr 1fr}
}

/* ---- Master catalogue -----------------------------------------------------
   The band is deliberately loud and on every page: in this mode the ordinary
   test and category screens are writing to organisation 0, and a vendor who
   forgets that edits the template every future laboratory is built from. */
.catalogue-band{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 14px;padding:10px 14px;border:1px solid var(--hive-amber);border-left:4px solid var(--hive-amber);border-radius:10px;background:var(--hive-amber-light);color:var(--text-title);font-size:12.5px;line-height:1.4}
.catalogue-band > i{font-size:18px;color:var(--hive-teal);flex:none}
.catalogue-band-exit{display:inline-flex;align-items:center;gap:6px;padding:5px 11px;border:1px solid var(--hive-teal);border-radius:7px;background:none;color:var(--hive-teal);font-family:inherit;font-size:12px;font-weight:700;cursor:pointer;white-space:nowrap}
.catalogue-band-exit:hover{background:var(--hive-teal);color:#fff}

.catalogue-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(224px,1fr));gap:12px}
.catalogue-tile{display:flex;flex-direction:column;gap:5px;padding:16px;border:1px solid var(--border);border-radius:12px;background:var(--bg-card);text-decoration:none;transition:border-color .15s,box-shadow .15s}
.catalogue-tile:hover{border-color:var(--hive-teal);box-shadow:var(--shadow-md)}
.catalogue-tile > i{font-size:22px;color:var(--hive-teal)}
.catalogue-tile-name{font-size:13.5px;font-weight:700;color:var(--text-title)}
.catalogue-tile-desc{font-size:11.5px;color:var(--text-muted);line-height:1.45}

@media (max-width: 480px){
  .catalogue-grid{grid-template-columns:1fr}
  .catalogue-band{font-size:12px}
}

/* ---- Vendor logs (sign-ins, errors, audit) --------------------------------
   Laid out like every other filter bar in the application rather than inventing
   a third shape: the same control height, gap and radius as the sample worklist,
   and the shared date box instead of a pair of native date inputs. */
.log-filter{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-bottom:14px}
.log-filter .form-control,.log-filter .form-select{height:36px;border-radius:7px;font-size:13px}
.log-filter input[name=search]{width:220px}
.log-filter select[name=orgId]{width:210px}
.log-filter .btn{height:36px;padding:0 14px;border-radius:7px}

/* The second line of a cell - a person's name under their username - reads as
   secondary rather than as another value. */
.log-sub{display:block;font-size:11px;color:var(--text-muted);margin-top:2px}
.log-where{font-size:11.5px;color:var(--text-muted);word-break:break-all}

.log-detail{margin-top:5px}
.log-detail summary{font-size:11.5px;color:var(--text-muted);cursor:pointer}
.log-detail pre{margin:6px 0 0;padding:8px;background:var(--bg-body);border:1px solid var(--border);
  border-radius:6px;font-size:11px;white-space:pre-wrap;word-break:break-word;max-height:240px;overflow:auto}

@media (max-width: 640px){
  .log-filter{gap:8px}
  .log-filter .field-box,
  .log-filter input[name=search],
  .log-filter select[name=orgId]{width:100%;flex:1 1 100%}
  .log-filter .btn{flex:1}
}

/* The same band in a cooler colour: looking at a laboratory is a weaker warning than
   editing the catalogue every laboratory is built from. */
.catalogue-band-warn{border-color:var(--hive-teal);border-left-color:var(--hive-teal);background:var(--hive-amber-light)}
.catalogue-band-warn > i{color:var(--hive-teal)}
.catalogue-lede{font-size:13px;color:var(--text-body);line-height:1.55;margin:14px 0}
.catalogue-leave{margin-top:16px}

/* ---- Exact date of birth (patient edit) ----------------------------------
   An offer, not a field. The age box above it is what registration actually
   uses; this is for the parent who has the card, and for a child it is the
   difference between the right paediatric band and the next one up. */
.dob-exact{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:7px}
.dob-known{font-size:11.5px;color:var(--text-muted)}
.dob-toggle{padding:0;background:none;border:0;font:inherit;font-size:11.5px;
  color:var(--hive-teal);cursor:pointer;text-decoration:underline;text-underline-offset:2px}
.dob-toggle:hover{opacity:.8}
.dob-input{height:36px;max-width:180px;font-size:13px}

@media (max-width: 640px){
  .dob-exact{gap:8px}
  .dob-input{max-width:100%;flex:1 1 100%}
}

/* A 14px line of text is a link on a mouse and a mis-tap on a thumb. Same 44px floor the
   rest of the application uses, keyed off the pointer rather than the width so a laptop
   keeps the compact line. */
@media(pointer:coarse){
  .dob-toggle{min-height:44px;display:inline-flex;align-items:center}
  .dob-input{height:44px;font-size:16px}
}

/* ── The logo, centred in its box ─────────────────────────────────────────────
   The uploaded mark and the fallback hex both used to sit hard against the left
   edge, which read as a crop rather than a header. Centring is why the close
   button is taken out of the flow: left in it, it would push the mark off centre
   by half its own width on a phone. */
.sidebar-logo{justify-content:center;position:relative}
.logo-text{flex:0 1 auto}
/* With a logo uploaded, the hexagon is only the rail's stand-in. */
.sidebar-logo.has-logo .logo-hex{display:none}
.sidebar-toggle-btn{position:absolute;right:10px;top:50%;transform:translateY(-50%);margin-left:0}

/* ── The menu as a rail ───────────────────────────────────────────────────────
   The menu button narrows the sidebar to its icons instead of only opening the
   drawer. The state is a preference of this browser and is applied before paint
   from the head, so the menu does not snap from 260px to 72px on every page.

   Only above the phone breakpoint. On a phone the sidebar is already a drawer
   that costs no width when closed, so a rail there would buy nothing and lose
   every label. */
.topbar-menu-btn{display:flex}

@media (min-width: 769px){
  :root[data-nav="rail"] .sidebar{width:72px;min-width:72px}
  :root[data-nav="rail"] .sidebar-logo{padding:14px 6px}
  :root[data-nav="rail"] .logo-text{display:none}
  /* An uploaded wordmark gives way to the initials: 60px of rail cannot hold one
     legibly, and a shrunken logo reads as a fault rather than as a choice. */
  :root[data-nav="rail"] .logo-img{display:none}
  :root[data-nav="rail"] .sidebar-logo.has-logo .logo-hex{display:block}

  /* The heading keeps its job as a divider once its words are gone, so the
     groups stay groups rather than becoming one undifferentiated column. */
  :root[data-nav="rail"] .section-label{
    height:1px;padding:0;margin:11px 14px;background:rgba(255,255,255,0.16);
    overflow:hidden;text-indent:-200px;white-space:nowrap}

  :root[data-nav="rail"] .sidebar-section{padding:0 8px}
  :root[data-nav="rail"] .sidebar-divider{margin:8px 14px}
  :root[data-nav="rail"] .nav-item{justify-content:center;gap:0;padding:9px 0}
  :root[data-nav="rail"] .nav-item i{font-size:19px;width:auto;opacity:0.9}
  :root[data-nav="rail"] .nav-item.active i{opacity:1}
  :root[data-nav="rail"] .sidebar .nav-label{display:none}
}
