/* The production app's one stylesheet: no build step, no web font, nothing from another server
 * (spec 8.1), so a crew page is one small file on one bar of signal.
 *
 * The system, from the design direction of the ux21 pass (review/ux21/reports/design.md):
 *   1. The moment first         .eyebrow .hero .facts .big   what is true now, largest, before the record
 *   2. Six sizes you can see    --t-*                        44 / 24 / 17 / 15 (17 on the phone pages) / 13 / 12 caps
 *   3. Colour is state          --ok --due --warn --bad      done is quiet; loud only where action is due
 *   4. One primary, in reach    .actionbar .saved            on screen on a long page; the result where it was pressed
 *   5. The thing, not the form  .readchange .doc             read first, change in place
 *   6. The gloved thumb         .tap .taps                   every tap on a phone a 48px row
 *   7. Space on a scale         --s1 to --s7                 4 8 12 16 24 32 48
 * A page reaches for these classes; each is described where it is defined, with its markup.
 * tests/DesignTest.php holds the contrast every colour pair here must keep, light, dark and printed. */

/* ---- Tokens ------------------------------------------------------------------------------------ */
:root {
  color-scheme: light dark;
  /* Colour. The palette stays calm and warm, and terracotta is the one accent, for the primary action. */
  --bg: #fbfaf8; --panel: #ffffff; --fill: #f3f0eb;
  --ink: #1c1b19;      /* what is read: 15 to 1 or more on every background (12.4 at night) */
  --muted: #6b6760;    /* when, by whom, the secondary line: 4.9 to 1 at least (5.2 at night) */
  --rule: #e6e2dc;     /* a hairline between rows and round a panel. It separates nothing a person has to find, so it stays light. */
  --field: #837c72;    /* the edge of anything pressed, typed into or dragged: 3.5 to 1 or more on every background, visible in sun (was --rule, 1.29 to 1) */
  --accent: #b5452f; --accent-ink: #ffffff;
  /* State, and it means the same wherever it appears. Each has a tint for a band or a chip. */
  --ok: #2f7a47;   --ok-fill: #e9f3ec;     /* done: confirmed, signed, sent. Said small; finished things are quiet. */
  --due: var(--field);                      /* needs doing, and nothing is wrong yet: drawn hollow, an empty box to fill */
  --warn: #8a5c0a; --warn-fill: #fbf1dd;   /* warning, look before the call: 5.1 to 1 on its tint (was #9a6a12, 4.16 on the fill) */
  --bad: #b3261e;  --bad-fill: #fbecea;    /* trouble, act now */
  /* The stripboard's industry colours: INT day white, EXT day yellow, INT night blue, EXT night green. */
  --strip-int-d: #ffffff; --strip-ext-d: #fff4b8; --strip-int-n: #cfe0ff; --strip-ext-n: #cdeccf; --strip-set: #f3e8ff;
  --strip-ink: #1c1b19; --strip-muted: #5a564f;
  /* Type: six sizes, set as the call sheet PDF sets them. Rem, so a larger default text size scales them all. */
  --t-display: 2.75rem;   /* 44px: a call time, the crew call */
  --t-title: 1.5rem;      /* 24px: what the page is about (the day, the person) */
  --t-head: 1.0625rem;    /* 17px: a section */
  --t-body: .9375rem;     /* 15px: what is read at a desk; 17px on a crew, signing or set page, below */
  --t-meta: .8125rem;     /* 13px: when, by whom, the fingerprint */
  --t-label: .75rem;      /* 12px in capitals: a field's name, as the call sheet sets LOCATION and PARKING */
  /* Space. A margin, padding or gap is one of these, apart from the pixel or two that places a hairline or
     a mark, the 6px inside the densest rows (a table cell's sides at a desk, a strip, a shot row, a ledger
     line, all set at their widths), a list's indent, and a hit area widened without taking room. */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px; --s7: 48px;
  --radius: 8px; --r-control: 8px; --r-card: 12px;
  /* One height for a field and a button, so a row of them lines up: 44px at a desk, 48px under a thumb.
     A compact action at the end of a line in a list is 32px at a desk, and 48px under a thumb like the rest. */
  --h-control: 44px; --h-compact: 32px;
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #151413; --panel: #1d1c1a; --fill: #25231f;
    --ink: #ece9e4; --muted: #9c978f; --rule: #33302c;
    --field: #807a72;
    --accent: #e0765f; --accent-ink: #151413;
    --ok: #6cc38a;   --ok-fill: #1c2a21;
    --warn: #e0b35a; --warn-fill: #2b2418;
    --bad: #f08a80;  --bad-fill: #2a1d1b;
    /* The same strip hues, dimmed, so the board is not the brightest thing in a dark room. */
    --strip-int-d: #33302c; --strip-ext-d: #4d4520; --strip-int-n: #2c3b57; --strip-ext-n: #2e4a33; --strip-set: #3b3050;
    --strip-ink: #ece9e4; --strip-muted: #c2bdb4;
  }
}
/* A crew, signing or set page is a phone page at any width: text at 17px, the call at 56, and every
   control a 48px row for a thumb (principle 6). An office page on a phone keeps its 15px text, since its
   tables were set for it and grew wider than a 320px screen at 17, but its controls are 48px rows too,
   and its fields are 17px, which also keeps iOS from zooming into one when it is pressed. */
@media (max-width: 640px) { :root { --h-control: 48px; --h-compact: 48px; } }
body.crew { --t-body: 1.0625rem; --t-display: 3.5rem; --h-control: 48px; --h-compact: 48px; }

/* ---- Base -------------------------------------------------------------------------------------- */
* { box-sizing: border-box; }
/* Hidden means hidden: without this, a class that sets display (a row, a button) would show
   an element the page has hidden. */
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body { margin: 0; background: var(--bg); color: var(--ink); font: var(--t-body)/1.45 var(--font); font-variant-numeric: tabular-nums; }
a { color: inherit; text-underline-offset: .2em; }   /* clear of the descenders, and the same as a quiet button's beside it */
main { max-width: 980px; margin: 0 auto; padding: var(--s5) var(--s4) var(--s7); }
/* A link to a place on the page lands with room above it, not against the top edge. */
:target { scroll-margin-top: var(--s5); }
h1 { font-size: var(--t-title); line-height: 1.2; letter-spacing: -.012em; margin: 0 0 var(--s2); }
h2 { font-size: var(--t-head); line-height: 1.3; margin: var(--s6) 0 var(--s3); }
h3 { font-size: var(--t-head); line-height: 1.3; margin: var(--s5) 0 var(--s2); }
/* A paragraph's space is below it, so a label hugs its text; after a field, a table, a form or a block,
   a paragraph keeps the room above it that the pages were written with (it was the browser's 1em). */
p { margin: 0 0 var(--s2); }
:is(input, select, textarea, button, table, form, div, ul, ol, dl, details, fieldset, section, nav, hr, img) + p { margin-top: var(--s3); }
.muted { color: var(--muted); }
.small { font-size: var(--t-meta); }   /* a real step now: 13px beside 15, where it was 14.08 */
.meta { font-size: var(--t-meta); color: var(--muted); }
.nw { white-space: nowrap; }   /* a time never breaks between its digits and PM */
.fingerprint { font-size: var(--t-meta); line-height: 1.4; color: var(--muted); }
.linkbox { font: var(--t-meta)/1.4 ui-monospace, Menlo, monospace; word-break: break-all; background: var(--fill); padding: var(--s1) var(--s2); border-radius: var(--r-control); }

/* ---- The frame: the bar, the sections, the page ------------------------------------------------ */
header.bar { border-bottom: 1px solid var(--rule); background: var(--panel); }
header.bar .in { max-width: 980px; margin: 0 auto; padding: var(--s2) var(--s4); display: flex; flex-wrap: wrap; gap: var(--s1) var(--s4); align-items: center; min-height: 56px; }
header.bar .in > * { white-space: nowrap; }   /* a name or "Sign out" moves down whole on a phone, never broken over two lines */
header.bar .in > a { padding: var(--s1) 0; }   /* a link on its own gets a target of 24px or more at a desk (WCAG 2.5.8) */
@media (max-width: 640px) { header.bar .in > a { display: inline-flex; align-items: center; min-height: var(--h-control); padding: 0; } }
header.bar .brand { font-weight: 650; text-decoration: none; }
header.bar .sp { flex: 1; }
header.bar form { margin: 0; }
/* Over a production's frame the bar is as wide as the frame, so the brand sits over the sections and
   Sign out ends where the page does (it was 980px over 1240: the brand 120px right of the column). */
header.bar .in.wide { max-width: 1240px; }
.flash { background: var(--fill); border: 1px solid var(--rule); border-left: 3px solid var(--accent); padding: var(--s3); border-radius: var(--radius); margin: var(--s3) 0; }

/* Production frame: a sidebar of sections on a laptop, a scrolling strip on a phone. */
main.wide { max-width: 1240px; }
.frame { display: grid; grid-template-columns: 190px minmax(0, 1fr); gap: var(--s5); align-items: start; }
.side { position: sticky; top: var(--s3); display: flex; flex-direction: column; }
.side .tabs { display: flex; flex-direction: column; gap: 2px; }
.side a { text-decoration: none; padding: var(--s2) var(--s3); border-radius: var(--r-control); color: var(--muted); }
.side .tabs a { display: flex; justify-content: space-between; align-items: center; gap: var(--s2); }
.side a:hover { background: var(--fill); color: var(--ink); }
.side a.on { background: var(--fill); color: var(--ink); font-weight: 600; }
.side a .n { font-size: var(--t-meta); color: var(--muted); font-weight: 500; }   /* a count beside a section: People 1 */
.side .ptitle { color: var(--ink); font-weight: 700; margin-bottom: var(--s1); }
.side .tag { margin: 0 var(--s3) var(--s2); align-self: flex-start; }
.side .sep { height: 1px; background: var(--rule); margin: var(--s2) var(--s3); flex: none; }   /* between the day's work, the money and the settings */
@media (min-width: 761px) {
  /* The brand's words start where the sections' words do. */
  header.bar .in.wide .brand { padding-left: var(--s3); }
}
.content { min-width: 0; }
@media (max-width: 760px) {
  .frame { grid-template-columns: minmax(0, 1fr); gap: var(--s3); }
  .side { position: static; flex-direction: row; flex-wrap: wrap; align-items: center; gap: 0 var(--s2); }
  /* Which production this is, said small above the sections, since a section's title alone does not say. */
  .side .ptitle { padding: 14px 0; margin: -14px 0 -10px; font-size: var(--t-label); font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); background: none; }   /* a 44px target that takes one line: the row below is on top where they meet */
  .side .tag { margin: 0; }
  /* The sections scroll sideways. A shadow at an edge says there are more that way, and the one open is
     scrolled into view (project/frame.php). The covers travel with the row and hide each shadow at its end. */
  .side .tabs { flex: 1 0 100%; flex-direction: row; gap: 2px; overflow-x: auto; white-space: nowrap; position: relative; margin-top: var(--s1);
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
    background:
      linear-gradient(to right, var(--bg) 40%, transparent) left center / 32px 100% no-repeat local,
      linear-gradient(to left, var(--bg) 40%, transparent) right center / 32px 100% no-repeat local,
      radial-gradient(farthest-side at 0 50%, rgba(0, 0, 0, .22), transparent) left center / 14px 100% no-repeat scroll,
      radial-gradient(farthest-side at 100% 50%, rgba(0, 0, 0, .22), transparent) right center / 14px 100% no-repeat scroll; }
  .side .tabs::-webkit-scrollbar { display: none; }
  .side .tabs a { flex: none; min-height: var(--h-control); padding: var(--s2) var(--s3); }
  .side .sep { width: 1px; height: auto; margin: var(--s3) var(--s1); align-self: stretch; }
}
@media (max-width: 760px) and (prefers-color-scheme: dark) {
  .side .tabs { background:
      linear-gradient(to right, var(--bg) 40%, transparent) left center / 32px 100% no-repeat local,
      linear-gradient(to left, var(--bg) 40%, transparent) right center / 32px 100% no-repeat local,
      radial-gradient(farthest-side at 0 50%, rgba(255, 255, 255, .2), transparent) left center / 14px 100% no-repeat scroll,
      radial-gradient(farthest-side at 100% 50%, rgba(255, 255, 255, .2), transparent) right center / 14px 100% no-repeat scroll; }
}

/* ---- Panels, tables and fields ----------------------------------------------------------------- */
.panel { background: var(--panel); border: 1px solid var(--rule); border-radius: var(--radius); padding: var(--s4); margin: var(--s3) 0; }
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: var(--s2) 6px; border-top: 1px solid var(--rule); vertical-align: middle; }
/* A column's name is a label, set as the call sheet sets its labels. */
th { font-weight: 650; font-size: var(--t-label); letter-spacing: .06em; text-transform: uppercase; color: var(--muted); border-top: 0; }
th button, th .button { text-transform: none; letter-spacing: normal; }
/* On a phone a table's cells sit closer, since a column's name in capitals is wider than it was in
   small letters and a one-word name sets how narrow its column can go. */
@media (max-width: 640px) { th, td { padding-left: var(--s1); padding-right: var(--s1); } th { letter-spacing: .03em; } }
tr:first-child > td { border-top: 0; }   /* a table with no header row starts without a rule above it */
tr.total th { color: var(--ink); font-size: inherit; font-weight: 700; letter-spacing: normal; text-transform: none; border-top: 1px solid var(--rule); }   /* a total reads as the sum, not as a heading */
.qr { width: 200px; margin: var(--s1) 0 var(--s3); } .qr svg { display: block; width: 100%; height: auto; }
.phone-step { display: none; }
@media (max-width: 600px) and (pointer: coarse) { .qr-step { display: none; } .phone-step { display: block; } }
input, select, textarea, button { font: inherit; color: inherit; }
@media (max-width: 640px) { input, select, textarea { font-size: var(--t-head); } }
input[type=text], input[type=email], input[type=tel], input[type=date], input[type=time], input[type=datetime-local], input[type=number], input[type=search], input[type=url], select, textarea {
  background: var(--panel); border: 1px solid var(--field); border-radius: var(--r-control); padding: var(--s2) var(--s3); width: 100%; }
textarea { min-height: 64px; }
/* A dropdown drawn by the page, the height of the text fields beside it; the system's own is
   shorter in Safari, which put labels and controls at uneven heights in every row. */
input[type=text], input[type=email], input[type=tel], input[type=date], input[type=time], input[type=datetime-local], input[type=number], input[type=search], input[type=url] { min-height: var(--h-control); }
select { -webkit-appearance: none; appearance: none; padding-right: 28px; min-height: var(--h-control);
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 15px) 50%, calc(100% - 10px) 50%; background-size: 5px 5px; background-repeat: no-repeat; }
label { display: block; font-size: var(--t-meta); color: var(--muted); margin-bottom: var(--s1); }
/* A field that cannot change says so by looking it, not only when someone tries. */
input[readonly] { background: var(--fill); color: var(--muted); cursor: default; }
/* Boxes to tick at 18px, where they were the browser's 12, in ink: the system blue was the only blue in the app. */
input[type=checkbox], input[type=radio] { accent-color: var(--ink); width: 18px; height: 18px; }
.grid { display: grid; gap: var(--s3); grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
.grid > * { min-width: 0; }
/* Where a grid is down to one column, a field set to span two takes the row: spanning two there made
   the grid grow a second, narrower column, lopsided at 390 wide and off the screen at 320. */
@media (max-width: 760px) { .grid > [style*="span 2"] { grid-column: 1 / -1 !important; } }
.row { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }
.row > select { width: auto; }   /* a dropdown beside its field and button takes its own width, not the row's */

/* ---- Buttons ------------------------------------------------------------------------------------ */
button, .button { display: inline-block; border: 1px solid var(--field); background: var(--panel); border-radius: var(--r-control); padding: var(--s2) var(--s4); min-height: var(--h-control); cursor: pointer; text-decoration: none; text-align: center; }
a.button { display: inline-flex; align-items: center; justify-content: center; }
button.primary, .button.primary { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); font-weight: 600; }
/* A small button is a compact one at a desk: an action at the end of a line in a list. */
button.small, .button.small { min-height: var(--h-compact); padding: var(--s1) var(--s3); }
/* In a row with fields, a button is as tall as they are, small or not, so the row lines up. */
.row:has(> input:not([type=hidden]), > select) > :is(button, .button) { min-height: var(--h-control); }
/* Quiet: an action that is there but not the point, drawn as the words themselves. */
button.quiet, .button.quiet { border-color: transparent; background: transparent; text-decoration: underline; text-underline-offset: .2em; padding-left: 0; padding-right: 0; min-width: var(--h-compact); }   /* "Set" is still a target, not the width of its word */
button.quiet[aria-label] { text-decoration: none; }   /* a quiet button named for the reader alone (× for "Remove the tripod") is a mark, not words to underline */
/* Disabled looks it: no colour, no edge, and the words still readable, since a disabled button often
   says what to do first ("Tick someone to invite"). It looked pressable before. */
:is(button, .button):is(:disabled, [aria-disabled="true"]), fieldset:disabled button { background: var(--fill); border-color: var(--rule); color: var(--muted); cursor: not-allowed; }
:is(button, .button).quiet:is(:disabled, [aria-disabled="true"]) { background: transparent; border-color: transparent; text-decoration: none; }
:is(input, select, textarea):disabled { background: var(--fill); border-color: var(--rule); color: var(--muted); cursor: not-allowed; opacity: 1; -webkit-text-fill-color: var(--muted); }
/* One focus ring: the app had none of its own. A field shows it whenever it has focus, as a text field
   always has (a date or time field is focused in its parts, which never counts as the keyboard's); a
   link, a button or a box to tick shows it only for the keyboard. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible,
:where(input:not([type=checkbox]):not([type=radio]):not([type=file]), select, textarea):focus { outline: 2px solid var(--accent); outline-offset: 2px; }
details summary { cursor: pointer; }
.danger { color: var(--bad); }

.tag { display: inline-block; font-size: var(--t-meta); line-height: 1.4; padding: 1px var(--s2); border-radius: 99px; background: var(--fill); border: 1px solid var(--rule); color: var(--muted); }
.k-confirmed { color: var(--ok); } .k-problem, .k-failed, .k-declined { color: var(--bad); } .k-manual, .k-removed { color: var(--warn); } .k-untold { color: var(--muted); }
td.time input { width: 132px; }
/* The day's calls: the boxes to pick several for a shift show only while shifting, and a time
   for someone not called is shown faint, since it is not sent. */
table.calls:not(.picking) .pick-col { display: none; }
/* The publish preview says what Tell everyone does, once it is ticked. */
.preview-tell { display: none; }
form:has(input[name=tell_everyone]:checked) .preview-tell { display: block; }
form:has(input[name=tell_everyone]:checked) .preview-quiet { display: none; }
table.calls tr:has(input[name^="called"]:not(:checked)) td.time input { opacity: .45; }
@media (max-width: 640px) { .hide-sm { display: none; } }
/* A table whose last cell holds buttons reads as a list on a phone: each row its own block. */
@media (max-width: 480px) { table.stack, table.stack tbody, table.stack tr, table.stack td { display: block; }
  table.stack tr { border-top: 1px solid var(--rule); padding: var(--s2) 0; } table.stack tr:first-child { border-top: 0; }
  table.stack td { border-top: 0; padding: 2px 0; } }

/* ---- Crew page: a phone, outdoors, possibly gloved, possibly at 5 AM (spec 12.3) --------------- */
body.crew main { max-width: 560px; padding-top: var(--s4); }
.card { background: var(--panel); border: 1px solid var(--rule); border-radius: var(--r-card); padding: var(--s4); margin: var(--s4) 0; }
.card .call { font-size: var(--t-display); font-weight: 750; letter-spacing: -.025em; line-height: 1.05; margin: var(--s1) 0 2px; }
.card .when { font-size: var(--t-head); font-weight: 600; }
.card dl { display: grid; grid-template-columns: 7.5em 1fr; gap: var(--s1) var(--s3); margin: var(--s3) 0; }
.card dt { color: var(--muted); } .card dd { margin: 0; }
.changed { background: var(--warn-fill); border-left: 3px solid var(--warn); padding: var(--s3); border-radius: var(--r-control); margin: var(--s3) 0; }
.card button { width: 100%; padding: var(--s3); font-size: var(--t-head); margin-top: var(--s2); }
.confirmed { color: var(--ok); font-weight: 650; font-size: var(--t-head); margin-top: var(--s3); }
/* Small actions inside a card stay small: Remove, New address, a shot's Save. */
.card button.small, .card .shotrow button { width: auto; padding: var(--s2) var(--s3); font-size: var(--t-meta); margin-top: 0; }
.card a.button { display: flex; text-align: center; padding: var(--s3); font-size: var(--t-head); margin-top: var(--s2); }
.card a.button.small { display: inline-flex; align-items: center; padding: var(--s2) var(--s3); font-size: var(--t-meta); margin-top: 0; }
/* A thumb's worth for everything pressed on a phone: 48px, where it was Apple's minimum of 44. */
body.crew input[type=text], body.crew input[type=email], body.crew input[type=tel], body.crew input[type=date], body.crew select { min-height: var(--h-control); }
body.crew details > summary { padding: var(--s3) 0; line-height: 24px; }   /* a 48px row, whatever the size of its words */
body.crew button { min-height: var(--h-control); }
body.crew label.row:has(> input[type=checkbox]), body.crew label.row:has(> input[type=radio]) { min-height: var(--h-control); padding: var(--s3) 0; }
body.crew label.row > input[type=checkbox], body.crew label.row > input[type=radio] { width: 20px; height: 20px; margin-top: 2px; }
/* A guardian's details are asked for once the box says under 18, where the browser can tell. */
@supports selector(:has(*)) { .minor-fields { display: none; } form:has(input[name=is_minor]:checked) .minor-fields { display: block; } }
/* The departments someone runs are asked for once their access says department head. */
@supports selector(:has(*)) { .dept-fields { display: none; } form:has(select[name=access] option[value=department]:checked) .dept-fields { display: block; } }
/* A quiet action that ends or replaces something sits apart from the ones beside it. */
.row > .away { margin-left: auto; }
.row > form.away { margin: 0 0 0 auto; }
/* A tick box keeps its words beside it on a narrow phone instead of wrapping below. */
label.row:has(> input[type=checkbox]), label.row:has(> input[type=radio]) { flex-wrap: nowrap; align-items: flex-start; }
label.row > input[type=checkbox], label.row > input[type=radio] { flex: 0 0 auto; margin-top: 2px; }
/* Have or need: the pressed half says the state, in its own colour, without shouting. */
.seg button { flex: 1; color: var(--muted); border-width: 2px; }
/* A department head's element: one row, have or need beside it, its note a tap on the name away. */
body.crew .dept-el { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s1) var(--s3); align-items: start; border-top: 1px solid var(--rule); padding: var(--s2) 0; margin-top: var(--s1); }
body.crew .dept-el details > summary { list-style: none; padding: 2px 0; line-height: inherit; }   /* a name over its note, not a 48px row */
body.crew .dept-el details > summary::-webkit-details-marker { display: none; }
body.crew .dept-el summary > * { display: block; }
body.crew .dept-el .linkish { display: inline; color: var(--accent); }
body.crew .dept-el .el-said { color: var(--ink); margin-top: 2px; }
body.crew .dept-el details[open] .el-said { display: none; }
body.crew .dept-el .seg { flex-wrap: nowrap; gap: 0; }
body.crew .dept-el .seg button { flex: 0 0 auto; width: auto; margin-top: 0; padding: var(--s2) var(--s3); min-width: 64px; font-size: var(--t-body); }
body.crew .dept-el .seg button:first-child { border-radius: var(--r-control) 0 0 var(--r-control); }
body.crew .dept-el .seg button:last-child { border-radius: 0 var(--r-control) var(--r-control) 0; margin-left: -2px; }
body.crew .dept-el details form { grid-column: 1 / -1; margin-top: var(--s2); }
.seg button[aria-pressed="true"] { background: var(--fill); border-color: currentColor; font-weight: 650; }
.seg .need[aria-pressed="true"] { color: var(--warn); } .seg .have[aria-pressed="true"] { color: var(--ok); }
.contact a { font-weight: 600; }

/* ---- Warnings a page lists ------------------------------------------------------------------------ */
ul.problems { margin: var(--s1) 0 0; padding-left: 18px; font-size: var(--t-meta); }
ul.problems li.error { color: var(--bad); } ul.problems li.warn { color: var(--warn); } ul.problems li.info { color: var(--muted); }
/* Where a warning comes from, under it. It is grey only when it is not itself a warning: the state
   classes at the end of this file win over it, so a conflict marked "origin warn" is amber. */
.origin { font-size: var(--t-meta); color: var(--muted); display: block; margin-top: 2px; }

/* ---- Breakdown ------------------------------------------------------------------------------------ */
.bd { display: grid; grid-template-columns: 220px 1fr; gap: var(--s4); align-items: start; }
.bd-scenes { display: flex; flex-direction: column; gap: 2px; position: sticky; top: var(--s3); max-height: 80vh; overflow: auto; }
.bd-scenes a { text-decoration: none; padding: var(--s1) var(--s2); border-radius: var(--r-control); font-size: var(--t-body); color: var(--muted); }
.bd-scenes a.on, .bd-scenes a:hover { background: var(--fill); color: var(--ink); }
/* A category keeps the colour the breakdown gives it, as a dot beside its name: white words on its
   fill were as low as 2.39 to 1 (Vehicles, pink). */
.cat { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-meta); font-weight: 600; line-height: 1.4; padding: 0 var(--s2); border-radius: 99px; color: var(--ink); background: var(--panel); border: 1px solid var(--rule); margin-right: 6px; }
.cat::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--c); flex: none; }
.el { display: inline-flex; align-items: center; gap: 2px; background: var(--fill); border: 1px solid var(--rule); border-radius: var(--r-control); padding: 1px var(--s1) 1px var(--s2); margin: 2px var(--s1) 2px 0; font-size: var(--t-body); }
.el .x { border: 0; background: none; padding: 0 var(--s1); cursor: pointer; color: var(--muted); min-height: 0; }
.el form { display: inline; }
/* Need or have: the state in its own colour, never a row of alarms. */
button.need-it { color: var(--warn); } button.have-it { color: var(--ok); }
@media (max-width: 760px) { .bd { grid-template-columns: 1fr; } .bd-scenes { position: static; flex-direction: row; overflow-x: auto; } }

/* ---- Shots: the places fixer's block (review/ux21, the places surface) ---------------------------
 * A shot is its words, with Change beside them (the .readchange component); the fields are labelled
 * and set in a grid that wraps by the room it has, not the window's: the seven-column row it replaces
 * gave the description 20px in the crew column at 768px and wider (ux21, A12).
 *    <nav class="shotdays"><a aria-current="page">Tue Oct 6 · 4 scenes, 9 shots</a>…<a>All scenes</a></nav>
 *    <ol class="shots" data-scene="10"><li class="shot"><section class="readchange shot-read">…</section></li></ol> */
.shotdays { display: flex; flex-wrap: wrap; gap: var(--s2); margin: var(--s3) 0 var(--s4); }
.shotdays a { display: inline-flex; align-items: center; min-height: var(--h-compact); padding: var(--s1) var(--s3); border: 1px solid var(--field); border-radius: 999px;
  background: var(--panel); color: var(--ink); text-decoration: none; font-size: var(--t-meta); font-weight: 600; }
.shotdays a[aria-current="page"] { background: var(--ink); border-color: var(--ink); color: var(--bg); }
.shotdays a.over:not([aria-current]) { color: var(--muted); border-style: dashed; }
@media (max-width: 640px) {
  .shotdays { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-left: calc(-1 * var(--s4)); margin-right: calc(-1 * var(--s4)); padding: 0 var(--s4);
    background: linear-gradient(to right, var(--bg) 40%, transparent) left center / 24px 100% no-repeat local,
      linear-gradient(to left, var(--bg) 40%, transparent) right center / 24px 100% no-repeat local,
      radial-gradient(farthest-side at 0 50%, rgba(0, 0, 0, .2), transparent) left center / 12px 100% no-repeat scroll,
      radial-gradient(farthest-side at 100% 50%, rgba(0, 0, 0, .2), transparent) right center / 12px 100% no-repeat scroll; }
  .shotdays::-webkit-scrollbar { display: none; }
  .shotdays a { flex: none; white-space: nowrap; }
}
.scenehead { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) var(--s2); margin: 0 0 var(--s2); font-size: var(--t-head); }
.scenehead .n { font-weight: 750; }
ol.shots { list-style: none; margin: 0; padding: 0; }
ol.shots > li.shot { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3); padding: var(--s3) 0; border-top: 1px solid var(--rule); }
ol.shots > li.shot:first-child { border-top: 0; padding-top: var(--s1); }
ol.shots[data-order] > li.shot { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
ol.shots[data-order] > li.shot > .shot-move { order: 2; }
.shot-read { padding: 0; border-top: 0; }
.shot-head { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 2px var(--s3); }
.shot-no { font-size: var(--t-head); }
.setup-no { font-size: var(--t-label); font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.shot-fields { color: var(--muted); }
.shot-headline { margin: 0; }
.shot-what { margin: var(--s1) 0 0; max-width: 62ch; }
.shot-notes { margin: var(--s1) 0 0; font-size: var(--t-meta); max-width: 62ch; }
.shot-ref { display: inline-block; margin-top: var(--s2); }
.shot-ref img { display: block; max-width: min(100%, 240px); max-height: 160px; border-radius: var(--r-control); }
.shotform-fields { display: grid; grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr)); gap: 0 var(--s3); }
.shotform textarea { min-height: 0; }
details.shotadd { margin-top: var(--s3); border-top: 1px solid var(--rule); }
details.shotadd > summary { display: flex; align-items: center; min-height: var(--h-control); font-weight: 600; }
.shotorder { margin: 0 0 var(--s3); }
/* Dragged by its grip, or moved with ▲ ▼, within its own scene. The grip takes the finger, so the page
   does not scroll under a drag; the arrows are the keyboard's, and the page's without its script. */
.shot-move { display: flex; align-items: center; gap: var(--s1); }
.shot-move .grip { width: 32px; height: var(--h-control); cursor: grab; touch-action: none; flex: none; box-sizing: border-box; padding: 12px 8px;
  background: radial-gradient(circle, var(--muted) 1.6px, transparent 2.2px) 0 0 / 8px 8px content-box; background-clip: content-box; }
.shot-move button { width: auto; min-width: var(--h-control); margin: 0; padding: 0; text-decoration: none; font-size: var(--t-body); }
/* In a crew card a button is the card's width; a shot's Save and Delete sit on one line, as the office's do. */
.card .shotform .row > button, .card .gearedit + form button.quiet, .card form > button.quiet { width: auto; }
li.shot.dragging { background: var(--fill); outline: 2px solid var(--accent); border-radius: var(--r-control); }

/* ---- Gear on a department head's link: the places fixer's block ------------------------------------
 * Each rental once, its kind, whether it is out, when it goes back and who to call; then the lines.
 *    <section class="card gearfrom"><p class="eyebrow"><b>Trade</b></p><h2 class="gearfrom-name">Lumen</h2>…</section> */
.gearfrom .eyebrow { margin-bottom: var(--s1); }
.gearfrom-name { margin: 0 0 var(--s1); font-size: var(--t-title); line-height: 1.2; }
.gearfrom-state { margin: 0 0 var(--s2); font-weight: 600; }
.gearlist { margin-top: var(--s2); }
.gearlist .readchange { padding: 0; border-top: 0; }
.gearedit-row { align-items: flex-end; }
.gearedit-row > p { flex: 1 1 8rem; margin: 0 0 var(--s2); }
details > summary.add { display: flex; align-items: center; min-height: var(--h-control); font-weight: 600; }

/* ---- Places: the places fixer's block ----------------------------------------------------------------
 * A shared place's details, words first with Change on each block (the .readchange component), and what
 * another production changed shown as the change itself, the words as they were struck through and the
 * words as they are (ux21, A13).
 *    <section class="check"><p class="eyebrow"><b>To check</b> · Bodega Liquor</p><div class="checkitem">…
 *      <div class="diff"><p class="was"><span class="lbl">Was</span><del>…</del></p><p class="now">…<ins>…</ins></p></div></div></section> */
.check { border: 1px solid var(--warn); border-left-width: 4px; border-radius: var(--r-card); background: var(--panel); padding: var(--s4); margin: 0 0 var(--s4); }
.card > .check { border: 0; border-left: 0; padding: 0; margin: 0; }
.card:has(> .check) { border-color: var(--warn); border-left: 4px solid var(--warn); }
.check .eyebrow b { color: var(--warn); }
.checkitem { padding: var(--s3) 0; border-top: 1px solid var(--rule); }
.checkitem:first-of-type { border-top: 0; padding-top: var(--s1); }
.checkwhat { margin: 0; }
.diff { display: grid; gap: var(--s2); margin-top: var(--s2); }
.diff p { margin: 0; max-width: 62ch; }
.diff .lbl { margin-bottom: 2px; }
.diff del { color: var(--muted); text-decoration-thickness: 1px; }
.diff ins { text-decoration: none; background: var(--warn-fill); color: var(--ink); box-shadow: 0 0 0 2px var(--warn-fill); border-radius: 2px; }
.checkacts { margin-top: var(--s3); }
.checkacts form { margin: 0; }
.card .checkacts button, .card .checkacts a.button { width: auto; margin-top: 0; }
.shared { margin: 0 0 var(--s3); }
.placewhere p { margin: 0 0 var(--s1); }
.placewhere { margin-bottom: var(--s3); }
.placeblocks .blockhead, #block-owner .blockhead { margin: 0 0 var(--s2); }
.placeblock .shown p, .placeblocks .readchange .shown p { max-width: 62ch; }
.placeform textarea, .placeform input[type=text] { margin-bottom: var(--s2); }
@supports (field-sizing: content) { .placeform textarea { field-sizing: content; min-height: 4.5em; } }
.noteadd { margin-top: var(--s4); padding-top: var(--s3); border-top: 1px dashed var(--rule); }
.noteadd .row > select { flex: 1 1 10rem; width: auto; }
.placenote { margin-top: var(--s2); padding: var(--s2) var(--s3); background: var(--fill); border-radius: var(--r-control); }
.placenote p { margin: var(--s1) 0 0; }
.placenote form { margin: 0; }
.placelist { list-style: none; margin: 0 0 var(--s4); padding: 0; }
.placelist > li { padding: var(--s3) 0; border-top: 1px solid var(--rule); }
.placelist > li:first-child { border-top: 0; }
.placelist p { margin: var(--s1) 0 0; }
.placelist-name { font-size: var(--t-head); font-weight: 700; }
.placecard-name { margin: 0 0 var(--s2); font-size: var(--t-title); line-height: 1.2; }
.placecard .placeblock { padding: var(--s3) 0; }
.placepapers { border-top: 1px solid var(--rule); padding-top: var(--s3); margin-top: var(--s2); }
details.placefold > summary { display: grid; gap: 2px; min-height: var(--h-control); padding: var(--s1) 0; list-style: none; }
details.placefold > summary::-webkit-details-marker { display: none; }
details.placefold > summary .placecard-name { font-size: var(--t-head); }
details.placefold > summary::after { content: "Open ›"; font-size: var(--t-meta); color: var(--muted); }
details.placefold[open] > summary::after { content: "Close ⌄"; }
/* Back to the crew page, a thumb's worth tall. */
.backrow { margin: 0 0 var(--s2); }
.backrow a { display: inline-flex; align-items: center; min-height: var(--h-control); }
/* A box to tick beside its words, and a folded line in the office's lists, a 24px target at a desk. */
.shotform label.row, .placeform label.row { min-height: var(--h-compact); align-items: center; }
body:not(.crew) .panel details.small > summary { padding: 3px 0; }
body:not(.crew) .panel form.row label.row:has(> input[type=checkbox]) { min-height: 24px; align-items: center; }
/* The breakdown's element chips: the × that untags one, a thumb's worth on a phone. */
.el .x { min-width: 24px; min-height: 24px; }
@media (max-width: 640px) { .el { min-height: var(--h-control); } .el .x { min-width: var(--h-control); min-height: var(--h-control); } }
/* A department head's card on their crew page (views/crew/dept.php): a row per page, the check loud. */
.deptcard .taps { margin-bottom: 0; }
.tap.due { border-color: var(--warn); background: var(--warn-fill); }

/* ---- Stripboard: the usual strip colours, INT day white, EXT day yellow, INT night blue, EXT night green ---- */
.board { display: flex; gap: var(--s3); overflow-x: auto; align-items: flex-start; padding-bottom: var(--s3); }
.board .col { flex: 1 0 260px; max-width: 420px; background: var(--panel); border: 1px solid var(--rule); border-radius: var(--r-control); padding: var(--s2); }
.board header { display: flex; flex-direction: column; gap: 2px; margin-bottom: 6px; }
/* Not scheduled stays in reach at the left while the board scrolls to the days to come; days shot are there, quieter. */
.board .col[data-day=""] { position: sticky; left: 0; z-index: 1; align-self: stretch; box-shadow: 6px 0 8px -6px rgba(0,0,0,.18); }
.board .col.over header strong, .board .col.over header .muted { color: var(--muted); }
.strips { list-style: none; margin: 0; padding: 0; min-height: 44px; display: flex; flex-direction: column; gap: 3px; }
/* A strip is something to pick up, so its edge is a field's edge, visible on the white column. */
.strip { display: grid; grid-template-columns: 34px 1fr 18px 62px; grid-template-rows: auto auto; gap: 0 6px; align-items: center;
  border: 1px solid var(--field); border-radius: 4px; padding: var(--s1) 6px; font-size: var(--t-meta); cursor: grab; background: var(--strip-int-d); color: var(--strip-ink); }
.strip .pl { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.strip .ci { grid-column: 2 / 5; font-size: var(--t-label); color: var(--strip-muted); }   /* the cast numbers: 4.31 to 1 on the night blue, now 5.5 */
.strip.int-d { background: var(--strip-int-d); } .strip.ext-d { background: var(--strip-ext-d); } .strip.int-n { background: var(--strip-int-n); } .strip.ext-n { background: var(--strip-ext-n); } .strip.set { background: var(--strip-set); }
.strip .tag { background: var(--panel); border-color: var(--field); color: var(--ink); }
.strip.dragging, .strip[aria-selected="true"] { outline: 2px solid var(--accent); opacity: .85; }
.strip:focus-visible { outline: 2px solid var(--accent); }
.warnings { margin: 6px 0 0; padding-left: var(--s4); color: var(--warn); }

/* ---- The AD's day view: big targets for gloves and one hand, plain states (spec 12.3) ------------- */
body.ad main { max-width: 620px; }
.savedstate { font-size: var(--t-meta); line-height: 1.4; color: var(--muted); margin: 2px 0 var(--s3); }
.refuseditem { border-top: 1px solid var(--rule); padding: var(--s3) 0 var(--s1); } .refuseditem p { margin: 0 0 var(--s1); }
.offline { background: var(--warn-fill); color: var(--ink); border-left: 3px solid var(--warn); border-radius: var(--r-control); padding: var(--s2) var(--s3); font-size: var(--t-body); }
.adtabs { display: flex; gap: 6px; margin: var(--s2) 0 var(--s3); }
.adtabs button { flex: 1; padding: var(--s3) var(--s2); font-weight: 600; }   /* "Saved pack" on one line at 17px, a third of a phone wide */
.adtabs button.on { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.stamps { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s2); margin: var(--s3) 0; }
.stamp { display: flex; flex-direction: column; align-items: flex-start; text-align: left; min-height: 72px; padding: var(--s3); border-radius: var(--r-card); font-size: var(--t-head); }
/* The stamp's name: its own, not the small capitals a label elsewhere is. */
.stamp .lbl { display: inline; font-weight: 700; font-size: inherit; letter-spacing: normal; text-transform: none; color: inherit; margin: 0; }
.stamp .t { font-size: var(--t-body); margin-top: 2px; }
.stamp .note { font-size: var(--t-label); color: var(--muted); margin-top: var(--s1); }
.stampcell { display: flex; flex-direction: column; border: 1px solid var(--field); border-radius: var(--r-card); background: var(--panel); }
.stampcell.done { border-color: var(--ok); }
.stampcell.conflict { border-color: var(--bad); }
.stampcell .stamp { flex: 1; width: 100%; border: 0; background: transparent; }
.takeback { margin: 0; padding: 0 var(--s3) var(--s3); display: flex; flex-wrap: wrap; gap: 6px; }
.takeback button { min-height: 36px; padding-top: var(--s1); padding-bottom: var(--s1); font-size: var(--t-meta); }   /* quiet (ad.js), so no side padding: "Take back 12:08 PM" stays on one line */
label.tick { display: flex; gap: var(--s3); align-items: center; padding: var(--s3) var(--s1); border-top: 1px solid var(--rule); font-size: var(--t-body); color: inherit; }
label.tick input { width: 22px; height: 22px; }
ul.rules { list-style: none; padding: 0; margin: 0; }
ul.rules li { padding: var(--s2) 0; border-top: 1px solid var(--rule); }
ul.rules li.lvl-warn strong { color: var(--bad); }
ul.rules li.lvl-unknown strong { color: var(--warn); }
ul.grouped { margin: var(--s1) 0 0; padding-left: 18px; }
ul.rules ul.grouped li { border-top: 0; padding: 1px 0; }
ul.dues { list-style: none; padding: 0; margin: 6px 0 0; }
/* A person's own times on the AD's list: none recorded is no line, not an empty gap. */
.person .t-list { margin: 0 0 6px; }
.person .t-list:empty { display: none; }
ul.dues li { padding: 2px 0; display: flex; gap: var(--s1); }
ul.dues li .t { flex: 0 0 5.5em; font-variant-numeric: tabular-nums; }
.card dl { display: grid; grid-template-columns: 6.5em 1fr; gap: var(--s1) var(--s3); }
/* On a phone a label goes above its value, so the value has the card's width and not a column of it. */
@media (max-width: 480px) {
  .card dl { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .card dt { margin-top: var(--s2); font-size: var(--t-label); font-weight: 650; letter-spacing: .06em; text-transform: uppercase; }
  .card dt:first-child { margin-top: 0; }
}

/* ---- A template: the words on the left, and on the right how they read with a real person's facts ---- */
.tpl { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); }
@media (max-width: 900px) { .tpl { grid-template-columns: 1fr; } }
.tpl textarea { font-size: var(--t-body); line-height: 1.55; min-height: 440px; }
.doc-preview { border: 1px solid var(--rule); border-radius: var(--r-control); padding: var(--s3); background: var(--bg); font-size: var(--t-body); line-height: 1.55; min-height: 440px; overflow-wrap: anywhere; }
.doc-preview .fact { background: var(--fill); border-radius: 2px; box-shadow: 0 0 0 2px var(--fill); }
.doc-preview .fact.empty { color: var(--muted); }
.doc-preview .fact.bad { color: var(--bad); }
.tpl-insert button { margin: var(--s1) 2px 0 0; }

/* Office pages on a phone, as an AD opens them on set: boxes and buttons a thumb can hit. */
@media (max-width: 640px) {
  body:not(.crew) input[type=checkbox], body:not(.crew) input[type=radio] { width: 22px; height: 22px; }
  body:not(.crew) details > summary { padding: var(--s3) 0; line-height: 24px; }
}

/* ---- Budget: a line or a receipt is a row that opens to change it ------------------------------ */
/* The figures line up down the page, and on a phone a row folds onto two lines instead of squeezing
   its words to a column. */
body:not(.crew) .ledger summary { padding: 0; list-style: none; }
.ledger summary::-webkit-details-marker { display: none; }
.ledger .lrow { display: grid; gap: 2px var(--s3); align-items: baseline; padding: var(--s2) 6px; border-top: 1px solid var(--rule); }
.ledger > :first-child .lrow, .ledger > .lrow:first-child, .ledger > .rrow:first-child { border-top: 0; }
.ledger summary:hover .lrow, .ledger details[open] > summary .lrow { background: var(--fill); }
.ledger .n { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Open, a row's fields sit under the figures they change, in the same columns. */
.ledger .edit { padding: 6px 6px var(--s3); background: var(--fill); }
.ledger .edit form { margin: 0; }
.ledger .edit .fields { display: grid; gap: var(--s2) var(--s3); align-items: end; }
.ledger .edit .fields .n { text-align: left; }
.ledger .edit .acts { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; }
.ledger .edit .acts select { width: auto; }
.ledger .edit .acts .away { margin-left: auto; }
.lines .lrow, .lines .edit .fields { grid-template-columns: minmax(0, 1fr) 8.5em 9.5em 8.5em; }
.receipts .rrow { display: grid; grid-template-columns: minmax(0, 1fr) 4em; align-items: start; border-top: 1px solid var(--rule); }
.receipts .rrow .lrow, .receipts .edit .fields { grid-template-columns: 9.5em minmax(0, 1.4fr) minmax(0, 1fr) 7em; grid-template-areas: "date what line n" "acts acts acts acts"; }
.receipts .rrow .lrow { border-top: 0; }
.receipts .edit .acts { grid-area: acts; }
.receipts .meta { display: contents; font-size: inherit; color: inherit; }   /* not the .meta line: a wrapper the date and the line sit in */
.receipts .date { grid-area: date; } .receipts .what { grid-area: what; } .receipts .line { grid-area: line; } .receipts .lrow .line { color: var(--muted); } .receipts .n { grid-area: n; }
.receipts .photo { padding: var(--s2) 6px; text-align: right; }
/* A file field drawn as a button that shows the photo chosen: the system's own ran out of room
   in a grid cell and read "no file selecte". */
.filepick { position: relative; display: inline-flex; align-items: center; gap: var(--s2); min-height: var(--h-control); margin: 0; font-size: inherit; color: inherit; max-width: 100%; }
.filepick.small { min-height: var(--h-compact); }
.filepick input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.filepick img { height: 28px; width: auto; border-radius: 3px; }
.filepick span { max-width: 22em; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filepick:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width: 640px) {
  .lines .lrow { grid-template-columns: repeat(3, auto); justify-content: start; column-gap: var(--s4); }
  .lines .lrow .what { grid-column: 1 / -1; }
  .lines .lrow .n { text-align: left; color: var(--muted); }
  .receipts .rrow .lrow { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "what n" "meta meta"; }
  .lines .edit .fields { grid-template-columns: 1fr 1fr; }
  .lines .edit .fields > div:first-of-type { grid-column: 1 / -1; }
  .receipts .edit .fields { grid-template-columns: 1fr 1fr; grid-template-areas: "what what" "n date" "line line" "acts acts"; }
  .receipts .meta { display: block; grid-area: meta; color: var(--muted); }
  .receipts .meta .line::before { content: " · "; }
}

/* ==== Components ================================================================================
 * What a rebuilt page is made of (review/ux21/mockups/*.html show them in place). Nothing here is
 * used by a page until its fixer reaches for it. */

/* 1. The kicker line: the small capitals line above a title, saying whose and when.
 *    <p class="eyebrow">Long Night · <b>Tomorrow</b> · Day 2 of 6</p><h1>Tue Oct 6</h1> */
.eyebrow { font-size: var(--t-label); font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin: 0 0 var(--s1); }
.eyebrow b { color: var(--ink); font-weight: 650; }
/* A label over its value, and the value large: <span class="lbl">Crew call</span><div class="big">5:00 PM</div> */
.lbl { display: block; font-size: var(--t-label); font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin-bottom: 2px; }
.big { font-size: var(--t-display); font-weight: 750; letter-spacing: -.025em; line-height: 1; }

/* The title of a page with its fingerprint and its links at the right.
 *    <div class="pagehead"><div><p class="eyebrow">…</p><h1>…</h1></div><div class="fp">Crew have revision 2…<br><a>Call sheet</a></div></div> */
.pagehead { display: flex; justify-content: space-between; align-items: flex-end; gap: var(--s2) var(--s4); margin-bottom: var(--s4); flex-wrap: wrap; }
.pagehead h1 { margin: 0; }
.pagehead .fp { text-align: right; font-size: var(--t-meta); color: var(--muted); line-height: 1.6; }
.pagehead .fp a { color: var(--ink); display: inline-block; padding: 3px 0; }   /* a link on its own: a 24px target at a desk */
@media (max-width: 640px) { .pagehead .fp { text-align: left; } }
/* A section's heading with its own links at the right: <div class="sectionhead"><h2>…</h2><div class="acts"><a>…</a></div></div> */
.sectionhead { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s2) var(--s4); flex-wrap: wrap; margin: var(--s6) 0 var(--s3); }
.sectionhead h2 { margin: 0; }
.sectionhead .acts { display: flex; gap: var(--s4); flex-wrap: wrap; font-size: var(--t-meta); }
.sectionhead .acts a { display: inline-block; padding: var(--s1) 0; }

/* The facts card: the day as the top of the call sheet sets it, each fact a label over its value.
 *    <section class="hero"><div class="when"><span class="lbl">Crew call</span><div class="big">5:00 PM</div></div>
 *      <div class="where"><span class="lbl">Where</span><b>Lewis &amp; Clark Landing</b><p>345 Riverfront Dr</p></div>
 *      <div class="facts"><div><span class="lbl">Tonight</span><p>…</p></div>…</div>
 *      <div class="row2">…who has their call…</div></section> */
.hero { background: var(--panel); border: 1px solid var(--rule); border-radius: var(--r-card); padding: var(--s5); display: grid; grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr); gap: var(--s5) var(--s6); align-items: start; margin: 0 0 var(--s4); }
.hero .when { border-right: 1px solid var(--rule); padding-right: var(--s6); }
.hero .where b { font-size: var(--t-head); display: block; line-height: 1.3; }
.hero p { margin: 0 0 var(--s1); }
.hero .row2 { grid-column: 1 / -1; border-top: 1px solid var(--rule); padding-top: var(--s4); display: flex; gap: var(--s3) var(--s5); align-items: center; flex-wrap: wrap; }
.facts { display: grid; gap: var(--s3); }
.facts > div > p { margin: 0; }
@media (max-width: 760px) {
  .hero { grid-template-columns: minmax(0, 1fr); padding: var(--s4); gap: var(--s4); }
  .hero .when { border-right: 0; padding-right: 0; border-bottom: 1px solid var(--rule); padding-bottom: var(--s4); }
}

/* The status strip: who has their call, one segment a person in the order of the list under it. The
 * eye counts five gaps in a row of twenty-five without reading a number. Filled is done, pale is
 * reached another way, red is trouble, hollow is still to do.
 *    <div class="reach"><div class="segs" aria-hidden="true"><i></i><i class="reached"></i><i class="bad"></i><i class="wait"></i></div>
 *      <span class="count">20 of 25 have their call</span></div> */
.reach { display: flex; align-items: center; gap: var(--s3) var(--s4); flex-wrap: wrap; }
.segs { display: flex; flex-wrap: wrap; gap: 2px; max-width: 100%; }
.segs > * { width: 9px; height: 18px; border-radius: 2px; background: var(--ok); flex: none; }
.segs > .reached { background: #8fbf9f; background: color-mix(in srgb, var(--ok) 55%, var(--panel)); }
.segs > .bad { background: var(--bad); }
.segs > .wait { background: transparent; box-shadow: inset 0 0 0 1.5px var(--due); }
.reach .count { font-size: var(--t-head); font-weight: 700; }

/* State chips: a band of colour with the word in it, never colour alone.
 *    <span class="chip warn"><span class="dot"></span>Showers likely, 60%</span>
 *    .chip alone is a state with nothing to do (Draft); .ok done, .due needs doing, .warn look before the call, .bad trouble. */
.chip { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-meta); font-weight: 600; line-height: 1.1; padding: var(--s1) var(--s2); border-radius: 999px; background: var(--fill); color: var(--muted); white-space: nowrap; vertical-align: baseline; }
.chip.ok { background: var(--ok-fill); color: var(--ok); }
.chip.due { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1px var(--due); }
.chip.warn { background: var(--warn-fill); color: var(--warn); }
.chip.bad { background: var(--bad-fill); color: var(--bad); }
.dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; display: inline-block; flex: none; }

/* A list where the problem is the loud part and its actions end its line.
 *    <ul class="exceptions"><li><div class="who"><b>Earl Tibbs</b><span>Driver · 4:00 PM</span></div>
 *      <div class="what"><p class="quote">"…"</p></div><div class="acts"><a class="button small" href="tel:…">Call</a></div></li></ul> */
.exceptions { list-style: none; margin: 0; padding: 0; }
.exceptions > li { display: grid; grid-template-columns: 11.5rem minmax(0, 1fr) auto; gap: var(--s1) var(--s4); align-items: start; padding: var(--s3) 0; border-top: 1px solid var(--rule); }
.exceptions > li:first-child { border-top: 0; }
.exceptions .who b { display: block; }
.exceptions .who span { color: var(--muted); font-size: var(--t-meta); }
.exceptions .what p { margin: 0; }
.exceptions .acts { display: flex; gap: var(--s2); align-items: center; justify-content: flex-end; flex-wrap: wrap; }
.exceptions .acts :is(.button, button) { min-height: var(--h-compact); padding: var(--s1) var(--s3); font-size: var(--t-meta); font-weight: 600; }
.quote { border-left: 3px solid var(--bad); padding-left: var(--s3); color: var(--ink); }
/* Things to do, the owner as the heading rather than a grey suffix, a filled mark for the state (an
 * empty ring read as a radio button to press).
 *    <ul class="todo"><li><span class="ring bad"></span><div><p><b>…</b> …</p></div><div class="acts">…</div></li></ul> */
.todo { list-style: none; margin: 0; padding: 0; }
.todo > li { display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; gap: var(--s1) var(--s3); align-items: start; padding: var(--s3) 0; border-top: 1px solid var(--rule); }
.todo > li:first-child { border-top: 0; }
.todo .ring { width: 10px; height: 10px; border-radius: 50%; background: var(--due); margin: 6px 0 0 var(--s1); }
.todo .ring.ok { background: var(--ok); } .todo .ring.warn { background: var(--warn); } .todo .ring.bad { background: var(--bad); }
.todo p { margin: 0; }
.todo .acts { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; justify-content: flex-end; }
.todo .acts :is(.button, button) { min-height: var(--h-compact); padding: var(--s1) var(--s3); font-size: var(--t-meta); font-weight: 600; white-space: nowrap; }
@media (max-width: 640px) {
  .exceptions > li { grid-template-columns: minmax(0, 1fr); }
  .exceptions .acts, .todo .acts { justify-content: flex-start; }
  .todo > li { grid-template-columns: 22px minmax(0, 1fr); }
  .todo .acts { grid-column: 2; }
}
/* More, folded to one line: <details class="more"><summary>Dana Ruiz, 1st AD, has 18 open</summary>…</details> */
details.more > summary { list-style: none; font-weight: 600; padding: var(--s2) 0; }
details.more > summary::-webkit-details-marker { display: none; }
details.more > summary::after { content: " ›"; color: var(--muted); }
details.more[open] > summary::after { content: " ⌄"; }

/* The shoot on one line: each day a tile, the next one marked, the ones over quiet.
 *    <nav class="days"><a class="over"><span class="d">Mon Oct 5</span><span class="t">6:00 AM</span><span class="p">Day 1 · Bodega</span><span class="s">Wrapped</span></a>…</nav> */
.days { display: grid; grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); gap: var(--s2); }
.days a { display: block; text-decoration: none; background: var(--panel); border: 1px solid var(--rule); border-radius: var(--r-control); padding: var(--s3); min-height: 104px; }
.days a:hover { border-color: var(--field); }
.days a.next { border: 2px solid var(--ink); padding: calc(var(--s3) - 1px); }
.days a.over { background: transparent; color: var(--muted); }
.days a.over .t { font-weight: 600; }
.days .d { font-weight: 700; display: block; }
.days .t { font-size: var(--t-head); font-weight: 700; display: block; margin: 6px 0 2px; }
.days .p { font-size: var(--t-meta); color: var(--muted); display: block; line-height: 1.35; }
.days .s { font-size: var(--t-meta); display: block; margin-top: 6px; }

/* A call ladder: everyone grouped by the time they are called, as an AD reads a day.
 *    <ul class="ladder"><li><div class="time">2:30 PM<small>rig</small></div><div class="people"><span class="person-chip">Hollis Park <span>Key Grip</span></span></div></li></ul> */
.ladder { list-style: none; margin: 0; padding: 0; }
.ladder > li { display: grid; grid-template-columns: 7.5rem minmax(0, 1fr); gap: var(--s4); padding: var(--s3) 0; border-top: 1px solid var(--rule); align-items: start; }
.ladder > li:first-child { border-top: 0; }
.ladder .time { font-size: var(--t-head); font-weight: 700; }
.ladder .time small { display: block; font-size: var(--t-meta); font-weight: 500; color: var(--muted); }
.ladder .people { display: flex; flex-wrap: wrap; gap: var(--s2); }
@media (max-width: 480px) { .ladder > li { grid-template-columns: minmax(0, 1fr); gap: var(--s2); } }
.person-chip { display: inline-flex; align-items: baseline; gap: 6px; padding: var(--s1) var(--s3); border: 1px solid var(--rule); border-radius: var(--r-control); background: var(--panel); }
.person-chip span { color: var(--muted); font-size: var(--t-meta); }
.person-chip.changed { border-color: var(--warn); background: var(--warn-fill); padding: var(--s1) var(--s3); margin: 0; border-left-width: 1px; }
.person-chip.changed s { color: var(--muted); }
.person-chip.off { background: transparent; border-style: dashed; color: var(--muted); }
/* A time that reads as text until it is pressed: <input class="inline-time" value="5:00 PM" aria-label="Crew call"> */
input.inline-time { font: inherit; font-weight: 700; border: 0; border-bottom: 1px dashed var(--field); border-radius: 0; background: transparent; padding: 0 1px; width: 5.2em; min-height: 0; color: inherit; }

/* A scene with its strip colour at its edge, so the day page and the board read as one thing.
 *    <ul class="scenes"><li class="ext-n"><span class="n">10</span><span class="h">EXT RIVERFRONT</span><span class="m">N</span><span class="m">2/8</span><span class="m">Cast 3</span><span></span></li></ul> */
.scenes { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s1); }
.scenes li { display: grid; grid-template-columns: 2.5rem minmax(0, 1fr) 2rem 3.5rem 6.5rem 5.5rem; gap: var(--s3); align-items: baseline; padding: 6px var(--s3); border-radius: 6px; border: 1px solid var(--rule); border-left: 6px solid var(--strip-int-d); background: var(--panel); }
.scenes li.int-d { border-left-color: var(--field); }   /* the white strip's colour is white, so its edge is drawn */
.scenes li.ext-d { border-left-color: var(--strip-ext-d); } .scenes li.int-n { border-left-color: var(--strip-int-n); } .scenes li.ext-n { border-left-color: var(--strip-ext-n); } .scenes li.set { border-left-color: var(--strip-set); }
.scenes .n { font-weight: 700; } .scenes .h { font-weight: 500; } .scenes .m { color: var(--muted); font-size: var(--t-meta); }
@media (max-width: 640px) {
  .scenes li { grid-template-columns: 2.5rem minmax(0, 1fr); row-gap: 2px; }
  .scenes li > :nth-child(n+3) { grid-column: 2; }
  .scenes li > :nth-child(n+3):empty { display: none; }
}

/* 5. Show the thing, then Change. The text as people read it, with Change beside its label; Change
 * opens the form where the text was, and Cancel closes it. No script.
 *    <section class="readchange"><details><summary><span class="lbl">Safety</span><span class="change">Change</span><span class="cancel">Cancel</span></summary>
 *      <form>…fields… <button class="primary">Save</button></form></details>
 *      <div class="shown"><p>Night work by the river: …</p></div></section> */
.readchange { padding: var(--s3) 0; border-top: 1px solid var(--rule); }
.readchange:first-child { border-top: 0; padding-top: 0; }
.readchange > details > summary { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3); list-style: none; padding: 0; }
.readchange > details > summary::-webkit-details-marker { display: none; }
.readchange > details > summary .lbl { margin: 0; }
.readchange :is(.change, .cancel) { font-size: var(--t-meta); text-decoration: underline; text-underline-offset: .2em; color: var(--ink); padding: var(--s1) 0; }
.readchange > details > summary .cancel, .readchange > details[open] > summary .change { display: none; }
.readchange > details[open] > summary .cancel { display: inline; }
.readchange > details[open] { margin-bottom: var(--s2); }
.readchange > details > form, .readchange > details > div { margin-top: var(--s2); }
.readchange:has(> details[open]) > .shown { display: none; }
.readchange .shown > :last-child { margin-bottom: 0; }
.readchange .shown p { max-width: 62ch; }
/* Actions that stand alone under a section, quieter than its buttons: <div class="footacts"><a>Call the day off</a>…</div> */
.footacts { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s5); margin-top: var(--s4); font-size: var(--t-meta); }
.footacts a { color: var(--muted); display: inline-block; padding: 3px 0; }
/* What crew will read, whole, in columns, with Change under each: the day page's notes, safety and
 * where to report. <div class="doc"><div><span class="lbl">Safety</span><p>…</p><a class="edit">Change</a></div>…</div> */
.doc { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: var(--s5); }
.doc p { margin: 0 0 var(--s2); max-width: 62ch; }
.doc .edit { font-size: var(--t-meta); }

/* 4. The quiet confirmation, where the thing was pressed: "Saved", "Confirmed for 2:30 PM at the Landing".
 *    <span class="saved" role="status">Saved</span>. Nothing else says success (Standard 15). */
.saved { display: inline-flex; align-items: baseline; gap: var(--s1); font-size: var(--t-meta); font-weight: 600; color: var(--muted); }
.saved::before { content: "✓"; color: var(--ok); font-weight: 700; }
p.saved, div.saved { display: flex; margin: var(--s2) 0; }

/* 4. One primary, always in reach: a bar that stays on screen at the foot of a long page, saying what
 * the button will do before it is pressed.
 *    <div class="actionbar" role="region" aria-label="Publish"><div class="state"><b>1 change not published</b><span>Earl Tibbs, 4:00 → 5:45 PM …</span></div>
 *      <button class="quiet">Undo</button><button>Save draft</button><button class="primary">Publish revision 3<span class="kbd">⌘↵</span></button></div> */
.actionbar { position: sticky; bottom: 0; z-index: 5; margin: var(--s6) calc(-1 * var(--s4)) 0; padding: var(--s3) var(--s4); padding-bottom: calc(var(--s3) + env(safe-area-inset-bottom, 0px));
  background: var(--panel); border-top: 1px solid var(--rule); box-shadow: 0 -6px 16px rgba(0, 0, 0, .06); display: flex; gap: var(--s3) var(--s4); align-items: center; flex-wrap: wrap; }
.actionbar .state { flex: 1 1 18rem; min-width: 0; }
.actionbar .state b { display: block; }
.actionbar .state span { color: var(--muted); font-size: var(--t-meta); }
.actionbar label { display: flex; gap: var(--s2); align-items: center; margin: 0; }
.actionbar button.primary { padding-left: var(--s5); padding-right: var(--s5); }
.kbd { font: 600 var(--t-label)/1 var(--font); border: 1px solid currentColor; border-radius: 4px; padding: 2px var(--s1); margin-left: var(--s2); }
@media (hover: none) { .kbd { display: none; } }   /* a phone has no ⌘ */

/* 6. The gloved thumb: a link or button as a whole row, 48px tall, the words at the left and a mark
 * that it goes somewhere at the right.
 *    <div class="taps"><a class="tap" href="tel:…">Call Dana Ruiz<small>1st AD · 402-555-0118</small></a></div>
 *    (the words and the small line may also sit in one <span>, as the crew mockup has them) */
.tap { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; align-content: center; column-gap: var(--s3); min-height: 48px; width: 100%; margin: 0; padding: var(--s2) var(--s4); border: 1px solid var(--field); border-radius: var(--r-control); background: var(--panel); color: var(--ink); font-size: inherit; font-weight: 600; text-align: left; text-decoration: none; }
.tap small { display: block; grid-column: 1; font-weight: 500; color: var(--muted); font-size: var(--t-meta); margin-top: 1px; }
.tap::after { content: "›"; grid-column: 2; grid-row: 1 / span 2; color: var(--muted); font-size: 1.3em; line-height: 1; }
.taps { display: grid; gap: var(--s2); margin: var(--s3) 0; }
.card .taps .tap { margin-top: 0; }

/* The crew card, as review/ux21/mockups/crew.html sets it: the next call first, the place, Maps,
 * the forecast, Confirm, then the AD. */
.crewhead { margin-bottom: var(--s3); }
.crewhead .who { font-size: var(--t-head); font-weight: 700; line-height: 1.2; }
.callcard { background: var(--panel); border: 1px solid var(--rule); border-radius: 16px; padding: var(--s4); margin: 0 0 var(--s4); }
.callcard .changeline { display: flex; gap: var(--s2); align-items: flex-start; background: var(--warn-fill); color: var(--ink); border-radius: var(--r-control); padding: var(--s2) var(--s3); margin: var(--s3) 0 var(--s4); }
.callcard .changeline b { color: var(--warn); }
.callcard .top { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3); }
.callcard .top a { font-size: var(--t-meta); font-weight: 650; color: var(--bad); white-space: nowrap; display: inline-flex; align-items: center; min-height: 44px; margin: -12px 0; }
.callcard .yourcall { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); flex-wrap: wrap; }
.callcard .yourcall .crewcall { text-align: right; margin-left: auto; }   /* at the right, also when a narrow phone moves it to its own line */
.callcard .place { margin: var(--s4) 0 var(--s3); }
.callcard .place b { font-size: var(--t-title); line-height: 1.2; display: block; letter-spacing: -.01em; }   /* spec 12.4: times and reporting places largest */
body.crew .confirm { display: block; width: 100%; min-height: 56px; font-size: var(--t-head); font-weight: 700; margin: var(--s4) 0 var(--s2); }
.weatherline { display: flex; gap: var(--s3); align-items: center; flex-wrap: wrap; margin: var(--s3) 0 0; }
.weatherline b { font-size: var(--t-head); }
.section { margin: var(--s6) 0 var(--s2); font-size: var(--t-head); font-weight: 700; }
/* Label over value, stacked: <div class="stack"><div><span class="lbl">Parking</span><p>…</p></div>…</div> (a table.stack is the list on a phone, above) */
.stack:not(table) { display: grid; gap: var(--s3); margin: var(--s4) 0; }
.stack:not(table) > div > p { margin: 0; }
.sos { border: 1px solid var(--rule); border-left: 4px solid var(--bad); border-radius: var(--r-card); padding: var(--s4); background: var(--panel); }
.sos .lbl { color: var(--bad); }
/* A day that is over steps aside: one line, and it opens if wanted.
 *    <details class="past-wrap"><summary class="past"><span><b>Today, Mon Oct 5</b> · wrapped 4:40 PM</span><span>Show</span></summary>…</details> */
.past { display: flex; justify-content: space-between; align-items: center; gap: var(--s3); min-height: 48px; padding: var(--s2) var(--s4); background: var(--fill); border-radius: var(--r-card); color: var(--muted); font-size: var(--t-meta); margin-bottom: var(--s4); }
.past > span:last-child { color: var(--ink); font-weight: 600; white-space: nowrap; }
.past b { color: var(--ink); font-weight: 600; }
details.past-wrap > summary { list-style: none; }
details.past-wrap > summary::-webkit-details-marker { display: none; }
body.crew details.past-wrap > summary { padding: var(--s2) var(--s4); }
.plainlist { list-style: none; margin: 0; padding: 0; }
.plainlist li { padding: var(--s3) 0; border-top: 1px solid var(--rule); }
.plainlist li:first-child { border-top: 0; }
.dir li { display: flex; justify-content: space-between; align-items: center; gap: var(--s3); min-height: 56px; padding: 6px 0; }
.dir a.phone { display: inline-flex; align-items: center; min-height: 48px; padding: 0 var(--s3); border: 1px solid var(--field); border-radius: var(--r-control); text-decoration: none; font-weight: 600; white-space: nowrap; }

/* ==== ad-day: the AD's day page and the stripboard (ux21, views/days/*, views/planning/schedule.php) ====
 * Built from the components above; what the day page and the board needed and the system did not have. */

/* A fieldset that only groups, with nothing drawn: the day form's, disabled whole after wrap. */
fieldset.bare { border: 0; padding: 0; margin: 0; min-width: 0; }
/* A label that sits in its line, not over its field: "Meal", "Cover set". */
label.inline, legend.inline { display: inline; margin: 0 var(--s2) 0 0; padding: 0; font-size: var(--t-meta); color: var(--muted); }
/* A dropdown drawn as the words it holds, dashed underneath, until it is pressed: the place, the meal. */
select.plain { width: auto; max-width: 100%; min-height: 0; border: 0; border-bottom: 1px dashed var(--field); border-radius: 0; background-color: transparent;
  padding: 0 22px 1px 0; font-weight: 700; font-size: var(--t-head); background-position: calc(100% - 10px) 55%, calc(100% - 5px) 55%; }
select.plain.small { font-size: var(--t-meta); font-weight: 600; color: var(--ink); min-height: 28px; }
@media (max-width: 640px) { select.plain, select.plain.small { min-height: var(--h-control); } }

/* The day's facts: the crew call at 44, the place, the forecast, and the rain plan across the foot. */
.dayfacts .when { min-width: 12rem; }
input.inline-time.big { font-size: var(--t-display); font-weight: 750; letter-spacing: -.025em; line-height: 1.1; width: 100%; max-width: 6.2em; }
.dayfacts .when .meta { margin-top: var(--s1); }
.titleline { display: flex; align-items: baseline; gap: var(--s2) var(--s4); flex-wrap: wrap; }
.datechange > summary .change { margin-left: 0; }
.datechange input[type=date] { width: auto; min-height: 36px; padding: 2px var(--s2); font-size: var(--t-meta); }
.datechange .origin { display: inline; margin-left: var(--s2); }
.forecast { font-size: var(--t-head); }
/* Rain on a day with exteriors is the one forecast to plan for: in the warning colour, at its edge. */
.forecast.rainy { color: var(--warn); border-left: 3px solid var(--warn); padding-left: var(--s2); }
/* A fact shown, with Change beside its label, that opens the field in place (the read-then-change block, inline). */
details.inlinechange > summary { display: flex; gap: var(--s2) var(--s3); align-items: baseline; flex-wrap: wrap; list-style: none; padding: 0; cursor: pointer; }
details.inlinechange > summary::-webkit-details-marker { display: none; }
details.inlinechange > summary .change { font-size: var(--t-meta); text-decoration: underline; text-underline-offset: .2em; color: var(--ink); margin-left: auto; padding: var(--s1) 0; }
details.inlinechange[open] > summary .change { color: var(--muted); }
details.inlinechange > :not(summary) { margin-top: var(--s2); }
.placename { display: block; font-size: var(--t-head); line-height: 1.3; margin-top: var(--s1); }
.ownforecast > div { margin-bottom: var(--s2); }
.ownforecast input { font-size: var(--t-meta); min-height: 36px; padding: var(--s1) var(--s2); }
.ownforecast .meta { margin: var(--s1) 0 0; }
@media (max-width: 640px) { .ownforecast input { min-height: var(--h-control); } details.inlinechange > summary .change { min-height: 44px; display: inline-flex; align-items: center; } }

/* The rain plan: one box, the cover set, the scenes shot there, what that means, the note, and whether the day is there. */
.rainplan { grid-column: 1 / -1; display: grid; gap: var(--s2); margin: 0 calc(-1 * var(--s5)) calc(-1 * var(--s5)); padding: var(--s3) var(--s5) var(--s4);
  background: var(--warn-fill); border-top: 1px solid var(--rule); border-radius: 0 0 var(--r-card) var(--r-card); }
.rainhead .lbl { margin: 0 var(--s2) 0 0; color: var(--ink); }
@media (max-width: 640px) { .rainhead > summary { display: grid; grid-template-columns: minmax(0, 1fr) auto; } .rainhead > summary .coverwhere { grid-column: 1 / -1; grid-row: 2; } }
.rainhead .coverwhere b { font-size: var(--t-head); }
.rainedit { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s2); }
.rainedit > * { min-width: 0; }
.coverpick select { width: auto; max-width: 100%; }
@media (max-width: 640px) { .coverpick select { width: 100%; } }
.rainplan .plan { font-weight: 650; margin: 0; }
.covernoteshown { margin: 0; color: var(--muted); font-style: italic; }
.coverscenes { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; }
.coverscenes .chk, .tickline { display: inline-flex; align-items: center; gap: var(--s2); margin: 0; font-size: var(--t-body); color: var(--ink); min-height: 32px; }
.coverscenes .chk { padding: var(--s1) var(--s3); border: 1px solid var(--field); border-radius: var(--r-control); background: var(--panel); }
.covernote { display: flex; gap: var(--s2) var(--s3); align-items: center; flex-wrap: wrap; }
.covernote label { margin: 0; }
.covernote input { flex: 1 1 16rem; min-height: 36px; }
.rainmove { display: flex; gap: var(--s2) var(--s4); align-items: center; flex-wrap: wrap; margin: 0; }
@media (max-width: 760px) { .rainplan { margin: 0 calc(-1 * var(--s4)) calc(-1 * var(--s4)); padding: var(--s3) var(--s4); } }
@media (max-width: 640px) { .coverscenes .chk, .tickline { min-height: var(--h-control); } .covernote input { min-height: var(--h-control); } }

/* What the day warns of, before it is published: under the facts, in the warning colour. */
.daywarnings { margin: 0 0 var(--s4); padding-left: var(--s5); font-size: var(--t-meta); }
.daywarnings li { margin: 2px 0; }
.daywarnings a { color: inherit; }

/* Who has their call: the answer to a problem under its quote, and a reply that reaches them. */
.reachpanel .reach { margin-bottom: var(--s3); }
.allhave { margin: 0; color: var(--ok); font-weight: 600; }
/* One message for the crew's own group thread, shown whole, with Copy beside its label (round 21 B, d8). */
.groupmsg { margin: 0 0 var(--s3); padding: var(--s3); background: var(--fill); border-radius: var(--r-control); }
/* Copy stays beside its label, which wraps first, so the words are not pushed a row further down on a phone. */
.groupmsg .grouphead { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); margin: 0 0 var(--s1); }
.groupmsg .grouphead .lbl { margin: 0; min-width: 0; }
.groupmsg .grouphead button { flex: none; min-height: var(--h-compact); padding: var(--s1) var(--s4); font-weight: 600; }
.groupmsg .grouptext { margin: 0; overflow-wrap: anywhere; }
.exceptions .what > * + * { margin-top: var(--s1); }
.answered { border-left: 3px solid var(--ok); padding-left: var(--s3); }
.answered .lbl { color: var(--ok); }
.replybox { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s1) var(--s2); align-items: end; max-width: 36rem; }
.replybox .lbl { grid-column: 1 / -1; margin: 0; }
/* One height, focused or not: it grew from 44 to 88px on focus and shrank back as Send the answer was pressed, so the
   button moved 44px up under the thumb and the press landed on nothing (round 21 B, sh1; walks/ad-night/again/why-answer-misses.js). */
.replybox textarea { min-height: 88px; height: 88px; resize: vertical; }
@media (max-width: 480px) { .replybox { grid-template-columns: minmax(0, 1fr); } .replybox button { justify-self: start; } }
/* The move screen's message for the crew's group thread, folded under its Copy button: a fold a thumb can open, with a
   mark that says it opens (views/onset/move.php, round 21 B, o1). */
.threadmsg > summary { list-style: none; display: flex; align-items: center; min-height: var(--h-control); font-weight: 600; }
.threadmsg > summary::-webkit-details-marker { display: none; }
.threadmsg > summary::after { content: "\00a0\203A"; color: var(--muted); }
.threadmsg[open] > summary::after { content: "\00a0\2304"; }
.threadmsg > p { margin: 0 0 var(--s2); overflow-wrap: anywhere; }
/* The number under a minor in the phone's header, a call away: a press 48 pixels tall, as every other call on the phone
   is, without moving a line, since an inline link's padding takes no room (ad.js adMinorLine, round 21 B, g4). */
.adminor a[href^="tel:"] { padding: 14px 0; }
details.everyone { margin-top: var(--s2); }
details.everyone table { margin-top: var(--s2); }
details.everyone .acts { white-space: nowrap; text-align: right; }
.exceptions .who b { color: var(--ink); }
@media (max-width: 640px) { .exceptions .acts :is(.button, button) { min-width: 64px; } }

/* The calls by department: a row a person, the Called box its own control, the time a field that reads
   as text. Each department names the two columns once. Two columns of departments at a desk. */
#calllist { padding-top: var(--s2); }
@media (min-width: 1100px) { #calllist { columns: 2; column-gap: var(--s6); } #calllist .dept { break-inside: avoid; } #calllist > p { column-span: all; } }
.dept { padding-top: var(--s2); }
.depthead { display: grid; grid-template-columns: minmax(0, 1fr) auto 2.75rem 8.5rem; gap: var(--s3); align-items: baseline; margin: 0 0 var(--s1); padding: 0 var(--s2); font-size: inherit; }
.depthead .lbl { margin: 0; }
.depthead .cols { display: contents; }
.depthead .cols > span { font-size: var(--t-label); font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.pick-dept { display: inline-flex; gap: var(--s2); align-items: center; margin: 0; font-size: var(--t-meta); grid-column: 2; }
#calllist:not(.picking) :is(.pick, .pick-dept) { display: none; }
.callrows { list-style: none; margin: 0; padding: 0; }
.callrow { display: grid; grid-template-columns: auto minmax(0, 1fr) 2.75rem 8.5rem; gap: var(--s1) var(--s3); align-items: center; padding: 5px var(--s2); border-top: 1px solid var(--rule); }
.callrows > .callrow:first-child { border-top: 0; }
#calllist:not(.picking) .callrow { grid-template-columns: minmax(0, 1fr) 2.75rem 8.5rem; }
.callrow .who { line-height: 1.3; }
.callrow .who .role { color: var(--muted); font-size: var(--t-meta); }
.callrow .calledbox { display: inline-flex; align-items: center; justify-content: center; margin: 0; min-height: 32px; }
.callrow .time input.inline-time { font-size: var(--t-head); width: 100%; }
.callrow .time .was, .callrow .time .origin { display: block; font-size: var(--t-meta); color: var(--muted); margin: 2px 0 0; }
.callrow.moved { background: var(--warn-fill); border-radius: var(--r-control); }
.callrow.moved .was { color: var(--warn); }
.callrow:has(input[name^="called"]:not(:checked)) .time input { opacity: .45; }
.dept.offday .who b { font-weight: 500; color: var(--muted); }
.shiftbar { margin: 0 0 var(--s2); }
.shiftbar input[type=number] { width: 88px; }
.shiftbar .pickall { margin: 0; color: inherit; }
@media (max-width: 640px) {
  .depthead, #calllist:not(.picking) .callrow { grid-template-columns: minmax(0, 1fr) 2.75rem 7.25rem; }
  .callrow { grid-template-columns: auto minmax(0, 1fr) 2.75rem 7.25rem; }
  .callrow .calledbox { min-height: var(--h-control); min-width: var(--h-control); }
  .callrow .time input.inline-time { min-height: var(--h-control); }
}

/* What crew read, in columns, each shown as text with Change beside its label. */
.crewread { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: var(--s4) var(--s5); }
.crewread .readchange { border-top: 0; padding: 0; }
.crewread textarea { min-height: 120px; }
.tickline { margin: var(--s4) 0 0; }

/* What publishing sends: said once for everyone, then only where somebody hears something else. */
.preview .lead { font-weight: 600; margin: 0 0 var(--s3); }
.preview .everyone { border-left: 3px solid var(--rule); padding-left: var(--s3); margin: 0 0 var(--s3); }
.preview .everyone .lbl { margin-bottom: var(--s1); }
.preview .everyone p { margin: 0 0 var(--s1); }
ul.differences { list-style: none; margin: 0; padding: 0; }
ul.differences > li { border-top: 1px solid var(--rule); padding: var(--s2) 0; }
ul.differences > li:first-child { border-top: 0; }
ul.differences summary { cursor: pointer; padding: var(--s1) 0; min-height: 32px; }
@media (max-width: 640px) { ul.differences summary { min-height: var(--h-control); padding: var(--s2) 0; } }
ul.differences summary .what { color: var(--ink); }
ul.differences .mail { margin: var(--s2) 0 0 var(--s4); }
.mailpreview .subject .lbl { display: inline; margin-right: var(--s2); }
.mailbody { white-space: pre-wrap; overflow-wrap: anywhere; font: var(--t-meta)/1.5 ui-monospace, Menlo, monospace; background: var(--fill); border-radius: var(--r-control); padding: var(--s3); margin: 0; }
/* The two ways of saying what Publish does, one shown: Tell everyone ticked is the second. */
.said-all { display: none; }
form:has(input[name=tell_everyone]:checked) .said-one { display: none; }
form:has(input[name=tell_everyone]:checked) span.said-all { display: inline; }
form:has(input[name=tell_everyone]:checked) p.said-all { display: block; }

/* The publish bar: what it will do, and under it the quiet line (Saved, Undo, Redo); at the right, Tell
   everyone, Save draft and the one primary action. */
.dayform .actionbar .state > span { display: block; }
.dayform .actionbar .state > span.said-all { display: none; }
.dayform:has(input[name=tell_everyone]:checked) .actionbar .state > span.said-one { display: none; }
.dayform:has(input[name=tell_everyone]:checked) .actionbar .state > span.said-all { display: block; }
.dayform.unsaved .actionbar .state #publish-said { color: var(--warn); }
.actionbar .quietline { display: flex !important; flex-wrap: wrap; gap: 0 var(--s4); align-items: center; margin-top: 2px; }
.actionbar .quietline button.quiet { min-height: 32px; font-size: var(--t-meta); color: var(--ink); text-align: left; }
.actionbar .tell { font-size: var(--t-meta); color: var(--muted); min-height: 32px; }
.barnote { margin: var(--s2) 0 0; }
/* After wrap the day is shown as it stands and nothing on it changes: no Change to press. */
.dayform fieldset:disabled :is(details.inlinechange > summary .change, .readchange .change) { display: none; }
.dayform fieldset:disabled details > summary { pointer-events: none; }
/* Nothing to publish: the bar stays at the foot of the form, not over the list of who to reach. The
   first change on the page brings it back into view (day.js), and a draft not published keeps it there. */
.dayform .actionbar.idle { position: static; box-shadow: none; border: 1px solid var(--rule); border-radius: var(--r-card); margin-left: 0; margin-right: 0; }
.dayform .actionbar .state b { display: inline; margin-right: .35em; }
.dayform .actionbar .state b + span.said-one { display: inline; }
@media (max-width: 640px) {
  .dayform .actionbar { gap: var(--s2); }
  .dayform .actionbar .state { flex-basis: 100%; }
  .dayform .actionbar .state b { display: none; }
  .dayform .actionbar .state > span.said-one, .dayform .actionbar .state > span.said-all { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
  .dayform:has(input[name=tell_everyone]:checked) .actionbar .state > span.said-one, .dayform .actionbar .state > span.said-all { display: none; }
  .dayform:has(input[name=tell_everyone]:checked) .actionbar .state > span.said-all { display: -webkit-box; }
  .actionbar .quietline button.quiet { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .dayform .actionbar #save-btn, .dayform .actionbar #publish-btn { flex: 1 1 auto; }
  /* Every tap on the page a thumb's worth: the day's links, a section's links, Undo, Tell everyone, the date. */
  .dayhead .fp a, .dayform ~ .dayacts button, .reachsec .sectionhead .acts a, .dayform .sectionhead .acts a { display: inline-flex; align-items: center; justify-content: center; min-height: var(--h-control); min-width: var(--h-control); }
  .actionbar .quietline button.quiet, .actionbar .tell, .tickline { min-height: var(--h-control); }
  .datechange input[type=date] { min-height: var(--h-control); }
}
.dayacts form { margin: 0; }

/* The stripboard. A set name wraps rather than hiding STOCKROOM behind COUNTER's ellipsis; the empty
   pile takes a narrow column rather than 260 of a phone's 358 pixels; each strip has Move to; and the
   board says it scrolls, with the days it holds named above it. */
.strip .pl { white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: break-word; hyphens: auto; line-height: 1.25; }
.board .col[data-day=""]:not(:has(.strip)) { flex: 0 0 132px; }
.board .col[data-day=""]:not(:has(.strip)) .strips { min-height: 96px; border: 1px dashed var(--field); border-radius: 4px; }
.strip .moveto { grid-column: 4; grid-row: 2; justify-self: end; white-space: nowrap; min-height: 28px; padding: 0 var(--s1); border: 0; background: transparent; color: var(--strip-ink);
  font-size: var(--t-label); text-decoration: underline; text-underline-offset: .2em; cursor: pointer; }
.strip .ci { grid-column: 2 / 4; }
@media (max-width: 640px) { .strip .moveto { min-height: var(--h-control); min-width: 64px; } }
.board header > a { display: inline-block; padding: 2px 0; }
@media (max-width: 640px) { .board header > a { display: inline-flex; align-items: center; min-height: var(--h-control); } }
.boardwrap { position: relative; }
.boardwrap::after { content: ""; position: absolute; top: 0; right: 0; bottom: var(--s3); width: 28px; pointer-events: none; opacity: 0; transition: opacity .2s;
  background: linear-gradient(to left, rgba(0, 0, 0, .16), transparent); border-radius: 0 var(--r-control) var(--r-control) 0; }
.boardwrap.more-right::after { opacity: 1; }
.board .col > header { scroll-margin-left: 280px; }
.boarddays { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s2); margin: 0 0 var(--s3); font-size: var(--t-meta); }
.boarddays a { display: inline-flex; align-items: center; min-height: 32px; padding: 0 var(--s2); border: 1px solid var(--rule); border-radius: 99px; text-decoration: none; background: var(--panel); }
.boarddays a.over { color: var(--muted); background: transparent; }
@media (max-width: 640px) { .boarddays a { min-height: 44px; } }
/* Move to: the days, as big targets, next to the strip that is moving. */
.movemenu { position: absolute; z-index: 20; background: var(--panel); border: 1px solid var(--field); border-radius: var(--r-card); box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
  padding: var(--s2); display: grid; gap: var(--s1); min-width: 15rem; max-width: calc(100vw - 32px); max-height: 70vh; overflow: auto; }
.movemenu p { margin: var(--s1) var(--s2); font-weight: 650; }
.movemenu button { text-align: left; min-height: 44px; }
.movemenu button[aria-current="true"] { color: var(--muted); }
@media (max-width: 640px) { .movemenu button { min-height: 48px; } }
@media (hover: none) { .keys { display: none; } }   /* a phone has no keys to pick a strip up with */

/* ==== The on-set surface (ux21, the onset fixer): the AD's day view on a phone, the company move, and
 * the day's report as a daily production report. Built from the tokens and components above; what is
 * here is only what those pages need and nothing else had. ================================== */

/* The day view: the day's facts and where the company is first, then the stamps, then the meal line;
   a bar at the foot holds the tabs and what is not sent, so the page leaves room under its last row. */
body.ad main { padding-bottom: calc(112px + env(safe-area-inset-bottom, 0px)); }
.adhead { margin: 0 0 var(--s2); }
.adtop { display: flex; justify-content: space-between; align-items: center; gap: 0 var(--s2); flex-wrap: wrap; }
.adtop .eyebrow { margin: 0; }
.adlinks { display: flex; gap: 0 var(--s1); font-size: var(--t-meta); margin: 0; }
.adlinks a { display: inline-flex; align-items: center; min-height: 48px; padding: 0 var(--s2); }
.adlinks a:last-child { padding-right: 0; }
.adfacts { display: flex; gap: var(--s1) var(--s2); flex-wrap: wrap; align-items: baseline; margin: var(--s1) 0 0; }
.adfacts .lbl { display: inline; margin: 0; }
.adfacts .adbig { font-size: var(--t-title); font-weight: 750; letter-spacing: -.01em; margin-right: var(--s3); }
.adfacts b { font-size: var(--t-head); }
.adwx { margin: 0 0 var(--s2); color: var(--muted); }
.adplace { margin: 0 0 var(--s1); }
.adplace .lbl { display: inline; margin: 0 var(--s1) 0 0; }
.adplacename { display: inline-block; font-size: var(--t-head); font-weight: 700; line-height: 1.3; padding: 13px 0; margin: -13px 0; }   /* the place, beside the time (spec 12.4), a 48 pixel target in a 22 pixel line */
.adplace #where-find { display: block; color: var(--muted); }
.adplace #where-note:empty { display: none; }
.adplace #where-note { margin: var(--s1) 0 0; }
.adcover { margin: 0 0 var(--s2); }
.adcover .lbl { display: inline; margin-right: var(--s1); }
/* Under way, from the crew call stamp (ad.js): the call and the address are known by then, and a stamp's note, which
   says what the button does, gives way to its time. The header had put the next stamp due under the bar at the foot
   (review/ux21/BALANCE.md). The place stays, a tap to Maps, as do sunset, weather and the cover set. */
.underway .adcall, .underway #where-find { display: none; }
.stampcell.done .stamp .note { display: none; }
.adacts { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s2); margin: var(--s2) 0; }
.adacts .tap { min-height: 52px; }
.adacts .tap:only-child { grid-column: 1 / -1; }
.adinc { border-left: 4px solid var(--bad); }
.adpanel { border: 2px solid var(--field); }
.adpanel label { margin-top: var(--s3); }
.card .adwide, .adwide { width: 100%; min-height: 56px; font-size: var(--t-head); margin-top: var(--s4); }
.adscene { margin: var(--s3) 0 var(--s1); }
/* A stamp waiting on the phone is drawn apart until the server has it: it turned green unsent. */
.stampcell.unsent { border-style: dashed; border-color: var(--warn); }
.stampcell.unsent .t::after { content: " · not sent"; color: var(--warn); font-size: var(--t-meta); }
.stampcell.needed { border-color: var(--warn); }
.stamp .need { color: var(--warn); font-size: var(--t-meta); font-weight: 650; margin-top: var(--s1); }
.stamps { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.stamp { min-height: 64px; }
.takeback button { min-height: 44px; }
/* The meal clock as one line that opens to the list, amber from thirty minutes out, red once late. */
.card.admeal { padding: var(--s2) var(--s4); margin: var(--s2) 0; }
.admeal summary { list-style: none; display: flex; align-items: center; min-height: 48px; font-size: var(--t-head); font-weight: 650; line-height: 1.3; }
.admeal summary::-webkit-details-marker { display: none; }
.admeal summary::after { content: "›"; margin-left: auto; padding-left: var(--s2); color: var(--muted); }
.admeal details[open] summary::after { content: "⌄"; }
.admeal.due { border-color: var(--warn); background: var(--warn-fill); }
.admeal.due .mealnext { color: var(--warn); }
.admeal.late { border-color: var(--bad); background: var(--bad-fill); }
.admeal.late .mealnext { color: var(--bad); }
.mealacts { display: flex; gap: var(--s2); flex-wrap: wrap; }
.mealacts:not(:has(button:not([hidden]))) { display: none; }
.mealacts button, .card .mealacts button { flex: 1 1 10rem; width: auto; margin: 0 0 var(--s2); padding: var(--s2) var(--s3); min-height: 48px; font-size: var(--t-body); }
.block { display: block; }
#meal-grace .block { margin-top: var(--s1); }
/* The stamps already pressed, one 48-pixel line of their times that opens to a take-back for each (round 21,
   BALANCE.md): the first stamp not yet pressed is then the first under the meal line. */
.pressed { margin: var(--s2) 0 0; }
.pressed summary { display: flex; align-items: center; min-height: 48px; color: var(--muted); list-style: none; }
.pressed summary::-webkit-details-marker { display: none; }
.pressed summary::after { content: "›"; margin-left: auto; padding-left: var(--s2); }
.pressed[open] summary::after { content: "⌄"; }
.pressedbacks { display: flex; flex-wrap: wrap; gap: var(--s2); padding: 0 0 var(--s2); }
.pressedbacks button { min-height: 44px; width: auto; margin: 0; }
/* The header belongs to The day; People and the pack open under one line (round 21, the design walk again, N3). */
.adstrip { display: none; margin: 0 0 var(--s2); }
#ad[data-tab="people"] .adhead, #ad[data-tab="pack"] .adhead { display: none; }
#ad[data-tab="people"] .adstrip, #ad[data-tab="pack"] .adstrip { display: block; }
/* An incident as one line at the top, its card under the stamps. */
.adincline { margin: 0 0 var(--s2); }
.adincline a { display: flex; align-items: center; min-height: 44px; color: var(--bad); font-weight: 650; }
/* The bar at the foot: the tabs where the thumb is, and what is not sent above them. */
.adbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 10; background: var(--panel); border-top: 1px solid var(--rule);
  box-shadow: 0 -6px 16px rgba(0, 0, 0, .08); padding: var(--s1) var(--s3) calc(var(--s2) + env(safe-area-inset-bottom, 0px)); }
.adbar .adtabs { max-width: 620px; margin: 0 auto; }
.adbar .adtabs button { min-height: 48px; }
.sendstate { max-width: 620px; margin: 0 auto var(--s1); font-size: var(--t-meta); font-weight: 650; line-height: 20px; text-align: center; color: var(--ok); }
.sendstate:empty { display: none; }
.sendstate.due { color: var(--warn); }
.sendstate.bad { color: var(--bad); }
/* People, by department, with a box to tick for sending home; whoever has gone is listed apart. */
.deptname { margin: var(--s4) 0 var(--s1); }
.addept .card.person { margin: var(--s1) 0; }
/* A person is one compact row: the name, their job and their call, with Call, Text and Time in a row under them at
   full width, and a time of their own folded under that. Beside a column 95 pixels wide the three buttons broke names
   and times over two lines each and the tab grew to 7.5 screens (round 21, the design walk again, N3). */
.card.person { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0 var(--s2); align-items: start; padding: var(--s2) var(--s3); margin: var(--s2) 0; }
/* Gone home is listed apart, and its row leaves the list. Written as .person.gone before the rule above, of the same
   weight, it lost to it: every row stayed, ticked and sendable again, and the list grew to 12.6 screens by 3 AM
   (round 21, the onset walk again). Three classes beat the two of the card's own rule wherever either stands. */
.card.person.gone { display: none; }
.card.person > .t-list, .card.person > details { grid-column: 1 / -1; }
.shrow { display: flex; gap: var(--s3); align-items: flex-start; min-height: 48px; margin: 0; padding: var(--s1) 0; color: inherit; font-size: var(--t-body); cursor: pointer; }
.shrow input[type=checkbox] { width: 26px; height: 26px; margin-top: 1px; flex: none; }
.shrow .adcall { display: block; }
.personacts { display: flex; gap: var(--s2); margin: 0 0 var(--s1); }
.adoff { margin: 0; }
.personacts .button, .card .personacts .button { min-height: 48px; min-width: 56px; margin-top: 0; padding: var(--s2) var(--s3); font-size: var(--t-body); }
.card.person details > summary { display: none; }   /* opened by the row's Time button */
.card.person details[open] { padding: var(--s2) 0; }
.personacts .t-open, .card .personacts .t-open { width: auto; min-height: 48px; min-width: 56px; margin-top: 0; padding: var(--s2) var(--s3); font-size: var(--t-body); }
.card.person .t-list { margin: 0; }
.goneitem { display: flex; justify-content: space-between; align-items: center; gap: var(--s2); min-height: 48px; }
.goneitem button { min-height: 48px; }
.sendbar { position: sticky; bottom: calc(96px + env(safe-area-inset-bottom, 0px)); z-index: 5; display: flex; gap: var(--s2); margin: var(--s4) 0 0;
  background: var(--panel); border: 1px solid var(--field); border-radius: var(--r-card); padding: var(--s2); box-shadow: 0 6px 16px rgba(0, 0, 0, .12); }
.sendbar button { flex: 1; min-height: 56px; }
.card.incident.unsent { border-style: dashed; border-color: var(--warn); }
.card.incident form { margin: 0; }
.card .dir a.phone { width: auto; }
.adnote summary { min-height: 48px; display: flex; align-items: center; font-weight: 650; }
/* The pack: each place with its way in and its emergency details, and every number a 48 pixel row. */
.packplace dd .tap { margin: var(--s1) 0; }
.packcalls { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s2); margin: var(--s2) 0 0; }
.packcalls .button, .card .packcalls .button { display: flex; flex-direction: column; align-items: flex-start; justify-content: center; min-height: 52px; margin: 0;
  padding: var(--s1) var(--s3); font-size: var(--t-body); font-weight: 650; text-align: left; overflow-wrap: anywhere; }
.packcalls small { font-size: var(--t-meta); font-weight: 500; color: var(--muted); }
.packcalls p { margin: 0; align-self: center; }
.packperson p { margin: var(--s1) 0 0; }
.card.packperson { padding: var(--s3); margin: var(--s2) 0; }
/* The report as a daily production report: a table of people or scenes is a list on a phone, its
   column names left off there since each row says what it is. */
.dprhead { margin-top: var(--s2); }
.dprtimes td:first-child { width: 40%; color: var(--muted); }
tr.deptrow th { padding-top: var(--s4); color: var(--ink); }
.dprincident { padding: var(--s2) 0; border-top: 1px solid var(--rule); }
.dprincident:first-child { border-top: 0; padding-top: 0; }
/* What the producer answers, first, each answer beside it (round 21, the walks again: design N2, wrap N3). */
.needs { border-left: 4px solid var(--bad); }
.needsitem { padding: var(--s2) 0; border-top: 1px solid var(--rule); }
.needsitem:first-of-type { border-top: 0; }
.needs details > summary { min-height: 44px; display: flex; align-items: center; }
@media (max-width: 480px) {
  table.stack thead { display: none; }
  table.stack tr.total th, table.stack tr.deptrow th { display: block; padding: 2px 0; }
  /* A person on one line on a phone: name, job, call to out. Twenty-five people were 13 screens. */
  table.dprpeople td { display: inline; padding: 0; }
  table.dprpeople td:first-child { font-weight: 650; }
  table.dprpeople td:nth-child(2)::before { content: " · "; }
  table.dprpeople td:nth-child(3)::before { content: " · call "; color: var(--muted); }
  table.dprpeople td.same { display: none; }   /* in at the call is the call, said once */
  table.dprpeople td:nth-child(4)::before { content: " · in "; color: var(--muted); }
  table.dprpeople td:nth-child(5)::before { content: " · out "; color: var(--muted); }
  table.dprpeople td:nth-child(6):not(:empty)::before { content: " · "; }
}
@media (max-width: 640px) { .dprlinks a, .dprlinks button { display: inline-flex; align-items: center; min-height: 48px; } }
@media print {
  .noprint { display: none !important; }
  .dprhead { display: grid; grid-template-columns: auto 1fr 1fr; }
}

/* The company move's own screen, for the office and a browser without the day view. */
.movecard .moveplace { margin: 0 0 var(--s2); }
.movecard .moveplace b, .moveplace { font-size: var(--t-title); font-weight: 700; line-height: 1.2; }
.movebutton { width: 100%; min-height: 56px; font-size: var(--t-head); }

/* ==== The crew page, rebuilt (ux21, the crew fixer) ===============================================
 * What views/crew/page.php needs beyond the components above, and nothing another page uses. */
/* The copy kept for no signal says so, at the top, when the worker shows it (public/js/crew-sw.js); and
 * calls not emailed while a new address waits on the production are said in a line the same way. */
.kept, .onhold { background: var(--warn-fill); color: var(--ink); border-left: 3px solid var(--warn); border-radius: var(--r-control); padding: var(--s2) var(--s3); margin: 0 0 var(--s3); }
.crewhead h1.who { margin: 0; font-size: var(--t-head); }
/* What is still owed, one card above the calls: each item its words, then its one action. */
.owed { background: var(--panel); border: 1px solid var(--field); border-left: 4px solid var(--warn); border-radius: var(--r-card); padding: var(--s3) var(--s4); margin: 0 0 var(--s4); }
.owed .plainlist li { padding: var(--s2) 0; }
/* The card's own padding is the first item's top and the last one's foot: one item waiting costs its
 * words and its button, which on a phone is what keeps Confirm on the first screen under it. */
.owed .plainlist li:first-child { padding-top: 0; }
.owed .plainlist li:last-child { padding-bottom: 0; }
.owed li > p { margin: 0 0 var(--s2); }
.owed li > :last-child { margin-bottom: 0; }
.owed form { margin: 0; }
.callcard .lead-in { font-size: var(--t-head); font-weight: 600; margin: var(--s2) 0 var(--s3); }
.callcard.off .big { margin-top: var(--s2); }
.callcard.quiet { background: transparent; }
.callcard .answer { display: flex; gap: var(--s2); margin: 0; }
.callcard .answer button { flex: 1; }
/* Confirm, and what was confirmed where it was pressed: a Confirm lands the page with the row most of
   a screen down, so the call and the place it confirms stay in view above it. */
.confirmrow { scroll-margin-top: 65vh; }
.confirmrow form { margin: 0; }
.confirmrow .confirmed { display: block; font-size: var(--t-head); font-weight: 650; color: var(--ink); margin: var(--s4) 0 var(--s2); line-height: 1.35; }
.confirmrow .confirmed::before { margin-right: var(--s1); }
.confirmrow .confirmed .meta { font-weight: 500; }
.note-sent { background: var(--warn-fill); border-left: 3px solid var(--warn); border-radius: var(--r-control); padding: var(--s2) var(--s3); margin: var(--s3) 0 0; scroll-margin-top: 50vh; }
/* The AD's answer under the note it answers, set apart from it by a rule. */
.note-sent .answered { margin-top: var(--s3); padding-top: var(--s2); border-top: 1px solid var(--rule); }
.note-sent p { margin: 0 0 var(--s1); }
.callcard details.more form { margin: var(--s2) 0 0; }
.callcard details.more form button { margin: var(--s2) 0; }
.callcard .weatherline { margin-bottom: var(--s1); row-gap: 2px; }
.callcard .weatherline small { font-size: var(--t-meta); flex-basis: 100%; }
.callcard .top a { min-height: 48px; margin: -14px 0; }   /* "If someone is hurt" is a thumb's row, where the foundation gave it 44 */
.callcard .top { flex-wrap: wrap; }
.callcard .top .eyebrow { white-space: nowrap; }   /* TOMORROW · TUE OCT 6 on one line; on a 320px phone the link goes under it */
/* The emergency details folded to the one line that names the hospital. */
details.sos { margin: var(--s4) 0 0; }
details.sos > summary { list-style: none; display: flex; flex-direction: column; gap: 2px; padding: var(--s1) 0; }
details.sos > summary::-webkit-details-marker { display: none; }
details.sos > summary > span:last-child { font-weight: 600; }
details.sos > summary > span:last-child::after { content: " ›"; color: var(--muted); }
details.sos[open] > summary > span:last-child::after { content: " ⌄"; }
details.sos .stack { margin-bottom: 0; }
/* A panel's own padding is the room above what it opens on (the details as they stand, read first). */
#details .panel > .stack:first-child { margin-top: 0; }
details.past-wrap .stack, details.past-wrap .taps { margin-left: var(--s4); margin-right: var(--s4); }
/* A folded list's heading with the line under it saying what it holds. */
details.more > summary small { display: block; font-weight: 500; color: var(--muted); font-size: var(--t-meta); }
.crewlist .dept { margin: var(--s4) 0 0; }
.gear li { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--s3); }
.gear li form { margin: 0; flex: none; }
.gear-add > p { margin: 0; }
.gear-add > p:first-child { flex: 0 0 6.5rem; }
.gear-add > p:last-child { flex: 1; }
.place-card .place-name { margin: 0; font-size: var(--t-head); }
.place-card .where a { display: inline-flex; align-items: center; min-height: 48px; }   /* a thumb's row, where it was a 15px line */
.el-cat { margin: var(--s4) 0 0; }
fieldset.consent { border: 0; padding: 0; margin: 0 0 var(--s3); }
fieldset.consent legend { margin-bottom: var(--s1); }
#d-dates input[type=date] { max-width: 11rem; }
.minor-said { margin-top: var(--s3); }
.footlinks { text-align: center; margin-top: var(--s5); }
.footlinks + .footlinks { margin-top: 0; }
@media print { .kept, details.sos:not([open]) { display: none !important; } }

/* ==== The home surface's own (round 21, ux-home): the budget, Home, Tonight, This server, closing out ====
 * Added beside the foundation's components, and built from its tokens. Each part says what it is for. */

/* The budget: the top sheet and every section are one grid of five columns, so Cash is Cash all the way
   down (it was a table sized by its own contents, 161px left of the lines below it). A header row names
   the columns at a desk; on a phone each figure carries its own word instead. */
.ledger.lines .lrow, .ledger.lines .edit .fields { grid-template-columns: minmax(0, 1fr) repeat(4, 8.5em); }
.ledger .lrow.head { padding-top: 0; }
.ledger .lrow.head > * { font-size: var(--t-label); font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.ledger .lrow.total { font-weight: 700; }
.ledger .lrow.loose .what a { color: var(--muted); }
.ledger .unit { display: none; }
@media (max-width: 640px) {
  .ledger.lines .lrow { grid-template-columns: repeat(2, minmax(0, 1fr)); justify-content: stretch; column-gap: var(--s3); }
  .ledger.lines .lrow > .what { grid-column: 1 / -1; }
  .ledger.lines .lrow > .n { text-align: left; }
  .ledger.lines .lrow > .n:empty { display: none; }
  .ledger.lines .lrow.head > .n { display: none; }
  .ledger .unit { display: inline; color: var(--muted); }
  .ledger.lines .edit .fields { grid-template-columns: 1fr 1fr; }
}

/* The budget's smaller things, each a target a finger or a pointer can take. */
.ledger .what a.tag { display: inline-flex; align-items: center; min-height: 26px; }
.receipts .photo a, .ledger.receipts + p a, .receipts > p.meta a { display: inline-flex; align-items: center; min-height: 32px; }
details#add-line > summary { padding: var(--s2) 0; min-height: 28px; }
.addline { margin-top: var(--s2); }
.addline .end { align-self: end; }
.panel.rates p { margin: 2px 0; }
@media (max-width: 640px) { .ledger .what a.tag, .receipts .photo a, .receipts > p.meta a { min-height: 48px; min-width: 48px; justify-content: center; } details#add-line > summary { min-height: 48px; } }
/* A receipt's vendor and who paid, under what it was for; the edit form's fields flow in rows. */
.receipts .what small { display: block; color: var(--muted); font-size: var(--t-meta); }
.receipts .what small.warn { color: var(--warn); }
.ledger.receipts .edit .fields { grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); grid-template-areas: none; }
.ledger.receipts .edit .fields > * { grid-area: auto; }
.ledger.receipts .edit .fields .acts { grid-column: 1 / -1; }
.ledger.receipts .edit .back { align-self: end; }
.newreceipt .end { align-self: end; }

/* Printed, the budget is the accountant's page: every line and receipt as it reads, without its edit
   form, and no form to add one. The foundation's print hides a closed fold whole, and a budget row is a
   fold whose summary is the row itself, so the lines and receipts printed as blank rows (before and after). */
@media print {
  .ledger details:not([open]) { display: block !important; }
  .ledger details > .edit, .newreceipt { display: none !important; }
}

/* The script's draft review, a table to each kind of row, reads as one list: the same columns in each (round 21 B, sd, s4). */
table.draftrows { table-layout: fixed; }
table.draftrows th:nth-child(1) { width: 40%; }
table.draftrows th:nth-child(3) { width: 30%; }

/* The wrap, below the list it records (views/wrap/wrap.php). Each tick is a label as tall as its row,
   so the target is the row's height and not the 18-pixel box; the notes form's fields flow in the grid. */
.wrapgo .row input { max-width: 12rem; }
table.credits td.tick { width: 1%; padding: 0; }
table.credits label.tickbox { display: flex; align-items: center; justify-content: center; min-width: 28px; min-height: 24px; margin: 0; cursor: pointer; }
table.credits label.who { color: inherit; font-size: inherit; margin: 0; }
.panel p.flush { margin: 0; }
.notesform .wide { grid-column: span 2; }
.notesform .end { align-self: end; }
label.plain { color: inherit; }
.wrapgo p.small a, .notesform label.plain { display: inline-flex; align-items: center; min-height: 32px; }
@media (max-width: 760px) { .notesform .wide { grid-column: 1 / -1; } }
@media (max-width: 640px) { table.credits label.tickbox { min-width: 48px; min-height: 48px; } .wrapgo p.small a, .notesform label.plain { min-height: 48px; } }
/* Printed, the credits are a list to read and hand on: no targets, and no form for notes. */
@media print { table.credits label.tickbox { min-height: 0; min-width: 0; } .notesform { display: none; } }

/* Closing out: To close's groups are labels in the list, each with its own mark (views/projects/show.php). */
.toclose .todo > li.group { padding-bottom: 0; }
.toclose .todo > li.group .lbl { display: inline; margin-right: var(--s2); }
.toclose .todo > li.group + li { border-top: 0; }
.toclose .ring.blank { visibility: hidden; }   /* a group with lines left: its lines carry the marks */

/* Home (views/projects/show.php, as review/ux21/mockups/home.html sets it). */
.panel.list { padding: var(--s2) var(--s4); }
.yours > h2:first-child { margin-top: var(--s6); }
.todo .acts .button.primary { color: var(--accent-ink); }
.todo details.names > summary { font-size: var(--t-meta); color: var(--muted); padding: var(--s1) 0; min-height: 24px; box-sizing: border-box; }
.todo details.names p { margin: var(--s1) 0 0; }
.hero .facts .chip { white-space: normal; }   /* a forecast is words, and wraps rather than running off the card */
.hero .reach .said { flex: 1 1 22rem; margin: 0; }
.hero .reach .said a, .hero .row2 .said a { font-weight: 600; }
.hero .row2 .said { margin: 0; }
details.more { margin: var(--s3) 0; }
details.more > .panel { margin-top: var(--s2); }
.panel.notice p { margin: 0 0 var(--s1); }
.panel.notice p:last-child { margin: 0; }
.adddays form { margin-top: var(--s2); align-items: flex-end; }
.meta.foot { margin-top: var(--s5); }
/* First steps' links and the links at a page's foot are targets, not lines of small text. */
.firsts .todo p a, .meta.foot a { display: inline-flex; align-items: center; min-height: 24px; }
@media (max-width: 640px) {
  .firsts .todo p a, .meta.foot a { min-height: 48px; }
  .todo details.names > summary { min-height: 48px; padding: 14px 0; }
}

/* This server (views/admin/check.php): the setup the app checks, folded under the five plain lines. */
.setup td.label { width: 13em; }
.setup .mark { display: inline-block; width: 1.4em; }
.drill .row { margin-top: var(--s2); }
.drill .row input { flex: 1 1 14rem; width: auto; }
.newprod form .grow { flex: 2 1 14rem; }
.newprod form .go, .adddays form .go { align-self: flex-end; }
/* A page's links under its title are a thumb's target on a phone, as every tap there is (principle 6). */
@media (max-width: 640px) { .taphead .fp a { display: inline-flex; align-items: center; justify-content: center; min-height: 48px; min-width: 48px; } }

/* ==== People surface: the pasted list, the team, papers, and the pages strangers sign on ===========
 * Added by the people fixer of the ux21 pass (review/work/ux-people), built from the tokens above.
 * The pasted list: each line a row, its box to tick at the left, its fields beside it, what is wrong with it
 * under them. <div class="pasterow"><label class="pick"><input type="checkbox"></label><div class="cells">…</div>…</div> */
.pastedept { margin: var(--s5) 0 var(--s2); }
.pastelist { padding-top: var(--s1); padding-bottom: var(--s1); }
.pasterow { display: grid; grid-template-columns: 32px minmax(0, 1fr); column-gap: var(--s3); padding: var(--s3) 0; border-top: 1px solid var(--rule); }
.pasterow:first-child { border-top: 0; }
.pasterow > .pick { grid-row: 1 / span 12; display: flex; align-items: flex-start; justify-content: center; margin: 0; padding-top: 30px; min-height: var(--h-control); }
.pasterow > :not(.pick) { grid-column: 2; }
.pasterow .cells { display: grid; grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); gap: var(--s2) var(--s3); }
.pasterow .cells label { margin-bottom: 2px; }
.pasterow:has(> .pick input:not(:checked)) .cells input { color: var(--muted); }
.pasterow .pastesaid { margin: var(--s2) 0 0; }
.pasterow ul.problems { margin-top: var(--s2); }
.pasterow .ask { display: flex; flex-wrap: wrap; gap: 0 var(--s5); margin-top: var(--s1); }
.pasterow label.row { color: var(--ink); margin: var(--s1) 0 0; min-height: 32px; }
@media (max-width: 640px) { .pasterow label.row { min-height: var(--h-control); } .pasterow > .pick { padding-top: 28px; } }
/* Under 18 on a line opens the guardian's fields, where the browser can tell. */
.minorline .guardian.cells { margin-top: var(--s2); }
@supports selector(:has(*)) { .minorline .guardian { display: none; } .minorline:has(input[name^="minor["]:checked) .guardian { display: grid; }
  .minorline:has(input[name^="minor["]:checked) label.guardian { display: flex; } .minorline:has(input[name^="minor["]:checked) p.guardian { display: block; } }
.pasteleft { margin: var(--s2) 0 var(--s3); }
.pasteleft > summary { font-weight: 500; color: var(--muted); }
.pasterow.quietrow { align-items: center; }
.pasterow.quietrow > .pick { padding-top: 0; }
.pasterow.quietrow p { margin: 0; }
/* A line reads as text with Change beside it, and opens on its fields: a line in red opens by itself. */
.pasterow > .pick { padding-top: 7px; align-items: flex-start; min-height: 32px; }
.pasterow:has(> details.linefix[open]) > .pick { padding-top: 30px; align-items: flex-start; }
details.linefix > summary { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3); list-style: none; min-height: 32px; padding: var(--s1) 0; }
details.linefix > summary::-webkit-details-marker { display: none; }
details.linefix > summary .shown { min-width: 0; overflow-wrap: anywhere; }
details.linefix > summary :is(.change, .close) { font-size: var(--t-meta); text-decoration: underline; text-underline-offset: .2em; flex: none; }
details.linefix > summary .close, details.linefix[open] > summary :is(.shown, .change) { display: none; }
details.linefix[open] > summary .close { display: inline; }
details.linefix[open] > summary { justify-content: flex-end; min-height: 0; padding: 0; }
@media (max-width: 640px) { details.linefix > summary { min-height: var(--h-control); } .pasterow > .pick { min-height: var(--h-control); padding-top: 13px; } }
/* The bar that sends the list: its state and Cancel on one line, then the two buttons side by side on a phone. */
.pastebar .state { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--s3); }
.pastebar .state b { display: inline; }
.pastebar .state .bad { color: var(--bad); }
@media (max-width: 640px) {
  .pastebar { gap: var(--s2); }
  .pastebar .state { flex: 1 1 100%; }
  .pastebar button { flex: 1 1 0; min-width: 0; white-space: normal; line-height: 1.25; padding-left: var(--s2); padding-right: var(--s2); }
}

/* Paperwork: each paper a row of the .todo list, what it would state under its name, its actions at its end,
 * and what to record for it folded under it. <li id="p-…"><span class="ring"></span><div>…</div><div class="acts">…</div><details class="rowmore">…</details></li> */
.papergroup { margin: var(--s5) 0 var(--s2); }
.paperrows .rowmore { grid-column: 2 / -1; margin: 0; }
.paperrows details.rowmore > summary { color: var(--muted); padding: 2px 0; }
.paperrows .acts form { margin: 0; }
.paperrows .said-here { color: var(--ink); background: var(--warn-fill); border-left: 3px solid var(--warn); padding: var(--s1) var(--s2); border-radius: var(--r-control); margin-top: var(--s1); }
.paperrows :is(form, details).inline { display: inline-block; margin: 0 var(--s3) 0 0; vertical-align: baseline; }
.paperrows p.meta, .sendrows p.meta { margin: 2px 0; }
.sendall { display: flex; align-items: center; justify-content: space-between; gap: var(--s3) var(--s4); flex-wrap: wrap; }
.sendall > div { flex: 1 1 20rem; }
.sendrows > li { grid-template-columns: 32px minmax(0, 1fr); }
.sendrows .pick { margin: 0; display: flex; align-items: flex-start; min-height: 32px; padding-top: 2px; }
@media (max-width: 640px) { .sendrows .pick { min-height: var(--h-control); } .paperrows details.rowmore > summary { min-height: var(--h-control); } }
.paperwords { white-space: normal; line-height: 1.55; max-width: 70ch; }
/* A paper as a contract reads (Paperwork::blocks): its opening as a heading, its terms in a box of labels and values. */
.paperwords p { margin: 0 0 var(--s2); }
.paperwords .paperhead { margin-bottom: var(--s3); }
.paperterms { display: grid; grid-template-columns: minmax(7rem, max-content) 1fr; margin: 0 0 var(--s3); border: 1px solid var(--rule); border-radius: var(--r-control); }
.paperterms > div { display: contents; }
.paperterms dt, .paperterms dd { margin: 0; padding: var(--s1) var(--s2); border-top: 1px solid var(--rule); }
.paperterms > div:first-child dt, .paperterms > div:first-child dd { border-top: 0; }
.paperterms dt { font-size: .75rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
@media (max-width: 30rem) { .paperterms { grid-template-columns: 1fr; } .paperterms dd { border-top: 0; padding-top: 0; } }

/* The team: one row a person, their terms in fields, one Save at the end (ux21, B13). A table's columns
 * at a desk; on a phone each person is a card, their name across it and the fields two by two. */
.teamgroup { margin: var(--s5) 0 var(--s2); }
.teamrows { padding-top: var(--s1); padding-bottom: var(--s1); }
.teamrow { display: grid; grid-template-columns: minmax(8rem, 1.1fr) minmax(8rem, 1.2fr) minmax(9rem, 1fr) minmax(6rem, .8fr) minmax(8rem, 1.1fr); gap: var(--s2) var(--s3);
  align-items: center; padding: var(--s2) 0; border-top: 1px solid var(--rule); }
.teamrow:first-child, .teamhead + .teamrow { border-top: 0; }
.teamrow .who { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.teamrow label { margin: 0; min-width: 0; }
.teamrow .cap { display: none; }
.teamhead { font-size: var(--t-label); font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); padding-bottom: 0; }
/* On a phone the bar is its button and Cancel, one line: what it does is said once above the table. */
@media (max-width: 640px) { .teambar .state span { display: none; } .teambar .state { flex: 1 1 auto; } .teambar { flex-wrap: nowrap; } }
@media (max-width: 760px) {
  .teamhead { display: none; }
  .teamrow { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); padding: var(--s3) 0; }
  .teamrow .who { grid-column: 1 / -1; }
  .teamrow .cap { display: block; font-size: var(--t-label); font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin-bottom: 2px; }
}

/* People: one table, its columns named once, each department a row across it as a crew list heads them. */
.peoplelist tr.grouprow th { padding-top: var(--s4); font-size: var(--t-label); font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); border-bottom: 1px solid var(--rule); }
.peoplelist tr:nth-child(2).grouprow th { padding-top: var(--s3); }
/* "Not told · Email them": a staff member nobody has told they are staff, and the one press that tells them, in the row
   (round 21 B, s10). The button is the words, as tall as a press needs. */
.peoplelist td form.inline { display: inline; margin: 0; }
.peoplelist td form.inline button { vertical-align: baseline; font-size: inherit; }
/* Beside Send invitations, while no shoot day stands: the invitations will not say when (round 21 B, s13). */
.nodays { display: block; margin-top: var(--s2); }

/* The days somebody is booked for, a grid of ticks: one to a line on a phone, as many as fit at a desk. */
.bookeddays { display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); gap: 0 var(--s4); }
.bookeddays label { margin: 0; }
/* A box ticked on a person's page is a whole row to a thumb on a phone: booked days, under 18, departments. */
@media (max-width: 640px) { label.tick { min-height: var(--h-control); } .teamrow .who a { display: inline-flex; align-items: center; min-height: var(--h-control); } }

/* From earlier productions: a production to a fold, each person a box to tick with their job there. */
.earlier details.more + details.more { border-top: 1px solid var(--rule); }
.earlierlist { margin: 0 0 var(--s2); }
.earlierlist label.row { color: var(--ink); margin: 0; min-height: 32px; align-items: center; }
@media (max-width: 640px) { .earlierlist label.row { min-height: var(--h-control); } }

/* ==== Minors (ux21 step 3, the minors fixer): a minor's latest time, on the phone, the day page, the
 * card and the person page; the adult on set; the guardian's view. Built from the tokens above. ====== */
/* The phone's header line: each minor and when they are done, amber from 45 minutes out, red from 15. */
.adminor { margin: 0 0 var(--s2); padding: var(--s2) var(--s3); border-left: 3px solid var(--rule); border-radius: var(--r-control); font-size: var(--t-body); }
.adminor .block { display: block; }
.adminor.due { border-left-color: var(--warn); background: var(--warn-fill); color: var(--ink); }
.adminor.late { border-left-color: var(--bad); background: var(--bad-fill); color: var(--ink); font-weight: 650; }
/* Beside a minor among the people: the adult on set and the guardian, each a number to call. */
.adminorwho { margin: var(--s1) 0 0; }
.card.person > .adminorwho { grid-column: 1 / -1; }   /* a row of its own under the name and the buttons */
.adminorwho p { margin: var(--s1) 0; }
.adminorwho .button { min-height: 48px; margin: var(--s1) 0 0; padding: var(--s2) var(--s3); font-size: var(--t-body); }
/* The day page's calls: a minor's "Done by" under the call time. */
/* The label over the field, as the call's column is too narrow for both on one line and the time whole. */
.callrow .doneby { display: grid; gap: 2px; margin: var(--s1) 0 0; color: var(--ink); }
.callrow .doneby .lbl { margin: 0; }
/* With no hours and none set, the field is a step of its own, drawn plain so an empty one looks empty. */
.callrow details.doneby { display: block; }
.callrow details.doneby > summary { font-size: var(--t-meta); text-decoration: underline; text-underline-offset: .2em; }
.callrow details.doneby label { display: grid; gap: 2px; margin: var(--s1) 0 0; }
.callrow details.doneby input { width: 100%; }
/* The crew card and the guardian's view: "Done by" beside the call, as the crew call sits. */
.yourcall .doneby b { color: var(--ink); }
/* The person page's permit and hours, and the consent's question about the adult on set. */
.minorrecord select { width: 100%; }
.minorrecord .wide { grid-column: span 2; }   /* the permit's kind reads whole: "School district employment certificate" */
@media (max-width: 760px) { .minorrecord .wide { grid-column: 1 / -1; } }   /* one column there: a span of 2 would make a second, and halve the rest */
fieldset.onsetadult { border: 1px solid var(--rule); border-radius: var(--r-control); padding: var(--s3); margin: 0 0 var(--s3); }
fieldset.onsetadult legend { font-weight: 650; padding: 0 var(--s1); }
fieldset.onsetadult label.row { min-height: 48px; align-items: center; margin: 0; }

/* ==== A day at more than one place (ux21 step 3, the two-places fixer): the day page's places and who
 * reports where, the crew card's places, the phone's move to a numbered place. Built from the tokens above. */
/* The day page: the places as the day has them, numbered, then Change opens a row a place. */
.placelist { list-style: none; margin: var(--s1) 0 0; padding: 0; display: grid; gap: var(--s2); }
.placelist li { display: grid; grid-template-columns: 1.6em minmax(0, 1fr); gap: var(--s2); align-items: baseline; }
.placelist b { font-size: var(--t-head); }
.placelist p { margin: 0; }
:is(.placelist, .placerow) .num { font-weight: 700; font-size: var(--t-head); font-variant-numeric: tabular-nums; }   /* the place name's own size and weight: no new step on the scale */
.placesform { display: grid; gap: var(--s2); }
.placesform > p.meta { margin: 0; }
.placerow { display: grid; grid-template-columns: 1.6em minmax(0, 1fr) auto; gap: var(--s2); align-items: center; }
/* WebKit counts a menu's longest choice as the page's width, however narrow the menu is drawn: the places editor's
 * menus scrolled a 320 phone sideways to 338 (round 21 B, d2). Clipped to the menu, the choices are still whole in it. */
.placerow select { min-width: 0; overflow: hidden; }
.placerow .moveat { display: flex; gap: var(--s1); align-items: center; margin: 0; font-size: var(--t-meta); color: var(--muted); white-space: nowrap; }
.placerow .moveat input { width: auto; }
.placerow.addplace { opacity: .85; }
/* Open, the places take the facts card's whole width, under the crew call and the forecast. Beside the crew call, the
 * forecast went under it and widened that column to 567 pixels, so the editor had 344, cut "2. Lewis & Clark La…" and
 * scrolled the page sideways at 1,280 (round 21 B, d2; before it, a name was cut to "Lewis & C"). Only where the card
 * has columns: in one, from 760 pixels down, it has the width already. */
@media (min-width: 761px) {
  .dayfacts:has(> .where > details.placesedit[open]) { grid-template-columns: auto minmax(0, 1fr); }
  .dayfacts .where:has(> details.placesedit[open]) { grid-column: 1 / -1; grid-row: 2; }
}
.placescenes, .placedeptlist { display: grid; gap: var(--s1); margin-top: var(--s2); }
details.placedepts { margin-top: var(--s2); }
/* A press's height: at the card's full width its words fit one line of 21 pixels (round 21 B, d2). */
details.placedepts > summary { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s3); align-items: center; min-height: var(--h-compact); cursor: pointer; }
.placescene { display: grid; grid-template-columns: minmax(0, 1fr) minmax(8rem, 45%); gap: var(--s2); align-items: center; margin: 0; font-size: var(--t-meta); color: var(--ink); }
.placescene select { min-width: 0; overflow: hidden; }
@media (max-width: 640px) {
  .placerow { grid-template-columns: 1.6em minmax(0, 1fr); }
  .placerow .moveat, .placerow > .meta { grid-column: 2; }
  .placerow .moveat input, .placescene select { min-height: var(--h-control); }
  .placescene { grid-template-columns: minmax(0, 1fr); }
}
/* Home's facts card and the report's header: a place a line, its number and name, then when. */
:is(.factsplace, .dprplace) { margin: 0 0 var(--s1); }
.factsplace b { font-size: var(--t-head); }
/* The phone: the day's places under Where, and the planned move as the first of the header's buttons. */
.adplaces { margin: 0 0 var(--s2); }
.adacts .movenext { grid-column: 1 / -1; border-color: var(--ink); font-weight: 700; }
/* The crew card: the day's places in one line under Where, each later place with its way in, and each place's emergency details. */
.placesline { margin: var(--s1) 0 0; font-size: var(--t-meta); color: var(--muted); }
.laterplace { margin-top: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--rule); }
.sosplace { margin-top: var(--s2); }
.sosplace .lbl { color: var(--ink); }

/* ---- State colours, last, so a state always wins over a grey that only says secondary ---------- */
/* `.origin` was declared after `.warn`, so a person's conflict warning ("origin warn") rendered grey. */
.warn { color: var(--warn); } .bad { color: var(--bad); } .good { color: var(--ok); }

/* ---- Print: a page prints as the document it shows, without the app around it ------------------ */
@page { margin: .6in .5in; }
@media print {
  :root { color-scheme: light; --bg: #fff; --panel: #fff; --fill: #fff; --ink: #000; --muted: #444; --rule: #bbb; --field: #777;
    --accent: #000; --accent-ink: #fff; --ok: #1e5a32; --ok-fill: #fff; --warn: #6b4708; --warn-fill: #fff; --bad: #8f1d17; --bad-fill: #fff;
    --strip-int-d: #ffffff; --strip-ext-d: #fff4b8; --strip-int-n: #cfe0ff; --strip-ext-n: #cdeccf; --strip-set: #f3e8ff; --strip-ink: #000; --strip-muted: #444;
    --t-display: 26pt; --t-title: 16pt; --t-head: 12pt; --t-body: 10.5pt; --t-meta: 9pt; --t-label: 8pt; }
  body, body.crew { --t-body: 10.5pt; --t-display: 26pt; background: #fff; color: #000; }
  header.bar, .side, .actionbar, .flash, .kbd, .tap, .taps, .noprint, details:not([open]),
  button:not([aria-pressed="true"]), .button, .readchange .change, .readchange .cancel, .doc .edit { display: none !important; }
  main, main.wide, body.crew main, body.ad main { max-width: none; padding: 0; }
  .frame { display: block; }
  .panel, .card, .hero, .callcard, .sos { border: 0; border-radius: 0; padding: 0; background: none; box-shadow: none; }
  .hero .when { border: 0; }
  a { text-decoration: none; }
  /* A field prints as what is in it. */
  :is(input:not([type=checkbox]):not([type=radio]), select, textarea) { border: 0; padding: 0; min-height: 0; background: none; appearance: none; -webkit-appearance: none; }
  textarea { field-sizing: content; resize: none; }
  input::-webkit-calendar-picker-indicator { display: none; }
  .strip { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  /* A label stays with what it labels, and a row is never split across two pages. Not every <label>:
     a name that labels a row's box is one on every row, and avoiding a break after each moved a whole
     table to the next page. */
  h1, h2, h3, .eyebrow, .lbl, dt, th, .section, .sectionhead, .card .when, .changed { break-after: avoid; page-break-after: avoid; }
  .card .call, .big, .lbl + *, dd { break-before: avoid; page-break-before: avoid; }   /* a call never starts a page away from "Your call" */
  tr, li, dd, .facts > div, .stack > div, .readchange, .person-chip, .changed, .sos { break-inside: avoid; page-break-inside: avoid; }
  thead { display: table-header-group; }
  p { orphans: 3; widows: 3; }
}

/* The shot list printed, after the print block above so it wins over its closed folds (the places fixer's block).
   Printed for the camera cart, the list is the list: on an editor's page each shot's heading (number, setup, size,
   lens, movement) is the label of its Change fold, and print hides every closed fold, so the DP's own printout lost
   every one and kept the descriptions (ux21, the department heads walked again, 1). The label prints with the words
   under it, open or closed, and never the form; the day's chips, the way back and the order's controls do not print. */
@media print {
  .shot-read > details { display: block !important; }
  .shot-read > details > :not(summary), .shot-read > details > summary :is(.change, .cancel) { display: none !important; }
  .shot-read > .shown { display: block !important; }
  .shotdays, .shotorder, .shot-move, details.shotadd, .backrow { display: none !important; }
}
