/* =============================================================================
   Deco Fabrinox ERP — design system
   =============================================================================
   Premium industrial ERP (rule 52): dense, quiet, fast to scan. No CDN, no
   framework — one stylesheet that loads instantly on a slow site connection and
   cannot break because someone else's server is down.

   Layout is a fixed sidebar plus a scrolling content column, collapsing to a
   drawer under 900px so a site engineer can use the same screens on a phone.
   ============================================================================= */

:root {
    /* Steel-and-brass palette: neutral greys with a warm accent, which is what
       the product itself looks like. */
    --ink:            #12161c;
    --ink-2:          #2b3440;
    --ink-3:          #55637a;
    --ink-4:          #8592a8;
    --line:           #dde3ec;
    --line-2:         #eaeef4;
    --surface:        #ffffff;
    --surface-2:      #f5f7fa;
    --surface-3:      #eef2f7;

    --brand:          #b4884a;
    --brand-dark:     #8f6a37;
    --brand-tint:     #fbf6ee;

    --nav-bg:         #161b23;
    --nav-bg-2:       #1f262f;
    --nav-text:       #a8b3c4;
    --nav-text-2:     #ffffff;

    --green:          #16794a;
    --green-bg:       #e7f4ee;
    --amber:          #9a6300;
    --amber-bg:       #fdf3e0;
    --red:            #b3261e;
    --red-bg:         #fdeceb;
    --blue:           #1c5aa8;
    --blue-bg:        #e9f1fb;
    --grey:           #55637a;
    --grey-bg:        #eef2f7;

    --radius:         6px;
    --radius-lg:      10px;
    --shadow-sm:      0 1px 2px rgba(18, 22, 28, .06);
    --shadow:         0 2px 8px rgba(18, 22, 28, .08);
    --shadow-lg:      0 12px 32px rgba(18, 22, 28, .14);

    --sidebar-w:      264px;
    --topbar-h:       56px;

    --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

*, *::before, *::after { box-sizing: border-box; }

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

body {
    margin: 0;
    font-family: var(--font);
    font-size: 14px;
    line-height: 1.5;
    color: var(--ink);
    background: var(--surface-2);
    -webkit-font-smoothing: antialiased;
}

a { color: var(--blue); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 1.25; letter-spacing: -.01em; }
h1 { font-size: 20px; }
h2 { font-size: 16px; }
h3 { font-size: 14px; }

p { margin: 0 0 .75rem; }

/* -- Layout ---------------------------------------------------------------- */

.shell { display: flex; min-height: 100vh; }

.sidebar {
    width: var(--sidebar-w);
    flex: 0 0 var(--sidebar-w);
    background: var(--nav-bg);
    background-image: linear-gradient(180deg, #1a212b 0%, var(--nav-bg) 220px);
    color: var(--nav-text);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
    overscroll-behavior: contain;
    border-right: 1px solid #0c1015;
}

.sidebar__brand {
    display: flex;
    align-items: center;
    gap: .625rem;
    padding: .875rem 1rem;
    border-bottom: 1px solid rgba(255, 255, 255, .07);
    color: var(--nav-text-2);
    font-weight: 600;
    font-size: 14px;
    letter-spacing: .01em;
    flex: 0 0 auto;
}
.sidebar__brand:hover { text-decoration: none; background: rgba(255, 255, 255, .03); }

.sidebar__mark {
    width: 32px; height: 32px;
    border-radius: 8px;
    background: linear-gradient(140deg, var(--brand) 0%, var(--brand-dark) 100%);
    display: grid; place-items: center;
    font-size: 12.5px; font-weight: 700; color: #fff;
    flex: 0 0 32px;
    letter-spacing: .04em;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .35);
}

/* Sized to the same 32px box as the wordmark it replaces, so the header height
   does not change with whatever aspect ratio the logo happens to have. */
.sidebar__logo {
    width: 32px; height: 32px;
    flex: 0 0 32px;
    object-fit: contain;
    border-radius: 6px;
    background: #fff;
    padding: 2px;
}

.sidebar__name { line-height: 1.25; }
.sidebar__brand small {
    display: block;
    font-size: 9.5px; font-weight: 600;
    color: #7d8ba0;
    letter-spacing: .1em; text-transform: uppercase;
    margin-top: .125rem;
}

/* The scrolling region is the nav alone, so the brand stays put at the top and
   the collapse control stays put at the bottom while fifty links move past. */
.nav {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: .5rem 0 1rem;
    scrollbar-width: thin;
    scrollbar-color: #333d4b transparent;
}
.nav::-webkit-scrollbar { width: 8px; }
.nav::-webkit-scrollbar-thumb { background: #333d4b; border-radius: 99px; }
.nav::-webkit-scrollbar-track { background: transparent; }

.nav__pinned { padding: .25rem .5rem .5rem; }

.nav__group { border-top: 1px solid rgba(255, 255, 255, .05); }
.nav__group:first-of-type { border-top: 0; }

/* The default disclosure triangle is drawn by the browser and sits at a size
   and colour we do not control, which is exactly the mismatch the icon sprite
   exists to avoid. */
.nav__head::-webkit-details-marker { display: none; }
.nav__head::marker { content: ""; }

.nav__head {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .625rem 1rem .625rem 1.0625rem;
    cursor: pointer;
    list-style: none;
    user-select: none;
}
.nav__head:hover { background: rgba(255, 255, 255, .035); }

.nav__head-text { flex: 1; min-width: 0; line-height: 1.3; }

.nav__head-title {
    display: block;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: #8b98ac;
}

/* One line saying what the group is for. It is the difference between a label
   somebody guesses at and a label somebody understands, and it costs a row. */
.nav__head-caption {
    display: block;
    font-size: 10.5px;
    color: #626f83;
    margin-top: .1875rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nav__chevron {
    width: 14px; height: 14px;
    flex: 0 0 14px;
    color: #5c6878;
    transition: transform .16s ease;
}
.nav__group[open] > .nav__head .nav__chevron { transform: rotate(90deg); }
.nav__group[open] > .nav__head .nav__head-title { color: var(--nav-text-2); }

.nav__body { padding: 0 .5rem .5rem; }

/* Setup sits after the sequence and is not part of it, so it is separated by a
   heavier rule rather than just being the last group in the list. */
.nav__group--admin { border-top: 1px solid rgba(255, 255, 255, .1); margin-top: .375rem; }

.nav__link {
    display: flex;
    align-items: center;
    gap: .625rem;
    padding: .4375rem .625rem;
    margin: 1px 0;
    border-radius: var(--radius);
    color: var(--nav-text);
    font-size: 13px;
    line-height: 1.35;
    position: relative;
}
.nav__link:hover { background: rgba(255, 255, 255, .06); color: var(--nav-text-2); text-decoration: none; }

.nav__link.is-active {
    background: rgba(180, 136, 74, .16);
    color: #fff;
    font-weight: 550;
}
/* A brass rule against the rail, so the current page is findable at a glance
   even in a group of eleven links. */
.nav__link.is-active::before {
    content: "";
    position: absolute;
    left: -.5rem; top: 50%;
    transform: translateY(-50%);
    width: 3px; height: 18px;
    border-radius: 0 3px 3px 0;
    background: var(--brand);
}
.nav__link.is-active .ico { color: var(--brand); opacity: 1; }

.nav__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.nav__badge {
    margin-left: auto;
    font-size: 10px;
    background: rgba(255, 255, 255, .12);
    padding: .0625rem .375rem;
    border-radius: 99px;
}

.sidebar__foot {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .5rem .75rem .625rem;
    border-top: 1px solid rgba(255, 255, 255, .07);
    background: rgba(0, 0, 0, .18);
}

.nav__collapse {
    background: none;
    border: 0;
    color: #7d8ba0;
    font: inherit;
    font-size: 11px;
    cursor: pointer;
    padding: .25rem .375rem;
    border-radius: var(--radius);
}
.nav__collapse:hover { color: var(--nav-text-2); background: rgba(255, 255, 255, .07); }

.sidebar__version { font-size: 10.5px; color: #5c6878; font-family: var(--mono); }

/* -- Icons ----------------------------------------------------------------- */

/* fill and stroke are set here rather than on every symbol, so a symbol that
   needs a solid dot can override with its own attribute and win. */
.ico {
    width: 17px; height: 17px;
    flex: 0 0 17px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: .78;
}
.nav__link:hover .ico { opacity: 1; }

.nav__chevron { fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }

/* Geometry only: 59 symbols that are never drawn until a <use> references one.
   It must take no space and must not be read aloud. */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 100;
    background: var(--surface);
    color: var(--ink);
    padding: .625rem 1rem;
    border: 1px solid var(--line);
    border-radius: 0 0 var(--radius) 0;
}
.skip-link:focus { left: 0; }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
    height: var(--topbar-h);
    background: var(--surface);
    border-bottom: 1px solid var(--line);
    display: flex;
    align-items: center;
    gap: .875rem;
    padding: 0 1rem;
    position: sticky;
    top: 0;
    z-index: 20;
}

.topbar__search { flex: 1; max-width: 460px; position: relative; display: flex; align-items: center; }

/* input[type=search] is matched by the generic form-control rule further down
   this file, at the same specificity and later in source order -- so a plain
   `.topbar__search input` loses, and the padding that clears the icon silently
   does not apply. The attribute is named here to win. This was already true of
   the glyph this icon replaced: the magnifier has been sitting on top of the
   placeholder text, and it took measuring the boxes to see it. */
.topbar__search input[type=search] {
    width: 100%;
    padding: .4375rem 2.25rem .4375rem 2.125rem;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface-2);
    font-size: 13px;
    font-family: inherit;
    color: var(--ink);
}
.topbar__search input::placeholder { color: var(--ink-4); }
.topbar__search input:focus {
    outline: 2px solid var(--brand);
    outline-offset: -1px;
    background: var(--surface);
}

.topbar__search-icon {
    position: absolute;
    left: .625rem;
    width: 15px; height: 15px;
    fill: none; stroke: var(--ink-4); stroke-width: 1.8;
    stroke-linecap: round; stroke-linejoin: round;
    pointer-events: none;
}

.topbar__key {
    position: absolute;
    right: .5rem;
    font-family: var(--mono);
    font-size: 10.5px;
    color: var(--ink-4);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 4px;
    padding: .0625rem .3125rem;
    pointer-events: none;
}
.topbar__search input:focus ~ .topbar__key { opacity: 0; }

/* The notification bell. `margin-left: auto` moves here from .topbar__user so
   the bell and the user chip travel together as one right-hand group -- with it
   left on the chip, the bell would sit stranded in the middle of the bar. */
.bell {
    position: relative;
    margin-left: auto;
    display: grid;
    place-items: center;
    width: 34px; height: 34px;
    border-radius: var(--radius);
    color: var(--ink-3);
}
.bell:hover { background: var(--surface-2); color: var(--ink); text-decoration: none; }
.bell--has { color: var(--brand-dark); }

.bell__count {
    position: absolute;
    top: 2px; right: 1px;
    min-width: 16px; height: 16px;
    padding: 0 4px;
    border-radius: 99px;
    background: var(--red);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
    border: 2px solid var(--surface);
    box-sizing: content-box;
}

.topbar__user { display: flex; align-items: center; gap: .625rem; }

/* An unread message reads as heavier than one already dealt with. */
.notes__item.is-unread { border-left-color: var(--brand); background: var(--brand-tint); }

.userchip {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .25rem .5rem .25rem .25rem;
    border-radius: 99px;
    color: var(--ink-2);
}
.userchip:hover { background: var(--surface-2); text-decoration: none; }
.userchip__text { line-height: 1.2; }
.userchip__text strong { display: block; font-size: 12.5px; font-weight: 600; }
.userchip__text small { display: block; font-size: 10.5px; color: var(--ink-3); }

.avatar {
    width: 30px; height: 30px; border-radius: 50%;
    background: var(--brand-tint); color: var(--brand-dark);
    display: grid; place-items: center; font-size: 11.5px; font-weight: 700;
    border: 1px solid var(--line);
    flex: 0 0 30px;
}

.content { padding: 1.25rem; flex: 1; max-width: 1600px; width: 100%; }

.menu-toggle {
    display: none;
    background: none; border: 0;
    cursor: pointer;
    color: var(--ink-2);
    padding: .375rem;
    border-radius: var(--radius);
    line-height: 0;
}
.menu-toggle:hover { background: var(--surface-2); }
.menu-toggle .ico { width: 20px; height: 20px; flex-basis: 20px; opacity: 1; }

/* -- Page header ----------------------------------------------------------- */

.page-head {
    display: flex;
    align-items: flex-start;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}
/* An employee's photograph, beside the name rather than buried in the file
   list. Fixed square with object-fit so a portrait and a landscape snapshot
   both land the same size -- a page whose header height depends on how
   somebody held their phone looks accidental. */
.employee-photo {
    width: 64px; height: 64px;
    flex: 0 0 64px;
    border-radius: var(--radius-lg);
    object-fit: cover;
    border: 1px solid var(--line);
    background: var(--surface-2);
}
.employee-photo--empty {
    display: grid; place-items: center;
    font-size: 20px; font-weight: 600;
    color: var(--ink-4);
    letter-spacing: .02em;
}

.page-head__text { flex: 1; min-width: 240px; }
.page-head__sub { color: var(--ink-3); font-size: 13px; margin-top: .1875rem; }
.page-head__actions { display: flex; gap: .5rem; flex-wrap: wrap; }

.breadcrumb { font-size: 12px; color: var(--ink-4); margin-bottom: .25rem; }
.breadcrumb a { color: var(--ink-3); }

/* -- Cards ----------------------------------------------------------------- */

.card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    margin-bottom: 1rem;
}
.card__head {
    padding: .75rem 1rem;
    border-bottom: 1px solid var(--line-2);
    display: flex;
    align-items: center;
    gap: .75rem;
    flex-wrap: wrap;
}
.card__head h2 { flex: 1; min-width: 140px; }
.card__body { padding: 1rem; }
.card__body--flush { padding: 0; }
.card__foot { padding: .75rem 1rem; border-top: 1px solid var(--line-2); background: var(--surface-2); border-radius: 0 0 var(--radius-lg) var(--radius-lg); }

/* -- Stat tiles ------------------------------------------------------------ */

.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: .75rem; margin-bottom: 1rem; }

.tile {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    padding: .875rem 1rem;
    box-shadow: var(--shadow-sm);
}
.tile__label { font-size: 11.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-4); font-weight: 600; }
.tile__value { font-size: 24px; font-weight: 600; margin-top: .25rem; letter-spacing: -.02em; }
.tile__meta { font-size: 12px; color: var(--ink-3); margin-top: .1875rem; }
.tile--accent { border-left: 3px solid var(--brand); }
.tile--warn { border-left: 3px solid var(--amber); }
.tile--danger { border-left: 3px solid var(--red); }
.tile--ok { border-left: 3px solid var(--green); }
.tile a { color: inherit; }

/* -- Tables ---------------------------------------------------------------- */

.table-wrap { overflow-x: auto; }

table.data {
    width: 100%;
    border-collapse: collapse;
    font-size: 13.5px;
}
table.data th {
    text-align: left;
    padding: .5rem .75rem;
    background: var(--surface-3);
    border-bottom: 1px solid var(--line);
    font-size: 11.5px;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--ink-3);
    font-weight: 600;
    white-space: nowrap;
    position: sticky;
    top: 0;
}
table.data th a { color: inherit; display: inline-flex; gap: .25rem; align-items: center; }
table.data td { padding: .5rem .75rem; border-bottom: 1px solid var(--line-2); vertical-align: middle; }
table.data tbody tr:hover { background: var(--surface-2); }
table.data tbody tr:last-child td { border-bottom: 0; }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.center { text-align: center; }
.nowrap { white-space: nowrap; }
.code { font-family: var(--mono); font-size: 12.5px; color: var(--ink-2); }
.muted { color: var(--ink-4); }
.small { font-size: 12px; }

/* Right-aligned action column that stays out of the way until hovered. */
.row-actions { display: flex; gap: .375rem; justify-content: flex-end; }

/* -- Badges ---------------------------------------------------------------- */

.badge {
    display: inline-block;
    padding: .125rem .4375rem;
    border-radius: 99px;
    font-size: 11.5px;
    font-weight: 500;
    line-height: 1.5;
    white-space: nowrap;
}
.badge--green { background: var(--green-bg); color: var(--green); }
.badge--amber { background: var(--amber-bg); color: var(--amber); }
.badge--red   { background: var(--red-bg);   color: var(--red); }
.badge--blue  { background: var(--blue-bg);  color: var(--blue); }
.badge--grey  { background: var(--grey-bg);  color: var(--grey); }

.dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: .375rem; }
.dot--green { background: var(--green); }
.dot--amber { background: var(--amber); }
.dot--red { background: var(--red); }
.dot--grey { background: var(--ink-4); }

/* -- Buttons --------------------------------------------------------------- */

.btn {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    padding: .4375rem .75rem;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--ink-2);
    font-size: 13.5px;
    font-family: inherit;
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
    line-height: 1.4;
}
.btn:hover { background: var(--surface-2); text-decoration: none; border-color: var(--ink-4); }
.btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.btn--primary { background: var(--ink); border-color: var(--ink); color: #fff; }
.btn--primary:hover { background: var(--ink-2); border-color: var(--ink-2); }
.btn--brand { background: var(--brand); border-color: var(--brand); color: #fff; }
.btn--brand:hover { background: var(--brand-dark); border-color: var(--brand-dark); }
.btn--danger { color: var(--red); border-color: #f0c4c1; }
.btn--danger:hover { background: var(--red-bg); border-color: var(--red); }
.btn--sm { padding: .25rem .5rem; font-size: 12.5px; }
/* Quiet by default, outlined on approach. For controls that must be reachable
   without competing with the page's real action -- Sign out beside a user's
   own name is the case this was added for. */
.btn--ghost { background: transparent; border-color: transparent; color: var(--ink-3); }
.btn--ghost:hover { background: var(--surface-2); border-color: var(--line); color: var(--ink-2); }
.btn--block { width: 100%; justify-content: center; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }

.btn-group { display: inline-flex; gap: .375rem; }

/* -- Forms ----------------------------------------------------------------- */

/* The hidden ATTRIBUTE must always win.
   -------------------------------------------------------------------------
   The browser hides [hidden] with `display: none` from its own stylesheet,
   which any author rule setting `display` silently beats. `.form-grid` sets
   `display: grid`, so `element.hidden = true` did NOTHING to the tube and
   bought-out field groups on the BOQ line form: the section-type chooser
   thought it was hiding them, the fields stayed on screen for every section
   type, and the form did not adapt the way the whole feature depends on.

   Declared before the rules it protects and marked !important, because the
   point of the attribute is that it outranks layout. */
[hidden] { display: none !important; }

.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: .875rem 1rem; }
.form-grid--2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.field--full { grid-column: 1 / -1; }

/* Three across rather than two, for forms of short fields — dates, codes,
   percentages — where two columns leaves half the row empty. Same auto-fit
   mechanism as the others, with a narrower minimum, so it still collapses to
   one column on a phone instead of producing three unusable slivers.

   Used by 21 views and defined by none of them until now: every one of those
   screens has been quietly falling back to the default column count. */
.form-grid--3 { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }

/* A field that sits ON the line with its label and whatever follows it —
   a reason box beside the button that needs it, rather than stacked above.
   `.field` is a column by default; this turns that row-wise and stops the
   label wrapping, which is what made these look broken when undefined. */
.field--inline { flex-direction: row; align-items: center; gap: .5rem; }
.field--inline > label { margin: 0; white-space: nowrap; font-size: 12px; }
.field--inline input, .field--inline select { min-width: 0; }

/* A one-line form: a field or two and the button that submits them, aligned
   along their bottom edge so the button sits level with the inputs rather
   than with the labels above them. */
.form-inline { display: flex; align-items: flex-end; gap: .625rem; flex-wrap: wrap; }

/* A row of actions, usually several small forms side by side. */
.btn-row { display: flex; align-items: flex-end; gap: .5rem; flex-wrap: wrap; }

/* Explanatory text that is not attached to a field. Deliberately identical to
   `.field .help`, because a hint reading differently depending on whether it
   happens to sit inside a field wrapper is a difference nobody intended. */
.hint { font-size: 11.5px; color: var(--ink-4); line-height: 1.5; }

/* -- Notes on a record ------------------------------------------------------
   Read newest first, so the list is scanned from the top and the meta line
   carries who and when before the words. The withdraw control sits on that
   meta line rather than under the text, where it would compete with the note
   itself for attention. */

.notes { list-style: none; margin: 0; padding: 0; }

.notes__item {
    border-left: 3px solid var(--line);
    padding: .5rem 0 .5rem .75rem;
    margin-bottom: .75rem;
}
.notes__item:last-child { margin-bottom: 0; }

.notes__meta {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
    font-size: 12px;
    margin-bottom: .25rem;
}
.notes__withdraw { margin-left: auto; }

.notes__body { font-size: 13.5px; color: var(--ink-2); line-height: 1.55; }

/* The photograph already on file, shown beside the replace control so it is
   obvious what a new upload would displace. */
.photo-current { display: flex; align-items: center; gap: .75rem; margin-bottom: .375rem; }

/* -- The guided quotation path ---------------------------------------------
   A numbered rail rather than a list of cards, because the point is the ORDER.
   The connecting line is drawn between the markers so the eye reads it as one
   path with a current position, not six unrelated boxes. */

.wizard { list-style: none; margin: 0; padding: 0; }

.wizard__step {
    display: flex;
    gap: 1rem;
    position: relative;
    padding-bottom: 1.25rem;
}

/* The rail. Drawn from each marker down to the next, and stopped on the last
   step so the path does not trail off into nothing. */
.wizard__step::before {
    content: "";
    position: absolute;
    left: 15px;
    top: 32px;
    bottom: 0;
    width: 2px;
    background: var(--line);
}
.wizard__step:last-child::before { display: none; }

.wizard__marker {
    position: relative;
    z-index: 1;
    flex: 0 0 32px;
    width: 32px; height: 32px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: 13px;
    font-weight: 600;
    background: var(--surface);
    color: var(--ink-3);
    border: 2px solid var(--line);
}
.wizard__step.is-done .wizard__marker {
    background: var(--green-bg);
    border-color: var(--green);
    color: var(--green);
}
.wizard__step.is-current .wizard__marker {
    background: var(--brand);
    border-color: var(--brand);
    color: #fff;
}

.wizard__body {
    flex: 1;
    min-width: 0;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    padding: .875rem 1rem;
}
/* The step to do now is the only one that gets a coloured edge. Emphasising
   more than one would be emphasising none. */
.wizard__step.is-current .wizard__body { border-color: var(--brand); box-shadow: var(--shadow-sm); }

.wizard__head { display: flex; align-items: center; gap: .625rem; flex-wrap: wrap; }
.wizard__title { font-size: 15px; margin: 0; }
.wizard__detail { font-size: 13px; color: var(--ink-2); margin-top: .25rem; font-weight: 500; }
.wizard__why { font-size: 12.5px; color: var(--ink-3); margin: .5rem 0 0; line-height: 1.55; }

.field { display: flex; flex-direction: column; gap: .25rem; min-width: 0; }
.field > label { font-size: 12.5px; font-weight: 600; color: var(--ink-2); }
.field .req { color: var(--red); margin-left: .125rem; }
.field .help { font-size: 11.5px; color: var(--ink-4); }
.field .error { font-size: 11.5px; color: var(--red); font-weight: 500; }

input[type=text], input[type=email], input[type=password], input[type=number],
input[type=date], input[type=datetime-local], input[type=tel], input[type=url],
input[type=search], input[type=color], select, textarea {
    width: 100%;
    padding: .4375rem .5625rem;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    font-size: 13.5px;
    font-family: inherit;
    color: var(--ink);
    background: var(--surface);
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--brand); outline-offset: -1px; border-color: var(--brand); }
input[readonly], input:disabled, select:disabled { background: var(--surface-3); color: var(--ink-3); }
textarea { resize: vertical; min-height: 72px; }
input[type=color] { padding: .125rem; height: 34px; }
.has-error input, .has-error select, .has-error textarea { border-color: var(--red); background: #fffafa; }

.check { display: flex; align-items: center; gap: .5rem; font-size: 13.5px; }
.check input { width: 15px; height: 15px; margin: 0; accent-color: var(--brand); }

.checkbox-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: .375rem .875rem; }

fieldset { border: 0; padding: 0; margin: 0 0 1.5rem; }
fieldset > legend {
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--ink-3);
    font-weight: 600;
    padding: 0 0 .5rem;
    border-bottom: 1px solid var(--line-2);
    width: 100%;
    margin-bottom: .875rem;
}

.form-actions {
    display: flex;
    gap: .5rem;
    padding: .875rem 1rem;
    border-top: 1px solid var(--line-2);
    background: var(--surface-2);
    position: sticky;
    bottom: 0;
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
    flex-wrap: wrap;
}

/* -- Filter bar ------------------------------------------------------------ */

.filters {
    display: flex;
    gap: .5rem;
    flex-wrap: wrap;
    align-items: flex-end;
    padding: .75rem 1rem;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    margin-bottom: 1rem;
}
.filters .field { min-width: 140px; }
.filters .field--search { flex: 1; min-width: 200px; }

/* -- Alerts ---------------------------------------------------------------- */

.alert {
    padding: .625rem .875rem;
    border-radius: var(--radius);
    margin-bottom: .75rem;
    border-left: 3px solid;
    font-size: 13.5px;
    display: flex;
    gap: .5rem;
    align-items: flex-start;
}
.alert--success  { background: var(--green-bg); border-color: var(--green); color: #0f5334; }
.alert--error    { background: var(--red-bg);   border-color: var(--red);   color: #8b1c16; }
.alert--warning  { background: var(--amber-bg); border-color: var(--amber); color: #6f4700; }
.alert--info     { background: var(--blue-bg);  border-color: var(--blue);  color: #164a8c; }
.alert strong { font-weight: 600; }

/* -- Empty state ----------------------------------------------------------- */

.empty { padding: 2.5rem 1rem; text-align: center; color: var(--ink-4); }
.empty__title { font-size: 15px; font-weight: 600; color: var(--ink-2); margin-bottom: .25rem; }
.empty__mark { font-size: 28px; opacity: .35; margin-bottom: .5rem; }

/* -- Pagination ------------------------------------------------------------ */

.pagination { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; }
.pagination__pages { display: flex; gap: .1875rem; margin-left: auto; }
.pagination__pages a, .pagination__pages span {
    min-width: 30px;
    padding: .25rem .4375rem;
    text-align: center;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    font-size: 12.5px;
    color: var(--ink-2);
    background: var(--surface);
}
.pagination__pages a:hover { background: var(--surface-2); text-decoration: none; }
.pagination__pages .is-current { background: var(--ink); border-color: var(--ink); color: #fff; font-weight: 600; }
.pagination__pages .gap { border: 0; background: none; color: var(--ink-4); }

/* -- Detail lists ---------------------------------------------------------- */

.detail-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: .75rem 1.25rem; }
.detail dt { font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-4); font-weight: 600; }
.detail dd { margin: .125rem 0 0; font-size: 13.5px; word-break: break-word; }

/* -- Timeline (audit, status history) -------------------------------------- */

.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li { padding: .5rem 0 .5rem 1.125rem; border-left: 2px solid var(--line); position: relative; }
.timeline li::before {
    content: ""; position: absolute; left: -5px; top: .875rem;
    width: 8px; height: 8px; border-radius: 50%; background: var(--ink-4); border: 2px solid var(--surface);
}
.timeline li:last-child { border-left-color: transparent; }
.timeline__meta { font-size: 11.5px; color: var(--ink-4); }
.timeline__body { font-size: 13px; }

/* -- Tabs ------------------------------------------------------------------ */

.tabs { display: flex; gap: .25rem; border-bottom: 1px solid var(--line); margin-bottom: 1rem; overflow-x: auto; }
.tabs a {
    padding: .5rem .875rem;
    font-size: 13.5px;
    color: var(--ink-3);
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    white-space: nowrap;
    font-weight: 500;
}
.tabs a:hover { color: var(--ink); text-decoration: none; }
.tabs a.is-active { color: var(--ink); border-bottom-color: var(--brand); }

/* -- Utilities ------------------------------------------------------------- */

.stack > * + * { margin-top: .75rem; }
.row { display: flex; gap: .75rem; flex-wrap: wrap; align-items: center; }
.grow { flex: 1; }
.split { display: grid; grid-template-columns: 2fr 1fr; gap: 1rem; align-items: start; }
.mt-0 { margin-top: 0; } .mb-0 { margin-bottom: 0; }
.mt-1 { margin-top: .5rem; } .mb-1 { margin-bottom: .5rem; }
.mt-2 { margin-top: 1rem; } .mb-2 { margin-bottom: 1rem; }
.text-green { color: var(--green); } .text-red { color: var(--red); } .text-amber { color: var(--amber); }
.hide { display: none !important; }

.swatch { display: inline-block; width: 14px; height: 14px; border-radius: 3px; border: 1px solid var(--line); vertical-align: -2px; margin-right: .375rem; }

.thumb { width: 40px; height: 40px; object-fit: cover; border-radius: var(--radius); border: 1px solid var(--line); background: var(--surface-3); }

.progress { height: 6px; background: var(--surface-3); border-radius: 99px; overflow: hidden; }
.progress__bar { height: 100%; background: var(--brand); }

/* -- BOQ tree -------------------------------------------------------------- */

/* Depth is conveyed by indentation and a left accent, not by colour alone —
   the tree has to stay readable when printed in black and white. */
.boq-row--item td      { background: var(--surface-2); }
.boq-row--item td:nth-child(2) { box-shadow: inset 3px 0 0 var(--brand); }
.boq-row--sub_item td:nth-child(2)  { box-shadow: inset 3px 0 0 var(--blue); }
.boq-row--component td:nth-child(2) { box-shadow: inset 3px 0 0 var(--line); }

/* -- What a BOQ is, on the screen where one is built ------------------------
   Three columns so the levels read as a progression rather than a list, with
   the same colour coding as the rows in the table below -- the guide and the
   thing it explains should be recognisably the same three things. */

.boq-guide { border-bottom: 1px solid var(--line); background: var(--surface-2); }
.boq-guide > summary {
    padding: .625rem 1rem;
    cursor: pointer;
    font-size: 13px;
    font-weight: 600;
    color: var(--ink-2);
}
.boq-guide > summary:hover { background: var(--surface-3); }

.boq-guide__body {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 1rem;
    padding: 0 1rem 1rem;
}
.boq-guide__body > .small { grid-column: 1 / -1; }

.boq-guide__level {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: .75rem .875rem;
}
/* Matching the row stripes in the table, so the guide and the BOQ read as one. */
.boq-guide__level--item      { border-left: 3px solid var(--brand); }
.boq-guide__level--sub_item  { border-left: 3px solid var(--blue); }
.boq-guide__level--component { border-left: 3px solid var(--ink-4); }

/* Orientation at the top of a line form: example, what to enter, where the
   price comes from. Three short facts side by side rather than a paragraph,
   because somebody opening this form is looking for one of them and should not
   have to read the other two to find it. */
.line-intro {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: .75rem;
    margin-bottom: 1rem;
    padding: .75rem .875rem;
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    font-size: 12.5px;
    line-height: 1.55;
    color: var(--ink-3);
}
/* Choosing what a part IS. Cards rather than a dropdown, because the choice
   decides which of the boxes below matter and a one-line select gives somebody
   no way to tell a folded profile from a bought-out lock before committing. */
.section-choice {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: .625rem;
}
.section-choice__option {
    display: block;
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    padding: .625rem .75rem;
    cursor: pointer;
    background: var(--surface);
    font-size: 12px;
    line-height: 1.5;
    color: var(--ink-3);
}
.section-choice__option:hover { border-color: var(--ink-4); }
.section-choice__option.is-chosen { border-color: var(--brand); background: var(--brand-tint); }
.section-choice__option input { margin-right: .375rem; }

.section-choice__name {
    display: inline-block;
    font-size: 13px;
    font-weight: 700;
    color: var(--ink);
    margin-bottom: .25rem;
}
.section-choice__what,
.section-choice__enter,
.section-choice__weight { display: block; margin-top: .25rem; }
.section-choice__weight { color: var(--ink-4); }

.line-intro__item { min-width: 0; }
.line-intro__label {
    display: block;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--ink-4);
    margin-bottom: .1875rem;
}

/* A fieldset's own explanation, above its fields.
   Darker than a per-field hint on purpose: this is the instruction for the
   whole section, not an aside about one box, and at --ink-4 it read as
   decoration somebody could skip. */
fieldset > .hint {
    margin: 0 0 .75rem;
    max-width: 68ch;
    font-size: 12.5px;
    color: var(--ink-3);
}

.boq-guide__name { font-size: 13.5px; font-weight: 700; margin-bottom: .375rem; }
.boq-guide__body p { font-size: 12px; line-height: 1.55; margin: 0 0 .375rem; color: var(--ink-3); }
.boq-guide__what { color: var(--ink-2) !important; }

/* Three kinds of information, told apart at a glance rather than read in
   sequence: what it looks like, what you type, and where the money comes from.
   The last is the one people actually come looking for. */
.boq-guide__eg { font-style: italic; }
.boq-guide__enter { color: var(--ink-3); }
.boq-guide__cost {
    background: var(--surface-2);
    border-radius: var(--radius);
    padding: .3125rem .4375rem;
    margin-top: .5rem !important;
}
.boq-guide__body p:last-child { margin-bottom: 0; }
.boq-row--component { font-size: 13px; }
.boq-row td { vertical-align: top; }

/* Phase notice: honest placeholder for modules that are not built yet. */
.phase-note {
    border: 1px dashed var(--line);
    border-radius: var(--radius-lg);
    padding: .875rem 1rem;
    background: var(--surface);
    color: var(--ink-3);
    font-size: 13px;
}
.phase-note strong { color: var(--ink-2); }

/* -- Auth / install screens ------------------------------------------------ */

.auth-shell {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 1.5rem;
    background: linear-gradient(160deg, #161b23 0%, #232c38 55%, #2f3a49 100%);
}
.auth-card {
    width: 100%;
    max-width: 400px;
    background: var(--surface);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    padding: 1.75rem;
}
.auth-card--wide { max-width: 720px; }
.auth-card__brand { display: flex; align-items: center; gap: .625rem; margin-bottom: 1.25rem; }
.auth-card__brand .sidebar__mark { width: 34px; height: 34px; flex-basis: 34px; }

.check-list { list-style: none; margin: 0; padding: 0; font-size: 13.5px; }
.check-list li { display: flex; gap: .5rem; padding: .375rem 0; border-bottom: 1px solid var(--line-2); align-items: flex-start; }
.check-list li:last-child { border-bottom: 0; }
.check-list .ok { color: var(--green); font-weight: 700; }
.check-list .bad { color: var(--red); font-weight: 700; }

/* -- Print ----------------------------------------------------------------- */

@media print {
    .sidebar, .topbar, .page-head__actions, .filters, .form-actions, .row-actions { display: none !important; }
    body { background: #fff; }
    .card { border: 0; box-shadow: none; }
    .content { padding: 0; }
}

/* -- Responsive ------------------------------------------------------------ */

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

@media (max-width: 900px) {
    .menu-toggle { display: block; }

    .sidebar {
        position: fixed;
        z-index: 40;
        left: 0; top: 0;
        transform: translateX(-100%);
        transition: transform .18s ease;
        box-shadow: var(--shadow-lg);
    }
    body.nav-open .sidebar { transform: translateX(0); }
    body.nav-open::after {
        content: ""; position: fixed; inset: 0; background: rgba(18,22,28,.45); z-index: 30;
    }

    .content { padding: .875rem; }
    .topbar { padding: 0 .875rem; }
    .tiles { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }

    /* Tables become card-like rows: a site engineer on a phone should not have
       to scroll sideways to read a status. */
    table.data.stack-mobile thead { display: none; }
    table.data.stack-mobile tbody tr {
        display: block;
        border: 1px solid var(--line);
        border-radius: var(--radius);
        margin-bottom: .5rem;
        padding: .375rem .5rem;
        background: var(--surface);
    }
    table.data.stack-mobile td {
        display: flex;
        justify-content: space-between;
        gap: 1rem;
        border: 0;
        padding: .25rem 0;
        text-align: right;
    }
    table.data.stack-mobile td::before {
        content: attr(data-label);
        font-size: 11.5px;
        text-transform: uppercase;
        letter-spacing: .04em;
        color: var(--ink-4);
        font-weight: 600;
        text-align: left;
    }
    table.data.stack-mobile td:empty { display: none; }
    .row-actions { justify-content: flex-end; }
}

@media (max-width: 560px) {
    .page-head__actions { width: 100%; }
    .page-head__actions .btn { flex: 1; justify-content: center; }
    .form-grid { grid-template-columns: 1fr; }
}

/* -- Assistant and dictation (Phase 9) ------------------------------------ */

.voice-controls {
    display: flex;
    align-items: center;
    gap: .75rem;
    flex-wrap: wrap;
}

.chat {
    max-height: 26rem;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: .5rem;
    padding: .25rem;
}

.chat:empty { display: none; }

.chat__msg {
    padding: .5rem .75rem;
    border-radius: 8px;
    max-width: 46rem;
    white-space: pre-wrap;
    line-height: 1.55;
    font-size: 13.5px;
}

.chat__msg--user {
    align-self: flex-end;
    background: var(--brand, #1f3a5f);
    color: #fff;
}

.chat__msg--assistant {
    align-self: flex-start;
    background: rgba(127, 140, 160, .12);
}

.chat__msg--error {
    align-self: flex-start;
    background: rgba(200, 60, 60, .12);
    color: var(--danger, #b03030);
}

/* Not a message — a note about what the assistant could not reach, so a
   permission refusal does not read as the assistant being unhelpful. */
.chat__msg--note {
    align-self: center;
    background: transparent;
    color: #6c7a90;
    font-size: 12px;
    font-style: italic;
}

.chat-suggestion { margin: 0 .375rem .375rem 0; }

/* The dictation button on a form, where hands are full. */
.voice-inline {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    margin-left: .5rem;
}

.voice-inline__state {
    font-size: 12px;
    color: #6c7a90;
}

/* A card that needs attention — used where a BOQ line is not fully costed.
   Defined because the view already asked for it: an undefined modifier renders
   as an ordinary card, so the warning it carries becomes invisible. */
.card--warning {
    border-color: var(--amber);
    background: var(--amber-bg);
}

.card--warning .card__head { border-bottom-color: var(--amber); }

/* ---------------------------------------------------------------------------
   Simple and advanced mode on a long form (master prompt S11).

   HIDDEN WITH CSS, NEVER REMOVED FROM THE FORM. Every advanced field stays in
   the DOM and is still submitted, so switching to simple mode and saving cannot
   silently drop a bend radius somebody typed. That is the whole requirement:
   both modes edit the same record, and switching must not lose data.

   FAILS OPEN. Advanced is what you get with no stored preference and with no
   JavaScript at all, because hiding fields somebody cannot get back is a worse
   failure than showing fields they did not ask for.
   --------------------------------------------------------------------------- */
[data-form-mode="simple"] .adv-only { display: none; }

.mode-switch { display: inline-flex; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; }
.mode-switch button {
    appearance: none; border: 0; background: transparent; cursor: pointer;
    font: inherit; font-size: 13px; padding: 5px 12px; color: var(--muted);
}
.mode-switch button + button { border-left: 1px solid var(--line); }
.mode-switch button[aria-pressed="true"] { background: var(--brand); color: #fff; }
.mode-switch button:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }

/* ===========================================================================
   THE JOB SHEET
   ---------------------------------------------------------------------------
   A whole BOQ typed across a grid, the way the people using it already work in
   Excel. The line form asks sixty questions about one component, which is right
   for a folded profile and wrong for fourteen flat panels.

   THE ONE IDEA HERE IS THE COLOUR. A cell you type is the surface colour. A
   cell worked out for you is tinted. That single distinction replaces the
   explanation of what calculates and what does not, which used to be spread
   over five screens and confused everybody anyway.

   Built on the existing tokens, so it follows the theme rather than inventing
   a second palette.
   =========================================================================== */

.sheet-bar {
    display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .875rem;
    padding: .625rem .875rem; margin-bottom: .75rem;
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
}
.sheet-bar__label {
    font-size: .75rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
    color: var(--ink-2); margin: 0;
}
.sheet-bar__select { min-width: 15rem; max-width: 100%; }

.sheet-legend { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem; margin-left: auto; }
.sheet-legend__item { font-size: .8125rem; color: var(--ink-2); display: inline-flex; align-items: center; }
.sw {
    display: inline-block; width: 1.125rem; height: .75rem; margin-right: .375rem;
    border: 1px solid var(--line); border-radius: 2px;
}
.sw--typed { background: var(--surface); }
.sw--auto { background: var(--blue-bg); border-color: var(--blue); }

/* The grid scrolls inside itself; the page never scrolls sideways. */
.sheet-scroll {
    overflow: auto; max-height: 60vh;
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
}

table.sheet { border-collapse: separate; border-spacing: 0; width: 100%; font-variant-numeric: tabular-nums; }
table.sheet th, table.sheet td {
    border-bottom: 1px solid var(--line-2); border-right: 1px solid var(--line-2);
    padding: 0; white-space: nowrap;
}
table.sheet th:last-child, table.sheet td:last-child { border-right: 0; }

table.sheet thead th {
    position: sticky; top: 0; z-index: 3; background: var(--grey-bg);
    padding: .5rem .5625rem; text-align: left;
    font-size: .6875rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
    color: var(--ink-2); border-bottom: 1px solid var(--line);
}
table.sheet thead th.num { text-align: right; }

table.sheet td input,
table.sheet td select {
    width: 100%; border: 0; background: transparent; color: inherit;
    font: inherit; font-size: .8125rem; padding: .4375rem .5625rem; outline: none;
}
table.sheet td.num input { text-align: right; font-family: var(--mono); }
table.sheet td input:focus, table.sheet td select:focus {
    background: var(--surface); border-radius: 2px;
    box-shadow: inset 0 0 0 2px var(--brand);
}
table.sheet td input[readonly] { color: var(--ink-2); cursor: not-allowed; }

/* Worked out for you. */
table.sheet td.auto { background: var(--blue-bg); }
.auto__v {
    display: block; padding: .4375rem .5625rem; text-align: right;
    font-family: var(--mono); font-size: .8125rem; color: var(--blue);
}

table.sheet td.sheet__no,
table.sheet th.sheet__no {
    width: 2.5rem; text-align: right; padding: .4375rem .5rem;
    font-family: var(--mono); font-size: .75rem; color: var(--ink-2);
    background: var(--grey-bg); position: sticky; left: 0; z-index: 2;
}
table.sheet thead th.sheet__no { z-index: 4; }

table.sheet td.sheet__desc, table.sheet th.sheet__desc {
    min-width: 14rem; position: sticky; left: 2.5rem; z-index: 2; background: var(--surface);
}
table.sheet thead th.sheet__desc { background: var(--grey-bg); z-index: 4; }

table.sheet td.sheet__kill, table.sheet th.sheet__kill { width: 2.25rem; text-align: center; }
.sheet__open {
    display: inline-block; padding: .25rem .5rem; border-radius: var(--radius);
    color: var(--ink-2); text-decoration: none; font-size: 1rem; line-height: 1;
}
.sheet__open:hover { color: var(--brand); background: var(--brand-tint); }

table.sheet tfoot td {
    position: sticky; bottom: 0; z-index: 3; background: var(--grey-bg);
    padding: .5rem .5625rem; text-align: right; font-family: var(--mono);
    font-size: .8125rem; font-weight: 600;
    border-top: 1px solid var(--line); border-bottom: 0;
}
table.sheet tfoot td.sheet__total {
    text-align: left; font-family: var(--font); font-size: .6875rem;
    letter-spacing: .06em; text-transform: uppercase; color: var(--ink-2);
}

@media (max-width: 700px) {
    .sheet-legend { margin-left: 0; }
    .sheet-scroll { max-height: none; }
}

/* The quotation sheet keeps the description as text rather than an input: it
   comes from the BOQ and is not edited here. The detail that does not belong on
   a grid -- customer-facing wording, work scope -- opens one row down, so it is
   reachable without being in the way. */
.sheet__name { padding: .4375rem .5625rem .0625rem; font-size: .8125rem; }
.sheet__sub {
    display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .5rem;
    padding: 0 .5625rem .4375rem; font-size: .6875rem; color: var(--ink-2);
}
.sheet__more {
    appearance: none; border: 0; background: transparent; cursor: pointer;
    font: inherit; font-size: .6875rem; color: var(--brand); padding: 0;
    text-decoration: underline;
}
.sheet__more:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

tr.sheet__detail > td { background: var(--grey-bg); padding: .75rem .875rem; white-space: normal; }
.sheet__drop { display: inline-flex; align-items: center; justify-content: center; padding: .375rem; cursor: pointer; }
