:root {
    /* KLM's brand colours, taken from klm-site/app/globals.css. The marketing
       site is dark; this is deliberately a light UI — it gets read on a phone
       in daylight on a job site, where a dark theme is unreadable. */
    --blue: #12314F;
    --blue-dark: #0C2136;
    --blue-mid: #2C4A68;
    --accent: #D95814;
    --accent-dark: #A8410D;

    --bg: #f4f6f8;
    --card-bg: #ffffff;
    --border: #dfe4ea;
    --text: #16202B;
    --muted: #5f6b78;
    --faint: #aeb7c2;
    --surface-2: #eef2f6;
    --surface-hover: #f7f9fb;
    --input-bg: #ffffff;

    --green: #1f7a3d;
    --green-bg: #e6f6ec;
    --red: #b3261e;
    --red-bg: #fbe9e7;
    --amber: #8a6d00;
    --amber-bg: #fff7e0;

    --shadow: 0 1px 2px rgba(18, 49, 79, 0.06);
    --heading-ink: var(--blue);           /* page h1 and KPI figures: navy in light, text in dark */
    --font-display: "Montserrat", -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --font-ui: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --radius: 8px;
    --radius-sm: 6px;
    color-scheme: light;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    background: var(--bg);
    color: var(--text);
    font-size: 14px;
    line-height: 1.5;
}

a { color: var(--blue); }
a:hover { color: var(--accent); }

/* ------------------------------------------------------------------ chrome */
/* Light header: the KLM wordmark is dark charcoal with the orange mark, so it
   needs a light ground to read. The orange rule underneath ties the header to
   the brand without competing with the logo itself. */
header {
    background: #fff;
    border-bottom: 1px solid var(--border);
    padding: 0 24px;
}
.user-bar {
    display: flex; justify-content: flex-end; align-items: center; gap: 12px;
    font-size: 12px; color: var(--muted); max-width: 1320px; margin: 0 auto;
    flex-wrap: wrap; padding: 6px 0 0 0;
}
.user-bar a { color: var(--muted); text-decoration: none; }
.user-bar a:hover { color: var(--accent); }
.header-inner {
    max-width: 1320px; margin: 0 auto; display: flex; align-items: center;
    gap: 16px; padding: 4px 0 14px 0;
}
.brand-logo { height: 38px; width: auto; flex: none; display: block; }
.brand-divider { width: 1px; align-self: stretch; background: var(--border); }
header h1 { margin: 0; font-size: 15px; font-weight: 600; color: var(--blue); letter-spacing: 0.2px; }
header h1 a { color: var(--blue); text-decoration: none; }
header h1 a:hover { color: var(--accent); }
.subtitle { margin: 1px 0 0 0; color: var(--muted); font-size: 12px; }

/* Login screen lockup */
.auth-logo { display: block; width: 100%; max-width: 260px; margin: 0 auto 18px auto; }

nav.main {
    background: var(--blue-dark);
    padding: 0 24px;
    border-bottom: 3px solid var(--accent);
}
nav.main ul {
    list-style: none; display: flex; gap: 2px; margin: 0 auto; padding: 0;
    max-width: 1320px; flex-wrap: wrap;
}
nav.main a {
    display: block; padding: 10px 14px; color: #c6d0da; text-decoration: none;
    font-size: 13px; font-weight: 500; border-bottom: 3px solid transparent;
    margin-bottom: -3px;
}
nav.main a:hover { color: #fff; background: rgba(255,255,255,0.06); }
nav.main a.active { color: #fff; border-bottom-color: var(--accent); }

/* The step number beside a label - Estimating's bar is the system, in order */
nav.main .nav-step {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; border-radius: 50%; margin-right: 7px; vertical-align: -3px;
    background: var(--accent); color: #fff; font-size: 11px; font-weight: 700; line-height: 1;
}
nav.main a.active .nav-step { background: #fff; color: var(--accent); }

/* The quieter second row: libraries and setup */
nav.main ul.more { border-top: 1px solid rgba(255,255,255,0.08); }
nav.main ul.more a { font-size: 12px; padding: 6px 10px; color: #93a3b3; }
nav.main ul.more .more-label {
    color: #6f8093; font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
    padding: 8px 12px 0 0; white-space: nowrap;
}

main { max-width: 1320px; margin: 22px auto; padding: 0 16px 60px 16px; }

/* ------------------------------------------------------------------- cards */
.card {
    background: var(--card-bg); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 18px 20px; margin-bottom: 18px;
}
.card h2 {
    margin: 0 0 12px 0; font-size: 12px; font-weight: 700; color: var(--muted);
    text-transform: uppercase; letter-spacing: 0.08em;
}
.card h2 .count { color: var(--muted); font-weight: 500; }
.card-head { display: flex; justify-content: space-between; align-items: center; gap: 12px;
             padding-bottom: 10px; border-bottom: 1px solid var(--border); margin-bottom: 14px; }
.card-head h2 { margin-bottom: 0; }
.grid.two, .grid.three { align-items: start; }

.grid { display: grid; gap: 16px; }
.grid.two { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }
.grid.three { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

/* -------------------------------------------------------------------- kpis */
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; margin-bottom: 18px; }
.kpi {
    background: var(--card-bg); border: 1px solid var(--border); border-top: 3px solid var(--border);
    border-radius: var(--radius); padding: 13px 16px;
}
.kpi .label {
    font-size: 10.5px; color: var(--muted); text-transform: uppercase;
    letter-spacing: 0.08em; font-weight: 600;
}
.kpi .value { font: 800 26px/1.1 var(--font-display); font-size: clamp(18px, 1.1vw + 8px, 26px); margin-top: 4px;
              color: var(--heading-ink); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; overflow-wrap: anywhere; }
.kpi .sub { font-size: 12px; color: var(--muted); margin-top: 3px; }
.kpi.accent { border-top-color: var(--app-accent); }
.kpi.warn .value, .kpi.warn .sub { color: var(--red); }
@media (min-width: 1100px) { .kpis.five { grid-template-columns: repeat(5, minmax(0, 1fr)); } }

/* ------------------------------------------------------------------ tables */
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { padding: 9px 12px; text-align: left; border-bottom: 1px solid var(--border); vertical-align: top; }
th {
    background: transparent; font-size: 11px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted);
    white-space: nowrap; border-bottom: 2px solid var(--border);
}
tfoot th { border-top: 2px solid var(--border); border-bottom: 0; text-transform: none; letter-spacing: 0;
           font-size: 13px; color: var(--text); }
td:first-child a { font-weight: 600; text-decoration: none; }
.table-wrap { -webkit-overflow-scrolling: touch; }
tbody tr:hover td { background: var(--surface-hover); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
td.nowrap, th.nowrap { white-space: nowrap; }
.empty { color: var(--muted); padding: 22px 12px; text-align: center; background: var(--surface-2); border-radius: var(--radius-sm); }
.empty a { font-weight: 600; }

/* ------------------------------------------------------------------- pills */
.pill {
    display: inline-block; padding: 2px 9px; border-radius: 999px;
    font-size: 11px; font-weight: 600; white-space: nowrap;
}
.pill.live, .pill.approved, .pill.issued, .pill.won, .pill.passed,
.pill.verified, .pill.paid, .pill.complete, .pill.certified {
    background: var(--green-bg); color: var(--green);
}
.pill.lead, .pill.draft, .pill.planned, .pill.invited, .pill.pending,
.pill.not_started, .pill.scheduled { background: var(--surface-2); color: #47555f; }
.pill.quoted, .pill.submitted, .pill.applied, .pill.bidding, .pill.in_progress,
.pill.ready, .pill.partial, .pill.open, .pill.answered, .pill.mobilized,
.pill.approved_as_noted { background: #e7f0fa; color: var(--blue); }
.pill.lost, .pill.rejected, .pill.expired, .pill.failed, .pill.no_bid,
.pill.blocked, .pill.terminated, .pill.revise_resubmit, .pill.void {
    background: var(--red-bg); color: var(--red);
}
.pill.overdue { background: var(--red-bg); color: var(--red); }
.pill.completed, .pill.closed { background: #e9eaec; color: #55606b; }
.pill.tag {
    background: #fdf0e8; color: var(--accent-dark); margin: 0 3px 3px 0;
    border: 1px solid #f6dccb;
}

/* ----------------------------------------------------------------- buttons */
.btn {
    display: inline-block; padding: 8px 14px; border-radius: var(--radius-sm); border: 1px solid var(--blue);
    background: var(--blue); color: #fff; font-size: 13px; font-weight: 600;
    cursor: pointer; text-decoration: none; font-family: inherit; line-height: 1.3;
}
.btn:hover { background: var(--blue-dark); color: #fff; }
.btn.accent { background: var(--accent); border-color: var(--accent); }
.btn.accent:hover { background: var(--accent-dark); border-color: var(--accent-dark); }
.btn.ghost { background: transparent; color: var(--text); border-color: var(--border); }
.btn.ghost:hover { background: var(--surface-2); color: var(--blue); border-color: var(--blue); }
.btn.danger { background: #fff; color: var(--red); border-color: #e8c3bf; }
.btn.danger:hover { background: var(--red-bg); color: var(--red); }
.btn.small { padding: 4px 10px; font-size: 12px; }
.btn-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* ------------------------------------------------------------------- forms */
.field { margin-bottom: 13px; }
.field label { display: block; font-size: 12px; font-weight: 600; color: #46525e; margin-bottom: 4px; }
.field .help { font-size: 11.5px; color: var(--muted); margin-top: 3px; }
.field .req { color: var(--accent); }
input[type=text], input[type=password], input[type=email], input[type=date],
input[type=number], input[type=search], select, textarea {
    width: 100%; padding: 8px 10px; border: 1px solid var(--border); border-radius: 7px;
    font-size: 13px; font-family: inherit; background: var(--input-bg); color: var(--text);
}
input:focus, select:focus, textarea:focus {
    outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(18,49,79,0.1);
}
textarea { min-height: 76px; resize: vertical; }
.field.check { display: flex; align-items: center; gap: 8px; }
.field.check input { width: auto; }
.field.check label { margin: 0; }

fieldset {
    border: 1px solid var(--border); border-radius: 9px; padding: 14px 16px 4px 16px;
    margin: 0 0 16px 0;
}
legend {
    font-size: 11px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.05em; color: var(--accent-dark); padding: 0 6px;
}
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 0 16px; }
.form-grid .span-2 { grid-column: 1 / -1; }

.filters {
    display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end;
    margin-bottom: 14px;
}
.filters .field { margin-bottom: 0; min-width: 145px; }

.checks { display: grid; grid-template-columns: repeat(auto-fit, minmax(165px, 1fr)); gap: 4px 14px; }
.checks label { display: flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 500; color: var(--text); }
.checks input { width: auto; }

/* ------------------------------------------------------------------ alerts */
.flash { padding: 10px 14px; border-radius: 8px; margin-bottom: 14px; font-size: 13px; font-weight: 500; border: 1px solid; }
.flash.ok { background: var(--green-bg); color: var(--green); border-color: #b7e3c6; }
.flash.error { background: var(--red-bg); color: var(--red); border-color: #f0c4bf; }

.warn-banner {
    background: var(--amber-bg); border: 1px solid #ecd98a; color: var(--amber);
    padding: 9px 13px; border-radius: 8px; font-size: 12.5px; margin-bottom: 12px;
}

/* ------------------------------------------------------------------ detail */
.crumb { font-size: 12.5px; color: var(--muted); margin-bottom: 10px; }
.crumb a { color: var(--muted); }
.crumb a:hover { color: var(--accent); }

.page-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 16px; flex-wrap: wrap;
             padding-bottom: 14px; margin-bottom: 20px; border-bottom: 1px solid var(--border); }
.page-head h1 { margin: 0; font: 800 26px/1.15 var(--font-display); letter-spacing: -0.02em; color: var(--heading-ink); overflow-wrap: anywhere; }
.page-head > * { min-width: 0; }
.page-head .meta { font-size: 13px; color: var(--muted); margin-top: 4px; }
.page-head .eyebrow { display: block; font: 700 10.5px/1 var(--font-display); letter-spacing: 0.12em;
                      text-transform: uppercase; color: var(--app-accent); margin-bottom: 6px; }
.page-head .actions { display: flex; gap: 8px; flex-wrap: wrap; }

dl.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(195px, 1fr)); gap: 11px 20px; margin: 0; }
dl.facts dt { font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); font-weight: 600; }
dl.facts dd { margin: 1px 0 0 0; font-size: 13.5px; }

.modtiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; }
.modtile {
    display: block; padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--card-bg); text-decoration: none; color: var(--text);
}
.modtile:hover { border-color: var(--accent); background: var(--surface-hover); color: var(--text); }
.modtile .n { font-size: 21px; font-weight: 700; color: var(--blue); }
.modtile .l { font-size: 12px; color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; }

.bar { height: 7px; background: var(--surface-2); border-radius: 4px; overflow: hidden; min-width: 70px; }
.bar > div { height: 100%; background: var(--green); }
.bar.warn > div { background: var(--amber); }
.bar.bad > div { background: var(--red); }

.money-pos { color: var(--green); }
.money-neg { color: var(--red); }
.muted { color: var(--muted); }
.small { font-size: 12px; }

/* --------------------------------------------------------------- auth page */
.auth-wrap { max-width: 380px; margin: 8vh auto; }
.auth-wrap .card { padding: 26px 28px; }
.auth-wrap h1 { font-size: 20px; margin: 0 0 4px 0; color: var(--blue); }
.auth-wrap .sub { color: var(--muted); font-size: 13px; margin-bottom: 20px; }
.auth-wrap .btn { width: 100%; text-align: center; }
.auth-links { margin-top: 14px; font-size: 12.5px; text-align: center; }

/* ------------------------------------------------------------------ mobile */
@media (max-width: 640px) {
    header { padding: 8px 14px 14px 14px; }
    nav.main { padding: 0 8px; }
    nav.main a { padding: 9px 10px; font-size: 12.5px; }
    nav.main ul.more a { padding: 5px 8px; font-size: 11.5px; }
    main { padding: 0 10px 40px 10px; margin-top: 14px; }
    .card { padding: 14px; }
    .page-head h1 { font-size: 19px; }
    .form-grid { grid-template-columns: 1fr; }
    table { font-size: 12.5px; }
    th, td { padding: 7px 8px; }
}

@media print {
    header, nav.main, .shell-side, .shell-top, .shell-scrim, .btn, .btn-row, .filters { display: none !important; }
    .card { border: none; box-shadow: none; page-break-inside: avoid; }
    body { background: #fff; }
}

/* ------------------------------------------------------------------ gantt */
/* Pure CSS bars positioned by percentage — no charting library, so it stays
   fast, printable, and works with the strict styling of the rest of the app. */
.gantt { border: 1px solid var(--border); border-radius: 9px; overflow: hidden; }
.gantt-scroll { overflow-x: auto; }
.gantt-inner { min-width: 720px; }

.gantt-head {
    position: relative; height: 26px; background: var(--surface-2);
    border-bottom: 1px solid var(--border);
}
.gantt-month {
    position: absolute; top: 5px; font-size: 10.5px; font-weight: 700;
    color: #55606b; text-transform: uppercase; letter-spacing: 0.04em;
    padding-left: 5px; border-left: 1px solid var(--border); height: 21px;
    white-space: nowrap;
}

.gantt-row {
    position: relative; display: flex; align-items: center; gap: 0;
    border-bottom: 1px solid #eef1f4; min-height: 34px;
}
.gantt-row:hover { background: var(--surface-hover); }
.gantt-label {
    width: 230px; flex: none; padding: 6px 10px; font-size: 12.5px;
    border-right: 1px solid var(--border); overflow: hidden;
}
.gantt-label a { text-decoration: none; font-weight: 600; }
.gantt-label .sub { font-size: 11px; color: var(--muted); }
.gantt-track { position: relative; flex: 1; height: 34px; }

.gantt-bar {
    position: absolute; top: 9px; height: 16px; border-radius: 4px;
    background: var(--blue); overflow: hidden; min-width: 3px;
}
.gantt-bar .fill { height: 100%; background: var(--green); opacity: 0.95; }
.gantt-bar.not_started { background: #9aa6b2; }
.gantt-bar.in_progress { background: var(--blue); }
.gantt-bar.complete    { background: var(--green); }
.gantt-bar.blocked,
.gantt-bar.on_hold     { background: var(--red); }

/* The original plan, drawn as a thin ghost under the live bar. Only shown
   when a baseline exists, so an unplanned scope is not implied to have one. */
.gantt-baseline {
    position: absolute; top: 27px; height: 3px; border-radius: 2px;
    background: var(--faint);
}
.gantt-today {
    position: absolute; top: 0; bottom: 0; width: 2px; background: var(--accent);
    opacity: 0.8; z-index: 2;
}
.gantt-today-label {
    position: absolute; top: -1px; font-size: 9.5px; font-weight: 700;
    color: var(--accent); transform: translateX(3px); letter-spacing: 0.04em;
}
.gantt-legend {
    display: flex; gap: 14px; flex-wrap: wrap; font-size: 11.5px;
    color: var(--muted); padding: 9px 12px; background: var(--surface-2);
    border-top: 1px solid var(--border);
}
.gantt-legend .key { display: inline-flex; align-items: center; gap: 5px; }
.gantt-legend .swatch { width: 13px; height: 9px; border-radius: 2px; display: inline-block; }

/* --------------------------------------------------------- scope gallery */
.photo-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 10px;
}
.photo-grid figure { margin: 0; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; background: #fff; }
.photo-grid img { width: 100%; height: 120px; object-fit: cover; display: block; }
.photo-grid figcaption { font-size: 11.5px; padding: 6px 8px; color: var(--muted); }

/* Field notes: a dated running log, colour-coded by kind so an issue or a
   delay is visible at a glance in a long list. */
.notefeed { list-style: none; margin: 0; padding: 0; }
.notefeed li {
    border-left: 3px solid var(--border); padding: 8px 0 8px 12px; margin-bottom: 10px;
}
.notefeed li.issue { border-left-color: var(--red); }
.notefeed li.delay { border-left-color: var(--amber); }
.notefeed li.progress { border-left-color: var(--green); }
.notefeed .meta { font-size: 11.5px; color: var(--muted); margin-bottom: 2px; }
.notefeed .body { font-size: 13px; white-space: pre-wrap; }
/* =========================================================== dark theme ===
   Keyed only on [data-theme="dark"], with no prefers-color-scheme copy —
   theme.js resolves "system" to an explicit light/dark attribute before first
   paint, so CSS only ever sees a decided value. That keeps one source of
   truth and avoids the two disagreeing on a manual override.

   Only tokens are redefined. Every component above reads them, so nothing
   below needs to know a component exists. */
:root[data-theme="dark"] {
    --blue: #7Fb0e0;              /* links and headings: lifted for contrast on dark */
    --blue-dark: #A9CCEC;
    --blue-mid: #4E7CA8;
    --accent: #F07A38;            /* KLM orange, lightened so it stays legible */
    --accent-dark: #FF9358;

    --bg: #10151B;
    --card-bg: #171E26;
    --border: #2A343F;
    --text: #E4E9EF;
    --muted: #93A0AE;
    --faint: #5A6774;
    --surface-2: #1E2731;
    --surface-hover: #1C242E;
    --input-bg: #131A22;

    --green: #5BC98A;
    --green-bg: #16301F;
    --red: #F08279;
    --red-bg: #35191A;
    --amber: #E0B44A;
    --amber-bg: #322817;

    --shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
    --heading-ink: var(--text);
    color-scheme: dark;
}

/* The header is white in light mode because the wordmark is dark charcoal.
   In dark mode that would be a glaring white slab, so the header goes dark and
   the logo is inverted to sit on it — the mark is monochrome plus orange, so
   inverting reads correctly rather than turning muddy. */
:root[data-theme="dark"] header { background: var(--card-bg); }
:root[data-theme="dark"] .brand-logo,
:root[data-theme="dark"] .auth-logo { filter: invert(1) hue-rotate(180deg); }
:root[data-theme="dark"] nav.main { background: #0B1016; }
:root[data-theme="dark"] nav.main a { color: #A9B6C4; }
:root[data-theme="dark"] nav.main a:hover { color: #fff; background: rgba(255,255,255,0.05); }

:root[data-theme="dark"] td { border-bottom-color: #222b35; }
:root[data-theme="dark"] .pill.lead, :root[data-theme="dark"] .pill.draft,
:root[data-theme="dark"] .pill.planned, :root[data-theme="dark"] .pill.invited,
:root[data-theme="dark"] .pill.pending, :root[data-theme="dark"] .pill.not_started,
:root[data-theme="dark"] .pill.scheduled { background: #232D38; color: #B4C1CE; }
:root[data-theme="dark"] .pill.quoted, :root[data-theme="dark"] .pill.submitted,
:root[data-theme="dark"] .pill.applied, :root[data-theme="dark"] .pill.bidding,
:root[data-theme="dark"] .pill.in_progress, :root[data-theme="dark"] .pill.ready,
:root[data-theme="dark"] .pill.partial, :root[data-theme="dark"] .pill.open,
:root[data-theme="dark"] .pill.answered, :root[data-theme="dark"] .pill.mobilized,
:root[data-theme="dark"] .pill.approved_as_noted { background: #1B2C3D; color: #93BFE8; }
:root[data-theme="dark"] .pill.completed, :root[data-theme="dark"] .pill.closed {
    background: #262E36; color: #9DA9B5;
}
:root[data-theme="dark"] .pill.tag { background: #33241A; color: #F0A377; border-color: #4A3524; }

/* Buttons: the light theme uses a dark-blue fill with white text, which in
   dark mode would be a low-contrast blue-on-blue. Invert the relationship. */
:root[data-theme="dark"] .btn { background: var(--blue-mid); border-color: var(--blue-mid); color: #0C1218; }
:root[data-theme="dark"] .btn:hover { background: var(--blue); border-color: var(--blue); color: #0C1218; }
:root[data-theme="dark"] .btn.ghost { background: var(--card-bg); color: var(--blue); border-color: var(--border); }
:root[data-theme="dark"] .btn.ghost:hover { background: var(--surface-2); }
:root[data-theme="dark"] .btn.accent { color: #1A0C04; }
:root[data-theme="dark"] .btn.danger { background: var(--card-bg); color: var(--red); border-color: #4A2724; }

:root[data-theme="dark"] .gantt-bar.not_started { background: #566472; }
:root[data-theme="dark"] .gantt-bar.in_progress { background: var(--blue-mid); }
:root[data-theme="dark"] .photo-grid figure { background: var(--card-bg); }

/* Theme switch in the user bar */
.theme-toggle {
    background: none; border: 1px solid var(--border); border-radius: 6px;
    color: var(--muted); cursor: pointer; font: inherit; font-size: 11.5px;
    padding: 3px 9px; line-height: 1.4;
}
.theme-toggle:hover { color: var(--accent); border-color: var(--accent); }

/* ------------------------------------------------------- portal app tiles */
/* Same tile pattern as the BluLight portal, on KLM's own palette. Each tile
   takes its accent from the app it opens: PM is KLM navy, Estimating is the
   brand orange, Financial is money green. The badge keeps a pale field in
   both themes for the same reason BluLight's does - the KLM mark is navy and
   orange, which goes muddy on a dark card without a light chip under it. */
.app-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 20px;
    margin-bottom: 22px;
}
.app-tile {
    --tile-accent: var(--blue);
    --tile-accent-2: var(--blue-mid);
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: 10px;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 22px 20px 16px 20px;
    text-decoration: none;
    color: var(--text);
    box-shadow: var(--shadow);
    transition: transform .12s ease, border-color .12s ease, box-shadow .12s ease;
}
.tile-pm  { --tile-accent: var(--blue);   --tile-accent-2: var(--blue-mid); }
.tile-est { --tile-accent: var(--accent); --tile-accent-2: #E8803F; }
.tile-fin { --tile-accent: var(--green);  --tile-accent-2: #3d9c5e; }
.tile-stripe {
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 5px;
    background: linear-gradient(90deg, var(--tile-accent), var(--tile-accent-2));
}
.app-tile::after {
    content: "";
    position: absolute;
    top: -60px; right: -60px;
    width: 160px; height: 160px;
    border-radius: 50%;
    background: var(--tile-accent);
    opacity: 0;
    transition: opacity .12s ease;
}
.app-tile:hover::after { opacity: 0.08; }
.app-tile:hover {
    transform: translateY(-3px);
    border-color: var(--tile-accent);
    box-shadow: 0 6px 18px rgba(18, 49, 79, 0.14);
}
.app-tile:focus-visible { outline: 3px solid var(--tile-accent); outline-offset: 2px; }
.tile-badge {
    width: 72px; height: 72px;
    border-radius: 16px;
    background: #f2f5f8;
    border: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
}
.tile-badge img { width: 52px; height: 52px; object-fit: contain; }
.app-tile h3 { margin: 0; font-size: 17px; font-weight: 700; color: var(--text); }
.app-tile p  { margin: 0; font-size: 13px; color: var(--muted); line-height: 1.55; flex: 1; }
.tile-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-top: 1px solid var(--border);
    padding-top: 10px;
    margin-top: 4px;
}
.tile-host { font-size: 12px; color: var(--faint); }
.tile-open { font-size: 13px; font-weight: 600; color: var(--tile-accent); }
.app-tile:hover .tile-open { text-decoration: underline; }

/* ---------- plan takeoff: staged flow ---------- */
/* Step rail. One pill per step; the current one carries the accent, finished
   ones go green. Pure CSS state - the template sets .now / .done. */
.steps { list-style: none; display: flex; gap: 8px; padding: 0; margin: 0 0 18px; flex-wrap: wrap; }
.step { display: flex; align-items: center; gap: 8px; padding: 7px 14px 7px 8px;
        border: 1px solid var(--border); border-radius: 999px; color: var(--muted);
        font-size: 13.5px; background: var(--card-bg); }
.step-dot { width: 24px; height: 24px; border-radius: 50%; display: inline-flex;
            align-items: center; justify-content: center; font-size: 12.5px; font-weight: 700;
            background: var(--surface-2); border: 1px solid var(--border); color: var(--muted); }
.step.now { border-color: var(--accent); color: var(--text); box-shadow: var(--shadow); }
.step.now .step-dot { background: var(--accent); border-color: var(--accent); color: #fff; }
.step.done { color: var(--text); }
.step.done .step-dot { background: var(--green); border-color: var(--green); color: #fff; }

/* Upload zone. The raw file input stays visible until JS arms the zone, so the
   page still works with scripts off. */
.dropzone { border: 2px dashed var(--border); border-radius: 12px; padding: 34px 20px;
            text-align: center; color: var(--muted); background: var(--surface-2);
            transition: border-color .15s, background .15s; }
.dropzone.js { cursor: pointer; }
.dropzone.js input[type="file"] { display: none; }
.dropzone.js:hover, .dropzone.drag { border-color: var(--accent); background: rgba(217, 88, 20, 0.06); }
.dropzone.has-file { border-style: solid; border-color: var(--green); }
.dropzone.busy { pointer-events: none; opacity: .6; }
.dz-icon { color: var(--accent); margin-bottom: 4px; }
.dz-title { font-size: 18px; font-weight: 700; color: var(--text); margin: 4px 0 2px; }
.dz-sub { margin: 0; }
.dz-link { color: var(--accent); text-decoration: underline; font-weight: 600; }
.filechip { display: flex; align-items: center; gap: 12px; border: 1px solid var(--border);
            border-radius: 10px; padding: 10px 14px; margin-top: 12px; background: var(--card-bg); }
.filechip svg { color: var(--accent); flex: none; }
.filechip-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.filechip-text strong { overflow-wrap: anywhere; }
.up-actions { display: flex; gap: 14px; align-items: flex-end; flex-wrap: wrap; margin-top: 14px; }
.up-actions .up-scale { flex: 1; min-width: 220px; margin: 0; }
#upprog { margin-top: 14px; }

/* The uploaded-file identity bar shown on every later step. */
.filebar { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.filebar-icon { color: var(--accent); flex: none; display: flex; }
.filebar-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.filebar-text strong { overflow-wrap: anywhere; font-size: 15px; }

/* Sheet previews: the proof the right PDF went up. */
.sheetgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
             gap: 14px; margin-top: 12px; }
.sheet-card { margin: 0; border: 1px solid var(--border); border-radius: 10px;
              overflow: hidden; background: var(--card-bg); box-shadow: var(--shadow); }
.sheet-card > a { display: block; }
.sheet-thumb { display: block; width: 100%; height: 150px; object-fit: cover;
               object-position: left top; background: #fff; border-bottom: 1px solid var(--border); }
.sheet-card > a:hover .sheet-thumb { opacity: .85; }
.sheet-cap { padding: 10px 12px; display: flex; flex-direction: column; gap: 5px;
             font-size: 13px; align-items: flex-start; }
.sheet-name { display: flex; gap: 8px; align-items: baseline; }

/* Duct + AI count side by side on a wide screen, stacked on a phone. */
.toolrow { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
.toolrow > .card, .toolrow > form.card { margin: 0; }
@media (max-width: 900px) { .toolrow { grid-template-columns: 1fr; } }

/* Indeterminate stripe for "the server is thinking" - no percentage exists yet. */
.bar.indet { overflow: hidden; }
.bar.indet > div { width: 40% !important; animation: bar-indet 1.2s linear infinite; }
@keyframes bar-indet { from { margin-left: -40%; } to { margin-left: 100%; } }
@media (prefers-reduced-motion: reduce) { .bar.indet > div { animation: none; width: 100% !important; opacity: .5; } }

:root[data-theme="dark"] .dropzone.js:hover,
:root[data-theme="dark"] .dropzone.drag { background: rgba(240, 122, 56, 0.10); }
:root[data-theme="dark"] .sheet-thumb { background: #fff; }

/* the [hidden] attribute must always win over the flex display above */
.filechip[hidden], #upprog[hidden] { display: none; }
/* ============================================================ DRAWING VIEWER ===
   The CAD / vector-PDF viewer (cad_view.html + cad.js). Everything is a class under
   .cad-app, and every colour is a token, so the dark theme needs nothing of its own. */
main:has(.cad-app) { max-width: none; padding-left: 14px; padding-right: 14px; }
.cad-app { display: flex; flex-direction: column; gap: 10px; }
.cad-top { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
.cad-title { display: flex; align-items: center; gap: 10px; min-width: 0; }
.cad-title strong { font-size: 16px; color: var(--blue); overflow-wrap: anywhere; }
.cad-back { font-size: 20px; text-decoration: none; color: var(--muted); padding: 2px 8px; border-radius: 6px; }
.cad-back:hover { background: var(--surface-2); color: var(--blue); }
.cad-noscale { color: var(--amber); font-weight: 600; }
.cad-tools { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.cad-tool { border: 1px solid var(--border); background: var(--card-bg); color: var(--text);
    padding: 6px 12px; border-radius: 6px; font-size: 13px; cursor: pointer; }
.cad-tool:hover { background: var(--surface-2); }
.cad-tool.on { background: var(--blue); border-color: var(--blue); color: #fff; }
:root[data-theme="dark"] .cad-tool.on { color: #0B1016; }
.cad-sep { width: 1px; height: 22px; background: var(--border); margin: 0 4px; }
.cad-sheet { max-width: 190px; }
.cad-warn { background: var(--amber-bg); color: var(--amber); border: 1px solid var(--border);
    border-radius: 8px; padding: 8px 12px; font-size: 13px; }
.cad-warn p { margin: 2px 0; }
.cad-body { display: grid; grid-template-columns: 340px minmax(0, 1fr); gap: 10px;
    height: calc(100vh - 250px); min-height: 460px; }
.cad-side { background: var(--card-bg); border: 1px solid var(--border); border-radius: 10px;
    display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.cad-tabs { display: flex; border-bottom: 1px solid var(--border); }
.cad-tab { flex: 1; background: none; border: 0; border-bottom: 2px solid transparent; padding: 9px 4px;
    font-size: 13px; color: var(--muted); cursor: pointer; }
.cad-tab.on { color: var(--blue); border-bottom-color: var(--accent); font-weight: 600; }
.cad-pane { display: flex; flex-direction: column; min-height: 0; flex: 1; padding: 8px; gap: 6px; }
.cad-pane.tab-off { display: none; }
.cad-pane form { display: flex; flex-direction: column; min-height: 0; flex: 1; gap: 6px; margin: 0; }
.cad-row input[type=search] { width: 100%; }
.cad-row-btns { display: flex; gap: 6px; flex-wrap: wrap; }
.cad-note { margin: 0; font-size: 12px; }
.cad-list { list-style: none; margin: 0; padding: 0; overflow-y: auto; flex: 1; min-height: 0; }
.cad-item { display: flex; align-items: center; gap: 6px; padding: 3px 4px; border-radius: 5px; flex-wrap: wrap; }
.cad-item:hover { background: var(--surface-hover); }
.cad-item.sel { background: var(--surface-2); box-shadow: inset 3px 0 0 var(--accent); }
.cad-sw { width: 11px; height: 11px; border-radius: 2px; flex: none; border: 1px solid var(--border); }
.cad-name { flex: 1; min-width: 0; background: none; border: 0; padding: 2px 0; text-align: left;
    color: var(--text); font-size: 12.5px; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cad-name:hover { color: var(--blue); }
.cad-solo { background: none; border: 0; color: var(--faint); font-size: 11px; cursor: pointer; padding: 0 2px; visibility: hidden; }
.cad-item:hover .cad-solo, .cad-solo:focus { visibility: visible; }
.cad-solo:hover { color: var(--accent); }
.cad-q { font-size: 12px; color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.cad-empty { color: var(--muted); font-size: 12.5px; padding: 8px 4px; }
.cad-more { flex-basis: 100%; padding: 2px 4px 6px 4px; }
.cad-more[hidden] { display: none; }
.cad-more p { margin: 4px 0 2px; font-size: 12px; }
.cad-sub { margin: 0; padding-left: 16px; font-size: 12px; max-height: 180px; overflow-y: auto; }
.cad-qty { overflow-y: auto; flex: 1; min-height: 0; }
.cad-qhead { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted);
    padding: 8px 2px 3px; border-bottom: 1px solid var(--border); position: sticky; top: 0; background: var(--card-bg); }
.cad-qrow { display: grid; grid-template-columns: 18px minmax(0, 1fr) auto auto; gap: 2px 6px; align-items: center;
    padding: 4px 2px; border-bottom: 1px solid var(--border); }
.cad-qname { font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cad-scope { grid-column: 2 / -1; width: 100%; font-size: 12px; padding: 3px 4px; }
.cad-x { background: none; border: 0; color: var(--muted); cursor: pointer; font-size: 15px; line-height: 1; }
.cad-x:hover { color: var(--red); }
.cad-push { border-top: 1px solid var(--border); padding-top: 8px; display: flex; flex-direction: column; gap: 6px; }
.cad-push select { width: 100%; }
.cad-check { font-size: 12.5px; display: flex; gap: 6px; align-items: center; }
.cad-stage { position: relative; background: var(--card-bg); border: 1px solid var(--border);
    border-radius: 10px; overflow: hidden; min-height: 0; }
#cad-canvas { display: block; width: 100%; height: 100%; touch-action: none; cursor: default; outline: none; }
#cad-canvas.cross { cursor: crosshair; }
#cad-canvas.grab { cursor: grabbing; }
.cad-load { position: absolute; left: 50%; top: 42%; transform: translate(-50%, -50%);
    width: min(440px, 86%); text-align: center; }
.cad-load[hidden], .cad-pop[hidden], .cad-warn[hidden], #cad-keep[hidden], .cad-sheet[hidden] { display: none; }
.cad-load.bad #cad-load-text { color: var(--red); font-weight: 600; }
.cad-load.bad .bar { display: none; }
.cad-pop { position: absolute; left: 50%; top: 14px; transform: translateX(-50%); background: var(--card-bg);
    border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 6px 24px rgba(0,0,0,.18);
    padding: 10px 12px; width: min(380px, 92%); }
.cad-pop label { font-weight: 600; font-size: 13px; }
.cad-pop-row { display: flex; gap: 6px; margin: 6px 0 2px; }
.cad-pop-row input { flex: 1; min-width: 0; }
.cad-status { position: absolute; left: 0; right: 0; bottom: 0; display: flex; gap: 12px; align-items: center;
    padding: 5px 10px; font-size: 12.5px; background: var(--surface-2); border-top: 1px solid var(--border);
    min-height: 30px; flex-wrap: wrap; }
#cad-hint { color: var(--muted); }
#cad-readout { font-weight: 600; color: var(--blue); }
.cad-coord { margin-left: auto; color: var(--muted); font-variant-numeric: tabular-nums; }
@media (max-width: 1099px) {
    .cad-body { grid-template-columns: minmax(0, 1fr); height: auto; }
    .cad-stage { height: 62vh; order: -1; }
    .cad-side { max-height: 60vh; }
    .cad-coord, #cad-hint { display: none; }
}
@media print { .cad-side, .cad-tools, .cad-status { display: none !important; } }

.cad-why { grid-column: 2 / -1; font-size: 11.5px; color: var(--green); }
.cad-why.cad-check-it, .cad-note.cad-check-it { color: var(--amber); }
.cad-note.cad-check-it:empty { display: none; }
.cad-new { display: flex; flex-direction: column; gap: 6px; }
.cad-new[hidden], .cad-cost[hidden], #qty-ai[hidden] { display: none; }
.cad-new select, .cad-new input { width: 100%; }
.cad-cost { border: 1px solid var(--accent); border-radius: 8px; padding: 8px; margin: 4px 0 8px;
    background: var(--surface-hover); display: flex; flex-direction: column; gap: 5px; }
.cad-cost-head { display: flex; justify-content: space-between; align-items: center; font-size: 13px; }
.cad-cost input[type=search] { width: 100%; }
.cad-cost .cad-list { max-height: 240px; flex: none; }
.cad-cost .cad-name { white-space: normal; }

.cad-why.cad-plain { color: var(--muted); }
.cad-qinfo { padding: 4px 2px; }
.cad-is { flex-basis: 100%; font-size: 11.5px; color: var(--green); padding-left: 2px; }
.cad-notes:empty { display: none; }
.cad-notes { border: 1px solid var(--border); border-left: 3px solid var(--amber); border-radius: 6px;
    padding: 6px 8px; background: var(--surface-hover); max-height: 150px; overflow-y: auto; flex: none; }
.cad-notes-head { margin: 0 0 3px; font-size: 12px; font-weight: 600; }

.cad-is.cad-fact { color: var(--muted); }

button.cad-qname.cad-qshow { background: none; border: 0; padding: 0; text-align: left; cursor: pointer;
    color: var(--blue); text-decoration: underline dotted; font: inherit; font-size: 12.5px; }
button.cad-qname.cad-qshow:hover { color: var(--accent); }

/* The walkthrough (Guide tab): one thing at a time, in plain words. */
.guide { display: flex; flex-direction: column; gap: 8px; min-height: 0; overflow-y: auto; flex: 1; }
.g-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px; }
.g-step button { border: 1px solid var(--border); background: var(--surface-2); color: var(--muted);
    border-radius: 999px; padding: 3px 9px; font-size: 11.5px; cursor: pointer; }
.g-step.now button { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }
.g-step.done button { color: var(--green); }
.g-card { border: 1px solid var(--border); border-radius: 10px; padding: 12px; background: var(--surface-hover);
    display: flex; flex-direction: column; gap: 8px; }
.g-card h3 { margin: 0; font-size: 16px; color: var(--blue); overflow-wrap: anywhere; }
.g-card p { margin: 0; }
.g-card select, .g-card input[type=text] { width: 100%; }
.g-big { font-size: 18px; font-weight: 700; }
.g-count { font-size: 11.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.g-think { font-size: 14px; }
.g-fact { font-size: 12.5px; color: var(--muted); border-left: 3px solid var(--border); padding-left: 8px; }
.g-facts { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; font-size: 13px; }
.g-facts li { padding-left: 22px; position: relative; }
.g-facts li::before { position: absolute; left: 0; top: 0; font-weight: 700; }
.g-facts li.ok::before { content: "\2713"; color: var(--green); }
.g-facts li.warn::before { content: "!"; color: var(--amber); }
.g-facts li .btn { margin-left: 6px; }
.g-btns { display: flex; flex-wrap: wrap; gap: 6px; }
.g-btns .btn { flex: 1 1 46%; text-align: center; }
.g-alt { border-top: 1px solid var(--border); padding-top: 8px; display: flex; flex-direction: column; gap: 6px; }
.g-list { list-style: none; margin: 0; padding: 0; max-height: 34vh; overflow-y: auto; }
.g-list li { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 2px 6px; align-items: center;
    padding: 4px 0; border-bottom: 1px solid var(--border); }
.g-row { background: none; border: 0; padding: 0; text-align: left; color: var(--text); font-size: 12.5px;
    cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.g-row:hover { color: var(--accent); }
.g-price { grid-column: 1 / -1; font-size: 11.5px; color: var(--green); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.g-notes { margin: 0; padding-left: 18px; font-size: 12.5px; max-height: 26vh; overflow-y: auto; }
.cad-tab { padding-left: 2px; padding-right: 2px; }

/* A row that is the same thing counted another way: shown, struck out of the price, explained. */
.cad-qrow.cad-over { opacity: .85; }
.cad-qrow.cad-over .cad-q { text-decoration: line-through; color: var(--muted); }
.cad-over-mark { color: var(--muted); width: 16px; text-align: center; }
.g-ask { border-top: 1px solid var(--border); padding-top: 8px; display: flex; flex-direction: column; gap: 6px; }
.g-ask .g-notes { max-height: 30vh; }
.g-ask .g-notes li { margin-bottom: 6px; }

.g-cond .g-facts li { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.g-cond-in { width: 84px; font-size: 12.5px; padding: 2px 4px; }
.g-src { font-size: 11.5px; flex-basis: 100%; overflow-wrap: anywhere; }

.g-firm-in { flex: 1 1 60%; min-width: 0; font-size: 13px; padding: 3px 6px; }

.g-quote { width: 100%; font: 12px/1.4 ui-monospace, Menlo, Consolas, monospace; }
.g-quote[hidden] { display: none; }
\n
/* The trade being priced: one tap, and the Guide, the quantities and the AI follow it. */
.trade-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-bottom: 8px; }
.trade-bar:empty { display: none; }
.trade-chip { border: 1px solid var(--border); background: var(--surface-2); color: var(--text);
    border-radius: 999px; padding: 3px 10px; font-size: 12px; cursor: pointer; }
.trade-chip.on { background: var(--blue); border-color: var(--blue); color: #fff; font-weight: 600; }

/* The one-button estimate: the project picker under the drop zone, the report bars, the check list. */
.up-project { display: flex; flex-wrap: wrap; gap: 10px 16px; margin: 12px 0; }
.up-project label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: var(--muted); min-width: 220px; flex: 1; }
.up-project label[hidden] { display: none; }
.up-actions .btn[hidden] { display: none; }
.set-basis { display: grid; grid-template-columns: 1fr auto; gap: 2px 8px; margin-bottom: 8px; font-size: 14px; }
.set-basis .bar { grid-column: 1 / -1; }
.set-check td { white-space: normal; vertical-align: top; }
.set-check .meta { font-size: 12px; max-width: 46ch; }
.set-act { white-space: nowrap; }
.set-act .btn { margin: 0 2px 4px 0; }
.set-pop[hidden] { display: none; }
.set-pop ul { list-style: none; padding: 0; margin: 8px 0; max-height: 40vh; overflow: auto; }
.set-pop li { margin-bottom: 4px; }
.set-pop li .btn { text-align: left; white-space: normal; }
.set-pop input[type=search] { width: 100%; }
.set-q li { margin-bottom: 6px; }

/* ============================================================== KLM motion ===
   klm-motion.js: progress drawn plainly - a line icon for the trade, a thin track that fills in
   the trade's colour, the figure in tabular numerals. One accent per trade, nothing drawn. */
:root {
    --kr-electrical: #D95814; --kr-hvac: #2F6DAE; --kr-plumbing: #1F7F8C; --kr-fire: #B3261E;
    --kr-framing: #7A6248; --kr-structural: #4E5968; --kr-measure: #12314F; --kr-plain: #12314F;
}
:root[data-theme="dark"] {
    --kr-electrical: #F07A38; --kr-hvac: #6FA3DC; --kr-plumbing: #4FB3BF; --kr-fire: #E2645C;
    --kr-framing: #B59A7C; --kr-structural: #9AA7B6; --kr-measure: #7FB0E0; --kr-plain: #7FB0E0;
}
.bar.wait.kr-src { display: none; }
.kr { display: flex; align-items: center; gap: 12px; margin: 6px 0; --kr: var(--kr-measure); }
.kr[hidden] { display: none; }
.kr-electrical { --kr: var(--kr-electrical); } .kr-hvac { --kr: var(--kr-hvac); }
.kr-plumbing { --kr: var(--kr-plumbing); } .kr-fire { --kr: var(--kr-fire); }
.kr-framing { --kr: var(--kr-framing); } .kr-structural { --kr: var(--kr-structural); }
.kr-plain { --kr: var(--kr-plain); }
.kr-ico { position: relative; flex: none; width: 30px; height: 30px; border-radius: 8px;
    border: 1px solid var(--border); background: var(--card-bg); color: var(--kr);
    display: grid; place-items: center; transition: background-color .3s, border-color .3s, color .3s; }
.kr-ico svg { width: 17px; height: 17px; grid-area: 1 / 1; transition: opacity .25s, transform .3s; }
.kr-ico .kr-check { opacity: 0; transform: scale(.6); }
.kr.full .kr-ico { background: var(--kr); border-color: var(--kr); color: #fff; }
.kr.full .kr-ico .kr-glyph { opacity: 0; transform: scale(.6); }
.kr.full .kr-ico .kr-check { opacity: 1; transform: none; }
.kr-track { flex: 1; height: 6px; border-radius: 3px; background: var(--surface-2);
    box-shadow: inset 0 0 0 1px var(--border); overflow: hidden; position: relative; }
.kr-fill { height: 100%; width: 0; border-radius: 3px; background: var(--kr);
    transition: width .6s cubic-bezier(.25, .8, .3, 1); position: relative; }
.kr.indet .kr-fill { width: 30%; animation: kr-slide 1.6s ease-in-out infinite alternate; opacity: .75; }
@keyframes kr-slide { from { transform: translateX(-10%); } to { transform: translateX(240%); } }
.kr-pct { flex: none; min-width: 3.4em; text-align: right; font-weight: 600; font-size: 13px;
    color: var(--muted); font-variant-numeric: tabular-nums; }
.kr.full .kr-pct { color: var(--kr); }
.kr.bad { --kr: var(--red); }

/* figures bars (budget used, % complete, cost by section) fill in when the page opens */
.bar:not(.wait) > div { animation: bar-grow .7s cubic-bezier(.25, .8, .3, 1) both; }
@keyframes bar-grow { from { width: 0; } }

/* an estimate from a whole drawing set: one line per piece of work */
.set-runs { display: flex; flex-direction: column; gap: 6px; margin: 8px 0 4px; }
.set-run-label { display: flex; justify-content: space-between; gap: 8px; font-size: 12px;
    letter-spacing: .04em; text-transform: uppercase; color: var(--muted); margin-top: 6px; }
.set-run-label b { color: var(--text); font-weight: 600; } .set-run-label span { text-transform: none; letter-spacing: 0; }
.reveal .set-trade { animation: klm-rise .4s cubic-bezier(.25, .8, .3, 1) backwards; }
.reveal .set-trade:nth-of-type(2) { animation-delay: .1s; } .reveal .set-trade:nth-of-type(3) { animation-delay: .2s; }
.reveal .set-trade:nth-of-type(4) { animation-delay: .3s; } .reveal .set-trade:nth-of-type(5) { animation-delay: .4s; }
@keyframes klm-rise { from { opacity: 0; transform: translateY(10px); } }

/* the punch list: the trade's line, filled row by row */
.punch-run { display: flex; align-items: center; gap: 14px; margin: 6px 0 12px; max-width: 720px; }
.punch-run > div:first-child { flex: 1; }
.punch-run .pw-word { flex: none; font-size: 13px; color: var(--muted); white-space: nowrap; }
.punch-run.complete .pw-word { color: var(--green); font-weight: 600; }

/* the activity card on the drawings page */
.klm-rank { display: grid; grid-template-columns: auto 1fr; gap: 4px 16px; align-items: center; }
.klm-rank .rk-badge { width: 52px; height: 52px; border-radius: 12px; background: var(--blue); display: grid; place-items: center; }
.klm-rank .rk-badge svg { width: 38px; }
.klm-rank .rk-name { font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
.klm-rank .rk-name::before { content: "Rank · "; font-weight: 500; }
.klm-rank .rk-next { color: var(--text); font-size: 14px; }
.klm-rank .rk-next b { font-variant-numeric: tabular-nums; }
.klm-rank .rk-row { grid-column: 1 / -1; }
.klm-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.klm-badges .bd { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px 3px 6px; border-radius: 6px;
    border: 1px solid var(--border); background: var(--surface-2); font-size: 12px; color: var(--text); }
.klm-badges .bd b { display: inline-grid; place-items: center; width: 18px; height: 18px; border-radius: 4px;
    background: var(--blue); color: #fff; font-size: 11px; font-weight: 600; }
.klm-badges .bd.locked { opacity: .45; }
.klm-badges .bd.locked b { background: var(--faint); }

@media (prefers-reduced-motion: reduce) {
    .kr *, .punch-run *, .bar > div, .reveal .set-trade { animation: none !important; transition: none !important; }
    .kr.indet .kr-fill { width: 100%; opacity: .35; }
}

/* ========================================================= KLM app shell ===
   The left rail ("Plumb line"): a navy rail carries the white-letter wordmark and
   the app's name; the brand orange does three jobs only - the lit item's keel, the
   step badges, the one primary button on a page. Appended last and scoped under
   body.shell / .shell-* so the header element rules above keep serving the guest
   chrome. KEEP THIS BLOCK LAST (only the print block below may follow it):
   .shell-side .user-bar .btn.ghost ties with the dark theme's .btn.ghost rule on
   specificity and wins only by coming later. */
:root {
    --side-w: 236px; --top-h: 52px;
    /* literal hexes on purpose: var(--blue-dark) turns pale in dark mode */
    --shell-bg: #0C2136; --shell-bg-2: #12314F; --shell-rule: #2C4A68;
    --shell-ink: #C6D0DA; --shell-ink-dim: #8FA2B4; --shell-ink-faint: #6F8499;
    --shell-hover: rgba(255,255,255,.05); --shell-active: rgba(255,255,255,.08); --shell-keel: #D95814;
    --app-accent: var(--blue);
}
:root[data-theme="dark"] {
    --shell-bg: #0D1117; --shell-bg-2: #141B23; --shell-rule: #262E38;
    --shell-ink: #B8C2CC; --shell-ink-dim: #8E98A3; --shell-ink-faint: #6B747E;
    --shell-hover: rgba(255,255,255,.04); --shell-active: rgba(255,255,255,.07); --shell-keel: #F07A38;
}
html[data-app="est"] { --app-accent: var(--accent); }
html[data-app="fin"] { --app-accent: var(--green); }

body.shell { display: grid; grid-template-columns: var(--side-w) minmax(0, 1fr); min-height: 100vh; }
.shell-side {
    position: sticky; top: 0; align-self: start; height: 100vh; overflow-y: auto;
    display: flex; flex-direction: column; background: var(--shell-bg); color: var(--shell-ink);
    border-right: 1px solid var(--shell-rule); z-index: 40;
}
.shell-brand { display: block; padding: 20px 18px 14px; text-decoration: none; }
.shell-logo { display: block; height: 22px; width: auto; }
.shell-app { display: block; margin-top: 8px; font: 700 10.5px/1 var(--font-display); letter-spacing: .14em;
             text-transform: uppercase; color: var(--shell-ink-dim); }
.shell-brand:hover .shell-app { color: #fff; }
.shell-back { display: inline-flex; align-items: center; gap: 6px; margin: 0 18px 14px; padding: 5px 10px; font-size: 12px;
              color: var(--shell-ink-dim); border: 1px solid var(--shell-rule); border-radius: var(--radius-sm); text-decoration: none; }
.shell-back:hover { color: #fff; border-color: var(--shell-ink-faint); }

.shell-nav { list-style: none; margin: 0; padding: 0; }
.shell-nav a {
    display: flex; align-items: center; gap: 10px; min-height: 40px; padding: 0 16px 0 15px;
    border-left: 3px solid transparent; color: var(--shell-ink); font: 500 13.5px/1.2 var(--font-ui); text-decoration: none;
}
.shell-nav a:hover { background: var(--shell-hover); color: #fff; }
.shell-nav a.active { background: var(--shell-active); border-left-color: var(--shell-keel); color: #fff; font-weight: 600; }
.shell-nav.has-steps a:not(.has-step) { padding-left: 45px; }      /* one label column under the badges */
.shell-nav .is-sub a { min-height: 30px; padding-left: 45px; font-size: 12.5px; color: var(--shell-ink-dim); }
.shell-nav.quiet a { min-height: 32px; font-size: 12.5px; color: var(--shell-ink-dim); padding-left: 15px; }
.shell-nav .is-sub a.active, .shell-nav.quiet a.active { color: #fff; }
.shell-group { margin: 18px 18px 4px; font: 700 10.5px/1 var(--font-display); letter-spacing: .12em;
               text-transform: uppercase; color: var(--shell-ink-dim); }
/* The step badge is one global class: the rail, the how-to and any page share it. */
.nav-step {
    display: inline-flex; align-items: center; justify-content: center; flex: none; width: 20px; height: 20px;
    border-radius: 50%; background: var(--accent); color: #1A0C04; font: 700 11px/1 var(--font-display);
}
.shell-nav a.active .nav-step { background: #fff; color: #A8410D; }

.shell-user { margin-top: auto; border-top: 1px solid var(--shell-rule); padding-top: 4px; }
.shell-side .user-bar {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-start; gap: 8px 12px;
    max-width: none; margin: 0; padding: 12px 16px 16px; font-size: 12px; color: var(--shell-ink-dim);
}
.shell-who { flex-basis: 100%; order: 0; display: flex; align-items: center; gap: 9px; color: #fff;
             font: 600 12.5px/1.2 var(--font-ui); min-width: 0; }
.shell-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shell-who small { font-weight: 500; color: var(--shell-ink-dim); font-size: 11px; }
.shell-avatar {
    flex: none; width: 28px; height: 28px; border-radius: 50%; background: var(--shell-bg-2); border: 1px solid var(--shell-rule);
    display: inline-flex; align-items: center; justify-content: center; font: 700 11px/1 var(--font-display); color: var(--shell-ink);
}
.shell-side .user-bar a { order: 1; color: var(--shell-ink-dim); text-decoration: none; }
.shell-side .user-bar a:hover { color: #fff; }
.shell-side .theme-toggle { order: 2; margin-left: auto; color: var(--shell-ink-dim); border-color: var(--shell-rule); }
.shell-side .theme-toggle:hover { color: #fff; border-color: var(--shell-ink-faint); }
.shell-side .user-bar form { order: 3; margin: 0; }
.shell-side .user-bar .btn.ghost { background: transparent; color: var(--shell-ink); border-color: var(--shell-rule); }
.shell-side .user-bar .btn.ghost:hover { background: var(--shell-hover); color: #fff; border-color: var(--shell-ink-faint); }
.shell-side .user-bar .pill.draft, :root[data-theme="dark"] .shell-side .pill.draft { background: rgba(217,88,20,.22); color: #F6B38C; }

.shell-main { max-width: 1400px; width: 100%; margin: 0; padding: 28px 32px 64px; }
.shell-main:has(.cad-app) { max-width: none; padding: 14px 16px 4px; }
body.shell .cad-body { height: calc(100vh - 212px); min-height: 460px; }   /* measured: main pad + page head + toolbar + scale row + warning = 209px above it at 1366x768 */
@media (max-width: 1099px) { body.shell .cad-body { height: auto; } }

.btn:focus-visible, .shell-nav a:focus-visible, .theme-toggle:focus-visible, .shell-menu:focus-visible,
.shell-back:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.shell-nav a:focus-visible { outline-offset: -2px; }        /* the rail clips outside rings */

/* ---- the phone: a top strip and a drawer. :target makes it work with scripts off;
        the inline script in base.html makes it smooth and closes it on Esc. */
.shell-top, .shell-scrim, .shell-close { display: none; }
@media (max-width: 759px) {
    body.shell { display: block; }
    .shell-top {
        position: sticky; top: 0; z-index: 50; display: flex; align-items: center; gap: 12px;
        height: var(--top-h); padding: 0 6px 0 14px; background: var(--shell-bg); color: #fff;
        border-bottom: 1px solid var(--shell-rule);
    }
    .shell-top-brand {
        display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; color: #fff; text-decoration: none;
        font: 700 12.5px/1 var(--font-display); letter-spacing: .1em; text-transform: uppercase;
    }
    .shell-mark { width: 28px; height: 28px; border-radius: 6px; }
    .shell-menu { width: 44px; height: 44px; display: grid; place-items: center; color: #fff; border-radius: var(--radius-sm); }
    .shell-side {
        position: fixed; inset: 0 auto 0 0; width: min(300px, 86vw); height: 100vh; height: 100dvh; z-index: 70;
        transform: translateX(-100%); visibility: hidden; transition: transform .2s ease, visibility .2s;
        box-shadow: 0 0 40px rgba(0,0,0,.4);
    }
    .shell-side:target, body.nav-open .shell-side { transform: none; visibility: visible; }
    .shell-scrim { position: fixed; inset: 0; background: rgba(12,33,54,.55); z-index: 60; }
    body.nav-open .shell-scrim, .shell-side:target ~ .shell-scrim { display: block; }
    .shell-close {
        display: block; position: absolute; top: 8px; right: 8px; width: 36px; height: 36px; line-height: 36px;
        text-align: center; color: var(--shell-ink); text-decoration: none; font-size: 22px;
    }
    body.nav-open { overflow: hidden; }
    .shell-main { padding: 16px 16px 48px; }
    .kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .page-head h1 { font-size: 22px; }
    .filters .field { flex: 1 1 140px; min-width: 0; }
}
@media (prefers-reduced-motion: reduce) { .shell-side { transition: none; } }

/* ---- print, last of all: the shell's grid and the dark theme's tokens must both lose
        here, and both are decided by source order. Paper is white whatever the screen was. */
@media print {
    :root, :root[data-theme="dark"] {
        --bg: #fff; --card-bg: #fff; --text: #16202B; --muted: #5f6b78; --heading-ink: #12314F;
        --border: #dfe4ea; --surface-2: #eef2f6; --blue: #12314F; --accent: #D95814;
    }
    body.shell { display: block; }
    .shell-main { max-width: none; padding: 0; }
}
