/* Site-wide styles, loaded by templates/base.html. */
:root {
  /* Palette. Keyword highlighter colors are separate (dashboard/palette.py). */
  --c-moss:    #5b8c5a;
  --c-clay:    #c0603c;
  --c-denim:   #4f6d9a;
  --c-mustard: #d9a420;
  --c-plum:    #7b5a8c;
  --c-teal:    #2a9d8f;
  --c-rose:    #c97b84;
  --c-olive:   #8a8f3c;
  --c-tan:     #b07d48;
  --c-navy:    #2b374b;
  --c-coral:   var(--c-clay);
  --c-gold:    var(--c-mustard);
  --c-sage:    var(--c-moss);

  /* Roles */
  --fg:        #222;
  --bg:        #fff;
  --muted:     #6b7686;
  --border:    #d8dde6;
  --border-strong: #a9b3c2;
  --bg-soft:   #f4f6fa;

  --accent:    var(--c-teal);
  --accent-dk: #217f73;
  --ok:        var(--c-sage);
  --warn:      var(--c-gold);
  --bad:       var(--c-coral);
  --header-bg: #f0f2f7;
  --header-fg: var(--c-navy);
  --header-border: #d0d6e4;

  /* Stage palette — each workflow stage gets one color, applied wherever
     that entity appears (day hub card, nav, schedule badge). Lets the
     user build muscle memory: gold = concrete, sage = cylinder, etc. */
  --stage-dfr:         var(--c-navy);
  --stage-dfr-soft:    #e5e9f0;
  --stage-concrete:    var(--c-gold);
  --stage-concrete-soft:#f8efd7;
  --stage-cylinder:    var(--c-sage);
  --stage-cylinder-soft:#e6eee6;
  --stage-transmittal: var(--c-teal);
  --stage-transmittal-soft:#dff0ee;
  --stage-compaction:  var(--c-tan);
  /* Binder-tab shades for breaks and compaction: light enough for navy tab text, the
     same on every page (day hub, project hub, review hub). */
  --stage-cylinder-tab:   #adc5ac;
  --stage-compaction-tab: #d7bea3;
  /* Asphalt: plum tint (5.2:1 with navy tab text). Proctors: rose tint (7:1). */
  --stage-asphalt-tab:    #b9a0c6;
  --stage-proctor-tab:    #e4bdc1;
}
* { box-sizing: border-box; }
body {
  font-family: -apple-system, "SF Pro Text", system-ui, "Segoe UI", Roboto, sans-serif;
  color: var(--fg); margin: 0; background: var(--bg);
  font-size: 14px; line-height: 1.45;
}

/* --- Header / nav --- */
header {
  background: var(--header-bg); color: var(--header-fg);
  padding: .55rem 1.2rem; display: flex; gap: .8rem 1.4rem;
  align-items: center; flex-wrap: wrap;
  border-bottom: 1px solid var(--header-border);
  box-shadow: 0 1px 3px rgba(43,55,75,0.06);
}
header form { display: inline-block; }
header a { color: var(--header-fg); text-decoration: none; font-weight: 500; font-size: .92rem; }
header a:hover { color: var(--accent-dk); }
header a > strong { font-weight: 700; letter-spacing: .02em; color: var(--c-teal); }
/* FieldDay: the D of Day is a half sun, its flat side the stem, at the letters' cap height
   (the half-disc spans .7em), with rays in the site's colours. */
header a.brand > strong { font-size: 1.15rem; white-space: nowrap; }
.brand-d { display: inline-block; width: 0.624em; height: 1.203em; vertical-align: -0.251em;
  margin: 0 .07em 0 .06em; overflow: visible; }
header .spacer { flex: 1; }
header .meta-chip {
  color: var(--muted); font-size: .8rem;
  padding: .2rem .55rem; border-radius: 12px;
  background: rgba(43,55,75,0.07);
}
header form button {
  background: transparent; border: 1px solid var(--border-strong);
  color: var(--header-fg); border-radius: 4px;
}
header form button:hover { background: var(--border); }

/* --- Layout --- */
main { padding: .7rem 1.4rem 2rem; max-width: 1520px; margin: 0 auto; }
body.embed main { padding: .6rem .8rem 1rem; max-width: none; }
body.embed .btn-back { display: none; }
/* --- Sizes: headers and controls -----------------------------------------------------
   Headers come in three sizes: .hdr-l a page title (h1), .hdr-m a section (h2), .hdr-s a
   form header bar or card subhead (h3). Controls (buttons and single-line fields) share one
   height per size, so a button and a field side by side line up: s (table cells, header
   bars, toolbars), m (the default) and l (phone touch targets). Controls in table cells and
   in header bars are always s. A container class (.ctl-s, .ctl-m, .ctl-l) sets the size for
   everything inside it; .btn-s / .btn-l size one button.
   Vertical space goes to documents and tables, so the sizes stay small. */
:root {
  --hdr-l: 1.3rem; --hdr-m: 1.05rem; --hdr-s: .9rem;
  --ctl-h: 2rem; --ctl-fs: .875rem; --ctl-px: .75rem; --fld-px: .5rem;
}
.ctl-s, .btn-s, td, th, header, .sticky-bar, .ps-head, .cmp-bar, .cmp-strip, .rv-clear, .sched-bar, .sched-pickup, .sched-pickup-bar { --ctl-h: 1.625rem; --ctl-fs: .8rem; --ctl-px: .5rem; --fld-px: .35rem; }
.ctl-m { --ctl-h: 2rem; --ctl-fs: .875rem; --ctl-px: .75rem; --fld-px: .5rem; }
.ctl-l, .btn-l { --ctl-h: 2.75rem; --ctl-fs: 1rem; --ctl-px: 1rem; --fld-px: .7rem; }
h1, .hdr-l { font-size: var(--hdr-l); margin: 0 0 .6rem; color: var(--c-navy); font-weight: 700; letter-spacing: -.01em; }
h2, .hdr-m { font-size: var(--hdr-m); margin: .9rem 0 .4rem; color: var(--c-navy); font-weight: 600; }
h3, .hdr-s { font-size: var(--hdr-s); margin: .7rem 0 .3rem; color: var(--c-navy); font-weight: 600; letter-spacing: .02em; text-transform: uppercase; }
h4 { font-size: .9rem; margin: .8rem 0 .3rem; color: var(--fg); }
a { color: var(--accent-dk); }
a:hover { color: var(--c-teal); }

/* --- Tables --- */
table {
  width: 100%; border-collapse: separate; border-spacing: 0;
  border: 1px solid var(--border); border-radius: 6px; overflow: hidden;
  background: #fff;
}
/* Wrap wide tables so they scroll horizontally instead of overflowing the layout */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; border-radius: 6px; }
th, td {
  padding: .55rem .7rem; text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--border); font-size: .87rem;
}
/* Data-entry rows: a row holding a field or button pads its cells just enough around the
   size-s control, so entry tables stay dense. */
tr:has(> td > :is(input, select, button, .btn):not([type="checkbox"], [type="hidden"])) > td {
  padding-top: .15rem; padding-bottom: .15rem; vertical-align: middle; }
tbody tr:last-child td { border-bottom: none; }
th {
  background: var(--bg-soft); color: var(--c-navy);
  font-weight: 600; font-size: .78rem; letter-spacing: .04em;
  text-transform: uppercase;
}
tbody tr:hover { background: #f2f9f8; }

/* --- Messages (flash banners) --- */
.messages { padding: 0; list-style: none; margin: 0 0 1rem; }
/* Grows into the free space up to 13rem, so it never pushes the header onto a new line. */
header form.hdr-search { flex: 1 1 5rem; max-width: 13rem; }
header form.hdr-search input { width: 100%; }
/* The clear (x) button of search boxes: gray, darker on hover. */
input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none;
  width: .75rem; height: .75rem; margin-left: .3rem; cursor: pointer; background: var(--muted);
  -webkit-mask: var(--ic-x) center / contain no-repeat; mask: var(--ic-x) center / contain no-repeat; }
input[type="search"]::-webkit-search-cancel-button:hover { background: var(--fg); }
.field-error { display: block; color: var(--bad); font-size: .8rem; margin-top: .2rem; }
/* Edit lock notes (js/edit_lock.js): a bar at the bottom; while released, a cover that
   takes the next click. */
.lock-bar { position: fixed; z-index: 500; left: 50%; bottom: 1rem; transform: translateX(-50%);
  max-width: min(40rem, calc(100vw - 2rem)); display: flex; align-items: center; gap: .6rem;
  padding: .55rem .9rem; border-radius: 8px; background: #2b374b; color: #fff; font-size: .88rem;
  box-shadow: 0 6px 20px rgb(0 0 0 / .25); }
.lock-bar[hidden] { display: none; }
.lock-bar-x { min-height: 0; padding: 0 .3rem; border: 0; background: none; color: #fff; font-size: 1.1rem; line-height: 1; cursor: pointer; }
.lock-cover { position: fixed; inset: 0; z-index: 499; cursor: pointer; background: rgb(255 255 255 / .35); }
/* Summaries / List on the Projects page (projects/workspace/_lead_toggle.html). */
.lead-toggle { display: inline-flex; gap: .3rem; margin-left: auto; }
/* Search dropdowns (js/search_suggest.js): the top matches under a search box. */
.suggest-host { position: relative; }
.suggest { position: absolute; z-index: 400; top: calc(100% + 4px); left: 0; width: max(100%, 22rem);
  max-width: calc(100vw - 1rem); margin: 0; padding: .25rem; list-style: none; background: #fff;
  border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 6px 20px rgb(0 0 0 / .14); }
.suggest[hidden] { display: none; }
header form.hdr-search .suggest { left: auto; right: 0; }
.suggest li { display: flex; flex-direction: column; gap: .05rem; padding: .35rem .5rem; border-radius: 6px; cursor: pointer; }
.suggest li[aria-selected="true"], .suggest li:hover { background: var(--bg-soft); }
.suggest .suggest-title { font-weight: 600; color: var(--fg); font-size: .88rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.suggest small { color: var(--muted); font-size: .76rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.suggest li.suggest-none { color: var(--muted); cursor: default; font-size: .85rem; }
@media (max-width: 700px) { header .chip-role { display: none; } }
/* Header menus open as popovers: their summaries keep the same box open or closed, so the
   header never changes height (the generic details[open] > summary rule adds a border). */
header details > summary, header details[open] > summary { padding: 0; margin: 0; border: 0; }
.acct { position: relative; }
.acct summary { list-style: none; cursor: pointer; }
.acct summary::-webkit-details-marker { display: none; }
.acct-pop { position: absolute; right: 0; top: 1.8rem; z-index: 200; min-width: 11rem; background: #fff; border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 6px 20px rgb(0 0 0 / .15); padding: .3rem; display: flex; flex-direction: column; }
header .acct-pop a, header .acct-pop button { display: block; width: 100%; text-align: left; padding: .45rem .6rem; border: 0; border-radius: 6px; background: none; font: inherit; font-size: .88rem; color: var(--fg); cursor: pointer; }
header .acct-pop a:hover, header .acct-pop button:hover { background: var(--bg-soft); }
header .acct-pop form { display: block; border-top: 1px solid var(--border); margin-top: .2rem; padding-top: .2rem; }
/* Chevron and refresh drawn as masks, for ::before/::after content. */
:root { --ic-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); }
:root { --ic-x: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E"); }
:root { --ic-refresh: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 12a9 9 0 1 1-3-6.7L21 8'/%3E%3Cpath d='M21 3v5h-5'/%3E%3C/svg%3E"); }
@keyframes ic-spin { to { transform: rotate(360deg); } }
/* Icons from the sprite in _icons.html. */
.ic { width: 1.1em; height: 1.1em; vertical-align: -.2em; flex-shrink: 0;
      fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
/* Flex buttons drop the space between an icon and its text. */
label.btn > .ic:first-child { margin-right: .4em; }
/* Phones do field data entry, desktops review and schedule (D-017). */
@media (min-width: 701px) { header .nav-mobile { display: none; } }
@media (max-width: 700px) { .desk-only { display: none !important; } }
@media (min-width: 701px) { .mobile-only { display: none !important; } }
.bell { position: relative; }
.bell summary { list-style: none; cursor: pointer; position: relative; padding: 0 .2rem; }
.bell summary::-webkit-details-marker { display: none; }
.bell-count { position: absolute; top: -.4rem; right: -.5rem; background: #b0542f; color: #fff; border-radius: 9px; font-size: .65rem; font-weight: 700; padding: 0 .3rem; line-height: 1.4; }
.bell-pop { position: absolute; right: 0; top: 1.8rem; z-index: 200; width: min(24rem, 92vw); max-height: 70vh; overflow-y: auto; background: #fff; color: var(--fg); border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 6px 20px rgb(0 0 0 / .15); padding: .4rem; }
.bell-pop ul { list-style: none; margin: 0; padding: 0; }
.bell-pop li a { display: block; padding: .45rem .5rem; border-radius: 6px; text-decoration: none; color: inherit; font-size: .88rem; }
.bell-pop li a:hover { background: var(--bg-soft); }
.bell-pop li.unread a { font-weight: 600; background: #f2f9f8; }
.bell-pop .bell-head { display: flex; justify-content: space-between; align-items: center; padding: .2rem .4rem .4rem; }
.messages li {
  padding: .65rem .9rem; border-radius: 5px;
  margin-bottom: .3rem; border-left: 4px solid;
  font-size: .9rem;
}
.messages li.success { background: #e6eee6; border-color: var(--c-sage); color: #2e482d; }
.messages li.warning { background: #faf4e4; border-color: var(--c-gold); color: #6e520f; }
.messages li.error   { background: #f6e7e2; border-color: var(--c-coral); color: #7a3520; }
.messages li.info    { background: #dff0ee; border-color: var(--c-teal); color: #155049; }

/* --- Forms --- */
form .field { margin-bottom: 1rem; display: flex; flex-direction: column; gap: .3rem; }
form label {
  font-weight: 600; font-size: .82rem;
  color: var(--c-navy); letter-spacing: .02em;
}
input, select, textarea {
  font: inherit; font-size: var(--ctl-fs); padding: .3rem var(--fld-px);
  border: 1px solid var(--border-strong); border-radius: 5px;
  background: #fff; color: var(--fg);
  transition: border-color .15s, box-shadow .15s;
  max-width: 100%; box-sizing: border-box;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--c-teal);
  box-shadow: 0 0 0 3px rgba(2,169,164,0.18);
}
input[type="checkbox"], input[type="radio"] { width: auto; }
/* Single-line fields take the control height whatever their type (text, number, date,
   time and select render alike). */
input:not([type="checkbox"], [type="radio"], [type="file"], [type="range"], [type="color"], [type="hidden"]),
select { height: var(--ctl-h); padding-top: 0; padding-bottom: 0; }
/* A select is drawn as the dropdown button; dropdown.js draws its list (D-037). */
select:not([multiple]):not([size]) {
  -webkit-appearance: none; appearance: none; cursor: pointer;
  padding-right: calc(var(--fld-px) + .9rem);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%236b7686' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right calc(var(--fld-px) - .05rem) center; background-size: .6rem auto;
  text-overflow: ellipsis;
}
select:disabled { cursor: default; opacity: .65; }
/* Touch-only screens: taps reach the page, which opens the app's list (dropdown.js). */
@media (hover: none) and (pointer: coarse) { select:not([multiple]):not([size]) { pointer-events: none; } }
.dd-list { position: fixed; z-index: 1000; margin: 0; overflow-y: auto; overscroll-behavior: contain;
  background: #fff; color: var(--fg); border: 1px solid var(--border); border-radius: 6px;
  box-shadow: 0 6px 18px rgb(0 0 0 / .15); padding: .2rem; font-size: var(--ctl-fs, .875rem); box-sizing: border-box; }
.dd-list[hidden] { display: none; }
.dd-opt { padding: .3rem .6rem; border-radius: 4px; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dd-opt.dd-in-group { padding-left: 1.2rem; }
.dd-opt:hover, .dd-opt.dd-active { background: var(--bg-soft); }
.dd-opt[aria-selected="true"] { background: var(--c-teal); color: #fff; font-weight: 600; }
.dd-opt[aria-selected="true"].dd-active { box-shadow: inset 0 0 0 2px var(--c-navy); }
.dd-opt[aria-disabled="true"] { color: var(--muted); cursor: default; background: none; }
.dd-group { padding: .35rem .6rem .15rem; font-size: .75em; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
@media (pointer: coarse) { .dd-opt { padding: .6rem .75rem; font-size: 1rem; } }
/* Hover tips for [data-tip] (tip.js). */
.tip { position: fixed; z-index: 1001; margin: 0; max-width: min(22rem, calc(100vw - 8px)); padding: .35rem .55rem;
  border-radius: 6px; background: #2b374b; color: #fff; font-size: .78rem; font-weight: 400; line-height: 1.4;
  white-space: pre-line; text-align: left; letter-spacing: normal; text-transform: none;
  pointer-events: none; opacity: 0; transition: opacity .08s; }
.tip.on { opacity: 1; pointer-events: auto; }
input::-webkit-datetime-edit, input::-webkit-datetime-edit-fields-wrapper { padding: 0; }
/* Checkbox / radio lists rendered by Django's CheckboxSelectMultiple */
form .field > ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: .2rem .9rem; }
form .field > ul li label { font-weight: normal; display: flex; align-items: center; gap: .35rem; font-size: .87rem; cursor: pointer; }
form .field > ul li label:hover { color: var(--accent-dk); }
/* Single boolean checkbox fields — inline with label */
form .field.field-check { flex-direction: row; align-items: center; gap: .5rem; margin-bottom: .55rem; }
form .field.field-check label { margin: 0; cursor: pointer; }
textarea { font-family: inherit; }
.helptext, small.meta { color: var(--muted); font-size: .8rem; }

/* --- Buttons --- */
button, .btn {
  font: inherit; font-size: var(--ctl-fs); line-height: 1.2; min-height: var(--ctl-h);
  padding: .15rem var(--ctl-px); box-sizing: border-box; white-space: nowrap;
  border: 1px solid var(--border-strong); border-radius: 5px;
  background: #fff; cursor: pointer; text-decoration: none;
  color: var(--fg); display: inline-flex; align-items: center; justify-content: center; gap: .3em;
  vertical-align: middle; font-weight: 500;
  transition: background .12s, border-color .12s, transform .05s;
}
button:hover, .btn:hover { background: var(--bg-soft); }
button:active, .btn:active { transform: translateY(1px); }
button.primary, .btn.primary {
  background: var(--c-teal); color: white; border-color: var(--c-teal);
}
button.primary:hover, .btn.primary:hover {
  background: var(--accent-dk); border-color: var(--accent-dk);
}
button.warn, .btn.warn {
  background: var(--c-gold); color: #4f3a0a; border-color: var(--c-gold);
}
button.warn:hover, .btn.warn:hover { background: #c08f19; border-color: #c08f19; }
button.danger, .btn.danger {
  background: var(--c-coral); color: white; border-color: var(--c-coral);
}
button.danger:hover, .btn.danger:hover { background: #b0542f; border-color: #b0542f; }
/* Disabled after the colour variants so it wins over them. */
button:disabled, button:disabled:hover, button.btn:disabled, button.btn:disabled:hover, .btn[aria-disabled="true"] {
  background: #e7e9ee; border-color: #d5d9e1; color: #9aa1ad; cursor: not-allowed; transform: none;
}

/* --- State pills (background chips, inline) --- */
.state-draft, .state-review, .state-approved, .state-sealed,
.state-sent, .state-superseded {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 10px;
  font-size: .76rem;
  font-weight: 600;
  letter-spacing: .02em;
  line-height: 1.5;
  vertical-align: 1px;
}
.state-draft     { background: #eef0f4; color: var(--muted); }
.state-review    { background: #faf4e4; color: #6e520f; }
.state-approved  { background: #e6eee6; color: #3d5f3c; }
.state-sealed    { background: var(--c-teal); color: #fff; }
.state-sent      { background: var(--c-navy); color: #fff; }
.state-superseded{ background: transparent; color: var(--muted); text-decoration: line-through; font-weight: 500; }
/* A form's state in the seal button's place (workflow_tags.seal_state): button-shaped,
   not clickable. */
.seal-state { display: inline-flex; align-items: center; vertical-align: middle; box-sizing: border-box;
  min-height: var(--ctl-h); padding: 0 var(--ctl-px); font-size: var(--ctl-fs);
  border: 1px solid var(--border-strong); border-radius: 5px; font-weight: 500;
  color: var(--muted); background: #fff; white-space: nowrap; cursor: default; }
.seal-state-sealed { border-color: var(--c-teal); color: var(--c-teal); }
.seal-state-superseded { text-decoration: line-through; font-weight: 500; }
/* Cylinder set break progress (CylinderSet.break_progress), same chip shape. */
.prog-none, .prog-partial, .prog-complete {
  display: inline-block; padding: 1px 8px; border-radius: 10px; font-size: .76rem;
  font-weight: 600; letter-spacing: .02em; line-height: 1.5; vertical-align: 1px; white-space: nowrap;
}
.prog-none     { background: #eef0f4; color: var(--muted); }
.prog-partial  { background: #faf4e4; color: #6e520f; }
.prog-complete { background: var(--c-teal); color: #fff; }

/* --- Nav marks: short bars in the logo's ray colours --- */
header a .stage-dot {
  display: inline-block; width: 12px; height: 4px;
  border-radius: 1px; margin-right: .4rem;
  vertical-align: 3px; opacity: .9;
}
header a:hover .stage-dot { opacity: 1; }

/* --- Meta + row --- */
.meta { color: var(--muted); font-size: .85rem; }
.row { display: flex; gap: .8rem; flex-wrap: wrap; align-items: center; }

/* --- Cards --- */
.card {
  border: 1px solid var(--border); border-radius: 8px;
  padding: 1rem 1.2rem; margin-bottom: 1rem;
  background: #fff;
  box-shadow: 0 1px 2px rgba(43,55,75,0.04);
}
.card > h3:first-child { margin-top: 0; }

/* --- Photo grid --- */
/* Photo thumbnails: one column in a narrow pane, up to four as it widens (each at least 200px);
   a click or tap shows the photo full size (lightbox.js). */
.photo-grid { display: grid; gap: .8rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, max(200px, (100% - 2.4rem) / 4)), 1fr)); }
.photo-grid figure { margin: 0; min-width: 0; }
.photo-grid img { display: block; width: 100%; height: 180px; object-fit: cover; border-radius: 4px;
  border: 1px solid var(--border); cursor: zoom-in; }
.photo-grid figcaption { display: flex; justify-content: space-between; gap: .4rem;
  font-size: .8rem; color: var(--muted); margin-top: .3rem; overflow-wrap: anywhere; }
.photo-grid .photo-item[draggable=true] { cursor: grab; }
.photo-grid .photo-cap { flex: 1; min-width: 0; }
.photo-cap-form { flex: 1; display: flex; gap: .3rem; min-width: 0; }
.photo-cap-form[hidden] { display: none; }
.photo-cap-form input { flex: 1; min-width: 0; }
/* A photo's caption row: position picker, caption, ⋮, centred on one line, the picker and ⋮
   one height. */
.photo-grid figcaption, .ff-photo figcaption { align-items: center; }
.photo-pos { order: -1; display: inline-flex; align-items: center; gap: .25rem; font-size: .75rem; color: var(--muted); white-space: nowrap; }
.photo-pos select { --ctl-h: 2rem; width: auto; margin: 0; padding-left: .45rem; }
.photo-grid figcaption .rm-btn, .ff-photo figcaption .rm-btn { width: 2rem; height: 2rem; }
.photo-dragging { opacity: .4; }
/* Shown on touch-only screens (phones, tablets) only. */
.touch-only { display: none !important; }
@media (hover: none) and (pointer: coarse) { .touch-only { display: inline-flex !important; } }
.lightbox { max-width: 96vw; max-height: 96dvh; padding: .5rem; border: 0; border-radius: 8px; background: #111; color: #fff; }
.lightbox::backdrop { background: rgb(0 0 0 / .7); }
.lightbox img { display: block; max-width: calc(96vw - 1rem); max-height: calc(96dvh - 4rem); margin: 0 auto; object-fit: contain; }
.lightbox-cap { margin: .4rem .2rem 0; font-size: .85rem; }
.lightbox-x { position: absolute; top: .35rem; right: .35rem; z-index: 1; border: 0; border-radius: 50%; width: 2.2rem; height: 2.2rem;
  min-height: 0; padding: 0; background: rgb(0 0 0 / .55); color: #fff; display: inline-flex; align-items: center; justify-content: center; }
/* Draggable dividers between a form and its preview (split.js): `.split`/`.review-split` side
   by side, `.vsplit` the form above the preview; each shares the window by --split-a/-b. */
.split-bar { position: relative; z-index: 2; touch-action: none; border-radius: 4px; outline-offset: -2px; }
.split-bar::after { content: ""; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  border-radius: 2px; background: var(--border-strong); }
.split-bar:hover, .split-bar.dragging, .split-bar:focus-visible { background: rgb(42 157 143 / .18); }
.split-bar.v { cursor: col-resize; }
.split-bar.v::after { width: 3px; height: 2.5rem; }
.split-bar.h { cursor: row-resize; }
.split-bar.h::after { width: 2.5rem; height: 3px; }
.split.has-bar, .review-split.has-bar { gap: 0;
  grid-template-columns: minmax(16rem, var(--split-a, 1fr)) 14px minmax(16rem, var(--split-b, 1fr)); }
.vsplit { display: grid; height: calc(100vh - 100px);
  grid-template-rows: minmax(8rem, var(--split-a, 45fr)) 14px minmax(10rem, var(--split-b, 55fr)); }
.vsplit > .form-pane { overflow-y: auto; min-height: 0; padding-right: .3rem; }
.vsplit > .lv { min-height: 0; }
body.split-dragging, body.split-dragging * { user-select: none; }
body.split-dragging iframe { pointer-events: none; }
@media (max-width: 900px) {
  .split.has-bar, .review-split.has-bar { grid-template-columns: 1fr; gap: 1rem; }
  .vsplit { display: block; height: auto; }
  .vsplit > .lv { height: calc(100vh - 4.5rem); min-height: 22rem; margin-top: .8rem; }
  .split-bar { display: none; }
}
.split.readonly.has-bar { grid-template-columns: 1fr; }
.split.readonly > .split-bar { display: none; }

/* --- Details / summary collapsible --- */
details > summary {
  cursor: pointer; padding: .4rem 0;
  font-weight: 600; color: var(--c-navy);
}
details > summary:hover { color: var(--accent-dk); }
details[open] > summary { border-bottom: 1px solid var(--border); margin-bottom: .6rem; }

/* --- Binder sections ---
   <details class="card binder" open> with an index tab in the section color
   sitting on top of the card. Clicking the tab collapses the section to its
   one-line .binder-sum. Pages set --c (section color) per section; --ink is
   the tab text color (navy; white on navy tabs). */
.binder {
  --c: var(--c-navy); --ink: var(--c-navy);
  position: relative; margin-top: 2.7rem;
  border-top: 3px solid var(--c); border-top-left-radius: 0;
}
.binder > summary {
  list-style: none; padding: 0; margin: 0; border: 0;
  font-weight: 400; color: inherit;
}
.binder > summary::-webkit-details-marker { display: none; }
.binder[open] > summary { border: 0; margin: 0; }
.binder > summary:hover { color: inherit; }
.binder-tab {
  position: absolute; bottom: 100%; left: -1px; margin: 0;
  display: flex; align-items: center; gap: .55rem; max-width: calc(100% + 2px);
  background: var(--c); color: var(--ink);
  font-size: 1rem; font-weight: 700; letter-spacing: 0; text-transform: none;
  padding: .42rem 1.05rem .4rem .95rem; border-radius: 9px 9px 0 0;
  white-space: nowrap; user-select: none;
}
.binder-tab::after {
  content: ""; width: .42rem; height: .42rem; margin: -.2rem 0 0 .55rem;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg); opacity: .8; transition: transform .15s;
}
.binder:not([open]) .binder-tab::after { transform: rotate(-45deg); margin-top: 0; }
.binder > summary:hover .binder-tab { filter: brightness(1.06); }
.binder > summary:focus-visible { outline: none; }
.binder > summary:focus-visible .binder-tab { outline: 2px solid var(--c-navy); outline-offset: 2px; }
.binder-sum { display: none; color: var(--muted); font-size: .9rem; }
.binder:not([open]) {
  padding-top: .6rem; padding-bottom: .6rem;
  background: #fff; background: color-mix(in srgb, var(--c) 6%, #fff);
}
.binder:not([open]) .binder-sum { display: block; }

/* --- Tab lines (D-027, core/_tab_lines.html, js/tab_lines.js) ---
   Binder tabs side by side over one panel. A closed line is its tabs on a rule in the
   first tab's color (the first shown, on phones), with the line's summary beside them on desktops. --c is the tab color; --ink
   the tab text (navy; white on navy tabs). */
.tl { margin-top: 1.4rem; }
/* The line under the tabs is a 3px strip (::after) drawn over the tabs' bottom edge: the
   closed line's color, or the open tab's (--c-open) over the panel's top border. Each tab
   runs 2px further down, ending inside the strip at any zoom, and hover lifts it by that
   same 2px with no transition; a raised tab's 2px shadow in its own color, under the
   strip, fills any rounding gap above its line. */
.tl-tabs { display: flex; align-items: flex-end; gap: .3rem; flex-wrap: wrap;
  position: relative; isolation: isolate; }
.tl-tabs:not(.is-open) { border-bottom: 3px solid var(--c-line); }
.tl-tabs::after { content: ""; position: absolute; left: 0; right: 0; bottom: -3px; height: 3px;
  background: var(--c-line); z-index: 1000; pointer-events: none; }
/* Open, the strip is drawn as a copy of the panel's top edge (3px top border, 1px side
   border, 8px corner) laid over it, so the line ends in the panel's rounded corner at
   any zoom. */
.tl-tabs.is-open::after { box-sizing: border-box; height: 10px; bottom: -10px; background: none;
  border-top: 3px solid var(--c-open, var(--c-line)); border-right: 1px solid var(--border);
  border-top-right-radius: 8px; }
.tl-tab {
  --ink: var(--c-navy); --tab-bg: color-mix(in srgb, var(--c) 45%, #fff);
  border: 0; border-radius: 9px 9px 0 0; min-height: 0; margin: 0 0 -2px;
  padding: .38rem 1rem calc(.34rem + 2px); font-size: .95rem; font-weight: 700;
  background: var(--tab-bg); color: var(--c-navy);
  cursor: pointer; white-space: nowrap;
  transition: background .15s ease-out;
}
.tl-tab[aria-selected="true"] { --tab-bg: var(--c); color: var(--ink); padding-top: .46rem; }
.tl-tab.tl-half { padding-left: .7rem; padding-right: .7rem; font-size: .88rem; }
/* Tab sizes (SPEC-19 R6): every tab is small, medium or large. Each is a minimum width in
   em of the tab's own font that fits the longest current label of its size, so the tabs
   of one size match; a longer label later means a wider size, not one wider tab. */
.tab-s, .tab-m, .tab-l { box-sizing: border-box; text-align: center; justify-content: center; }
.tab-s { min-width: 5.8em; }
.tab-m { min-width: 9.5em; }
.tab-l { min-width: 11.2em; }
@media (max-width: 700px) { .tl-tab.tab-s, .tl-tab.tab-m, .tl-tab.tab-l { min-width: 0; } }
/* Eye button: a square icon button that opens a preview. */
.btn-eye { width: var(--ctl-h); height: var(--ctl-h); padding: 0; }
.tl-count { display: inline-block; min-width: 1.15rem; margin-left: .35rem; padding: 0 .3rem; border-radius: 9px;
  background: var(--c-navy); color: #fff; font-size: .7rem; line-height: 1.15rem; text-align: center; vertical-align: .1em; }
.tl-count[hidden] { display: none; }
/* A closed line's first tab (the first shown, on phones) has the line's full color;
   the others stay faded. */
@media (min-width: 701px) {
  .tl-tabs:not(.is-open) .tl-tab.tl-lead, .tl-tabs:not(.is-open) .tl-tab.tl-lead:hover { --tab-bg: var(--c); color: var(--ink); }
}
@media (max-width: 700px) {
  .tl-tabs:not(.is-open) .tl-tab.tl-lead-phone, .tl-tabs:not(.is-open) .tl-tab.tl-lead-phone:hover { --tab-bg: var(--c); color: var(--ink); }
}
/* Hover keeps the tab color and lifts the tab a little, like a folder starting to open.
   background is set again here: .tl-tab alone loses to the generic button:hover gray. */
.tl-tab:hover { --tab-bg: color-mix(in srgb, var(--c) 65%, #fff); transform: translateY(-2px);
  background: var(--tab-bg); box-shadow: 0 2px 0 var(--tab-bg); }
.tl-tab[aria-selected="true"]:hover { --tab-bg: var(--c); }
.tl-tab:focus-visible { outline: 2px solid var(--c-navy); outline-offset: 2px; }
.tl-sum { color: var(--muted); font-size: .88rem; margin: 0 0 .3rem .5rem; align-self: center; }
.tl-tabs.is-open .tl-sum { display: none; }
.tl-panel { --pad-x: 1.2rem; border-top: 3px solid var(--c); border-top-left-radius: 0; margin-bottom: 0; }
/* Rows that run to the panel's edges (tables, strength sets) instead of a box inside it;
   their outer cells keep the panel's padding so text lines up with the rest. */
.tl-rows { margin-left: calc(-1 * var(--pad-x)); margin-right: calc(-1 * var(--pad-x)); }
.tl-rows > table, .tl-rows table.tl-rows-table { width: 100%; }
/* The panel is the frame: an edge-to-edge table draws only its row rules. */
.tl-rows > table { border: 0; border-radius: 0; }
.tl-rows th:first-child, .tl-rows td:first-child { padding-left: var(--pad-x); }
.tl-rows th:last-child, .tl-rows td:last-child { padding-right: var(--pad-x); }
.tl-panel[hidden] { display: none; }
/* Phones: one row of tabs. When they do not fit, tab_lines.js overlaps them like folder
   tabs (.is-stacked, negative margins): each tab lies over the end of the one before it,
   the open one on top. */
@media (max-width: 700px) {
  .tl-tabs { flex-wrap: nowrap; }
  .tl-tabs:not(.is-open) { border-bottom-color: var(--c-line-phone); }
  .tl-tabs:not(.is-open)::after { background: var(--c-line-phone); }
  .tl-tab { flex-shrink: 0; position: relative; }
  .tl-tabs.is-stacked .tl-tab:not(:first-child) { box-shadow: -3px 0 4px -1px rgba(43,55,75,.22); }
  .tl-tabs.is-stacked .tl-tab[aria-selected="true"] { box-shadow: 0 0 5px rgba(43,55,75,.28); }
}

/* --- Action strip (used by PDF detail views) --- */
.action-strip {
  display: flex; gap: .5rem; flex-wrap: wrap; align-items: center;
  padding: .7rem .9rem; background: var(--bg-soft);
  border: 1px solid var(--border); border-radius: 8px;
  margin-bottom: .8rem;
}
.action-strip h2 { margin: 0; font-size: 1.05rem; color: var(--c-navy); text-transform: none; letter-spacing: 0; }
.action-strip .crumbs { font-size: .82rem; color: var(--muted); }
.action-strip .crumbs a { color: var(--accent-dk); text-decoration: none; }
.action-strip .spacer { flex: 1; }

/* --- Form pages: one slim sticky header bar (Back, title, status, actions) and the form
   beside its live view. Everything in the bar is size s; nothing sits above or below it. --- */
.sticky-bar { position: sticky; top: 0; z-index: 10; background: var(--bg-soft); border: 1px solid var(--border);
  border-radius: 6px; padding: .2rem .4rem; margin-bottom: .4rem; display: flex; flex-wrap: wrap; align-items: center;
  gap: .35rem; box-shadow: 0 1px 4px rgba(43,55,75,0.06); }
.sticky-bar h2, .sticky-bar .bar-title { margin: 0; flex: 1; min-width: 180px; font-size: var(--hdr-s); color: var(--c-navy);
  font-weight: 600; letter-spacing: 0; text-transform: none; }
.sticky-bar form { display: inline-flex; margin: 0; }
.sticky-bar > :not(h2, .bar-title, .loc-input) { flex-shrink: 0; }
.save-status { font-size: .75rem; color: var(--muted); opacity: 0; transition: opacity .25s; min-width: 4rem; text-align: right; }
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; height: calc(100vh - 90px); }
.split.readonly { grid-template-columns: 1fr; }
.split.readonly .form-pane { display: none; }
.split .form-pane { overflow-y: auto; padding-right: .5rem; }
.result-pass { color: var(--accent); font-weight: 600; }
.result-fail { color: var(--bad); font-weight: 700; }

/* The reviewer's reason on a returned form, above its header bar. */
.return-note { background: #faf4e4; border: 1px solid #d9a420; border-radius: 6px; padding: .3rem .6rem;
  margin-bottom: .4rem; font-size: .85rem; }
/* A small dialog opened by a [data-open-dialog] button (static/js/base.js). */
.app-dialog { max-width: 32rem; width: calc(100% - 2rem); border: 1px solid var(--border); border-radius: 8px;
  padding: .9rem 1.1rem; }
.app-dialog form { display: grid; gap: .35rem; }
.app-dialog textarea { width: 100%; }
.dialog-actions { display: flex; gap: .5rem; justify-content: flex-end; margin-top: .5rem; }

/* --- Settings tables (keywords, review rules) --- */
.kw-table { width: 100%; border-collapse: collapse; }
.kw-table th, .kw-table td { border-bottom: 1px solid var(--border); padding: .45rem .5rem; text-align: left; vertical-align: middle; }
.kw-table th { font-size: .8rem; color: var(--muted); font-weight: 600; }
.kw-table tr.inactive td { color: var(--muted); }

/* --- PDF iframe pane --- */
.pdf-frame {
  width: 100%; height: calc(100vh - 260px); min-height: 540px;
  border: 1px solid var(--border); border-radius: 6px; background: #fff;
}
@media (max-width: 768px) { .pdf-frame { display: none; } .mobile-pdf-link { display: block !important; } }
.mobile-pdf-link { display: none; }

/* --- Mobile adjustments --- */
@media (max-width: 900px) {
  /* Page header rows wrap their button groups onto a second line */
  main > .row:first-child { flex-direction: column; align-items: stretch !important; gap: .6rem; }
  main > .row:first-child > .row { flex-wrap: wrap; }
}
@media (max-width: 700px) {
  header {
    gap: .5rem .8rem; flex-wrap: wrap; padding: .55rem .7rem;
    font-size: .88rem;
  }
  header a { font-size: .85rem; }
  header .nav-desk { display: none; }     /* desktop-only pages */
  header .meta-chip { font-size: .72rem; padding: .15rem .45rem; }
  header .spacer { flex-basis: 100%; height: 0; }  /* Forces user/logout to next row */
  main { padding: 1rem .7rem 2rem; }
  :root { --hdr-l: 1.15rem; --hdr-m: 1rem; }
  .row { gap: .5rem; }
  .card { padding: .8rem .9rem; }
  .tl-panel { --pad-x: .9rem; }
  th, td { padding: .4rem .5rem; font-size: .82rem; }
  th { font-size: .72rem; }
  /* Wide data tables scroll inside themselves instead of widening the page. */
  main table:not(.sched-table) { display: block; overflow-x: auto; }
  /* Phones: default controls get a little taller for touch. */
  :root { --ctl-h: 2.25rem; }
}
/* Interface text (buttons, labels, tabs, headers, nav) is not selectable and shows the arrow
   or hand, not the text cursor. Other page text keeps the arrow but stays selectable.
   :where() keeps these at zero specificity so any page rule wins. */
:where(body) { cursor: default; }
:where(button, .btn, label, summary, nav, header, th, legend, [role="button"], [role="menuitem"], [role="tab"]) {
  user-select: none; -webkit-user-select: none; cursor: default; }
:where(button, .btn, a[href], summary, select, [role="button"], [role="menuitem"], [role="tab"],
       input[type="checkbox"], input[type="radio"], label:has(> input[type="checkbox"], > input[type="radio"])) { cursor: pointer; }
:where(button:disabled, .btn:disabled) { cursor: not-allowed; }
:where(input:not([type="checkbox"], [type="radio"], [type="button"], [type="submit"]), textarea, [contenteditable="true"]) {
  user-select: text; -webkit-user-select: text; cursor: text; }
/* Live viewer (static/js/viewer.js; toolbar from core/_viewer_bar.html): a toolbar over a
   scrolling box of pages on a grey ground. .lv-fill fills its container (split panes,
   review panes, dialogs). */
.lv { display: flex; flex-direction: column; min-height: 0; border: 1px solid var(--border);
  border-radius: 8px; overflow: hidden; background: #e9ecef; }
.lv-fill { height: 100%; }
@media (max-width: 900px) { .split > .lv-fill, .review-split > .lv-fill { height: calc(100vh - 4.5rem); } }
.lv-bar { display: flex; align-items: center; gap: .6rem; flex-shrink: 0; padding: .3rem .6rem;
  background: #fff; border-bottom: 1px solid var(--border); font-size: .85rem; }
.lv-title, .lv-count { color: var(--muted); font-size: .8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lv-busy { visibility: hidden; color: var(--muted); font-size: .8rem; }
.lv-busy::before { content: ""; display: inline-block; width: .9em; height: .9em; margin-right: .3em; vertical-align: -.1em;
  background: currentColor; -webkit-mask: var(--ic-refresh) center / contain no-repeat; mask: var(--ic-refresh) center / contain no-repeat;
  animation: ic-spin 1s linear infinite; }
.lv.is-busy .lv-busy, .lv:has(.htmx-request) .lv-busy { visibility: visible; }
.lv-tools { margin-left: auto; display: flex; align-items: center; gap: .25rem; }
.lv-tools button { min-height: 0; padding: .15rem .55rem; font-size: .85rem; line-height: 1.4; }
.lv-tools button[data-lv="out"], .lv-tools button[data-lv="in"] { width: 1.9rem; padding: .15rem 0; font-weight: 700; }
.lv-zoom { min-width: 3.2rem; text-align: center; font-variant-numeric: tabular-nums; }
/* The box's content is one column as wide as its widest page (at least the box). viewer.js
   sets each page's width; an iframe or canvas fills it. */
/* touch-action: one finger scrolls natively; a pinch is the viewer's zoom (viewer.js), not the page's. */
.lv-scroll { flex: 1; min-height: 0; overflow: auto; outline: none; padding: 12px 0; cursor: grab; touch-action: pan-x pan-y;
  display: grid; grid-template-columns: minmax(max-content, auto); align-content: start; }
.lv-scroll.is-panning { cursor: grabbing; user-select: none; }
.lp-page { box-sizing: border-box; max-width: none; margin: 0 auto 12px; background: #fff;
  box-shadow: 0 1px 4px rgb(0 0 0 / .18); }
.lp-page > iframe { display: block; width: 100%; height: 100%; border: 0; pointer-events: none; }
.lp-page > canvas { display: block; width: 100%; height: 100%; }
/* The app's confirm and alert dialog (js/confirm.js), styled like the archive dialog. */
.app-confirm { max-width: 30rem; width: calc(100vw - 2rem); box-sizing: border-box; padding: 1.1rem 1.2rem 1rem;
  border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 12px 40px rgb(0 0 0 / .22);
  background: #fff; color: var(--fg); }
.app-confirm::backdrop { background: rgb(0 0 0 / .35); }
.app-confirm p { margin: 0 0 1rem; line-height: 1.45; }
.app-confirm-actions { display: flex; justify-content: flex-end; gap: .5rem; }
.lp-menu { position: fixed; z-index: 300; padding: .25rem; background: #fff; border: 1px solid var(--border);
  border-radius: 8px; box-shadow: 0 6px 20px rgb(0 0 0 / .14); font-size: .85rem; }
.lp-menu button { display: flex; align-items: center; justify-content: space-between; gap: 1.2rem; width: 100%;
  min-width: 10rem; min-height: 0; padding: .35rem .5rem; border: 0; border-radius: 6px; background: none;
  font: inherit; color: var(--fg); text-align: left; cursor: pointer; }
.lp-menu button:hover, .lp-menu button:focus-visible { background: var(--bg-soft, #f3f5f7); outline: none; }
.lp-menu small { color: var(--muted); font-size: .75rem; }
.lp-menu form { margin: 0; }
.rm.rm-right { float: right; }
/* A project-day's forms in a modal (js/day_preview.js): schedule task preview, Reports rows. */
.sched-preview { width: min(860px, calc(100vw - 2rem)); height: calc(100vh - 3rem); max-height: none; padding: 0;
  border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 12px 40px rgb(0 0 0 / .25); overflow: hidden; }
.sched-preview[open] { display: flex; flex-direction: column; }
.sched-preview::backdrop { background: rgb(0 0 0 / .35); }
.sched-preview-head { display: flex; align-items: center; gap: .6rem; padding: .55rem .75rem;
  border-bottom: 1px solid var(--border); background: #fff; }
.sched-preview-head h2 { margin: 0; font-size: 1rem; text-transform: none; letter-spacing: 0; color: var(--fg); }
/* One chip per form in the package; the one in view is marked. */
.sched-preview-tabs { display: flex; flex-wrap: wrap; gap: .25rem; }
.sched-preview-tabs[hidden] { display: none; }
.sched-preview-tabs button { padding: .1rem .5rem; min-height: 0; font-size: .78rem; font-weight: 600; line-height: 1.5;
  border: 1px solid var(--border); border-radius: 999px; background: #fff; color: var(--fg); cursor: pointer; }
.sched-preview-tabs button[aria-current="true"] { background: var(--c-navy, #2b374b); border-color: var(--c-navy, #2b374b); color: #fff; }
.sched-preview-body .pkg-sec + .pkg-sec { margin-top: .8rem; }
.sched-preview-open { margin-left: auto; padding: 0 .6rem; height: 28px; font-size: .82rem; min-height: 0; }
.sched-preview-x { padding: .25rem; min-height: 0; line-height: 1; background: none; border: 0; cursor: pointer; color: var(--muted); }
.sched-preview-x:hover { color: var(--fg); }
.sched-preview-lv { flex: 1; border: 0; border-radius: 0; }
.sched-preview-body { padding: .75rem; }
/* Touch screens: the preview fills the visible screen (dvh leaves out the browser's bars).
   Header, two rows: close, title and Open on one; the form chips on one line that scrolls
   sideways. The viewer's bar floats over the pages' bottom right with the zoom and Fit page;
   − and + give way to pinching. */
@media (hover: none) and (pointer: coarse) {
  .sched-preview { inset: 0; margin: 0; width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh;
    border: 0; border-radius: 0; }
  .sched-preview-head { display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "x title open" "tabs tabs tabs"; gap: .3rem .4rem; padding: .3rem .5rem .4rem; }
  .sched-preview-x { grid-area: x; padding: .35rem; }
  .sched-preview-head h2 { grid-area: title; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .95rem; }
  .sched-preview-open { grid-area: open; margin-left: 0; height: 2rem; padding: 0 .65rem; }
  .sched-preview-tabs { grid-area: tabs; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .sched-preview-tabs::-webkit-scrollbar { display: none; }
  .sched-preview-tabs button { flex-shrink: 0; max-width: 13rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .sched-preview-lv { position: relative; }
  .sched-preview-lv > .lv-bar { position: absolute; right: .5rem; bottom: calc(.5rem + env(safe-area-inset-bottom)); z-index: 2;
    padding: .2rem .3rem; border: 1px solid var(--border); border-radius: 8px; background: rgb(255 255 255 / .94);
    box-shadow: 0 2px 10px rgb(0 0 0 / .18); }
  .sched-preview-lv > .lv-bar .lv-title, .sched-preview-lv > .lv-bar .lv-count,
  .sched-preview-lv > .lv-bar [data-lv="in"], .sched-preview-lv > .lv-bar [data-lv="out"] { display: none; }
  .sched-preview-lv:not(.is-busy):not(:has(.htmx-request)) > .lv-bar .lv-busy { display: none; }
  .sched-preview-lv > .lv-bar .lv-zoom { min-width: 2.6rem; }
}
/* Row ⋮ menus (js/row_menu.js); the menu itself is an .lp-menu. */
.rm { display: inline-block; }
.rm-btn { min-height: 0; width: var(--ctl-h); height: var(--ctl-h); padding: 0; border: 1px solid transparent;
  border-radius: 6px; background: none; color: var(--fg); font-size: 1.15rem; line-height: 1; cursor: pointer; }
.rm-btn:hover, .rm-btn[aria-expanded="true"] { background: var(--bg-soft, #f3f5f7); border-color: var(--border); }
.rm-menu[hidden] { display: none; }
.rm-btn.rm-btn-text { width: auto; height: auto; padding: .35rem .8rem; font-size: inherit; border-color: var(--border); }
.lp-menu a[role="menuitem"] { display: block; min-width: 10rem; padding: .35rem .5rem; border-radius: 6px;
  color: var(--fg); text-decoration: none; }
.lp-menu a[role="menuitem"]:hover, .lp-menu a[role="menuitem"]:focus-visible { background: var(--bg-soft, #f3f5f7); outline: none; }
.lp-menu button.rm-danger { color: var(--bad); }
