/* Every colour, font and button style is a custom property from /theme.css, generated
   from theme.toml at the repo root (nemo.theme) -- light and dark -- with Settings > Theme
   over it. Change them there. */

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--font-weight) var(--font-size)/1.45 var(--font-body);
  overflow: hidden;
}
button, input, select, textarea { font: inherit; color: inherit; }
/* Headings take the heading font. The small uppercase section labels keep their muted colour:
   their own rules are more specific. */
h1, h2, h3, .brand { font-family: var(--font-heading); font-weight: var(--heading-weight); color: var(--heading); }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
[hidden] { display: none !important; }
.muted { color: var(--muted); }

/* --- layout ------------------------------------------------------------ */

.shell { display: grid; grid-template-columns: 236px minmax(0, 1fr); height: 100vh; }

.sidebar {
  display: flex; flex-direction: column;
  background: var(--surface);
  border-right: 1px solid var(--border);
  min-height: 0;
}
.brand { display: flex; align-items: center; gap: 10px; padding: 16px 16px 10px; font-weight: 700; font-size: 16px; }
.brand-mark { width: 22px; height: 22px; border-radius: 6px; background: var(--accent); display: inline-block; }
#nav { flex: 1; overflow-y: auto; padding: 4px 8px 12px; display: flex; flex-direction: column; }
.nav-group { margin-top: 14px; }
/* Settings: at the foot of the rail, below the places the data is. */
#nav > .nav-end { margin-top: auto; }
.nav-group h2 {
  margin: 0 8px 4px; font-size: 11.5px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted);
}
.nav-item {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; padding: 7px 10px; border: 0; border-radius: 6px;
  background: transparent; text-align: left; cursor: pointer;
}
.nav-item:hover { background: var(--hover); }
.nav-item[aria-current="page"] { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.nav-item .count { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.sidebar-foot { border-top: 1px solid var(--border); padding: 12px 14px 14px; display: grid; gap: 8px; }
.foot-row { display: flex; align-items: center; gap: 8px; }
.foot-row #sync-button { flex: 1; }
.theme-toggle {
  display: grid; place-items: center; width: 24px; height: 24px; flex: none; padding: 0;
  border: 1px solid var(--border); border-radius: 50%; background: transparent; color: var(--muted);
  cursor: pointer; opacity: .6;
}
.theme-toggle:hover, .theme-toggle:focus-visible { opacity: 1; color: var(--text); }
.theme-toggle .icon-sun, .theme-toggle[aria-pressed="true"] .icon-moon { display: none; }
.theme-toggle[aria-pressed="true"] .icon-sun { display: block; }
.sync-status { font-size: 12.5px; color: var(--muted); display: flex; align-items: center; gap: 6px; min-height: 18px; }
.sync-status .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex: none; }
.sync-status.ok .dot { background: var(--ok); }
.sync-status.failed { color: var(--danger); }
.sync-status.failed .dot { background: var(--danger); }
.sync-status.running .dot { background: var(--accent); animation: pulse 1s ease-in-out infinite; }
@keyframes pulse { 50% { opacity: .3; } }

/* Who is signed in (web/auth.py), and Sign out. */
.user-chip { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 12.5px; }
.user-chip .who { flex: 1; min-width: 0; display: grid; }
.user-chip .who span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-chip .name { font-weight: 600; }
.user-chip .role { color: var(--muted); }
.user-chip .off { color: var(--warn); font-weight: 600; }
.avatar {
  display: grid; place-items: center; flex: none; width: 28px; height: 28px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent); font-size: 11.5px; font-weight: 700; cursor: default;
}

/* The tray (app.js setNavOpen): a rail of icons, each named by its tooltip, until expanded;
   then it lies over the page without resizing it. The labels stay for screen readers. On a
   narrow screen the whole tray slides in instead (see "narrow screens"). */
.brand-name { flex: 1; }
.nav-expand { padding: 6px; }
body.nav-open .nav-expand .icon { transform: scaleX(-1); }
.nav-item { justify-content: flex-start; gap: 10px; }
.nav-item .label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#sync-button { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
#sync-button .icon { width: 15px; height: 15px; }
@media (min-width: 761px) {
  .shell { grid-template-columns: 56px minmax(0, 1fr); }
  /* Wider than its column when expanded: it overflows over the page. The z-index drops only
     once it has shrunk back, so the page does not cover it as it closes. */
  .sidebar {
    position: relative; width: 56px; overflow: hidden; white-space: nowrap;
    transition: width .15s ease, box-shadow .15s ease, z-index 0s .15s;
  }
  body.nav-open .sidebar {
    width: 236px; z-index: 45; box-shadow: var(--shadow);
    transition: width .15s ease, box-shadow .15s ease;
  }
  body:not(.nav-open) .sidebar .label {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%);
  }
  body:not(.nav-open) .brand-name,
  body:not(.nav-open) .nav-group h2,
  body:not(.nav-open) .nav-item .count,
  body:not(.nav-open) .user-chip .who,
  body:not(.nav-open) .user-chip .sign-out { display: none; }
  body:not(.nav-open) .brand { flex-direction: column; gap: 10px; padding: 14px 0 6px; }
  body:not(.nav-open) #nav { padding: 0 8px 12px; scrollbar-width: none; }
  body:not(.nav-open) .nav-group { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--border); }
  body:not(.nav-open) .nav-group:first-child { margin-top: 4px; padding-top: 0; border-top: 0; }
  body:not(.nav-open) .nav-item { position: relative; justify-content: center; padding: 10px 0; }
  body:not(.nav-open) .nav-item .badge {
    position: absolute; top: 2px; right: 2px; min-width: 16px; height: 16px; padding: 0 4px; font-size: 10px;
  }
  body:not(.nav-open) .sidebar-foot { padding: 10px 0 12px; justify-items: center; }
  body:not(.nav-open) .foot-row { flex-direction: column; }
  body:not(.nav-open) #sync-button { padding: 7px; }
}
@media (min-width: 761px) and (prefers-reduced-motion: reduce) {
  .sidebar, body.nav-open .sidebar { transition: none; }
}

/* Controls a role may not use are hidden; the server refuses them either way (web/auth.py).
   Until /api/me answers, body has no role and nothing is hidden. */
body[data-role="Viewer"] .needs-editor,
body[data-role="Viewer"] .needs-admin,
body[data-role="Editor"] .needs-admin { display: none !important; }

.main { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.toolbar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 16px; border-bottom: 1px solid var(--border); background: var(--surface);
}
/* Never squeezed away: past this the actions wrap below. */
.title-block { display: flex; align-items: baseline; gap: 10px; min-width: min(260px, 100%); flex: 1; }
.title-block h1 { font-size: 19px; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.toolbar-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.search {
  width: 240px; max-width: 100%; padding: 7px 10px;
  border: 1px solid var(--border); border-radius: 6px; background: var(--bg);
}
.grid { flex: 1; min-height: 0; }
.nav-toggle { display: none; }

/* --- controls ---------------------------------------------------------- */

/* Buttons by type (theme.toml's button.default / primary / outline / danger / quiet). */
.btn {
  padding: 7px 12px; border-radius: var(--btn-radius); cursor: pointer; white-space: nowrap;
  border: var(--btn-default-border-width) solid var(--btn-default-border);
  background: var(--btn-default-bg); color: var(--btn-default-text);
}
.btn:hover { background: var(--btn-default-bg-hover); }
.btn:disabled { opacity: .55; cursor: default; }
/* A link that looks like a button (Download, Open in Comms). */
a.btn { display: inline-block; text-decoration: none; }
.btn-primary {
  border: var(--btn-primary-border-width) solid var(--btn-primary-border);
  background: var(--btn-primary-bg); color: var(--btn-primary-text); font-weight: 600;
}
.btn-primary:hover { background: var(--btn-primary-bg-hover); }
.btn-danger {
  border: var(--btn-danger-border-width) solid var(--btn-danger-border);
  background: var(--btn-danger-bg); color: var(--btn-danger-text);
}
.btn-danger:hover { background: var(--btn-danger-bg-hover); }
.btn-quiet {
  border: var(--btn-quiet-border-width) solid var(--btn-quiet-border);
  background: var(--btn-quiet-bg); color: var(--btn-quiet-text);
}
.btn-quiet:hover { background: var(--btn-quiet-bg-hover); }
.btn-outline {
  border: var(--btn-outline-border-width) solid var(--btn-outline-border);
  background: var(--btn-outline-bg); color: var(--btn-outline-text); font-weight: 600;
}
.btn-outline:hover { background: var(--btn-outline-bg-hover); }
.btn-small { padding: 3px 8px; font-size: 12.5px; }

.menu-wrap { position: relative; }
.menu {
  position: absolute; right: 0; top: calc(100% + 4px); z-index: 30;
  width: 260px; max-height: 60vh; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 6px;
}
.menu label { display: flex; align-items: center; gap: 8px; padding: 5px 8px; border-radius: 5px; cursor: pointer; }
.menu label:hover { background: var(--hover); }
.menu hr { border: 0; border-top: 1px solid var(--border); margin: 6px 0; }
.menu .btn { width: 100%; }
.menu-note { margin: 2px 8px 6px; font-size: 12px; }

/* --- grid cells -------------------------------------------------------- */

.chips { display: inline-flex; gap: 4px; flex-wrap: nowrap; }
.chip {
  display: inline-block; padding: 0 7px; border-radius: 10px; line-height: 20px;
  background: var(--accent-soft); color: var(--accent); font-size: 12px; white-space: nowrap;
}
.cell-link { color: var(--accent); text-decoration: none; }
.cell-link:hover { text-decoration: underline; }
.open-btn {
  border: 0; background: transparent; cursor: pointer; color: var(--muted);
  padding: 0 4px; font-size: 15px; line-height: 1;
}
.open-btn:hover { color: var(--accent); }
.clip { color: var(--muted); font-size: 12px; margin-left: 4px; }
.computed { color: var(--muted); font-style: italic; }

/* --- the choice filter ------------------------------------------------- */

/* The column filter (filters.js): conditions, a value list, the grouping switches. */
.column-filter {
  display: flex; flex-direction: column; gap: 8px; padding: 10px;
  width: 300px; max-width: calc(100vw - 32px); font-size: 13px;
}
.column-filter .empty { font-style: italic; color: var(--muted); padding: 4px; }
.column-filter select, .column-filter input[type="text"], .column-filter input[type="number"],
.column-filter input[type="date"], .column-filter input[type="search"] {
  width: 100%; min-width: 0; padding: 5px 8px;
  border: 1px solid var(--border); border-radius: 6px; background: var(--bg);
}
.cf-conditions { display: flex; flex-direction: column; gap: 6px; padding-bottom: 8px; border-bottom: 1px solid var(--border); }
.cf-row { display: flex; flex-direction: column; gap: 4px; }
.cf-inputs { display: flex; gap: 4px; }
.cf-inputs input[hidden], .cf-row[hidden], .cf-join[hidden] { display: none; }
.cf-join { display: flex; gap: 14px; }
.cf-join label { display: flex; align-items: center; gap: 4px; cursor: pointer; }
.cf-values { display: flex; flex-direction: column; gap: 6px; }
.cf-values-head { display: flex; flex-direction: column; gap: 6px; }
.cf-check { display: flex; align-items: center; gap: 6px; cursor: pointer; color: var(--muted); }
.cf-list {
  max-height: 260px; overflow-y: auto; border: 1px solid var(--border); border-radius: 6px; padding: 4px;
}
.cf-value {
  display: flex; align-items: center; gap: 8px; padding: 3px 4px; border-radius: 4px; cursor: pointer;
  padding-left: calc(4px + var(--depth, 0) * 18px);
}
.cf-value:hover { background: var(--hover); }
.cf-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cf-count { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.cf-all { border-bottom: 1px solid var(--border); border-radius: 4px 4px 0 0; margin-bottom: 2px; }
.cf-group-head { display: flex; align-items: center; padding-left: calc(var(--depth, 0) * 18px); }
.cf-group-head .cf-value { flex: 1; min-width: 0; padding-left: 4px; font-weight: 600; }
.cf-twisty {
  display: flex; align-items: center; justify-content: center;
  width: 20px; height: 22px; flex: none; border: 0; background: transparent; cursor: pointer;
  color: var(--muted); padding: 0;
}
.cf-twisty:hover { color: var(--accent); }
/* An open/closed chevron: points right when closed, down when open. */
.twisty {
  display: inline-block; width: 6px; height: 6px; flex: none;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg); transition: transform .12s;
}
[aria-expanded="true"] > .twisty { transform: rotate(45deg) translate(-1px, -1px); }
.cf-note { font-size: 12px; }
.cf-footer { display: flex; align-items: center; gap: 8px; padding-top: 8px; border-top: 1px solid var(--border); }
.cf-footer .spacer { flex: 1; }

/* A group's heading row in a grouped grid (grid.js). */
.group-row {
  display: flex; align-items: center; gap: 8px; width: 100%; height: 100%;
  padding: 0 12px; border: 0; border-bottom: 1px solid var(--border);
  background: var(--surface-2); color: var(--text); cursor: pointer; text-align: left;
}
.group-row:hover { background: var(--hover); }
.group-row:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.group-row .twisty { color: var(--muted); margin: 0 4px 0 2px; }
.group-column { color: var(--muted); }
.group-label { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.group-count {
  padding: 0 8px; border-radius: 10px; line-height: 20px; font-size: 12px;
  background: var(--accent-soft); color: var(--accent); font-variant-numeric: tabular-nums;
}
.group-edge { margin-left: 4px; color: var(--muted); font-size: 12.5px; white-space: nowrap; }

/* --- drawer ------------------------------------------------------------ */

.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 40;
  width: var(--drawer-width, 560px); max-width: 100vw; display: flex; flex-direction: column;
  background: var(--surface); border-left: 1px solid var(--border); box-shadow: var(--shadow);
}
/* A pane's edge: drag (or arrow keys) to resize it (util.resizable). */
.resize-handle {
  position: absolute; top: 0; bottom: 0; width: 8px; z-index: 1;
  cursor: col-resize; touch-action: none;
}
.resize-handle::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: 3px; width: 2px;
  background: transparent; transition: background .12s;
}
.resize-handle:hover::after, .resize-handle:focus-visible::after, .resize-handle.dragging::after {
  background: var(--accent);
}
.resize-handle:focus-visible { outline: none; }
.drawer-resize { left: -4px; }
/* An iframe (the PDF preview) would take the pointer away mid-drag. */
.drawer.resizing iframe { pointer-events: none; }
body.resizing { user-select: none; cursor: col-resize; }
.scrim { position: fixed; inset: 0; z-index: 35; background: rgb(0 0 0 / 0.18); }
.drawer-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 14px 16px; border-bottom: 1px solid var(--border); }
.drawer-head h2 { margin: 0; font-size: 17px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drawer-head-actions { display: flex; align-items: center; gap: 4px; flex: none; }
.drawer-body { flex: 1; overflow-y: auto; padding: 14px 16px 24px; }
.drawer-foot { display: flex; gap: 8px; justify-content: flex-end; padding: 12px 16px; border-top: 1px solid var(--border); flex-wrap: wrap; }
.drawer-foot .spacer { flex: 1; }

.field { display: grid; gap: 4px; margin-bottom: 14px; }
.field > label, .field > .label { font-weight: 600; font-size: 13px; }
.field .req { color: var(--danger); margin-left: 2px; }
.field .hint { font-size: 12px; color: var(--muted); }
.field input[type="text"], .field input[type="number"], .field input[type="date"],
.field input[type="url"], .field input[type="search"], .field select, .field textarea {
  width: 100%; padding: 7px 9px; border: 1px solid var(--border); border-radius: 6px;
  background: var(--bg);
}
.field textarea { min-height: 96px; resize: vertical; }
.field.invalid input, .field.invalid select, .field.invalid textarea { border-color: var(--danger); }
.field .error { color: var(--danger); font-size: 12.5px; }
.checks { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.checks label { display: inline-flex; gap: 6px; align-items: center; font-weight: 400; }
.url-pair { display: grid; gap: 6px; }

.combo { position: relative; }
.combo-list {
  position: absolute; left: 0; right: 0; top: calc(100% + 2px); z-index: 50;
  max-height: 240px; overflow-y: auto; margin: 0; padding: 4px; list-style: none;
  background: var(--surface); border: 1px solid var(--border); border-radius: 6px; box-shadow: var(--shadow);
}
.combo-list li { padding: 6px 8px; border-radius: 4px; cursor: pointer; }
.combo-list li[aria-selected="true"], .combo-list li:hover { background: var(--hover); }

.section { margin-top: 22px; }
.section h3 { font-size: 13px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); margin: 0 0 8px; }
.facts { display: grid; grid-template-columns: max-content 1fr; gap: 4px 14px; margin: 0; font-size: 13px; }
.facts dt { color: var(--muted); }
.facts dd { margin: 0; overflow-wrap: anywhere; }
.files { list-style: none; margin: 0 0 8px; padding: 0; display: grid; gap: 4px; }
.files li { display: flex; align-items: center; gap: 8px; justify-content: space-between; padding: 6px 8px; background: var(--surface-2); border-radius: 6px; }
.files li a { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.preview { width: 100%; height: 340px; border: 1px solid var(--border); border-radius: 6px; background: var(--surface-2); }
img.preview { height: auto; max-height: 340px; object-fit: contain; }
.dropzone {
  border: 1.5px dashed var(--border); border-radius: var(--radius); padding: 18px; text-align: center;
  color: var(--muted); cursor: pointer;
}
.dropzone.over { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.banner { padding: 10px 12px; border-radius: 6px; margin-bottom: 14px; font-size: 13px; }
.banner.error { background: var(--danger-soft); color: var(--danger); }

/* --- toasts ------------------------------------------------------------ */

.toasts { position: fixed; right: 16px; bottom: 16px; z-index: 60; display: grid; gap: 8px; max-width: min(420px, calc(100vw - 32px)); }
.toast {
  padding: 10px 14px; border-radius: var(--radius); background: var(--text); color: var(--bg);
  box-shadow: var(--shadow); font-size: 13.5px;
}
.toast.error { background: var(--danger); color: #fff; }

/* --- saved views ------------------------------------------------------- */

.title-block .view-name { color: var(--muted); font-weight: 500; }
.views-menu { left: 0; right: auto; width: 280px; }
.menu-heading {
  padding: 4px 8px 6px; font-size: 11.5px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted);
}
.menu-item {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 6px 8px;
  border: 0; border-radius: 5px; background: transparent; text-align: left; cursor: pointer;
}
.menu-item:hover:not(:disabled) { background: var(--hover); }
.menu-item:disabled { color: var(--muted); cursor: default; }
.menu-item.danger { color: var(--danger); }
.menu-item .check { width: 14px; flex: none; color: var(--accent); font-weight: 700; }
.menu-form { display: grid; gap: 6px; padding: 4px; }
.menu-input { width: 100%; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); }
.menu-input[aria-invalid="true"] { border-color: var(--danger); }

/* --- home -------------------------------------------------------------- */

.home-page { flex: 1; min-height: 0; overflow-y: auto; }
.home { padding: 16px; display: grid; gap: 16px; max-width: 1400px; }
.dash-loading { padding: 16px; }

/* The vessel: its photo beside its name, words and particulars; stacked on a narrow screen. */
.vessel {
  display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); overflow: hidden;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
}
.vessel.no-photo { grid-template-columns: minmax(0, 1fr); }
.vessel-photo { min-height: 220px; max-height: 360px; background: var(--surface-2); }
.vessel-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
.vessel-text { display: grid; gap: 12px; align-content: start; padding: 20px 22px; min-width: 0; }
.vessel-title { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.vessel-title h2 { margin: 0; font-size: 26px; line-height: 1.2; overflow-wrap: anywhere; }
.vessel-subtitle { margin: 2px 0 0; color: var(--muted); }
.vessel-edit { flex: none; }
.vessel-intro { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; max-width: 75ch; }
.vessel-facts {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px 18px;
  margin: 4px 0 0; padding-top: 12px; border-top: 1px solid var(--border);
}
.vessel-facts div { min-width: 0; }
.vessel-facts dt { color: var(--muted); font-size: 12px; }
.vessel-facts dd { margin: 0; font-weight: 600; overflow-wrap: anywhere; }
.vessel-editor { display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 18px 20px; }
.vessel-editor-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 28px; }
.vessel-editor-foot { justify-content: flex-end; }
.fact-rows { display: grid; gap: 6px; }
.fact-row { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr) auto; gap: 6px; align-items: center; }
.fact-row input, .vessel-editor .field input[type="text"] {
  width: 100%; padding: 7px 9px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg);
}
.fact-rows + div { margin-top: 6px; }
.check-line { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; cursor: pointer; }

/* The way to each part of the app. */
.home-nav { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; }
.nav-card {
  display: flex; align-items: flex-start; gap: 12px; padding: 14px; text-align: left; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
}
.nav-card:hover { border-color: var(--accent); background: var(--hover); }
.nav-card-icon {
  display: grid; place-items: center; flex: none; width: 38px; height: 38px; border-radius: 10px;
  background: var(--accent-soft); color: var(--accent);
}
.nav-card-icon .icon { width: 20px; height: 20px; }
.nav-card-text { display: grid; gap: 2px; min-width: 0; }
.nav-card-title { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: 15px; }
.nav-card-count { color: var(--muted); font-weight: 400; font-size: 12.5px; font-variant-numeric: tabular-nums; }
.nav-card-hint { color: var(--muted); font-size: 12.5px; }

/* The modules, and the menu that chooses and orders them. */
.home-modules-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 4px; }
.home-modules-head h2 { margin: 0; font-size: 13px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.home-modules > .empty { grid-column: 1 / -1; }
.customise-menu { width: 340px; }
.module-list { list-style: none; margin: 0; padding: 0; }
.module-item { display: flex; align-items: center; gap: 2px; border-radius: 5px; }
.module-item:hover { background: var(--hover); }
.module-item label { flex: 1; min-width: 0; }
.module-item label:hover { background: transparent; }
.module-item.dragging { opacity: .45; }
.module-item.drop-target { box-shadow: inset 0 2px 0 var(--accent); }
.grip { display: inline-flex; color: var(--muted); cursor: grab; padding-left: 2px; }
.grip .icon { width: 16px; height: 16px; }
.icon-btn.mini { padding: 4px; }
.icon-btn.mini .icon { width: 14px; height: 14px; }
.icon-btn:disabled { opacity: .3; cursor: default; background: var(--btn-quiet-bg); }

.panel .tiles { margin-bottom: 4px; }
.panel .tile { background: var(--surface-2); border-color: transparent; }
.panel .tile:hover { border-color: var(--accent); }
.split { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 24px; margin-top: 14px; }
.sub-head { margin: 0 0 6px; font-size: 12px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.dash-table td.overdue { color: var(--danger); }
.home-chats { list-style: none; margin: 0; padding: 0; }
.home-chat {
  display: grid; gap: 1px; width: 100%; padding: 8px 6px; text-align: left; cursor: pointer;
  border: 0; border-bottom: 1px solid var(--border); background: transparent;
}
.home-chats li:last-child .home-chat { border-bottom: 0; }
.home-chat:hover { background: var(--hover); }
.home-chat.unread .chat-subject { font-weight: 700; }
.home-chat.unread .chat-preview { color: var(--text); }
.home-chat.unread .chat-time { color: var(--accent); font-weight: 600; }

.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; }
.tile {
  display: grid; gap: 2px; align-content: start; padding: 12px 14px; text-align: left; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
}
.tile:hover { border-color: var(--accent); }
.tile-label { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); }
.tile-value { font-size: 30px; font-weight: 600; line-height: 1.15; }
.tile.hero .tile-value { font-size: 48px; }
.tile-note { font-size: 12px; color: var(--muted); }
.tone-mark { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--viz-neutral); }
.tone-danger .tone-mark { background: var(--status-critical); }
.tone-warn .tone-mark { background: var(--status-warning); }
.tone-ok .tone-mark { background: var(--status-good); }

.panels { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.panel {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 14px 16px 16px; min-width: 0;
}
.panel.wide { grid-column: 1 / -1; }
.panel-head { margin-bottom: 10px; }
.panel-head h2 { margin: 0; font-size: 15px; }
.panel-head p { margin: 2px 0 0; font-size: 12.5px; }
.panel .empty { margin: 8px 0; }

.legend { display: flex; gap: 14px; margin-bottom: 8px; font-size: 12.5px; color: var(--muted); }
.legend-item { display: inline-flex; align-items: center; gap: 6px; }
.swatch { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }

.bars { display: grid; gap: 2px; }
.bar-row {
  display: grid; grid-template-columns: minmax(0, 13em) minmax(0, 1fr); align-items: center; gap: 10px;
  width: 100%; padding: 4px 6px; border: 0; border-radius: 5px; background: transparent;
  text-align: left; cursor: pointer;
}
.bar-row:hover:not(:disabled) { background: var(--hover); }
.bar-row:disabled { cursor: default; }
.bar-label { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-track { display: flex; align-items: center; gap: 8px; min-width: 0; height: 20px; }
/* Square at the baseline, rounded at the data end. */
.bar { display: block; height: 16px; min-width: 3px; border-radius: 0 4px 4px 0; flex: none; }
.bar-value { font-size: 12.5px; color: var(--text); font-variant-numeric: tabular-nums; flex: none; }
.stack { display: flex; gap: 2px; height: 16px; flex: none; min-width: 3px; }
.stack .bar { flex: 1 1 0; min-width: 2px; border-radius: 0; }
.stack .bar:last-child { border-radius: 0 4px 4px 0; }
.series-1 { background: var(--series-1); }
.series-2 { background: var(--series-2); }
.status-critical { background: var(--status-critical); }
.status-warning { background: var(--status-warning); }
.status-good { background: var(--status-good); }
.viz-neutral { background: var(--viz-neutral); }
.link-button {
  margin-top: 8px; padding: 0; border: 0; background: none; color: var(--accent); cursor: pointer; font-size: 13px;
}
.link-button:hover { text-decoration: underline; }

.columns { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); height: 190px; }
.column { display: grid; grid-template-rows: minmax(0, 1fr) auto; min-width: 0; border-radius: 4px 4px 0 0; }
.column:hover, .column:focus-visible { background: var(--hover); }
/* The baseline is the bottom edge of the plot area. */
.column-plot {
  display: flex; flex-direction: column; justify-content: flex-end; align-items: center;
  min-height: 0; padding-top: 18px; border-bottom: 1px solid var(--border);
}
.column-bar { width: min(24px, 70%); border-radius: 4px 4px 0 0; min-height: 3px; }
.column-value { font-size: 12px; font-variant-numeric: tabular-nums; margin-bottom: 2px; }
.column-label { font-size: 11.5px; color: var(--muted); text-align: center; padding-top: 4px; }

.table-wrap { overflow-x: auto; }
.dash-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.dash-table th {
  text-align: left; font-weight: 600; color: var(--muted); font-size: 12px; padding: 6px 8px;
  border-bottom: 1px solid var(--border); white-space: nowrap;
}
.dash-table td { padding: 7px 8px; border-bottom: 1px solid var(--border); }
.dash-table tbody tr { cursor: pointer; }
.dash-table tbody tr:hover, .dash-table tbody tr:focus-visible { background: var(--hover); }
.dash-table .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

.viz-tip {
  position: fixed; z-index: 70; pointer-events: none; max-width: 320px;
  padding: 6px 9px; border-radius: 6px; font-size: 12.5px;
  background: var(--text); color: var(--bg); box-shadow: var(--shadow);
}

/* --- comms ------------------------------------------------------------- */

.comms { flex: 1; min-height: 0; display: flex; }
/* The chat list is as wide as dragged (comms.js), within bounds that leave the chat at least
   360px: the same bounds the script uses, so a narrow window or the modal stays sane. */
.comms-layout {
  flex: 1; min-height: 0; display: grid;
  grid-template-columns: clamp(300px, var(--chat-list-width, 440px), calc(100% - 360px)) minmax(0, 1fr);
}
.icon { width: 18px; height: 18px; flex: none; }
.badge {
  display: inline-grid; place-items: center; flex: none; min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: 10px; background: var(--accent); color: var(--accent-text);
  font-size: 11.5px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.segmented { display: inline-flex; padding: 2px; border: 1px solid var(--border); border-radius: 999px; background: var(--bg); }
.segmented button {
  padding: 3px 12px; border: 0; border-radius: 999px; background: transparent; color: var(--muted); cursor: pointer;
}
.segmented button[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.segmented.small button { padding: 1px 10px; font-size: 12.5px; }
.chip-close {
  display: inline-flex; padding: 2px; border: 0; border-radius: 4px; background: transparent;
  color: var(--muted); cursor: pointer;
}
.chip-close:hover { background: var(--hover); color: var(--text); }
.chip-close .icon { width: 14px; height: 14px; }
.button-row { display: flex; gap: 8px; flex-wrap: wrap; }

/* The chat list. */
.chat-list-pane { position: relative; display: flex; flex-direction: column; min-height: 0; background: var(--surface); border-right: 1px solid var(--border); }
.comms-resize { right: -4px; }
.chat-list-head { display: grid; gap: 8px; padding: 12px; border-bottom: 1px solid var(--border); }
.chat-list-head .row { display: flex; align-items: center; gap: 8px; }
.chat-list-head .search { flex: 1; width: auto; min-width: 0; }
.chat-list-head .sort { margin-left: auto; padding: 4px 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); }
.new-chat-btn { display: inline-flex; align-items: center; gap: 4px; }
.new-chat-btn .icon { width: 16px; height: 16px; }
.equipment-filter { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 12.5px; }
.equipment-filter .chip { overflow: hidden; text-overflow: ellipsis; }
.chat-list { flex: 1; min-height: 0; overflow-y: auto; margin: 0; padding: 4px 0; list-style: none; }
.list-empty { padding: 28px 16px; text-align: center; }
.chat-row {
  display: grid; grid-template-columns: 44px minmax(0, 1fr); align-items: center; gap: 12px;
  width: 100%; padding: 0 14px; border: 0; background: transparent; text-align: left; cursor: pointer;
}
.chat-row:hover { background: var(--hover); }
.chat-row.active { background: var(--accent-soft); }
.chat-main { display: grid; gap: 1px; min-width: 0; padding: 10px 0; border-bottom: 1px solid var(--border); }
.chat-list li:last-child .chat-main { border-bottom: 0; }
.avatar {
  display: grid; place-items: center; flex: none; width: 44px; height: 44px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent); font-weight: 700; font-size: 15px;
}
.chat-line { display: flex; align-items: center; gap: 8px; min-width: 0; }
.chat-subject { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.chat-time { flex: none; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.chat-equipment { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: var(--muted); }
.chat-preview { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; color: var(--muted); }
.chat-preview .icon { width: 13px; height: 13px; margin-right: 2px; vertical-align: -2px; }
.chat-row.unread .chat-subject { font-weight: 700; }
.chat-row.unread .chat-preview { color: var(--text); }
.chat-row.unread .chat-time { color: var(--accent); font-weight: 600; }

/* The tray: the open chat. */
.tray { display: flex; min-width: 0; min-height: 0; background: var(--surface-2); }
.tray-empty { margin: auto; max-width: 380px; padding: 24px; text-align: center; }
.tray-empty h2 { margin: 0 0 6px; font-size: 18px; }
.tray-panel { position: relative; display: flex; flex-direction: column; flex: 1; min-width: 0; min-height: 0; }
.tray-enter { animation: tray-in .18s ease-out; }
@keyframes tray-in { from { opacity: 0; transform: translateX(24px); } }
@media (prefers-reduced-motion: reduce) { .tray-enter { animation: none; } }
.tray-head {
  display: flex; align-items: center; gap: 10px; padding: 10px 16px;
  background: var(--surface); border-bottom: 1px solid var(--border);
}
.tray-head .avatar { width: 36px; height: 36px; font-size: 13px; }
.tray-back { display: none; padding: 4px; }
.tray-title { min-width: 0; }
.tray-title h2 { margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 16px; }
.tray-title p { margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; }
.tray-equipment { margin: 0; font-size: inherit; }
.tray-body { position: relative; display: flex; flex: 1; min-height: 0; }
.messages { flex: 1; display: flex; flex-direction: column; gap: 4px; overflow-y: auto; padding: 12px 6% 16px; }
.chat-empty { margin: auto; }
.day { align-self: center; margin: 10px 0 6px; }
.day span, .unread-divider span {
  display: inline-block; padding: 3px 10px; border-radius: 8px; font-size: 12px;
  background: var(--surface); color: var(--muted); box-shadow: 0 1px 0 rgb(0 0 0 / 0.05);
}
.unread-divider { margin: 8px 0; text-align: center; }
.unread-divider span { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.new-pill {
  position: absolute; bottom: 12px; left: 50%; transform: translateX(-50%);
  padding: 6px 14px; border-radius: 999px; font-weight: 600; box-shadow: var(--shadow); cursor: pointer;
  border: var(--btn-primary-border-width) solid var(--btn-primary-border);
  background: var(--btn-primary-bg); color: var(--btn-primary-text);
}
.new-pill:hover { background: var(--btn-primary-bg-hover); }

/* Messages: yours on the right, the Shipyard's on the left. */
.msg { display: flex; }
.msg.out { justify-content: flex-end; }
.bubble {
  display: grid; gap: 4px; min-width: 84px; max-width: min(560px, 78%); padding: 6px 9px 4px;
  border-radius: 10px; background: var(--surface); box-shadow: 0 1px 0 rgb(0 0 0 / 0.06);
}
.msg.out .bubble { background: var(--accent-soft); border-top-right-radius: 3px; }
.msg.in .bubble { border-top-left-radius: 3px; }
.msg-sender { font-size: 12px; font-weight: 600; color: var(--accent); }
.msg-text { white-space: pre-wrap; overflow-wrap: anywhere; }
.msg-meta { display: flex; align-items: center; justify-content: flex-end; gap: 8px; font-size: 11px; color: var(--muted); }
.msg-meta .link-button { margin: 0; font-size: 12px; }
.msg-image { display: block; }
.msg-image img { display: block; max-width: 100%; max-height: 320px; border-radius: 6px; }
.msg-video { display: block; max-width: 100%; max-height: 360px; border-radius: 6px; background: #000; }
.msg-audio { max-width: 100%; }
.msg-file {
  display: flex; align-items: center; gap: 8px; min-width: 0; padding: 8px 10px; border-radius: 6px;
  background: color-mix(in srgb, currentColor 7%, transparent); color: inherit; text-decoration: none;
}
a.msg-file:hover { background: color-mix(in srgb, currentColor 12%, transparent); }
.msg-file-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg.pending .bubble { opacity: .75; }
.msg.failed .bubble { opacity: 1; box-shadow: inset 0 0 0 1px var(--danger); }
.msg-failed { color: var(--danger); font-weight: 600; }
.msg-error { font-size: 12px; color: var(--danger); }

/* The composer. */
.composer { display: grid; gap: 6px; padding: 8px 12px 10px; background: var(--surface); border-top: 1px solid var(--border); }
.composer-row { display: flex; align-items: flex-end; gap: 8px; }
.composer-text {
  flex: 1; min-width: 0; max-height: 180px; padding: 9px 14px; resize: none;
  border: 1px solid var(--border); border-radius: 18px; background: var(--bg); line-height: 1.4;
}
/* Quiet buttons with no stroke: the icon muted until hovered. */
.icon-btn {
  display: inline-flex; padding: 9px; border: 0; border-radius: 50%; background: var(--btn-quiet-bg);
  color: var(--muted); cursor: pointer;
}
.icon-btn:hover { background: var(--btn-quiet-bg-hover); color: var(--text); }
/* A primary button. */
.send-btn {
  display: grid; place-items: center; flex: none; width: 40px; height: 40px; border-radius: 50%; cursor: pointer;
  border: var(--btn-primary-border-width) solid var(--btn-primary-border);
  background: var(--btn-primary-bg); color: var(--btn-primary-text);
}
.send-btn:hover { background: var(--btn-primary-bg-hover); }
.composer-foot { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; font-size: 12.5px; }
.composer-hint { margin-left: auto; }
.composer-send-as { display: inline-flex; align-items: center; gap: 8px; }
.composer-files { display: flex; flex-wrap: wrap; gap: 6px; }
.file-chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 240px; padding: 4px 4px 4px 6px;
  border-radius: 8px; background: var(--surface-2); font-size: 12.5px;
}
.file-chip img { width: 32px; height: 32px; object-fit: cover; border-radius: 4px; }
.tray-panel.dropping::after {
  content: "Drop to attach"; position: absolute; inset: 8px; z-index: 5; display: grid; place-items: center;
  border: 2px dashed var(--accent); border-radius: var(--radius); pointer-events: none;
  background: color-mix(in srgb, var(--accent-soft) 85%, transparent); color: var(--accent); font-weight: 600;
}

/* A new chat. */
.new-chat-body { flex: 1; overflow-y: auto; width: 100%; max-width: 580px; padding: 16px; }
.new-chat .field input[type="file"] { font-size: 13px; }
.fixed-value { padding: 7px 0; overflow-wrap: anywhere; }
.new-chat-foot {
  display: flex; justify-content: flex-end; gap: 8px; padding: 12px 16px;
  background: var(--surface); border-top: 1px solid var(--border);
}

/* One pane at a time: the list, or the open chat with a way back. */
@media (max-width: 900px) {
  .comms-layout { grid-template-columns: minmax(0, 1fr); }
  .comms-layout .tray { display: none; }
  .comms-layout.tray-open .tray { display: flex; }
  .comms-layout.tray-open .chat-list-pane { display: none; }
  .chat-list-pane { border-right: 0; }
  .comms-resize { display: none; }
  .tray-back { display: inline-flex; }
  .messages { padding: 10px 10px 14px; }
  .bubble { max-width: 88%; }
  .composer-hint { display: none; }
}

/* --- model ------------------------------------------------------------- */

/* The picture, whole, as large as fits below the toolbar (letterboxed). The stage has exactly
   the picture's shape (--ratio, set by model.js), so a tag's % position lands on its tag. */
.model {
  flex: 1; min-height: 0; position: relative; overflow: hidden; background: var(--bg);
  container-type: size; display: grid; place-items: center;
}
.model-stage { position: relative; aspect-ratio: var(--ratio); width: min(100cqw, 100cqh * var(--ratio)); }
.model-image { display: block; width: 100%; height: 100%; user-select: none; -webkit-user-select: none; }
/* Transparent over the picture's own tag; a ring on hover or keyboard focus shows it is there. */
.model-tag {
  position: absolute; width: 3%; aspect-ratio: 1; translate: -50% -50%;
  border: 0; padding: 0; border-radius: 50%; background: transparent; cursor: pointer;
}
.model-tag:hover { box-shadow: 0 0 0 2px rgb(255 255 255 / .85), 0 0 0 4px rgb(0 0 0 / .3); }
.model-tag:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Over the picture: no 3D model uploaded yet. */
.model-note {
  position: absolute; left: 16px; bottom: 16px; max-width: 380px; display: grid; gap: 10px; padding: 12px 14px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow);
}
.model-note p { margin: 0; font-size: 13px; }
.model-loading { padding: 16px; }

/* The 3D model (model.js, twin/): a toolbar, the viewport, and the tag list beside it. */
.twin { place-self: stretch; width: 100%; height: 100%; min-height: 0; display: flex; flex-direction: column; }
.twin-toolbar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 8px 12px;
  border-bottom: 1px solid var(--border); background: var(--surface);
}
.twin-toolbar .spacer { flex: 1; }
.twin-toolbar .btn[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.twin-select { max-width: 260px; }
.twin-hint { color: var(--muted); font-size: 12.5px; }
/* A little room below, so the model does not look as if it runs off the page. */
.twin-body { flex: 1; min-height: 0; display: flex; position: relative; padding-bottom: 12px; }
.twin-stage { flex: 1; min-width: 0; position: relative; border-bottom: 1px solid var(--border); }
.twin-viewport { position: absolute; inset: 0; overflow: hidden; }
/* Edit mode: a frame round the model, over the canvas and under everything on it. */
.twin-viewport.editing::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none; border: 3px solid var(--accent);
}
.twin-viewport.placing .twin-canvas { cursor: crosshair; }
.twin-viewport.flying .twin-canvas { cursor: move; }
.twin-canvas { display: block; touch-action: none; }
/* The tags' layer: clicks pass through to the canvas except on a pin. Its own stacking context
   (three.js gives each label a z-index), under the section panel and the tag editor. */
.twin-labels { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.twin-progress {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%; padding: 10px 16px; border-radius: var(--radius);
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow); font-size: 13px;
}

/* A tag: a dot with its view's icon on its point -- equipment blue, the Tasks view in the
   worst status's colour, the Warranty view's own -- a count of what the view shows, and its
   name with Labels. */
.twin-pin {
  pointer-events: auto; display: inline-flex; align-items: center; gap: 6px; padding: 0; border: 0;
  background: transparent; cursor: pointer; color: var(--text); font: inherit; transition: opacity .2s;
  /* The dot, not the button, sits on the point. */
  translate: calc(50% - 12px) 0;
  --pin: var(--accent);
}
.twin-pin.tone-danger, .twin-tag-icon.tone-danger { --pin: var(--status-critical); }
.twin-pin.tone-warn, .twin-tag-icon.tone-warn { --pin: var(--status-warning); }
.twin-pin.tone-ok, .twin-tag-icon.tone-ok { --pin: var(--status-good); }
.twin-pin.tone-neutral, .twin-tag-icon.tone-neutral { --pin: var(--viz-neutral); }
.twin-pin.tone-equipment, .twin-tag-icon.tone-equipment { --pin: var(--series-1); }
.twin-pin.tone-warranty, .twin-tag-icon.tone-warranty { --pin: var(--twin-warranty); }
.pin-dot {
  position: relative; flex: none; display: grid; place-items: center; width: 24px; height: 24px; border-radius: 50%;
  background: var(--pin); color: var(--surface);
  border: 2px solid var(--surface); box-shadow: 0 1px 4px rgb(0 0 0 / .45);
}
/* Amber is too light for a light icon. */
.tone-warn .pin-dot, .twin-tag-icon.tone-warn { color: color-mix(in srgb, var(--pin) 25%, black); }
.pin-icon { width: 13px; height: 13px; }
.pin-badge {
  position: absolute; top: -8px; right: -10px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px;
  display: grid; place-items: center; background: var(--status-warning); color: color-mix(in srgb, var(--status-warning) 25%, black);
  border: 1.5px solid var(--surface); font-size: 10px; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1;
}
.pin-badge.tone-danger { background: var(--status-critical); color: var(--surface); }
.pin-badge.tone-neutral { background: var(--text); color: var(--surface); }
/* A tag the view leaves out, shown in Edit only. */
.twin-pin.dimmed:not(.occluded) { opacity: .45; }
.twin-tag-icon.dimmed { opacity: .45; }
.pin-label {
  display: none; padding: 2px 8px; border-radius: 10px; white-space: nowrap; font-size: 12px; font-weight: 600;
  background: var(--surface); border: 1px solid var(--border); box-shadow: 0 1px 4px rgb(0 0 0 / .2);
}
.show-labels .twin-pin:not(.occluded) .pin-label { display: inline; }
.twin-pin:hover .pin-dot { transform: scale(1.15); }
.twin-pin:focus-visible { outline: none; }
.twin-pin:focus-visible .pin-dot { outline: 2px solid var(--focus); outline-offset: 2px; }
/* Behind part of the model: faint, and not clickable through the hull. */
.twin-pin.occluded { opacity: .28; pointer-events: none; }
.twin-pin.occluded .pin-dot { --pin: var(--muted); }
.twin-pin.cut, .twin-pin.filtered { visibility: hidden; pointer-events: none; }
.twin-pin.draft .pin-dot { width: 16px; height: 16px; background: var(--status-warning); }
.twin-pin.draft { translate: calc(50% - 8px) 0; }
.twin-pin.flash .pin-dot { animation: pin-flash 1.2s ease-out 2; }
@keyframes pin-flash {
  0% { box-shadow: 0 0 0 0 var(--pin); }
  100% { box-shadow: 0 0 0 18px transparent; }
}

/* A tag's card: what it marks and how that stands, beside its pin while pointed at. */
.twin-card {
  position: absolute; z-index: 2; width: 320px; padding: 10px 12px; display: grid; gap: 4px; pointer-events: none;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow);
}
.twin-card[hidden] { display: none; }
.twin-card-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
.twin-card-head strong { flex: 1; min-width: 0; font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.twin-card-type { font-size: 11.5px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.twin-card-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.twin-card-tasks { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.twin-card-tasks li { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 12.5px; }
.twin-card-task { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.twin-card-due { color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.twin-card-line, .twin-card-sub, .twin-card-notes, .twin-card-hint { margin: 0; font-size: 12.5px; }
.twin-card-sub { color: var(--muted); }
.twin-card-notes { white-space: pre-line; padding-top: 2px; border-top: 1px solid var(--border); }
.twin-card-hint { color: var(--muted); font-size: 12px; }
/* A tag's icon in its colour: in the card and the tag list. */
.twin-tag-icon {
  flex: none; display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%;
  background: var(--pin); color: var(--surface);
}
.twin-tag-icon .pin-icon { width: 12px; height: 12px; }

/* A tag's editor, next to where it was clicked. */
.twin-popover {
  position: absolute; z-index: 2; width: 320px; padding: 12px 14px; display: grid; gap: 4px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow);
}
/* One column that never grows past the popover: a long name wraps or ends in an ellipsis. */
.twin-popover { max-height: calc(100% - 16px); overflow-y: auto; grid-template-columns: minmax(0, 1fr); }
/* Dragged by its header, the whole strip across the top (placePopover). */
.twin-popover-head {
  display: flex; align-items: center; gap: 8px; margin: -12px -14px 0; padding: 12px 14px 6px;
  cursor: move; user-select: none; touch-action: none;
}
.twin-popover-head h3 { flex: 1; min-width: 0; margin: 0; font-size: 14px; overflow-wrap: anywhere; }
.twin-popover-head .grip { cursor: move; }
.twin-popover .button-row { display: flex; gap: 6px; align-items: center; }
.twin-popover .spacer { flex: 1; }
.twin-popover .field[hidden] { display: none; }
.twin-popover textarea { resize: vertical; min-height: 52px; height: 52px; }
.twin-part { gap: 4px; }
.twin-part-label { font-size: 13px; }
.twin-part-views { display: flex; flex-wrap: wrap; gap: 4px 14px; }
.twin-part-row { display: flex; align-items: center; gap: 6px; }
.twin-part-name { flex: 1; min-width: 0; font-size: 12.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.twin-part .hint { margin: 0; font-size: 12px; color: var(--muted); }
/* The handles of a tag's Part Box (twin/boxedit.js): one on each face, dragged along its axis. */
/* The button is a larger, unseen target; the square is its ::before, and only that grows when
   pointed at. Nothing may scale the button itself: CSS2D places it with `transform`, and a
   `scale` on it scales that placing too -- the handle jumped away from the pointer and back. */
.twin-box-handle {
  pointer-events: auto; width: 28px; height: 28px; padding: 0; cursor: grab; touch-action: none;
  display: grid; place-items: center; background: none; border: 0; border-radius: 6px;
}
.twin-box-handle::before {
  content: ""; width: 14px; height: 14px; box-sizing: border-box; border-radius: 3px;
  background: var(--accent); border: 2px solid var(--surface); box-shadow: 0 1px 4px rgb(0 0 0 / .45);
  transition: transform .1s;
}
.twin-box-handle:hover::before, .twin-box-handle.dragging::before { transform: scale(1.3); }
.twin-box-handle.dragging { cursor: grabbing; }
.twin-box-handle:focus-visible { outline: 2px solid var(--focus); outline-offset: -4px; }
/* The box-editing screen (model.js startBoxing): the part among the rest, a bar at the bottom
   with Save and Exit; the toolbar and the tag list wait, dimmed (and inert). */
.twin.boxing .twin-toolbar, .twin.boxing .twin-panel { opacity: .45; }
.twin.boxing .twin-viewport.placing .twin-canvas { cursor: grab; }
.twin-boxbar {
  position: absolute; z-index: 3; left: 50%; bottom: 16px; translate: -50% 0; max-width: calc(100% - 32px);
  display: flex; align-items: center; gap: 8px 14px; flex-wrap: wrap; justify-content: center; padding: 8px 10px 8px 14px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow);
}
.twin-boxbar[hidden] { display: none; }
.twin-boxbar-hint { font-size: 12.5px; color: var(--muted); }
.twin-boxbar-actions { display: flex; gap: 6px; }

/* The view cube (twin/cube.js): at the viewport's top right, under the menus. Each face is a
   3 x 3 grid of buttons -- the face, its edges, its corners -- shaded by how squarely it faces
   the eye (--shade, set by the cube). Turned, it reaches 0.37 of its size past its box on every
   side: the inset keeps it in view. The body's own plane runs through the middle of the cube,
   so it takes no clicks, or it would catch those on the far half of a face. */
.twin-cube {
  --cube: 76px; --half: calc(var(--cube) / 2);
  position: absolute; z-index: 2; top: 34px; right: 34px; width: var(--cube); height: var(--cube);
  user-select: none; -webkit-user-select: none; touch-action: none; cursor: grab;
}
.twin-cube.dragging, .twin-cube.dragging .twin-cube-cell { cursor: grabbing; }
.twin-cube-body { position: absolute; inset: 0; transform-style: preserve-3d; pointer-events: none; }
.twin-cube-face {
  pointer-events: auto;
  position: absolute; inset: 0; display: grid; grid-template: 22% 1fr 22% / 22% 1fr 22%;
  border: 1px solid color-mix(in srgb, var(--border), var(--text) 20%); border-radius: 3px; overflow: hidden;
  background: color-mix(in srgb, var(--surface), var(--text) var(--shade, 0%));
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
}
.twin-cube-cell {
  display: grid; place-items: center; min-width: 0; padding: 0; margin: 0; border: 0; background: transparent;
  color: var(--text); font: inherit; font-size: 11px; font-weight: 600; letter-spacing: .02em; cursor: pointer;
}
.twin-cube-cell.hot { background: var(--accent-soft); color: var(--accent); }
.twin-cube-cell:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }

/* Section (twin/sections.js): a small menu under its button -- off, a saved deck, any height. */
.twin-section-menu {
  position: absolute; z-index: 3; top: 8px; width: 260px; display: grid; gap: 8px; padding: 8px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow);
}
.twin-section-menu[hidden] { display: none; }
.twin-section-levels { display: grid; gap: 2px; }
.twin-section-levels .hint { margin: 2px 8px; font-size: 12px; color: var(--muted); }
.twin-section-row { display: flex; align-items: center; gap: 4px; }
.twin-section-choice {
  flex: 1; display: flex; justify-content: space-between; gap: 8px; padding: 6px 8px; border: 0; border-radius: 6px;
  background: transparent; color: var(--text); font: inherit; font-size: 13px; text-align: left; cursor: pointer;
}
.twin-section-choice:hover { background: var(--hover); }
.twin-section-choice[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.twin-section-height { display: flex; align-items: center; gap: 8px; padding: 0 8px; font-size: 12.5px; color: var(--muted); }
.twin-section-height .twin-range { flex: 1; }
.twin-section-save { display: flex; gap: 6px; padding: 6px 8px 0; border-top: 1px solid var(--border); }
.twin-section-save[hidden] { display: none; }
.twin-section-save input { flex: 1; min-width: 0; }
.twin-section-menu .error { margin: 0 8px; }
.twin-check { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; cursor: pointer; }
.twin-check input { margin: 0; accent-color: var(--accent); }
.twin-readout { color: var(--muted); font-size: 12.5px; font-variant-numeric: tabular-nums; min-width: 52px; text-align: right; }
.twin-range { width: 100%; margin: 0; accent-color: var(--accent); }
/* Settings (the cog, model.js): everything that is not looking -- Edit mode, tag names, edges,
   the ghost, tag colours, a new model -- in one menu at the viewport's top right. */
.twin-cog { padding: 4px 6px; }
.twin-cog[aria-expanded="true"] { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.twin-settings {
  position: absolute; z-index: 3; top: 8px; right: 8px; width: 290px; display: grid; gap: 6px; padding: 10px 12px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow);
}
.twin-settings[hidden] { display: none; }
.twin-settings-group { display: grid; gap: 6px; }
.twin-settings hr { width: 100%; margin: 2px 0; border: 0; border-top: 1px solid var(--border); }
.twin-switch { display: flex; align-items: center; gap: 10px; cursor: pointer; }
.twin-switch-text { flex: 1; min-width: 0; display: grid; font-size: 13px; }
.twin-switch-hint { font-size: 12px; color: var(--muted); }
/* A checkbox drawn as a switch. */
.twin-switch input {
  appearance: none; -webkit-appearance: none; flex: none; width: 34px; height: 20px; margin: 0; border-radius: 10px;
  background: var(--border); position: relative; cursor: pointer; transition: background .15s;
}
.twin-switch input::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%;
  background: var(--surface); box-shadow: 0 1px 2px rgb(0 0 0 / .3); transition: translate .15s;
}
.twin-switch input:checked { background: var(--accent); }
.twin-switch input:checked::after { translate: 14px 0; }
.twin-switch input:disabled { opacity: .45; cursor: not-allowed; }
.twin-switch input:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.twin-settings-head { display: flex; align-items: center; justify-content: space-between; font-size: 13px; }
.twin-colours { display: flex; flex-wrap: wrap; gap: 8px 12px; }
.twin-colour { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; white-space: nowrap; cursor: pointer; }
.twin-colour input {
  width: 26px; height: 26px; padding: 0; border: 1px solid var(--border); border-radius: 50%; background: none; cursor: pointer;
}
.twin-colour input::-webkit-color-swatch-wrapper { padding: 2px; }
.twin-colour input::-webkit-color-swatch { border: 0; border-radius: 50%; }
.twin-colour input::-moz-color-swatch { border: 0; border-radius: 50%; }
.twin-settings-upload { width: 100%; }
/* The model's orientation: Forward and Up, for the view cube's labels (Edit only). */
.twin-orientation { display: grid; gap: 6px; }
.twin-orientation[hidden] { display: none; }
.twin-orientation .twin-switch-hint { margin: 0; }
.twin-orientation-row { display: flex; gap: 14px; }
.twin-orientation-row label { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; }
.twin-settings > span:last-child { display: grid; }

/* "Editing · Done": Edit mode, said in the toolbar, and the way back to Browse. */
.twin-box-chip {
  padding: 3px 10px; border-radius: 999px; border: 1px solid var(--accent); background: var(--accent-soft);
  color: var(--accent); font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;
}
.twin-box-chip[hidden] { display: none; }

/* The tag list. */
.twin-panel {
  position: relative; flex: none; width: var(--twin-panel-width, 300px); display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; min-height: 0;
  border-left: 1px solid var(--border); border-bottom: 1px solid var(--border); background: var(--surface);
}
.twin-panel-resize { left: -4px; }
.twin-panel-head { display: flex; align-items: center; gap: 8px; }
/* What the model shows: tags by type, and by the status of what they mark. */
.twin-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.twin-chip {
  display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px; border-radius: 12px; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface); color: var(--muted); font: inherit; font-size: 12px;
}
.twin-chip[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); color: var(--text); }
.twin-chip[aria-pressed="false"] .tone-mark { opacity: .35; }
.twin-chip-count { font-variant-numeric: tabular-nums; color: var(--muted); }
.twin-panel-head h3 { margin: 0; font-size: 13px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.twin-tag-list { list-style: none; margin: 0; padding: 0; overflow-y: auto; display: grid; gap: 2px; align-content: start; }
.twin-tag-list li { display: flex; align-items: center; gap: 6px; }
.twin-tag-go {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; text-align: left; padding: 6px 8px; border: 0;
  border-radius: 6px; background: transparent; color: var(--text); cursor: pointer; font: inherit;
}
.twin-tag-text { flex: 1; min-width: 0; display: grid; }
.twin-tag-go:hover { background: var(--hover); }
.twin-tag-name { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.twin-tag-sub { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.twin-empty { padding: 8px 4px; font-size: 13px; }
@media (max-width: 760px) {
  .twin-panel { position: absolute; right: 0; top: 0; bottom: 12px; z-index: 3; box-shadow: var(--shadow); }
  .twin-panel-resize { display: none; }
  .twin-hint { display: none; }
  .twin-cube { --cube: 60px; top: 26px; right: 26px; }
  .twin-cube-cell { font-size: 9px; }
  /* The list would lie over the part being boxed. */
  .twin.boxing .twin-panel { display: none; }
  .twin-boxbar { left: 16px; right: 16px; translate: none; max-width: none; }
}

/* --- the equipment modal ---------------------------------------------- */

/* Below the drawer (35/40), which opens over it for an item's form, and below the toasts. */
.modal-scrim { position: fixed; inset: 0; z-index: 32; background: rgb(0 0 0 / 0.32); }
.modal {
  position: fixed; z-index: 33; inset: 24px; margin: auto;
  width: min(1280px, calc(100vw - 48px)); height: calc(100vh - 48px);
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow);
}
.modal-head { display: flex; align-items: center; gap: 8px; padding: 12px 16px; border-bottom: 1px solid var(--border); }
/* Moved by its header and resized from any edge or corner (util.movable); once moved or
   resized, its place is inline and the centring rules step aside. */
.modal.placed { inset: auto; margin: 0; }
.modal-head { cursor: move; user-select: none; touch-action: none; }
.modal-head button { cursor: pointer; }
.modal-resize { position: absolute; z-index: 5; touch-action: none; }
.modal-resize[data-edge="n"], .modal-resize[data-edge="s"] { left: 12px; right: 12px; height: 5px; cursor: ns-resize; }
.modal-resize[data-edge="e"], .modal-resize[data-edge="w"] { top: 12px; bottom: 12px; width: 5px; cursor: ew-resize; }
.modal-resize[data-edge="n"] { top: 0; }
.modal-resize[data-edge="s"] { bottom: 0; }
.modal-resize[data-edge="e"] { right: 0; }
.modal-resize[data-edge="w"] { left: 0; }
.modal-resize[data-edge="nw"], .modal-resize[data-edge="ne"],
.modal-resize[data-edge="sw"], .modal-resize[data-edge="se"] { width: 12px; height: 12px; }
.modal-resize[data-edge="nw"] { top: 0; left: 0; cursor: nwse-resize; }
.modal-resize[data-edge="se"] { bottom: 0; right: 0; cursor: nwse-resize; }
.modal-resize[data-edge="ne"] { top: 0; right: 0; cursor: nesw-resize; }
.modal-resize[data-edge="sw"] { bottom: 0; left: 0; cursor: nesw-resize; }
.modal.resizing iframe { pointer-events: none; }
.modal-title { flex: 1; min-width: 0; display: grid; }
.modal-title .muted { font-size: 12px; }
.modal-title h2 { margin: 0; font-size: 18px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The item's details: compact, and never so many that the tabs leave the screen. */
.modal-facts {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 8px 18px;
  margin: 0; padding: 12px 16px; max-height: 24vh; overflow-y: auto; font-size: 13px;
  border-bottom: 1px solid var(--border); background: var(--surface-2);
}
.modal-facts div { min-width: 0; }
.modal-facts dt { color: var(--muted); font-size: 12px; }
.modal-facts dd { margin: 0; overflow-wrap: anywhere; }
.modal-tabs { display: flex; gap: 2px; padding: 0 12px; border-bottom: 1px solid var(--border); overflow-x: auto; flex: none; }
.modal-tab {
  display: inline-flex; align-items: center; gap: 6px; padding: 10px 12px; white-space: nowrap;
  border: 0; border-bottom: 2px solid transparent; background: transparent; color: var(--text); cursor: pointer;
}
.modal-tab:hover { background: var(--hover); }
.modal-tab[aria-selected="true"] { border-bottom-color: var(--accent); color: var(--accent); font-weight: 600; }
.tab-count {
  min-width: 20px; padding: 0 6px; border-radius: 10px; line-height: 18px; text-align: center;
  font-size: 11.5px; font-variant-numeric: tabular-nums; background: var(--surface-2); color: var(--muted);
}
.modal-tab[aria-selected="true"] .tab-count { background: var(--accent-soft); color: var(--accent); }
/* Nothing linked yet: a quieter tab, still open to add the first item. */
.modal-tab.empty:not([aria-selected="true"]) { color: var(--muted); }
.modal-tab .badge { min-width: 18px; height: 18px; font-size: 11px; }
.modal-panels { flex: 1; min-height: 0; display: flex; }
.modal-panel { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.modal-toolbar { display: flex; align-items: center; gap: 8px; padding: 8px 12px; flex-wrap: wrap; }
.modal-toolbar .search { width: min(280px, 100%); }
.modal-toolbar .spacer { flex: 1; }
.modal-grid { flex: 1; min-height: 0; }
.modal-panel .comms { flex: 1; }
.modal-loading { padding: 16px; }

/* --- the task form ----------------------------------------------------- */

/* Above the equipment modal (a task opened from its tabs); below the drawer and toasts. */
.task-scrim { z-index: 36; }
.task-modal { z-index: 37; width: min(1080px, calc(100vw - 48px)); }
.task-status { display: flex; align-items: center; gap: 8px; flex: none; font-size: 13px; }
.status-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 2px 10px; border-radius: 12px;
  background: var(--surface-2); font-size: 12.5px; font-weight: 600; white-space: nowrap;
}
.status-chip::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--viz-neutral); }
.status-chip.tone-danger::before { background: var(--status-critical); }
.status-chip.tone-warn::before { background: var(--status-warning); }
.status-chip.tone-ok::before { background: var(--status-good); }
.status-chip.tone-warranty::before { background: var(--twin-warranty); }
.task-body { flex: 1; min-height: 0; overflow-y: auto; padding: 16px 20px 24px; }
.task-form { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 0 28px; }
.task-details #f-task_description { min-height: 260px; }
.task-schedule {
  align-self: start; padding: 14px 16px 2px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2);
}
.task-schedule > .hint { margin: 0 0 14px; font-size: 12px; color: var(--muted); }
.switch { display: inline-flex; align-items: center; gap: 10px; margin-bottom: 10px; font-size: 13px; font-weight: 600; cursor: pointer; }
.switch input {
  appearance: none; position: relative; flex: none; width: 34px; height: 20px; margin: 0; border-radius: 10px;
  background: var(--border); cursor: pointer; transition: background .15s;
}
.switch input::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%;
  background: var(--surface); box-shadow: 0 1px 2px rgb(0 0 0 / 0.25); transition: transform .15s;
}
.switch input:checked { background: var(--accent); }
.switch input:checked::after { transform: translateX(14px); }
.switch input:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.unit-pair { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: 8px; }
.readout { padding: 7px 0; }
.task-completion { margin-top: 8px; padding-top: 16px; border-top: 1px solid var(--border); }
.task-completion h3 { margin: 0 0 12px; font-size: 13px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.task-completion-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 28px; align-items: start; }
.task-completion #f-job_comments { min-height: 120px; }
.task-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 28px; margin: 0; }
.task-facts dt { color: var(--muted); font-size: 12px; }
.task-facts dd { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.task-facts .wide { grid-column: 1 / -1; }
/* The Task List's Fill / Open button. */
.task-btn { min-width: 52px; padding: 1px 10px; line-height: 20px; }
.task-btn.fill {
  border: var(--btn-outline-border-width) solid var(--btn-outline-border);
  background: var(--btn-outline-bg); color: var(--btn-outline-text); font-weight: 600;
}
.task-btn.fill:hover { background: var(--btn-outline-bg-hover); }
.task-open { display: inline-flex; align-items: center; gap: 2px; }
.history-btn { display: inline-flex; padding: 2px 4px; }
.history-btn .icon { width: 16px; height: 16px; }
/* The task form's tabs sit right under its header, like the equipment modal's. */
.task-modal .modal-tabs { padding: 0 16px; }
/* History: one entry per job, newest first, down a line. The record opened is marked. */
.history-head { margin: 0 0 14px; font-size: 13px; }
.history-empty { margin: 8px 0; }
.history { list-style: none; margin: 0; padding: 0 0 0 18px; border-left: 2px solid var(--border); display: grid; gap: 16px; }
.history-entry { position: relative; padding: 10px 14px; border-radius: var(--radius); }
.history-entry::before {
  content: ""; position: absolute; left: -25px; top: 15px; width: 10px; height: 10px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--viz-neutral);
}
.history-entry:first-child::before { border-color: var(--accent); background: var(--accent); }
.history-entry.current { background: var(--accent-soft); }
.history-when { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.history-when .muted { font-size: 12.5px; }
.history-by { margin-top: 2px; font-size: 13px; color: var(--muted); }
.history-comments { margin: 8px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.history-entry .files { margin: 10px 0 0; max-width: 560px; }

@media (max-width: 760px) {
  .task-form, .task-completion-grid, .task-facts { grid-template-columns: minmax(0, 1fr); }
}

/* --- settings (settings.js) ------------------------------------------- */

.settings-page { flex: 1; min-height: 0; overflow-y: auto; }
.settings-tabs { background: var(--surface); }
.settings-panel { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; max-width: 1100px; padding: 0 16px 24px; }
.settings-error { color: var(--danger); }
/* Save stays in reach however far down the values go. */
.settings-actions {
  position: sticky; top: 0; z-index: 3; display: flex; align-items: flex-end; justify-content: space-between;
  flex-wrap: wrap; gap: 10px 16px; padding: 14px 0 12px; background: var(--bg); border-bottom: 1px solid var(--border);
}
.settings-intro { min-width: 0; flex: 1 1 360px; }
.settings-intro h2 { margin: 0 0 2px; font-size: 18px; }
.settings-intro p { margin: 0; max-width: 75ch; font-size: 13px; }
.settings-buttons { display: flex; flex-wrap: wrap; gap: 8px; }
.settings-notice {
  padding: 10px 14px; border: 1px solid var(--warn); border-radius: var(--radius); background: var(--surface);
}
.settings-notice ul { margin: 6px 0 0; padding-left: 20px; font-size: 12.5px; }

/* Theme: each mode drawn in its own values (.theme-scope-light / -dark, set by settings.js),
   so the dark column and preview look dark while the page is light, and back. */
.theme-previews { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.theme-preview {
  padding: 12px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg); color: var(--text); font: var(--font-weight) var(--font-size)/1.45 var(--font-body);
}
.theme-preview-label {
  margin-bottom: 8px; font-size: 11.5px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted);
}
.theme-preview-card {
  display: grid; gap: 10px; padding: 14px 16px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow);
}
.theme-preview-card h3 { margin: 0; font-size: 16px; }
.theme-preview-card p { margin: 0; }
.theme-preview a { color: var(--accent); }
.theme-preview-buttons { display: flex; flex-wrap: wrap; gap: 6px; }
.theme-preview-states { display: flex; flex-wrap: wrap; gap: 14px; font-size: 12.5px; font-weight: 600; }
.tp-ok { color: var(--ok); }
.tp-warn { color: var(--warn); }
.tp-danger { color: var(--danger); }
.theme-preview-chart { display: flex; gap: 4px; height: 16px; padding: 3px; border-radius: 4px; background: var(--viz-track); }
.theme-preview-chart span { flex: 1; border-radius: 2px; }

.theme-group h3 {
  margin: 6px 0 8px; font-size: 13px; letter-spacing: .05em; text-transform: uppercase; color: var(--muted);
}
.theme-table { overflow: hidden; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.theme-row {
  display: grid; grid-template-columns: minmax(180px, 1.1fr) minmax(0, 1fr) minmax(0, 1fr);
  border-top: 1px solid var(--border);
}
.theme-row:first-child { border-top: 0; }
.theme-head { background: var(--surface-2); color: var(--muted); font-size: 12px; font-weight: 600; }
.theme-head span { padding: 6px 12px; }
.theme-name { display: grid; gap: 1px; align-content: center; min-width: 0; padding: 8px 12px; }
.theme-label { font-weight: 600; }
.theme-hint, .theme-var { font-size: 12px; color: var(--muted); }
.theme-var { font-size: 11.5px; }
.theme-cell {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 4px 8px;
  min-width: 0; padding: 8px 12px; border-left: 1px solid var(--border); background: var(--surface); color: var(--text);
}
.theme-row.shared .theme-cell { grid-column: 2 / 4; }
.theme-input {
  width: 100%; min-width: 0; padding: 5px 8px; font-size: 12.5px;
  border: 1px solid var(--border); border-radius: 6px; background: var(--bg);
}
.theme-input:disabled { border-color: transparent; background: transparent; }
.theme-cell.changed .theme-input { border-color: var(--accent); }
.theme-cell.unsaved .theme-input { background: var(--accent-soft); }
.theme-input[aria-invalid="true"] { border-color: var(--danger); }
.theme-error { grid-column: 1 / -1; color: var(--danger); font-size: 12px; }
.theme-both { grid-column: 2 / -1; color: var(--muted); font-size: 11.5px; }
.theme-reset { padding: 2px 7px; }
/* A colour over a checkerboard, so a see-through one shows as such; the picker lies on top. */
.theme-swatch {
  position: relative; width: 26px; height: 26px; overflow: hidden; border: 1px solid var(--border); border-radius: 6px;
  background: repeating-conic-gradient(var(--surface-2) 0 25%, var(--surface) 0 50%) 0 0 / 10px 10px;
}
.theme-chip { position: absolute; inset: 0; }
.theme-picker { position: absolute; inset: 0; width: 100%; height: 100%; padding: 0; border: 0; opacity: 0; cursor: pointer; }
.theme-picker:disabled { cursor: default; }
.theme-sample { display: inline-grid; place-items: center; width: 26px; height: 26px; font-size: 15px; }
.theme-sample.theme-shadow {
  width: 22px; height: 18px; margin: 0 2px; border: 1px solid var(--border); border-radius: 4px; background: var(--surface);
}

@media (max-width: 760px) {
  .theme-previews { grid-template-columns: minmax(0, 1fr); }
  .theme-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .theme-name { grid-column: 1 / -1; padding-bottom: 0; }
  .theme-head span:first-child { display: none; }
  .theme-cell { border-left: 0; }
  .theme-row.shared .theme-cell { grid-column: 1 / -1; }
}

/* --- login page (static/login.html) ------------------------------------ */

body.login-page {
  overflow: auto; min-height: 100%; padding: 16px;
  display: grid; grid-template-columns: minmax(0, 1fr); place-items: center;
}
.login-card {
  width: min(400px, 100%); padding: 28px 28px 22px; display: grid; gap: 14px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.login-card h1 { margin: 0; font-size: 22px; }
.login-card p { margin: 0; }
.login-brand { padding: 0; }
.login-message { padding: 9px 12px; border-radius: var(--radius); background: var(--accent-soft); }
.login-message.error { background: var(--danger-soft); color: var(--danger); }
/* After Microsoft's sign-in button: its logo, its words, a plain frame. */
.ms-signin {
  display: flex; align-items: center; justify-content: center; gap: 12px; height: 41px;
  border: 1px solid var(--border); border-radius: var(--btn-radius); background: var(--surface);
  color: var(--text); font-weight: 600; text-decoration: none;
}
.ms-signin:hover { background: var(--hover); }
.login-foot { font-size: 12.5px; }

/* --- narrow screens ---------------------------------------------------- */

@media (max-width: 760px) {
  .shell { grid-template-columns: minmax(0, 1fr); }
  .sidebar {
    position: fixed; inset: 0 auto 0 0; width: 260px; z-index: 45;
    transform: translateX(-100%); transition: transform .18s ease;
  }
  body.nav-open .sidebar { transform: none; box-shadow: var(--shadow); }
  .nav-toggle { display: inline-block; }
  .nav-expand { display: none; }
  .search { width: 100%; }
  .toolbar-actions { width: 100%; }
  .drawer { width: 100vw; }
  .drawer-resize { display: none; }
  .modal { inset: 0; width: 100vw; height: 100vh; border-radius: 0; border: 0; }
  .modal-resize { display: none; }
  .modal-head { cursor: auto; touch-action: auto; }
  .panels { grid-template-columns: minmax(0, 1fr); }
  .bar-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); }
  .vessel, .vessel-editor-grid, .split { grid-template-columns: minmax(0, 1fr); }
  .vessel-photo { min-height: 160px; max-height: 240px; }
  .customise-menu { width: min(340px, calc(100vw - 32px)); }
}
