/* Layout: app shell. Left navigation, top bar with search and view controls, one working page per route.
   Direction: Instrument. Cool neutrals, one blue accent, status colors reserved for status. */
:root{
  --bg:#F7F8FA; --surface:#FFFFFF; --surface-2:#F7F8FA; --border:#E3E6EB; --border-strong:#D5DAE1; --rule:#EEF0F3;
  --ink:#0F1720; --muted:#55606E; --nav:#3A4553;
  --accent:#1D4ED8; --accent-ink:#FFFFFF; --accent-soft:#EAF0FE; --accent-soft-ink:#1D4ED8; --link:#1D4ED8;
  --red:#A32014; --red-bg:#FCE8E5; --amber:#7A4A00; --amber-bg:#FBEFD0; --amber-border:#C9952C;
  --green:#0B6B43; --green-bg:#E2F4EA; --gray-ink:#3A4553; --gray-bg:#EEF0F3;
  --flag-row:#FFF6F4; --step-done:#9DB7F5; --overlay:rgba(15,23,32,.45); --shadow:0 12px 40px rgba(15,23,32,.18);
  --paper:#FFFFFF; --paper-ink:#111827; --paper-rule:#111827; --paper-muted:#4B5563; --paper-hl:#EAF0FE; --paper-flag:#FBEFD0;
  --font:'Geist',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
  --mono:'Geist Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --bg:#0C0E12; --surface:#14171C; --surface-2:#101318; --border:#262B33; --border-strong:#323843; --rule:#1E2229;
    --ink:#E8EBF0; --muted:#9AA4B2; --nav:#B9C1CC;
    --accent:#2F5FE0; --accent-ink:#FFFFFF; --accent-soft:#1A2540; --accent-soft-ink:#A9C2FF; --link:#8FB0FF;
    --red:#FF9F92; --red-bg:#361814; --amber:#F0C569; --amber-bg:#33280F; --amber-border:#8A6A1F;
    --green:#7FD6A8; --green-bg:#12281E; --gray-ink:#B9C1CC; --gray-bg:#1E2229;
    --flag-row:#1C1618; --step-done:#3B5BB5; --overlay:rgba(0,0,0,.6); --shadow:0 12px 40px rgba(0,0,0,.5);
    color-scheme:dark;
  }
}
:root[data-theme="dark"]{
  --bg:#0C0E12; --surface:#14171C; --surface-2:#101318; --border:#262B33; --border-strong:#323843; --rule:#1E2229;
  --ink:#E8EBF0; --muted:#9AA4B2; --nav:#B9C1CC;
  --accent:#2F5FE0; --accent-ink:#FFFFFF; --accent-soft:#1A2540; --accent-soft-ink:#A9C2FF; --link:#8FB0FF;
  --red:#FF9F92; --red-bg:#361814; --amber:#F0C569; --amber-bg:#33280F; --amber-border:#8A6A1F;
  --green:#7FD6A8; --green-bg:#12281E; --gray-ink:#B9C1CC; --gray-bg:#1E2229;
  --flag-row:#1C1618; --step-done:#3B5BB5; --overlay:rgba(0,0,0,.6); --shadow:0 12px 40px rgba(0,0,0,.5);
  color-scheme:dark;
}
*,*::before,*::after{box-sizing:border-box}
html,body{height:100%}
body{margin:0;background:var(--bg);color:var(--ink);font:14px/1.45 var(--font)}
h1,h2,h3,p,dl,dd,ol,ul{margin:0;padding:0}
ol,ul{list-style:none}
h1{font-size:22px;font-weight:600;letter-spacing:-.015em;text-wrap:balance}
h2{font-size:15px;font-weight:600}
h3{font-size:14px;font-weight:600}
a{color:var(--link)}
button,input,select,textarea{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums}
.muted{color:var(--muted)} .small{font-size:12px} .s13{font-size:13px} .b{font-weight:500} .bb{font-weight:600}
.red{color:var(--red)} .green{color:var(--green)} .amber{color:var(--amber)}
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.right{text-align:right} .ctr{text-align:center} .nowrap{white-space:nowrap}
.row{display:flex;flex-wrap:wrap;align-items:center;gap:8px} .row.rtop{align-items:flex-start;gap:12px} .row.between{justify-content:space-between}
.sp{flex:1 1 0} .stack{display:flex;flex-direction:column;gap:16px} .stack.tight{gap:8px}

.app{display:flex;min-height:100%}
.side{flex:0 0 208px;display:flex;flex-direction:column;gap:2px;padding:16px 12px;background:var(--surface);border-right:1px solid var(--border);position:sticky;top:env(safe-area-inset-top,0px);align-self:flex-start;height:100vh;max-height:100%}
/* The mark at the top left: the symbol in a 14 by 14 box beside the name, set in Geist at 17 px (brandMark in util.js; decision 42, October 27, 2026). Each is on the page in its light and its dark
   version, and the theme rules below show one. The symbol in dark and blue goes on a light background and the one in light gray and blue on a dark background; the name's reverse version has
   white letters. The owner's image files, when embedded, sit in the same boxes. */
.brand{display:flex;align-items:center;gap:8px;padding:4px 8px 16px}
.brand .mark{display:block;flex:none;width:14px;height:14px}
.brand .mark svg,.brand .mark img{display:block;width:100%;height:100%}
.brand .wordmark{display:block;min-width:0}
.brand .wordmark svg,.brand .wordmark img{display:block;height:16px;width:auto}
.brand .wm{display:block;font-family:var(--font);font-weight:600;font-size:17px;letter-spacing:-0.01em;line-height:1;white-space:nowrap}
.b-dark{display:none}
@media (prefers-color-scheme: dark){:root:not([data-theme="light"]) .b-light{display:none} :root:not([data-theme="light"]) .b-dark{display:block}}
:root[data-theme="dark"] .b-light{display:none} :root[data-theme="dark"] .b-dark{display:block}
/* The product with nobody signed in: the mark and one line, until sign-in and the first fetch of the records arrive (a later part). */
.starting{display:flex;flex-direction:column;align-items:center;gap:12px;padding:64px 16px;color:var(--muted)}
.nav{display:flex;align-items:center;gap:8px;width:100%;min-height:36px;padding:0 10px;border:0;border-radius:6px;background:transparent;color:var(--nav);text-align:left;cursor:pointer;white-space:nowrap}
.nav:hover{background:var(--surface-2)}
.nav[aria-current="page"]{background:var(--accent-soft);color:var(--accent-soft-ink);font-weight:500}
.nav .count{margin-left:auto;font-size:12px;padding:0 6px;border-radius:999px;background:var(--red-bg);color:var(--red);font-weight:500}
.who{display:flex;align-items:center;gap:10px;margin-top:auto;padding:12px 8px 0;border-top:1px solid var(--border);font-size:13px}
.avatar{display:flex;align-items:center;justify-content:center;flex:0 0 32px;height:32px;border-radius:16px;background:var(--accent-soft);color:var(--accent-soft-ink);font-size:12px;font-weight:600}
.main{flex:1 1 0;min-width:0;display:flex;flex-direction:column}
.top{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:12px 24px;background:var(--surface);border-bottom:1px solid var(--border)}
.searchbtn{flex:1 1 220px;min-width:0;max-width:420px;display:flex;align-items:center;gap:8px;height:36px;padding:0 12px;border:1px solid var(--border-strong);border-radius:8px;background:var(--surface-2);color:var(--muted);cursor:pointer;text-align:left;white-space:nowrap;overflow:hidden}
.searchbtn span:first-child{overflow:hidden;text-overflow:ellipsis}
.kbd{margin-left:auto;flex:none;padding:1px 6px;border:1px solid var(--border-strong);border-radius:5px;font-family:var(--mono);font-size:11px}
.pill{padding:3px 10px;border-radius:999px;background:var(--gray-bg);color:var(--muted);font-size:12px;white-space:nowrap}
/* The product's word in the top bar: whether the page's changes are saved on the server (sync.js). Not saved reads in red with its reason. */
.sync{font-size:12px;color:var(--muted);white-space:nowrap} .sync[data-sync="saving"]{color:var(--amber)} .sync[data-sync="not-saved"]{color:var(--red);white-space:normal}
/* While a legal command waits for the server, the buttons that could send another are held. */
body[data-busy] .btn,body[data-busy] button[type="submit"],body[data-busy] .link{pointer-events:none;opacity:.6}
.page{flex:1 1 auto;padding-block:20px 28px;padding-inline:24px;display:flex;flex-direction:column;gap:16px;min-width:0}
.crumbs{font-size:13px;color:var(--muted)} .crumbs .link{font-size:13px}
.h1row{display:flex;flex-wrap:wrap;align-items:center;gap:12px}
.meta{display:flex;flex-wrap:wrap;gap:6px 24px;font-size:13px}
.meta dt{display:inline;color:var(--muted)} .meta dd{display:inline;font-weight:500;margin-left:4px}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:36px;padding:0 14px;border:1px solid var(--border-strong);border-radius:8px;background:var(--surface);color:var(--ink);cursor:pointer;white-space:nowrap}
.btn:hover{border-color:var(--muted)}
.btn.pri{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);font-weight:500}
.btn.pri:hover{filter:brightness(1.08)}
.btn.sm{min-height:32px;padding:0 10px;font-size:13px;border-radius:7px}
.btn[disabled]{opacity:.5;cursor:not-allowed}
.link{display:inline;padding:0;border:0;background:none;color:var(--link);text-decoration:underline;text-underline-offset:2px;cursor:pointer;font-size:inherit;text-align:left}
.iconbtn{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border:1px solid var(--border-strong);border-radius:8px;background:var(--surface);cursor:pointer}
select,input[type="text"],input[type="number"],input[type="date"],input[type="search"],input[type="email"],input[type="tel"],textarea{min-height:36px;padding:0 10px;border:1px solid var(--border-strong);border-radius:8px;background:var(--surface);color:var(--ink);max-width:100%}
textarea{padding:8px 10px;min-height:96px;width:100%;resize:vertical}
select.sel{background:var(--surface)}
.field{display:flex;flex-direction:column;gap:4px;flex:1 1 180px;min-width:0}
.field>span{font-size:12px;color:var(--muted)}
.field input,.field select{width:100%}
/* a figure in a form that is shown and cannot be typed in, such as the one total of a check's deductions */
.field .ro{display:flex;align-items:center;min-height:36px;padding:0 10px;border-radius:8px;background:var(--surface-2);font-family:var(--mono);font-size:14px}
.modal-b>.field,.card-b>.field,.stack>.field,.drawer-b>.field{flex:none}
.check{display:flex;align-items:flex-start;gap:8px} .check input{margin-top:3px}

.chip{display:inline-block;padding:2px 9px;border-radius:999px;font-size:12px;font-weight:500;white-space:nowrap}
.c-red{color:var(--red);background:var(--red-bg)} .c-amber{color:var(--amber);background:var(--amber-bg)}
.c-green{color:var(--green);background:var(--green-bg)} .c-blue{color:var(--accent-soft-ink);background:var(--accent-soft)}
.c-gray{color:var(--gray-ink);background:var(--gray-bg)}
/* The chip beside Exceptions says what a payroll still needs. Its words can be long, so it may wrap inside its column. */
.chip.wrapok{white-space:normal;border-radius:12px}

.steps{display:flex;flex-wrap:wrap;gap:8px}
.step{flex:1 1 110px;font-size:13px;color:var(--muted)}
.step i{display:block;height:4px;margin-bottom:8px;border-radius:2px;background:var(--border)}
.step small{display:block;font-size:12px}
.step.done{color:var(--ink)} .step.done i{background:var(--step-done)} .step.done small{color:var(--green)}
.step.cur{color:var(--ink);font-weight:600} .step.cur i{background:var(--accent)} .step.cur small{font-weight:400}
/* A step that is past reads a green Done. When it still says what is left, such as dollars acknowledged and still owed, the words keep their own color and are never green. */
.step.done small.red{color:var(--red)} .step.done small.amber{color:var(--amber)} .step.done small.gray{color:var(--muted)}

.stats{display:flex;flex-wrap:wrap;gap:12px}
.stat{flex:1 1 170px;min-width:0;padding:12px 16px;border:1px solid var(--border);border-radius:10px;background:var(--surface)}
.stat dt{font-size:12px;color:var(--muted)} .stat dd.v{margin-top:2px;font-size:22px;font-weight:600;font-variant-numeric:tabular-nums}
.stat dd.n{margin-top:2px;font-size:12px;color:var(--muted)}

.cols{display:flex;flex-wrap:wrap;align-items:flex-start;gap:16px}
.col-main{flex:999 1 520px;min-width:0;display:flex;flex-direction:column;gap:16px}
.col-side{flex:1 1 320px;min-width:0;display:flex;flex-direction:column;gap:12px}
/* The column that holds the hours grid. The panel beside it moves under it when less than 755 would be left for the grid, which is what the three-row table needs. With room for both nothing changes.
   755 is the most that still leaves the panel beside the grid on a screen 1366 wide that shows a scroll bar. On a screen narrower than 755 the column is the width of the screen. */
.col-main.gridcol{min-width:min(755px,100%)}
.card{border:1px solid var(--border);border-radius:10px;background:var(--surface);min-width:0}
.card-h{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;padding:12px 16px;border-bottom:1px solid var(--border)}
.card-b{padding:14px 16px}
.tw{overflow-x:auto}
table.t{width:100%;border-collapse:collapse}
.t th{padding:8px 12px;background:var(--surface-2);border-bottom:1px solid var(--border);font-size:12px;font-weight:500;color:var(--muted);text-align:left;white-space:nowrap}
.t td{padding:10px 12px;border-bottom:1px solid var(--rule);vertical-align:middle}
.t tr:last-child td{border-bottom:0}
.t th.num,.t td.num{text-align:right;font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:13px}
.t th.num{font-family:var(--font);font-size:12px}
.t th.ctr,.t td.ctr{text-align:center}
/* A long heading over a narrow column may wrap, so the table fits its box: "Owed to workers" on the payroll list and "Period or recipient" on the Documents page. */
.t th.wrapth{white-space:normal;line-height:1.25}
.t tr.flag td{background:var(--flag-row)}
.t tr.sel td{background:var(--accent-soft)}
.t tr.click{cursor:pointer} .t tr.click:hover td{background:var(--surface-2)}
.t td .sub{display:block;font-size:12px;color:var(--muted)}
.t.compact td{padding:5px 12px} .t.compact select{min-height:30px}
/* The lists in the mapping dialog. A list is as wide as its column and no wider, so a long choice such as "FICA (used for Social Security deduction)" does not push the table past the dialog. */
.t.compact select{width:100%;min-width:140px}
/* On a phone the cells and the lists give up side padding, so the words "Not in this file" show whole in every list and the table still fits the dialog. */
@media (max-width:560px){.t.maptbl td{padding:5px 6px} .t.maptbl select{min-width:124px;padding:0 4px}}
/* The hours grid. Each line is one tbody of three rows: straight time, overtime, double time. The worker, Paid, Required, the status and the links span the three.
   From 1000 wide it is a table. Below 1000 the same markup is laid out as one block for each line, so all seven days show with no sideways scroll.
   The table needs about 711 wide with the font the tests fall back to and about 734 with the web font, and at 1000 wide its card is 744. From 861 to 966 wide it was a table wider than its card, with the status and the Pay and Edit links cut off. */
.t.grid tbody td{border-bottom:0}
.t.grid tbody th.g-row{background:none;border-bottom:0}
.t.grid tr.flag th{background:var(--flag-row)}
/* Two headings are words for a screen reader only. Each is placed against its own cell. Otherwise the one at the far end of a table wider than its card is placed against the page and makes the whole page scroll sideways. */
.t.grid thead th.g-row,.t.grid thead th.g-acth{position:relative}
.t.grid .lbl{display:none}
/* A status is one line. Only the list of rules that are switched off can be long, and it wraps inside its chip. */
.t.grid .g-st{white-space:nowrap}
.t.grid .g-st.wrap .chip{white-space:normal;max-width:126px;border-radius:12px}
/* A cell is 34 wide. Four characters, such as 8.25, and five, such as 10.25, are set smaller so the whole figure shows. */
.t.grid .cell{padding:0 1px!important} .t.grid .cell.l4{font-size:12px} .t.grid .cell.l5{font-size:10px}
.t.grid .g-rate .none{font-family:var(--font);font-size:12px;line-height:1.15;color:var(--red)}
.t.grid button.flagv{font-size:12px;cursor:pointer;text-align:left}
@media (min-width:1000px){
  .t.grid th,.t.grid td{padding:3px 4px}
  .t.grid thead th{padding-top:8px;padding-bottom:8px}
  .t.grid .g-whoh,.t.grid .g-who{padding-left:14px}
  .t.grid .g-acth,.t.grid .g-act{padding-right:14px}
  .t.grid thead th.g-day,.t.grid thead th.g-rateh{white-space:normal;line-height:1.25}
  .t.grid thead th.g-day{min-width:38px;padding-left:2px;padding-right:2px}
  .t.grid tbody th.g-row{padding-left:8px;padding-right:2px}
  .t.grid tbody.ln+tbody.ln tr:first-child>*{border-top:1px solid var(--rule)}
  .t.grid tbody.ln tr:first-child>*{padding-top:8px} .t.grid tbody.ln tr:last-child>*{padding-bottom:8px}
  .t.grid tbody.ln tr>[rowspan]{vertical-align:top;padding-top:12px}
  .t.grid tbody.ln tr>.g-paid,.t.grid tbody.ln tr>.g-req{padding-top:13px}
  /* Version 2.0 step 1 (#3): the note under Required beside an apprentice with no registration on file wraps inside its column */
  .t.grid td.g-req .g-reqj{white-space:normal;line-height:1.3;margin-top:2px;font-family:var(--font)}
  .t.grid tbody.ln tr>.g-st{padding-top:11px}
  /* A read-only grid has no boxes to type in, so its rows are shorter and the cells that span them sit higher. */
  .t.grid.ro tbody.ln tr>[rowspan]{padding-top:7px}
  .t.grid.ro tbody.ln tr>.g-paid,.t.grid.ro tbody.ln tr>.g-req{padding-top:8px}
  .t.grid td.g-d{padding-left:2px;padding-right:2px}
  .t.grid td.g-who{min-width:106px}
  .t.grid td.g-tot{min-width:28px}
  .t.grid .g-rate .none{display:inline-block;max-width:48px;text-align:right}
}
.cell{width:34px;min-height:28px!important;padding:0 2px!important;border:1px solid var(--border-strong);border-radius:5px!important;background:var(--surface);color:var(--ink);text-align:center;font-family:var(--mono);font-size:13px}
.cell:hover{border-color:var(--muted)} .cell[disabled]{opacity:.6}
.cell.w{width:64px}
/* product step 8, the second fixer: a box left empty on purpose says so in words that fit it ("No change" in the owner's publish form) */
.cell.w.nochange{width:84px} .cell.nochange::placeholder{font-family:var(--font);font-size:11px;color:var(--muted)}
.flagv{display:inline-block;padding:1px 6px;border:1px solid var(--amber-border);border-radius:5px;background:var(--amber-bg);color:var(--amber)}

.tabs{display:flex;gap:4px;overflow-x:auto;border-bottom:1px solid var(--border)}
.tab{padding:8px 12px;border:0;border-bottom:2px solid transparent;background:none;color:var(--muted);cursor:pointer;white-space:nowrap}
.tab[aria-selected="true"]{color:var(--ink);font-weight:500;border-bottom-color:var(--accent)}

.exc{padding:14px 16px;border:1px solid var(--border);border-radius:10px;background:var(--surface)}
.exc p{margin:8px 0 12px;font-size:13px}
.list>li{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:11px 16px;border-bottom:1px solid var(--rule)}
.list>li:last-child{border-bottom:0}
.list>li.col{flex-direction:column;align-items:stretch;gap:6px}
/* first-run setup (part 1e): one form in the middle of the page */
.setup{max-width:760px;margin:0 auto;display:flex;flex-direction:column;gap:16px} .setup .card-b.stack>h3{font-size:14px;margin:0}
/* product step 3, part b: the certification the signer makes, shown in full in the sign dialog and in a signed version */
.cert{border-left:3px solid var(--accent);background:var(--surface-2);padding:10px 14px;border-radius:0 8px 8px 0;font-size:13px;line-height:1.55;color:var(--ink)}
.cert .small{display:block;margin-bottom:4px}
.banner{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;padding:10px 14px;border-radius:10px;font-size:13px}
.banner.info{background:var(--accent-soft);color:var(--accent-soft-ink)} .banner.warn{background:var(--amber-bg);color:var(--amber)}
.banner.ok{background:var(--green-bg);color:var(--green)} .banner.bad{background:var(--red-bg);color:var(--red)}
.banner.unused{background:var(--amber-bg);color:var(--amber)}
.banner .link{color:inherit}
.footbar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding:12px 16px;border:1px solid var(--border);border-radius:10px;background:var(--surface);position:sticky;bottom:calc(8px + env(safe-area-inset-bottom,0px))}
.empty{padding:28px 16px;text-align:center;color:var(--muted)}
.kv{display:grid;grid-template-columns:minmax(120px,200px) 1fr;gap:8px 16px;font-size:14px}
.kv dt{color:var(--muted)}
.tree-ind{display:inline-block;width:18px;border-left:1px solid var(--border-strong);border-bottom:1px solid var(--border-strong);height:12px;margin-right:8px;vertical-align:4px}

.overlay{position:fixed;inset:0;z-index:50;background:var(--overlay);display:flex;align-items:flex-start;justify-content:center;padding:max(24px,env(safe-area-inset-top,0px)) 16px 24px;overflow-y:auto}
.modal{width:100%;max-width:560px;border-radius:12px;background:var(--surface);border:1px solid var(--border);box-shadow:var(--shadow)}
.modal.wide{max-width:920px}
.modal-h{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 18px;border-bottom:1px solid var(--border)}
.modal-b{padding:16px 18px;display:flex;flex-direction:column;gap:14px}
.modal-msg{flex:1 1 200px;min-width:0;align-self:center;font-size:13px;font-weight:500}
/* The buttons keep their own height beside a message of several lines. */
.modal-f{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:8px;padding:12px 18px;border-top:1px solid var(--border)}
.drawer{position:fixed;top:0;right:0;bottom:0;z-index:51;width:min(440px,100%);background:var(--surface);border-left:1px solid var(--border);box-shadow:var(--shadow);display:flex;flex-direction:column;padding-top:env(safe-area-inset-top,0px)}
.drawer-b{padding:16px 18px;overflow-y:auto;display:flex;flex-direction:column;gap:14px}
.calc{padding:10px 12px;border-radius:8px;background:var(--surface-2);font-family:var(--mono);font-size:13px;line-height:1.7}
/* The message at the top of the screen. A tap or a click on it puts it away (toast in app.js), so it takes the pointer. */
/* Above phone width a click on the message goes through to what is under it, so a first click on a cell or a list never only puts the message away. On a phone, where a long message can lie over a dialog's Close button, a tap closes it (see the phone rules below). */
.toast{position:fixed;left:50%;top:calc(14px + env(safe-area-inset-top,0px));transform:translateX(-50%);z-index:60;pointer-events:none;text-align:center;max-width:calc(100% - 32px);padding:10px 16px;border-radius:10px;background:var(--ink);color:var(--bg);font-size:13px;box-shadow:var(--shadow)}
.pal{width:100%;max-width:640px;border-radius:12px;background:var(--surface);border:1px solid var(--border);box-shadow:var(--shadow);overflow:hidden}
.pal input{width:100%;min-height:48px;border:0;border-bottom:1px solid var(--border);border-radius:0;padding:0 16px;font-size:15px;background:var(--surface)}
.pal-r{max-height:60vh;overflow-y:auto;padding:8px}
.pal-g{padding:8px 8px 4px;font-size:12px;color:var(--muted)}
.pal-i{display:flex;justify-content:space-between;gap:12px;width:100%;padding:8px;border:0;border-radius:6px;background:none;text-align:left;cursor:pointer}
.pal-i:hover,.pal-i:focus{background:var(--surface-2)}

.paperwrap{padding:16px;background:var(--gray-bg);border-radius:8px;overflow-x:auto}
.paper{min-width:560px;padding:22px 20px;border:1px solid var(--border-strong);background:var(--paper);color:var(--paper-ink);font-size:11px;line-height:1.5}
.paper.pwide{min-width:860px}
.paper h4{margin:0;font-size:13px;text-align:center}
.paper .pm{color:var(--paper-muted)}
.paper table{width:100%;border-collapse:collapse;margin-top:10px}
.paper th,.paper td{border:1px solid var(--paper-rule);padding:3px 4px;font-size:10px;text-align:left;vertical-align:top}
.paper td.n,.paper th.n{text-align:right;font-family:var(--mono)}
.paper .hl td{background:var(--paper-hl)} .paper .fl{background:var(--paper-flag);outline:2px solid #C9952C}
.paper .sig{margin-top:14px;padding-top:8px;border-top:1px solid var(--paper-rule)}
/* The blocks of the certified payroll: a heavier rule above each block, a tint on the row that names the worker, and a figure at the right of each line in a box.
   The downloaded file carries its own stylesheet (wrapPaper in docs.js), which holds the same rules. */
.paper .cp tbody.cp-blk,.paper .cp tbody.cp-tot{border-top:2px solid var(--paper-rule)}
.paper .cp .cp-who th{background:var(--paper-hl)}
.paper .cp .cp-cls{float:right;font-weight:400}
.paper .cp .cp-note{font-weight:400;color:var(--paper-muted)}
.paper .cp-ln{display:flex;justify-content:space-between;gap:8px}
.paper .cp-fig{font-family:var(--mono);white-space:nowrap}
.paper .cp th[scope=row]{white-space:nowrap}
.formwrap{padding:12px}
.oform{position:relative;container-type:inline-size;width:100%;max-width:850px;margin:0 auto;background:#fff;border:1px solid var(--border-strong);overflow:hidden}
.oform+.oform{margin-top:12px}
.oform.oturn{max-width:1180px}
.paper.ocont{margin:12px auto 0;max-width:850px;min-width:0}
.paper h5{margin:12px 0 0;font-size:11px}
.paper ul{margin:6px 0 0;padding-left:18px}
.oform img{display:block;width:100%;height:100%}
.of-t{position:absolute;display:flex;align-items:center;padding:0 .3cqw;color:#000;font-family:Arial,Helvetica,sans-serif;line-height:1.2;white-space:nowrap;overflow:hidden}
.of-t.ml{align-items:flex-start;padding-top:.25cqw}
.of-x{position:absolute;display:flex;align-items:center;justify-content:center}
.of-x i{display:block;width:46%;height:46%;background:#000}
pre.code{margin:0;padding:12px;border-radius:8px;background:var(--surface-2);border:1px solid var(--border);font-family:var(--mono);font-size:12px;line-height:1.5;overflow:auto;max-height:420px;white-space:pre}

@media (max-width:1180px){
  .searchbtn{flex-basis:100%;max-width:none}
  .top .sp{display:none}
  .t th,.t td{padding-left:8px;padding-right:8px}
}
/* Just above the width where the side menu appears the page is at its narrowest for a table, so the cells give up some of their side padding there and the payroll list and the Documents page fit their boxes. */
@media (min-width:861px) and (max-width:920px){.t th,.t td{padding-left:6px;padding-right:6px}}
@media (max-width:860px){
  .app{flex-direction:column}
  .side{position:static;height:auto;max-height:none;flex:none;flex-direction:row;align-items:center;align-self:stretch;overflow-x:auto;padding:8px 16px;border-right:0;border-bottom:1px solid var(--border)}
  .brand{padding:0 8px 0 0} .who{display:none} .nav{width:auto}
  .top{padding:10px 16px} .page{padding-inline:16px}
  .kv{grid-template-columns:1fr}
  /* fit: a table of a few columns whose text wraps, such as the profile's version history, keeps the width of its card on a phone and never scrolls sideways */
  .t:not(.compact):not(.grid):not(.rules):not(.fit){min-width:600px}
  /* The requirement profile: each rule's settings sit under the rule, so no setting is off to the right of the screen. The heading row takes no room and is still read out. */
  .t.rules,.t.rules tbody,.t.rules tr,.t.rules td{display:block}
  .t.rules thead{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
  .t.rules tr{padding:10px 12px;border-bottom:1px solid var(--rule)} .t.rules tr:last-child{border-bottom:0}
  .t.rules td{padding:0;border-bottom:0} .t.rules td:empty{display:none}
  .t.rules td+td{padding:8px 0 0 24px}
  .footbar{position:static}
}
@media (max-width:999px){
  /* The hours grid as blocks: the worker across the top, the three hour rows under the seven dates, then the rate for each row, Paid and Required, the status and the links. */
  .t.grid{display:block}
  .t.grid thead,.t.grid tbody.ln{display:grid;grid-template-columns:30px repeat(7,minmax(0,1fr)) 48px;align-items:center}
  .t.grid tr{display:contents}
  /* The dates stay at the top of the screen while the lines scroll under them. The grid never scrolls sideways here, so its wrapper does not need to. */
  .tw.gw{overflow:visible}
  .t.grid thead{position:sticky;top:0;z-index:2;background:var(--surface-2);border-bottom:1px solid var(--border)}
  .t.grid .cell{scroll-margin-top:56px}
  .t.grid th,.t.grid td{padding:2px 0}
  .t.grid thead th{padding:6px 0;border-bottom:0;text-align:center;white-space:normal;line-height:1.25}
  .t.grid thead th.g-tot{padding-right:10px;text-align:right}
  .t.grid thead th:not(.g-row):not(.g-day):not(.g-tot){position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip-path:inset(50%)}
  .t.grid tbody.ln{padding:10px 0 12px}
  .t.grid tbody.ln+tbody.ln{border-top:1px solid var(--rule)}
  .t.grid tbody.ln.flag{background:var(--flag-row)}
  .t.grid tbody th.g-row{padding-left:12px}
  .t.grid td.g-who{grid-column:1/-1;padding:0 12px 6px;overflow-wrap:anywhere}
  .t.grid .g-who .b{display:block}
  .t.grid .g-who .sub{display:inline-block;margin-right:10px}
  .t.grid td.g-tot{padding-right:10px;font-size:12px}
  .t.grid .cell{width:calc(100% - 6px);max-width:40px}
  .t.grid td.g-rate{order:1;grid-column:span 3;align-self:start;padding:8px 0 0 12px;text-align:left}
  .t.grid td.g-paid,.t.grid td.g-req{order:2;grid-column:span 3;align-self:start;padding:6px 0 0 12px;text-align:left}
  .t.grid td.g-st{order:3;grid-column:1/span 6;padding:10px 0 0 12px}
  .t.grid td.g-act{order:3;grid-column:span 3;padding:10px 12px 0 0;white-space:nowrap}
  .t.grid .lbl{display:block;font-family:var(--font);font-size:12px;color:var(--muted)}
}
/* The hours of one line, in the line dialog. As a table it needs 573 wide, and the dialog gives it that only from about 645 wide. Below that the table is laid on its side,
   with the dates down the left and straight time, overtime and double time across, so all 21 boxes are on the screen. The boxes, their names and their order in the form are the same.
   The cells flow down each column in the order they are in the page: the dates, then one column for each hour row. */
@media (max-width:660px){
  .t.hrs{display:grid;grid-auto-flow:column;grid-template-rows:repeat(9,auto);grid-template-columns:auto repeat(3,minmax(0,1fr));align-items:stretch}
  .t.hrs thead,.t.hrs tbody,.t.hrs tr{display:contents}
  .t.hrs thead th,.t.hrs tbody th,.t.hrs tbody td{display:flex;align-items:center;justify-content:center;padding:4px 6px;border-bottom:1px solid var(--rule);background:none;text-align:center}
  .t.hrs thead th{justify-content:flex-start;font-size:12px}
  .t.hrs thead th:first-child,.t.hrs tbody th{background:var(--surface-2);border-bottom:1px solid var(--border);font-size:12px;font-weight:500;color:var(--muted);white-space:normal;line-height:1.2;min-height:36px}
  .t.hrs thead th:last-child,.t.hrs tbody td:last-child{border-bottom:0}
}
@media (max-width:560px){
  /* A message in the foot of a dialog gets its own line above the buttons, so a long refusal does not make a button as tall as the message or push one to the next line. While it is empty it takes no room. */
  .modal-msg{flex-basis:100%}
  .modal-msg:empty{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
  /* A message at the top of the screen. A long one, such as a refusal that says what changed, runs the width of a phone and is set left, so it reads as lines that all start in the same place.
     A short one stays a small box in the middle. */
  .toast{left:12px;right:12px;transform:none;width:fit-content;max-width:calc(100% - 24px);margin:0 auto;padding:12px 14px;text-align:left;line-height:1.5;pointer-events:auto;cursor:pointer}
}
/* The table in the pay dialog that sets a file's pay figures beside what is on file. Its six columns do not fit a phone: Deductions was cut off and Net was off the screen.
   Up to 560 wide each row is a block: its name, "On file" or "In the file", then one line for each figure with the figure's name in front of it. The heading row takes no room and is still read out. */
@media (max-width:560px){
  .t.payfile,.t.payfile tbody,.t.payfile tr,.t.payfile td{display:block}
  .t.payfile thead{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
  .t.payfile tr{padding:6px 0;border-bottom:1px solid var(--rule)} .t.payfile tr:last-child{border-bottom:0}
  .t.payfile td{display:flex;justify-content:space-between;gap:12px;padding:1px 0;border-bottom:0;text-align:right}
  .t.payfile td:first-child{font-weight:500}
  .t.payfile td[data-l]::before{content:attr(data-l);font-family:var(--font);font-size:13px;text-align:left}
}
/* A narrow phone. The row label and the total give a few pixels to the seven days, and a cell fills more of its column, so a figure of five characters such as 10.25 shows whole. */
@media (max-width:389px){
  /* The mapping's three columns no longer fit side by side below 390 wide. Each field becomes two lines: its name with what the first row holds, then its list at full width. */
  .t.maptbl,.t.maptbl tbody{display:block}
  .t.maptbl thead{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
  .t.maptbl tr{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:4px 8px;padding:6px 8px;border-bottom:1px solid var(--rule)} .t.maptbl tr:last-child{border-bottom:0}
  .t.maptbl td{padding:0;border-bottom:0}
  .t.maptbl td:nth-child(2){grid-column:1/-1;grid-row:2}
  .t.maptbl td:nth-child(3){grid-column:2;grid-row:1;max-width:150px;text-align:right;overflow-wrap:anywhere}
  .t.maptbl select{min-width:0}
  .t.grid thead,.t.grid tbody.ln{grid-template-columns:28px repeat(7,minmax(0,1fr)) 42px}
  .t.grid thead th.g-tot,.t.grid td.g-tot{padding-right:6px}
  .t.grid .cell{width:calc(100% - 4px);padding:0!important}
}
/* The narrowest phones. Figures of four and five characters are set one size smaller again. */
@media (max-width:359px){
  .t.grid .cell{width:calc(100% - 2px)}
  .t.grid .cell.l4{font-size:11px} .t.grid .cell.l5{font-size:9px}
}
@media (prefers-reduced-motion:no-preference){.btn,.nav{transition:background .12s,border-color .12s}}
/* product step 2: the determination as uploaded, beside its draft (the rate review's Source card on the product); the frame keeps the card's width and scrolls inside */
.srcwrap{background:var(--gray-bg);border-radius:8px;padding:8px}
.srcframe{display:block;width:100%;height:640px;border:0;border-radius:6px;background:#fff}
@media (max-width:700px){.srcframe{height:420px}}
/* product step 4: the review of a returned intake workbook. A reason is a short list with no bullets. On a phone each line read is a block: the line and its result across the top, then the cell and the
   reason, then what accepting does, so nothing is off to the right of the screen. The heading row takes no room and is still read out. */
ul.plain{list-style:none;margin:0;padding:0;display:grid;gap:4px}
@media (max-width:860px){
  .t.intake-lines,.t.intake-lines tbody{display:block;min-width:0}
  .t.intake-lines thead{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
  .t.intake-lines tr{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 10px;padding:10px 12px;border-bottom:1px solid var(--rule)} .t.intake-lines tr:last-child{border-bottom:0}
  .t.intake-lines td{padding:0;border-bottom:0}
  .t.intake-lines td:nth-child(3),.t.intake-lines td:nth-child(4){grid-column:1/-1}
}
/* Product step 4, part b: the demo's upload link page (#/u/<token>), drawn without the app's frame as the contractor sees it (the product serves its own at /u/<token>), and the link shown once on a request */
.linkpage main{max-width:620px;margin:0 auto;padding:28px 16px 48px}
.linkpage .brand{color:var(--muted);font-size:13px;margin:0 0 12px}
.linkpage h1{margin:16px 0 10px}
.linkpage h2{font-size:16px;margin:0 0 6px}
.linkcard{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:18px;display:flex;flex-direction:column;gap:12px}
.linkcard .lead{line-height:1.55}
.linkcard .notice{padding:12px 14px;border:1px solid var(--amber-border);border-radius:10px;background:var(--amber-bg);color:var(--amber)}
.linkcard .ok{padding:12px 14px;border-radius:10px;background:var(--green-bg);color:var(--green);display:flex;flex-direction:column;gap:6px}
.linkcard .ok ul{list-style:disc;padding-left:20px}
.linkform{display:flex;flex-direction:column;gap:8px}
.linkform label{font-weight:600}
.linkform input[type=file]{padding:10px;border:1px dashed var(--border-strong);border-radius:10px;background:var(--surface-2);max-width:100%}
.linkbox{flex:1 1 260px;min-width:0;max-width:100%;padding:6px 8px;border:1px solid var(--border-strong);border-radius:8px;background:var(--surface);font-family:var(--mono);font-size:12px}
.h3{margin:14px 0 6px}
.linkshown{display:flex;flex-direction:column;gap:8px;padding:12px 14px;border-radius:10px;background:var(--green-bg);color:var(--green)}
.linkshown .muted{color:inherit;opacity:.85}
/* Product step 5, part a: the compliance checklist. On a wide screen each contractor's table keeps the same columns, so the cards line up; below 861 wide each item is a block (the item, its date, its
   status, its buttons), as the requirement profile is, so nothing is off to the right of a phone. The count chips above the cards set the status filter. */
.ckbar{gap:8px 16px;margin:4px 0 8px} .kv .sub{display:block;font-size:12px;color:var(--muted)} .kv ul.plain{margin:0} .ckcounts{gap:6px;margin:0 0 12px}
.t.ck button.link{white-space:normal;text-align:left} button.ckpick{border:1px solid transparent;cursor:pointer;font-family:inherit} button.ckpick[aria-pressed="true"]{border-color:currentColor}
@media (min-width:861px){.t.ck{table-layout:fixed;width:100%} .t.ck th:nth-child(2){width:132px} .t.ck th:nth-child(3){width:30%} .t.ck th:nth-child(4){width:252px} .t.ck td{overflow-wrap:anywhere}}
@media (max-width:860px){
  .t.ck,.t.ck tbody,.t.ck tr,.t.ck td{display:block} .t.ck{min-width:0!important}
  .t.ck thead{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
  .t.ck tr{padding:10px 12px;border-bottom:1px solid var(--rule)} .t.ck tr:last-child{border-bottom:0}
  .t.ck td{padding:0;border-bottom:0} .t.ck td+td{padding-top:6px}
  .t.ck td.right{text-align:left;white-space:normal}
}
/* Product step 5, part b: the package email as it will go (the notice wraps, in the app's own font), the parts left out of a package, and the CSLB and package lines under a sub's name on the Subs tab */
pre.code.rawpage{white-space:pre-wrap;word-break:break-all;max-height:60vh}
pre.code.mailtext{white-space:pre-wrap;word-break:break-word;font-family:var(--font);font-size:13px;max-height:360px}
.list.plainlist>li{display:block} .list.plainlist .sub{display:block;font-size:12px;color:var(--muted)}
.list.pkglist>li{border:1px solid var(--rule);border-radius:8px;margin:0 0 8px} .list.pkglist{margin:0 0 8px}
/* Product step 6, part b: a long file name wraps inside its cell; the places of a flat form and the employee detail of a fringe proof keep their boxes inside the dialog */
.t td.wrapany{overflow-wrap:anywhere}
.t.fplace{table-layout:fixed;width:100%} .t.fplace th:first-child{width:36%} .t.fpdet{table-layout:fixed;width:100%} .t.fpdet th:last-child{width:34%} .t.fplace select,.t.fplace input,.t.fpdet input{width:100%;min-width:0}
.t.fp td.num .sub,.t.fp td.num .muted{font-family:var(--font)}
/* Product step 8: what a page the watch reads changed, line by line (taken out, added), and an update's table of what changes on a project */
.wdiff{margin:0;padding:0;list-style:none;font-size:13px;line-height:1.45}
.wdiff li{padding:4px 8px;border-left:3px solid var(--rule);margin:3px 0;word-break:break-word;overflow-wrap:anywhere}
.wdiff li.out{border-left-color:var(--red);background:var(--red-bg)}
.wdiff li.in{border-left-color:var(--green);background:var(--green-bg)}
.wdiff li .k{display:block;font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.04em}
.lawsum{white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere}
/* product step 8, part b: the owner portal's email templates, the support session's banner, and the AI's wording of an exception */
.tpl{margin:4px 0 0;font:inherit;font-size:13px;white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere}
.tplpv{border:1px solid var(--border);border-radius:10px;padding:10px 12px;display:flex;flex-direction:column;gap:4px}
.supportbar{margin-bottom:14px}
.aiwords{border-left:3px solid var(--accent);padding:6px 10px;background:var(--accent-soft)}
.aiwords h3,.aiwords p{color:var(--accent-soft-ink)}
