/* ============================================================
   PLUS WERK — marketing dashboard
   Adapted from the BOS light direction. Frosted panels floating
   on a soft grey ground, a black icon rail, heavy rounding, and
   colour only on a thing that needs you or a thing that is wrong.
   ============================================================ */

:root{
  --well:inset 0 2px 4px rgba(0,0,0,.11), inset 0 -1px 0 rgba(255,255,255,.55);
  --well-deep:inset 0 3px 8px rgba(0,0,0,.17), inset 0 -2px 2px rgba(255,255,255,.72), inset 0 0 0 1px rgba(0,0,0,.05);
  --ink:#1a1a1a;
  --dim:#6e6e6e;
  --dim2:#949494;
  --pos:#2e9e68;
  --neg:#d6503f;

  /* BOS names, for the door — globals.css :root */
  --card:rgba(255,255,255,.34);
  --lift-pane:0 8px 22px rgba(0,0,0,.09), inset 0 1px 0 rgba(255,255,255,.7);
  --float:0 26px 60px rgba(0,0,0,.17), 0 2px 5px rgba(0,0,0,.06), inset 0 1px 0 rgba(255,255,255,.7), inset 0 -1px 0 rgba(0,0,0,.06);
  --radius-card:32px;
  --radius-well:22px;
  --field:rgba(255,255,255,.3);
  --faint:#8b8b8b;
  --fainter:#a3a3a3;
  --radius-field:20px;
  --lift:0 2px 6px rgba(0,0,0,.1), inset 0 1px 0 rgba(255,255,255,.9);
  --calm:200ms;
  --enter:280ms;
  --ease:cubic-bezier(.22,.7,.25,1);
  /* the black pill's shadow, at every width */
  --float-dark:0 12px 28px rgba(0,0,0,.26), inset 0 1px 0 rgba(255,255,255,.1), inset 0 -1px 0 rgba(0,0,0,.5);
}
*{box-sizing:border-box}
html,body{height:100%}
body{margin:0;color:var(--ink);
  font-family:"Inter","Helvetica Neue",Arial,system-ui,sans-serif;
  font-feature-settings:"cv11" 1,"ss01" 1;letter-spacing:-.006em;
  -webkit-font-smoothing:antialiased;
  background:radial-gradient(130% 100% at 35% 0%, #bcbcbc 0%, #b0b0b0 55%, #a6a6a6 100%);
  background-attachment:fixed}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;border:0;background:none;cursor:pointer}
input,textarea{font:inherit;color:inherit}
.num{font-variant-numeric:tabular-nums}
.dim{color:var(--dim)}
.dim2{color:var(--dim2)}

/* ---- the shell ----
   BOS: src/components/Shell.tsx. Two panels and a gap. The window is the
   full height and never scrolls; the room inside the right panel does.

   NO PADDING ON THE RIGHT. The room's own scroll box carries that 32px as
   part of its 64, so the box reaches the window's edge and its scrollbar
   lands on the grey BEYOND the panel instead of inside it. */
.app{position:relative;display:flex;width:100%;height:100svh;gap:16px;overflow:hidden;
  padding:32px 0 32px 32px}

/* ---- glass ---- */
.glass{background:rgba(255,255,255,.28);border-radius:40px;box-shadow:var(--float)}
.pane{background:var(--card);border-radius:var(--radius-card);box-shadow:var(--lift-pane)}
.raise{background:rgba(255,255,255,.5);border-radius:20px;box-shadow:var(--lift)}
.sunk{background:rgba(255,255,255,.24);border-radius:20px;box-shadow:var(--well)}
.hair{height:1px;background:rgba(0,0,0,.09);margin:18px 0}

/* ---- the rail ----
   One inset round both: the glass panel holds the black pill 16px from its
   own edge, so the pill carries no margin of its own. */
.side{flex:0 0 316px;width:316px;display:flex;flex-direction:column;gap:8px;padding:16px;
  background:rgba(255,255,255,.28);border-radius:40px;box-shadow:var(--float)}
.navblock{display:flex;min-height:0;flex:0 1 auto;flex-direction:column;overflow-y:auto;
  padding:16px;border-radius:32px;background:#1c1c1c}
.stack{display:flex;flex-shrink:0;flex-direction:column}
/* a grey thumb inside a black pill is the scrollbar this app said no to */
.navblock{scrollbar-width:none}
.navblock::-webkit-scrollbar{display:none;width:0;height:0}

.wsrow{padding:8px 8px 8px}
.wsmark{display:block;width:178px;height:auto}
.wsname{margin-top:16px;display:block;font-size:13px;line-height:1.3;color:#8e8e8e}
.wssub{margin-top:4px;display:block;font-size:11px;line-height:1.3;color:#7a7a7a}

.sect{margin:16px 0 8px;padding:0 8px;font-size:11px;font-weight:500;color:#7a7a7a}
.item{display:flex;align-items:center;gap:8px;height:38px;padding:0 8px;border-radius:16px;
  font-size:13px;color:#a8a8a8;width:100%;text-align:left;
  transition:color var(--calm) var(--ease),background-color var(--calm) var(--ease)}
.item .ic{display:grid;place-items:center;width:19px;height:19px;flex:0 0 19px}
.item .tx{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.item .ct{font-size:11px;color:#7a7a7a}
.item:hover{color:#fff}
.item.on{background:rgba(255,255,255,.11);color:#fff}
.item.on .ct{color:#a8a8a8}
.badge{display:inline-grid;place-items:center;min-width:20px;height:20px;padding:0 6px;border-radius:11px;
  background:rgba(214,80,63,.22);color:#ff8b7d;font-size:11px;font-weight:600}
.badge.grey{background:rgba(255,255,255,.10);color:#a8a8a8}
.navfoot{margin-top:16px;padding:16px 8px 0;font-size:11px;color:#6e6e6e;line-height:1.5}

/* ---- the track ----
   A stadium PRESSED INTO the rail: the deep well below it, a white lip along
   the bottom, and the letters cut in rather than printed on. It takes whatever
   height the rooms leave, and goes entirely when that is under 176px. */
.track{display:grid;place-items:center;overflow:hidden;border-radius:9999px;
  min-height:46px;flex:1 1 0%;opacity:1;
  background:linear-gradient(180deg,rgba(255,255,255,.14) 0%,rgba(255,255,255,.42) 100%);
  box-shadow:var(--well-deep),0 1px 0 rgba(255,255,255,.65);
  transition:flex-grow 200ms var(--ease),min-height 200ms var(--ease),opacity 200ms var(--ease)}
.track.off{min-height:0;flex:none;opacity:0}

/* THE SAME NAVIGATION AT THE PHONE'S TWO SHAPES (the phone rule, §2): a paged bar
   floating over the room's foot when held upright, a strip up the left edge when held
   sideways. Neither exists at the desk, and there is still no second menu anywhere. */
.pbar,.pstrip{display:none}
.track span{font-size:11px;text-transform:uppercase;letter-spacing:.32em;color:#8a8a8a;
  writing-mode:vertical-rl;transform:rotate(180deg);
  text-shadow:1px 0 0 rgba(255,255,255,.9)}

/* ---- the room ----
   <main> holds the frosted panel and nothing else; the scrolling box is the
   .room inside it. The panel is drawn as a layer behind, inset 32px from the
   right, which is the strip the scrollbar stands in. */
.main{position:relative;isolation:isolate;display:flex;flex-direction:column;
  flex:1;min-width:0;min-height:0}
.main::before{content:"";position:absolute;inset:0 32px 0 0;z-index:-1;display:block;
  pointer-events:none;border-radius:40px;background:rgba(255,255,255,.28);box-shadow:var(--float)}

.room{min-height:0;flex:1 1 0%;overflow-y:auto;padding:32px;padding-right:64px}

/* THE ARRIVAL (§9). A room you walk into rises eight pixels from nothing. Two lengths and
   one curve in this app, and no third. */
@keyframes rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
/* `.rise` and `.foot` are set by `app.js` at every width and READ only below 64rem — the
   rules are in the phone section, so the desk compiles exactly what it always did. */

/* ---- the room's head ----
   Not a card: it sits straight on the room's own glass, and the tiles
   underneath are the only surface up here. */
.headrow{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;
  gap:16px 32px;padding:0 8px}
.h1{margin:0;font-size:34px;font-weight:700;letter-spacing:-.03em;line-height:1.05}
.lead{margin-top:8px;font-size:13px;line-height:1.5;color:var(--dim);max-width:62ch}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:38px;padding:0 16px;
  border-radius:var(--radius-field);background:rgba(255,255,255,.55);font-size:13px;
  box-shadow:var(--lift);
  transition:transform var(--calm) var(--ease),box-shadow var(--calm) var(--ease),background-color var(--calm) var(--ease)}
.btn:hover{background:rgba(255,255,255,.75)}
.btn:active{transform:scale(.965);box-shadow:var(--well)}
.btn-dark{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:38px;padding:0 16px;
  border-radius:var(--radius-field);background:#1c1c1c;color:#fff;font-size:13px;
  box-shadow:0 6px 14px rgba(0,0,0,.22);
  transition:transform var(--calm) var(--ease),box-shadow var(--calm) var(--ease),background-color var(--calm) var(--ease)}
.btn-dark:hover{background:#000}
.btn-dark:active{transform:scale(.965);box-shadow:0 1px 3px rgba(0,0,0,.3)}
.btn:disabled,.btn-dark:disabled{pointer-events:none;opacity:.4}

.tag{display:inline-flex;align-items:center;height:24px;padding:0 10px;border-radius:var(--radius-tag,12px);
  background:var(--muted,rgba(255,255,255,.45));font-size:11px;color:#5a5a5a;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.6)}
.tag-neg{background:rgba(214,80,63,.12);color:var(--neg);box-shadow:none}
.tag-pos{background:rgba(46,158,104,.16);color:var(--pos);box-shadow:none}
.tag-dark{background:#1c1c1c;color:#fff;box-shadow:none}

/* ---- the facts, as a row of frosted tiles ---- */
.stats{margin-top:24px;display:grid;grid-template-columns:repeat(auto-fit,minmax(264px,1fr));gap:16px}
.stat{display:flex;min-width:0;flex-direction:column;gap:16px;padding:24px;
  background:var(--card);border-radius:var(--radius-card);box-shadow:var(--lift-pane)}
.statlab{font-size:11px;line-height:1.3;color:var(--dim)}
.statbig{font-size:28px;font-weight:700;letter-spacing:-.04em;line-height:1;
  font-variant-numeric:tabular-nums;color:var(--faint)}
.statbig.alert{color:var(--neg)}

/* ---- board ---- */
.board{display:flex;gap:14px;margin-top:22px;overflow-x:auto;padding-bottom:10px;align-items:flex-start}
.col{flex:0 0 288px;width:288px;border-radius:32px;background:rgba(255,255,255,.22);padding:14px 12px 16px;
  box-shadow:var(--well)}
.colhead{display:flex;align-items:center;gap:9px;padding:2px 8px 12px}
.coltitle{font-size:13px;font-weight:600;letter-spacing:-.01em}
.coldot{width:8px;height:8px;border-radius:9999px;background:#9a9a9a;flex:0 0 8px}
.coldot.needs{background:var(--neg)}
.coldot.approved,.coldot.done{background:var(--pos)}
.colcount{margin-left:auto;font-size:12px;color:var(--dim2)}

.card{display:block;width:100%;text-align:left;padding:14px 16px 15px;border-radius:22px;margin-bottom:9px;
  background:rgba(255,255,255,.62);box-shadow:0 2px 6px rgba(0,0,0,.09), inset 0 1px 0 rgba(255,255,255,.9)}
.card:hover{background:rgba(255,255,255,.82);transform:translateY(-1px)}
.card:last-child{margin-bottom:0}
.cardtop{display:flex;align-items:center;gap:8px;margin-bottom:7px}
.cardtype{font-size:11px;letter-spacing:.04em;text-transform:uppercase;color:var(--dim2);font-weight:500}
.carddate{margin-left:auto;font-size:11.5px;color:var(--dim2)}
.cardtitle{font-size:14.5px;font-weight:600;letter-spacing:-.012em;line-height:1.3}
.cardbrief{margin-top:5px;font-size:12.5px;color:var(--dim);line-height:1.4}
.cardfoot{margin-top:10px;display:flex;gap:6px;flex-wrap:wrap}
.empty{padding:16px 10px;font-size:12.5px;color:var(--dim2);text-align:center}

/* ---- needs-you list ---- */
.needs{margin-top:20px;display:flex;flex-direction:column;gap:11px}
/* ---- a room read as pages ----
   The Plans room shows the document, not a card you click. Owner, 2026-09-22:
   "the plans shouldnt show on a card, i want it to be a whole page." The panel
   is the card's surface at document width, and the body inside is `.md`, so it
   inherits every heading, table and section-tag rule the drawer already has. */
.pages{display:flex;flex-direction:column;gap:20px;max-width:920px}
.page{padding:28px 32px 30px;border-radius:32px;background:rgba(255,255,255,.5);
  box-shadow:var(--lift)}
.pagehead{display:flex;align-items:flex-start;justify-content:space-between;gap:16px 24px;
  flex-wrap:wrap}
.pagehead-l{min-width:0}
.pagehead-r{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.pagetitle{margin:4px 0 0;font-size:22px;font-weight:650;letter-spacing:-.025em;
  line-height:1.2}
.pagepath{margin-top:5px;font-size:12px;color:var(--dim2);
  font-family:ui-monospace,Menlo,Consolas,monospace}
.pageview{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  margin:16px 0 4px;padding-bottom:16px;border-bottom:1px solid rgba(0,0,0,.09)}
.pagebody{padding-top:4px}
.pagebody>:last-child{margin-bottom:0}
@media (max-width:64rem){
  .pages{max-width:none}
  .page{padding:20px 18px 22px;border-radius:26px}
  .pagetitle{font-size:19px}
}

.need{padding:20px 22px;border-radius:28px;background:rgba(255,255,255,.5);
  box-shadow:0 2px 6px rgba(0,0,0,.10), inset 0 1px 0 rgba(255,255,255,.9)}
.needhead{display:flex;align-items:flex-start;gap:12px}
.needtitle{font-size:16px;font-weight:600;letter-spacing:-.015em;line-height:1.3;flex:1;min-width:0}
.needwhy{margin-top:6px;font-size:13.5px;color:var(--dim);line-height:1.5}

/* A question card holds the thing he is judging — usually two or three options
   in a table. It is rendered as markdown, so `.md` applies; these lines pull it
   back to card size, because a card is not a document. The last block loses its
   bottom margin so the card does not end in a gap. */
.needwhy.md{font-size:13.5px;line-height:1.55;color:var(--dim)}
.needwhy.md>:last-child{margin-bottom:0}
.needwhy.md p{margin:0 0 10px}
.needwhy.md ul,.needwhy.md ol{margin:0 0 10px;padding-left:20px}
.needwhy.md strong{color:#2a2a2a;font-weight:620}
.needwhy.md table{font-size:12.5px;margin:2px 0 12px}
.needwhy.md th{padding:7px 11px;font-size:12px;letter-spacing:.01em}
.needwhy.md td{padding:7px 11px}
.needwhy.md .tablebox{margin:2px 0 12px}
.needwhy.md code{font-size:11.5px}
.needact{margin-top:14px;display:flex;gap:9px;flex-wrap:wrap;align-items:center}
.done-state{margin-top:12px;padding:12px 16px;border-radius:18px;background:rgba(46,158,104,.10);
  font-size:13px;color:#2a7d55;line-height:1.5}

/* ---- inputs ---- */
.field{width:100%;min-height:74px;padding:13px 16px;border-radius:20px;resize:vertical;
  background:rgba(255,255,255,.4);box-shadow:var(--well);border:0;outline:0;
  font-size:14px;line-height:1.5;color:var(--ink)}
.field:focus{background:rgba(255,255,255,.62)}
.field::placeholder{color:var(--dim2)}

/* ---- detail drawer ---- */
.scrim{position:fixed;inset:0;background:rgba(40,40,40,.4);backdrop-filter:blur(3px);
  display:none;z-index:40}
.scrim.on{display:block}
.drawer{position:fixed;top:0;right:0;bottom:0;width:min(760px,100vw);z-index:50;
  background:#eeeeec;box-shadow:-30px 0 70px rgba(0,0,0,.3);
  transform:translateX(100%);transition:transform .22s cubic-bezier(.3,.8,.3,1);
  display:flex;flex-direction:column}
.drawer.on{transform:none}
.dhead{padding:26px 34px 18px;flex:0 0 auto}
.dtop{display:flex;align-items:center;gap:10px;margin-bottom:12px}
.dclose{margin-left:auto;width:34px;height:34px;border-radius:17px;display:grid;place-items:center;
  background:rgba(0,0,0,.06);color:#5a5a5a}
.dclose:hover{background:rgba(0,0,0,.11)}
.dtitle{font-size:26px;font-weight:700;letter-spacing:-.025em;line-height:1.15;margin:0}
.dpath{margin-top:8px;font-size:12px;color:var(--dim2);font-family:ui-monospace,Menlo,Consolas,monospace}
.dbody{flex:1;overflow-y:auto;padding:4px 34px 30px}
.dact{flex:0 0 auto;padding:18px 34px 22px;background:rgba(255,255,255,.6);
  box-shadow:0 -1px 0 rgba(0,0,0,.08)}
.dactrow{display:flex;gap:9px;margin-top:11px;flex-wrap:wrap}
/* the save row keeps its note beside the press — below 64rem `.dactrow` stacks it */
.dactrow-save{align-items:center}

/* ---- Summary / Full toggle ----
   Sections are tagged in the markdown itself — "## Method [reference]". The
   dashboard never decides what matters; it only hides what the agent marked as
   working. A file with no tags has no toggle, which is how you can see at a
   glance which files have been converted. */
.dview{display:flex;align-items:center;gap:6px;margin-top:13px}
.vbtn{font-size:12.5px;font-weight:550;padding:5px 13px;border-radius:14px;
  background:rgba(0,0,0,.06);color:#5a5a5a;letter-spacing:-.01em}
.vbtn:hover{background:rgba(0,0,0,.1)}
.vbtn.on{background:#2a2a2a;color:#f4f4f2}
.vbtn:disabled{opacity:.35;cursor:default;background:rgba(0,0,0,.05)}
.vbtn:disabled:hover{background:rgba(0,0,0,.05)}
.cardver{font-size:11px;font-weight:600;color:#6a6a6a;background:rgba(0,0,0,.06);
  padding:2px 7px;border-radius:8px;margin-left:7px}

.vsel{font-size:12.5px;font-weight:550;padding:5px 9px;border-radius:14px;
  background:rgba(0,0,0,.06);color:#3a3a3a;border:0;margin-left:3px;
  font-family:inherit;letter-spacing:-.01em}
.vsel:hover{background:rgba(0,0,0,.1)}
.vnote{font-size:12px;color:var(--dim2);margin-left:4px}
/* reading an older version: the page is history, not something to act on */
.vnote.old{color:#9d2f26;font-weight:550}

/* the tag pill that replaces the "[reference]" text in a heading */
.stag{font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;
  padding:3px 8px;border-radius:9px;margin-left:9px;vertical-align:middle;
  background:rgba(0,0,0,.07);color:#6a6a6a}
.stag-decide{background:rgba(190,60,50,.13);color:#9d2f26}
.stag-read{background:rgba(0,0,0,.07);color:#6a6a6a}
.stag-reference{background:rgba(0,0,0,.05);color:#9a9a9a}

.md .sec{display:block}
/* Summary shows only what is untagged (the summary block, the verdict box) and
   what needs a decision. [read] and [reference] are the full process. */
.md.view-summary .sec-read,
.md.view-summary .sec-reference{display:none}

/* markdown inside the drawer */
.md{font-size:14.5px;line-height:1.62;color:#2a2a2a}
.md h1{font-size:24px;font-weight:700;letter-spacing:-.025em;margin:26px 0 10px}
.md h1:first-child{margin-top:6px}
.md h2{font-size:17px;font-weight:650;letter-spacing:-.018em;margin:26px 0 8px}
.md h3{font-size:14.5px;font-weight:650;margin:20px 0 6px}
.md p{margin:0 0 12px}
.md ul,.md ol{margin:0 0 14px;padding-left:22px}
.md li{margin-bottom:5px}
.md strong{font-weight:620}
.md code{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12.5px;
  background:rgba(0,0,0,.06);padding:2px 6px;border-radius:7px}
.md pre{background:rgba(0,0,0,.05);padding:14px 16px;border-radius:16px;overflow-x:auto;margin:0 0 14px}
/* A TABLE SLIDES RATHER THAN SQUEEZING — the same answer `.md pre` has always had, and
   `app.js` wraps each table in one as it renders. The box is here rather than in the
   phone query because a table wider than the drawer is wider than the drawer at any
   width; what the phone adds is §3's fade in place of the thumb. */
.tablebox{overflow-x:auto;margin:0 0 16px}
.tablebox>table{margin:0;min-width:100%;width:max-content}
.md pre code{background:none;padding:0;font-size:12.5px;line-height:1.6}
.md table{width:100%;border-collapse:collapse;margin:0 0 16px;font-size:13.5px}
.md th{text-align:left;font-weight:600;padding:8px 12px;border-bottom:1px solid rgba(0,0,0,.14);color:#4a4a4a}
.md td{padding:8px 12px;border-bottom:1px solid rgba(0,0,0,.07);vertical-align:top}
.md blockquote{margin:0 0 14px;padding:10px 18px;border-left:2px solid rgba(0,0,0,.18);color:#4a4a4a}
.md hr{border:0;height:1px;background:rgba(0,0,0,.1);margin:22px 0}
.md a{text-decoration:underline;text-underline-offset:2px}

/* ---- intake form ---- */
.form{padding-top:6px}
.qblock{margin-bottom:22px}
.qhead{font-size:16px;font-weight:650;letter-spacing:-.015em;line-height:1.3;margin-bottom:6px}
.qhint{font-size:13.5px;color:var(--dim);line-height:1.5;margin-bottom:10px}
.qhint p{margin:0 0 6px}
.qhint ul,.qhint ol{margin:0 0 6px;padding-left:20px}
.qhint strong{font-weight:600;color:#3a3a3a}
.qblock .field{min-height:86px;background:rgba(255,255,255,.55)}
.qblock .field:focus{background:#fff}

/* ---- toast ---- */
.toast{position:fixed;left:50%;bottom:30px;transform:translate(-50%,20px);z-index:60;
  display:flex;align-items:center;gap:10px;height:44px;padding:0 20px;border-radius:22px;
  background:#1c1c1c;color:#fff;font-size:13.5px;box-shadow:0 14px 34px rgba(0,0,0,.32);
  opacity:0;pointer-events:none;transition:opacity .18s,transform .18s}
.toast.on{opacity:1;transform:translate(-50%,0)}
.toast.bad{background:var(--neg)}

/* an unsaved form should look unsaved */
.btn-dark.urgent{background:var(--neg);box-shadow:0 6px 14px rgba(214,80,63,.34)}
.btn-dark.urgent:hover{background:#c2452f}

/* ---- unsaved-changes dialog ---- */
.confirm-scrim{position:fixed;inset:0;background:rgba(30,30,30,.46);backdrop-filter:blur(4px);
  display:none;z-index:80}
.confirm-scrim.on{display:block}
.confirm{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);z-index:90;display:none;
  width:min(420px,calc(100vw - 40px));padding:28px 30px 24px;border-radius:32px;background:#f2f1ef;
  box-shadow:0 30px 70px rgba(0,0,0,.36)}
.confirm.on{display:block}
.confirm-title{font-size:20px;font-weight:700;letter-spacing:-.022em;line-height:1.2}
.confirm-body{margin-top:8px;font-size:14px;color:var(--dim);line-height:1.55}
.confirm-acts{margin-top:22px;display:flex;gap:9px;flex-wrap:wrap;align-items:center}
.confirm-discard{margin-left:auto;color:var(--neg);background:rgba(214,80,63,.10);box-shadow:none}
.confirm-discard:hover{background:rgba(214,80,63,.18)}

/* ---- stale build notice ---- */
.stale{position:fixed;left:50%;bottom:30px;transform:translateX(-50%);z-index:70;display:none;
  align-items:center;gap:14px;height:52px;padding:0 14px 0 22px;border-radius:26px;
  background:#1c1c1c;color:#fff;font-size:13.5px;box-shadow:0 14px 34px rgba(0,0,0,.34)}
.stale.on{display:flex}

/* ---- the door ----
   Lifted from BOS: src/components/Login.tsx on globals.css. One glass panel on
   the grey ground, the real mark, two boxes pressed in, one dark press.
   A box is pressed INTO the panel; a button is lifted OFF it. That one
   distinction is the whole look, so nothing here invents a third surface. */

.door{display:grid;min-height:100svh;place-items:center;padding:16px}
.door-panel{width:100%;max-width:400px;padding:32px}
.door-logo{display:block;width:150px;height:auto}
.door-sub{display:block;margin-top:16px;font-size:13px;color:var(--dim)}
.door-stack{margin-top:32px;display:flex;flex-direction:column;gap:16px}

.door-lab{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:11px;line-height:1.3;color:var(--faint)}
.door-box{margin-top:8px}

.door-field{display:flex;align-items:center;width:100%;height:42px;padding:0 16px;
  border:0;outline:0;border-radius:var(--radius-field);
  background:var(--field);box-shadow:var(--well);
  font-size:13px;color:var(--ink);transition:background-color var(--calm) var(--ease)}
.door-field::placeholder{color:var(--fainter)}
.door-field:focus{background:rgba(255,255,255,.45)}

.door-press{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;
  height:38px;padding:0 16px;border:0;border-radius:var(--radius-field);
  background:var(--primary,#1c1c1c);color:#fff;font-size:13px;cursor:pointer;
  box-shadow:0 6px 14px rgba(0,0,0,.22);
  transition:transform var(--calm) var(--ease),box-shadow var(--calm) var(--ease),
             background-color var(--calm) var(--ease),color var(--calm) var(--ease)}
.door-press:hover{background:#000}
.door-press:active{transform:scale(.965);box-shadow:0 1px 3px rgba(0,0,0,.3)}
.door-press:disabled{pointer-events:none;opacity:.4}

/* The refusal is one sentence, the one colour, and it is not a panel. */
.door-refusal{display:none;margin:-8px 0 0;font-size:11px;line-height:1.5;color:var(--neg)}
.door-refusal.on{display:block}

/* The phone: every target 44 tall, the panel to the window's edge. */
@media (width < 64rem),(height < 31.25rem){
  .door-field,.door-press{height:44px}
}

/* ---- the scrollbar ----
   A thin grey thumb on no track at all, hugging the right of its own gutter
   so it stands against the edge it belongs to. */
*{scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.22) transparent}
*::-webkit-scrollbar{width:10px;height:10px}
*::-webkit-scrollbar-track{background:transparent}
*::-webkit-scrollbar-thumb{background-color:rgba(0,0,0,.22);
  border-width:3px 0 3px 6px;border-style:solid;border-color:transparent;
  background-clip:content-box;border-radius:5px}


/* ============================================================
   THE PHONE — THREE SHAPES, NOT BREAKPOINTS

   The whole rule is BOS `docs/Phone.md`, and this is that rule at this app's
   width. Read it before touching anything below 64rem.

     phone     width < 64rem                                 OR height < 31.25rem
     upright   width < 64rem AND height >= 31.25rem AND portrait
     sideways  width < 64rem AND landscape                   OR height < 31.25rem

   THE DESK RENDERS FROM THE SAME DECLARATIONS IT ALWAYS DID. Every rule here
   is behind one of those three queries and nothing above them changed. Check
   that by reading the file above this line, not by trusting yourself.

   ORIENTATION DECIDES WHICH SHAPE IT IS, NEVER HEIGHT. A bar along the foot
   costs height and a strip up the side costs width, so the one to spend is
   whichever the window has more of. Asking "is this under 500px tall" is
   asking about a handset lying down, and it calls a 1000x640 window portrait.

   `upright` AND `sideways` ARE EXACT COMPLEMENTS over everything `phone`
   covers. Narrow one without widening the other and some window falls between
   the two and gets no navigation at all.
   ============================================================ */

/* ---- the shell, below the desk ----
   The rail goes and the bar takes its place. The panel reaches the window's
   edge and the scrollbar is the browser's own overlay, so there is no strip
   beyond the panel for it to stand in: 16px all round, and the room is still
   the only thing that scrolls. */
@media (width < 64rem),(height < 31.25rem){
  .slide{scrollbar-width:none}
  .slide::-webkit-scrollbar{display:none;width:0;height:0}

  .side{display:none}
  .app{gap:0;padding:0}

  /* THE ARRIVAL (§9). A room you walk into rises eight pixels from nothing. */
  .room.rise{animation:rise var(--enter) var(--ease) both}
  /* THE FOOT FADE (§3), on while there is more below. The mask is on the scroll box itself,
     so it stays at the box's edge while the contents move under it — and it is never put on
     `.main`, which carries the frosted panel: a panel whose bottom edge dissolves is not a
     panel. The bar is outside the room, and a mask paints its whole subtree, which is the
     other half of why it is not in there. */
  .room.foot{-webkit-mask-image:linear-gradient(#000 calc(100% - 40px),transparent);
    mask-image:linear-gradient(#000 calc(100% - 40px),transparent)}
  .main::before{display:none}
  .room{padding:16px}

  .h1{font-size:28px}
  .lead{margin-top:6px}
  /* A HEAD'S RIGHT-HAND SIDE DROPS BELOW IT (Phone.md §5). Beside a 28px name
     on 358px of screen there is no "beside": the two collide and what gets
     squeezed is the sentence. */
  .headrow{gap:12px;padding:0}

  /* 44 IS THE FLOOR FOR ANYTHING A FINGER HAS TO FIND (§2) — buttons, fields,
     tab pills, the drawer's close. Heights are sizes, not spacing, so they
     stay off the type ladder. */
  .btn,.btn-dark{height:44px}
  .dclose{width:44px;height:44px;border-radius:22px}
  .dview{flex-wrap:wrap;gap:8px;margin-top:14px}
  .vbtn{min-height:44px;padding:0 16px;border-radius:18px;display:inline-flex;align-items:center}
  .vsel{min-height:44px;padding:0 12px;border-radius:18px}

  /* WHAT A HEAD DOES IS A COLUMN BELOW THE DESK (§5): full width, 44 each, in
     the order it was already written. A group of more than three is not a
     column but a group, and a group wraps whole — two up, never auto-fill. */
  .dactrow,.needact{flex-direction:column;align-items:stretch}
  .dactrow>.btn,.dactrow>.btn-dark,
  .needact>.btn,.needact>.btn-dark{width:100%}
  .dactrow-many{flex-direction:row;flex-wrap:wrap}
  .dactrow-many>.btn{flex:1 1 calc(50% - 5px);width:auto}
  .confirm-acts{flex-direction:column;align-items:stretch}
  .confirm-acts>.btn,.confirm-acts>.btn-dark{width:100%}
  .confirm-discard{margin-left:0}

  /* A ROOM'S FACTS ARE A RAIL OF CARDS, ONE FACT TO A CARD (§5). Above 64rem
     the same auto-fit grid it has always been; below it a card as wide as the
     window less 72 — 288 at 360 — snapping, with the next card showing past
     the edge.

     IT IS SHORTER AND LESS SQUEEZED, WHICH IS NOT A CONTRADICTION: the height
     was being spent on a second COLUMN. And because 288px is room for the
     figure at its own rank, the compromise the half-width tile forced goes —
     `.statbig` was dropped to 16px here, a rank BELOW a dialog's title, which
     is not where a room's headline figure belongs.

     THE PEEK IS THE WHOLE INSTRUCTION, SO THIS ONE HAS NO FADE. Everywhere
     else a dissolving edge is what says "there is more this way" (§3), and it
     is right there because what is sliding is a row of words. Half a CARD
     showing past the edge says the same thing without dimming what it is
     saying it about. */
  .stats{display:flex;flex-wrap:nowrap;margin-top:16px;gap:16px;
    overflow-x:auto;overscroll-behavior-x:contain;scroll-snap-type:x mandatory}
  .stats>.stat{flex:0 0 calc(100vw - 72px);scroll-snap-align:start;padding:20px}

  /* The board keeps its columns and slides, and §3 says what that looks like:
     the edge dissolves, never a scrollbar. `slide` hides the bar; `app.js`
     measures which end has more past it and masks that end. */
  .board{gap:10px;padding-bottom:0}
  .col{flex:0 0 250px;width:250px}

  .need{padding:18px 18px 20px}
  .needtitle{font-size:15.5px}

  /* A DIALOG IS A SHEET AT THE FOOT (§5): 16px in from every edge, as tall as
     its question up to the screen less those edges, scrolling inside itself.
     The dim fades in and the sheet rises.

     `overflow:hidden` because the action row paints its own background and a
     32px corner it does not know about is a square one. */
  .scrim{display:block;opacity:0;visibility:hidden;
    transition:opacity var(--calm) var(--ease),visibility var(--calm)}
  .scrim.on{opacity:1;visibility:visible}
  .drawer{top:auto;left:16px;right:16px;bottom:calc(16px + env(safe-area-inset-bottom,0px));
    width:auto;overflow:hidden;border-radius:32px;box-shadow:var(--float);
    max-height:calc(100svh - 32px - env(safe-area-inset-top,0px) - env(safe-area-inset-bottom,0px));
    transform:translateY(calc(100% + 24px + env(safe-area-inset-bottom,0px)))}
  .drawer.on{transform:none}
  .dhead{padding:20px 20px 14px}
  .dbody{padding:4px 20px 20px}
  .dact{padding:14px 20px 18px}
  .dtitle{font-size:22px}
  .dpath{font-size:11px;word-break:break-all}

  .confirm{top:auto;left:16px;right:16px;bottom:calc(16px + env(safe-area-inset-bottom,0px));
    width:auto;transform:none;border-radius:32px;padding:24px 22px 22px}

  /* Neither of these may sit under the bar or in the home-indicator strip. */
  .toast,.stale{left:16px;right:16px;transform:none;justify-content:center}
  .toast{bottom:calc(110px + env(safe-area-inset-bottom,0px));transform:translateY(20px)}
  .toast.on{transform:none}
  .stale{bottom:calc(110px + env(safe-area-inset-bottom,0px));height:auto;
    flex-wrap:wrap;gap:10px;padding:14px 18px;border-radius:24px}

}

/* ---- held upright ----
   THE BAR TURNS PAGES; IT DOES NOT SLIDE (Phone.md §2). Six rooms never fit
   across 342px, and every answer that made them fit did it by moving
   something under the thumb. Four rooms to a page, each chip a quarter of the
   bar and carrying its name at all times, dots saying how many pages, a swipe
   to turn them. Nothing on the bar changes size, which is the whole of why it
   cannot rock.

   THE BAR FLOATS 16px OVER THE ROOM'S FOOT AND THE ROOM'S LAST CARD CLEARS
   IT: 78 of bar and 16 of float is 94, so 110 is what the room puts under
   itself. `absolute`, inside the shell, which is the containing block and has
   no transform on it. */
@media (width < 64rem) and (height >= 31.25rem) and (orientation: portrait){
  .room{padding-bottom:calc(110px + env(safe-area-inset-bottom,0px))}

  .pbar{display:block;position:absolute;z-index:20;left:16px;right:16px;
    bottom:calc(16px + env(safe-area-inset-bottom,0px));
    height:78px;padding:8px;border-radius:32px;background:#1c1c1c;
    box-shadow:var(--float-dark)}
  .pbtrack{overflow:hidden}
  .pbpages{display:flex;transition:transform var(--calm) var(--ease)}
  /* While a thumb is on it the track IS the thumb; easing that is fighting it. */
  .pbpages.held{transition:none}
  /* A grid, so a page holding fewer than four still gives each a quarter. */
  .pbpage{display:grid;flex:0 0 auto;grid-template-columns:repeat(4,1fr);gap:6px}
  .pbchip{display:flex;position:relative;flex-direction:column;align-items:center;justify-content:center;
    gap:4px;height:48px;min-width:0;border-radius:18px;color:#8e8e8e;
    transition:background-color var(--calm) var(--ease),color var(--calm) var(--ease),
               transform var(--calm) var(--ease)}
  .pbchip:active{transform:scale(.965)}
  .pbchip svg{width:18px;height:18px}
  /* The chosen room is the only white thing in the black bar; colour is all
     that changes, so nothing on the bar can rock. */
  .pbchip.on{background:#fff;color:#1a1a1a}
  .pbchip .tx{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
    font-size:9px;line-height:1;letter-spacing:0}
  .pbchip .badge{position:absolute;top:2px;right:6px;min-width:16px;height:16px;
    padding:0 4px;font-size:9.5px;border-radius:8px}

  /* The dots are an indicator first and a control second: the swipe is the
     gesture. The hit area reaches out over the bar's own padding, so a
     pointer with no swipe can still turn the page. */
  .pbdots{display:flex;align-items:center;justify-content:center;gap:2px;height:14px}
  .pbdot{position:relative;display:grid;place-items:center;width:32px;height:26px;margin:-6px 0}
  .pbdot::after{content:"";position:absolute;inset:-9px -4px}
  .pbdot i{display:block;height:6px;width:6px;border-radius:3px;background:rgba(255,255,255,.22);
    transition:width var(--calm) var(--ease),background-color var(--calm) var(--ease)}
  .pbdot.on i{width:16px;background:#fff}
}

/* ---- turned sideways ----
   THE BAR STANDS BACK UP (Phone.md §2): 64px wide, icons only, scrolling
   downwards, up the left edge. A landscape phone is about 688 x 360 and the
   room gets what is left of it, so the one thing not to spend is height.

   It is the same navigation at the same width — same black pill, same corner,
   same shadow, same icons, same rooms. There is still no second menu
   anywhere in this app. */
@media (width < 64rem) and (orientation: landscape),(height < 31.25rem){
  .app{gap:8px;padding:8px}

  .pstrip{display:flex;flex:0 0 64px;width:64px;flex-direction:column;align-items:center;
    padding:8px;border-radius:32px;background:#1c1c1c;box-shadow:var(--float-dark)}
  /* `flex:1` so the track takes the height the strip has left and `min-height:0` so it is
     allowed to be shorter than its chips — without both, a seventh room overflows the
     pill instead of scrolling inside it. */
  .pstriptrack{display:flex;flex:1;min-height:0;width:100%;flex-direction:column;
    align-items:center;gap:2px;overflow-y:auto;overflow-x:hidden}
  .pchip{display:grid;flex:0 0 auto;place-items:center;position:relative;
    width:44px;height:44px;border-radius:16px;color:#8e8e8e;
    transition:background-color var(--calm) var(--ease),color var(--calm) var(--ease)}
  .pchip.on{background:rgba(255,255,255,.11);color:#fff}
  .pchip svg{width:19px;height:19px}
  .pchip .badge{position:absolute;top:-1px;right:-1px;min-width:16px;height:16px;
    padding:0 4px;font-size:9.5px;border-radius:8px}

  /* THE HEAD IS SHORTER LYING DOWN AND NOTHING PINS (§2). The name takes the
     rank below, the head's buttons go back beside it, and the head leaves the
     screen the way everything else does. */
  .h1{font-size:20px}
  .room{padding:12px}

  /* A FACT TILE IS SHORTER THAN IT IS UPRIGHT, AND THERE ARE THREE OF THEM
     (§5). Lying down there is width to spare and no height at all, so the
     tiles stand side by side and the figure drops one rank. Written off the
     rail's own gap rather than as pixels, so it is the same three at 600 as
     at 800. */
  .stats>.stat{flex:0 0 calc((100% - 32px) / 3);padding:12px 16px;gap:8px}
  .statbig{font-size:20px;letter-spacing:-.02em}

  /* No bar at the foot lying down, so these come back down — but the strip is still up
     the left edge and neither may stand on it: 64 of pill, the shell's 8 and the gap's 8. */
  .toast,.stale{left:88px;bottom:calc(16px + env(safe-area-inset-bottom,0px))}
}

/* ---- the off switch ----
   Not optional: every screen still works without any motion. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.01ms !important;animation-delay:0ms !important;
    animation-iteration-count:1 !important;transition-duration:.01ms !important}
}

/* ---- a plan read as a task list ----
   The owner, 2026-09-24, twice. First: "i want it to looks like an app showing
   list of task, then i can see the details." Then, with his own Planning page
   as the picture: "you still only showing text mostly." So: number tiles on
   top, one table of the quarter with month rows that fold, a task opens in
   place, and the report sits closed at the bottom. Ink only — colour stays for
   a thing that waits on him (red) and a thing that is done (green). */
.tasks{padding-top:4px}
.tstats{margin-top:4px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px}
.tstats .stat{padding:18px 20px;gap:10px;background:rgba(255,255,255,.42);border-radius:24px}
.tbig{color:var(--ink);font-size:26px}
.tbig .of{font-size:15px;font-weight:500;color:var(--dim2);letter-spacing:-.01em}
.statsub{font-size:11px;line-height:1.35;color:var(--dim2)}

.qhead-row{display:flex;align-items:baseline;justify-content:space-between;gap:12px;
  margin:28px 4px 10px;font-size:13px;font-weight:500}
.qhead-row .dim2{font-size:11px;font-weight:400}
.qtable{padding:6px;border-radius:24px;background:rgba(255,255,255,.3);box-shadow:var(--well)}
.qrow{display:grid;grid-template-columns:minmax(0,1fr) 150px 70px 104px;align-items:center;gap:14px;
  padding:11px 14px;border-radius:16px}
.qcols{padding:6px 14px 8px;font-size:11px;color:var(--dim2)}
.qcols .qc-h,.qcols .qc-st{text-align:right}
.qgroup{margin-top:4px;background:rgba(255,255,255,.34);cursor:pointer}
.qgroup .qname{font-weight:620}
.qtask{cursor:pointer;border-bottom:1px solid rgba(0,0,0,.05);border-radius:0;padding-left:40px}
.qtask:hover{background:rgba(255,255,255,.28)}
.qtask.open{background:rgba(255,255,255,.62);border-radius:16px 16px 0 0;border-bottom-color:transparent}
.qc-name{display:flex;align-items:center;gap:12px;min-width:0}
.qname{display:flex;flex-direction:column;gap:3px;min-width:0;font-size:13.5px;line-height:1.3}
.qsub{font-size:11px;color:var(--dim2);font-weight:400}
.qtri{flex:0 0 12px;font-size:11px;color:var(--dim);transition:transform var(--calm) var(--ease)}
.qtri.shut{transform:rotate(-90deg)}
.qc-type .tag{height:22px;padding:0 9px;font-size:10.5px}
.qc-h{text-align:right;font-size:13px}
.qc-st{text-align:right;font-size:11.5px;color:var(--dim)}
.qpill{display:inline-flex;align-items:center;height:22px;padding:0 9px;border-radius:11px;
  font-size:10.5px;background:rgba(255,255,255,.5);color:#5a5a5a}
.qpill-wait{background:rgba(214,80,63,.12);color:var(--neg)}
.qpill-done{background:rgba(46,158,104,.16);color:var(--pos)}
.tdot{flex:0 0 9px;width:9px;height:9px;border-radius:50%;box-shadow:inset 0 0 0 1.5px var(--dim2)}
.tdot-done{background:var(--pos);box-shadow:none}
.tdot-wait{background:var(--neg);box-shadow:none}
.qmeter{height:6px;border-radius:3px;background:rgba(0,0,0,.08);overflow:hidden}
.qmeter i{display:block;height:100%;border-radius:3px;background:#1c1c1c}

.qdetail{margin:0 0 6px;padding:6px 18px 18px 40px;border-radius:0 0 16px 16px;background:rgba(255,255,255,.62)}
.qfacts{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px;margin-bottom:12px}
.qfact{padding:10px 12px;border-radius:14px;background:rgba(255,255,255,.55);box-shadow:var(--well)}
.qfv{margin-top:4px;font-size:13px;font-weight:560}
.qswaps{margin-bottom:12px}
.qswaps>div:last-child{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
.tbody{font-size:13.5px;line-height:1.55}
.tbody>:last-child{margin-bottom:0}
.qnote{margin:10px 4px 0;font-size:11.5px;line-height:1.5;color:var(--dim2);max-width:70ch}

.tchev{flex:0 0 8px;width:8px;height:8px;border-right:1.5px solid var(--dim2);border-bottom:1.5px solid var(--dim2);
  transform:rotate(-45deg);transition:transform var(--calm) var(--ease)}
.open>.reasonbtn .tchev{transform:rotate(45deg)}
.reason{margin-top:28px;border-top:1px solid rgba(0,0,0,.09);padding-top:8px}
.reasonbtn{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;
  padding:12px 4px;font-size:13px;color:var(--dim);text-align:left}
.reasonbtn:hover{color:var(--ink)}
.reasonbody{padding-top:4px}
@media (max-width:640px){
  .qrow{grid-template-columns:minmax(0,1fr) 56px;gap:10px;padding:11px 10px}
  .qc-type,.qc-st{display:none}
  .qtask{padding-left:26px}
  .qdetail{padding:6px 12px 16px 12px}
  .tstats{grid-template-columns:1fr 1fr}
}
/* The phone turns .stats into a sliding row. The plan's tiles stay a grid. */
@media (max-width:1023px){
  .stats.tstats{display:grid;overflow:visible;grid-template-columns:1fr 1fr;gap:10px}
  .stats.tstats>.stat{flex:none;width:auto;padding:14px 16px}
}
.pages:has(.tasks){max-width:1280px}

/* ---- task edits: done, move, request a change (2026-09-24) ---- */
.qgrip{flex:0 0 auto;margin-left:-22px;width:12px;font-size:10px;letter-spacing:-2px;color:var(--fainter);cursor:grab;opacity:0;transition:opacity var(--calm) var(--ease)}
.qtask:hover .qgrip{opacity:1}
.tick{flex:0 0 18px;width:18px;height:18px;border-radius:50%;box-shadow:inset 0 0 0 1.5px var(--dim2);position:relative;
  transition:background-color var(--calm) var(--ease),box-shadow var(--calm) var(--ease)}
.tick:hover{box-shadow:inset 0 0 0 1.5px var(--ink)}
.tick-done{background:var(--pos);box-shadow:none}
.tick-done::after{content:"";position:absolute;left:6px;top:3px;width:4px;height:8px;border:solid #fff;border-width:0 2px 2px 0;transform:rotate(45deg)}
.tick-wait{box-shadow:inset 0 0 0 1.5px var(--neg)}
.isdone .qname{color:var(--dim2)}
.isdone .qname>:first-child,.isdone .qname{text-decoration:line-through;text-decoration-color:rgba(0,0,0,.25)}
.isdone .qsub{text-decoration:none}
.qtask.dragging{opacity:.4}
.dropon{box-shadow:inset 0 0 0 2px #1c1c1c !important;background:rgba(255,255,255,.6) !important}
.qempty{margin:4px 0;padding:14px;border-radius:14px;font-size:12px;color:var(--dim2);text-align:center;
  box-shadow:inset 0 0 0 1.5px rgba(0,0,0,.08)}

.qacts{margin-top:16px}
.qmoves{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
.qmove{height:30px;padding:0 12px;border-radius:15px;font-size:12px;background:rgba(255,255,255,.7);box-shadow:var(--lift);
  transition:transform var(--calm) var(--ease)}
.qmove:hover{background:#fff}
.qmove:active{transform:scale(.96);box-shadow:var(--well)}
.qreqs{margin-top:14px;display:flex;flex-direction:column;gap:8px}
.qreq{padding:10px 12px;border-radius:14px;font-size:13px;line-height:1.45;background:rgba(255,255,255,.55);box-shadow:var(--well)}
.qask{margin-top:16px;padding-top:14px;border-top:1px solid rgba(0,0,0,.07)}
.qaskbox{display:block;width:100%;margin-top:6px;padding:10px 12px;border:0;border-radius:14px;resize:vertical;
  font-size:13px;line-height:1.45;background:rgba(255,255,255,.7);box-shadow:var(--well);outline:none}
.qaskbox:focus{background:#fff}
.qaskrow{display:flex;justify-content:flex-end;margin-top:8px}
@media (max-width:640px){ .qgrip{display:none} }

/* ---- a written page read as rows (2026-09-27) ----
   Same parts as the plan's task list: tiles, then tables whose rows open. */
.dv .qrow{grid-template-columns:minmax(0,1fr) auto}
.dv .qtask{padding-left:14px}
.dv .qtask.flat{cursor:default}
.dv .qtask.flat:hover{background:none}
.dv .qdetail{padding:4px 18px 16px 36px}
.dv .qname p{margin:0}
.dv .qname code{font-size:12px}
.dv .qhead-row{margin-top:24px}
.dvtiles{margin-top:6px}
.dvtiles .statbig{font-size:22px;overflow-wrap:anywhere}
.dvdot{flex:0 0 8px;width:8px;height:8px;border-radius:50%;background:var(--dim2)}
.dvdot.neg{background:var(--neg)}
.dvnum{flex:0 0 18px;font-size:12px;color:var(--dim2);text-align:right}
.dvsub{display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}
.dvlead{margin:2px 4px 14px;font-size:13.5px;line-height:1.5;color:var(--dim)}
.dvlead>:last-child,.dvnote>:last-child{margin-bottom:0}
.dvnote{margin:0 4px 10px;font-size:12.5px;line-height:1.5;color:var(--dim)}
@media (max-width:640px){
  .dv .qrow{grid-template-columns:minmax(0,1fr) auto}
  .dv .qc-st{display:block}
  .dv .qdetail{padding:4px 12px 14px 12px}
}

/* The brain's lists: a name and a pill, two columns at every width. */
.dvt .qrow{grid-template-columns:minmax(0,1fr) auto}
.dvt .qdetail{padding:4px 18px 16px 36px}
.dvt .qtask.flat{cursor:default}
.dvt .qtask.flat:hover{background:none}
.dvt + .qhead-row,.needs + .qhead-row{margin-top:22px}
@media (width < 64rem){.dvt .qdetail{padding:4px 12px 14px 12px}}
/* A file name inside a row reads as part of the sentence, not a code block. */
.dvt .qname code{font:inherit;font-weight:560;background:none;padding:0}
