/* Type: Fraunces (display) and Figtree (text), self-hosted, standing in
   for the brand's The Seasons and Proxima Nova Wide, which come first in
   the stacks below for anyone who has them. Licences: fonts/LICENSES.md. */
@font-face {
  font-family: "Figtree"; src: url(/fonts/figtree.woff2) format("woff2");
  font-weight: 300 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Fraunces"; src: url(/fonts/fraunces.woff2) format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
}

/* Signature Homes brand tokens (Signature Homes design system, built from the
   2025 Logo Brand Guide v2.0), applied the way SigDesk applies them: SH Blue
   header, action blue for controls, SH Gold as the active marker, flat
   colour, square-ish corners. */
:root {
  --sh-blue: #00305a;
  --sh-concrete: #d7d0c0;
  --sh-gold: #e5b300;
  --sh-terracotta: #a04b2b;
  --sh-dark-gravel: #0c0b09;

  --bg: #f6f7f8;
  --panel: #ffffff;
  --panel-2: #f6f7f8;
  --ink: #24221e;
  --heading: var(--sh-blue);
  --muted: #656c73;
  --line: #dadee2;
  --line-strong: #c6ccd2;
  --accent: #0f4a80;          /* action blue */
  --accent-deep: #00305a;
  --accent-soft: #edf2f7;
  --accent-ink: #ffffff;
  --bar: var(--sh-blue);
  --bar-ink: #c8d4e0;
  --bar-hover: #0b4170;
  --bar-mark: var(--sh-gold);
  --danger: #a04b2b;          /* terracotta */
  --ok: #1f7a4d;
  --read: #7a5a00;
  --warn-bg: #fff8e6;
  --override: #b44d00;         /* a rate override (rate-override.js) */
  --override-bg: #ffecd9;
  --radius: 6px;
  --control: 4px;
  --shadow: none;
  --page: 1680px;
  --font-display: "The Seasons", "Fraunces", Georgia, "Times New Roman", serif;
  --font-sans: "Proxima Nova Wide", "Proxima Nova", "Figtree", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-data: ui-monospace, "Cascadia Mono", "SF Mono", Consolas, "Liberation Mono", monospace;
  /* Takeoff (takeoff.css). The plan sheet is paper, white in either theme,
     so the marks drawn on it keep their colours; what sits on the app's own
     panels follows the theme. */
  --paper: #ffffff;
  --paper-ink: #1d2433;        /* handle outlines on the sheet */
  --mark: #e0218a;             /* dimensions, snaps and arc guides on the sheet */
  --mark-alt: #1f5fa8;         /* midpoint handles on the sheet */
  --mark-ink: #c41a78;         /* the same magenta as text on a panel */
  --viewer-bg: #8a8f98;        /* around the sheet */
  /* Four text sizes, smallest first: labels and badges; secondary text and
     dense tables; controls and notes; body. Headings and big numbers have
     their own sizes. Use these rather than a new rem value. */
  --fs-xs: 0.75rem;
  --fs-sm: 0.82rem;
  --fs-md: 0.9rem;
  --fs-base: 1rem;
  /* Rows that freeze at the top as the page scrolls (table headings, a
     page's bar of section links): the yellow of the Takeoff Methodology's
     craft roll-up rows (tr.group), dark text, a step larger than before. */
  --freeze-bg: color-mix(in srgb, var(--sh-gold) 16%, var(--panel));
  --freeze-hover: color-mix(in srgb, var(--sh-gold) 30%, var(--panel));
  --freeze-ink: var(--ink);
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--ink);
  background: var(--bg);
}

/* Dark: the brand's SH Blue ground with SH Concrete type. theme.js stamps
   data-theme on <html> before the page draws: the person's choice (profile
   menu: Light, Dark or Auto), or the system's setting while it's on Auto. */
:root[data-theme="dark"] {
  --bg: #001a31;
  --panel: #00243f;
  --panel-2: #002b4b;
  --ink: #e9e4d8;
  --heading: var(--sh-concrete);
  --muted: #a9b4c0;
  --line: #12395c;
  --line-strong: #23507a;
  --accent: #e5b300;        /* SH Gold reads on SH Blue (6.9:1) */
  --accent-deep: #f0c636;
  --accent-soft: #0b3557;
  --accent-ink: #0c0b09;    /* Dark Gravel on Gold */
  --bar: #001427;
  --bar-hover: #0b2f52;
  --danger: #f08a6a;
  --ok: #5fcf92;
  --read: #e5b300;
  --warn-bg: #1f2a1a;
  --override: #ffa24d;
  --override-bg: #3d2410;
  --mark-ink: #ff6fb5;
  --viewer-bg: #0b1d30;
}

* { box-sizing: border-box; }
body { margin: 0; background: var(--bg); color: var(--ink); line-height: 1.4; }
a { color: var(--accent); text-underline-offset: 2px; }
a:hover { text-decoration-thickness: 2px; }
h1 { font-family: var(--font-display); font-weight: 600; font-size: 1.85rem; letter-spacing: -0.01em; margin: 0 0 4px; color: var(--heading); font-optical-sizing: auto; }
h2 { font-size: 1.05rem; font-weight: 700; margin: 0 0 12px; color: var(--heading); }
h3 { font-size: var(--fs-md); margin: 18px 0 8px; }
p.sub { color: var(--muted); margin: 0 0 20px; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Top bar: SH Blue with the concrete logo, Gold marks the page you're on. */
.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 28px;
  padding: 0 24px; height: 56px; background: var(--bar); color: var(--bar-ink);
}
.topbar[hidden] { display: none; }

/* nav.js: "You're viewing the program as …" while an admin impersonates */
.viewing-as {
  position: sticky; top: 56px; z-index: 19;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 8px 24px; background: var(--warn-bg); color: var(--ink);
  border-bottom: 2px solid var(--read); font-size: var(--fs-sm);
}
.viewing-as span { flex: 1; min-width: 200px; }
.viewing-as button { flex: none; }
.brand { display: flex; align-items: center; gap: 12px; text-decoration: none; color: var(--sh-concrete); flex: none; }
.brand img { height: 26px; width: auto; display: block; }
.brand .app { font-size: var(--fs-sm); font-weight: 300; letter-spacing: 0.08em; text-transform: uppercase; padding-left: 12px; border-left: 1px solid color-mix(in srgb, var(--sh-concrete) 45%, transparent); }
#nav { display: flex; gap: 2px; flex: 1; height: 100%; }
#nav a { display: flex; align-items: center; gap: 6px; white-space: nowrap; text-decoration: none; color: var(--bar-ink); padding: 0 12px; border-bottom: 3px solid transparent; border-top: 3px solid transparent; }
#nav a:hover { color: #fff; background: var(--bar-hover); }
#nav a.active { color: #fff; border-bottom-color: var(--bar-mark); font-weight: 600; }
/* A tab with sections (nav.js tabMenu): the tab, its arrow, and the list
   dropping down under it, placed against the window so the scrolling tab
   row can't clip it. */
#nav .nav-drop { display: flex; align-items: stretch; }
#nav .nav-drop > a { padding-right: 4px; }
#nav .nav-drop > a::after { right: 0; }
#nav .nav-arrow {
  display: flex; align-items: center; padding: 0 8px 0 2px; margin: 0; border: 0; border-radius: 0; box-shadow: none;
  background: none; color: var(--bar-ink); cursor: pointer; border-top: 3px solid transparent; border-bottom: 3px solid transparent;
}
#nav .nav-arrow .icon { transform: rotate(90deg); width: 14px; height: 14px; opacity: 0.7; transition: transform 0.15s; }
#nav .nav-arrow[aria-expanded="true"] .icon { transform: rotate(-90deg); }
#nav .nav-drop:hover > a, #nav .nav-drop:hover > .nav-arrow { color: #fff; background: var(--bar-hover); }
#nav .nav-menu {
  position: fixed; z-index: 30; min-width: 200px; padding: 4px 0; margin-top: 2px;
  background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.18);
}
#nav .nav-menu[hidden] { display: none; }
#nav .nav-menu a {
  display: block; padding: 8px 14px; color: var(--ink); background: none; border: 0; font-weight: 400; white-space: nowrap;
}
#nav .nav-menu a::after { content: none; }
#nav .nav-menu a:hover, #nav .nav-menu a:focus-visible { background: var(--hover, color-mix(in srgb, var(--accent) 10%, transparent)); color: var(--ink); }
#nav .nav-menu a.on { font-weight: 600; color: var(--accent); box-shadow: inset 3px 0 0 var(--sh-gold); }
#nav .count { font-size: var(--fs-xs); font-weight: 700; background: var(--sh-gold); color: var(--sh-dark-gravel); border-radius: 3px; padding: 0 5px; }
/* Profile menu (top right): the user's page, admin controls, sign out. */
#profile { flex: none; position: relative; margin-left: auto; }
.profile-menu > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px;
  color: var(--bar-ink); font-size: var(--fs-md); white-space: nowrap; padding: 6px 8px; border-radius: var(--control);
}
.profile-menu > summary::-webkit-details-marker { display: none; }
.profile-menu > summary:hover, .profile-menu[open] > summary { color: #fff; background: var(--bar-hover); }
.profile-menu > summary.active .name { box-shadow: inset 0 -2px 0 var(--bar-mark); }
/* Profile pictures (avatar.js): the picture, or initials when there's none. */
.avatar {
  flex: none; display: inline-grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; overflow: hidden;
  background: var(--sh-gold); color: var(--sh-dark-gravel); font-weight: 700; font-size: var(--fs-xs); line-height: 1;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.avatar.has-photo { background: var(--line); }
.avatar.large { width: 72px; height: 72px; font-size: var(--fs-base); }
.profile-picture { display: flex; gap: 16px; align-items: center; }
.profile-picture p { margin: 0 0 8px; }
.user-cell { display: flex; gap: 10px; align-items: center; }
.user-head { display: flex; gap: 16px; align-items: center; margin-bottom: 8px; }
.user-head h1 { margin-bottom: 2px; }
.user-head .sub { margin: 0; }
.profile-menu .role { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--sh-gold); }
.profile-menu .menu {
  position: absolute; right: 0; top: calc(100% + 6px); min-width: 240px; z-index: 30;
  background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.18); padding: 4px 0;
}
.profile-menu .group + .group { border-top: 1px solid var(--line); }
.profile-menu .group { padding: 4px 0; }
.profile-menu .heading { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); padding: 6px 14px 2px; }
.profile-menu .menu a, .profile-menu .menu button.link {
  display: block; width: 100%; text-align: left; padding: 7px 14px; color: var(--ink); text-decoration: none; font: inherit; font-size: var(--fs-md);
}
.profile-menu .menu a:hover, .profile-menu .menu button.link:hover { background: var(--panel-2); }
.topbar :focus-visible { outline-color: var(--sh-gold); }

main { max-width: var(--page); margin: 0 auto; padding: 24px 24px 64px; }

.crumbs { margin: 0 0 6px; font-size: var(--fs-md); color: var(--muted); }
.crumbs ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 2px 0; }
.crumbs li + li::before { content: "›"; padding: 0 8px; color: var(--muted); }
.crumbs a { text-decoration: none; }
.crumbs a:hover { text-decoration: underline; }
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 16px; }
.page-head p.sub { margin: 0; }

.panel { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 20px; margin-bottom: 20px; box-shadow: var(--shadow); }
.panel > h2:first-child, .panel-head h2 { margin-bottom: 12px; }
.panel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 8px; }
.panel-head h2 { margin: 0; }
.columns { display: grid; grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)); gap: 20px; }
.columns > .panel { margin-bottom: 0; }
.stack > * + * { margin-top: 20px; }
.narrow { max-width: 400px; margin: 12vh auto 0; }
/* "Connect Claude to Estimating?" (connect.js) and the profile page's Claude connections. */
.panel.connect { max-width: 560px; margin: 8vh auto 0; }
.panel.connect label.check { align-items: flex-start; margin: 16px 0; }
.panel.connect label.check input { margin-top: 3px; flex: none; }
ul.plain-list { list-style: none; margin: 12px 0 0; padding: 0; }
ul.plain-list li { justify-content: space-between; padding: 8px 0; border-top: 1px solid var(--line); }
.profile-password { max-width: 400px; }
.row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.spread { justify-content: space-between; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px 16px; }

/* Stat tiles */
.stats { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 12px; margin-bottom: 20px; }
.stat { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 12px 14px; box-shadow: var(--shadow); }
.stat .label { color: var(--muted); font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.04em; }
.stat .value { font-size: 1.35rem; font-weight: 700; color: var(--heading); font-variant-numeric: tabular-nums; margin-top: 2px; }
.stat.empty .value { color: var(--muted); font-weight: 400; }
.stat .note { color: var(--muted); font-size: var(--fs-sm); }

label { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-sm); color: var(--muted); }
label.check { flex-direction: row; align-items: center; gap: 8px; color: var(--ink); font-size: var(--fs-md); }
input, select, textarea {
  font: inherit; color: var(--ink); background: var(--panel);
  border: 1px solid var(--line-strong); border-radius: var(--control); padding: 7px 9px;
}
input:hover, select:hover, textarea:hover { border-color: color-mix(in srgb, var(--accent) 40%, var(--line-strong)); }
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
input:disabled, select:disabled, textarea:disabled { opacity: 0.7; cursor: not-allowed; background: var(--panel-2); }
textarea { min-height: 70px; resize: vertical; }
form .actions, .actions { margin-top: 16px; display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

button {
  font: inherit; cursor: pointer; border-radius: var(--control); padding: 7px 14px;
  border: 1px solid var(--line-strong); background: var(--panel); color: var(--ink);
  transition: background 0.1s, border-color 0.1s;
}
button:hover:not(:disabled) { background: var(--panel-2); border-color: color-mix(in srgb, var(--accent) 35%, var(--line-strong)); }
button.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 600; }
button.primary:hover:not(:disabled) { background: var(--accent-deep); border-color: var(--accent-deep); }
button.danger { color: var(--danger); }
button.link { border: 0; background: none; padding: 0; color: var(--accent); }
button.link:hover:not(:disabled) { background: none; text-decoration: underline; }
button.small, .small button { padding: 3px 9px; font-size: var(--fs-sm); }
button:disabled { opacity: 0.5; cursor: not-allowed; }
a.button { display: inline-block; text-decoration: none; padding: 7px 14px; border-radius: var(--control); border: 1px solid var(--line-strong); color: var(--ink); background: var(--panel); }
a.button.primary { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); font-weight: 600; }
a.button.small { padding: 3px 9px; font-size: var(--fs-sm); }

table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--line); vertical-align: top; }
th { font-size: var(--fs-xs); color: var(--muted); font-weight: 650; text-transform: uppercase; letter-spacing: 0.04em; }
tbody tr:hover td { background: color-mix(in srgb, var(--accent) 4%, transparent); }
tr.inactive td { color: var(--muted); }
tr.over-threshold td { background: color-mix(in srgb, var(--danger) 7%, transparent); }
label.threshold { flex-direction: row; align-items: center; gap: 6px; color: var(--ink); }
td.num, th.num { font-variant-numeric: tabular-nums; text-align: right; }
.eyebrow { font-size: var(--fs-xs); font-weight: 300; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); margin: 0 0 4px; }
.table-wrap { overflow-x: auto; }

.badge { display: inline-block; white-space: nowrap; font-size: var(--fs-xs); font-weight: 600; padding: 2px 8px; border-radius: 3px; border: 1px solid currentColor; }
.badge.edit { color: var(--ok); }
.badge.read { color: var(--read); }
.badge.override { color: var(--override); margin-left: 4px; }
.badge.discontinued { color: var(--override); }
/* An active rate override: the rate cell in orange. */
td.rate-override { background: var(--override-bg); color: var(--override); font-weight: 600; }
dialog.src-dialog form.rate-form label > input { display: block; width: 100%; margin-top: 4px; }
dialog.src-dialog form.rate-form label > input[type=date] { width: auto; }
.badge.admin { color: var(--accent); }
.badge.off { color: var(--muted); }
.badge.failed { color: var(--danger); }
.badge.set-current { color: var(--ok); }
.badge.set-draft { color: var(--accent); }
.badge.set-replaced { color: var(--muted); }
.badge.solid { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

.notice { padding: 10px 12px; border-radius: var(--radius); border: 1px solid var(--read); color: var(--read); background: var(--warn-bg); margin-bottom: 16px; }
.notice.info { border-color: var(--accent); color: var(--ink); background: var(--accent-soft); }
.error { color: var(--danger); margin-top: 10px; min-height: 1.2em; }
.muted { color: var(--muted); }
.ok { color: var(--ok); }
.small { font-size: var(--fs-sm); }
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chip { font-size: var(--fs-sm); padding: 2px 8px; border-radius: var(--control); background: var(--panel-2); border: 1px solid var(--line); text-decoration: none; }
a.chip.elev { font-size: var(--fs-md); font-weight: 600; padding: 6px 14px; }
.pick-search { margin-bottom: 14px; }
.pick-search input[type=search] { width: 100%; max-width: 360px; }
.pick-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px; }
.pick { display: flex; flex-direction: column; gap: 2px; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel-2); text-decoration: none; color: var(--ink); }
.pick:hover { border-color: var(--accent); }
.plan-pick { display: flex; flex-direction: column; }
.plan-row { display: grid; grid-template-columns: minmax(120px, 200px) 1fr; gap: 12px; align-items: center; padding: 10px 0; }
.plan-row + .plan-row { border-top: 1px solid var(--line); }
a.chip:hover { border-color: var(--accent); }
input.num-input { width: 6em; text-align: right; }
input.wide-input { width: 100%; min-width: 12em; }
.settings-table td { vertical-align: top; }
.settings-table td:first-child { width: 50%; }
.settings-table td:last-child { width: 25%; }
.chip.warn-chip { color: var(--read); border-color: var(--read); }
.chip.discontinued { color: var(--muted); text-decoration: line-through; border-style: dashed; }
/* Budget lines: a unit's or the shell's line, by its craft's boxes on *optmaster. */
.chip.scope { font-size: var(--fs-xs); padding: 0 6px; color: var(--muted); white-space: nowrap; }
.pick-search.row { gap: 16px; flex-wrap: wrap; }
pre.diff { margin: 0; font-size: var(--fs-xs); white-space: pre-wrap; color: var(--muted); max-width: 640px; }
.spaced, h2.spaced { margin-top: 24px; }

.toast {
  position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); z-index: 50;
  display: flex; flex-direction: column; align-items: center; gap: 8px; max-width: min(640px, calc(100vw - 32px));
  pointer-events: none;
}
.toast[hidden], .toast:empty { display: none; }
.toast-item {
  background: var(--ink); color: var(--bg); padding: 10px 16px; border-radius: var(--radius); pointer-events: auto;
}
.toast-item.error { background: var(--danger); color: #fff; display: flex; align-items: center; gap: 12px; }
.toast-item.error button { flex: none; }

.segmented { display: inline-flex; border: 1px solid var(--line-strong); border-radius: var(--control); overflow: hidden; flex-wrap: wrap; }
.segmented button { border: 0; border-radius: 0; padding: 5px 12px; font-size: var(--fs-md); }
.segmented button + button { border-left: 1px solid var(--line-strong); }
.segmented button.on { background: var(--accent); color: var(--accent-ink); }
input[type=search] { min-width: 260px; }

details { margin-top: 8px; }
details summary { cursor: pointer; }
details ul { margin: 6px 0 0; padding-left: 20px; columns: 2; }

/* Sortable, filterable tables (table.js) */
.data-table { margin-top: 4px; }
.table-tools { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.table-tools .grow { flex: 1; }
.wide { overflow: auto; border: 1px solid var(--line); border-radius: var(--radius); max-height: 72vh; background: var(--panel); }
/* A table that fits the width scrolls with the page instead (ui.js). */
:root { --sticky-top: 56px; }
.wide.fits { overflow: visible; max-height: none; }
.wide.fits table.sheet thead th { top: var(--sticky-top); }
.wide.fits table.sheet thead tr.filters th { top: calc(var(--sticky-top) + var(--head-h, 31px) - 1px); }
.data-table > .more { margin-top: 8px; }
/* Show more where a grouped list's rows stop (Expand all draws the first few hundred). */
tr.more-row td { text-align: center; padding: 10px; }
th.sortable { padding: 0; }
th.sortable button.sort {
  all: unset; box-sizing: border-box; display: block; width: 100%; padding: 8px 10px; cursor: pointer;
  font: inherit; color: inherit; text-transform: inherit; letter-spacing: inherit;
}
th.num.sortable button.sort { text-align: right; }
th.sortable button.sort:hover { color: var(--ink); background: var(--freeze-hover); }
th.sortable button.sort:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
th[aria-sort=ascending], th[aria-sort=descending] { color: var(--accent); }
.arrow { font-size: 0.7em; }
tr.filters th { padding: 4px 6px; text-transform: none; letter-spacing: 0; font-weight: 400; background: var(--panel-2); }
tr.filters input, tr.filters select { width: 100%; min-width: 60px; padding: 3px 6px; font-size: var(--fs-sm); border-radius: 3px; }
tr.filters th.num input { text-align: right; }
tr.filters th.active input, tr.filters th.active select { border-color: var(--accent); background: var(--accent-soft); }
/* A select column's filter: tick any of its values (table.js pickList). */
details.colfilter { margin: 0; }
details.colfilter > summary {
  display: flex; align-items: center; gap: 4px; min-width: 60px; padding: 3px 6px; cursor: pointer; list-style: none;
  font-size: var(--fs-sm); color: var(--ink); background: var(--panel);
  border: 1px solid var(--line-strong); border-radius: 3px; white-space: nowrap;
}
details.colfilter > summary::-webkit-details-marker { display: none; }
details.colfilter > summary::after { content: '▾'; margin-left: auto; padding-left: 4px; color: var(--muted); font-size: 0.85em; }
details.colfilter > summary:hover { border-color: color-mix(in srgb, var(--accent) 40%, var(--line-strong)); }
details.colfilter > summary:focus-visible, details.colfilter[open] > summary { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
tr.filters th.active details.colfilter > summary { border-color: var(--accent); background: var(--accent-soft); }
.cf-label { overflow: hidden; text-overflow: ellipsis; max-width: 16em; }
.cf-panel {
  position: fixed; z-index: 60; display: flex; flex-direction: column; min-width: 200px; max-width: 340px;
  padding: 6px; background: var(--panel); border: 1px solid var(--line-strong); border-radius: var(--radius);
  box-shadow: 0 8px 24px color-mix(in srgb, var(--sh-dark-gravel) 18%, transparent);
  text-transform: none; letter-spacing: 0; font-weight: 400; text-align: left;
}
.cf-panel input[type=search] { min-width: 0; width: 100%; margin-bottom: 4px; padding: 4px 6px; font-size: var(--fs-sm); }
.cf-panel input[type=search][hidden] { display: none; }
.cf-actions { display: flex; gap: 12px; padding: 2px 4px 6px; margin-bottom: 4px; border-bottom: 1px solid var(--line); }
.cf-list { overflow: auto; min-height: 0; max-height: 300px; }
label.cf-opt { flex-direction: row; align-items: center; gap: 8px; padding: 3px 4px; border-radius: 3px; cursor: pointer; font-size: var(--fs-sm); color: var(--ink); white-space: nowrap; }
label.cf-opt[hidden] { display: none; }
label.cf-opt:hover { background: var(--panel-2); }
.cf-panel label.cf-opt input { width: auto; min-width: 0; margin: 0; padding: 0; flex: none; }
.cf-text { overflow: hidden; text-overflow: ellipsis; }
.cf-n { margin-left: auto; padding-left: 12px; color: var(--muted); font-family: var(--font-data); font-size: var(--fs-xs); }
tr.empty td { text-align: center; padding: 20px; }
tbody.data-rows { overflow-anchor: none; }
/* Group headings in every grouped table: tinted SH Gold, a large fold arrow
   (the same one fold-out sections use), and the name and its label bold. */
table.sheet tbody tr.group td { background: color-mix(in srgb, var(--sh-gold) 16%, var(--panel)) !important; padding: 0; border-top: 1px solid var(--line); }
tr.group .group-toggle { display: flex; align-items: center; gap: 8px; width: 100%; border: 0; border-radius: 0; background: none; padding: 7px 10px; text-align: left; font: inherit; color: var(--ink); cursor: pointer; }
tr.group .group-toggle:hover { background: color-mix(in srgb, var(--sh-gold) 14%, transparent); }
tr.group .caret { width: 1.1em; font-size: 1.3em; line-height: 1; color: var(--ink); }
tr.group .group-name { font-weight: 600; }
tr.group .group-label { color: var(--ink); font-weight: 600; font-size: var(--fs-md); }

/* Fold-out sections (<details>): the same ▸/▾ arrow as the group headings,
   in place of the browser's own. Menus, column filters and folding panels
   draw their own. */
details:not(.profile-menu, .colfilter, .fold) > summary { list-style: none; }
details:not(.profile-menu, .colfilter, .fold) > summary::-webkit-details-marker { display: none; }
details:not(.profile-menu, .colfilter, .fold) > summary::before { content: '▸'; display: inline-block; flex: none; width: 1.1em; font-size: 1.3em; line-height: 1; color: var(--ink); }
details[open]:not(.profile-menu, .colfilter, .fold) > summary::before { content: '▾'; }
table.sheet tbody tr.group.with-cells td + td { padding: 7px 10px; font-weight: 600; }

/* Spreadsheet-like tables */
table.sheet { font-size: var(--fs-sm); }
table.sheet th, table.sheet td { padding: 5px 8px; white-space: nowrap; }
table.sheet thead th { position: sticky; top: 0; background: var(--freeze-bg); color: var(--freeze-ink); font-size: var(--fs-sm); z-index: 1; box-shadow: inset 0 -1px 0 var(--line); }
/* --head-h: the headings' height (table.js). The filter row tucks 1px under
   them, drawing the line between itself, so no sliver of a scrolled row shows
   between the two. */
table.sheet thead tr.filters th { top: calc(var(--head-h, 31px) - 1px); background: var(--panel-2); box-shadow: inset 0 1px 0 var(--line), inset 0 -1px 0 var(--line); }
table.sheet thead tr:first-child th.sortable { background: var(--freeze-bg); }
table.sheet .sticky { position: sticky; left: 0; background: var(--panel); z-index: 2; text-transform: none; letter-spacing: 0; color: var(--ink); font-weight: 500; }
table.sheet thead .sticky { z-index: 3; background: var(--freeze-bg); }
table.sheet th.model { text-transform: none; letter-spacing: 0; }
table.sheet .picked { background: color-mix(in srgb, var(--accent) 10%, var(--panel)); }
table.sheet tr.section th { color: var(--muted); font-size: var(--fs-xs); text-transform: uppercase; padding-top: 12px; }
table.sheet td.desc { white-space: normal; min-width: 240px; max-width: 420px; }
table.sheet td.wrap { white-space: normal; }
table.sheet tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--panel-2) 60%, transparent); }
table.sheet tbody tr:hover td { background: color-mix(in srgb, var(--accent) 7%, var(--panel)); }
td.swatch { width: 6px; padding: 0 !important; background: var(--swatch, transparent) !important; }

code.formula {
  font-family: var(--font-data); font-size: var(--fs-sm);
  white-space: pre-wrap; word-break: break-word; display: inline-block; max-width: 720px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px; padding: 1px 5px;
}
table.sheet code.formula { max-width: 520px; }

/* Takeoff Formulas */
.page-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin: 0 0 16px; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
.page-tabs a { padding: 8px 14px; color: var(--muted); text-decoration: none; font-weight: 600; border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; }
.page-tabs a:hover { color: var(--ink); }
.page-tabs a.on { color: var(--accent); border-bottom-color: var(--accent); }
.takeoff-formula-tools { gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
table.takeoff-formulas td.desc .key { font-family: var(--font-data); margin-top: 2px; }
table.takeoff-formulas td.qty { min-width: 280px; }
code.formula a.ref { color: var(--accent); text-decoration: none; border-bottom: 1px dotted currentColor; }
code.formula a.ref:hover { border-bottom-style: solid; }

/* Numbers an estimator keys in */
table.sheet td.input { padding: 2px 4px; }
table.sheet td.input input.qty { width: 7em; text-align: right; font: inherit; font-variant-numeric: tabular-nums; padding: 3px 6px; }
table.sheet td.input.todo { background: color-mix(in srgb, var(--read) 16%, var(--panel)) !important; }
table.sheet td.input.todo input.qty { border-color: var(--read); }
.fx { font-family: var(--font-data); font-style: italic; font-weight: 700; font-size: var(--fs-sm); text-decoration: none; padding: 0 5px; border-radius: 4px; border: 1px solid var(--line); color: var(--accent); margin-left: 6px; }
.fx:hover { background: var(--accent-soft); border-color: var(--accent); }
/* ⟲ beside a number opens its history (budget-history.js). */
.hist-btn { font: inherit; font-size: var(--fs-sm); line-height: 1.2; padding: 0 5px; margin-left: 4px; border-radius: 4px; border: 1px solid var(--line); background: none; color: var(--muted); cursor: pointer; }
.hist-btn:hover { color: var(--accent); background: var(--accent-soft); border-color: var(--accent); }
td.input .hist-btn { vertical-align: middle; }
.hist-list { list-style: none; margin: 12px 0 0; padding: 0; max-height: 60vh; overflow-y: auto; border-top: 1px solid var(--line); }
.hist-list li { padding: 8px 2px; border-bottom: 1px solid var(--line); }
.hist-formula { margin-top: 2px; overflow-wrap: anywhere; font-size: var(--fs-sm); }
.notice.ok { border-color: var(--ok); color: var(--ink); background: none; }

/* Formula editor */
.editor textarea.formula {
  width: 100%; min-height: 110px; font-family: var(--font-data); font-size: var(--fs-md); line-height: 1.5;
}
.check-result { margin-top: 8px; font-size: var(--fs-md); }
.check-result.good { color: var(--ok); }
.check-result.bad { color: var(--danger); }
.check-result ul { margin: 4px 0 0; padding-left: 18px; }
.ref-help { font-size: var(--fs-sm); }
.ref-help table td, .ref-help table th { padding: 4px 8px; }
.ref-help code { font-family: var(--font-data); font-size: var(--fs-sm); }
.picker { position: relative; }
.picker-list { position: absolute; z-index: 10; left: 0; right: 0; top: 100%; max-height: 260px; overflow: auto; background: var(--panel); border: 1px solid var(--line-strong); border-radius: var(--control);  }
.picker-list button { display: block; width: 100%; text-align: left; border: 0; border-radius: 0; padding: 6px 10px; font-size: var(--fs-sm); }
.picker-list button + button { border-top: 1px solid var(--line); }
/* Autocomplete under the cursor in the formula box (formula-complete.js) */
.suggest-anchor { position: relative; }
.suggest {
  position: absolute; z-index: 20; width: max-content; min-width: min(340px, 100%); max-width: min(640px, 100%);
  background: var(--panel); border: 1px solid var(--line-strong); border-radius: var(--control);
  box-shadow: 0 6px 18px rgb(0 20 39 / 16%);
}
.suggest [role=listbox] { position: relative; max-height: 244px; overflow-y: auto; }
.suggest-item { display: flex; align-items: baseline; gap: 10px; padding: 5px 10px; font-size: var(--fs-sm); cursor: pointer; }
.suggest-item + .suggest-item { border-top: 1px solid var(--line); }
.suggest-item.on { background: var(--accent-soft); }
.suggest-item code { font-family: var(--font-data); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 340px; flex: none; }
.suggest-detail { flex: 1; min-width: 0; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.suggest-kind { flex: none; font-size: var(--fs-xs); color: var(--muted); }
.suggest-foot { white-space: nowrap; overflow: hidden; padding: 5px 10px; border-top: 1px solid var(--line); font-size: var(--fs-xs); color: var(--muted); background: var(--panel-2); border-radius: 0 0 var(--control) var(--control); }
.suggest-foot kbd { margin-right: 2px; }
.suggest-hint { margin: 6px 0 0; }
/* Mail merge keys: the plan data fields a formula can name */
.key-find { max-width: 520px; }
.picker-list .picker-empty { margin: 0; padding: 6px 10px; }
.editor .badge[hidden] { display: none; }
.merge-keys h3 { margin: 18px 0 2px; }
.merge-keys h4 { margin: 12px 0 2px; font-size: var(--fs-sm); }
.merge-keys h3 + p, .merge-keys h4 + p { margin: 0 0 6px; }
.merge-keys details { margin-top: 8px; }
.merge-keys summary { cursor: pointer; font-weight: 600; font-size: var(--fs-sm); }
.merge-keys details[open] summary { margin-bottom: 2px; }
.merge-key-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 6px; margin-top: 6px; }
button.merge-key { display: flex; align-items: baseline; gap: 8px; text-align: left; padding: 5px 8px; font-size: var(--fs-sm); min-width: 0; }
button.merge-key[hidden] { display: none; }
button.merge-key code { font-family: var(--font-data); font-weight: 600; color: var(--accent); flex: none; }
button.merge-key:disabled code { color: inherit; }
.merge-key-name { min-width: 0; overflow-wrap: anywhere; }
.levels { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.change { display: grid; grid-template-columns: 90px 1fr; gap: 4px 10px; align-items: baseline; font-size: var(--fs-sm); }
.delta.up { color: var(--danger); }
.delta.down { color: var(--ok); }
.kv { display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px; align-items: baseline; }
.kv dt { color: var(--muted); font-size: var(--fs-sm); }
.kv dd { margin: 0; }

@media (max-width: 900px) {
  .columns { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  :root { --sticky-top: 0px; }
  .topbar { flex-wrap: wrap; gap: 6px 16px; padding: 8px 16px; height: auto; position: static; }
  .brand .app { display: none; }
  .profile-menu .name, .profile-menu .role { display: none; }
  #nav { order: 3; flex-basis: 100%; overflow-x: auto; height: 36px; }
  main { padding: 16px 16px 48px; }
  table.sheet .sticky { white-space: normal; min-width: 120px; max-width: 150px; }
  input[type=search] { min-width: 0; width: 100%; }
  details ul { columns: 1; }
}

/* Sign-in */
.login { padding: 32px; }
/* Microsoft sign-in above the password form (account.js) */
.login-sso:empty { display: none; }
a.sso-button { display: block; text-align: center; text-decoration: none; }
.login-or { display: flex; align-items: center; gap: 10px; margin: 18px 0 6px; }
.login-or::before, .login-or::after { content: ""; flex: 1; border-top: 1px solid var(--line); }
.login-logo { display: block; height: 40px; width: auto; margin-bottom: 24px; }
:where(:root[data-theme="dark"]) .login-logo { content: url(/brand/sh-logo-horizontal-concrete.svg); }
.grow { flex: 1; min-width: 220px; }
.picker input[type=search] { width: 100%; }

/* Lines against Newstar */
.newstar-bar { border: 1px solid var(--line); background: var(--panel-2); border-radius: var(--radius); padding: 10px 12px; margin-bottom: 10px; }
.newstar-bar .chip.ns-chip { border-color: var(--read); color: var(--read); }
td.ns-match { color: var(--ok); }
td.ns-diff { white-space: nowrap; }
/* HighArc beside our own number: red where the two differ. */
td.ha-diff, .ha-diff { color: var(--danger); white-space: nowrap; font-weight: 600; }
.newstar-bar .chip.ha-chip { border-color: var(--danger); color: var(--danger); }
.higharc-conflict { color: var(--danger); font-weight: 600; }

/* HighArc quantities: where a line's quantity comes from. */
.src { display: inline-block; white-space: nowrap; font-size: var(--fs-xs); font-weight: 600; padding: 1px 7px; border-radius: 3px; border: 1px solid currentColor; }
.src-manual { color: var(--muted); border-color: var(--line-strong); font-weight: 500; }
.src-ha { color: var(--accent); background: var(--accent-soft); }
.src-pin { color: var(--sh-terracotta); background: color-mix(in srgb, var(--sh-terracotta) 10%, var(--panel)); }
.src-missing { color: var(--read); background: var(--warn-bg); }
button.src-btn { background: none; border: 0; padding: 0; cursor: pointer; }
button.src-btn:hover .src, button.src-btn:focus-visible .src { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
table.sheet td.from-src, td.from-src { background: color-mix(in srgb, var(--accent) 6%, var(--panel)); font-weight: 600; }
dialog.src-dialog { width: min(640px, calc(100vw - 32px)); border: 1px solid var(--line-strong); border-radius: var(--radius); padding: 20px 22px; color: var(--ink); background: var(--panel); }
dialog.src-dialog::backdrop { background: rgb(12 11 9 / 35%); }
dialog.src-dialog h3 { margin: 0 0 2px; color: var(--heading); }
dialog.src-dialog h4 { margin: 14px 0 6px; }
dialog.src-dialog .row { flex-wrap: wrap; }
dialog.src-dialog label { display: block; margin: 10px 0; }
dialog.src-dialog select { max-width: 100%; }
dialog.src-dialog input.qty { width: 8em; text-align: right; }
dialog.src-dialog .actions { margin-top: 16px; display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap; }
dialog.src-dialog .in-use-list { max-height: 60vh; overflow-y: auto; margin: 12px 0 4px; border-top: 1px solid var(--line); }
dialog.src-dialog .new-line-form .in-use-list { max-height: 30vh; }
dialog.src-dialog form.new-line-form .in-use-row > input { display: inline-block; width: auto; margin: 0 8px 0 0; }
dialog.src-dialog .new-line-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 0 12px; }
dialog.src-dialog .new-line-grid label > select { display: block; width: 100%; margin-top: 4px; }
dialog.src-dialog .new-line-form label > select { display: block; margin-top: 4px; }
dialog.src-dialog label.in-use-row { display: flex; flex-direction: row; align-items: center; gap: 10px; margin: 0; padding: 7px 2px; border-bottom: 1px solid var(--line); cursor: pointer; }
dialog.src-dialog label.in-use-row.muted { cursor: default; }
dialog.src-dialog .place-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 7px 2px; border-bottom: 1px solid var(--line); }
dialog.src-dialog label.place-plan { padding-left: 28px; }
dialog.src-dialog .in-use-list h4 { margin: 12px 0 2px; }
td.num button.in-use { font: inherit; text-align: right; }
input.short { width: 10em; }

/* Budget Builder (builder.js) */
/* Plans without a plan set can't be measured yet (builder.js). */
.plan-row.no-set strong { color: var(--muted); }
a.chip.elev.no-set { background: none; border-style: dashed; color: var(--muted); font-weight: 500; }
form.upload-set input[type=file] { max-width: 100%; }
/* The takeoff on the Budget Builder, Room Measures and DO Takeoffs tabs
   (builder.js, options.js): the breadcrumbs at the top left as on every other
   page, the elevation's tabs under them, and the takeoff filling the rest of
   the window under the header. */
.builder-budget { display: flex; flex-direction: column; height: calc(100vh - 56px); }
.builder-budget > .crumbs { flex: none; margin: 0; padding: 10px 26px 0; background: var(--panel); }
.builder-budget > .builder-tabs { flex: none; margin: 0; padding: 0 12px; background: var(--panel); }
.builder-budget > .takeoff { flex: 1; min-height: 0; height: auto; }
/* Structural tab (structural.js): the bar over the layout (plan set, import,
   upload, saved state), then the layout tool filling the rest, edge to edge
   across the whole window as the takeoff does (takeoff.css). The tool's own
   look is structural-tool.css. */
main:has(> .structural) { max-width: none; padding: 0; }
.structural > .structural-bar { flex: none; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 8px 26px; background: var(--panel); border-bottom: 1px solid var(--line); }
.structural-bar select { max-width: 320px; }
.structural-status { margin-left: auto; }
.structural > .structural-note { flex: none; margin: 8px 26px; }
/* Under the bar: the takeoff's plan controls (structural-viewer.js), then the
   tool pane on the left and the tool with the page box on the plan. */
.structural > .structural-viewbar { flex: none; }
.structural-hint { flex: 1 1 240px; min-width: 0; font-size: var(--fs-sm); color: var(--muted); }
.structural > .structural-work { flex: 1; min-height: 420px; display: flex; }
.structural-tools { width: 220px; flex: none; overflow-y: auto; padding: 10px; background: var(--panel); border-right: 1px solid var(--line); display: flex; flex-direction: column; gap: 14px; }
.structural-tools section { display: flex; flex-direction: column; gap: 3px; }
.structural-tools h3 { margin: 0 0 2px; font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.structural-tools .structural-tool { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; padding: 5px 8px; text-align: left; border-color: transparent; background: transparent; }
.structural-tools .structural-tool:hover { background: var(--panel-2); border-color: var(--line-strong); }
.structural-tools .structural-tool.primary { background: var(--accent-soft); color: var(--accent); }
.structural-tools .structural-tool[aria-pressed=true] { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.structural-tools kbd { font-size: 11px; opacity: 0.7; background: transparent; color: inherit; border-color: currentColor; box-shadow: none; }
.structural-select { display: flex; flex-direction: column; gap: 2px; margin: 0 0 4px 8px; }
.structural-select select { width: 100%; min-width: 0; }
.structural-plan { flex: 1; min-width: 0; position: relative; display: flex; }
.structural-plan > .structural-host { flex: 1; min-width: 0; display: flex; background: var(--viewer-bg); }
@media (max-width: 640px) {
  .structural > .structural-work { flex-direction: column; }
  .structural-tools { width: auto; max-height: 30vh; border-right: 0; border-bottom: 1px solid var(--line); }
  .structural-plan { min-height: 70vh; }
}
.structural > .structural-body { flex: 1; overflow: auto; padding: 16px 26px; }
.structural-history { width: min(560px, calc(100vw - 32px)); max-height: 80vh; }
.structural-versions { list-style: none; margin: 0 0 12px; padding: 0; }
.structural-versions li { padding: 8px 0; border-bottom: 1px solid var(--line); }
.structural-versions li:last-child { border-bottom: 0; }
/* Which page each page of a layout goes on (structural.js, pageMapDialog). */
dialog.page-map-dialog { width: min(640px, calc(100vw - 32px)); max-height: 85vh; }
dialog.page-map-dialog .dialog-detail { white-space: pre-line; margin: 8px 0 12px; }
table.page-map { width: 100%; }
table.page-map td, table.page-map th { padding: 6px 8px; vertical-align: middle; }
table.page-map select { max-width: 100%; }
/* Admin › Structural defaults (structural-defaults.js): a section per
   group of settings, folding; the Save bar stays in reach. */
.structural-defaults-bar { position: sticky; top: 0; z-index: 2; }
.structural-defaults-bar .grow { flex: 1; min-width: 200px; }
details.structural-defaults-section { margin-top: 0; }
details.structural-defaults-section > summary { display: flex; align-items: center; gap: 10px; }
details.structural-defaults-section > summary h2 { margin: 0; }
details.structural-defaults-section[open] > summary { margin-bottom: 8px; }
form.plan-data h2 { margin-top: 20px; }
form.plan-data h2:first-child { margin-top: 0; }
/* HighArc's picture of the linked elevation (plan-data.js). */
.higharc-picture { margin: 0 0 12px; }
.higharc-picture figcaption { margin-top: 4px; }
.higharc-picture img { display: block; max-width: min(100%, 480px); max-height: 320px; border-radius: 8px; border: 1px solid var(--line); background: var(--paper); }
input.from-hblive { background: var(--panel-2); color: var(--ok); cursor: help; }
/* Read from HBLive (ui.js fromHBLive): green, with a dot before it. */
.hb-src { color: var(--ok); cursor: help; }
.hb-src::before { content: ''; display: inline-block; width: 6px; height: 6px; margin: 0 5px 1px 0; border-radius: 50%; background: var(--ok); vertical-align: middle; }
td.hb-src::before { margin-left: 0; }
input.hb-placeholder::placeholder { color: var(--ok); opacity: 0.85; }
select.hb-select { color: var(--ok); }
.src-hover { cursor: help; }
.hb-key { margin: 4px 0 8px; }
/* In a link or a button the value still clicks; the hover text says where it's from. */
a .hb-src, button .hb-src, label .hb-src { cursor: inherit; }
a:hover > .hb-src, a:hover strong > .hb-src { text-decoration: underline; }
/* On a filled or tinted background (a chosen chip, a primary button, a
   community's band, a discontinued or unavailable chip) green wouldn't read
   or would hide the state: the text keeps its colour and only the dot marks it. */
a.chip.elev.on .hb-src, .button.primary .hb-src, button.primary .hb-src, button.on .hb-src, .cc-band .hb-src, .community-strip .hb-src, .cs-code .hb-src,
.work-badge .hb-src, .chip.discontinued .hb-src, a.chip.elev.no-set .hb-src, tr.inactive .hb-src, .community-card.off .hb-src { color: inherit; }
a.chip.elev.on .hb-src::before, .button.primary .hb-src::before, button.primary .hb-src::before, button.on .hb-src::before, .cc-band .hb-src::before,
.community-strip .hb-src::before, .cs-code .hb-src::before, .work-badge .hb-src::before, .chip.discontinued .hb-src::before, a.chip.elev.no-set .hb-src::before,
tr.inactive .hb-src::before, .community-card.off .hb-src::before { background: currentColor; }
/* A heading's dot sits a little larger, to match its text. */
.stat .value.hb-src { color: var(--ok); }
h1 .hb-src::before, h3.cc-name .hb-src::before, .stat .value.hb-src::before { width: 8px; height: 8px; margin-right: 8px; }
ul.plan-sets { margin: 0 0 12px; padding-left: 18px; }
ul.plan-sets li { margin: 4px 0; }

/* Budget template page (template.js): what comes across from the project a
   template is started from, and what stays behind, side by side. */
.template-start { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 4px 28px; margin: 12px 0; }
.template-start h3 { margin: 0 0 4px; }
.template-start ul { margin: 0; padding-left: 18px; }
.template-start li { margin: 2px 0; }
.template-pick select { max-width: 520px; }

/* Plan budget page (plan-budget.js) */
a.chip.elev.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
td.num.up { color: var(--read); }
td.num.down { color: var(--ok, inherit); }
.grid > .full { grid-column: 1 / -1; margin: 0; }

/* Page loading (app.js): the page being left dims under a progress bar
   until the next one draws. */
body.loading main { opacity: 0.55; pointer-events: none; transition: opacity 0.15s 0.1s; }
body.loading::before {
  content: ""; position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 40;
  background: linear-gradient(90deg, transparent, var(--sh-gold), transparent);
  background-size: 40% 100%; background-repeat: no-repeat;
  animation: page-loading 1.1s ease-in-out infinite;
}
@keyframes page-loading { from { background-position: -40% 0; } to { background-position: 140% 0; } }
@media (prefers-reduced-motion: reduce) { body.loading::before { animation: none; background: var(--sh-gold); } }

/* Plan page (plan-budget.js): jump links that stick under the header; the
   panels and their table headers stop below them. */
.jump-page { --sticky-top: 96px; }
.jump-page > .panel { scroll-margin-top: 112px; }
.jump-bar {
  position: sticky; top: 56px; z-index: 15; display: flex; gap: 4px 20px; flex-wrap: wrap;
  margin: 0 0 16px; padding: 10px 16px; border-bottom: 1px solid var(--line);
  background: var(--freeze-bg);
}
.jump-bar button.link { font-weight: 650; font-size: var(--fs-base); color: var(--freeze-ink); }
@media (max-width: 640px) {
  .jump-page { --sticky-top: 0px; }
  .jump-bar { position: static; }
}

/* Plan attributes (budget.js): label and value side by side, in columns. */
table.attrs tbody { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); column-gap: 28px; }
table.attrs tr { display: flex; align-items: center; justify-content: space-between; gap: 12px; border-bottom: 1px solid var(--line); }
table.attrs th, table.attrs td { border: 0; }
table.attrs th[scope=row] { white-space: normal; font-size: var(--fs-xs); }
table.sheet.attrs tbody tr:nth-child(even) td { background: none; }
.visually-hidden { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* confirmDialog / promptDialog (ui.js) */
dialog.app-dialog { width: min(480px, calc(100vw - 32px)); }
dialog.app-dialog .dialog-detail { white-space: pre-line; margin: 8px 0 0; }
dialog.app-dialog input[type=text] { width: 100%; }
button.primary.danger-fill { background: var(--danger); border-color: var(--danger); color: #fff; }
button.primary.danger-fill:hover:not(:disabled) { background: color-mix(in srgb, var(--danger) 85%, #000); border-color: color-mix(in srgb, var(--danger) 85%, #000); }

/* Table columns sized to their contents (class: 'fit'), and access shown as
   text rather than a bordered badge (communities.js). */
th.fit, td.fit { width: 1%; white-space: nowrap; }
.access { font-weight: 600; }
.access.edit { color: var(--ok); }
.access.read { color: var(--read); }

/* repeat: false columns (table.js): a value shows where it changes, and a
   stronger rule marks the start of each run. */
td.repeat { color: transparent; }
td.repeat > * { visibility: hidden; }
tr.run-start > td { border-top: 1px solid var(--line-strong); }

/* Dark: links inside tables take the text colour with a gold underline, so a
   column of plan names isn't a wall of gold. Gold stays for actions, the
   page you're on and links in running text. */
:where(:root[data-theme="dark"]) table a:not(.button):not(.fx):not(.ref):not(.chip) {
  color: var(--ink);
  text-decoration-color: color-mix(in srgb, var(--accent) 55%, transparent);
}
:where(:root[data-theme="dark"]) table a:not(.button):not(.fx):not(.ref):not(.chip):hover { color: var(--accent); }
:where(:root[data-theme="dark"]) table a.muted:not(.button):not(.fx):not(.ref):not(.chip) { color: var(--muted); }

/* The key above a budget's lines (budget.js): the colour strip's meanings,
   then the quantity boxes. */
.legend { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; margin: 0 0 6px; font-size: var(--fs-sm); color: var(--muted); }
.legend .key { display: inline-flex; align-items: center; gap: 6px; }
.legend .key-swatch { width: 6px; height: 16px; border-radius: 1px; background: var(--swatch); }
.legend .key-box { width: 22px; height: 14px; border: 1px solid var(--line-strong); border-radius: 3px; background: var(--panel); }
.legend .key-box.todo { border-color: var(--read); background: color-mix(in srgb, var(--read) 16%, var(--panel)); }
.legend .key-sep { width: 1px; height: 16px; background: var(--line); }
.legend .fx { margin-left: 0; }

/* Takeoff tool library (tool-library.js). */
.tool-input-row { display: flex; gap: 6px; align-items: center; margin-bottom: 6px; }
.tool-input-row input[data-k="name"] { flex: 1; min-width: 0; }
.tool-input-row input[data-k="value"] { width: 90px; }
/* min-width: a fieldset is otherwise as wide as its widest field, off a phone's screen. */
fieldset.tool-part { border: 1px solid var(--line); border-radius: var(--radius); padding: 12px 16px; margin: 0 0 12px; min-width: 0; }
fieldset.tool-part legend { font-weight: 600; padding: 0 4px; }
fieldset.tool-part h4 { margin: 12px 0 6px; }
input.formula { font-family: var(--font-data); }
input.tool-ref { font-family: var(--font-data); text-transform: uppercase; }
td > input.tool-ref { width: 14ch; padding: 2px 6px; }
/* The tool library: its folders beside the tools in the one picked. */
.tool-library { display: grid; grid-template-columns: minmax(220px, 280px) minmax(0, 1fr); gap: 16px; align-items: start; }
.tool-library > .panel { margin: 0; min-width: 0; }
.folder-panel { position: sticky; top: 72px; max-height: calc(100vh - 96px); overflow-y: auto; }
.folder-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
.folder-head h2 { margin: 0; }
.folder-list { list-style: none; margin: 0 0 12px; padding: 0; }
button.folder-row {
  display: flex; align-items: center; gap: 6px; width: 100%; text-align: left; border: 1px solid transparent; background: none;
  padding: 4px 8px 4px calc(8px + var(--depth, 0) * 16px); border-radius: var(--control); font-size: var(--fs-md);
}
button.folder-row:hover { background: var(--bg); }
button.folder-row.on { background: color-mix(in srgb, var(--accent) 18%, var(--panel)); font-weight: 600; }
button.folder-row.drop { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--panel)); }
button.folder-row .icon { flex: none; color: var(--muted); }
button.folder-row .folder-name { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.folder-actions { display: flex; flex-direction: column; gap: 8px; border-top: 1px solid var(--line); padding-top: 10px; }
.folder-actions .row { gap: 6px; }
.folder-actions select { max-width: 100%; }
.folder-actions p { margin: 0; }
td > select.tool-folder { max-width: 22ch; padding: 2px 6px; }
tr[draggable="true"] { cursor: grab; }
@media (max-width: 800px) {
  .tool-library { grid-template-columns: 1fr; }
  .folder-panel { position: static; max-height: none; }
  table.cards td > select.tool-folder { max-width: 100%; }
}
.colour-preview { width: 20px; height: 20px; }
.grid > .span-2 { grid-column: span 2; }
.tool-inputs, .tool-inputs + button { max-width: 640px; }
@media (max-width: 640px) { .grid > .span-2 { grid-column: 1 / -1; } }

/* Flair: a light layer of depth and motion over the flat brand base. Gold
   stays the accent; everything still reads without it, and motion stops
   for anyone who asks the system for less of it (end of this section). */
:root {
  --shadow: 0 1px 2px rgb(0 48 90 / 0.05), 0 6px 20px -8px rgb(0 48 90 / 0.12);
  --shadow-lift: 0 2px 4px rgb(0 48 90 / 0.06), 0 14px 28px -10px rgb(0 48 90 / 0.25);
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
}
:root[data-theme="dark"] {
  --shadow: 0 1px 2px rgb(0 0 0 / 0.25), 0 8px 24px -10px rgb(0 0 0 / 0.5);
  --shadow-lift: 0 2px 6px rgb(0 0 0 / 0.3), 0 16px 32px -12px rgb(0 0 0 / 0.6);
}
::selection { background: color-mix(in srgb, var(--sh-gold) 40%, transparent); color: inherit; }
html { scrollbar-color: color-mix(in srgb, var(--muted) 45%, transparent) transparent; }

/* Header: a little depth in the blue, and a gold hairline that fades out. */
.topbar {
  background:
    radial-gradient(120% 140% at 0% 0%, color-mix(in srgb, #fff 7%, transparent), transparent 60%),
    var(--bar);
  box-shadow: 0 2px 12px rgb(0 20 40 / 0.18);
}
.topbar::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; pointer-events: none;
  background: linear-gradient(90deg, color-mix(in srgb, var(--sh-gold) 70%, transparent), color-mix(in srgb, var(--sh-gold) 15%, transparent) 55%, transparent);
}
.brand img { transition: opacity 0.2s, transform 0.3s var(--ease-out); }
.brand:hover img { opacity: 0.85; transform: translateY(-1px); }
/* Tabs: the gold marker grows out from the middle. */
#nav a { position: relative; border-bottom-color: transparent !important; transition: color 0.15s, background 0.15s; }
#nav a::after {
  content: ""; position: absolute; left: 12px; right: 12px; bottom: -3px; height: 3px; border-radius: 3px 3px 0 0;
  background: var(--bar-mark); transform: scaleX(0); opacity: 0.5;
  transition: transform 0.25s var(--ease-out), opacity 0.2s;
}
#nav a:hover::after { transform: scaleX(0.4); }
#nav a.active::after { transform: scaleX(1); opacity: 1; }
.profile-menu .avatar { box-shadow: 0 0 0 2px transparent; transition: box-shadow 0.2s; }
.profile-menu > summary:hover .avatar, .profile-menu[open] .avatar { box-shadow: 0 0 0 2px var(--bar), 0 0 0 4px color-mix(in srgb, var(--sh-gold) 60%, transparent); }
.profile-menu[open] .menu { animation: pop-in 0.16s var(--ease-out); transform-origin: top right; }

/* Page titles carry a short gold rule. */
main h1::after {
  content: ""; display: block; width: 40px; height: 3px; margin-top: 6px; border-radius: 2px;
  background: linear-gradient(90deg, var(--sh-gold), color-mix(in srgb, var(--sh-gold) 30%, transparent));
}

/* Cards and tiles */
.stat { position: relative; overflow: hidden; transition: box-shadow 0.2s, transform 0.2s var(--ease-out); }
.stat::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 3px; background: var(--sh-gold); }
.stat.empty::before { background: var(--line-strong); }
.stat:hover { box-shadow: var(--shadow-lift); transform: translateY(-1px); }
.pick { position: relative; overflow: hidden; transition: border-color 0.15s, box-shadow 0.2s, transform 0.2s var(--ease-out), background 0.2s; }
.pick::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 3px; background: var(--sh-gold);
  transform: scaleY(0); transition: transform 0.25s var(--ease-out);
}
.pick:hover { background: var(--panel); box-shadow: var(--shadow-lift); transform: translateY(-2px); }
.pick:hover::before { transform: scaleY(1); }
a.chip { transition: border-color 0.15s, background 0.15s, transform 0.15s var(--ease-out); }
a.chip:hover { transform: translateY(-1px); }

/* Buttons: a soft top light on primary, and a press you can feel. */
button.primary, a.button.primary {
  background-image: linear-gradient(180deg, rgb(255 255 255 / 0.12), transparent);
  box-shadow: 0 1px 2px rgb(0 48 90 / 0.2);
}
button, a.button { transition: background-color 0.12s, border-color 0.12s, box-shadow 0.15s, transform 0.08s; }
button:active:not(:disabled):not(.link), a.button:active { transform: translateY(1px); }
button.primary:hover:not(:disabled), a.button.primary:hover { box-shadow: 0 3px 10px -2px color-mix(in srgb, var(--accent) 55%, transparent); }

/* Tables: the row under the pointer gets a gold edge. */
tbody tr:hover > td:first-child { box-shadow: inset 3px 0 0 var(--sh-gold); }
tr.group:hover > td:first-child { box-shadow: none; }

/* Toasts slide up; notes get a gold edge. */
.toast-item { box-shadow: 0 10px 30px -8px rgb(0 0 0 / 0.35); animation: toast-in 0.28s var(--ease-out); }
.toast-item:not(.error) { border-left: 3px solid var(--sh-gold); }
@keyframes toast-in { from { opacity: 0; transform: translateY(12px) scale(0.98); } }

/* Dialogs */
dialog[open] { animation: pop-in 0.2s var(--ease-out); box-shadow: 0 24px 60px -12px rgb(0 0 0 / 0.4); }
dialog[open]::backdrop { animation: fade-in 0.2s ease-out; backdrop-filter: blur(2px); }
@keyframes pop-in { from { opacity: 0; transform: translateY(6px) scale(0.98); } }
@keyframes fade-in { from { opacity: 0; } }

/* Going away (motion.js leave): a closed dialog fades down before it leaves
   the page, a toast slides off, and the profile menu folds back up. Only
   where the browser can keep something on screen while it closes; elsewhere
   they go at once, as before. The tutorial has its own way out. */
.toast-item.leaving { animation: toast-out 0.18s ease-in forwards; pointer-events: none; }
@keyframes toast-out { to { opacity: 0; transform: translateY(8px) scale(0.98); } }
@supports (overlay: auto) and (transition-behavior: allow-discrete) {
  dialog:not([open]):not(.tutorial) {
    opacity: 0; transform: translateY(4px) scale(0.98); pointer-events: none;
    transition: opacity 0.14s ease-in, transform 0.14s ease-in, overlay 0.14s allow-discrete, display 0.14s allow-discrete;
  }
  dialog:not([open]):not(.tutorial)::backdrop { opacity: 0; transition: opacity 0.14s ease-in, overlay 0.14s allow-discrete, display 0.14s allow-discrete; }
}
@supports selector(::details-content) and (transition-behavior: allow-discrete) {
  .profile-menu::details-content { transition: content-visibility 0.12s allow-discrete; }
  .profile-menu:not([open]) .menu { opacity: 0; transform: translateY(-4px) scale(0.98); transition: opacity 0.12s ease-in, transform 0.12s ease-in; }
}

/* A new page eases in, its first blocks a beat apart (ui.js render). */
main.page-enter > * { animation: page-in 0.38s var(--ease-out) backwards; }
main.page-enter > *:nth-child(2) { animation-delay: 0.04s; }
main.page-enter > *:nth-child(3) { animation-delay: 0.08s; }
main.page-enter > *:nth-child(n+4) { animation-delay: 0.12s; }
@keyframes page-in { from { opacity: 0; transform: translateY(8px); } }

/* Sign-in: the brand blue rises behind the card, which wears a gold cap. */
body:has(.login), body:has(main > .narrow) {
  background:
    radial-gradient(90% 60% at 50% -10%, color-mix(in srgb, var(--sh-blue) 22%, transparent), transparent 70%),
    radial-gradient(40% 30% at 85% 105%, color-mix(in srgb, var(--sh-gold) 12%, transparent), transparent 70%),
    var(--bg);
  min-height: 100vh;
}
main > .narrow { position: relative; overflow: hidden; box-shadow: var(--shadow-lift); }
main > .narrow::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 4px;
  background: linear-gradient(90deg, var(--sh-blue), var(--sh-gold) 55%, var(--sh-concrete));
}

@media (max-width: 640px) { .topbar { position: relative; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .stat:hover, .pick:hover, a.chip:hover, button:active, a.button:active { transform: none !important; }
}

/* Welcome tutorial (tutorial.js): a card per step with a screenshot in a
   browser-window frame, the header item it describes ringed in gold above a
   light backdrop. The card rises in, steps slide, the screenshot drifts and
   the ring pulses; none of it with prefers-reduced-motion. */
dialog.tutorial { width: min(760px, calc(100vw - 32px)); max-height: calc(100vh - 88px); margin-top: 72px; padding: 0; overflow: auto; }
dialog.tutorial[open] { animation: tutorial-in 0.34s cubic-bezier(.2, .7, .2, 1); }
dialog.tutorial.closing { animation: tutorial-out 0.18s ease-in forwards; }
/* No blur behind this dialog (Flair blurs the others): the header item it
   points at must stay sharp. */
dialog.tutorial[open]::backdrop { background: rgb(12 11 9 / 22%); animation: tutorial-fade 0.34s ease-out; backdrop-filter: none; }
dialog.tutorial.closing::backdrop { animation: tutorial-fade 0.18s ease-in reverse forwards; }
@keyframes tutorial-in { from { opacity: 0; transform: translateY(16px) scale(0.97); } }
@keyframes tutorial-out { to { opacity: 0; transform: translateY(8px) scale(0.98); } }
@keyframes tutorial-fade { from { opacity: 0; } }

.tutorial-frame { margin: 18px 22px 0; border: 1px solid var(--line-strong); border-radius: 8px; overflow: hidden; background: var(--panel-2); box-shadow: 0 10px 30px rgb(0 48 90 / 14%); }
.tutorial-chrome { display: flex; gap: 6px; padding: 7px 10px; background: var(--bar); }
.tutorial-chrome span { width: 9px; height: 9px; border-radius: 50%; background: color-mix(in srgb, var(--sh-concrete) 55%, transparent); }
.tutorial-chrome span:first-child { background: var(--sh-gold); }
.tutorial-view { position: relative; aspect-ratio: 16 / 9; overflow: hidden; background: #fff; }
.tutorial-shot { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top center; }
/* The cursor's tip is its box's top-left corner, at the point it points to. */
.tutorial-cursor { position: absolute; z-index: 2; width: 0; height: 0; pointer-events: none; }
.tutorial-cursor[hidden] { display: none; }
.tutorial-pointer { position: absolute; left: -5px; top: -2px; width: 22px; height: 22px; transform-origin: 5px 2px; filter: drop-shadow(0 2px 3px rgb(0 0 0 / 35%)); }
.tutorial-say {
  position: absolute; left: 18px; top: 18px; white-space: nowrap; padding: 3px 8px; border-radius: 4px;
  background: var(--sh-blue); color: #fff; font-size: var(--fs-xs); font-weight: 600; box-shadow: 0 2px 6px rgb(0 0 0 / 25%);
}
.tutorial-say:empty { display: none; }
.tutorial-cursor.left .tutorial-say { left: auto; right: 10px; }
.tutorial-cursor.up .tutorial-say { top: auto; bottom: 8px; }
.tutorial-ripple {
  position: absolute; z-index: 1; width: 44px; height: 44px; border-radius: 50%; pointer-events: none;
  border: 3px solid var(--sh-gold); background: color-mix(in srgb, var(--sh-gold) 25%, transparent); transform: translate(-50%, -50%) scale(0);
}

dialog.tutorial .tutorial-dots { margin: 16px 22px 0; }
dialog.tutorial .tutorial-text { padding: 0 22px; min-height: 9.5em; }
dialog.tutorial h3 { font-family: var(--font-display); font-size: 1.5rem; font-weight: 400; margin: 8px 0 4px; }
dialog.tutorial .tutorial-body p { margin: 8px 0; line-height: 1.5; }
dialog.tutorial .actions { align-items: center; margin: 8px 0 0; padding: 12px 22px 18px; }
dialog.tutorial .actions .spacer { flex: 1; }
dialog.tutorial .actions .muted { margin-right: 4px; }
.tutorial-dots { display: flex; gap: 6px; list-style: none; padding: 0; }
.tutorial-dots li { width: 14px; height: 4px; border-radius: 2px; background: var(--line-strong); transition: width 0.3s cubic-bezier(.2, .7, .2, 1), background-color 0.3s; }
.tutorial-dots li.on { width: 34px; background: var(--sh-gold); }

.tutorial-lit { outline: 3px solid var(--sh-gold) !important; outline-offset: -3px; border-radius: var(--control); color: #fff !important; background: var(--bar-hover) !important; animation: tutorial-pulse 1.6s ease-out infinite; }
@keyframes tutorial-pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--sh-gold) 70%, transparent); }
  70%, 100% { box-shadow: 0 0 0 12px transparent; }
}

@media (max-width: 640px) {
  dialog.tutorial { margin-top: 16px; max-height: calc(100vh - 32px); }
  .tutorial-frame { margin: 14px 14px 0; }
  dialog.tutorial .tutorial-dots, dialog.tutorial .tutorial-text { margin-left: 14px; margin-right: 14px; padding: 0; }
  dialog.tutorial .actions { padding: 12px 14px 14px; flex-wrap: wrap; }
}
@media (prefers-reduced-motion: reduce) {
  dialog.tutorial[open], dialog.tutorial.closing, dialog.tutorial[open]::backdrop, .tutorial-lit { animation: none; }
  .tutorial-dots li { transition: none; }
}

/* Phones (up to 640px wide). Desktop is unchanged; everything here only
   reshapes what's already on the page. */
#nav .short { display: none; }
@media (max-width: 640px) {
  /* Header: the five tabs share the width, with their short labels
     (nav.js), so none is pushed off the edge. The full label stays for
     screen readers. */
  .topbar { padding: 6px 12px 0; }
  .brand img { height: 22px; }
  #nav { height: 42px; gap: 0; overflow: visible; }
  #nav a { flex: 1 1 auto; justify-content: center; padding: 0 4px; font-size: var(--fs-md); min-width: 0; }
  #nav a::after { left: 8px; right: 8px; }
  #nav .long { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  #nav .short { display: inline; }
  /* No room for a tab's arrow on a phone: the tab opens its picker, which
     switches sections too (builder.js). */
  #nav .nav-drop { flex: 1 1 auto; min-width: 0; }
  #nav .nav-drop > a { flex: 1 1 auto; padding-right: 4px; }
  #nav .nav-drop > a::after { right: 8px; }
  #nav .nav-arrow { display: none; }
  .profile-menu .menu { position: fixed; left: 12px; right: 12px; top: 52px; min-width: 0; }
  .profile-menu .menu a, .profile-menu .menu button.link { padding: 11px 16px; }
  /* The header is taller here, so the "viewing as" strip scrolls away. */
  .viewing-as { position: static; padding: 8px 12px; }

  /* Page */
  h1 { font-size: 1.45rem; }
  .panel { padding: 16px 14px; margin-bottom: 14px; }
  .page-head { margin-bottom: 12px; }
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .stat .value { font-size: 1.15rem; }
  .grid, .pick-grid { grid-template-columns: 1fr; }
  .plan-row { grid-template-columns: 1fr; gap: 6px; }
  .kv { grid-template-columns: 1fr; gap: 2px; }
  .kv dd { margin-bottom: 8px; }
  .change { grid-template-columns: 1fr; }
  .page-tabs { flex-wrap: wrap; overflow: visible; }
  .page-tabs a { padding: 8px 10px; }
  .builder-budget > .crumbs { padding: 10px 22px 0; }
  table.attrs tbody { grid-template-columns: 1fr; }
  code.formula, table.sheet code.formula { max-width: 100%; }

  /* Controls: 16px text so iOS doesn't zoom in on a tap, and targets a
     thumb can hit. */
  input:not([type=checkbox]):not([type=radio]), select, textarea { font-size: 16px; }
  button:not(.link):not(.sort):not(.group-toggle), a.button { min-height: 40px; }
  button.small:not(.link), a.button.small, .small button:not(.link) { min-height: 34px; }
  label.check { min-height: 32px; }
  input[type=checkbox], input[type=radio] { width: 18px; height: 18px; }
  .table-tools input[type=search], .pick-search input[type=search] { max-width: none; }

  /* Narrow tables (table.js cards) become a card per row: label on the
     left, value on the right. Sort stays as a row of chips; the column
     filters give way to the search box. */
  .wide:has(> table.cards) { overflow: visible; border: 0; background: none; border-radius: 0; }
  table.cards, table.cards tbody, table.cards tr, table.cards td { display: block; }
  table.cards thead { display: block; }
  table.cards thead tr.filters { display: none; }
  table.cards thead tr:first-child { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 10px; }
  table.cards thead tr:first-child::before { content: "Sort"; font-size: var(--fs-xs); color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; margin-right: 2px; }
  table.cards thead th { position: static; display: block; width: auto; padding: 0; border: 0; box-shadow: none; background: none !important; }
  table.cards thead th:not(.sortable) { display: none; }
  table.cards th.sortable button.sort {
    padding: 5px 10px; border: 1px solid var(--line-strong); border-radius: 999px; background: var(--panel);
    text-align: left !important; white-space: nowrap;
  }
  table.cards th[aria-sort=ascending] button.sort, table.cards th[aria-sort=descending] button.sort { border-color: var(--accent); background: var(--accent-soft); }
  table.cards tbody tr {
    margin-bottom: 8px; padding: 8px 14px; border: 1px solid var(--line); border-radius: var(--radius);
    background: var(--panel); box-shadow: var(--shadow);
  }
  table.cards tbody tr[hidden] { display: none; }
  table.cards td {
    display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
    padding: 5px 0; border: 0; white-space: normal; text-align: right; overflow-wrap: anywhere;
    background: none !important; box-shadow: none !important; width: auto; min-width: 0; max-width: none;
  }
  table.cards td + td { border-top: 1px solid color-mix(in srgb, var(--line) 60%, transparent); }
  table.cards td::before { content: attr(data-label); flex: none; max-width: 45%; text-align: left; color: var(--muted); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.04em; }
  table.cards td:not([data-label])::before, table.cards td[data-label=""]::before { content: none; }
  table.cards td:not([data-label]), table.cards td[data-label=""] { justify-content: flex-start; text-align: left; }
  table.cards td:empty { display: none; }
  table.cards td.swatch { display: none; }
  table.cards td.repeat { color: inherit; }
  table.cards td.repeat > * { visibility: visible; }
  table.cards td > a:only-child, table.cards td > button.link:only-child { padding: 4px 0; }
  table.cards tr.run-start > td { border-top: 0; }
  table.cards tbody tr.group, table.cards tbody tr.empty { padding: 0; box-shadow: none; }
  table.cards tbody tr.empty td { justify-content: center; text-align: center; padding: 16px; }
  table.cards tbody tr.group td { padding: 0; }
  table.cards .sticky { position: static; min-width: 0; max-width: none; }
}

/* ---------------------------------------------------------------------------
   Polish: icons, the Home page, community cards, quick search, the split
   sign-in, loading outlines and the "?" help. Colours come from the tokens
   at the top, so all of it follows light and dark.
   ------------------------------------------------------------------------- */

/* Icons (icons.js): sized to the text and sitting on its baseline. */
.icon { width: 1.15em; height: 1.15em; flex: none; vertical-align: -0.2em; }
/* Only buttons that carry an icon become flex rows, so every other button
   (the takeoff's own among them) keeps its layout. */
a.button:has(> .icon), button:not(.link):has(> .icon) { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
.icon.go { margin-left: auto; color: var(--muted); transition: transform 0.2s var(--ease-out), color 0.2s; }
h2:has(> .icon) { display: flex; align-items: center; gap: 8px; }
h2 > .icon { color: var(--sh-gold); width: 1.05em; height: 1.05em; }
:root { --icon-soft: color-mix(in srgb, var(--accent) 9%, var(--panel)); }

/* Header: icons on the tabs, a search button, and who's signed in at the
   head of the profile menu (the Admin label moved there). */
#nav a .icon { opacity: 0.75; transition: opacity 0.15s; }
#nav a:hover .icon, #nav a.active .icon { opacity: 1; }
#nav a.active .icon { color: var(--sh-gold); }
#profile { display: flex; align-items: center; gap: 10px; }
.search-button {
  height: 34px; padding: 0 8px 0 10px; gap: 8px; border-radius: 8px; font-size: var(--fs-md);
  color: var(--bar-ink); background: color-mix(in srgb, #fff 8%, transparent); border: 1px solid color-mix(in srgb, #fff 14%, transparent);
}
.search-button:hover:not(:disabled) { color: #fff; background: color-mix(in srgb, #fff 14%, transparent); border-color: color-mix(in srgb, #fff 24%, transparent); }
.search-button .search-label { min-width: 90px; text-align: left; }
kbd, .search-button kbd, .home-search kbd, .palette kbd {
  background: none; color: inherit; box-shadow: none;
  font-family: var(--font-sans); font-size: var(--fs-xs); font-weight: 600; line-height: 1;
  padding: 3px 6px; border-radius: 4px; border: 1px solid currentColor; opacity: 0.7; white-space: nowrap;
}
.profile-menu .who { display: flex; gap: 12px; align-items: center; padding: 10px 14px 12px; border-bottom: 1px solid var(--line); }
.avatar.big { width: 38px; height: 38px; font-size: var(--fs-md); }
.who-text { display: flex; flex-direction: column; min-width: 0; font-size: var(--fs-md); }
.who-text .muted { font-size: var(--fs-sm); overflow: hidden; text-overflow: ellipsis; }
.who-role { margin-top: 4px; align-self: flex-start; font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--accent); background: var(--accent-soft); padding: 2px 7px; border-radius: 3px; }
.profile-menu .menu a, .profile-menu .menu button.link { display: flex; align-items: center; gap: 10px; }
.profile-menu .menu .icon { color: var(--muted); }
.profile-menu .menu { min-width: 280px; }
/* Between a phone and a wide screen (641-1400px) the header steps down
   instead of running past the right edge, which also scrolled the whole
   page sideways: first the "Estimating" word goes, then search shrinks to
   its icon (its title still names the shortcut, nav.js), then your name, then
   the tabs take their short labels (nav.js), then lose their icons. As a
   last resort the tabs scroll, so search and the profile menu stay in reach. */
.profile-menu .name { max-width: 10em; overflow: hidden; text-overflow: ellipsis; }
@media (min-width: 641px) {
  #nav { min-width: 0; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
  #nav::-webkit-scrollbar { display: none; }
  #nav a:focus-visible { outline-offset: -3px; } /* inside the row, so the scroller doesn't clip it */
}
@media (min-width: 641px) and (max-width: 1400px) {
  .brand .app { display: none; }
}
@media (min-width: 641px) and (max-width: 1340px) {
  .topbar { gap: 16px; padding: 0 16px; }
  .search-button { width: 34px; padding: 0; justify-content: center; }
  .search-button .search-label, .search-button kbd { display: none; }
}
@media (min-width: 641px) and (max-width: 1100px) {
  .profile-menu .name { display: none; }
}
@media (min-width: 641px) and (max-width: 1020px) {
  #nav .long { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  #nav .short { display: inline; }
  #nav a { padding: 0 10px; }
  #nav a::after { left: 10px; right: 10px; }
}
@media (min-width: 641px) and (max-width: 760px) {
  #nav a { padding: 0 8px; }
  #nav a::after { left: 8px; right: 8px; }
  #nav a .icon { display: none; }
}

/* Numbers in calculated cells that are a workbook error: a quiet dash. */
.cell-error { color: var(--muted); cursor: help; }

/* Subtitle with a "?" that opens the rest (ui.js subtitle). */
.sub-wrap { margin: 0 0 20px; position: relative; }
.sub-wrap p.sub { margin: 0; }
.page-head .sub-wrap { margin: 0; }
.help-toggle {
  width: 20px; height: 20px; padding: 0; border-radius: 50%; font-size: var(--fs-xs); font-weight: 700; line-height: 1;
  vertical-align: 1px; color: var(--muted); background: var(--panel); border: 1px solid var(--line-strong);
}
.help-toggle:hover:not(:disabled), .help-toggle[aria-expanded=true] { color: var(--accent-ink); background: var(--accent); border-color: var(--accent); }
/* Floats over the page under the subtitle, so nothing below moves. Under the
   sticky bars (z-index 19–20) so it scrolls beneath them. */
.help-more {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 18;
  width: max-content; max-width: min(820px, calc(100vw - 32px)); padding: 10px 14px; font-size: var(--fs-md); color: var(--ink);
  background-color: var(--panel); /* solid under the tint, so the page doesn't show through */
  background-image: linear-gradient(var(--accent-soft), var(--accent-soft));
  border: 1px solid var(--line); border-left: 3px solid var(--sh-gold); border-radius: 0 var(--radius) var(--radius) 0;
  box-shadow: 0 8px 24px rgb(0 20 40 / 0.18);
  animation: pop-in 0.18s var(--ease-out);
}
.help-more[hidden] { display: none; }
.help-more p { margin: 4px 0; line-height: 1.5; }

/* Loading outline (ui.js showSkeleton): grey blocks with a slow sheen. */
.skeleton { display: flex; flex-direction: column; gap: 12px; }
.sk { border-radius: 6px; background: linear-gradient(90deg, var(--line) 25%, color-mix(in srgb, var(--line) 45%, var(--panel)) 37%, var(--line) 63%); background-size: 400% 100%; animation: sk-sheen 1.4s ease infinite; }
.sk-crumb { width: 180px; height: 12px; }
.sk-title { width: 300px; max-width: 70%; height: 30px; }
.sk-sub { width: 460px; max-width: 90%; height: 14px; margin-bottom: 8px; }
.sk-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 12px; }
.sk-tile { height: 84px; border-radius: var(--radius); }
.sk-panel { display: flex; flex-direction: column; gap: 12px; padding: 20px; background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); }
.sk-h { width: 200px; height: 18px; }
.sk-line { height: 12px; }
.sk-line.short { width: 60%; }
@keyframes sk-sheen { from { background-position: 100% 50%; } to { background-position: 0 50%; } }
main.skeleton-page { opacity: 1 !important; }
body.loading main.skeleton-page { opacity: 1; }

/* Empty blocks (ui.js emptyState). */
.empty-state { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 10px; padding: 28px 16px; color: var(--muted); }
.empty-state p { margin: 0; max-width: 460px; line-height: 1.5; }
.empty-state strong { color: var(--ink); }
.empty-icon { display: grid; place-items: center; width: 56px; height: 56px; border-radius: 50%; color: var(--accent); background: var(--icon-soft); }

/* Rows that open from anywhere on them (ui.js, a.row-link). */
tbody tr:has(a.row-link) { cursor: pointer; }
a.row-link { font-weight: 600; text-decoration: none; }
tbody tr:hover a.row-link { text-decoration: underline; }

/* Home (home.js) */
.home-hero { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; margin-bottom: 20px; }
.home-hero h1 { font-size: 2.2rem; }
.home-hero p.sub { margin: 0; }
.home-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.home-search {
  min-width: 300px; justify-content: flex-start; gap: 10px; padding: 9px 12px; color: var(--muted);
  background: var(--panel); border-color: var(--line-strong); border-radius: 8px; box-shadow: var(--shadow);
}
.home-search span { flex: 1; text-align: left; }
.home-actions a.button.primary { padding: 9px 16px; border-radius: 8px; }
.home-stats { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.stat .label { display: flex; align-items: center; gap: 6px; }
.stat .label .icon { color: var(--accent); }
.stat .value { font-family: var(--font-display); font-size: 1.75rem; font-weight: 600; letter-spacing: -0.01em; }
a.stat { display: block; text-decoration: none; color: inherit; }
a.stat:hover { border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); }
.stat.warn::before { background: var(--sh-terracotta); }
.stat.warn .value { color: var(--danger); }
.home-grid { display: grid; grid-template-columns: minmax(0, 1.65fr) minmax(300px, 1fr); gap: 20px; align-items: start; }
.home-panel h2 { margin-bottom: 14px; }
.home-main > .panel:last-child, .home-side > .panel:last-child { margin-bottom: 0; }
.work-list { display: flex; flex-direction: column; }
.work {
  display: flex; align-items: center; gap: 14px; padding: 12px 10px; margin: 0 -10px; border-radius: 8px;
  text-decoration: none; color: var(--ink); transition: background 0.15s;
}
.work + .work { border-top: 1px solid var(--line); }
.work:hover { background: var(--panel-2); }
.work:hover .icon.go { transform: translateX(3px); color: var(--accent); }
.work-badge {
  display: grid; place-items: center; flex: none; width: 44px; height: 44px; border-radius: 10px;
  font-weight: 700; font-size: var(--fs-md); color: var(--sh-concrete); background: var(--sh-blue);
}
.work-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.work-text .muted { font-size: var(--fs-sm); }
.work-meta { display: flex; flex-direction: column; align-items: flex-end; font-size: var(--fs-sm); white-space: nowrap; }
ol.feed { list-style: none; margin: 0; padding: 0; position: relative; }
ol.feed::before { content: ""; position: absolute; left: 5px; top: 8px; bottom: 8px; width: 2px; background: var(--line); }
ol.feed li { position: relative; display: flex; gap: 14px; padding: 6px 0; }
ol.feed p { margin: 0; line-height: 1.45; }
.feed-dot { flex: none; width: 12px; height: 12px; margin-top: 4px; border-radius: 50%; background: var(--panel); border: 2px solid var(--sh-gold); position: relative; }
ul.changelog { list-style: none; margin: 0; padding: 0; columns: auto; }
ul.changelog li { display: flex; gap: 12px; align-items: baseline; padding: 6px 0; line-height: 1.45; }
ul.changelog li.changelog-day { padding: 10px 0 2px; font-size: var(--fs-sm); font-weight: 600; color: var(--muted); }
ul.changelog li.changelog-day:first-child { padding-top: 0; }
.changelog-area {
  flex: none; width: 104px; padding: 1px 8px; border-radius: 999px; text-align: center;
  font-size: var(--fs-xs); font-weight: 600; color: var(--accent); background: var(--icon-soft);
}
details.changelog-more { margin-top: 10px; }
details.changelog-more > summary { color: var(--accent); font-size: var(--fs-sm); font-weight: 600; }
/* The side column is narrow: the area tag sits above its line. */
.home-side ul.changelog li:not(.changelog-day) { flex-direction: column; gap: 4px; }
.home-side .changelog-area { width: auto; }
ul.attention { list-style: none; margin: 0; padding: 0; }
ul.attention li { display: flex; align-items: center; gap: 12px; padding: 10px 0; }
ul.attention li + li { border-top: 1px solid var(--line); }
.attention-icon { display: grid; place-items: center; flex: none; width: 34px; height: 34px; border-radius: 8px; color: var(--read); background: var(--warn-bg); }
.attention-text { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.all-clear { display: flex; gap: 12px; align-items: center; padding: 6px 0; color: var(--ok); }
.all-clear > span { display: flex; flex-direction: column; color: var(--ink); }
.all-clear .muted { font-size: var(--fs-sm); }

/* Community cards (communities.js) */
.page-head h1 { margin-bottom: 4px; }
.list-tools { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 16px; }
.search-field {
  flex-direction: row; align-items: center; gap: 8px; padding: 0 10px; min-width: 300px;
  background: var(--panel); border: 1px solid var(--line-strong); border-radius: 8px; color: var(--muted);
}
.search-field:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
.search-field input { border: 0; box-shadow: none !important; padding: 9px 0; background: none; min-width: 0; flex: 1; font-size: var(--fs-base); }
.view-switch button { display: inline-flex; gap: 6px; }
.community-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }
.community-card {
  position: relative; display: flex; flex-direction: column; gap: 10px; padding: 18px 18px 14px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px; box-shadow: var(--shadow);
  color: var(--ink); text-decoration: none; overflow: hidden;
  transition: transform 0.2s var(--ease-out), box-shadow 0.2s, border-color 0.2s;
}
.community-card::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: linear-gradient(90deg, var(--sh-blue), var(--sh-gold)); transform: scaleX(0); transform-origin: left;
  transition: transform 0.3s var(--ease-out);
}
.community-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); border-color: color-mix(in srgb, var(--accent) 30%, var(--line)); }
.community-card:hover::before { transform: scaleX(1); }
.community-card:hover .icon.go { transform: translateX(3px); color: var(--accent); }
.community-card.off { opacity: 0.7; }
.cc-logo { margin: -18px -18px 4px; height: 104px; display: flex; align-items: center; justify-content: center; padding: 14px 18px; border-bottom: 1px solid var(--line); }
.cc-logo.on-dark, .logo-tile.on-dark { background: var(--sh-blue); }
.cc-logo.on-light, .logo-tile.on-light { background: #fff; }
.cc-logo img { max-width: 100%; max-height: 100%; object-fit: contain; }
.community-card.has-logo::before { z-index: 1; }

/* Community logos (logos.js) */
.logo-tile { width: 132px; height: 60px; display: flex; align-items: center; justify-content: center; padding: 8px 12px; border-radius: 6px; border: 1px solid var(--line); }
.logo-tile img { max-width: 100%; max-height: 100%; object-fit: contain; }
.logo-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: flex-end; }
.pull-results { margin-top: 12px; }
.site-logos { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.site-logo { display: flex; flex-direction: column; gap: 8px; padding: 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel-2); }
.site-logo .logo-tile { width: 100%; height: 84px; }
.site-logo .row { display: flex; gap: 8px; }
.site-logo select { flex: 1; min-width: 0; }
.cc-head { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.cc-code { font-family: var(--font-data); font-size: var(--fs-xs); font-weight: 600; color: var(--muted); background: var(--panel-2); border: 1px solid var(--line); border-radius: 4px; padding: 1px 6px; }
.cc-market, .cc-access { font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; padding: 2px 7px; border-radius: 3px; }
.cc-market { color: var(--accent); background: var(--accent-soft); }
.cc-access { color: var(--read); background: var(--warn-bg); }
.cc-name { margin: 0; font-family: var(--font-display); font-size: 1.3rem; font-weight: 600; color: var(--heading); letter-spacing: -0.005em; }
.cc-facts { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-md); }
.cc-facts > span, .cc-foot > span { display: inline-flex; align-items: center; gap: 7px; }
.cc-facts .icon { color: var(--muted); }
.cc-facts .ok .icon { color: var(--ok); }
.cc-facts .warn { color: var(--read); }
.cc-facts .warn .icon { color: var(--read); }
.cc-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; margin-top: auto; padding-top: 10px; border-top: 1px solid var(--line); font-size: var(--fs-sm); }
.no-match { grid-column: 1 / -1; }

/* Quick search (palette.js) */
dialog.palette {
  width: min(640px, calc(100vw - 32px)); margin-top: 12vh; padding: 0; overflow: hidden;
  color: var(--ink); background: var(--panel); border: 1px solid var(--line-strong); border-radius: 12px;
}
dialog.palette::backdrop { background: rgb(0 20 39 / 45%); backdrop-filter: blur(3px); }
.palette-input { display: flex; align-items: center; gap: 10px; padding: 0 16px; border-bottom: 1px solid var(--line); color: var(--muted); }
.palette-input .icon { width: 20px; height: 20px; }
.palette-input input { flex: 1; min-width: 0; border: 0; padding: 16px 0; font-size: 1.1rem; background: none; box-shadow: none !important; }
.palette-list { list-style: none; margin: 0; padding: 6px; max-height: min(420px, 55vh); overflow-y: auto; }
.palette-item { display: flex; align-items: center; gap: 12px; padding: 9px 10px; border-radius: 8px; cursor: pointer; }
.palette-item.on { background: var(--accent-soft); }
.palette-item.off { opacity: 0.6; }
.palette-icon { display: grid; place-items: center; flex: none; width: 32px; height: 32px; border-radius: 8px; color: var(--accent); background: var(--icon-soft); }
.palette-item.on .palette-icon { color: var(--accent-ink); background: var(--accent); }
.palette-text { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.palette-label { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette-detail { font-size: var(--fs-sm); color: var(--muted); }
.palette-also { display: flex; gap: 4px; }
.palette-also a { font-size: var(--fs-xs); font-weight: 600; text-decoration: none; padding: 3px 8px; border-radius: 4px; border: 1px solid var(--line-strong); color: var(--ink); background: var(--panel); }
.palette-also a:hover { border-color: var(--accent); color: var(--accent); }
.palette-kind { font-size: var(--fs-xs); color: var(--muted); width: 72px; text-align: right; }
.palette-empty { padding: 24px; text-align: center; color: var(--muted); }
.palette-foot { display: flex; gap: 18px; padding: 9px 16px; border-top: 1px solid var(--line); font-size: var(--fs-xs); color: var(--muted); background: var(--panel-2); }
.palette-foot kbd { margin-right: 2px; }

/* Sign-in (account.js): a Signature Homes photo (public/brand/login-photo.jpg,
   from signature.homes) under a wash of SH Blue, the form beside it. The
   wash darkens the top for the logo and the foot for the line of text. */
main:has(.login-split) { max-width: none; padding: 0; }
body:has(.login-split) { background: var(--bg); }
.login-split { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(380px, 1fr); min-height: 100vh; }
.login-art {
  position: relative; display: flex; flex-direction: column; justify-content: space-between; padding: 40px 48px; overflow: hidden;
  color: var(--sh-concrete);
  background:
    linear-gradient(180deg, rgb(0 30 58 / 0.72) 0%, rgb(0 30 58 / 0.12) 26%, rgb(0 30 58 / 0.1) 52%, rgb(0 30 58 / 0.88) 100%),
    linear-gradient(90deg, rgb(0 48 90 / 0.25), transparent 60%),
    url(/brand/login-photo.jpg) center / cover no-repeat,
    var(--sh-blue);
}
.login-art::after { content: ""; position: absolute; inset: auto 0 0 0; height: 4px; background: linear-gradient(90deg, var(--sh-gold), color-mix(in srgb, var(--sh-gold) 10%, transparent)); }
.login-art-logo { height: 34px; width: auto; align-self: flex-start; }
.login-art-text { max-width: 440px; }
.login-art-kicker { margin: 0 0 6px; font-size: var(--fs-sm); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--sh-gold); }
.login-art-line { margin: 0; font-family: var(--font-display); font-size: 2rem; line-height: 1.2; color: #fff; text-shadow: 0 2px 16px rgb(0 0 0 / 0.35); }
.login-side { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 40px 24px; }
.login-side .login { width: 100%; max-width: 380px; padding: 0; }
.login-side .login h1 { font-size: 2rem; }
.login-side .login form { margin-top: 8px; display: flex; flex-direction: column; gap: 14px; }
.login-side .login input { padding: 10px 12px; font-size: var(--fs-base); border-radius: 8px; }
.login-side .login button.wide-button { width: 100%; padding: 11px 16px; border-radius: 8px; font-size: var(--fs-base); }
.login-side .login .actions { margin-top: 6px; }
.login-foot { margin-top: 40px; }

/* Phones */
@media (max-width: 900px) {
  .home-grid { grid-template-columns: 1fr; }
  .login-split { grid-template-columns: 1fr; }
  .login-art { min-height: 260px; padding: 24px; }
  .login-art-line { font-size: 1.4rem; }
}
@media (max-width: 640px) {
  /* Five tabs: the icon above a short label. */
  #nav a { flex-direction: column; gap: 1px; font-size: var(--fs-xs); padding: 2px 2px 4px; }
  #nav a .icon { width: 18px; height: 18px; }
  #nav .count { position: absolute; top: 0; right: 6px; }
  .search-button { width: 34px; padding: 0; justify-content: center; }
  .search-button .search-label, .search-button kbd { display: none; }
  .home-hero h1 { font-size: 1.6rem; }
  .home-actions, .home-search { width: 100%; min-width: 0; }
  .home-search kbd { display: none; }
  .home-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat .value { font-size: 1.35rem; }
  .search-field { min-width: 0; flex: 1 1 100%; }
  .community-grid { grid-template-columns: 1fr; }
  .work-meta { display: none; }
  .palette-kind, .palette-foot { display: none; }
  dialog.palette { margin-top: 16px; }
  /* A band of the photo with the logo on it; the form below has none. */
  .login-art { min-height: 190px; padding: 22px 24px; }
  .login-art-text { display: none; }
  .login-side .login-logo { display: none; }
  button.help-toggle { min-height: 0; width: 22px; height: 22px; }
}
@media (prefers-reduced-motion: reduce) {
  .sk { animation: none; }
  .community-card:hover { transform: none; }
}

/* Settings page: each setting stacks on a phone. */
@media (max-width: 640px) {
  .settings-table thead { display: none; }
  .settings-table, .settings-table tbody, .settings-table tr, .settings-table td { display: block; width: auto !important; }
  .settings-table tr { padding: 10px 0; border-bottom: 1px solid var(--line); }
  .settings-table td { border: 0; padding: 4px 0; }
  .settings-table td[data-label="Default"]::before { content: "Default: "; color: var(--muted); }
}

/* whats-new.js: the new-version pop-up */
dialog.whats-new-dialog h3 { display: flex; align-items: center; gap: 8px; }
dialog.whats-new-dialog ul.changelog { margin: 12px 0 4px; max-height: 50vh; overflow-y: auto; }
dialog.whats-new-dialog ul.changelog li { flex-direction: column; gap: 4px; }
dialog.whats-new-dialog .changelog-area { width: auto; align-self: flex-start; }
dialog.whats-new-dialog .actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }
#whats-new { scroll-margin-top: 72px; }

/* DO Takeoffs (options.js, options-newstar.js) */
/* An option's elevations: each chip with how far along its take-off is. */
.option-elevs { gap: 10px 16px; align-items: flex-start; }
.option-elev { display: inline-flex; flex-direction: column; align-items: center; gap: 3px; }
.option-elev .progress { white-space: nowrap; }
/* The option's own PDFs: name, facts and Remove on one line. */
ul.option-docs li { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
form.option-upload .row { align-items: flex-end; }
form.option-upload label { min-width: 0; }
/* Newstar upload: the three pick groups side by side, each a column of tick boxes. */
.option-newstar-picks { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px 24px; margin-bottom: 12px; }
.option-newstar-picks .pick-group { min-width: 0; }
.option-newstar-picks .pick-grid { grid-template-columns: 1fr; }
.pick-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.pick-head h3 { margin: 0; }
/* Admin › Rates from HBLive: the part lists to read. */
.part-lists { margin-top: 18px; border-top: 1px solid var(--line); }
.part-list-picks { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 4px 16px; margin: 8px 0; }
.option-picks { display: flex; flex-direction: column; gap: 4px; }
.option-picks label.check { align-items: baseline; flex-wrap: wrap; gap: 6px; }
.option-picks label.check input { align-self: center; }
.newstar-summary { font-weight: 600; margin: 12px 0 0; }
/* Signed quantities in a comparison: adds in green, takes away in red. */
.sign-add { color: var(--ok); }
.sign-deduct { color: var(--danger); }
@media (max-width: 640px) {
  .option-newstar-picks { grid-template-columns: 1fr; }
  .option-elev { align-items: flex-start; }
}

/* *optmaster page (optmaster.js): the default minor codes in a row and the
   option master model box, then the crafts sheet with a code box per cell.
   A craft with codes (saved or typed) carries an accent bar on its left. */
.optmaster form > h2 { margin-top: 20px; }
.optmaster form > h2:first-child { margin-top: 0; }
.optmaster h2 + p { margin: -4px 0 10px; }
.optmaster-fields { display: flex; gap: 16px 24px; flex-wrap: wrap; align-items: flex-start; margin-bottom: 4px; }
.optmaster-field label { color: var(--ink); font-weight: 600; width: max-content; }
.optmaster-field label input { font-weight: 400; }
.optmaster-field.model input.code-input { width: 12em; }
.optmaster-field .small { margin-top: 4px; }
.optmaster-field .badge { margin-right: 6px; }
.optmaster-field button.link { margin-left: 8px; }
input.code-input { width: 7em; font-family: var(--font-data); }
.optmaster-add { display: inline-flex; gap: 6px; align-items: center; }
.optmaster td.code { font-weight: 600; font-family: var(--font-data); }
.optmaster td.code-cell { padding: 2px 4px; }
.optmaster td.code-cell input.code-input { padding: 3px 6px; min-width: 0; } /* width set in optmaster.js: the longest code or placeholder in its column */
/* Narrow columns (On budgets, the flags, the codes, Major header): as narrow
   as what's in them, their headings wrapped. */
.optmaster .narrow { width: 1%; }
.optmaster th.narrow { white-space: normal; line-height: 1.25; vertical-align: bottom; }
.optmaster th.narrow.sortable button.sort { padding: 6px 6px; }
.optmaster td.flag .badge { white-space: normal; }
.optmaster td.major-header { white-space: normal; min-width: 8em; font-family: var(--font-data); }
.optmaster td.major-header .small { font-family: var(--font-sans); line-height: 1.2; }
.optmaster td.code-cell select.type-select { padding: 3px 6px; width: 8em; }
.optmaster td.code-cell select.type-select.inherited { color: var(--muted); }
/* A blank choice that takes HBLive's craft type: green, over the grey above. */
.optmaster td.code-cell select.type-select.inherited.hb-select { color: var(--ok); }
.optmaster td.code-cell.fixed { padding: 2px 10px; font-family: var(--font-data); }
.optmaster-scope { display: inline-flex; gap: 6px; align-items: center; }
.optmaster-scope select { width: auto; max-width: 18em; }
.optmaster tr.set td.code { box-shadow: inset 3px 0 var(--accent); }
.optmaster td.changed-cell button.link { margin-left: 8px; }
.optmaster input[aria-invalid="true"] { border-color: var(--danger); box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 20%, transparent); }
.optmaster .actions .small { margin-left: 4px; }
.optmaster td.craft-pick, .optmaster th.craft-pick { width: 1%; text-align: center; padding-left: 6px; padding-right: 6px; }
.optmaster .craft-pick input[type=checkbox] { width: 16px; height: 16px; padding: 0; margin: 0; vertical-align: middle; accent-color: var(--accent); }
.optmaster td.flag { text-align: center; white-space: nowrap; }
.optmaster td.projects-cell { max-width: 16em; }
.optmaster-bulk { display: inline-flex; gap: 6px; align-items: center; }
.optmaster-bulk select { width: auto; }
.craft-projects-dialog .project-list { max-height: 50vh; overflow: auto; display: grid; gap: 2px; margin: 8px 0; padding: 6px 8px; border: 1px solid var(--line); border-radius: 6px; }
dialog.src-dialog.craft-projects-dialog .project-list label { display: flex; flex-direction: row; gap: 8px; align-items: center; margin: 0; padding: 4px 2px; color: var(--ink); font-size: var(--fs-md); cursor: pointer; }
dialog.src-dialog.craft-projects-dialog .project-list label[hidden] { display: none; }
.craft-projects-dialog .project-list input[type=checkbox] { width: 16px; height: 16px; padding: 0; margin: 0; accent-color: var(--accent); }
.craft-projects-dialog input[type=search] { width: 100%; min-width: 0; }
.craft-projects-dialog .project-all { font-weight: 600; border-bottom: 1px solid var(--line); padding-bottom: 4px; margin-bottom: 2px; }

/* ---------------------------------------------------------------------------
   Polish: the header's depth, community bands, plan pictures, trend lines,
   the "changed lately" dot, and a little motion. */

/* Header: SH Blue with a soft light from the left, a faint drafting grid and
   a gold hairline along the bottom. */
.topbar {
  background:
    radial-gradient(120% 220% at 0% 0%, color-mix(in srgb, #fff 9%, transparent), transparent 55%),
    linear-gradient(color-mix(in srgb, #fff 4%, transparent) 1px, transparent 1px) 0 0 / 28px 28px,
    linear-gradient(90deg, color-mix(in srgb, #fff 4%, transparent) 1px, transparent 1px) 0 0 / 28px 28px,
    var(--bar);
}
.topbar::after {
  content: ""; position: absolute; inset: auto 0 0 0; height: 2px; pointer-events: none;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--sh-gold) 70%, transparent) 20%, var(--sh-gold) 50%, color-mix(in srgb, var(--sh-gold) 70%, transparent) 80%, transparent);
  opacity: 0.55;
}

/* A tab whose part of the program changed lately (tab-news.js). */
#nav a { position: relative; }
.news-dot {
  position: absolute; top: 12px; right: 2px; width: 7px; height: 7px; border-radius: 50%;
  background: var(--sh-gold); box-shadow: 0 0 0 2px var(--bar);
  animation: news-pulse 2.4s ease-in-out 3;
}
@keyframes news-pulse { 50% { box-shadow: 0 0 0 2px var(--bar), 0 0 0 6px color-mix(in srgb, var(--sh-gold) 30%, transparent); } }

/* A community without a logo: its initials on a blueprint grid
   (community-band.js communityBand), in one of four brand tones. */
.cc-band {
  position: relative; overflow: hidden; color: var(--sh-concrete);
  --band: var(--sh-blue); --band-glow: var(--sh-gold);
  background:
    radial-gradient(80% 140% at 100% 0%, color-mix(in srgb, var(--band-glow) 28%, transparent), transparent 60%),
    linear-gradient(color-mix(in srgb, #fff 7%, transparent) 1px, transparent 1px) 0 0 / 16px 16px,
    linear-gradient(90deg, color-mix(in srgb, #fff 7%, transparent) 1px, transparent 1px) 0 0 / 16px 16px,
    var(--band);
}
.cc-band.tone-1 { --band: #0b3f6e; --band-glow: var(--sh-concrete); }
.cc-band.tone-2 { --band: #12324f; --band-glow: var(--sh-terracotta); }
.cc-band.tone-3 { --band: #002544; --band-glow: #4f8fc9; }
.cc-initials {
  font-family: var(--font-display); font-weight: 600; font-size: 3rem; line-height: 1; letter-spacing: 0.02em;
  color: color-mix(in srgb, var(--sh-concrete) 92%, transparent);
  text-shadow: 0 2px 18px rgb(0 0 0 / 0.25);
  transition: transform 0.4s var(--ease-out), letter-spacing 0.4s var(--ease-out);
}
.cc-band-name {
  position: absolute; left: 14px; bottom: 9px; font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: color-mix(in srgb, var(--sh-concrete) 55%, transparent);
}
.community-card:hover .cc-initials { transform: scale(1.06); letter-spacing: 0.06em; }
.community-card .cc-logo img { transition: transform 0.4s var(--ease-out); }
.community-card:hover .cc-logo img { transform: scale(1.04); }

/* Home tiles: a trend line along the bottom, and a quieter "None yet". */
.stat .sparkline { position: relative; display: block; width: 100%; height: 30px; margin-top: 8px; color: var(--accent); }
.sparkline svg { display: block; width: 100%; height: 100%; overflow: visible; }
.stat .spark-span { display: flex; justify-content: space-between; margin-top: 4px; font-size: var(--fs-xs); color: var(--muted); }
.spark-line { fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.spark-area { fill: currentColor; opacity: 0.12; }
.spark-dot { position: absolute; width: 7px; height: 7px; border-radius: 50%; background: var(--sh-gold); box-shadow: 0 0 0 1.5px var(--panel); transform: translate(-50%, -50%); }
main.page-enter .spark-line { stroke-dasharray: 1; stroke-dashoffset: 1; animation: spark-draw 0.9s 0.2s var(--ease-out) forwards; }
@keyframes spark-draw { to { stroke-dashoffset: 0; } }
.stat.quiet .value { color: var(--muted); font-size: 1.35rem; }

/* What's new on Home: each change folds to three lines until clicked. */
.home-side ul.changelog li:not(.changelog-day) > span:last-child {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; cursor: pointer;
}
.home-side ul.changelog li.open:not(.changelog-day) > span:last-child { -webkit-line-clamp: unset; line-clamp: none; cursor: auto; }

/* A community's page: its numbers across the top. */
.community-stats { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.community-stats .stat .value { font-size: 1.5rem; }

/* An elevation's chip with HighArc's picture of it above its code (builder.js). */
.plan-pick .chips { align-items: flex-end; }
a.chip.elev.pictured { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 4px 4px 3px; }
a.chip.elev.pictured img { display: block; width: 132px; height: 76px; object-fit: cover; border-radius: 4px; background: var(--paper); }

/* Cards and tiles come in one after another when a page opens. */
main.page-enter .community-grid > *, main.page-enter .stats > *, main.page-enter .plan-pick > * {
  animation: page-in 0.42s var(--ease-out) backwards;
}
main.page-enter .community-grid > :nth-child(2), main.page-enter .stats > :nth-child(2), main.page-enter .plan-pick > :nth-child(2) { animation-delay: 0.05s; }
main.page-enter .community-grid > :nth-child(3), main.page-enter .stats > :nth-child(3), main.page-enter .plan-pick > :nth-child(3) { animation-delay: 0.1s; }
main.page-enter .community-grid > :nth-child(4), main.page-enter .stats > :nth-child(4), main.page-enter .plan-pick > :nth-child(4) { animation-delay: 0.15s; }
main.page-enter .community-grid > :nth-child(5), main.page-enter .stats > :nth-child(5), main.page-enter .plan-pick > :nth-child(5) { animation-delay: 0.2s; }
main.page-enter .community-grid > :nth-child(n+6), main.page-enter .plan-pick > :nth-child(n+6) { animation-delay: 0.25s; }

/* A note that something's done: a gold check that draws itself. */
.toast-item.done { display: flex; align-items: center; gap: 10px; }
.toast-check { flex: none; color: var(--sh-gold); width: 18px; height: 18px; }
.toast-check path, .toast-check polyline { stroke-dasharray: 30; stroke-dashoffset: 30; animation: check-draw 0.45s 0.12s var(--ease-out) forwards; }
@keyframes check-draw { to { stroke-dashoffset: 0; } }

@media (max-width: 640px) {
  .news-dot { top: 6px; right: 4px; }
  .cc-initials { font-size: 2.4rem; }
  .community-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (prefers-reduced-motion: reduce) {
  .spark-line, .toast-check path, .toast-check polyline { stroke-dasharray: none; stroke-dashoffset: 0; }
  .community-card:hover .cc-initials, .community-card:hover .cc-logo img { transform: none; }
}

/* ---------------------------------------------------------------------------
   Colours (theme.js; nav.js themeSwitch): Light, Dark or Auto in the profile
   menu. The dark colours themselves are at the top of this file. */
.profile-menu .theme-group { padding: 6px 14px 10px; }
.profile-menu .theme-group .heading { padding: 2px 0 6px; }
.theme-switch { display: flex; flex-wrap: nowrap; width: 100%; }
.theme-switch button { flex: 1; padding: 6px 8px; font-size: var(--fs-sm); color: var(--ink); background: var(--panel); }
.profile-menu .menu .theme-switch .icon { color: currentColor; }
.theme-switch button.on { background: var(--accent); color: var(--accent-ink); font-weight: 600; }

/* Rings and meters (ring.js): a number as a share of a whole, on a tile or a
   card. The unfilled part is a lighter step of the fill's own colour. */
.ring { display: block; flex: none; }
.ring-track { fill: none; stroke: color-mix(in srgb, var(--accent) 16%, var(--panel)); stroke-width: 4; }
.ring-fill { fill: none; stroke: var(--accent); stroke-width: 4; stroke-linecap: round; }
.ring.full .ring-track { stroke: color-mix(in srgb, var(--ok) 18%, var(--panel)); }
.ring.full .ring-fill { stroke: var(--ok); }
.ring-text { font-family: var(--font-sans); font-size: 9px; font-weight: 700; fill: var(--heading); }
.meter { height: 6px; border-radius: 3px; overflow: hidden; background: color-mix(in srgb, var(--accent) 16%, var(--panel)); }
.meter > span { display: block; height: 100%; border-radius: 3px; background: var(--accent); transform-origin: left; }
.meter.ok { background: color-mix(in srgb, var(--ok) 18%, var(--panel)); }
.meter.ok > span { background: var(--ok); }
.meter.warn { background: color-mix(in srgb, var(--danger) 18%, var(--panel)); }
.meter.warn > span { background: var(--danger); }
main.page-enter .ring-fill { animation: ring-draw 0.9s 0.15s var(--ease-out) backwards; }
main.page-enter .meter > span, main.page-enter .cost-track { animation: meter-grow 0.8s 0.15s var(--ease-out) backwards; }
@keyframes ring-draw { from { stroke-dasharray: 0 100; } }
@keyframes meter-grow { from { transform: scaleX(0); } }
/* On a tile: a meter along its foot with a line saying what it shows, or a
   ring to the right of the number (home.js, communities.js). */
.stat-figure { margin-top: 12px; }
.stat-figure .note { margin-top: 5px; font-size: var(--fs-xs); }
.stat-beside { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.stat-beside > div { min-width: 0; align-self: flex-start; }
.home-stats .stat { display: flex; flex-direction: column; }
.home-stats .stat > .stat-figure, .home-stats .stat > .stat-trend { margin-top: auto; }
.home-stats .stat > .stat-figure { padding-top: 12px; }
.home-stats .stat > .stat-beside { flex: 1; }

/* A community card's ring: how many of its budget's models are approved
   (communities.js approvedRing). */
.cc-body { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.cc-approved { display: flex; flex-direction: column; align-items: center; gap: 1px; flex: none; font-size: var(--fs-xs); color: var(--muted); }

/* The band across the head of a community's own pages (community-band.js
   communityStrip): its card's band, slim. From the Communities list the
   card's band grows into it: both carry the same view-transition-name, and
   ui.js starts the transition for that click. */
.community-strip {
  position: relative; display: flex; align-items: center; gap: 14px; height: 60px; padding: 9px 18px; margin: 0 0 14px;
  border-radius: 10px; overflow: hidden; box-shadow: var(--shadow); view-transition-name: community-band;
}
.community-strip.on-dark { background: var(--sh-blue); }
.community-strip.on-light { background: #fff; border: 1px solid var(--line); }
.community-strip img { max-height: 100%; max-width: min(260px, 60%); object-fit: contain; }
.community-strip .cc-initials { font-size: 1.9rem; }
.community-strip .cc-band-name { position: static; font-size: var(--fs-sm); color: color-mix(in srgb, var(--sh-concrete) 80%, transparent); }
.cs-code {
  margin-left: auto; font-family: var(--font-data); font-size: var(--fs-sm); font-weight: 600; padding: 2px 8px; border-radius: 4px;
  color: var(--sh-concrete); background: rgb(255 255 255 / 0.1); border: 1px solid rgb(255 255 255 / 0.2);
}
/* A light logo band stays white in either theme, so its code does too. */
.community-strip.on-light .cs-code { color: #00305a; background: #f1f3f5; border-color: #dadee2; }
a.community-strip-link { display: block; text-decoration: none; border-radius: 10px; margin: 0 0 14px; }
a.community-strip-link .community-strip { margin: 0; transition: box-shadow 0.2s; }
a.community-strip-link:hover .community-strip { box-shadow: var(--shadow-lift); }
.morph-from { view-transition-name: community-band; }
main.page-enter > .no-enter { animation: none; }
::view-transition-group(community-band) { animation-duration: 0.42s; animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1); }
/* Each picture fills the moving box and is cut to it, so the tall card band
   and the wide page band cross over without either being squashed. */
::view-transition-old(community-band), ::view-transition-new(community-band) { width: 100%; height: 100%; object-fit: cover; overflow: clip; }
::view-transition-group(community-band) { border-radius: 10px; overflow: clip; }

/* Gross margin against the target (budget.js marginTone; Settings › Target
   gross margin): a tint behind the number, and a ▼ on the ones below, so it
   doesn't rest on the colour. The tint is an inset shadow: the row's hover
   and the picked column set the cell's background. */
td.margin-ok { box-shadow: inset 0 0 0 100px color-mix(in srgb, var(--ok) 14%, transparent); }
td.margin-low { box-shadow: inset 0 0 0 100px color-mix(in srgb, var(--danger) 15%, transparent); }
td.margin-low::before { content: "▼ "; font-size: 0.7em; color: var(--danger); }
:root[data-theme="dark"] td.margin-ok { box-shadow: inset 0 0 0 100px color-mix(in srgb, var(--ok) 20%, transparent); }
:root[data-theme="dark"] td.margin-low { box-shadow: inset 0 0 0 100px color-mix(in srgb, var(--danger) 24%, transparent); }
.margin-key { margin: 0 0 8px; }
.margin-chip { display: inline-block; padding: 1px 8px; border-radius: 3px; font-weight: 600; color: var(--ink); }
.margin-chip.ok { background: color-mix(in srgb, var(--ok) 16%, transparent); }
.margin-chip.low { background: color-mix(in srgb, var(--danger) 16%, transparent); }
.stat.margin-ok::before { background: var(--ok); }
.stat.margin-low::before { background: var(--sh-terracotta); }
.stat.margin-low .value { color: var(--danger); }

/* The rollup's cell under the pointer lights its column too (budget.js
   crosshair); the row is already lit by its hover. */
table.sheet td.col-hover { background: color-mix(in srgb, var(--accent) 7%, var(--panel)); }
table.sheet tbody tr:hover td.col-hover { background: color-mix(in srgb, var(--accent) 18%, var(--panel)); }
table.sheet thead th.col-hover { box-shadow: inset 0 -2px 0 var(--sh-gold); }

/* Where the cost goes (cost-bar.js): one bar split by header major code, with a key that
   holds every figure. A fixed order of colours, chosen to stay apart for
   colour-blind readers on the light and the dark panel; Other is grey. */
.cost-bar {
  --s1: #2a78d6; --s2: #eb6834; --s3: #1baf7a; --s4: #eda100; --s5: #e87ba4; --s-other: #848b93;
  margin-bottom: 20px;
}
:root[data-theme="dark"] .cost-bar { --s1: #3987e5; --s2: #d95926; --s3: #199e70; --s4: #c98500; --s5: #d55181; --s-other: #7f8c99; }
.cost-slot:empty { display: none; }
.cost-head { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 4px 16px; margin-bottom: 12px; }
.cost-head h2 { margin: 0; }
.cost-track { display: flex; gap: 2px; height: 18px; transform-origin: left; }
.cost-seg { flex-basis: 0; min-width: 3px; background: var(--seg); transition: opacity 0.15s; }
.cost-seg:first-child { border-radius: 4px 0 0 4px; }
.cost-seg:last-child { border-radius: 0 4px 4px 0; }
.cost-seg:only-child { border-radius: 4px; }
.cost-track:has(.on) .cost-seg:not(.on) { opacity: 0.4; }
.cost-seg.s1, .cost-swatch.s1 { --seg: var(--s1); }
.cost-seg.s2, .cost-swatch.s2 { --seg: var(--s2); }
.cost-seg.s3, .cost-swatch.s3 { --seg: var(--s3); }
.cost-seg.s4, .cost-swatch.s4 { --seg: var(--s4); }
.cost-seg.s5, .cost-swatch.s5 { --seg: var(--s5); }
.cost-seg.other, .cost-swatch.other { --seg: var(--s-other); }
.cost-key { list-style: none; margin: 10px 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); gap: 0 24px; font-size: var(--fs-md); }
.cost-key li { display: grid; grid-template-columns: 10px minmax(0, 1fr) auto 3.4em; align-items: center; gap: 8px; padding: 4px 6px; border-radius: 4px; }
.cost-key li.on { background: var(--accent-soft); }
.cost-swatch { width: 10px; height: 10px; border-radius: 2px; background: var(--seg); }
.cost-craft { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cost-amount, .cost-share { text-align: right; font-variant-numeric: tabular-nums; }

/* An approved elevation carries a stamp beside its approval (budget-approval.js
   stamp); it presses on once, when the approval is made. */
.notice.approved { display: flex; align-items: center; justify-content: space-between; gap: 12px 20px; flex-wrap: wrap; }
.approval-stamp {
  flex: none; display: flex; flex-direction: column; align-items: center; gap: 1px; margin: 5px 12px 5px 4px; padding: 6px 14px 5px;
  color: var(--ok); border: 2px solid currentColor; border-radius: 6px; outline: 1px solid currentColor; outline-offset: 2px;
  transform: rotate(-5deg); opacity: 0.92;
}
.stamp-word { display: flex; align-items: center; gap: 6px; font-size: var(--fs-md); font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; }
.stamp-date { font-size: var(--fs-xs); font-weight: 600; letter-spacing: 0.06em; }
.approval-stamp.fresh { animation: stamp-press 0.55s cubic-bezier(0.2, 1.4, 0.4, 1) backwards; }
@keyframes stamp-press {
  0% { opacity: 0; transform: rotate(-14deg) scale(2.3); }
  55% { opacity: 0.92; transform: rotate(-5deg) scale(0.93); }
  100% { opacity: 0.92; transform: rotate(-5deg) scale(1); }
}

@media (max-width: 640px) {
  .community-strip { height: 52px; padding: 8px 12px; }
  .community-strip .cc-initials { font-size: 1.5rem; }
  .community-strip .cc-band-name { display: none; }
  .cost-key { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  main.page-enter .ring-fill, main.page-enter .meter > span, main.page-enter .cost-track, .approval-stamp.fresh { animation: none; }
}

/* community-settings.js: the gear by a community's name, its dialog and the bulk page */
.title-row { gap: 6px; flex-wrap: nowrap; min-width: 0; }
.title-row h1 { margin-bottom: 0; }
button.title-gear { flex: none; display: inline-flex; padding: 6px; border: 0; border-radius: 6px; background: none; box-shadow: none; color: var(--muted); cursor: pointer; }
button.title-gear:hover { color: var(--accent); background: var(--accent-soft); }
dialog.settings-dialog { width: min(760px, calc(100vw - 32px)); }
dialog.settings-dialog form > .muted { margin: 0 0 12px; }
dialog.settings-dialog label { display: flex; margin: 0; }
dialog.settings-dialog form > label { margin-top: 12px; }
dialog.settings-dialog label.check { margin-top: 8px; }
dialog.settings-dialog .grid input, dialog.settings-dialog .grid select, dialog.settings-dialog textarea { width: 100%; }
.bulk-fill { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px 16px; }
.bulk-fill input.num-input { width: 9em; text-align: left; }
input.changed, select.changed { border-color: var(--accent); background: var(--accent-soft); }

/* A panel that folds (Differences from corporate, communities.js) */
details.panel.fold > summary { display: flex; align-items: center; justify-content: space-between; gap: 12px; list-style: none; }
details.panel.fold > summary::-webkit-details-marker { display: none; }
details.panel.fold > summary h2 { margin: 0; }
details.panel.fold[open] > summary { margin-bottom: 12px; }
.fold-hint { display: inline-flex; align-items: center; gap: 4px; color: var(--accent); font-size: var(--fs-sm); font-weight: 600; }
.fold-hint svg { transform: rotate(90deg); transition: transform 0.15s; }
details[open] > summary .fold-hint svg { transform: rotate(-90deg); }
details[open] > summary .when-shut, details:not([open]) > summary .when-open { display: none; }
@media (prefers-reduced-motion: reduce) { .fold-hint svg { transition: none; } }

/* Takeoff Methodology › Resources (resources.js) and the Formulas tab's
   Resource column. Everything in .hb-table is read from HBLive. */
.hb-table td { color: var(--ok); }
.hb-table td .badge { color: var(--muted); }
input.hb-text { color: var(--ok); }
td.resource-cell { min-width: 190px; }
.resource-pick { display: flex; gap: 4px; align-items: center; }
.resource-pick .code-input { width: 120px; }
.icon-button { display: inline-flex; align-items: center; justify-content: center; padding: 4px 6px; }
td.resource-cell .formula-input { display: block; width: 100%; margin-top: 4px; font-family: var(--font-data); font-size: 12px; }
td.resource-cell code.formula { display: block; margin-top: 2px; }
.formula-input-actions { display: flex; gap: 4px; margin-top: 4px; }
.formula-input-actions[hidden] { display: none; }
/* A line with several resources: "Multiple" folds open into a row per
   resource under the line (methodology.js resourceRows). */
button.resource-fold { display: inline-flex; align-items: center; gap: 4px; border: 0; background: none; padding: 2px 0; font: inherit; color: var(--ink); cursor: pointer; }
button.resource-fold:hover { color: var(--accent); background: none; }
button.resource-fold .caret { width: 1em; color: var(--muted); }
td.resource-cell .add-resource { display: block; margin-top: 4px; }
.takeoff-formulas tr.resource-row td { background: color-mix(in srgb, var(--accent) 4%, transparent); border-top: 1px dotted var(--line); }
.takeoff-formulas tr.resource-row td.resource-of { padding-left: 22px; font-size: 13px; }
dialog.resource-dialog { width: min(760px, calc(100vw - 32px)); }
.resource-dialog input[type="search"] { width: 100%; }
.resource-list { max-height: min(55vh, 520px); overflow-y: auto; border: 1px solid var(--line); border-radius: 6px; }
.resource-option { display: grid; grid-template-columns: auto minmax(90px, auto) 1fr auto auto; gap: 8px; align-items: center; width: 100%;
  text-align: left; background: none; border: 0; border-bottom: 1px solid var(--line); border-radius: 0; padding: 6px 10px; color: var(--ink); cursor: pointer; }
.resource-option:hover:not([disabled]), .resource-option:focus-visible { background: var(--panel-2); }
.resource-option[disabled] { opacity: 0.55; cursor: not-allowed; }
.resource-option .code { color: var(--ok); }
@media (max-width: 640px) { .resource-option { grid-template-columns: auto 1fr; } }

/* Change history (change-history.js): a project's changes in plain words.
   Each entry opens to its changes, their fields and the stored record. */
.change-history td.hist-day:not(.repeat), .change-history td.hist-time { color: var(--muted); }
.change-history td.hist-what { width: 60%; white-space: normal; }
.hist-area {
  display: inline-block; white-space: nowrap; padding: 1px 8px; border-radius: 999px;
  font-size: var(--fs-xs); font-weight: 600; color: var(--accent); background: var(--icon-soft);
}
details.hist-entry { margin: 0; }
details.hist-entry > summary { display: flex; align-items: baseline; gap: 8px; list-style: none; }
details.hist-entry > summary::-webkit-details-marker { display: none; }
details.hist-entry > summary:hover > span:first-of-type { color: var(--accent); }
.hist-count { flex: none; white-space: nowrap; font-size: var(--fs-xs); color: var(--muted); }
.hist-body { margin: 6px 0 6px 18px; }
dl.hist-fields { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 2px 14px; margin: 0 0 6px; font-size: var(--fs-sm); }
dl.hist-fields dt { color: var(--muted); }
dl.hist-fields dd { margin: 0; overflow-wrap: anywhere; }
.hist-was { color: var(--muted); }
ol.hist-changes { list-style: none; margin: 0; padding: 0; border-left: 2px solid var(--line); }
ol.hist-changes > li { padding: 3px 0 3px 10px; font-size: var(--fs-sm); }
.hist-stored pre.diff { max-height: 260px; overflow: auto; margin: 2px 0 6px; padding: 6px 8px; border: 1px solid var(--line); border-radius: 4px; background: var(--panel-2); }
.change-history .table-tools label.check { margin: 0; }
.change-history .table-tools label.check[hidden] { display: none; }
/* On a phone each entry is a card: what happened first, then when, who and where on one line. */
@media (max-width: 640px) {
  .change-history table.cards tbody tr { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; }
  .change-history table.cards td { display: block; padding: 0; border: 0; text-align: left; font-size: var(--fs-sm); }
  .change-history table.cards td::before { content: none; }
  .change-history table.cards td.hist-what { order: -1; flex: 0 0 100%; width: auto; padding-bottom: 4px; font-size: inherit; }
  .change-history table.cards td.hist-day.repeat { color: var(--muted); }
  dl.hist-fields { grid-template-columns: minmax(0, 1fr); gap: 0; }
  dl.hist-fields dd { margin-bottom: 4px; }
}

/* Badges (badges.js): a medal for each, the profile page's and Home's
   panels, and the card that says a new one has been earned. An earned medal
   is SH Gold on SH Blue in either theme; the rest are an outline. */
.medal {
  display: inline-grid; place-items: center; flex: none; width: 40px; height: 40px; border-radius: 50%;
  color: var(--muted); background: var(--panel-2); border: 2px dashed var(--line-strong);
}
.medal .icon { width: 52%; height: 52%; }
.medal.small { width: 28px; height: 28px; }
.medal.large { width: 52px; height: 52px; }
.medal.earned {
  color: var(--sh-gold); background: var(--sh-blue); border: 2px solid var(--sh-gold);
  box-shadow: inset 0 0 0 2px var(--sh-blue), inset 0 0 0 3px color-mix(in srgb, var(--sh-gold) 55%, transparent);
}
.medal.fresh { animation: medal-pop 0.6s 0.15s cubic-bezier(0.2, 1.4, 0.4, 1) backwards; }
@keyframes medal-pop { from { opacity: 0; transform: scale(0.4) rotate(-20deg); } }
.medal-count { margin-left: auto; font-size: var(--fs-sm); font-weight: 600; color: var(--muted); }
ul.medal-grid { list-style: none; margin: 14px 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; }
.medal-item { display: flex; gap: 12px; align-items: flex-start; padding: 12px; border: 1px solid var(--line); border-radius: 8px; }
.medal-item.earned { border-color: color-mix(in srgb, var(--sh-gold) 55%, var(--line)); background: color-mix(in srgb, var(--sh-gold) 6%, var(--panel)); }
.medal-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.medal-text .muted { font-size: var(--fs-sm); line-height: 1.4; }
.medal-when { display: inline-flex; align-items: center; gap: 5px; margin-top: 3px; font-size: var(--fs-xs); font-weight: 600; color: var(--muted); }
.medal-item.earned .medal-when { color: var(--ok); }
.medal-new {
  margin-left: 8px; padding: 1px 7px; border-radius: 999px; vertical-align: 1px;
  font-size: var(--fs-xs); font-weight: 700; color: var(--sh-dark-gravel); background: var(--sh-gold);
}
/* Home: how many, the latest few, the next one to go for. */
.home-badges .meter { margin-bottom: 14px; }
ul.medal-row { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.medal-more { font-size: var(--fs-sm); font-weight: 600; }
.medal-next { margin: 0 0 12px; line-height: 1.45; }
/* The card: at the corner of the page, under the pop-ups, until it's closed. */
.medal-card {
  position: fixed; right: 20px; bottom: 20px; z-index: 49; display: flex; gap: 14px; align-items: flex-start;
  width: min(400px, calc(100vw - 32px)); padding: 14px 16px; border-radius: 10px;
  background: var(--panel); border: 1px solid var(--line-strong); border-top: 3px solid var(--sh-gold);
  box-shadow: 0 14px 40px -10px rgb(0 0 0 / 0.4); animation: medal-card-in 0.35s var(--ease-out);
}
.medal-card-medals { display: flex; flex: none; }
.medal-card-medals .medal + .medal { margin-left: -20px; }
.medal-card .medal-text { flex: 1; }
.medal-card .eyebrow { margin: 0; font-weight: 700; color: var(--read); }
.medal-card a { margin-top: 4px; font-size: var(--fs-sm); font-weight: 600; }
button.medal-card-close { flex: none; display: inline-flex; margin: -6px -8px 0 0; padding: 4px; border: 0; background: none; box-shadow: none; color: var(--muted); }
button.medal-card-close:hover { color: var(--ink); }
.medal-card.leaving { animation: medal-card-out 0.2s ease-in forwards; pointer-events: none; }
@keyframes medal-card-in { from { opacity: 0; transform: translateY(16px); } }
@keyframes medal-card-out { to { opacity: 0; transform: translateY(10px); } }
@media (max-width: 640px) { .medal-card { left: 16px; right: 16px; bottom: 16px; width: auto; } }
@media (prefers-reduced-motion: reduce) { .medal-card, .medal-card.leaving, .medal.fresh { animation: none; } }

/* Takeoff Methodology, Formulas tab: Download for Excel and Upload from
   Excel, and the upload's list of changes (methodology-excel.js). */
.excel-tools { display: inline-flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }
dialog.src-dialog.excel-upload { width: min(1080px, calc(100vw - 32px)); }
.excel-upload .excel-lists { max-height: 50vh; overflow: auto; margin: 10px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.excel-upload .excel-lists h4 { margin: 12px 0 6px; }
.excel-upload .excel-lists td.wrap { min-width: 200px; }
.excel-upload .excel-lists td.desc .key { font-family: var(--font-data); margin-top: 2px; }
.excel-upload .excel-publish { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; justify-content: flex-end; }
.excel-upload .excel-publish input.reason { flex: 1 1 260px; min-width: 0; }
dialog.src-dialog.excel-upload .excel-publish label.check { display: inline-flex; align-items: center; gap: 6px; margin: 0; }

/* Takeoff Methodology, Formulas tab: the bulk action tick boxes, the UofM
   typed in where a line has no resource, and the Budget Source pick. */
.takeoff-formulas td.line-pick, .takeoff-formulas th.line-pick { width: 1%; text-align: center; padding-left: 6px; padding-right: 6px; }
.takeoff-formulas .line-pick input[type=checkbox] { width: 16px; height: 16px; padding: 0; margin: 0; vertical-align: middle; accent-color: var(--accent); }
.takeoff-formulas .uofm-input { width: 6em; }
.takeoff-formulas td.budget-source select { min-width: 7em; }
select.line-bulk { width: auto; max-width: 22em; }
input.field-input { width: 100%; min-width: 16em; }

/* ---- Formulas tab: craft types, resource rows' quantities (methodology.js, methodology-resources.js) ---- */
.takeoff-formulas tr.group td.line-pick { padding: 0 6px; }
.takeoff-formulas tr.group.with-cells td.line-pick + td { padding: 0; font-weight: normal; }
.takeoff-formulas td.type-cell { white-space: nowrap; }
.takeoff-formulas td.type-cell .badge { display: inline-block; margin-top: 2px; }
.takeoff-formulas td.craft-type select { min-width: 8em; font-weight: normal; }
.takeoff-formulas .craft-type-project { margin-top: 4px; font-weight: normal; }
.takeoff-formulas .formula-box .formula-input { display: block; width: 100%; font-family: var(--font-data); font-size: 12px; }
.takeoff-formulas .qty-input { width: 8em; text-align: right; }
.takeoff-formulas .legacy-qty { margin-top: 4px; font-family: var(--font-data); }
.takeoff-formulas .legacy-qty.unused { text-decoration: line-through; }

/* ---- A line's page: Line Details' Save (methodology-line.js) ---- */
.line-details-save { align-items: center; gap: 8px; }
.line-details-save [hidden] { display: none; }
input.changed, select.changed { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--panel)); }
input.invalid { border-color: var(--danger, #c0392b); }
.takeoff-formulas tr.group td { vertical-align: middle; }
.takeoff-formulas tr.group.with-cells td.craft-type { padding-top: 3px; padding-bottom: 3px; }
.takeoff-formulas td.craft-type select { padding: 2px 6px; font-size: var(--fs-sm); min-height: 0; height: auto; }

/* The Lines table's Resource column: Multiple opens each resource (budget.js). */
td.resources-cell details > summary { cursor: pointer; font-weight: 600; }
table.sheet.resource-breakdown { margin: 6px 0 2px; font-size: var(--fs-xs); background: var(--panel-2); }
table.sheet.resource-breakdown thead th { position: static; }

/* Change approval: a tick box per changed line, and the bulk bar above. */
.approval-bulk { margin: 8px 0; }
