:root{
  --bg:#f5f6f8; --card:#fff; --sunk:#f8f9fb; --ink:#15181c; --muted:#6b7280; --line:#e3e6ea;
  --brand:#c8102e; --brand-dark:#9d0c24; --ok:#0f7b3f; --okbg:#e8f7ee;
  --warn:#b45309; --warnbg:#fff7ed; --bad:#991b1b; --badbg:#fee2e2;
  --radius:12px;
}
/* Three states, which is what a theme choice actually is.

   Bare :root is the light one. The media query gives dark to anybody whose machine asks
   for it, unless they have chosen light here — that is what the :not does. And
   [data-theme="dark"] gives dark to anybody who has chosen it whatever their machine
   says, so the choice wins in both directions.

   Every colour in this file comes from these, which is why a second theme is a block of
   values rather than a rewrite. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
  --bg:#121518; --card:#1b1f23; --sunk:#15181b; --ink:#e9ecef; --muted:#98a2ac;
  --line:#2b3137; --warnbg:#2a1f12; --okbg:#14291d; --badbg:#2c1618; --bad:#f8b4b4;
  }
}
:root[data-theme="dark"]{
  --bg:#121518; --card:#1b1f23; --sunk:#15181b; --ink:#e9ecef; --muted:#98a2ac;
  --line:#2b3137; --warnbg:#2a1f12; --okbg:#14291d; --badbg:#2c1618; --bad:#f8b4b4;
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);
  font:15px/1.55 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}
h3.h3{margin:0;font-size:15px}

/* ------------------------------------------------------------------- bar */
/* Three columns: the brand, what is going on, and everything else. A grid rather than
   space-between so the middle is genuinely the middle and does not move about as the
   chips on the right change width. */
header.bar{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;
  gap:16px;padding:8px 18px;background:var(--card);
  border-bottom:1px solid var(--line);position:sticky;top:0;z-index:30}
.brand{display:flex;align-items:center;gap:10px;font-weight:600}
.mark{display:inline-grid;place-items:center;width:28px;height:28px;border-radius:7px;
  background:var(--brand);color:#fff;font-size:12px;font-weight:700;letter-spacing:.5px}
.bar-right{display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end}
.who{color:var(--muted);font-size:13px}
.state{font-size:12px;color:var(--muted);background:var(--sunk);
  border:1px solid var(--line);border-radius:20px;padding:3px 11px;white-space:nowrap}
.state b{color:var(--ink);font-weight:600;margin-right:3px}
.state.stale{border-color:var(--warn);color:var(--warn)}

/* ----------------------------------------------------------------- tabs */
.tabs{display:flex;gap:2px;padding:12px 18px 0;max-width:1320px;margin:0 auto;
  overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.tabs::-webkit-scrollbar{display:none}
.tab{flex:0 0 auto}
.tab{border:1px solid transparent;background:none;color:var(--muted);cursor:pointer;
  padding:8px 15px;border-radius:9px 9px 0 0;font:inherit;font-size:14px}
.tab:hover{color:var(--ink)}
.tab.active{background:var(--card);border-color:var(--line);border-bottom-color:var(--card);
  color:var(--ink);font-weight:600;margin-bottom:-1px}

.panel{display:none;gap:18px;padding:0 18px 24px;max-width:1320px;margin:0 auto}
.panel.active{display:flex}
@media (max-width:940px){ .panel.active{flex-direction:column} }
.col{flex:1;min-width:0;background:var(--card);border:1px solid var(--line);
  border-radius:var(--radius);padding:18px;display:flex;flex-direction:column;gap:14px}
.col.wide{flex:1 1 100%}

/* The bar that carries a draft back to the Inbox reply it came from.

   .panel.active is a flex row, so this was a third column: it took a share of the width
   and squeezed the form and the draft into what was left. It belongs on a line of its
   own above them. Only this panel is allowed to wrap - the two sections in it are
   flex:1 with min-width:0, so they share the line below and never wrap against each
   other. */
#tab-compose.panel.active{flex-wrap:wrap}
#composeWayBack{flex:0 0 100%;order:-1;gap:10px;align-items:baseline}

/* --------------------------------------------------------------- inputs */
.field{display:flex;flex-direction:column;gap:6px}
.lbl{font-size:11.5px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;color:var(--muted)}
.lbl.inline{text-transform:none;font-size:13px;align-self:center;letter-spacing:0}
.opt{font-weight:400;text-transform:none;letter-spacing:0}
textarea,input:not([type=checkbox]):not([type=radio]){width:100%;padding:10px 12px;border:1px solid var(--line);
  border-radius:9px;background:var(--sunk);color:var(--ink);font:inherit;resize:vertical;
  font-size:16px}
textarea:focus,input:focus,select:focus{outline:2px solid var(--brand);outline-offset:-1px}
#draft{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13.5px;line-height:1.62}
.grow{flex:1;min-width:180px}
.check{font-size:13px;color:var(--muted);display:flex;align-items:center;gap:6px;
  white-space:nowrap;min-width:0}

/* A dropdown is as wide as its longest option unless it is told otherwise, and this app
   puts document names and course names in them. Left alone, one long option pushes its
   row - and everything sharing that row - off the side of a phone. */
select{max-width:100%;min-width:0}

button{font:inherit}
.primary{background:var(--brand);color:#fff;border:0;border-radius:9px;padding:11px 18px;
  font-weight:600;cursor:pointer}
.primary.small{padding:8px 14px;font-size:13.5px}
.primary:hover{background:var(--brand-dark)}
.primary:disabled{opacity:.55;cursor:default}
.ghost{background:var(--card);border:1px solid var(--line);color:var(--ink);border-radius:9px;
  padding:7px 12px;cursor:pointer;text-decoration:none;font-size:13px;display:inline-block}
.ghost:hover{border-color:var(--muted)}
.ghost.tiny{padding:3px 9px;font-size:12px}

.seg{display:inline-flex;border:1px solid var(--line);border-radius:9px;overflow:hidden;
  align-self:flex-start}
.seg.grow{align-self:stretch;display:flex}
.seg.grow button{flex:1}
.seg button{background:var(--card);border:0;padding:9px 16px;cursor:pointer;color:var(--muted);
  white-space:nowrap}
.seg button:hover{color:var(--ink)}
.seg button.on{background:var(--brand);color:#fff;font-weight:600}

.row{display:flex;gap:10px;align-items:center}
.row.spread{justify-content:space-between}
.row.wrap{flex-wrap:wrap}
.tones{border-top:1px solid var(--line);padding-top:14px}
.hint{font-size:12.5px;color:var(--muted)}
.foot{font-size:12px;color:var(--muted);margin:2px 0 0}
.small{font-size:13px}
.hidden{display:none !important}

/* --------------------------------------------------------------- output */
.empty{color:var(--muted);text-align:center;padding:52px 22px;border:1px dashed var(--line);
  border-radius:var(--radius)}
.pill{background:var(--sunk);border:1px solid var(--line);border-radius:20px;padding:3px 12px;
  font-size:12px;color:var(--muted)}
.pill.soft{border-style:dashed}
.notes{background:var(--warnbg);border:1px solid var(--warn);border-radius:9px;padding:11px 15px}
.notes h4{margin:0 0 6px;font-size:13px;color:var(--warn)}
.notes ul{margin:0;padding-left:18px;font-size:13.5px}
.notes li{margin:3px 0}
.flag{background:var(--brand);color:#fff;border-radius:9px;padding:11px 15px;font-size:13.5px}
.attached{display:flex;justify-content:space-between;align-items:center;gap:10px;
  background:var(--sunk);border:1px solid var(--line);border-radius:9px;padding:9px 13px;
  font-size:13.5px}

/* ---------------------------------------------------------------- cards */
.cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px}
.card{background:var(--sunk);border:1px solid var(--line);border-radius:10px;padding:13px 15px;
  display:flex;flex-direction:column}
.card h4{margin:0 0 8px;font-size:14.5px;display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}
.card dl{display:grid;grid-template-columns:auto minmax(0,1fr);gap:2px 12px;margin:0;font-size:13px}
.card dt{color:var(--muted)}
.card dd{margin:0;overflow-wrap:anywhere}
.card .actions{margin-top:auto;padding-top:11px;display:flex;gap:6px;flex-wrap:wrap}
.tag{display:inline-block;font-size:11px;font-weight:600;padding:2px 8px;border-radius:12px}
.tag.paid{background:var(--okbg);color:var(--ok)}
.tag.unpaid{background:var(--badbg);color:var(--bad)}
.tag.private{background:var(--badbg);color:var(--bad)}
.tag.open{background:var(--okbg);color:var(--ok)}
.tag.full{background:var(--badbg);color:var(--bad)}
.tag.unknown{background:var(--warnbg);color:var(--warn)}
.hist{white-space:pre-wrap;font-size:13px;color:var(--muted);max-height:120px;overflow:auto;
  border-top:1px solid var(--line);margin-top:8px;padding-top:8px}

/* -------------------------------------------------------------- compare */
.diff{border:1px solid var(--line);border-radius:10px;padding:14px 16px;background:var(--sunk)}
.diff h4{margin:0 0 4px;font-size:14px}
.diff ul{margin:6px 0 12px;padding-left:18px;font-size:13.5px}
.diff li{margin:3px 0}
.diff .ok{color:var(--ok)}
.diff .bad{color:var(--bad);font-weight:600}
.diff .warnrow{color:var(--warn)}
.diff section{margin-top:10px}
.diff h5{margin:0 0 2px;font-size:12px;text-transform:uppercase;letter-spacing:.4px;color:var(--muted)}

.stalegroup{margin:10px 0 14px}
.stalegroup > b{margin-right:8px}
.stalegroup ul{margin:5px 0 0}
.stalegroup li .foot{display:block;margin:0}
.diff .ok{color:var(--ok);font-weight:600}

td.slcol,th.slcol{width:1%;white-space:nowrap;text-align:right;padding-right:12px;
  color:var(--muted);font-variant-numeric:tabular-nums}
table.grid.sortable th .arrow{margin-left:5px;opacity:.35;font-size:10px}
table.grid.sortable th.sorted .arrow{opacity:1}
table.grid.sortable th:hover .arrow{opacity:.8}

table.grid.sortable th{cursor:pointer;user-select:none;white-space:nowrap}
table.grid.sortable th:hover{color:var(--ink)}
table.grid.sortable th.sorted{color:var(--brand)}
.colpick{display:flex;flex-wrap:wrap;gap:6px;padding:8px 0}
.colpick .colchip{display:inline-flex;align-items:center;gap:6px;cursor:grab;
  user-select:none}
.colpick .colchip label{display:inline-flex;align-items:center;gap:6px;cursor:pointer;
  margin:0}
.colpick .colchip.dragging{opacity:.4}
.colpick .colchip.dragover{border-color:var(--brand);box-shadow:-3px 0 0 var(--brand)}
/* Whether this column's text may run onto a second line. */
.wrapbtn{border:0;background:transparent;cursor:pointer;color:var(--muted);font-size:12px;
  line-height:1;padding:1px 3px;border-radius:4px;opacity:.5}
.wrapbtn:hover{opacity:1;color:var(--ink)}
.wrapbtn.on{opacity:1;color:#fff;background:var(--brand)}
.colpick .grip{color:var(--muted);font-size:11px;letter-spacing:-1px;cursor:grab}
.colpicker>p{margin:4px 0 0}
.colpick .check{background:var(--sunk);border:1px solid var(--line);border-radius:20px;
  padding:4px 8px 4px 11px;font-size:12.5px}

tr.roomrow-late td{background:var(--badbg)}
tr.roomrow-late td:first-child{border-left:3px solid var(--bad)}
table.grid td .foot{display:block;margin:0}

.rules{gap:6px;align-items:center;margin:6px 0}
.check.tiny-rule{font-size:11.5px;padding:3px 7px;gap:4px;background:var(--bg)}
.check.tiny-rule select{font-size:11.5px;padding:2px 4px}

.pastbox{margin-top:8px}
.pastbox table.grid{min-width:0}
tr.wasago td{opacity:.6}

.demobar{background:var(--brand);color:#fff;padding:11px 18px;font-size:13.5px;
  line-height:1.5}
.demobar .foot{display:block;color:#fff;opacity:.85;margin-top:4px}
/* Folded, it is one line. Unconnected is a state somebody can be in for a week while
   they chase a service account key, and three lines of red across the top of every
   screen for a week is three lines they stop reading and cannot get past. */
.demobar-line{display:flex;align-items:baseline;gap:7px;flex-wrap:wrap}
.demobar-brief{opacity:.9}
.demobar-rest{margin-top:5px}
.demobar.shut .demobar-rest{display:none}
.demobar.shut .demobar-brief{display:inline}
.demobar:not(.shut) .demobar-brief{display:none}
.demobar-x{margin-left:auto;flex:none;background:rgba(0,0,0,.22);color:#fff;
  border:1px solid rgba(255,255,255,.45);border-radius:999px;
  padding:2px 11px;font-size:12px;font-weight:600;cursor:pointer;line-height:1.6}
.demobar-x:hover{background:rgba(0,0,0,.34)}
@media (max-width:640px){
  /* On a phone the banner is most of the first screen. It starts folded there, and the
     button keeps a thumb-sized target. */
  .demobar{padding:9px 13px;font-size:13px}
  .demobar-x{padding:4px 13px}
}
.demobar code{background:rgba(0,0,0,.25);border-color:transparent;color:#fff}
.state.danger{border-color:#fff;background:var(--brand);color:#fff}
.state.danger b{color:#fff}

.resetlink{margin-top:9px;border-top:1px solid var(--line);padding-top:9px}
.resetlink input{font-size:12px;font-family:ui-monospace,Menlo,monospace;margin-bottom:6px}

.keys{border:1px solid var(--line);border-radius:9px;padding:11px 13px;
  display:flex;flex-direction:column;gap:8px;background:var(--sunk)}
.keylist{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
.keylist li{display:flex;align-items:center;gap:7px;flex-wrap:wrap;font-size:13px}
details.legacy{opacity:.75}

.check.bigcheck{align-items:flex-start;gap:9px;font-size:13.5px;background:var(--sunk);
  border:1px solid var(--line);border-radius:9px;padding:11px 14px;white-space:normal}
.check.bigcheck input{margin-top:3px}
details.setup{margin:2px 0}
details.setup p{margin:6px 0}
code{background:var(--bg);border:1px solid var(--line);border-radius:5px;padding:1px 5px;
  font-size:12px}
.foot.bad{color:var(--bad)}

.partnerpick{display:flex;flex-wrap:wrap;gap:8px;padding:8px 0}
.partnerpick label{display:flex;align-items:center;gap:6px;font-size:13px;
  background:var(--sunk);border:1px solid var(--line);border-radius:20px;padding:5px 12px;
  cursor:pointer}
.partnerpick label.on{border-color:var(--brand);color:var(--ink)}
.b2bfound{background:var(--sunk);border:1px solid var(--line);border-radius:9px;
  padding:9px 13px;font-size:13px}
.b2bfound ul{margin:4px 0 0;padding-left:18px}
details#pasteWrap summary{margin:6px 0}
details#pasteWrap[open] summary{margin-bottom:8px}

.swapnote{background:var(--okbg);border:1px solid var(--ok);color:var(--ok);
  border-radius:9px;padding:9px 13px;font-size:13px}

.toast{position:fixed;bottom:22px;left:50%;transform:translateX(-50%) translateY(90px);
  background:var(--ink);color:var(--bg);padding:11px 19px;border-radius:9px;font-size:14px;
  transition:transform .18s ease;z-index:50;max-width:80vw}
.toast.show{transform:translateX(-50%) translateY(0)}


/* ------------------------------------------------------------------------- *
 * Phones. The office answers a lot of WhatsApp from a handset, so every      *
 * control here has to be reachable with a thumb.                            *
 * ------------------------------------------------------------------------- */
@media (max-width:640px){
  body{font-size:15px}

  .bar{padding:9px 12px;gap:8px}
  .bar-right{gap:6px;width:100%;justify-content:space-between}
  .state{font-size:11px;padding:2px 9px;flex:1;text-align:center;overflow:hidden;
    text-overflow:ellipsis}
  .who{display:none}

  .tabs{padding:10px 12px 0;gap:0}
  .tab{padding:9px 13px;font-size:13.5px}

  .panel{padding:0 12px 20px;gap:12px}
  .col{padding:14px;border-radius:10px;gap:12px}

  /* Four audiences will not sit on one line on a phone.

     minmax(0,1fr) rather than 1fr, and this is the whole bug Ruman photographed. A bare
     1fr means minmax(auto,1fr), and auto as a minimum is the item's min-content width -
     which for these buttons is the full label, because .seg button is white-space:nowrap.
     So the two tracks refused to go below "Ours + partners" wide, the grid came out at
     425px inside a 351px column, and every screen using a segment pushed itself off the
     right of the phone. The labels wrap instead. */
  .seg.grow{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
    align-self:stretch}
  .seg.grow button{padding:11px 8px;font-size:13.5px;border-bottom:1px solid var(--line);
    white-space:normal;overflow-wrap:anywhere}
  .seg.grow button:nth-last-child(-n+2){border-bottom:0}
  .seg.grow button:nth-child(odd){border-right:1px solid var(--line)}
  .seg.grow button.on{border-color:transparent}

  .seg:not(.grow){align-self:stretch;display:flex}
  .seg:not(.grow) button{flex:1;padding:11px 10px}

  .row{flex-wrap:wrap}
  .grow{flex:1 1 100%}

  /* A tick with a sentence beside it wraps on a phone.

     .check is white-space:nowrap, which is right for "Flag" or "Quote their message
     underneath" and wrong for "Include private courses - only ever for the company that
     booked one": nowrap makes the label's minimum width the whole sentence, and a flex
     column cannot shrink below its content's minimum. That one label was holding the
     Compose screen 82px wider than the phone, and everything in the column with it.
     The box stays on the first line rather than floating to the middle of a
     three-line label. */
  .check{padding:6px 0;white-space:normal;align-items:flex-start}
  .check input[type=checkbox]{margin-top:2px;flex:0 0 auto}

  .primary{width:100%;padding:14px 18px}
  .primary.small{width:auto}
  .ghost{padding:9px 13px}
  .ghost.tiny{padding:6px 11px;font-size:12.5px}

  .tones{gap:8px}
  .tones .ghost{flex:1 1 calc(50% - 8px);text-align:center}

  .cards{grid-template-columns:minmax(0,1fr);gap:10px}
  .card dl{grid-template-columns:minmax(84px,auto) minmax(0,1fr);font-size:12.5px}
  .empty{padding:34px 16px}

  #draft{font-size:14px}
  .toast{left:12px;right:12px;bottom:12px;max-width:none;transform:translateY(90px);
    text-align:center}
  .toast.show{transform:translateY(0)}
}

/* Very small handsets only. A 375px iPhone still gets two columns. */
@media (max-width:359px){
  .seg.grow{grid-template-columns:minmax(0,1fr)}
  .seg.grow button{border-right:0 !important;border-bottom:1px solid var(--line)}
  .seg.grow button:last-child{border-bottom:0}
  .tones .ghost{flex:1 1 100%}
}

/* Coarse pointers get bigger hit areas regardless of width. */
@media (pointer:coarse){
  .tab{padding-top:11px;padding-bottom:11px}
  .card .actions .ghost{min-height:34px}
}

/* ------------------------------------------------------- settings + auth */
.block{border-top:1px solid var(--line);padding-top:16px;display:flex;flex-direction:column;gap:10px}
.block:first-child{border-top:0;padding-top:0}
.block.admin{background:var(--sunk);border:1px solid var(--line);border-radius:10px;padding:16px}
h5.sub{margin:10px 0 4px;font-size:11.5px;text-transform:uppercase;letter-spacing:.4px;
  color:var(--muted)}
.tag.admin-tag{background:var(--brand);color:#fff}
.plain{margin:4px 0;padding-left:18px;font-size:13px;color:var(--muted)}
.balances p{margin:4px 0}
select{padding:9px 11px;border:1px solid var(--line);border-radius:9px;background:var(--sunk);
  color:var(--ink);font:inherit;font-size:15px;max-width:100%}
.provider{border:1px solid var(--line);border-radius:10px;padding:13px 15px;margin-bottom:10px;
  display:flex;flex-direction:column;gap:9px;background:var(--card)}
.testout.good{color:var(--ok)}
.testout.bad{color:var(--bad)}
.ghost.danger{color:var(--bad);border-color:var(--badbg)}
.ghost.danger:hover{border-color:var(--bad)}

.tablewrap{overflow-x:auto;-webkit-overflow-scrolling:touch}

/* ------------------------------------------------------------- the report */
.statcard{display:flex;flex-direction:column;gap:1px;border:1px solid var(--line);
  border-radius:11px;padding:11px 15px;background:var(--card);min-width:130px}
.statnum{font-size:22px;font-weight:700;line-height:1.15;font-variant-numeric:tabular-nums}
.statlbl{font-size:12px;color:var(--muted)}
#reportTotals{gap:9px;margin:12px 0}

/* One bar a day, drawn with divs. A chart library for a fortnight of rectangles would be
   a download, a licence, and a thing to keep up to date. */
.bars{display:flex;align-items:flex-end;gap:2px;height:120px;padding:6px 0;
  border-bottom:1px solid var(--line);overflow-x:auto}
/* Scoped to the chart. Unscoped, this also hit <header class="bar"> - it is the later
   rule, so it won the flex-direction and forced the header into a column, which is why
   the header was three times taller than it needed to be. */
.bars .bar{flex:1;min-width:9px;display:flex;flex-direction:column;justify-content:flex-end;
  align-items:center;height:100%;gap:3px;cursor:default}
.barfill{width:100%;height:var(--h);min-height:2px;background:var(--brand);
  border-radius:3px 3px 0 0}
.barfill.none{background:var(--line);min-height:1px}
.barday{font-size:9px;color:var(--muted);font-variant-numeric:tabular-nums}
tr.quiet-day td{color:var(--muted)}
tr.mine-row td{background:var(--sunk);font-weight:600}
#adsFindings p{margin:8px 0 2px}

/* ------------------------------------------------- filtering and paging */
.tabletools{gap:8px;align-items:center;margin:0 0 6px}
/* Where these rows came from. The screens are named after the job rather than the tab,
   so somebody wanting to change a row has to be told which tab to open. */
.tablesource{font-size:11.5px;color:var(--muted);background:var(--sunk);
  border:1px solid var(--line);border-radius:20px;padding:3px 10px;white-space:nowrap}
.tabletools .grow{flex:1}
.tabletools select{margin:0;padding:3px 6px!important;font-size:12px!important;width:auto}
.tabletools .check.dim{opacity:.5}
.tabletools select:disabled{cursor:not-allowed}

/* A filter row under the headings: a match-mode picker no wider than its symbol, and
   the box to type in taking the rest. Sticky with the heading so it stays reachable
   part-way down a thousand rows. */
tr.filterrow th{padding:3px 6px;background:var(--sunk);position:sticky;top:0;cursor:default}
/* The box you type in comes first and takes the room; how to match is a quiet word
   beside it. A filter that is doing something shows it, so a table filtered three
   columns ago does not look like a table with nothing on. */
.filtercell{display:flex;gap:4px;align-items:center;min-width:170px}
.filtercell input{flex:1;min-width:72px;margin:0;padding:3px 7px!important;
  font-size:12px!important;font-weight:400}
.filtercell input:disabled{opacity:.5;font-style:italic}
.filtercell select{width:auto;max-width:82px;margin:0;padding:3px 2px 3px 4px!important;
  font-size:11px!important;border:0;background:transparent;color:var(--muted);
  cursor:pointer}
.filtercell select:hover{color:var(--ink)}
.filtercell.set input{border-color:var(--brand)}
.filtercell.set select{color:var(--brand);font-weight:600}

.pager{margin:7px 0 0;align-items:center;gap:8px}
.pagebtns{gap:4px;align-items:center}
.pagebtns .foot{margin:0 5px;white-space:nowrap}
table.grid{border-collapse:collapse;width:100%;font-size:13px;min-width:480px}
table.grid th{text-align:left;font-size:11px;text-transform:uppercase;letter-spacing:.3px;
  color:var(--muted);font-weight:600;padding:6px 10px 6px 0;border-bottom:1px solid var(--line)}
table.grid td{padding:6px 10px 6px 0;border-bottom:1px solid var(--line);white-space:nowrap}

/* Resizing and wrapping.

   Widths live in a colgroup, which is what a colgroup is for: one element per column,
   applied by the browser to every row. A table only switches to a fixed layout once
   somebody has actually set a width - until then it sizes itself as it always has. */
table.grid.sized{table-layout:fixed}
table.grid.sized td,table.grid.sized th{overflow:hidden;text-overflow:ellipsis}
table.grid td.wrapcell{white-space:normal;word-break:break-word;text-overflow:clip}

table.grid.sortable th{position:relative}
.colgrip{position:absolute;top:0;right:-3px;width:7px;height:100%;cursor:col-resize;
  z-index:2}
.colgrip::after{content:"";position:absolute;top:22%;bottom:22%;left:3px;width:1px;
  background:var(--line)}
.colgrip:hover::after{background:var(--brand);width:2px;left:2px}
body.dragging-col{cursor:col-resize;user-select:none}
body.dragging-col *{cursor:col-resize!important}

.auth-page{display:grid;place-items:center;min-height:100vh;padding:20px}
.auth{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:26px;width:100%;max-width:400px;display:flex;flex-direction:column;gap:13px}
.brand.big{font-size:19px}
.authform{display:flex;flex-direction:column;gap:12px}
.notice{background:var(--sunk);border:1px solid var(--line);border-radius:9px;padding:11px 14px;
  font-size:13.5px}
.notice code{background:var(--bg);padding:2px 6px;border-radius:5px;font-size:12.5px;
  display:inline-block;margin-top:4px;overflow-wrap:anywhere}

.sourcebar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin:8px 0 2px;
  padding:7px 12px;background:var(--sunk);border:1px solid var(--line);border-radius:9px}
.sourcebar .foot{margin:0}
.sourcebar.danger{border-color:var(--bad);background:var(--badbg)}
.sourcebar.warn{border-color:var(--warn)}
.sourcebar .dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto}
.sourcebar .dot.ok{background:var(--ok)}
.sourcebar .dot.warn{background:var(--warn)}
.sourcebar .dot.bad{background:var(--bad)}
.sourcebar button{margin-left:auto}

/* Spending right now. Not the same as "paid is permitted", which is a setting; this is
   money leaving, and it says so on every screen. */
#creditState.paying{border-color:var(--warn,#b45309);color:var(--warn,#b45309);
  background:var(--warnbg,#fff7ed)}

/* The section pills. They pick which page of the tab is on the screen, so the one you
   are on has to look picked - they used to be jump links, where nothing was selected
   because nothing stayed. */
#settingsNav .ghost.on{background:var(--brand);border-color:var(--brand);color:#fff}
#settingsNav .ghost.on:hover{background:var(--brand-dark);border-color:var(--brand-dark)}

.exportbar{gap:6px;align-items:center;margin:8px 0 4px}
.exportbar .foot{margin-right:2px}

@media print{
  .bar,.tabs,.tones,.actions,.toast,#empty,.exportbar,.demobar,
  .seg,.check,button,select,input,textarea,details{display:none !important}
  body.printing .panel{display:none !important}
  body.printing .panel.print-me{display:block !important}
  .print-title{font-size:16px;margin:0 0 10px}
  .col{border:0;padding:0;background:#fff}
  .card{break-inside:avoid;border:1px solid #ccc}
  table.grid{font-size:10px}
  table.grid th,table.grid td{padding:3px 6px}
  tr{break-inside:avoid}
  .tablewrap{overflow:visible}
  *{background:#fff !important;color:#000 !important}
  .tag{border:1px solid #999;padding:0 4px}
  .cardx{display:none !important}
  /* Printing one card: hide its siblings rather than the whole panel. */
  body.printing-one .card{display:none !important}
  body.printing-one .card.print-me-card{display:block !important}
  body.printing-one .block,body.printing-one .row,body.printing-one h3,
  body.printing-one .foot{display:none !important}
  body.printing-one .cards{display:block !important}

  /* The calendar. Every course on it is a <button>, and the rule above hides every
     button on the page - so the grid printed as empty boxes with day numbers in them
     and nothing else. That is the whole reason a printed month came out blank. */
  .cal-chip{display:block !important;border:1px solid #999 !important;
    padding:2px 4px;margin-bottom:2px;break-inside:avoid}
  .cal-chip .chip-sub{opacity:1}
  /* The grid draws its own lines with a background colour, which the blanket
     background rule above wipes out. Real borders instead. */
  .cal-grid{gap:0;border:1px solid #999 !important}
  .cal-day{border:1px solid #999 !important;min-height:0}
  .cal-dow{border:1px solid #999 !important;font-weight:700}
  .cal-day.today{box-shadow:none;outline:2px solid #000;outline-offset:-2px}
  /* The controls and the colour key are for the screen. */
  .cal-bar,.cal-key,#calDay{display:none !important}

  /* A month is seven columns wide. The paper is turned round by a rule printNode puts
     in and takes out again - @page cannot be switched on by a class on the body. */
  body.printing-wide .cal-grid{width:100%}
  /* S, M and L set --cal-font on .cal, and printing keeps it: the printed page is the
     size that was chosen, which is what the choice is for. */
}

.cardx{display:inline-flex;gap:5px;margin-left:auto}
.card .actions{align-items:center}

/* ------------------------------------------------------------- schedule */
.tally{gap:8px;margin:2px 0 6px}
.pill.bad{border-color:var(--bad);color:var(--bad);background:var(--badbg)}
.pill.warn{border-color:var(--warn);color:var(--warn);background:var(--warnbg)}
.dim{opacity:.45}
ul.plain.dates{margin:8px 0 0;padding:0;list-style:none;display:grid;gap:5px}
ul.plain.dates li{display:flex;flex-wrap:wrap;align-items:center;gap:7px;
  padding:5px 9px;background:var(--sunk);border:1px solid var(--line);border-radius:8px}
ul.plain.dates li.bad{border-color:var(--bad)}
ul.plain.dates .foot{margin:0;font-size:12px}

/* -------------------------------------------------------------- calendar */
.cal{--cal-font:12.5px}
.cal-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:9px}
.cal-bar.options{padding:8px 10px;background:var(--sunk);border:1px solid var(--line);
  border-radius:9px;margin-bottom:11px;row-gap:7px}
.cal-bar .grow{flex:1;min-width:60px}
.tiny-select{width:auto!important;padding:5px 8px!important;font-size:12px!important;
  border:1px solid var(--line);border-radius:7px;background:var(--card);color:var(--ink)}
.seg.tiny-seg button{padding:5px 10px;font-size:12px}
.check.tiny{font-size:12px;gap:4px}

.cal-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:var(--radius);
  overflow:hidden}
.cal-dow{background:var(--sunk);color:var(--muted);font-size:12px;font-weight:600;
  padding:7px 8px;text-align:center}
.cal-day{background:var(--card);min-height:104px;padding:5px 5px 7px;
  display:flex;flex-direction:column;gap:4px}
.cal-grid.week .cal-day{min-height:340px}
.cal-day.empty{background:var(--sunk)}
.cal-day.outside{background:var(--sunk)}
.cal-day.today{box-shadow:inset 0 0 0 2px var(--brand)}
.cal-num{font-size:12px;color:var(--muted);font-weight:600}
.cal-mon{font-weight:400;opacity:.8}
.cal-day.busy .cal-num{color:var(--ink)}
.cal-items{display:grid;gap:3px;align-content:start}

.cal-chip{display:block;width:100%;text-align:left;border:1px solid var(--line);
  border-radius:6px;padding:3px 6px;font-size:var(--cal-font);line-height:1.3;
  cursor:pointer;background:var(--sunk);color:var(--ink);overflow:hidden}
.cal-chip .chip-main{display:block;font-weight:600}
.cal-chip .chip-sub{display:block;font-size:.86em;opacity:.85;margin-top:1px}
/* Compact keeps one line per course so a busy day still fits the cell. Sentence wraps,
   because the whole point of it is the full wording. */
.cal.detail-compact .cal-chip .chip-main{white-space:nowrap;text-overflow:ellipsis;
  overflow:hidden}
.cal.detail-full .cal-chip .chip-main{font-weight:400;white-space:normal}
.cal-chip:hover{filter:brightness(.96)}
.cal-chip.ok{background:var(--okbg);border-color:var(--ok);color:var(--ok)}
.cal-chip.full{background:var(--sunk);border-color:var(--muted);color:var(--muted)}
.cal-chip.full .chip-main{text-decoration:line-through}
.cal-chip.bad{background:var(--badbg);border-color:var(--bad);color:var(--bad)}
.cal-chip.private{background:var(--warnbg);border-color:var(--warn);color:var(--warn)}
.cal-chip.web{background:var(--card);border-style:dashed}
.cal-chip.cont{opacity:.72}
.cal-key{display:flex;gap:7px;flex-wrap:wrap;margin-top:9px;align-items:center}
.cal-key .cal-chip{width:auto;cursor:default;padding:2px 8px}

/* -------------------------------------------------------------- agenda */
.agenda{display:grid;gap:7px}
.agenda-day{display:flex;gap:13px;align-items:flex-start;padding:9px 11px;
  background:var(--card);border:1px solid var(--line);border-radius:9px}
.agenda-day.today{border-color:var(--brand)}
.agenda-when{min-width:74px;display:flex;flex-direction:column;line-height:1.2}
.agenda-when b{font-size:19px}
.agenda-when span{font-size:12px;color:var(--muted)}
.agenda-day .cal-items{flex:1}

/* A seven-column grid on a phone gives every day four characters. Below that width the
   grid becomes an agenda: the days that have something on, in order. */
@media (max-width:760px){
  .cal-grid{grid-template-columns:minmax(0,1fr);background:transparent;border:0;
    gap:6px}
  .cal-dow{display:none}
  .cal-day{display:none}
  .cal-day.busy{display:flex;border:1px solid var(--line);border-radius:9px;
    min-height:0;flex-direction:row;align-items:flex-start;gap:10px;padding:9px 11px}
  .cal-grid.week .cal-day.busy{min-height:0}
  .cal-day.busy .cal-num{min-width:26px;font-size:15px}
  .cal-day.busy .cal-items{flex:1}
  .cal.detail-compact .cal-chip .chip-main{white-space:normal}
}

/* -------------------------------------------------------------- settings */
.settings-find{position:sticky;top:52px;z-index:9;background:var(--card);
  padding:8px 0;margin-bottom:2px}
.section-nav{gap:6px;margin-bottom:12px}
.section-nav button{border-radius:20px}
.block.flash{animation:flash 1.2s ease-out}
@keyframes flash{
  0%{box-shadow:0 0 0 2px var(--brand)}
  100%{box-shadow:0 0 0 2px transparent}
}
.testout.ok{color:var(--ok)}
.testout.bad{color:var(--bad)}
.sub-details{margin-top:10px;border:1px solid var(--line);border-radius:9px;
  padding:8px 12px;background:var(--sunk)}
.sub-details summary{cursor:pointer;font-size:13px;color:var(--muted)}
#sheetJson{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12px}

/* ---------------------------------------------------------------- actions */
.ghost.danger{border-color:var(--bad);color:var(--bad)}
.ghost.danger:hover{background:var(--badbg)}
.ghost.danger:disabled{opacity:.45;cursor:default}
td.actions-cell{white-space:nowrap}
td.actions-cell button{margin-right:4px}
/* Built to be exported, not to be looked at. */
.cards.offscreen{position:absolute;left:-10000px;top:0;width:520px}
tr.row-open td{background:var(--sunk)}

/* ------------------------------------------------------- settings sub-tabs */
.sub-tabs{margin:0 0 14px;gap:2px;border-bottom:1px solid var(--line)}
.sub-tabs.dim{opacity:.5}
.sub-tabs .tab{font-size:13px;padding:7px 14px}

/* ------------------------------------------------------- the row editor */
.sheet-editor{position:fixed;inset:0;z-index:60;background:rgba(0,0,0,.45);
  display:flex;align-items:flex-start;justify-content:center;overflow-y:auto;
  padding:24px 14px}
.sheet-editor-inner{background:var(--card);border:1px solid var(--line);
  border-radius:var(--radius);padding:18px 20px;width:100%;max-width:720px;
  box-shadow:0 18px 48px rgba(0,0,0,.28)}
/* A bare 1fr is minmax(auto,1fr), and that auto floor is the item's min-content width -
   which on a phone is how one long label holds a whole column wider than the screen.
   minmax(0,1fr) throughout, so a track may actually shrink. */
.sheet-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(230px,100%),1fr));
  gap:10px;margin:14px 0}
.sheet-fields .field{display:flex;flex-direction:column;gap:3px}
.sheet-fields .lbl{font-size:12px}
.sheet-actions{border-top:1px solid var(--line);padding-top:13px;align-items:center}
@media (max-width:620px){
  .sheet-editor{padding:0}
  .sheet-editor-inner{border-radius:0;min-height:100%}
  .sheet-fields{grid-template-columns:minmax(0,1fr)}
}

/* --------------------------------------------------------- setup guidance */
.setup-help{margin:8px 0 12px;border:1px solid var(--line);border-radius:9px;
  background:var(--sunk)}
.setup-help summary{cursor:pointer;padding:8px 12px;font-size:13px;color:var(--brand);
  font-weight:600;list-style:none}
.setup-help summary::-webkit-details-marker{display:none}
.setup-help summary::before{content:"? ";font-weight:700}
.setup-help[open] summary{border-bottom:1px solid var(--line)}
.setup-body{padding:4px 16px 12px;font-size:13.5px;line-height:1.6}
.setup-body h5{margin:12px 0 4px;font-size:13px;color:var(--ink)}
.setup-body ol,.setup-body ul{margin:6px 0;padding-left:20px}
.setup-body li{margin:4px 0}
.setup-body code{background:var(--card);padding:1px 5px;border-radius:4px;font-size:12px}
.setup-body .foot{margin:8px 0 0}

/* ------------------------------------------------------------------- mail */
.mail{display:grid;
  /* The panel is a flex row, so without this the grid sizes to its contents and folding
     a pane shrinks the whole thing instead of giving the room to the reading pane. */
  flex:1;min-width:0;
  /* minmax(0,…) lets a pane be squeezed rather than forcing the grid wider than the
     screen; the reading pane keeps a floor so it never disappears entirely. */
  grid-template-columns:minmax(0,var(--mail-folders,190px)) 5px
                        minmax(0,var(--mail-list,300px)) 5px minmax(220px,1fr);
  gap:0;background:var(--line);border:1px solid var(--line);
  border-radius:var(--radius);overflow:hidden;min-height:560px}
.mail>section,.mail>aside{border-right:1px solid var(--line)}
.mail>.mail-read{border-right:0}

/* The dividers. Wide enough to catch with a mouse, quiet enough to ignore — a hairline
   that thickens a little under the cursor, and only takes a colour while it is actually
   being dragged. A full-height bar on hover is a lot of movement for something you were
   only passing over. */
.mail-drag{cursor:col-resize;background:transparent;position:relative}
.mail-drag::before{content:"";position:absolute;top:0;bottom:0;left:2px;width:1px;
  background:var(--line);transition:background .12s,width .12s}
.mail-drag:hover::before{background:var(--muted);width:2px;left:1.5px}
/* Grey while dragging, not red. Red reads as a warning, and resizing a pane is not one. */
.mail-drag:active::before{background:var(--ink);width:2px;left:1.5px}
/* A little more room to grab than the line itself, without looking wider. */
.mail-drag::after{content:"";position:absolute;inset:0 -3px}
body.dragging-pane{cursor:col-resize;user-select:none}
body.dragging-pane iframe{pointer-events:none}

/* A folded pane keeps its place in the grid at zero width; hiding its contents stops
   the text spilling out of a column that is no longer there. */
.mail.folded-folders>.mail-folders,
.mail.folded-list>.mail-list{padding:0;overflow:hidden;border-right:0}
.mail.folded-folders>.mail-folders>*,
.mail.folded-list>.mail-list>*{display:none}
/* The toolbar: a pencil on the left, the four menus on the right. */
.mailbar{gap:2px;align-items:center;padding:2px 0 4px}
.mailbar-space{flex:1}
.mailbar .iconbtn{font-size:17px;padding:7px 11px;line-height:1;min-width:38px}
.mailbar .iconbtn.on{background:var(--brand);color:#fff;border-color:var(--brand)}
/* Writing a message is the one thing on this bar somebody comes looking for, so it is
   the one thing that is not grey. */
#mailNewTop{background:var(--brand);color:#fff;border-color:var(--brand);font-size:18px}
#mailNewTop:hover{background:var(--brand-dark);border-color:var(--brand-dark)}
#mailBarNote{margin:0 0 6px}

/* A menu, whether it drops from the bar or comes from a right-click. */
.mailmenu{position:absolute;z-index:75;min-width:210px;background:var(--card);
  border:1px solid var(--line);border-radius:10px;padding:5px;
  box-shadow:0 14px 38px rgba(0,0,0,.4);display:grid;gap:1px}
.mailmenu button{display:block;width:100%;text-align:left;border:0;background:transparent;
  color:var(--ink);padding:7px 10px;border-radius:6px;cursor:pointer;font-size:13px;
  white-space:nowrap}
.mailmenu button:hover:not(:disabled){background:var(--sunk)}
.mailmenu button:disabled{color:var(--muted);cursor:not-allowed}
.mailmenu-head{font-size:10.5px;text-transform:uppercase;letter-spacing:.4px;
  color:var(--muted);padding:8px 10px 3px;border-top:1px solid var(--line);margin-top:3px}
.mailmenu-rule{height:1px;background:var(--line);margin:3px 6px}
/* The one with no undo looks like it. */
.mailmenu button.danger-item{color:var(--bad)}
.mailmenu button.danger-item:hover:not(:disabled){background:var(--badbg);color:var(--bad)}
/* The list pane has to be the frame the dropdown is positioned against. */
.mail-list{position:relative}
/* Ticks only show while somebody is selecting. */
#mailMessages:not(.picking) .mail-tick{display:none}

/* The filter sits at the end of the search box rather than beside it. */
.mail-searchwrap{position:relative;display:flex;align-items:center;flex:1;
  min-width:180px;max-width:360px}
.mail-search{margin:0;padding:6px 34px 6px 11px!important;font-size:13px!important;
  width:100%}
.mail-searchwrap .iconbtn{position:absolute;right:3px;border:0;background:transparent;
  color:var(--muted);cursor:pointer;font-size:14px;padding:4px 6px;border-radius:6px}
.mail-searchwrap .iconbtn:hover{color:var(--brand);background:var(--sunk)}
/* A dot rather than a number written over the icon. */
.mail-searchwrap .iconbtn.filtering{color:var(--brand)}
.mail-searchwrap .iconbtn.filtering::after{content:"";position:absolute;top:2px;right:2px;
  width:6px;height:6px;border-radius:50%;background:var(--brand)}

/* The act-on-several row stays on one line and scrolls if it has to. */
.mail-toolbar.nowrap{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none}
.mail-toolbar.nowrap::-webkit-scrollbar{display:none}
.mail-toolbar.nowrap>*{flex:0 0 auto}
/* Stays put while the message scrolls under it: on a long thread the search and the
   fold buttons were three screens up. */
.mail-folds{position:sticky;top:0;z-index:15;background:var(--card);padding-top:2px;
  gap:5px;padding-bottom:8px;margin-bottom:8px;align-items:center;
  border-bottom:1px solid var(--line)}
/* The panes scroll and have padding; the dividers between them are 5px of nothing and must not. */
/* The panes run to the bottom of the window rather than stopping at 76% of it, which
   left a band of empty page under them. The top of the grid is measured into --mailtop
   because it moves: the header wraps, the ticker takes a row, the tab bar is sticky. */
.mail>section,.mail>aside{background:var(--card);padding:12px 14px;overflow-y:auto;
  height:calc(100vh - var(--mailtop, 210px) - 14px);min-height:320px}

/* Thin, and never red. A scrollbar is furniture; the red one between the panes read as
   something gone wrong. */
.mail>section::-webkit-scrollbar,.mail>aside::-webkit-scrollbar{width:8px;height:8px}
.mail>section::-webkit-scrollbar-thumb,.mail>aside::-webkit-scrollbar-thumb{
  background:var(--line);border-radius:4px}
.mail>section::-webkit-scrollbar-thumb:hover,
.mail>aside::-webkit-scrollbar-thumb:hover{background:var(--muted)}
.mail>section::-webkit-scrollbar-track,.mail>aside::-webkit-scrollbar-track{
  background:transparent}
.mail>section,.mail>aside{scrollbar-width:thin;
  scrollbar-color:var(--line) transparent}
.mail-folders{display:flex;flex-direction:column;gap:2px}
/* A folder row: the twist, the name, and the pin. The pin appears on hover or when it is
   set, so a list of forty is not a list of forty stars. */
.mail-folder-row{display:flex;align-items:center;gap:1px}
.mail-folder-row .mail-folder{flex:1;min-width:0}
.mail-folder-row .mail-pin{opacity:0;font-size:11px;padding:2px 4px;flex:0 0 auto}
.mail-folder-row:hover .mail-pin{opacity:.55}
.mail-folder-row .mail-pin.on{opacity:1;color:var(--brand);filter:none}
.mail-twist-space{width:15px;flex:0 0 auto}
.mail-folders .mail-twist{float:none;padding:2px 3px;width:15px;flex:0 0 auto}
.mail-folder{display:block;width:100%;text-align:left;border:0;background:transparent;
  color:var(--ink);padding:7px 10px;border-radius:7px;cursor:pointer;font-size:13.5px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mail-folder:hover{background:var(--sunk)}
.mail-folder.on{background:var(--brand);color:#fff;font-weight:600}

.mail-item{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:2px 8px;width:100%;
  text-align:left;border:0;border-bottom:1px solid var(--line);background:transparent;
  color:var(--ink);padding:9px 8px;cursor:pointer}
.mail-item:hover{background:var(--sunk)}
.mail-item.on{background:var(--sunk);box-shadow:inset 3px 0 0 var(--brand)}
.mail-from{font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mail-when{font-size:11.5px;color:var(--muted);white-space:nowrap}
.mail-subject{grid-column:1/-1;font-size:12.5px;color:var(--muted);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.mail-item.unread .mail-from{font-weight:700}
.mail-item.unread .mail-subject{color:var(--ink)}

.mail-head{border-bottom:1px solid var(--line);padding-bottom:12px;margin-bottom:12px}
.mail-meta{display:grid;grid-template-columns:auto minmax(0,1fr);gap:2px 12px;margin:9px 0;
  font-size:13px}
.mail-meta dt{color:var(--muted)}
.mail-meta dd{margin:0}
.mail-body{white-space:pre-wrap;font-size:14px;line-height:1.6;word-break:break-word}

/* An HTML message, on its own sheet of white paper.

   Mail is written for a white background - senders set a dark grey for their body text
   and leave the background to the client - so rendering one on this app's dark theme
   gives dark grey on near-black. Every mail client in the world puts the message on
   white for this reason, and so does this.

   Contained, so a message with a very wide table scrolls itself rather than stretching
   the screen, and so its own sizes cannot reach anything outside. */
.mail-html{background:#fff;color:#15181c;border:1px solid var(--line);
  border-radius:var(--radius);padding:16px 18px;font-size:14px;line-height:1.55;
  overflow-x:auto;overflow-wrap:anywhere;contain:content;
  font-family:-apple-system,"Segoe UI",Roboto,Arial,sans-serif}
.mail-html img{max-width:100%;height:auto}
.mail-html table{border-collapse:collapse;max-width:100%}
.mail-html td,.mail-html th{padding:2px 6px;vertical-align:top}
.mail-html a{color:#0b57d0;text-decoration:underline}
.mail-html blockquote{margin:8px 0 8px 10px;padding-left:10px;
  border-left:3px solid #d7dbe0;color:#4a5158}
.mail-html pre{white-space:pre-wrap;overflow-wrap:anywhere}
.mail-html h1,.mail-html h2,.mail-html h3{margin:10px 0 6px;line-height:1.25}
.mail-html p{margin:0 0 10px}
.mail-html hr{border:0;border-top:1px solid #dfe3e8;margin:12px 0}
/* A picture that has not been asked for leaves a marker, not a broken-image icon. */
.mail-html img.mail-img-off{min-width:18px;min-height:18px;max-height:24px;
  background:#eceff2;border:1px dashed #c3c9d0;border-radius:4px}
.mail-bodybar{gap:9px;align-items:center;margin:0 0 7px;font-size:12.5px}
.mail-imgbar{color:var(--muted);display:inline-flex;align-items:center;gap:7px;
  flex-wrap:wrap}
.mail-reply{margin-top:16px;border-top:2px solid var(--line);padding-top:14px;
  display:grid;gap:9px}
.mail-reply .field{display:flex;flex-direction:column;gap:3px}

@media (max-width:1000px){
  /* Stacked, so the dividers have nothing to divide. */
  .mail{grid-template-columns:minmax(0,1fr);max-height:none}
  .mail-drag{display:none}
  .mail.folded-folders>.mail-folders,.mail.folded-list>.mail-list{padding:12px 14px}
  .mail.folded-folders>.mail-folders>*,.mail.folded-list>.mail-list>*{display:""}
  .mail>section,.mail>aside{height:auto;max-height:none;min-height:0}
  .mail-folders{flex-direction:row;flex-wrap:wrap;overflow-x:auto}
  .mail-folder{width:auto}
  .mail-list{max-height:340px!important}
}

#mailMessages.waiting{opacity:.45;transition:opacity .12s;pointer-events:none}

/* --------------------------------------------------------------- team chat */
.ask-head{display:flex;align-items:center;justify-content:space-between;gap:9px}
[data-cpane-body]{display:flex;flex-direction:column;flex:1;min-height:0;overflow:hidden}
.ask-form{display:flex;gap:7px;align-items:flex-end}
.ask-form textarea{flex:1;min-width:0;margin:0}
.iconbtn.primary{min-width:40px;display:grid;place-items:center;font-size:15px}
.iconbtn{font-size:14px;line-height:1;padding:4px 8px;border-radius:7px}
.ask-where-line{margin:0 0 6px}

/* Who is here, as heads. A picture where somebody has set one, initials where not.
   They overlap in the head bar the way every chat app stacks them - four at most and a
   count for the rest, or a busy morning squeezes the tabs off the panel. */
.heads{display:inline-flex;align-items:center;border:0;background:transparent;
  cursor:pointer;padding:2px 4px;border-radius:14px}
.heads:hover{background:var(--sunk)}
.heads.choosing{box-shadow:inset 0 0 0 1px var(--brand)}
.chathead.mini{width:22px;height:22px;font-size:9px;margin-left:-7px;
  border:2px solid var(--card)}
.chathead.mini:first-child{margin-left:0}
.chathead.mini.more{background:var(--sunk);color:var(--muted);font-size:9.5px}
.chathead.mini.picked{border-color:var(--brand)}
.chathead{display:inline-grid;place-items:center;width:26px;height:26px;border-radius:50%;
  background:var(--brand);color:#fff;font-size:10px;font-weight:700;overflow:hidden;
  flex:0 0 auto}
.chathead.small{width:22px;height:22px;font-size:9px}
/* A head is also the way to pick who a message goes to, so it has to look pressable. */
button.chathead{border:2px solid transparent;cursor:pointer;padding:0}
button.chathead:hover{border-color:var(--muted)}
button.chathead.picked{border-color:var(--brand);box-shadow:0 0 0 2px var(--card),
  0 0 0 4px var(--brand)}
.chat-to{margin:0 0 7px}
/* The row of heads. They overlap, so fifteen people fit on a line that four used to
   fill, and the row still wraps rather than pushing the panel wider. */
.chat-here{display:flex;align-items:center;flex-wrap:nowrap;margin:0 0 6px;
  min-height:26px}
.chat-here > button.chathead{margin-left:-8px}
.chat-here > button.chathead:first-child{margin-left:0}
.chat-here > button.chathead:hover,.chat-here > button.chathead.picked{
  transform:translateY(-1px);z-index:2}
.chat-here .sub-block{width:100%}
.chat-here > button.chathead.more{background:var(--sunk);color:var(--muted);
  font-size:10px;border-color:var(--line)}
.pick-find{margin:5px 0 3px;font-size:13px;padding:6px 9px}
.pick-list{max-height:168px;overflow-y:auto;display:flex;flex-direction:column;gap:1px}

/* The writing line. The paperclip and the emoji are inside the box, so the box keeps the
   whole width and there is no arrow spending space on hiding two icons. */
/* The icons take the first line and the text takes every line under it, with the whole
   width. Beside the box they cost width; beside the text on one row they left an empty
   corner above themselves once the message ran to two lines - which is the gap Ruman
   marked. A row of their own has neither problem. */
.chat-box{display:flex;flex-direction:column;flex:1;min-width:0;
  border:1px solid var(--line);border-radius:9px;background:var(--sunk);padding:2px 4px 3px}
.chat-box:focus-within{outline:2px solid var(--brand);outline-offset:-1px}
.chat-icons{display:flex;gap:1px}
.chat-box textarea{width:100%;border:0;background:none;outline:0;resize:none;
  padding:0 4px 4px;margin:0;font-size:13.5px;color:var(--ink);line-height:1.5}
.chat-box .iconbtn{padding:3px 5px;background:none;border:0;color:var(--muted);
  cursor:pointer;font-size:14px}
.chat-box .iconbtn:hover{color:var(--ink)}

/* ------------------------------------------ what the assistant knows */
/* The four figures at the top. Big enough to be the thing somebody reads first, because
   the whole point of this screen is that a cost is visible before it is paid. */
.know-summary{border:1px solid var(--line);border-radius:11px;padding:12px 14px;
  background:var(--sunk);margin:4px 0 12px}
.know-figures{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:10px;margin-bottom:8px}
.know-figures > div{display:flex;flex-direction:column;gap:1px}
.know-big{font-size:21px;font-weight:700;color:var(--ink);line-height:1.1}
.know-big.good{color:var(--ok,#3fb950)}
.know-summary .foot{margin:0}

/* One row per source, tab, piece or limit. The same shape for all four so the screen
   reads as one list rather than four different screens stacked up. */
.know-rows{display:flex;flex-direction:column;gap:1px;margin:4px 0 14px}
.know-rows.scroller{max-height:290px;overflow-y:auto;border:1px solid var(--line);
  border-radius:9px;padding:4px}
.know-row{display:flex;align-items:flex-start;gap:9px;padding:7px 9px;border-radius:8px;
  font-size:13.5px}
.know-row:hover{background:var(--sunk)}
.know-row > .grow{display:flex;flex-direction:column;gap:1px;min-width:0}
.know-row > .grow > b{display:block}
.know-row > .grow > .foot{display:block}
.know-row .foot{margin:0;font-size:11.5px;overflow-wrap:anywhere}
.know-row input[type=checkbox]{margin-top:3px;flex:0 0 auto}
.know-cost{flex:0 0 auto;text-align:right;font-size:12.5px;color:var(--muted);
  display:flex;flex-direction:column;gap:0;white-space:nowrap}
.know-cost .foot{font-size:11px}
.know-row .linky{flex:0 0 auto;font-size:11.5px;align-self:center}

/* Dropping a file onto the list of pieces. */
.know-rows.dropping{outline:2px dashed var(--brand);outline-offset:3px;
  background:var(--sunk)}

/* The limits. Wider columns and a real two-line label: the name and the sentence under
   it were running into each other because the label span was not a column, so "Waiting-
   list breakdown" and "How many of the commonest requests to list" met in the middle. */
.know-limits{display:grid;grid-template-columns:repeat(auto-fit,minmax(330px,1fr));
  gap:4px;margin:4px 0 14px}
.know-limit{display:flex;align-items:center;gap:12px;padding:8px 10px;border-radius:8px;
  font-size:13.5px;border:1px solid transparent}
.know-limit:hover{background:var(--sunk);border-color:var(--line)}
.know-limit > .grow{display:flex;flex-direction:column;gap:2px;min-width:0;
  flex:1 1 auto}
/* Block on the two children as well as a column on the parent. The name and the sentence
   under it are a <b> and a <span>, which are inline by nature, and relying on the parent
   alone means one selector standing between "Waiting-list breakdown" and "How many of
   the commonest requests to list" ending up on the same line - which is what Ruman saw. */
.know-limit b{display:block;line-height:1.25}
.know-limit .foot{display:block;margin:0;font-size:11.5px;line-height:1.35}
/* The number box, pinned to its own width.
   The global rule is `input:not([type=checkbox]):not([type=radio]){width:100%}`, and each
   :not() carries the weight of the attribute selector inside it - so that rule is more
   specific than `.know-limit input` and was winning. The input took the whole row, the
   label was squeezed into a column two characters wide, and every word wrapped onto a
   line of its own. Matching on the type as well settles it, and flex-basis makes it
   independent of the width fight entirely. */
.know-limits input[type=number]{width:104px;max-width:104px;flex:0 0 104px;
  text-align:right}
/* A section heading with its own Save beside it. Ruman kept missing the one button at
   the bottom, which is a fair thing to miss on a screen this long. */
/* The row number, when it opens that row in the sheet. Quiet until hovered: it is a way
   through, not something to read. */
.slcol a{color:inherit;text-decoration:none;border-bottom:1px dotted var(--line)}
.slcol a:hover{color:var(--brand);border-bottom-color:var(--brand)}

/* The link out to the sheet, above a table. An anchor rather than a button, so it can be
   opened in a new tab the way somebody would expect a link out to behave. */
.sheet-add{display:inline-flex;align-items:center;gap:6px;text-decoration:none}
.sheet-add::before{content:"B";font-weight:700}
.sheet-add.waiting{opacity:.6;pointer-events:none}

/* ------------------------------------------------- what it has cost */
/* Bottom left, out of the way of the chat bubble on the right. Quiet: it is a thing to
   glance at, and a running total at the edge of the screen should not be the loudest
   thing on it - somebody who hesitates before asking a question they should ask is worse
   off than somebody who spent a penny. */
.spend{position:fixed;left:12px;bottom:12px;z-index:60;display:flex;gap:11px;
  padding:5px 10px;border-radius:9px;border:1px solid var(--line);
  background:var(--card);color:var(--muted);font-size:11.5px;line-height:1.5;
  box-shadow:0 4px 14px rgba(0,0,0,.14);cursor:pointer;
  font-variant-numeric:tabular-nums}
.spend:hover{color:var(--ink);border-color:var(--muted)}
.spend b{font-weight:700;color:var(--muted);margin-right:3px;letter-spacing:.3px}
.spend:hover b{color:var(--brand)}
/* Small: the last query alone. A dot: still there, still tappable — hiding something
   with no way back is not hiding it, it is losing it. */
.spend.small{gap:0}
.spend.dot.on{border-color:var(--brand);color:var(--brand)}
.spend.dot{gap:0;width:30px;height:30px;padding:0;display:grid;place-items:center;
  font-size:14px;border-radius:50%}
@media (max-width:620px){
  .spend{font-size:11px;padding:4px 8px;gap:8px;left:8px;bottom:8px;
    max-width:calc(100vw - 76px);flex-wrap:wrap}
}

/* The breakdown, opening upward from the chip - it is already at the bottom of the
   screen, so a panel that opened downward would open off it. */
.spend-detail{position:fixed;left:12px;bottom:52px;z-index:61;width:290px;
  max-width:calc(100vw - 24px);max-height:min(60vh,420px);overflow-y:auto;overscroll-behavior:contain;
  border:1px solid var(--line);border-radius:11px;background:var(--card);
  padding:10px 12px;box-shadow:0 10px 30px rgba(0,0,0,.28);font-size:12.5px}
.spend-head{color:var(--muted);font-size:11.5px;margin-bottom:6px}
.spend-head:not(:first-child){margin-top:8px;padding-top:8px;
  border-top:1px solid var(--line)}
.spend-person{margin:8px 0 0}
.spend-person > b{color:var(--ink)}
.spend-total{float:right;color:var(--brand);font-weight:700;
  font-variant-numeric:tabular-nums}
/* Which model this person is on now, as against which ones have been answering them. */
.spend-now{color:var(--brand);font-size:11px;padding:1px 0 2px 10px}
.spend-model{display:flex;justify-content:space-between;gap:10px;color:var(--muted);
  font-size:11.5px;padding:1px 0 1px 10px;font-variant-numeric:tabular-nums}
@media (max-width:620px){ .spend-detail{left:8px;bottom:46px} }

/* An address somebody has to paste somewhere else, with the button that copies it. */
.copyrow{display:inline-flex;align-items:center;gap:7px;margin-top:4px;flex-wrap:wrap}
.copyrow code{background:var(--sunk);border:1px solid var(--line);border-radius:6px;
  padding:2px 7px;font-size:12.5px;overflow-wrap:anywhere}

.tiny-select{font:inherit;font-size:11.5px;padding:1px 4px;border-radius:6px;
  border:1px solid var(--line);background:var(--sunk);color:var(--muted)}
.h4row{align-items:baseline;margin:16px 0 2px;gap:10px}
.h4row .h4{margin:0}
.h4{margin:16px 0 2px;font-size:13px;font-weight:700;letter-spacing:.3px;
  text-transform:uppercase;color:var(--muted)}

@media (max-width:620px){
  .know-row{flex-wrap:wrap}
  .know-cost{text-align:left;width:100%;flex-direction:row;gap:7px}
}

/* The briefing, shown word for word. Long, so it scrolls in its own box rather than
   pushing the rest of Settings off the screen. */
.know-preview{max-height:340px;overflow:auto;background:var(--sunk);
  border:1px solid var(--line);border-radius:9px;padding:11px 13px;margin:9px 0 0;
  font:12px/1.55 ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--ink);
  white-space:pre-wrap;word-break:break-word}

/* Reply and forward. The two buttons stay quiet until the message is hovered, so a
   scrollback of twenty messages is not a wall of links. On a touch screen there is no
   hover, so there they are simply always there. */
.chat-acts{display:flex;gap:9px;margin-top:3px;opacity:0;transition:opacity .12s}
.ask-turn:hover .chat-acts,.ask-turn:focus-within .chat-acts{opacity:1}
@media (hover:none){ .chat-acts{opacity:1} }
.chat-acts .linky{font-size:11.5px}

.chat-quote{margin:3px 0 5px;padding:3px 0 3px 8px;border-left:2px solid var(--brand);
  color:var(--muted);font-size:12.5px}
.chat-quote b{color:var(--ink)}
.chat-fwd{margin:0 0 2px;color:var(--muted);font-size:11.5px;font-style:italic}

/* The bar above the box saying what is being answered. */
.chat-replybar{display:flex;align-items:center;gap:8px;margin:0 14px 5px;padding:5px 9px;
  border-left:2px solid var(--brand);border-radius:0 7px 7px 0;background:var(--sunk);
  font-size:12.5px}
.chat-replybar button{background:none;border:0;color:var(--muted);cursor:pointer;
  font-size:12px;line-height:1;padding:2px 4px}
.chat-replybar button:hover{color:var(--ink)}
.linky.block{display:block;width:100%;text-align:left;padding:5px 2px}

/* Somebody is typing, and the files waiting to go with the next message. */
.chat-typing{margin:0 14px 3px;color:var(--muted);font-style:italic}
.ask-files{display:flex;flex-wrap:wrap;gap:5px;margin-top:4px}
.chat-pending{display:flex;flex-wrap:wrap;gap:5px;margin:0 14px 5px}
.chat-pending .chip{display:inline-flex;align-items:center;gap:5px;font-size:12px}
.chat-pending .chip button{background:none;border:0;color:var(--muted);cursor:pointer;
  font-size:12px;padding:0 2px;line-height:1}
.chat-pending .chip button:hover{color:var(--bad,#e5484d)}

/* ------------------------------------------- the @ list and the emoji grid */
/* Both sit just above the writing line, inside the panel, so neither can end up off the
   screen on a phone the way an absolutely-placed menu would. */
.chat-pop{margin:0 14px;border:1px solid var(--line);border-radius:9px;
  background:var(--card);box-shadow:0 -6px 20px rgba(0,0,0,.28);max-height:190px;
  overflow-y:auto}
.chat-pop > button{display:flex;align-items:baseline;gap:7px;width:100%;text-align:left;
  background:none;border:0;color:var(--ink);font:inherit;font-size:13.5px;
  padding:7px 11px;cursor:pointer}
.chat-pop > button:hover,.chat-pop > button.on{background:var(--sunk)}
.chat-pop > button.on{box-shadow:inset 2px 0 0 var(--brand)}
.chat-pop .foot{font-size:11.5px}
.emoji-grid{display:grid;grid-template-columns:repeat(9,1fr);gap:1px;padding:7px}
.emoji-grid button{background:none;border:0;cursor:pointer;font-size:18px;line-height:1;
  padding:5px 0;border-radius:6px}
.emoji-grid button:hover{background:var(--sunk)}
@media (max-width:620px){ .emoji-grid{grid-template-columns:repeat(7,1fr)} }
.chat-to.private{color:var(--brand)}
/* Unread, on the bubble for anybody who has the panel shut. */
#askBadge{position:absolute;top:-4px;right:-4px;min-width:19px;height:19px;
  border-radius:10px;background:#fff;color:var(--brand);font-size:11px;font-weight:700;
  display:grid;place-items:center;padding:0 5px;box-shadow:0 2px 6px rgba(0,0,0,.3)}
.chathead img{width:100%;height:100%;object-fit:cover}
.ask-turn{display:flex;gap:8px;align-items:flex-start;margin:0 0 9px}
.ask-turn p{margin:1px 0 0;white-space:pre-wrap;word-break:break-word}
.ask-turn.mine>div{background:var(--sunk);border-radius:9px;padding:5px 9px}
/* A shared picture shows; anything else is a chip to open. Both go when the messages do. */
.chat-shot{display:block;max-width:100%;max-height:220px;border-radius:9px;margin-top:4px;
  border:1px solid var(--line)}
.ask-turn .chip{display:inline-flex;align-items:center;gap:7px;margin-top:4px;
  border:1px solid var(--line);border-radius:8px;padding:5px 10px;background:var(--sunk);
  color:var(--ink);text-decoration:none;font-size:12.5px}
.ask-turn .chip:hover{border-color:var(--brand)}
#chatUnread{background:var(--brand);color:#fff;border-color:var(--brand);margin-left:4px}

/* ------------------------------------------------------------- the ticker */
/* One line across the middle of the header, moving. Three stacked lines made the header
   three lines tall, and the header is what every screen gives up space to. */
.ticker{flex:1 1 auto;min-width:0;overflow:hidden;position:relative;height:22px;
  margin:0 14px;mask-image:linear-gradient(90deg,transparent,#000 3%,#000 97%,transparent)}
.ticker-run{display:inline-flex;gap:34px;white-space:nowrap;align-items:center;
  height:100%;padding-left:100%;animation:tickalong 42s linear infinite;font-size:12px}
.ticker:hover .ticker-run{animation-play-state:paused}
@keyframes tickalong{from{transform:translateX(0)}to{transform:translateX(-100%)}}
.ticker-item{display:inline-flex;align-items:center;gap:7px;color:var(--muted)}
.ticker-tag{font-size:9.5px;text-transform:uppercase;letter-spacing:.4px;
  border:1px solid var(--line);border-radius:9px;padding:1px 6px;color:var(--muted)}
.ticker-item.fresh{color:var(--ink)}
.ticker-item.fresh .ticker-tag{color:#fff;background:var(--brand);border-color:var(--brand)}
/* Somebody who has asked for less movement should not be given a moving header. */
@media (prefers-reduced-motion:reduce){
  .ticker-run{animation:none;padding-left:0;overflow-x:auto}
}

a.brand{text-decoration:none;color:inherit;cursor:pointer;flex:0 0 auto}
a.brand:hover .mark{background:var(--brand-dark)}

/* ------------------------------------------------------ the menu that sticks */
/* Nine tabs at the top of a long Schedule means scrolling back up to change screen,
   which on a phone is most of a page swipe.

   The header is sticky at top:0 already, so the menu has to stop below it rather than
   behind it. Its height is measured and written to --barh, because it changes with the
   window - the chips wrap on a narrow screen and the ticker takes its own row on a
   phone. */
.tabs{position:sticky;top:var(--barh,52px);z-index:20;background:var(--bg);
  box-shadow:0 1px 0 var(--line)}

/* ------------------------------------------------------------------ phones */
/* Ruman asked that working from a phone be a strong rule rather than an afterthought, so
   these are not tweaks to a desktop layout - they are what the app is on a small screen. */
@media (max-width:760px){
  /* The menu slides on a phone, so a spacer pushing the toggle to the far end would
     push it off the end. It follows Settings instead. */
  .tabs-space{display:none}
  .tab-theme{padding:8px 10px}
  .bar{flex-wrap:wrap;gap:6px;padding:8px 12px}
  /* The brand keeps the top row to itself; everything else gets a row it can slide
     along. Squeezing eight chips into half a phone width truncated every one of them to
     a single letter and wrapped Sign out onto a line of its own - which is how the
     header ended up three rows tall and unreadable. */
  /* Three rows of header stuck to the top of a phone is a third of the screen gone
     before anything useful is on it. It scrolls away here; the menu is the part worth
     keeping, and it takes one row. */
  header.bar{grid-template-columns:minmax(0,1fr);row-gap:7px;position:static}
  .tabs{top:0}
  .ticker{grid-column:1;grid-row:3;margin:0}
  .bar-right{grid-row:2;flex-wrap:nowrap;overflow-x:auto;justify-content:flex-start;
    scrollbar-width:none;-webkit-overflow-scrolling:touch;
    /* Faded at the edges, so it is obvious there is more of it sideways. */
    mask-image:linear-gradient(90deg,#000 92%,transparent)}
  .bar-right::-webkit-scrollbar{display:none}
  .bar-right>*{flex:0 0 auto}
  .bar-right .state{font-size:11.5px;padding:3px 10px}
  .who{display:inline}

  /* Sideways rather than four rows of tabs. */
  .tabs{display:flex;overflow-x:auto;flex-wrap:nowrap;scrollbar-width:none;
    -webkit-overflow-scrolling:touch}
  .tabs::-webkit-scrollbar{display:none}
  .tabs .tab{flex:0 0 auto}

  /* A table takes the room it needs inside its own box, and never pushes the page. */
  .tablewrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
  .tabletools{gap:6px}
  .find-grid{grid-template-columns:minmax(0,1fr)}
  .compose-head{grid-template-columns:minmax(0,1fr)}
  .compose-head .lbl{margin-top:6px}

  /* The column grip is a hover affordance, and a phone has nothing to hover with. */
  .colgrip{display:none}
  #askOpen{right:12px;bottom:12px;padding:10px 16px}

  /* The panel takes the width of the phone rather than sitting in a 420px column with a
     strip of page beside it. The drag handle goes too - there is nothing to drag to.

     All four edges, and no height sum. height:calc(100vh - 80px) was the bug Ruman hit:
     on a phone 100vh is the whole screen including the browser's own URL bar, which is
     taller than the part you can actually see. Anchored to the bottom, that pushed the
     top of the panel - and the close button living in its header - up past the top of
     the screen, where there was no way to reach it. Pinning top and bottom instead asks
     the browser for the viewport it really has, whatever its chrome is doing. */
  /* Every one of these is !important, and not out of habit: the plain #askPanel rule
     that sets the desktop size lives further down this file, and at equal specificity
     the later rule wins. Its max-height:calc(100vh - 90px) was still capping the panel
     at 722px of an 812px screen, which is the strip of dead space under the composer
     that Ruman spotted. */
  #askPanel{top:10px!important;left:10px!important;right:10px!important;
    bottom:10px!important;width:auto!important;height:auto!important;
    max-height:none!important}
  .ask-grip{display:none}

  /* Nothing in that header may be pushed out of it. The close button keeps its size
     while everything to its left gives way, and the head can never be wider than the
     panel. */
  .ask-head{flex-wrap:nowrap;min-width:0;overflow:hidden}
  .ask-head .seg{flex:0 1 auto;min-width:0;overflow:hidden}
  .ask-head .heads{flex:1 1 auto;min-width:0;overflow:hidden;
    text-overflow:ellipsis;white-space:nowrap}
  .ask-head #askClose,.ask-head #chatBell{flex:0 0 auto;margin-left:auto}
  .ask-head #chatBell+#askClose{margin-left:0}
}

/* A field you can type in, inside a table cell. Narrow, because a variation screen is
   twenty columns wide and every one of them is editable. */
.cellbox{margin:0;padding:3px 6px!important;font-size:12px!important;min-width:88px;
  width:100%;box-sizing:border-box}
/* A tick is a tick, not a box the width of the column. */
.cellbox.tickbox{width:auto;min-width:0;margin:0 auto;display:block}
#edPane th{white-space:nowrap;vertical-align:bottom}
#edPane td{padding:5px 8px 5px 0;vertical-align:middle}

/* One panel per variation, the way the WooCommerce product screen has it: a row of ticks
   along the top, then two columns. Closed until opened, because a course with eleven
   dates is eleven panels and nobody edits all eleven. */
.varcard{border:1px solid var(--line);border-radius:10px;margin:7px 0;background:var(--card)}
.varcard>summary{cursor:pointer;padding:9px 12px;display:flex;align-items:center;gap:9px;
  list-style:none}
.varcard>summary::-webkit-details-marker{display:none}
.varcard>summary::before{content:"b8";color:var(--muted);font-size:11px}
.varcard[open]>summary::before{content:"be"}
.varcard[open]>summary{border-bottom:1px solid var(--line);background:var(--sunk)}
.varform{padding:12px}
.varticks{display:flex;flex-wrap:wrap;gap:16px;padding-bottom:11px;
  border-bottom:1px solid var(--line);margin-bottom:11px}
.vargrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px 22px}
.varfield{display:block;margin:0 0 9px}
.varfield .lbl{display:block;margin:0 0 2px;font-size:11.5px}
.varfield .cellbox{width:100%}
.avatar-big{width:64px;height:64px;border-radius:50%;object-fit:cover;
  border:1px solid var(--line)}
/* The QR is drawn white-on-black by default, which is unreadable by a phone camera on a
   dark page. It gets its own white square whatever the theme is. */
/* A white square whatever the theme is: a QR drawn dark-on-transparent sits on the dark
   page background and no camera will read it. The size is set on the box, and the SVG
   fills it - it carries a viewBox, so it scales rather than crops. */
.qrcode{display:inline-block;background:#fff;padding:12px;border-radius:10px;
  line-height:0;margin:0 0 10px;width:200px;height:200px;box-sizing:content-box}
.qrcode svg{display:block;width:100%;height:100%;shape-rendering:crispEdges}

/* Back to the top. Nine tabs of table is a long way down on a phone. */
#toTop{position:fixed;right:18px;bottom:74px;z-index:60;border:0;cursor:pointer;
  width:40px;height:40px;border-radius:50%;background:var(--card);color:var(--ink);
  border:1px solid var(--line);font-size:16px;line-height:1;
  box-shadow:0 4px 14px rgba(0,0,0,.24);opacity:0;pointer-events:none;
  transition:opacity .16s}
#toTop.on{opacity:1;pointer-events:auto}
#toTop:hover{background:var(--brand);color:#fff;border-color:var(--brand)}
@media (max-width:760px){ #toTop{right:12px;bottom:64px;width:44px;height:44px} }

.qrbox{font-family:ui-monospace,Menlo,monospace;font-size:15px;letter-spacing:.12em;
  background:var(--sunk);border:1px solid var(--line);border-radius:8px;padding:9px 12px;
  display:inline-block;user-select:all}
.varmore{margin-top:10px;border-top:1px solid var(--line);padding-top:9px}
@media (max-width:760px){ .vargrid{grid-template-columns:minmax(0,1fr)} }

/* The newest of the three notices, so it is obvious which one just arrived. */
.ticker-item.newest{color:var(--ink);font-weight:600}
.ticker-item.newest .ticker-tag{color:#fff;background:var(--brand);
  border-color:var(--brand)}
#edPane .tablewrap{max-height:420px;overflow:auto}
#edPane textarea{font-size:13px;font-family:inherit}
@media (max-width:760px){ .cellbox{min-width:120px} }

/* --------------------------------------------------------- the composer */
/* One row an address line, with a hairline under it, the way every mail program does it.
   Four stacked label-and-box pairs took a third of the pane before a word was typed. */
.compose-head{display:grid;grid-template-columns:auto minmax(0,1fr);gap:2px 10px;align-items:center;
  margin:8px 0}
.compose-head .lbl{margin:0;font-size:12px;color:var(--muted)}
.compose-head input{margin:0;padding:6px 2px!important;font-size:13.5px!important;
  border:0;border-bottom:1px solid var(--line);border-radius:0;background:transparent}
.compose-head input:focus{border-bottom-color:var(--brand);outline:0}
.compose-line{display:flex;align-items:center;gap:8px;min-width:0}
.compose-line input{flex:1;min-width:0}
.linky{border:0;background:transparent;color:var(--muted);cursor:pointer;font-size:12px;
  padding:2px 4px;white-space:nowrap}
.linky:hover{color:var(--brand);text-decoration:underline}
.compose-bar{gap:8px;align-items:center;margin:4px 0}
.mail-reply.dropping{outline:2px dashed var(--brand);outline-offset:3px}
.attach-strip{gap:7px;align-items:center;margin:2px 0 6px}
.attach-chip{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--line);
  border-radius:8px;padding:4px 6px 4px 9px;background:var(--sunk);font-size:12.5px;
  max-width:260px}
.attach-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.attach-x{border:0;background:transparent;cursor:pointer;color:var(--muted);font-size:15px;
  line-height:1;padding:0 3px}
.attach-x:hover{color:var(--bad)}

/* ------------------------------------------------------- advanced search */
/* Over the middle of the screen rather than inside the list pane. Fourteen fields in a
   three-hundred-pixel column pushed the messages off the bottom. */
.find-panel{position:fixed;inset:auto;top:50%;left:50%;transform:translate(-50%,-50%);
  z-index:80;width:min(620px,calc(100vw - 32px));max-height:calc(100vh - 90px);
  overflow:auto;border:1px solid var(--line);border-radius:12px;background:var(--card);
  padding:16px 18px;display:grid;gap:11px;box-shadow:0 24px 60px rgba(0,0,0,.45)}
.find-panel::backdrop,.find-back{position:fixed;inset:0;z-index:79;
  background:rgba(0,0,0,.45)}
/* One label, one field, the full width - the way the mail client the office already uses
   lays it out. Underlined rather than boxed, so fourteen rows do not read as fourteen
   boxes. */
.find-grid{grid-template-columns:120px 1fr!important;gap:2px 18px!important;
  align-items:center}
.find-grid .lbl{font-size:13px!important;color:var(--ink)!important;padding:9px 0}
.find-grid input[type=text],.find-grid input[type=date],.find-grid select{
  padding:8px 2px!important;font-size:13.5px!important;width:100%}
.find-grid input[type=text]:focus,.find-grid select:focus,
.find-grid input[type=date]:focus{border-bottom-color:var(--brand);
  box-shadow:0 1px 0 var(--brand)}
.find-panel .spread{border-top:1px solid var(--line);padding-top:12px;margin-top:4px}
@media (max-width:700px){.find-panel{width:calc(100vw - 20px);padding:13px}
  .find-grid{grid-template-columns:1fr!important}
  .find-grid .lbl{padding:8px 0 0}}
.find-grid{display:grid;grid-template-columns:auto 1fr;gap:5px 11px;align-items:center}
.find-grid .lbl{margin:0;font-size:12px;color:var(--muted);white-space:nowrap}
.find-grid input[type=text],.find-grid input[type=date],.find-grid select{
  margin:0;padding:5px 8px!important;font-size:13px!important;
  border:0;border-bottom:1px solid var(--line);border-radius:0;background:transparent}
.find-grid input[type=text]:focus,.find-grid input[type=date]:focus,
.find-grid select:focus{border-bottom-color:var(--brand);outline:0}
.find-dates{display:flex;gap:9px}
.find-dates input{flex:1;min-width:0}
@media (max-width:700px){.find-grid{grid-template-columns:1fr}
  .find-grid .lbl{margin-top:6px}}

/* --------------------------------------------------------- link preview */
.draft-preview{border:1px solid var(--line);border-radius:9px;padding:12px 14px;
  background:var(--sunk);white-space:pre-wrap;font-size:14px;line-height:1.6;
  min-height:120px;word-break:break-word}
.draft-preview a{color:var(--brand);text-decoration:underline}
.draft-preview a:hover{text-decoration:none}

/* Previewing real HTML rather than a typed draft.
 *
 * .draft-preview is pre-wrap, which is right for a draft somebody typed - its line
 * breaks are the only thing holding it together. It is wrong for HTML: a signature
 * pasted out of Outlook is pretty-printed, one tag per line and indented, and pre-wrap
 * renders every one of those newlines and tabs as real whitespace. The preview came out
 * with the logo, the name and the icons floating a couple of centimetres apart, looking
 * nothing like the signature.
 *
 * So: ordinary whitespace, and the same white sheet the mail body gets, because a
 * signature is written assuming white paper and its own dark grey text on this app's
 * dark background cannot be read. */
/* No contain:content here, unlike the mail body. It buys nothing on a preview box and
 * it makes innerText come back empty on the contained subtree, which quietly breaks
 * anything that reads the preview as text. */
.draft-preview.as-html{white-space:normal;background:#fff;color:#15181c;
  overflow-x:auto;
  font-family:-apple-system,"Segoe UI",Roboto,Arial,sans-serif}
.draft-preview.as-html img{max-width:100%;height:auto}
.draft-preview.as-html table{border-collapse:collapse;max-width:100%}
.draft-preview.as-html a{color:#0b57d0}
.draft-preview.as-html p{margin:0}
/* Being typed in. It has to look like somewhere you can type. */
.draft-preview.as-html.editing{outline:2px solid var(--brand);outline-offset:-2px;
  cursor:text}
.draft-preview.as-html.editing img{cursor:pointer}

/* ------------------------------------------------------- mail, continued */
.folder-find{padding:6px 9px!important;font-size:12.5px!important;margin:2px 0 6px}
.mail-toolbar{gap:6px;padding:6px 0;border-bottom:1px solid var(--line);align-items:center}
.mail-item{display:grid;grid-template-columns:auto auto 1fr auto;gap:0 9px;
  align-items:center;border-bottom:1px solid var(--line);padding:8px 6px}
.mail-item:hover{background:var(--sunk)}
.mail-item.on{background:var(--sunk);box-shadow:inset 3px 0 0 var(--brand)}
.mail-tick{width:auto!important;margin:0}
.mail-avatar{display:grid;place-items:center;width:30px;height:30px;border-radius:50%;
  background:var(--brand);color:#fff;font-size:11px;font-weight:700}
/* The message button takes whatever is left and no more. Without min-width:0 a long
   subject makes the grid column grow, and the marks get pushed off the right-hand edge
   instead of staying where somebody expects to find them. */
.mail-open{border:0;background:transparent;text-align:left;cursor:pointer;padding:0;
  color:var(--ink);min-width:0;max-width:100%;display:grid;gap:2px;overflow:hidden}
.mail-open .mail-from,.mail-open .mail-subject{overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;min-width:0}
.mail-line{display:flex;justify-content:space-between;gap:8px;align-items:baseline}
.mail-flag{border:0;background:transparent;cursor:pointer;color:var(--muted);
  font-size:15px;padding:2px 4px;line-height:1}
.mail-flag.on{color:var(--brand)}
.mail-item.flagged{background:var(--warnbg)}
/* Four, because these are the four that come up: read or unread, move, flag, pin. They
   are quiet until the row is hovered, so a list of sixty is not a wall of icons. */
/* Always at the right-hand end, whatever the subject is doing. */
.mail-marks{display:flex;align-items:center;gap:1px;flex:0 0 auto;margin-left:auto}
.mail-mark{border:0;background:transparent;cursor:pointer;color:var(--muted);
  font-size:13px;line-height:1;padding:3px 4px;border-radius:5px;opacity:.25}
.mail-item:hover .mail-mark{opacity:.7}
/* No fill behind them. A filled square sits over the subject when the pane is narrow,
   and the icon changing colour says the same thing without covering anything. */
.mail-mark:hover{opacity:1!important;color:var(--ink)}
.mail-mark.on,.mail-item:hover .mail-mark.on{opacity:1;color:var(--brand)}
/* The bin only goes red under the cursor, so a row of them does not read as a warning. */
.mail-bin:hover{color:var(--bad)!important}
#mailBinMany{font-size:14px}
.mail-pin{border:0;background:transparent;cursor:pointer;font-size:13px;line-height:1;
  padding:2px 3px;opacity:.22;filter:grayscale(1)}
.mail-item:hover .mail-pin{opacity:.6}
.mail-pin.on,.mail-item:hover .mail-pin.on{opacity:1;filter:none}
.mail-clip{font-size:11px;opacity:.65}

/* A conversation: the newest of the exchange, with the rest folded behind a twist. */
.mail-thread{border-bottom:1px solid var(--line)}
.mail-thread .mail-item{border-bottom:0}
.mail-thread.open{background:var(--sunk)}
.mail-twist{float:left;border:0;background:transparent;cursor:pointer;color:var(--muted);
  font-size:11px;padding:11px 2px 0 4px;line-height:1;font-variant-numeric:tabular-nums}
.mail-twist:hover{color:var(--ink)}
.mail-item.inside{padding-left:30px;border-top:1px dashed var(--line);
  background:transparent}
.mail-item.pinned{box-shadow:inset 3px 0 0 var(--warn,#c98a00)}
.mail-item.pinned.on{box-shadow:inset 3px 0 0 var(--brand)}
.file-pick{display:inline-flex;align-items:center;cursor:pointer;border:1px solid var(--line);
  border-radius:9px;padding:7px 13px;background:var(--card)}
.sub-block{border:1px solid var(--line);border-radius:9px;padding:13px 15px;
  background:var(--sunk);margin:10px 0}

/* ------------------------------------------------------- ask about this screen */
#askOpen{position:fixed;right:18px;bottom:18px;z-index:70;border:0;cursor:pointer;
  background:var(--brand);color:#fff;border-radius:24px;padding:12px 20px;
  font-size:14px;font-weight:600;box-shadow:0 6px 20px rgba(0,0,0,.28)}
#askOpen:hover{background:var(--brand-dark)}
#askOpen.on{background:var(--brand-dark)}
#askOpen::before{content:"\1F4AC";margin-right:7px}
/* Taller and a little wider: this is a conversation now, not a single answer, and eight
   lines of it in a 380px box is a lot of scrolling. */
/* Sits at the bottom of the window, not 74px up. It was held clear of the bubble, and
   the bubble hides while the panel is open - so that was an empty strip under the
   composer, waiting for a button that was not there. */
#askPanel{position:fixed;right:18px;bottom:18px;z-index:70;width:420px;
  max-width:calc(100vw - 36px);height:720px;max-height:calc(100vh - 90px);
  background:var(--card);
  border:1px solid var(--line);border-radius:var(--radius);display:flex;
  flex-direction:column;box-shadow:0 18px 48px rgba(0,0,0,.3);overflow:hidden}
/* A file waiting to be sent, and one that has been. */
.chat-pending{display:flex;flex-wrap:wrap;gap:6px;padding:0 14px 7px}
.chip.pend{display:inline-flex;align-items:center;gap:6px;max-width:100%}
.pend-shot{width:30px;height:30px;object-fit:cover;border-radius:5px;flex:none}
.pend-name{max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chat-file{display:inline-flex;flex-direction:column;align-items:flex-start;gap:3px}
.chat-file .link.tiny{font-size:11.5px}

.ask-head{display:flex;gap:8px;align-items:center;padding:9px 12px;
  border-bottom:1px solid var(--line);flex-wrap:nowrap}
/* The heads take the space between the tabs and the bell, which is what that gap was
   there for. */
.ask-head .heads{flex:1;min-width:0;justify-content:center}

/* The corner it is dragged bigger by. Top-left, because it is anchored bottom-right and
   that is the corner that grows. */
.ask-grip{position:absolute;top:0;left:0;width:18px;height:18px;cursor:nwse-resize;
  z-index:2}
.ask-grip::after{content:"";position:absolute;top:5px;left:5px;width:7px;height:7px;
  border-top:2px solid var(--muted);border-left:2px solid var(--muted);
  border-radius:2px 0 0 0}
.ask-grip:hover::after{border-color:var(--brand)}
.ask-head .foot{margin:2px 0 0}
.ask-turns{flex:1;min-height:0;flex:1;overflow-y:auto;padding:12px 14px;display:grid;gap:11px;
  align-content:start;min-height:80px}
.ask-turn{display:grid;gap:3px}
.ask-turn.user .ask-text{background:var(--brand);color:#fff;justify-self:end;
  border-radius:12px 12px 3px 12px}
.ask-turn.assistant .ask-text{background:var(--sunk);border:1px solid var(--line);
  border-radius:12px 12px 12px 3px}
.ask-text{padding:8px 12px;font-size:13.5px;line-height:1.55;max-width:92%;
  word-break:break-word;white-space:pre-wrap}
.ask-turn.user .ask-text{white-space:pre-wrap}
.ask-text a{color:inherit;text-decoration:underline}
.ask-who{font-size:11px;color:var(--muted)}
.ask-actions{display:flex;gap:5px}
.ask-suggest{display:flex;flex-wrap:wrap;gap:5px;padding:0 14px 8px}
.ask-form{display:flex;gap:7px;padding:10px 14px;border-top:1px solid var(--line);
  align-items:flex-end}
.ask-form textarea{flex:1;resize:none;font-size:13.5px}
@media (max-width:620px){
  #askPanel{right:8px;left:8px;bottom:70px;width:auto;max-height:calc(100vh - 100px)}
  #askOpen{right:12px;bottom:12px;padding:11px 16px}
}

/* -------------------------------------------------------- document preview */
.doc-split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);gap:16px;
  align-items:start}
.doc-preview{position:sticky;top:66px}
.preview-stage{border:1px solid var(--line);border-radius:9px;background:#fff;
  overflow:hidden;min-height:180px;position:relative}
.preview-stage.busy{opacity:.55}
.preview-page{background:#fff;color:#111;position:relative}
.preview-page.slide{box-shadow:inset 0 0 0 1px rgba(0,0,0,.06)}
.preview-page.slide div{line-height:1.15}
.preview-page.flow{padding:26px 30px;font:11pt/1.5 Calibri,Arial,sans-serif;
  transform:none!important}
.preview-page.flow p{margin:0 0 6px}
.preview-page.flow p.heading{font-size:15pt;font-weight:700;margin:10px 0 6px}
.preview-page.flow .gap{height:9px}
.preview-page.flow table{border-collapse:collapse;width:100%;margin:8px 0}
.preview-page.flow td{border:1px solid #ccc;padding:3px 6px;font-size:9.5pt}
.preview-page img{display:block}
img.preview-page{width:100%;height:auto}
.bulk-nav{align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--line);
  margin-bottom:10px}
.bulk-nav b{min-width:86px;text-align:center}
@media (max-width:1000px){
  .doc-split{grid-template-columns:minmax(0,1fr)}
  .doc-preview{position:static}
}

/* ------------------------------------------------- naming words as fields */
.lit-list{display:grid;gap:7px;margin:10px 0}
.lit-row{display:grid;grid-template-columns:minmax(0,1.1fr) auto minmax(0,1fr);
  gap:9px;align-items:center}
.lit-was{font-size:13px;background:var(--card);border:1px solid var(--line);
  border-radius:7px;padding:6px 10px;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.lit-arrow{font-size:11.5px;color:var(--muted);white-space:nowrap}
@media (max-width:760px){
  .lit-row{grid-template-columns:1fr}
  .lit-arrow{margin-left:2px}
}

/* ------------------------------------------------------------ pdf preview */
.preview-pdf{width:100%;height:min(68vh,760px);border:0;display:block;background:#fff}
.preview-stage:has(.preview-pdf){height:auto!important}
.sheet-fields .field.wide{grid-column:1/-1}
.sheet-fields textarea{font:14px/1.55 inherit;resize:vertical}

/* ------------------------------------------------- putting boxes on a page */
.place-stage{border:1px solid var(--line);border-radius:9px;background:#fff;
  overflow:hidden;position:relative;min-height:240px}
.place-page{position:relative;background:#fff;color:#111;cursor:crosshair;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.06)}
.place-word{position:absolute;white-space:nowrap;color:#333;pointer-events:none;
  font-family:Helvetica,Arial,sans-serif;line-height:1}
.place-box{position:absolute;border:1.5px solid var(--brand);
  background:rgba(200,16,46,.10);cursor:move;border-radius:2px}
.place-box.on{background:rgba(200,16,46,.20);box-shadow:0 0 0 2px rgba(200,16,46,.35)}
.place-name{position:absolute;left:2px;top:-14px;font-size:9px;color:var(--brand);
  background:#fff;padding:0 3px;white-space:nowrap;border-radius:2px;
  font-family:-apple-system,Segoe UI,Roboto,Arial,sans-serif}
.place-grip{position:absolute;right:-4px;bottom:-4px;width:10px;height:10px;
  background:var(--brand);border:1px solid #fff;border-radius:2px;cursor:nwse-resize}
.place-row{border:1px solid var(--line);border-radius:8px;padding:8px 10px;margin:6px 0;
  display:grid;gap:5px;background:var(--card)}
.place-row.on{border-color:var(--brand);background:var(--sunk)}

/* An image in the editor, with a corner to drag and somewhere to put it. The frame sits
   on the body rather than inside the editor, so Quill never sees it as content. */
.imgframe{position:absolute;z-index:78;border:1px solid var(--brand);pointer-events:none;
  box-shadow:0 0 0 1px rgba(0,0,0,.25)}
.imgframe>*{pointer-events:auto}
.imggrip{position:absolute;right:-6px;bottom:-6px;width:13px;height:13px;
  background:var(--brand);border:2px solid var(--card);border-radius:3px;
  cursor:nwse-resize}
.imgsize{position:absolute;left:0;top:-21px;font-size:10.5px;background:var(--brand);
  color:#fff;padding:1px 6px;border-radius:4px;white-space:nowrap}
.imgtools{position:absolute;left:0;bottom:-30px;display:flex;gap:2px;background:var(--card);
  border:1px solid var(--line);border-radius:7px;padding:2px;white-space:nowrap;
  box-shadow:0 6px 18px rgba(0,0,0,.3)}
.imgtools button{border:0;background:transparent;color:var(--muted);cursor:pointer;
  font-size:11px;padding:3px 7px;border-radius:5px}
.imgtools button:hover{background:var(--sunk);color:var(--ink)}
.ql-editor img{max-width:100%;height:auto;cursor:pointer}

/* --------------------------------------------- the adjusted version */
/* Marked off from the draft so the two are never mistaken for one another - this is the
   version on offer, not the one in hand. */
.alt-wrap{border:1px solid var(--brand);border-radius:11px;padding:11px 12px;
  background:color-mix(in srgb,var(--brand) 5%,transparent)}
.alt-wrap .lbl{color:var(--brand)}
.alt-wrap .opt{color:var(--muted)}

/* ----------------------------------------------------- the theme toggle */
/* Pushed to the far end of the menu bar. It is not a tab and should not read as one:
   no underline, no active state, just the glyph. */
.tabs-space{flex:1;min-width:8px}
.tab-theme{background:none;border:0;color:var(--muted);cursor:pointer;font-size:17px;
  line-height:1;padding:8px 12px;border-radius:8px;align-self:center}
.tab-theme:hover{color:var(--ink);background:var(--sunk)}
.tab-theme:focus-visible{outline:2px solid var(--brand);outline-offset:-2px}

/* ------------------------------------------------------------- rich boxes */
/* Quill ships a light theme. These are the few colours it needs to belong here, rather
   than a fork of its stylesheet - the rest of snow.css is layout and does no harm. */
/* The wrapper holds the toolbar and the writing area together. Quill's own container is
   height:100%, which before the wrapper resolved against the field and was harmless -
   inside it, it resolved against the wrapper, so the toolbar's height was counted once
   for the wrapper and again for the box, and the editor hung 93px past its own bottom
   edge, over whatever was underneath. That was the input covered on the Compose tab.
   Both halves size to their content; the box keeps its own min-height. */
.richshell{width:100%;display:flex;flex-direction:column}
.richshell .ql-toolbar{flex:0 0 auto}
.richshell .ql-container{flex:0 0 auto;height:auto}
/* Dragged taller by its bottom corner, the way the textareas it replaced could be. The
   grip goes on the writing area rather than the wrapper, so the box grows with it and
   the toolbar stays where it is. */
.richshell .ql-editor{height:auto;resize:vertical;overflow-y:auto}
/* The same colour every other box in the app uses for something you type into. It was
   --card, which is the colour of the panel it sits on, so the editor had no edge and no
   surface - there was nothing to say where the writing area began. */
.richbox{background:var(--sunk);border:1px solid var(--line);border-radius:0 0 9px 9px;
  color:var(--ink);font-size:15px}
.richshell:focus-within .richbox,
.richshell:focus-within .ql-toolbar.ql-snow{border-color:var(--brand)}
.ql-toolbar.ql-snow{border:1px solid var(--line);border-bottom:0;border-radius:9px 9px 0 0;
  background:var(--sunk);padding:5px 7px}
.ql-container.ql-snow{border:0}
/* Quill's own stylesheet is written for a light page, so the text it sets is dark. On a
   dark page that is dark on dark. Everything it draws takes the page's own colours. */
/* 13px was Quill's own, and at 13px on a dark background this reads as blurred rather
   than small. This is a box people write paragraphs in, so it gets the size the rest of
   the app uses for body text. */
.ql-editor{min-height:inherit;padding:11px 13px;line-height:1.6;color:var(--ink);
  font-size:15px;-webkit-font-smoothing:antialiased}
.ql-editor.ql-blank::before{font-size:15px}
.ql-editor p,.ql-editor li,.ql-editor h1,.ql-editor h2,.ql-editor h3,
.ql-editor strong,.ql-editor em,.ql-editor u{color:inherit}
.ql-editor a{color:var(--brand)}
.ql-container{color:var(--ink)}
.ql-snow .ql-picker-options{background:var(--card);border-color:var(--line)}
.ql-snow .ql-picker-item{color:var(--ink)}
/* Quill's placeholder is faint italic, which on a dark page reads as smudged rather than
   as a hint. Same weight as the text it stands in for, just quieter. */
.ql-editor.ql-blank::before{color:var(--muted);font-style:normal;left:13px;right:13px;
  opacity:.85}
.ql-snow .ql-stroke{stroke:var(--muted)}
.ql-snow .ql-fill{fill:var(--muted)}
.ql-snow .ql-picker{color:var(--muted)}
.ql-snow .ql-toolbar button:hover .ql-stroke,
.ql-snow button:hover .ql-stroke{stroke:var(--ink)}
.ql-snow .ql-toolbar button.ql-active .ql-stroke,
.ql-snow button.ql-active .ql-stroke{stroke:var(--brand)}
.ql-snow .ql-toolbar button.ql-active .ql-fill,
.ql-snow button.ql-active .ql-fill{fill:var(--brand)}
/* Quill's link tooltip is white-on-white against a dark page without this. */
.ql-snow .ql-tooltip{background:var(--card);border-color:var(--line);color:var(--ink);
  box-shadow:0 8px 24px rgba(0,0,0,.35);border-radius:8px}
.ql-snow .ql-tooltip input[type=text]{background:var(--sunk);border-color:var(--line);
  color:var(--ink)}
.ql-snow .ql-tooltip a.ql-action,.ql-snow .ql-tooltip a.ql-remove{color:var(--brand)}
/* The dropdowns: heading, size, colour, alignment. Quill draws the closed one as text
   rather than an icon, so it needs the page's ink or it stays near-black on dark. */
.ql-snow .ql-picker-label{color:var(--ink)}
/* Quill calls the unset heading "Normal" and the unset size "Normal" too, so the two
   dropdowns sat side by side saying the same word. The first one is paragraph style. */
.ql-snow .ql-picker.ql-header .ql-picker-label:not([data-value])::before,
.ql-snow .ql-picker.ql-header .ql-picker-item:not([data-value])::before{
  content:"Paragraph"}
.ql-snow .ql-picker-label:hover,.ql-snow .ql-picker-label.ql-active{color:var(--brand)}
.ql-snow .ql-picker-label:hover .ql-stroke,
.ql-snow .ql-picker-label.ql-active .ql-stroke{stroke:var(--brand)}
.ql-snow .ql-picker-options{box-shadow:0 8px 24px rgba(0,0,0,.35);border-radius:8px}
.ql-snow .ql-picker-item:hover,.ql-snow .ql-picker-item.ql-selected{color:var(--brand)}
/* Headings and sizes are classes on the way out, so they are given real sizes here -
   a class name means nothing once the HTML is sitting in somebody else's inbox. */
.ql-editor h1{font-size:1.7em;margin:.5em 0 .3em}
.ql-editor h2{font-size:1.4em;margin:.5em 0 .3em}
.ql-editor h3{font-size:1.18em;margin:.5em 0 .3em}
.ql-editor blockquote{border-left:3px solid var(--line);padding-left:12px;margin:.5em 0;
  color:var(--muted)}
.ql-editor pre.ql-syntax,.ql-editor pre{background:var(--bg);color:var(--ink);
  border:1px solid var(--line);border-radius:6px;padding:8px 10px;
  font:13px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;white-space:pre-wrap}
/* A toolbar this long wraps on a narrow pane; the rows need to sit together. */
.ql-toolbar.ql-snow .ql-formats{margin-right:9px}

/* The four lines a drafted email ends with, shown as they will arrive. Monospace and a
   sunk panel so it reads as a preview of something rather than as more form to fill in.
   --sunk rather than --card: it sits on a card already, and matching it would leave the
   preview with no edge. */
.draft-signoff {
  margin: .5rem 0;
  padding: .6rem .75rem;
  border-left: 3px solid var(--line);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--sunk);
  color: var(--ink);
  white-space: pre-wrap;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  line-height: 1.5;
}

/* ------------------------------------------------------------- course day

   The list taken to a course and marked afterwards. Built for a phone held in one hand
   in a room with no desk: the two marks are big enough to hit with a thumb, the row
   colours what has been decided, and the money column is the only thing that shrinks
   away on a narrow screen. */
.cd-totals { gap: .4rem; margin: .5rem 0; }

.cd-chip {
  padding: .25rem .6rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--sunk);
  font-size: .85rem;
  white-space: nowrap;
}
.cd-chip b { font-size: 1rem; }
.cd-chip.ok   { border-color: var(--ok);   background: var(--okbg); }
.cd-chip.warn { border-color: var(--warn); background: var(--warnbg); }
.cd-chip.bad  { border-color: var(--bad);  background: var(--badbg); }

.cd-head { margin: .5rem 0; }

.cd-table { width: 100%; border-collapse: collapse; }
.cd-table th {
  text-align: left;
  font-size: .75rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
  padding: .4rem .5rem;
  border-bottom: 1px solid var(--line);
}
.cd-table td { padding: .5rem; border-bottom: 1px solid var(--line); vertical-align: top; }

/* What has been decided, at a glance and without reading anything. */
.cd-row.present, .cd-row.added { background: var(--okbg); }
.cd-row.absent { opacity: .55; }
.cd-row.absent b { text-decoration: line-through; }

.cd-mark { white-space: nowrap; width: 5.5rem; }
.cd-tick, .cd-cross {
  width: 2.2rem;
  height: 2.2rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--card);
  color: var(--muted);
  font-size: 1.1rem;
  cursor: pointer;
}
.cd-tick.on  { background: var(--ok);  border-color: var(--ok);  color: #fff; }
.cd-cross.on { background: var(--bad); border-color: var(--bad); color: #fff; }

.cd-amount { text-align: right; white-space: nowrap; }
.cd-phone { white-space: nowrap; }

/* What the photograph proposed. Sits above the list, and every line in it is a
   question with its answer beside it. */
.cd-proposal {
  margin: .75rem 0;
  padding: .75rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--brand);
  border-radius: var(--radius);
  background: var(--sunk);
}
.cd-suggest {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  align-items: center;
  justify-content: space-between;
  padding: .4rem 0;
  border-bottom: 1px solid var(--line);
}
.cd-suggest:last-child { border-bottom: 0; }
.cd-suggest.done { opacity: .45; }
.cd-suggest.done button { display: none; }

.warn-line {
  margin: .4rem 0;
  padding: .4rem .6rem;
  border-radius: 8px;
  background: var(--warnbg);
  color: var(--warn);
  font-size: .9rem;
}

.file-button { cursor: pointer; }

@media (max-width: 620px) {
  /* On a phone the invoice number and the company are the first things to go: the job
     in the room is ticking names, and "has this one paid?" is a colour rather than a
     column. */
  .cd-table th:nth-child(5), .cd-table td:nth-child(5) { display: none; }
  .cd-table th, .cd-table td { padding: .45rem .3rem; }
  .cd-amount { font-size: .85rem; }
}

/* The day and the course, side by side. A course day carries more than one course often
   enough that picking the day first and the course second is fewer taps than finding one
   line in a list as long as the year. */
.cd-pick { display: flex; flex-direction: column; gap: .15rem; font-size: .8rem; color: var(--muted); }
.cd-pick input, .cd-pick select { font-size: 1rem; }
.link {
  background: none; border: 0; padding: 0;
  color: var(--brand); text-decoration: underline; cursor: pointer; font: inherit;
}
@media (max-width: 620px) { .cd-pick { width: 100%; } }

/* The photographed sheet, kept and shown. Collapsed by default because it is a tall
   page, and a tap away rather than a scroll away. */
.cd-photo { margin-top: .6rem; }
.cd-photo summary { cursor: pointer; font-size: .9rem; color: var(--muted); }
.cd-photo img {
  display: block;
  max-width: 100%;
  margin: .5rem 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

/* The photographed page, line by line, so a misreading is fixed where it happened. */
.cd-lines { display: flex; flex-direction: column; gap: .3rem; margin: .5rem 0; }
.cd-line { display: flex; gap: .4rem; align-items: center; }
.cd-line .cd-n { width: 1.6rem; text-align: right; flex: none; }
.cd-line .cd-name { flex: 3 1 10rem; min-width: 0; }
.cd-line .cd-ph { flex: 2 1 7rem; min-width: 0; }
.cd-line .cd-res { flex: none; width: 3rem; text-align: center; }
.cd-who { max-width: 14rem; }

@media (max-width: 620px) {
  /* On a phone the three boxes stack rather than squeeze: a name box two characters
     wide is worse than a taller row. */
  .cd-line { flex-wrap: wrap; }
  .cd-line .cd-name { flex: 1 1 100%; }
  .cd-who { max-width: 100%; width: 100%; }
}

/* The views: the same list in the shapes it gets asked for. Counts on the chips, so
   "paid but did not come" answers itself without being opened. */
.cd-views { gap: .35rem; margin: .6rem 0 .2rem; align-items: center; }
/* Named cd-pill rather than chip. "chip" is already used in the team chat for a staged
   file and for a file link in a message, and a bare .chip rule appended here would have
   reached both - a border, a pill radius and a background on something that never had
   them. A class name nobody else uses costs nothing; a specificity fight costs an
   afternoon and comes back. */
.cd-pill {
  padding: .3rem .65rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--card);
  color: var(--ink);
  font-size: .85rem;
  cursor: pointer;
  white-space: nowrap;
}
.cd-pill b { color: var(--muted); margin-left: .15rem; }
.cd-pill.on { background: var(--ink); border-color: var(--ink); color: var(--card); }
.cd-pill.on b { color: var(--card); opacity: .7; }
/* Empty but still there: "nobody" is an answer, and a button that vanishes is not. */
.cd-pill.empty { opacity: .5; }

.cd-more { width: 2.4rem; }
.cd-open {
  width: 2rem; height: 2rem;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--card); color: var(--muted); cursor: pointer;
}
.cd-row.open .cd-open { background: var(--sunk); color: var(--ink); }

/* Everything changeable about one person, under their own row. */
.cd-panel > td { background: var(--sunk); border-bottom: 1px solid var(--line); }
.cd-panel .row { margin: .25rem 0; }
.cd-note-said { font-style: italic; }
.cd-move { max-width: 16rem; }

@media (max-width: 620px) { .cd-move { max-width: 100%; width: 100%; } }

/* Which columns to show. A summary rather than a row of tick boxes always on screen:
   it is set once and then left alone for weeks. */
.cd-columns { margin: .2rem 0 .4rem; }
.cd-columns summary { cursor: pointer; font-size: .85rem; color: var(--muted); }
.cd-columns .row { gap: .5rem 1rem; margin: .4rem 0; }
.cd-columns .check { font-size: .85rem; white-space: nowrap; }

/* The line editor's boxes, at a specificity that beats the global input rule.
   `input:not([type=checkbox]):not([type=radio]){width:100%}` scores (0,2,1); a class
   pair like `.cd-line .cd-name` only scores (0,2,0), so the global one wins and every
   box collapses to whatever is left after the widest. Naming the element takes this to
   (0,3,1), which is the same trap the limits section fell into. */
.cd-lines .cd-line input.cd-name { flex: 4 1 8rem; width: auto; min-width: 0; }
.cd-lines .cd-line input.cd-ph { flex: 2 1 6rem; width: auto; min-width: 0; }
.cd-lines .cd-line input.cd-res { flex: 0 0 3.2rem; width: 3.2rem; text-align: center; }

/* The line number on the attendance sheet: narrow, and read as a number. */
.cd-sl { width: 2.5rem; text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; }
.cd-panel input.cd-sl-in { width: 4.5rem; }

@media (max-width: 620px) {
  .cd-lines .cd-line input.cd-name { flex: 1 1 100%; }
}

/* A heading that sorts. Looks like a heading, behaves like a button - so the whole
   width is the target rather than the word, which matters on a phone. */
.cd-table th { padding: 0; }
.cd-sort {
  display: block;
  width: 100%;
  padding: .4rem .5rem;
  border: 0;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: .75rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
}
.cd-sort:hover { color: var(--ink); }
.cd-sort.on { color: var(--ink); font-weight: 600; }
.cd-table th:last-child .cd-sort, .cd-table th:first-child { cursor: default; }

/* The second toolbar: what the list is filtered to, and how to take it away. */
.cd-bar { gap: .4rem; align-items: flex-end; margin: .1rem 0 .3rem; }
.cd-bar .foot { margin-right: .1rem; }
.cd-bar select { min-width: 12rem; }

@media (max-width: 620px) {
  /* On a phone the company picker takes the line and the three buttons share the next
     one, rather than four things squeezing onto one row. */
  .cd-bar .cd-pick { width: 100%; }
  .cd-bar select { min-width: 0; width: 100%; }
  .cd-bar .grow { display: none; }
  .cd-bar .foot { width: 100%; }
}

/* The three kinds of column, kept apart: the ones this screen knows about, whatever
   else the booking sheet holds, and the blank ones for writing on. */
.cd-colgroup { margin: .5rem 0 .1rem; }

/* Adding somebody who is in the room and on no booking. Under the table, where the
   button is, rather than in a dialog over the list they are being added to. */
.cd-addform { margin: .5rem 0 .2rem; gap: .4rem; align-items: center; }
.cd-addform input.cd-name { flex: 3 1 12rem; width: auto; min-width: 0; }
.cd-addform input.cd-ph { flex: 2 1 8rem; width: auto; min-width: 0; }
.cd-addform input.cd-sl-new { flex: 0 0 4.5rem; width: 4.5rem; text-align: center; }

@media (max-width: 620px) {
  .cd-addform input.cd-name, .cd-addform input.cd-ph { flex: 1 1 100%; }
}

/* Typed into the signed sheet and not compared yet. Amber rather than red: it is not
   wrong, it is just not counted for anything until Compare again is pressed. */
.cd-unsaved { color: var(--warn); }

/* Five boxes on a line now: the number, the name, the phone, the email and the P/R -
   which is what a signature sheet usually carries, minus the signature itself. */
.cd-lines .cd-line input.cd-sl-line { flex: 0 0 3.2rem; width: 3.2rem; text-align: center; }
.cd-lines .cd-line input.cd-em { flex: 3 1 9rem; width: auto; min-width: 0; }

@media (max-width: 620px) {
  /* On a phone the name and the email take a line each; the number, phone and result
     share one. Five boxes across a phone is five boxes nobody can type into. */
  .cd-lines .cd-line input.cd-em { flex: 1 1 100%; }
}

/* The chosen columns in their order, each able to move one place. Arrows rather than
   dragging: this gets used on a phone, in a room, one-handed. */
.cd-order { gap: .3rem; margin: .3rem 0 .5rem; }
.cd-ord {
  display: inline-flex;
  align-items: center;
  gap: .15rem;
  padding: .15rem .3rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--sunk);
  font-size: .8rem;
  white-space: nowrap;
}
.cd-mv {
  border: 0;
  background: none;
  color: var(--muted);
  cursor: pointer;
  padding: 0 .15rem;
  font-size: .75rem;
  line-height: 1;
}
.cd-mv:hover:not(:disabled) { color: var(--ink); }
.cd-mv:disabled { opacity: .25; cursor: default; }
