/* ============================================================================
   Mandaue DTS — design system
   Ported from "DTS Modern B" (Claude Design handoff, 3 Sep 2026).

   Supersedes the navy-rail design of 10 Aug. The rail is now a light neutral
   surface; navy is reserved for actions, active state and the logo mark, which
   makes the primary button the loudest thing on the page instead of the
   furniture.
   ============================================================================ */

:root{
  /* ONE PALETTE, AND IT IS NOT OURS.
   *
   * CPDO asked for their own system back, and they meant the look as well as the
   * layout: "i prefer that since they are familiar with that design" (Mike,
   * 28 September 2026). So this is Dynamics 365's palette, typeface and geometry,
   * not Mandaue's.
   *
   * The navy-and-gold set that was here is kept below in --brand-*, because the
   * seal, the sign-in page and the public tracker are the city's own face and have
   * no PowerDTS equivalent to imitate. See DTS-PLAN-E-POWERDTS-SHELL.md, second
   * pass, decision 2 — which this reverses, with the reason recorded there. */

  /* Accent — Microsoft's, because it is the colour their staff read as "the system" */
  --navy:#0078D4; --navy-600:#106EBE; --navy-dark:#005A9E; --navy-tint:#DEECF9; --navy-wash:#F3F9FD;

  /* Gold is no longer an accent. It survives only where it carries MEANING —
   * a paused clock, a warning — and never as decoration. */
  --gold:#FFB900; --gold-soft:#FFD335; --gold-deep:#D29200;

  /* The city's own colours, for the city's own surfaces: the seal, the landing
   * page, the sign-in screen, the public tracker. Not used inside the staff app. */
  --brand-navy:#102C72; --brand-gold:#F0A500;

  /* Neutrals — Fluent's greys. Flatter and cooler than the warm paper set, which
   * is most of why their grids read as denser than ours did. */
  --page:#FFFFFF; --surface:#F3F2F1; --card:#FFFFFF;
  --line:#EDEBE9; --line-strong:#D2D0CE; --track:#EDEBE9;
  --ink:#201F1E; --ink-dim:#605E5C; --ink-mute:#A19F9D;

  /* Status — Fluent's semantic set */
  --success:#107C10; --success-bg:#DFF6DD;
  --pending:#797673; --pending-bg:#FFF4CE; --pending-line:#F2E1A5;
  --alert:#A4262C;   --alert-bg:#FDE7E9;

  /* SQUARE. Dynamics rounds almost nothing, and the corner is the single strongest
   * signal of which application you are looking at — stronger than the hue. */
  /* Surfaces and furniture that were hardcoded until dark mode needed them to move.
     A dark block is worthless while a white still sits underneath it. */
  --hover:#F1EFEA;          /* rail and row hover */
  --knob:#FFFFFF;           /* the moving part of a toggle */
  --track-off:#C9C7C2;      /* a toggle at rest */
  --glyph-bg:#EFEDE8; --glyph-dot:#DCD9D2;   /* the empty-grid mark */
  --pending-ink:#6b4e00;    /* text on the pending wash */
  --ring:#FFFFFF;           /* the halo that lifts a dot off the page */
  --scrim:rgba(11,31,82,.16);
  --shadow-pop:0 18px 48px rgba(16,44,114,.16);
  --shadow-pop-left:-18px 0 48px rgba(16,44,114,.16);

  --r-card:2px; --r-ctl:2px; --r-pill:2px; --r-round:50%;
  --sans:"Segoe UI","Segoe UI Web (West European)",-apple-system,BlinkMacSystemFont,
    "Helvetica Neue",sans-serif;

  /* Hairlines, not lift. Their surfaces sit flat on the page; a raised card is a
   * consumer-app gesture and reads as a different product immediately. */
  --shadow-hover:0 0 0 1px var(--line-strong);
  --shadow-lift:0 1.6px 3.6px rgba(0,0,0,.13), 0 .3px .9px rgba(0,0,0,.11);
}

*{box-sizing:border-box}
/* 14px and a tighter leading. Their grids fit noticeably more on a screen than
   ours did, and a clerk reading a 17-row list feels that before they notice a
   colour. */
body{margin:0;font-family:var(--sans);font-size:14px;line-height:1.38;color:var(--ink);background:var(--page)}
a{color:var(--navy)}
h1,h2,h3{letter-spacing:-.02em}
@keyframes dtsFade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@keyframes dtsGrow{from{transform:scaleY(0)}to{transform:scaleY(1)}}
@keyframes dtsDraw{from{stroke-dashoffset:1400}to{stroke-dashoffset:0}}

/* ---- Signed-out chrome --------------------------------------------------
   What remains of the old topbar: the landing page, the tracker and the sign-in
   screen, which have no rail because they have no entities to navigate.

   This block once read "CPDO's own system puts the whole document module behind
   one menu", and the burger was built on it. A photograph of PowerDTS on
   12 September 2026 showed a standing rail with Document Tracking expanded to
   seven entities. The claim was simply wrong, and it survived long enough to
   shape a navigation because nobody had checked it against the screen. The rail
   that replaced the burger is under "The shell", further down. */
.brand{display:flex;align-items:center;gap:10px;text-decoration:none;color:inherit;flex:none}
/* The seal tile is the CITY's mark, not the application's chrome, so it keeps
   Mandaue navy while everything around it wears Fluent's blue. */
.brand-mark{width:36px;height:36px;border-radius:2px;background:var(--brand-navy);display:grid;place-items:center;flex:none}
.brand-mark i{width:14px;height:14px;border-radius:2px;background:var(--brand-gold);transform:rotate(45deg);display:block}
.brand-name{font-weight:800;font-size:19px;letter-spacing:-.02em;white-space:nowrap}
.brand-name span{font-weight:500;color:var(--ink-dim)}
.iconbtn{width:30px;height:30px;border:1px solid var(--line);border-radius:2px;background:var(--card);
  display:grid;place-items:center;color:var(--ink-dim);font-size:12px;cursor:pointer;text-decoration:none;
  flex:none;font-family:inherit;padding:0}
.iconbtn:hover{border-color:var(--navy);color:var(--navy);background:var(--card)}

/* details/summary, not a scripted drawer: Escape closes it, the keyboard opens
   it, and it works with scripting off. The marker has to be removed on both
   engines — ::-webkit-details-marker for Safari, list-style for the rest. */
.menuwrap{position:relative}
.burger{display:grid;gap:4px;width:40px;height:40px;padding:10px 9px;cursor:pointer;
  border-radius:2px;list-style:none;align-content:center;flex:none}
.burger::-webkit-details-marker{display:none}
.burger::marker{content:''}
.burger:hover{background:var(--navy-tint)}
.burger span{display:block;height:2px;background:var(--ink);border-radius:2px}
.menuwrap[open] .burger{background:var(--navy-tint)}
.menu{position:absolute;top:52px;left:0;z-index:40;width:274px;padding:10px;
  background:var(--card);border:1px solid var(--line);border-radius:2px;
  box-shadow:var(--shadow-pop)}
.menu a{display:flex;align-items:center;gap:10px;height:40px;padding:0 10px;
  border-radius:2px;color:var(--ink);text-decoration:none;font-size:14.5px}
.menu a svg{flex:none;color:var(--ink-dim)}
.menu a:hover{background:var(--surface)}
.menu a.on{background:var(--navy-tint);color:var(--navy);font-weight:600}
.menu a.on svg{color:var(--navy)}
.menu .count{margin-left:auto;font-size:12px;font-weight:700;padding:1px 8px;border-radius:2px;
  background:var(--alert-tint);color:var(--alert)}
.menu .count.calm{background:var(--navy-tint);color:var(--navy)}
.menugroup{padding:12px 10px 6px;font-size:11.5px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-mute)}

.topbar{display:flex;align-items:center;gap:14px;height:72px;padding:0 24px;
  background:var(--card);border-bottom:1px solid var(--line);
  position:sticky;top:0;z-index:30}
.topbar .brand{padding:0}
.topnav{margin-left:10px;display:flex;gap:6px}
.topnav a{display:flex;align-items:center;gap:8px;height:40px;padding:0 14px;border-radius:2px;
  color:var(--ink);text-decoration:none;font-weight:500;font-size:14.5px}
.topnav a svg{color:var(--ink-dim)}
.topnav a:hover{background:var(--surface)}
.topnav a.on{background:var(--navy-tint);color:var(--navy);font-weight:600}
.topnav a.on svg{color:var(--navy)}
.topright{margin-left:auto;display:flex;align-items:center;gap:10px}
.topright .iconbtn{width:38px;height:38px;position:relative;border-color:transparent}
.topright .iconbtn .dot{position:absolute;top:7px;right:8px;width:8px;height:8px;
  border-radius:var(--r-round);background:var(--alert);border:2px solid var(--card)}
.topright .avatar{width:38px;height:38px;border-radius:var(--r-round);background:var(--navy);
  color:#fff;display:grid;place-items:center;font-weight:700;font-size:13px}
.topright .signin{color:var(--navy);text-decoration:none;font-weight:600}

.main{min-height:calc(100vh - 72px)}
.wrap{padding:28px 24px 64px;max-width:1320px;margin:0 auto;width:100%;animation:dtsFade .4s ease-out}

@media (max-width:720px){
  .topbar{height:60px;padding:0 14px;gap:8px}
  .brand-name{display:none}
  .topnav{margin-left:0}
  .topnav a span{display:none}
  .menu{width:calc(100vw - 28px)}
  .wrap{padding:20px 14px 48px}
}

/* ---- Page head ------------------------------------------------------------ */
/* The Modern-B page heading was removed on 14 Sep 2026. A list screen's title IS its
   saved view in PowerDTS — see .viewpick below and the viewpicker component. Leaving
   these rules in place was an invitation: they still worked, so a screen written from an
   older example looked right on its author's machine and wrong beside everything else.
   Three screens were missed in the Plan E rebuild and two more were written in the old
   vocabulary a week later, which is how long an unenforced convention survives. */
.stamp{display:flex;align-items:center;gap:8px;font-size:15px;color:var(--ink-dim)}
.tick{width:16px;height:16px;border-radius:var(--r-round);background:var(--success);color:#fff;font-size:10px;
  display:grid;place-items:center;font-weight:800}

/* ---- Buttons and controls -------------------------------------------------
   The base rule is `.btn`, NOT `.btn,button.btn`. The element-qualified form was
   0,1,1 and quietly beat every 0,1,0 variant that followed it, so `.btn-ghost`
   and `.btn-gold` on a <button> painted navy — a submit button styled gold in
   the markup came out as the page's primary action. Author styles already beat
   the user agent's; the element qualifier bought nothing and cost that. */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:44px;padding:0 18px;
  background:var(--navy);color:#fff;border:0;border-radius:var(--r-ctl);font:inherit;font-size:15px;font-weight:600;
  text-decoration:none;cursor:pointer;transition:background .15s,transform .12s}
.btn:hover{background:var(--navy-600);color:#fff}
.btn:active{transform:scale(.97)}
.btn-ghost{background:var(--card);color:var(--ink);border:1px solid var(--line);font-weight:500}
.btn-ghost:hover{background:var(--surface);color:var(--ink)}
.btn-gold{background:var(--gold);color:var(--navy-dark)}
.btn-gold:hover{background:var(--gold-soft);color:var(--navy-dark)}
.btn-block{width:100%;height:48px;font-size:15.5px}

/* Only an UNCLASSED button gets the default primary styling. The earlier form of this
   rule listed exceptions — :not(.btn):not(.iconbtn)… — which meant every new button class
   silently inherited a navy slab until someone remembered to add it to the list. Opting
   out by having a class of your own is the version that does not rot. */
button:not([class]){height:44px;padding:0 18px;background:var(--navy);color:#fff;border:0;
  border-radius:var(--r-ctl);font:inherit;font-size:15px;font-weight:600;cursor:pointer}
button:not([class]):hover{background:var(--navy-600)}
.linkbtn{background:none;border:0;color:var(--navy);font:inherit;padding:0;cursor:pointer;font-weight:600}
.linkbtn:hover{text-decoration:underline}

input[type=text],input[type=password],input[type=email],input[type=date],input[type=number],select,textarea{
  height:48px;padding:0 14px;border:1px solid var(--line);border-radius:var(--r-ctl);
  font-family:var(--sans);font-size:15.5px;color:var(--ink);background:var(--card);max-width:100%}
textarea{height:auto;padding:12px 14px;resize:vertical;line-height:1.5}
/* Focus is the accent, not amber. This ring appears the moment anybody clicks a
 * field, so an amber one is the most frequently seen piece of "not their system"
 * in the whole application. */
input:focus,select:focus,textarea:focus{outline:2px solid var(--navy);outline-offset:1px;border-color:var(--navy)}
label.field{display:block;font-size:14.5px;color:var(--ink-dim);font-weight:500}
label.field > input,label.field > select,label.field > textarea{display:block;width:100%;margin-top:6px}
label.field .hint{color:var(--ink-mute);font-weight:400}

/* ---- Cards ---------------------------------------------------------------- */
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-card);overflow:hidden;
  margin-bottom:24px}
.card-pad{padding:22px 24px}
.card-head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:20px 24px;
  border-bottom:1px solid var(--line)}
.card-head h2{font-size:22px;font-weight:600;margin:0;letter-spacing:-.01em}
.card-foot{display:flex;justify-content:space-between;gap:12px;padding:12px 22px;background:var(--surface);
  border-top:1px solid var(--line);font-size:14.5px}

.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:20px;margin-bottom:24px}
.kpi{background:var(--card);border:1px solid var(--line);border-radius:var(--r-card);overflow:hidden;
  transition:box-shadow .15s,transform .15s}
.kpi:hover{box-shadow:var(--shadow-lift);transform:translateY(-2px)}
.kpi .body{padding:22px 22px 18px}
.kpi .ico{width:48px;height:48px;border-radius:2px;border:1px solid var(--line);display:grid;place-items:center;
  color:var(--navy)}
.kpi .ico.warn{color:var(--pending)} .kpi .ico.bad{color:var(--alert)} .kpi .ico.good{color:var(--success)}
.kpi .l{font-size:15px;color:var(--ink-dim);margin-top:22px}
.kpi .n{font-size:26px;font-weight:600;letter-spacing:-.02em;margin-top:2px}
.kpi .delta{font-weight:600}
.kpi .note{color:var(--ink-dim)}

/* ---- Segmented control (tabs) --------------------------------------------- */
.segmented{display:flex;gap:4px;padding:4px;border:1px solid var(--line);border-radius:var(--r-ctl);
  background:var(--surface);flex-wrap:wrap}
.segmented a{padding:8px 14px;border-radius:2px;color:var(--ink-dim);font-size:14.5px;text-decoration:none;
  white-space:nowrap}
.segmented a:hover{color:var(--navy)}
.segmented a.on{background:var(--card);color:var(--ink);font-weight:600;box-shadow:0 1px 3px rgba(0,0,0,.06)}
.segmented a.danger{color:var(--alert);font-weight:600}
.toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:18px}
.toolbar .grow{flex:1 1 240px;min-width:200px}
.toolbar .right{margin-left:auto;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.toolbar select,.toolbar input{height:44px;font-size:15px}
.toolbar .inline{display:flex;align-items:center;gap:6px;font-size:14px;color:var(--ink-dim)}

/* ---- Row list (replaces the old data table) ------------------------------- */
.rowhead,.row{display:grid;gap:16px;align-items:center;padding:14px 20px}
.rowhead{background:var(--surface);border:1px solid var(--line);border-radius:2px;font-size:15px;
  color:var(--ink-dim);margin-bottom:12px}
.rows{display:flex;flex-direction:column;gap:12px}
.row{background:var(--card);border:1px solid var(--line);border-radius:2px;text-decoration:none;color:inherit;
  padding:16px 20px;transition:box-shadow .15s,border-color .15s}
a.row:hover{box-shadow:var(--shadow-hover);border-color:var(--line-strong)}
.row > *{min-width:0}
.row .lead{display:flex;align-items:center;gap:14px;min-width:0}
.row .lead > span{min-width:0}
/* display:block matters: text-overflow does nothing on an inline box, so without it a
   long title silently overflows into the next grid column instead of ellipsing. */
.row .title{display:block;font-size:16px;font-weight:600;letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.row .sub{display:block;font-size:14px;color:var(--ink-dim);margin-top:1px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.typemark{width:44px;height:44px;border-radius:var(--r-round);background:var(--navy-tint);color:var(--navy);
  display:grid;place-items:center;font-weight:700;font-size:13px;flex:none;
  letter-spacing:.03em;overflow:hidden}
.typemark.warn{background:var(--pending-bg);color:var(--pending)}
.typemark.bad{background:var(--alert-bg);color:var(--alert)}
.typemark.good{background:var(--success-bg);color:var(--success)}

/* ---- Status pills --------------------------------------------------------- */
/* A pill is a STATE, and a state is read down a column: twenty rows of "Open" in twenty
   outlined boxes is twenty badges saying the same thing, and the one row that is overdue
   has to shout over them. The dot and the colour carry it; the box is gone.

   The dot stays because colour alone is not a distinction — it is the shape that still
   separates open from overdue in print, or for a reader who cannot tell gold from red. */
.pill{display:inline-flex;align-items:center;gap:6px;font-size:13.5px;
  font-weight:600;white-space:nowrap;color:var(--ink-dim);background:none;border:0;padding:0}
.pill i{width:6px;height:6px;border-radius:var(--r-round);background:currentColor;display:block;flex:none}
.pill.ok{color:var(--success)}
.pill.warn{color:var(--pending)}
.pill.bad{color:var(--alert)}
.pill.info{color:var(--navy)}
/* A verdict on its own, rather than one cell of a column, may still be a badge. */
.pill.boxed{padding:7px 14px;border-radius:var(--r-pill);border:1px solid currentColor;
  background:var(--surface);font-size:14px}
.pill.boxed.ok{background:var(--success-bg)}
.pill.boxed.bad{background:var(--alert-bg)}
/* A bare .tag is a document CATEGORY, and a category is not a status: it says what the
   letter IS, on every row of every list, so a lavender slab behind it turns a column of
   plain facts into a column of badges. Coloured text, no pill.

   The modifiers below ARE statuses — verified, overdue, signed, awaiting — and they keep
   their pill, because they are the thing the eye is meant to find. */
.tag{display:inline-block;font-size:12.5px;font-weight:600;color:var(--navy);
  letter-spacing:.01em}
.tag.plain,.tag.warn,.tag.good,.tag.bad,.tag.gold,.tag.power,.tag.role{
  padding:3px 9px;border-radius:2px}
.tag.plain{background:var(--surface);border:1px solid var(--line);color:var(--ink-dim);font-weight:500;font-size:13px}
.tag.warn{background:var(--pending-bg);color:var(--pending)}
.tag.good{background:var(--success-bg);color:var(--success)}
.tag.bad{background:var(--alert-bg);color:var(--alert)}
.tag.gold{background:var(--gold);color:var(--navy-dark);font-weight:700;font-size:12px}

/* ---- SLA meters ----------------------------------------------------------- */
.meter{height:8px;border-radius:2px;background:var(--track);overflow:hidden}
.meter > i{display:block;height:100%;border-radius:2px;background:var(--navy)}
.meter > i.warn{background:var(--pending)} .meter > i.bad{background:var(--alert)} .meter > i.good{background:var(--success)}
.meterlabel{display:flex;justify-content:space-between;font-size:14px;color:var(--ink-dim);margin-bottom:6px}
.pips{display:flex;gap:4px;margin-top:14px}
.pips span{flex:1;height:8px;border-radius:2px;background:var(--track)}
.pips span.on{background:var(--navy)} .pips span.warn{background:var(--pending)} .pips span.over{background:var(--alert)}

/* ---- Timeline ------------------------------------------------------------- */
.trail{display:grid;grid-template-columns:20px 1fr auto;gap:0 14px;padding-bottom:18px}
.trail .spine{display:flex;flex-direction:column;align-items:center}
.trail .dot{width:12px;height:12px;border-radius:var(--r-round);background:var(--navy);border:3px solid var(--ring);
  box-shadow:0 0 0 1.5px var(--navy);margin-top:4px}
.trail .dot.mute{background:var(--ink-mute);box-shadow:0 0 0 1.5px var(--ink-mute)}
.trail .line{flex:1;width:2px;background:var(--line);margin-top:6px}
.trail .what{font-size:16px;font-weight:600}
.trail .what span{color:var(--ink-dim);font-weight:400}
.trail .meta{font-size:14px;color:var(--ink-dim);margin-top:2px}
.trail .when{text-align:right;font-size:14px;color:var(--ink-dim);white-space:nowrap}

.stages{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:26px}
.stage .bar{height:6px;border-radius:2px;background:var(--track);margin-bottom:10px}
.stage .bar.on{background:var(--navy)} .stage .bar.now{background:var(--pending)}
.stage .name{font-size:15px;font-weight:600;color:var(--ink-mute)}
.stage.done .name,.stage.now .name{color:var(--ink)}
.stage .sub{font-size:13.5px;color:var(--ink-dim);margin-top:2px}

/* ---- Grids and misc ------------------------------------------------------- */
.split{display:grid;grid-template-columns:repeat(auto-fit,minmax(340px,1fr));gap:24px;align-items:start}
.stack{display:flex;flex-direction:column;gap:24px}
.side{position:sticky;top:104px}
.notice{background:var(--pending-bg);border:1px solid var(--pending-line);border-radius:2px;padding:16px 18px;
  font-size:14.5px;color:var(--pending-ink);line-height:1.5;margin-bottom:18px}
.notice.bad{background:var(--alert-bg);border-color:var(--alert);color:var(--alert)}
.notice.good{background:var(--success-bg);border-color:var(--success);color:var(--success)}
.explain{background:var(--surface);border:1px solid var(--line);border-radius:2px;padding:16px 20px;font-size:15px;
  color:var(--ink-dim);line-height:1.55;margin-bottom:24px}
.explain strong{color:var(--ink);font-weight:600}
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.94em}
.lede{color:var(--ink-dim);font-size:16px;margin:8px 0 22px}
.deflist{display:grid;grid-template-columns:auto 1fr;gap:12px 16px;font-size:15px;line-height:1.4}
.deflist dt{color:var(--ink-dim);margin:0} .deflist dd{margin:0;font-weight:600}
.keyrow{display:flex;justify-content:space-between;padding:12px 0;border-bottom:1px solid var(--line);font-size:15px}
.keyrow span:first-child{color:var(--ink-dim)}
.keyrow span:last-child{font-weight:600}
.empty{padding:40px 24px;text-align:center;color:var(--ink-dim)}

/* ---- Pagination ----------------------------------------------------------- */
.pagination{display:flex;gap:10px;align-items:center;flex-wrap:wrap;font-size:15px;padding:18px 4px}
.pg{height:38px;padding:0 14px;border:1px solid var(--line);border-radius:2px;display:inline-flex;align-items:center;
  color:var(--navy);text-decoration:none;font-weight:600}
.pg:hover{border-color:var(--navy)}
.pg.disabled{color:var(--ink-mute);background:var(--surface)}
.pg-status{color:var(--ink-dim)}

/* ---- Responsive ----------------------------------------------------------- */
@media(max-width:1000px){
  /* The shell no longer needs a narrow-screen variant — one topbar and a drawer
     already collapse. What remains here is content, not chrome. */
  .wrap{padding:20px 20px 48px}
  /* Row grids collapse to a single column; the header row has nothing to head. */
  .rowhead{display:none}
  .row{grid-template-columns:1fr !important;gap:10px}
  .stages{grid-template-columns:repeat(2,1fr)}
  .side{position:static}
}

/* ── Organisation chart ─────────────────────────────────────────────────────
   A general .avatar lands here rather than in the topbar block because the
   throughput screen has been asking for one since it was written — it renders
   `avatar sm tint` against a rule scoped to `.topright`, so those initials have
   always drawn as bare text. One rule fixes both screens. */
.avatar{display:grid;place-items:center;border-radius:var(--r-round);background:var(--navy);
        color:#fff;font-weight:700;font-size:14px;letter-spacing:.02em;flex:none;
        width:38px;height:38px}
.avatar.sm{width:32px;height:32px;font-size:12.5px}
.avatar.tint{background:var(--navy-tint);color:var(--navy)}

.orghead{display:flex;justify-content:center;margin-bottom:0}
.orghead .person{border-color:var(--navy);box-shadow:var(--shadow-lift)}
/* The stem under the gate. Purely decorative — the heading structure carries
   the hierarchy for anyone not seeing the lines. */
.orgstem{width:2px;height:26px;background:var(--line-strong);margin:0 auto}
.orgunits{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:20px}
.orgunit{background:var(--card);border:1px solid var(--line);border-radius:var(--r-card);
         padding:18px 18px 12px}
.orgunit > h3{margin:0;font-size:17px;font-weight:700;letter-spacing:-.01em;
              display:flex;align-items:center;gap:9px}
.orgunit > h3 .code{font-size:11.5px;font-weight:700;letter-spacing:.06em;color:var(--ink-mute);
                    border:1px solid var(--line);border-radius:2px;padding:2px 6px}
.orgunit .vacant{font-size:14px;color:var(--ink-mute);padding:14px 2px 6px}
.orgnest{margin:14px 0 0;padding-left:14px;border-left:2px solid var(--line);display:grid;gap:14px}

.person{display:flex;gap:12px;align-items:flex-start;padding:13px 0;
        border-top:1px solid var(--line)}
.orgunit > h3 + .person{border-top:0}
.orghead .person{border:1px solid var(--navy);border-radius:var(--r-card);padding:16px 20px;
                 background:var(--card);min-width:min(420px,100%)}
.person .who{min-width:0;flex:1}
.person .nm{font-size:15.5px;font-weight:600;letter-spacing:-.01em;display:block}
.person .pos{font-size:13.5px;color:var(--ink-dim);display:block;margin-top:1px}
.person .marks{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px}
.person .reach{font-size:13px;color:var(--ink-dim);margin-top:7px;display:flex;
               align-items:center;gap:6px}
.person .reach b{font-weight:600;color:var(--ink)}
.tag.power{background:var(--navy-tint);color:var(--navy);font-weight:600;font-size:12px}
.tag.role{background:transparent;border:1px solid var(--line-strong);color:var(--ink-dim);
          font-weight:500;font-size:12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}

.grants{margin-top:24px}
.grants summary{cursor:pointer;font-weight:600;font-size:15.5px;padding:14px 0;
                display:flex;align-items:center;gap:8px}
.grants summary::-webkit-details-marker{display:none}
.grants summary::marker{content:''}
.grants summary::before{content:'▸';color:var(--ink-mute);font-size:13px}
.grants[open] summary::before{content:'▾'}
.grantrow{display:grid;grid-template-columns:minmax(140px,180px) 1fr;gap:18px;
          padding:14px 0;border-top:1px solid var(--line);align-items:start}
.grantrow .rolename{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13.5px;
                    font-weight:600;color:var(--navy)}
.grantrow .perms{display:flex;flex-wrap:wrap;gap:5px}
.grantrow .perms code{font-size:12px;background:var(--surface);border:1px solid var(--line);
                      border-radius:2px;padding:2px 7px;color:var(--ink-dim)}
@media (max-width:640px){
  .grantrow{grid-template-columns:1fr;gap:8px}
}

/* ── Saved views and filter chips ───────────────────────────────────────────
   Seven named views do not fit a fixed row on a laptop, so the control scrolls
   sideways rather than wrapping into a ragged block. */
.segmented.scroll{overflow-x:auto;flex-wrap:nowrap;scrollbar-width:thin}
.segmented.scroll a{white-space:nowrap;flex:none}
.viewhint{margin:10px 2px 16px;font-size:14.5px;color:var(--ink-dim);max-width:80ch}

.chips{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 16px}
.chip{display:inline-flex;align-items:center;gap:8px;height:30px;padding:0 6px 0 12px;
      border-radius:999px;background:var(--navy-tint);color:var(--navy);
      font-size:13px;font-weight:600}
.chip a{display:grid;place-items:center;width:20px;height:20px;border-radius:999px;
        color:var(--navy);text-decoration:none;font-size:15px;line-height:1}
.chip a:hover{background:var(--navy-tint)}
.chipclear{font-size:13px;color:var(--ink-dim);text-decoration:none}
.chipclear:hover{color:var(--navy);text-decoration:underline}

/* ── Record screen: stage ribbon ────────────────────────────────────────────
   Five stages, not four — the terminal one is synthetic, because resolving ends
   a branch rather than moving to a step. auto-fit so a department with a longer
   workflow does not squeeze the labels into columns nobody can read. */
.ribbon{display:flex;align-items:flex-end;gap:20px;flex-wrap:wrap;margin-bottom:26px}
.ribbon .stages{flex:1 1 480px;grid-template-columns:repeat(auto-fit,minmax(118px,1fr));margin-bottom:0}
.ribbon .stamp{flex:none;font-size:14.5px;font-weight:600;color:var(--ink-dim);
               border:1px solid var(--line);border-radius:999px;padding:7px 14px;background:var(--card)}
.ribbon .stamp.ok{border-color:var(--success);color:var(--success);background:var(--success-bg)}
.stage.now .bar{background:var(--pending)}
.stage.now .name{color:var(--pending)}

.rectabs{margin-bottom:18px}
.reltype{font-size:12.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-mute)}

/* ── Daily task log ─────────────────────────────────────────────────────────
   One row of fields that wraps rather than scrolls: this form is filled in on
   a Friday afternoon, several times in a row, and a horizontal scrollbar
   between the title and the Log button would be felt every time. */
.taskform{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap}
.taskform .field{margin:0}
.taskform .grow{flex:1 1 260px;min-width:200px}
.taskform button{flex:none}

/* ── Calendar ───────────────────────────────────────────────────────────────
   CSS Grid and one loop. A calendar library would cost more in bundle, upgrade
   surface and CSP allowances than it saves in code. */
/* minmax(0,1fr), not 1fr. A bare 1fr means minmax(AUTO,1fr), and a grid item's auto
   minimum is its content width — so one long document title widened Wednesday to half
   the month and pushed its own entries across three other days. The nowrap/ellipsis on
   .calentry cannot bite until the track is allowed to be narrower than its contents. */
.cal{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:1px;background:var(--line);
     border:1px solid var(--line);border-radius:var(--r-card);overflow:hidden}
.calhead{background:var(--surface);padding:10px 12px;font-size:11.5px;font-weight:700;
         letter-spacing:.06em;text-transform:uppercase;color:var(--ink-mute)}
.calday{background:var(--card);min-height:112px;padding:8px;display:flex;
        flex-direction:column;gap:4px;min-width:0}
.calday.outside{background:var(--surface)}
.calday.outside .caldate{color:var(--ink-mute)}
.caldate{font-size:12.5px;font-weight:600;color:var(--ink-dim)}
.calday.today .caldate{background:var(--navy);color:#fff;border-radius:var(--r-round);
                       width:24px;height:24px;display:grid;place-items:center}
.calentry{display:block;max-width:100%;padding:3px 7px;border-radius:2px;font-size:12px;
          font-weight:600;text-decoration:none;overflow:hidden;text-overflow:ellipsis;
          white-space:nowrap}
.calentry.deadline{background:var(--pending-bg);color:var(--pending)}
.calentry.deadline.at_risk{background:var(--pending-bg);color:var(--pending);
                           box-shadow:inset 0 0 0 1px var(--pending-line)}
.calentry.deadline.overdue{background:var(--alert-bg);color:var(--alert)}
.calentry.meeting{background:var(--navy-tint);color:var(--navy)}
.calentry.task{background:var(--success-bg);color:var(--success)}
.calentry.done{opacity:.6;text-decoration:line-through}
.callegend{display:flex;gap:10px;flex-wrap:wrap;margin-top:14px}
.callegend .calentry{cursor:default}
@media (max-width:720px){
  /* One column, and empty days dropped: a 7-wide grid at 360px is unreadable,
     and scrolling past three weeks of blank cells to reach a deadline is worse. */
  .cal{grid-template-columns:1fr}
  .calhead{display:none}
  .calday{min-height:0;flex-direction:row;align-items:center;flex-wrap:wrap;gap:8px}
  .calday.outside{display:none}
  .calday:not(.today):not(:has(.calentry)){display:none}
  .calday .caldate{min-width:70px}
}

/* ── The record sheet ───────────────────────────────────────────────────────
   The record screen was nine cards stacked down a page: a 14px radius and 22px
   of padding around every fact, so a document with forty facts on it read as
   forty objects rather than one. This block is the spreadsheet vocabulary that
   replaces it — hairline boxes, 34px rows, aligned columns, tabular numerals.

   It is ADDITIVE. Nothing here touches .card, .kpi or .row, because the queue
   and the dashboard are lists of many records and were never the problem; the
   record is one record, and wants density instead of separation.

   Three layouts consume it (App\Support\RecordLayout). They differ in
   composition only — the same partials, arranged three ways — which is why
   there is one stylesheet block and not three. */
:root{--mono:ui-monospace,SFMono-Regular,Menlo,monospace}

.colhd{font-size:11.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-mute)}
.num{font-family:var(--mono);font-variant-numeric:tabular-nums}
/* text-overflow needs a block box; on an inline span it silently does nothing and
   the cell just gets wider. Same trap as .row .title above. */
.clip{display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.box{border:1px solid var(--line);border-radius:2px;background:var(--card);overflow:hidden}
/* A SECTION HEADING HAS TO OUTRANK THE COLUMN HEADINGS UNDERNEATH IT.
 *
 * It did not. "ROUTING TRAIL" was 12px/700/uppercase in ink-dim on white; the
 * column header row below it was 11.5px/700/uppercase in ink-mute, and .grid th
 * was 12px/700 in ink-dim — the same size, weight and colour as the section
 * heading itself. Three levels of structure rendered as one, so four stacked
 * cards read as one long ribbon of grey capitals and you could not see where a
 * section began.
 *
 * Two changes, and between them they do the whole job. The heading takes the
 * near-black ink, which puts a real step between it and the muted column labels.
 * The strip takes a cool tint — distinct from the warm neutral the column header
 * row uses, so the two bands never merge — which marks the top of each card while
 * scrolling without adding another rule.
 *
 * Deliberately NOT navy: navy is this interface's action colour, worn by links
 * and the active state, and a heading in it invites a click that does nothing. */
.boxhd{display:flex;align-items:center;justify-content:space-between;gap:10px;
  min-height:38px;padding:6px 12px;background:var(--navy-wash);
  border-bottom:1px solid var(--line)}
.boxhd h2{margin:0;font-size:12px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  color:var(--ink)}
.boxhd .n{font-size:12px;color:var(--ink-mute);font-family:var(--mono)}
.boxft{display:flex;justify-content:space-between;gap:12px;padding:9px 12px;background:var(--surface);
  border-top:1px solid var(--line);font-size:12.5px;color:var(--ink-dim)}

.sheet{width:100%;border-collapse:collapse;font-size:13.5px;table-layout:fixed}
/* ink-DIM, not ink-mute. The Fluent greys are lighter than the warm set they
 * replaced, and --ink-mute on --surface came out at roughly 2:1 — grey lettering on
 * a grey bar, which is what the column headers actually looked like. Dynamics'
 * own headers are dark and semibold; they are read, not merely present. */
.sheet th{background:var(--surface);text-align:left;padding:7px 12px;white-space:nowrap;
  border-bottom:1px solid var(--line);
  font-size:11.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-dim)}
.sheet td{padding:0 12px;height:34px;border-bottom:1px solid var(--line);vertical-align:middle;
  overflow:hidden;text-overflow:ellipsis}
.sheet tr:last-child td{border-bottom:0}
.sheet td.k{color:var(--ink-dim);background:var(--surface);border-right:1px solid var(--line);
  font-weight:500;white-space:nowrap;width:168px}
.sheet td.v{font-weight:600}
.sheet td.c{border-right:1px solid var(--line)}
.sheet td.g{background:var(--surface);color:var(--ink-mute);text-align:right;
  border-right:1px solid var(--line);font-family:var(--mono)}
.sheet td.dim{font-weight:400;color:var(--ink-dim)}
/* A timestamp that wraps costs the column nothing to widen and costs the reader a
   second line on every row. Numbers never wrap; only .wrap cells do. */
.sheet td.num{white-space:nowrap}
.sheet td.none{font-weight:400;color:var(--ink-mute)}
.sheet tr.alt td{background:#FCFCFA}
.sheet tr.alt td.k,.sheet tr.alt td.g{background:var(--surface)}
.sheet .empty{padding:18px 12px;text-align:center;color:var(--ink-dim);font-size:14px}
/* A six-column grid does not fit the worksheet's centre pane, and proportional
   tracks just squash every column instead of one. Below the min-width the sheet
   scrolls sideways — which is what a spreadsheet does, and what the saved-views
   control on the queue already does. */
.sheetwrap{overflow-x:auto}
.sheetwrap > .sheet{min-width:620px}
/* A tall cell (a remark, a wrapped subject) still has to sit on the grid. */
.sheet td.wrap{white-space:normal;padding-top:8px;padding-bottom:8px;height:auto;line-height:1.45}

/* Cell blocks — the header facts. Gridlines are a 1px gap over a line-coloured
   background, the same trick .cal uses, so every rule is exactly one pixel and
   the corners stay clipped by the parent radius. */
.cells{display:grid;gap:1px;background:var(--line);border:1px solid var(--line);
  border-radius:2px;overflow:hidden}
.cells.c4{grid-template-columns:repeat(4,minmax(0,1fr))}
.cells.c5{grid-template-columns:repeat(5,minmax(0,1fr))}
.cells.c6{grid-template-columns:repeat(6,minmax(0,1fr))}
.cell{background:var(--card);padding:9px 12px;min-width:0}
.cell.key{background:var(--surface)}
.cell .val{font-size:14px;font-weight:600;margin-top:3px;display:flex;align-items:center;gap:7px;min-width:0}
.cell .big{font-size:21px;font-weight:700;letter-spacing:-.02em;margin-top:1px}
.cell .foot{font-size:12.5px;color:var(--ink-dim);margin-top:2px}
.cell .foot.bad{color:var(--alert);font-weight:600}

/* The stage strip: the ribbon on the same gridlines as everything else. */
.strip .cell{padding-bottom:11px}
.strip .bar{display:block;height:5px;border-radius:2px;background:var(--track);margin-bottom:8px}
.strip .bar.on{background:var(--navy)}
.strip .bar.now{background:var(--pending)}
.strip .name{font-size:13.5px;font-weight:600}
.strip .stage.todo .name{color:var(--ink-mute)}
.strip .stage.now .name{color:var(--pending)}
.strip .sub{font-size:12.5px;color:var(--ink-dim);margin-top:1px}

/* Identity bar: everything that names the record, on one line. */
.idbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-height:44px;padding:5px 12px;
  border:1px solid var(--line);border-radius:2px;background:var(--surface)}
.idbar .back{display:flex;align-items:center;gap:5px;font-size:13.5px;color:var(--ink-dim);
  font-weight:500;text-decoration:none}
.idbar .back:hover{color:var(--navy)}
.idbar .sep{width:1px;height:18px;background:var(--line-strong);display:block}
.idbar .age{margin-left:auto;font-size:13px;color:var(--ink-dim);font-weight:600}

/* Compact form controls. The 48px inputs are right on the intake form, which is
   typed into once; they are wrong in a 372px action rail beside a 34px grid. */
.rform{padding:12px;display:flex;flex-direction:column;gap:10px}
.rform + .rform{border-top:1px solid var(--line)}
.lbl{display:block;font-size:11.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-mute);margin-bottom:5px}
.lbl .hint{font-weight:400;text-transform:none;letter-spacing:0}
/* input.inp, not .inp: the base control rule is `input[type=text]` and friends, which is
   (0,1,1) — so a bare .inp at (0,1,0) LOST to it and every compact input in the app has
   been silently rendering at the 48px page-form height while the selects beside it were
   34. Same specificity trap as the .btn one; qualify, and it wins on order. */
input.inp,select.inp,textarea.inp{height:34px;width:100%;padding:0 10px;border:1px solid var(--line);
  border-radius:2px;font-family:var(--sans);font-size:13.5px;color:var(--ink);background:var(--card);
  display:block;max-width:100%}
textarea.inp,select.inp[multiple]{height:auto;padding:8px 10px;line-height:1.5;resize:vertical}
.btn.sm{height:36px;padding:0 14px;font-size:14px;border-radius:2px}

.segmented.sm{padding:3px;border-radius:2px}
.segmented.sm a{padding:5px 12px;border-radius:2px;font-size:13.5px}

/* The layout switch. Three names, no icons — an icon for "worksheet" would be a
   guess the user has to decode. */

/* Layout frames */

/* The grid layout keeps its actions in a disclosure rather than a permanent rail:
   on most records the rail is empty, because only the officer holding the open
   step can do anything with it. */
/* Full width, so the forms lay out across it rather than stretching a Reason
   field to 1272px. Same 1px-gap gridlines as the cell blocks, which handles the
   separators in both axes when the row wraps. */

@media (max-width:1180px){
  /* Three columns need 1280px to stay readable. Below that the worksheet is a
     ledger, and the ledger is one column — the panes stack in reading order:
     what the record says, then what you can do about it. */
}
@media (max-width:900px){
  .cells.c4,.cells.c5,.cells.c6{grid-template-columns:repeat(2,minmax(0,1fr))}
  .sheet{table-layout:auto}
}

/* ── The shell: a standing rail, not a burger ───────────────────────────────
   CPDO's staff navigate PowerDTS by a standing list of entities. The burger
   that was here first was chosen on the belief that their own system hid the
   document module behind one menu; a photograph of PowerDTS showed otherwise.
   The rail costs 260px and buys never having to remember what is behind a menu.

   Below 900px it becomes a drawer — still details/summary, still no JavaScript. */
.shell{display:grid;grid-template-columns:260px minmax(0,1fr);min-height:100vh}
.pane{min-width:0;display:flex;flex-direction:column}
.shell .main{min-height:0;flex:1}

.rail{background:var(--surface);border-right:1px solid var(--line);padding:8px;
  display:flex;flex-direction:column;gap:1px}
.railapp{display:flex;align-items:center;gap:10px;height:52px;padding:0 8px;margin-bottom:4px;
  text-decoration:none;color:inherit;flex:none}
.railapp .mark{width:32px;height:32px;border-radius:2px;background:var(--navy);
  display:grid;place-items:center;flex:none}
.railapp .mark i{width:12px;height:12px;border-radius:2px;background:var(--gold);
  transform:rotate(45deg);display:block}
.railapp .nm{font-weight:800;font-size:16px;letter-spacing:-.02em;white-space:nowrap}
.railapp .nm span{font-weight:500;color:var(--ink-dim)}

.railitem{display:flex;align-items:center;gap:11px;min-height:36px;padding:0 10px;border-radius:2px;
  color:var(--ink);font-size:14px;text-decoration:none;position:relative}
.railitem svg{color:var(--ink-mute);flex:none}
.railitem:hover{background:var(--hover)}
.railitem.on{background:var(--navy-tint);color:var(--navy);font-weight:600}
.railitem.on svg{color:var(--navy)}
/* The active marker sits in the rail's 8px padding, so it reads as a tab against
   the edge rather than as a border inside the item. */
.railitem.on::before{content:'';position:absolute;left:-8px;top:7px;bottom:7px;width:3px;
  border-radius:0 2px 2px 0;background:var(--navy)}
.railitem .count{margin-left:auto;font-size:11.5px;font-weight:700;padding:1px 7px;border-radius:2px;
  background:var(--alert-bg);color:var(--alert)}
.railitem .count.calm{background:var(--navy-tint);color:var(--navy)}
.railgroup{display:flex;align-items:center;gap:7px;padding:15px 10px 5px;
  font-size:11.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-mute)}
.railgroup svg{color:var(--ink-mute);flex:none}
.railsep{height:1px;background:var(--line);margin:8px 2px;flex:none}

/* ── Command bar ────────────────────────────────────────────────────────────
   The verbs for the screen you are on. Save is first because it is pressed most. */
.cmdbar{display:flex;align-items:center;gap:1px;min-height:46px;padding:6px 14px;flex-wrap:wrap;
  border-bottom:1px solid var(--line);background:var(--card);
  position:sticky;top:0;z-index:20}
.cmd{display:inline-flex;align-items:center;gap:7px;height:32px;padding:0 10px;border-radius:2px;
  font-size:13.5px;color:var(--ink);background:none;border:0;font-family:inherit;cursor:pointer;
  text-decoration:none;white-space:nowrap}
.cmd:hover{background:var(--surface);color:var(--ink);text-decoration:none}
.cmd svg{color:var(--ink-dim);flex:none}
.cmd.primary{color:var(--navy);font-weight:600}
.cmd.primary svg{color:var(--navy)}
.cmdsep{width:1px;height:20px;background:var(--line);margin:0 7px;flex:none}
.cmdbar .right{margin-left:auto;display:flex;align-items:center;gap:8px}
.cmdbar .right .iconbtn{border-color:transparent;width:32px;height:32px}

.raildrawer{display:none}
@media (max-width:900px){
  .shell{grid-template-columns:minmax(0,1fr)}
  .shell > .rail{display:none}
  .raildrawer{display:block;position:sticky;top:0;z-index:30;background:var(--card);
    border-bottom:1px solid var(--line)}
  .raildrawer > .rail{border-right:0;background:var(--card)}
  .raildrawer[open]{box-shadow:var(--shadow-pop)}
  /* The toggle carries the wordmark. A bare hamburger alone at the top of a phone
     screen leaves the app with no identity at all until you open the drawer. */
  .railtoggle{display:flex;align-items:center;gap:11px;height:56px;padding:0 14px;cursor:pointer;
    list-style:none}
  .railtoggle::-webkit-details-marker{display:none}
  .railtoggle::marker{content:''}
  .railtoggle .bars{display:grid;gap:4px;width:20px;flex:none}
  .railtoggle .bars span{display:block;height:2px;background:var(--ink);border-radius:2px}
  .railtoggle .mark{width:30px;height:30px;border-radius:2px;background:var(--navy);
    display:grid;place-items:center;flex:none}
  .railtoggle .mark i{width:11px;height:11px;border-radius:2px;background:var(--gold);
    transform:rotate(45deg);display:block}
  .railtoggle .nm{font-weight:800;font-size:16px;letter-spacing:-.02em}
  .railtoggle .nm span{font-weight:500;color:var(--ink-dim)}
  /* The drawer's own copy of the wordmark would be the second one on screen. */
  .raildrawer .railapp{display:none}
  /* The command bar cannot also be sticky under a sticky drawer — two stacked
     sticky elements at top:0 overlap, and the bar wins by source order. */
  .cmdbar{position:static}
}

/* ── Business process flow ──────────────────────────────────────────────────
   The stage bar CPDO reads first. A chip naming the flow and its age, then the
   track. Clicking the live stage opens its own fields, so finishing a stage
   never means hunting the page for the field that gates it.

   Note .bpfname, not .lbl — .lbl is already the uppercase form-label class, and
   the mockup's stage names borrowed it and came out shouting. */
.bpf{position:relative;display:flex;align-items:flex-start;gap:18px;margin:0 0 18px;
  /* Right padding reserves the lane the Act button sits in. A shorthand `padding`
     after a `padding-right` silently wins, which is how the track ended up running
     161px underneath the button. */
  padding:10px 172px 10px 14px;border:1px solid var(--line);border-radius:2px;background:var(--surface)}
.bpfchip{flex:none;max-width:220px;background:var(--navy);color:#fff;border-radius:2px;padding:7px 12px}
.bpfchip b{display:block;font-size:13px;font-weight:700;letter-spacing:-.01em}
.bpfchip span{display:block;font-size:11.5px;color:#B9C4E4;margin-top:1px}
.bpftrack{flex:1;display:flex;align-items:flex-start;min-width:0;padding-top:4px}
.bpfstage{flex:1;position:relative;padding-top:28px;text-align:center;min-width:0}
.bpfstage .line{position:absolute;top:11px;left:0;right:0;height:2px;background:var(--track)}
.bpfstage.done .line{background:var(--navy)}
/* The rail must not run off the ends of the track. */
.bpfstage:first-child .line{left:50%}
.bpfstage:last-child .line{right:50%}
.bpfstage .dot{position:absolute;top:0;left:50%;transform:translateX(-50%);width:24px;height:24px;
  border-radius:50%;background:var(--card);border:2px solid var(--line-strong);
  display:grid;place-items:center;font-size:11px;font-weight:800;color:var(--ink-mute)}
.bpfstage.done .dot{background:var(--navy);border-color:var(--navy);color:#fff}
/* THE CURRENT STAGE IS BLUE, not gold.
 *
 * A gold ring was ours and it was defensible — it separates "where it is now" from
 * "done" at a glance, which their bar cannot do. But CPDO read the stage bar in
 * their own system every day and it is their accent that says "you are here", so
 * the ring follows them. The distinction survives in the shape: done is a filled
 * disc with a tick, now is a hollow disc with a halo. */
.bpfstage.now .dot{background:var(--card);border-color:var(--navy);color:var(--navy);
  box-shadow:0 0 0 4px var(--navy-tint)}
/* Two lines' worth, always. The names wrap rather than truncate — a stage nobody
   can read is worse than a ribbon one line taller — and reserving the height keeps
   every stage's detail line ("here now", "not reached") on one baseline instead of
   stepping up and down with the length of the name above it. */
.bpfstage .bpfname{font-size:13px;font-weight:600;color:var(--ink-mute);
  line-height:1.25;min-height:2.5em;text-wrap:balance;overflow-wrap:break-word;
  padding:0 4px}
.bpfstage.done .bpfname{color:var(--ink)}
.bpfstage.now .bpfname{color:var(--navy-dark)}
.bpfstage .sub{font-size:12.5px;color:var(--ink-dim);margin-top:1px}
@media (max-width:820px){
  /* Five stages in a row is unreadable on a phone. Stacked, the track becomes a
     vertical list and the connector would be drawing a line to nowhere. */
  .bpf{flex-direction:column;gap:12px}
  .bpfchip{max-width:none;width:100%}
  .bpftrack{flex-direction:column;gap:10px;width:100%;padding-top:0}
  .bpfstage{padding-top:0;text-align:left;padding-left:34px}
  /* The two reserved lines exist to align the detail lines ACROSS columns. Stacked,
     there are no columns, and the reservation is just a gap under every name. */
  .bpfstage .bpfname{min-height:0;padding:0}
  .bpfstage .line{display:none}
  .bpfstage .dot{top:0;left:0;transform:none}
}

/* The stage's own panel. It overlays rather than pushing the record down, so
   opening it does not move what you were reading. */
.bpfact{position:absolute;top:14px;right:14px;z-index:26}
.bpfact > summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:7px}
.bpfact > summary::-webkit-details-marker{display:none}
.bpfact > summary::marker{content:''}
.bpfact[open] > summary{background:var(--navy-600)}
.bpfact > summary svg{transition:transform .15s}
.bpfact[open] > summary svg{transform:rotate(180deg)}
.bpfpanel{position:absolute;top:44px;right:0;width:336px;z-index:25;
  background:var(--card);border:1px solid var(--line);border-radius:2px;
  box-shadow:var(--shadow-pop)}
.bpfpanel .hd{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:10px 14px;border-bottom:1px solid var(--line)}
/* A fanned-out document stacks its branches in the one panel, each with its own
   heading. The rule above the second and later headings separates them. */
.bpfpanel .bd + .hd{border-top:1px solid var(--line)}
.bpfpanel{max-height:min(70vh,620px);overflow-y:auto}
.bpfpanel .hd h4{margin:0;font-size:12px;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:var(--ink-dim)}
.bpfpanel .hd .n{font-size:12px;color:var(--ink-mute)}
.bpfpanel .bd{padding:14px}
.flyfield{margin-bottom:10px}
.flyhint{margin:6px 0 0;font-size:12px;color:var(--ink-dim);line-height:1.45}
@media (max-width:820px){
  /* Overlaying a 336px panel on a 375px screen hides the record entirely. Below
     this width it is simply the last thing in the stage list. */
  .bpf{padding:10px 14px}
  .bpfact{position:static;width:100%}
  .bpfact > summary{width:100%;justify-content:center}
  .bpfpanel{position:static;width:auto;box-shadow:none;margin-top:8px;max-height:none}
}

/* ── A command that needs arguments ─────────────────────────────────────────
   The popover hangs off the bar rather than pushing the page down, so opening
   one does not move the record underneath it. */
.cmddialog{position:relative}
.cmddialog > summary{list-style:none;cursor:pointer}
.cmddialog > summary::-webkit-details-marker{display:none}
.cmddialog > summary::marker{content:''}
.cmddialog[open] > summary{background:var(--navy-tint);color:var(--navy)}
.cmddialog[open] > summary svg{color:var(--navy)}
.cmdpop{position:absolute;top:38px;left:0;z-index:40;width:316px;padding:14px;
  background:var(--card);border:1px solid var(--line);border-radius:2px;
  box-shadow:var(--shadow-pop)}
.cmdpop .popnote{margin:0 0 10px;font-size:12.5px;color:var(--ink-dim);line-height:1.45}
.cmdpop .poprow{display:flex;justify-content:space-between;gap:10px;padding:6px 0;
  border-bottom:1px solid var(--line);font-size:13px}
.cmdpop .poprow span{color:var(--ink-dim)}
.cmdpop .poprow strong{font-weight:600}
.cmdpop .popsplit{margin-top:12px;padding-top:12px;border-top:1px solid var(--line)}
@media (max-width:600px){
  /* A 316px popover anchored left runs off a 375px screen once the command it
     hangs from is not the first one in the bar. */
  .cmdpop{left:auto;right:0;width:min(316px,calc(100vw - 28px))}
}
/* The worksheet lost its action pane to the command bar; two columns, not three. */

/* ── The record form ────────────────────────────────────────────────────────
   The arrangement CPDO already uses. Two columns of label-and-value on one
   150px label track, so values line up down the page rather than wandering
   with their labels. */
.rechead{display:flex;align-items:center;gap:24px;padding:4px 0 0;flex-wrap:wrap}
.rechead .back{width:28px;height:28px;border-radius:2px;display:grid;place-items:center;
  color:var(--ink-dim);flex:none}
.rechead .back:hover{background:var(--surface)}
.rechead .name{font-size:21px;font-weight:700;letter-spacing:-.025em;display:flex;
  align-items:baseline;gap:9px}
.rechead .saved{font-size:12.5px;font-weight:500;color:var(--ink-mute)}
.rechead .ent{font-size:12.5px;color:var(--ink-dim);margin-top:1px}
.headfields{margin-left:auto;display:flex;align-items:center;gap:28px;flex-wrap:wrap}
.headfield{min-width:0}
.headfield .l{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-mute)}
.headfield .v{font-size:14px;font-weight:600;margin-top:2px;display:flex;align-items:center;
  gap:8px;max-width:300px}

/* Underlined tabs, not pills: these switch the form's sections, they do not
   filter a list, and the two should not look alike. */
.formtabs{display:flex;gap:4px;border-bottom:1px solid var(--line);margin:16px 0 0;
  overflow-x:auto;scrollbar-width:thin}
.formtabs a{padding:11px 12px 9px;font-size:14px;color:var(--ink-dim);
  border-bottom:2px solid transparent;text-decoration:none;white-space:nowrap}
.formtabs a:hover{color:var(--ink)}
.formtabs a.on{color:var(--navy);font-weight:600;border-bottom-color:var(--navy)}

.formsec{padding:16px 0 0}
.formgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 44px}
.fld{display:grid;grid-template-columns:150px minmax(0,1fr);align-items:center;gap:14px;
  min-height:42px;padding:5px 0;border-bottom:1px solid var(--line);min-width:0}
.fld > .l{font-size:12.5px;color:var(--ink-dim);display:flex;align-items:center;gap:6px;
  line-height:1.3}
.fld > .l svg{color:var(--ink-mute);flex:none}

/* ONE TYPEFACE RULE FOR EVERY VALUE IN A FIELD GRID.
 *
 * The record screen had grown three unrelated treatments and read as noise: the
 * phone and email in monospace, the dates ALSO in monospace (via .num, which was
 * written for numeric table columns and has no alignment to do here), and
 * everything else in the sans — while read-only values sat at 600 and the editable
 * ones at 400, so the fields you cannot change shouted and the ones you can
 * whispered.
 *
 * The rule now:
 *
 *   MONOSPACE MEANS "TRANSCRIBE THIS CHARACTER BY CHARACTER" — a tracking code, a
 *   reference, a verification code, an email, a phone number. Things a clerk reads
 *   aloud down the telephone, copies onto a receipt slip, or types into another
 *   system, where 0/O and 1/l have to be told apart. Nothing else earns it.
 *
 * A date is read as a word, not transcribed, so it wears the sans like "Approved"
 * and "3 working days" beside it. It keeps tabular figures, which cost nothing and
 * keep the digits in line where two dates sit in one column.
 *
 * And one weight for every value, editable or not. They are the same data; the
 * input's own border and background already say which ones you may change, so
 * weight does not need to say it again — least of all backwards.
 */
/* ONE declaration, so these cannot out-specify each other. Splitting them is how
 * the sizes drifted apart in the first place. */
.fld .ro,
.fld .ed,
.fld .look,
.fld .mono{font-size:13.5px;font-weight:500}
.fld .ro{min-width:0}
.fld .date{font-family:var(--sans);font-variant-numeric:tabular-nums}
/* Monospace changes the FACE, never the size. The global .mono carries a .94em
 * optical correction that is right in running prose and wrong in this grid:
 * `class="ro mono"` on one element kept 13.5px while a nested <span class="mono">
 * inherited the reduction, so the tracking code sat 0.8px shorter than the email
 * two rows above it. */
.fld .mono{font-family:var(--mono)}

/* A STRING SOMEBODY WILL READ ALOUD AND WRITE DOWN BY HAND.
 *
 * The tracking code is the only value on this screen that leaves the building.
 * Everything else is internal bookkeeping; this one gets copied onto a receipt
 * slip at the counter, and read down the telephone to a complainant who has lost
 * the slip. The notice on registration says as much in so many words: "write this
 * on the receipt slip."
 *
 * So it is sized and spaced for the two ways it actually fails — misreading a
 * character, and losing your place halfway through dictating it:
 *
 *   - bigger than its neighbours, and the ONE deliberate exception to the single
 *     value size above. It is not a value you scan, it is an object you hand over;
 *   - letter-spaced, so characters do not touch. Monospace already tells 0 from O,
 *     and spacing is what makes that legible at arm's length across a counter;
 *   - on its own surface, so the eye finds it without reading the label first;
 *   - user-select:all, so one click takes the whole code and none of the
 *     surrounding words — the nearest thing to a copy button that needs no
 *     JavaScript, and this app deliberately has none.
 *
 * Reusable on purpose: the released document's verification code has the same job
 * and should wear this too when that screen is next touched.
 */
.fld .readaloud{display:inline-block;font-family:var(--mono);font-size:15px;font-weight:600;
  letter-spacing:.085em;line-height:1.35;color:var(--ink);background:var(--surface);
  border:1px solid var(--line-strong);border-radius:var(--r-pill);padding:3px 8px 3px 10px;
  /* NEVER broken across lines. A code split as MDU-C3GC-22Y- / 3 is worse than no
   * styling at all: the clerk dictating it loses the boundary between a hyphen that
   * belongs to the code and one the layout invented. */
  white-space:nowrap;
  -webkit-user-select:all;user-select:all}

/* The handover field takes the full width of the grid.
 *
 * Not decoration — geometry. The value columns are half of a two-column grid, and a
 * fourteen-character code at 15px with letter-spacing does not fit one, so it wrapped
 * mid-code. Given the whole row it fits with room for its note alongside instead of
 * stacked beneath, which also stops this field being the one that is mysteriously
 * twice as tall as its neighbours.
 *
 * It pairs the remaining fields better as a side effect: the two dates end up beside
 * each other, and so do the two approval fields. */
.fld.handover{grid-column:1/-1}
.fld.handover .ro{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.fld.handover .fldnote{margin-top:0}
/* UNDERLINED, NOT BOXED.
 *
 * PowerDTS draws an editable field as a value sitting on a rule — no box, no fill —
 * and a read-only one as the same value with no rule at all. The difference a clerk
 * reads is "there is a line under this, so I may type here", which is the smallest
 * signal that still works, and it is the one they already know.
 *
 * Boxed inputs were ours, and on a grid of eighteen fields they drew eighteen
 * rectangles competing with the row rules underneath them for the same job. The box
 * is gone; the rule does the work.
 *
 * The rule thickens and turns navy on focus rather than moving anything, so the
 * baseline never shifts under the cursor — a 1px border growing to 2px inside a
 * 32px box is a jump a touch-typist feels. */
.fld .ed{height:32px;width:100%;padding:0 2px;border:0;border-bottom:1px solid var(--line);
  border-radius:0;font-family:var(--sans);color:var(--ink);background:transparent;display:block}
.fld .ed:hover{border-bottom-color:var(--ink-mute)}
.fld .ed:focus{outline:none;border-bottom:2px solid var(--navy);
  box-shadow:0 1px 0 0 var(--gold);padding-bottom:0}
/* A select has to keep its chevron, which the browser draws inside the control's own
 * box; zeroing the padding on the right clips it. */
.fld select.ed{padding-right:0}

/* THE OWNER CHIP.
 *
 * A disc of initials, the name beside it. Their header carries one because the
 * question this screen is asked most often is "who has it", and the answer is a
 * person — so it is drawn as one. The disc is suppressed when the holder is not a
 * person (Nobody, Unassigned, "3 people"); see staff/record/form.blade.php. */
.ownerchip{display:inline-flex;align-items:center;gap:8px;min-width:0}
.ownerchip .av{flex:none;width:24px;height:24px;border-radius:50%;display:grid;
  place-items:center;background:var(--navy);color:#fff;font-size:10.5px;font-weight:700;
  letter-spacing:.02em}
.fld .look{display:inline-flex;align-items:center;gap:6px;color:var(--navy);min-width:0}
.fld .look svg{flex:none}
.recsheets{display:flex;flex-direction:column;gap:16px;margin-top:22px}

@media (max-width:900px){
  /* One column of fields. Two 150px label tracks side by side leave nothing for
     the values on a phone. */
  .formgrid{grid-template-columns:minmax(0,1fr);gap:0}
  .headfields{margin-left:0;gap:18px}
  .headfield .v{max-width:none}
}
.formsec-h{margin:0 0 6px;font-size:12px;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:var(--ink-dim)}

/* ── List screens ───────────────────────────────────────────────────────────
   A grid under a view picker. The title IS the saved view, which is how
   PowerDTS names a list; the chevron opens the others. */
.viewpick{display:flex;align-items:center;gap:6px;padding:4px 0 0}
.viewpick h1{margin:0;font-size:21px;font-weight:700;letter-spacing:-.025em}
.viewpick .chev{display:grid;place-items:center;width:30px;height:30px;border-radius:2px;
  color:var(--ink-mute);cursor:pointer}
.viewpick .chev:hover{background:var(--surface);color:var(--navy)}
.viewpick .cmdpop{width:300px}
.viewlist{display:flex;flex-direction:column;gap:1px}
.viewlist a{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:8px 10px;border-radius:2px;color:var(--ink);font-size:13.5px;text-decoration:none}
.viewlist a:hover{background:var(--surface);text-decoration:none}
.viewlist a.on{background:var(--navy-tint);color:var(--navy);font-weight:600}
.viewlist a .n{font-family:var(--mono);font-size:12px;color:var(--ink-mute)}
.viewlist a.on .n{color:var(--navy)}

.grid{width:100%;border-collapse:collapse;font-size:13.5px;table-layout:fixed}
/* Column labels, and they must read as subordinate to the section heading above
 * them. These were 12px/700 in ink-dim — the section heading's exact size, weight
 * and colour — so on a card like "Assignment history" the heading and its own
 * column row rendered as equals. They now match .sheet th, which means one
 * treatment for column labels across the whole application instead of two that
 * differ for no reason a reader could name. */
.grid th{background:var(--surface);text-align:left;padding:8px 12px;white-space:nowrap;
  border-bottom:1px solid var(--line);
  font-size:11.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;
  color:var(--ink-dim)}
.grid th .sort{color:var(--ink-mute);font-size:10px;margin-left:4px}
.grid td{padding:0 12px;height:44px;border-bottom:1px solid var(--line);vertical-align:middle;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.grid tr:last-child td{border-bottom:0}
.grid tbody tr:hover td{background:var(--surface)}
.grid .chk{width:46px;padding-left:15px;padding-right:0;text-overflow:clip}
.grid .empty{padding:34px 14px;text-align:center;color:var(--ink-dim);white-space:normal;height:auto}
.box{border:1px solid var(--line);border-radius:2px;background:var(--card);overflow:hidden}
.gridwrap{overflow-x:auto}
/* Seven columns now, not eight — see staff/approvals. Squashing them to fit a 1024
   screen made every cell an ellipsis, so the grid still scrolls sideways there; what
   changed is that the first cell is a link to the panel, so the action is never the
   thing that falls off the edge. */
.gridwrap > .grid{min-width:680px}
.chkbox{width:15px;height:15px;border:1.5px solid var(--line-strong);border-radius:2px;
  display:inline-block;vertical-align:middle;background:var(--card)}
/* A second line inside a grid cell — a reference under a title, a status under a
   holder. The cell stops being a single 44px line, so it may not clip its text. */
.grid td .sub{display:block;font-size:12px;color:var(--ink-dim);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.grid td:has(.sub){height:52px}
.grid td .meterlabel{margin-bottom:4px;font-size:12px}
/* Filter controls on a list screen sit above a 44px grid; the 48px intake-form
   controls read as a different application stacked on top of one. */
.toolbar.compact select,.toolbar.compact input{height:34px;font-size:13.5px;border-radius:2px}
.toolbar.compact button{height:34px;padding:0 14px;font-size:13.5px;border-radius:2px}
.toolbar.compact .inline{font-size:13px}

/* ── The approval inbox ─────────────────────────────────────────────────────
   A grid of what is waiting, and the summary in a panel on the right when he
   opens a row. The panel is driven by ?open, not by script: this app has no
   JavaScript, and a server-rendered panel is linkable and survives the back
   button. */
.approval-title{display:block;font-size:17px;font-weight:700;letter-spacing:-.02em;
  line-height:1.25;color:var(--ink);text-decoration:none}
.approval-title:hover{color:var(--navy);text-decoration:underline}
.approval-ask{margin:14px 0 0;padding:10px 14px;background:var(--surface);border-radius:2px;
  border-left:3px solid var(--gold);font-size:13.5px;line-height:1.5;color:var(--ink)}
.approval-open{display:block;margin-top:16px;font-size:13px;color:var(--ink-dim)}
.grid tr.on td{background:var(--navy-tint)}

/* The scrim is the same link as the close button, so clicking anywhere off the
   panel closes it — which is what people try first. */
.slidescrim{position:fixed;inset:0;z-index:55;background:var(--scrim)}
.slideover{position:fixed;top:0;right:0;bottom:0;z-index:60;width:min(440px,100vw);
  background:var(--card);border-left:1px solid var(--line);
  box-shadow:var(--shadow-pop-left);
  display:flex;flex-direction:column;animation:dtsSlide .22s ease-out}
@keyframes dtsSlide{from{transform:translateX(28px);opacity:0}to{transform:none;opacity:1}}
.slideover .hd{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;
  padding:14px 16px;border-bottom:1px solid var(--line);flex:none}
.slideover .bd{flex:1;overflow-y:auto;padding:16px}
.slideover .ft{flex:none;border-top:1px solid var(--line);padding:14px 16px;background:var(--surface)}
@media (prefers-reduced-motion:reduce){.slideover{animation:none}}


/* People in the approval panel. A .chip is a dismissible filter; two unit heads
   rendered as chips became two lavender slabs with the post — which is how the
   Director tells one unit head from another — set in the same weight as the name. */
.refperson{display:flex;align-items:flex-start;gap:11px;padding:9px 0;
  border-bottom:1px solid var(--line)}
.refperson:last-of-type{border-bottom:0}
.refperson .nm{display:block;font-size:14px;font-weight:600;letter-spacing:-.01em}
.refperson .pos{display:block;font-size:12.5px;color:var(--ink-dim);margin-top:1px;
  line-height:1.35}
.refnobody{margin:8px 0 0;padding:10px 12px;border-radius:2px;background:var(--alert-bg);
  color:var(--alert);font-size:13px;line-height:1.45;font-weight:500}
.refcount{margin:10px 0 0;font-size:12px;color:var(--ink-mute);line-height:1.4}

/* ── The assign tree, drawn as a chart ──────────────────────────────────────
   A trunk everything shares, then one branch per person the Director approved.
   Connectors are CSS rather than an SVG or a library: --n carries the branch
   count, so the horizontal bar starts at the centre of the first card and ends
   at the centre of the last, whatever the count. With one branch it collapses
   to zero width and disappears, which is correct. */
.otree{padding:20px 16px 22px;overflow-x:auto}
.otrunk{display:flex;flex-direction:column;align-items:center}
.ostem{display:block;width:2px;height:18px;background:var(--line-strong);margin:0 auto;flex:none}
.ostem.short{height:12px}

.ocard{width:214px;border:1px solid var(--line);border-radius:2px;padding:10px 12px;
  background:var(--card);text-align:left;flex:none}
.ocard .ostep{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-mute);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ocard .owho{font-size:14px;font-weight:600;margin-top:3px;letter-spacing:-.01em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ocard .owhen{font-size:12px;color:var(--ink-dim);margin-top:3px}
/* Done is quiet, here-now is loud, gated is the one that needs somebody. */
.ocard.done{background:var(--navy-wash);border-color:var(--navy-tint)}
/* Same reasoning as the stage dot: 'here now' wears the application's accent. */
.ocard.now{border-color:var(--navy);box-shadow:0 0 0 3px var(--navy-tint)}
.ocard.gated{background:var(--pending-bg);border-color:var(--pending-line)}

.osplit{max-width:440px;margin:0 auto;padding:8px 12px;border-radius:2px;
  background:var(--surface);font-size:12.5px;color:var(--ink-dim);line-height:1.45;
  text-align:center}

.obranches{display:flex;justify-content:center;align-items:flex-start;gap:18px;
  position:relative;padding-top:32px;margin-top:14px}
/* The bar between the split and the branch stems. Each branch is an equal-width
   flex child, so the centre of the first is 50%/n from the left. */
.obranches::before{content:'';position:absolute;top:0;left:calc(50% / var(--n));
  right:calc(50% / var(--n));height:2px;background:var(--line-strong)}
.obranch{display:flex;flex-direction:column;align-items:center;flex:1 1 0;min-width:0;
  position:relative;max-width:240px}
.obranch::before{content:'';position:absolute;top:-32px;left:50%;width:2px;height:20px;
  background:var(--line-strong)}
.olabel{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--navy);margin-bottom:8px;text-align:center;max-width:100%;line-height:1.3;
  /* Wraps rather than truncates: an ellipsised office name loses which unit it is,
     which is the whole point of the label. The min-height keeps a one-line and a
     two-line label starting their cards at the same y. */
  min-height:29px;display:flex;align-items:flex-end;justify-content:center}

@media (max-width:720px){
  /* Side-by-side branches do not fit a phone. Stacked, a horizontal bar would be
     drawing a line to nowhere, so it goes. */
  .obranches{flex-direction:column;align-items:center;gap:0;padding-top:0;margin-top:10px}
  .obranches::before{display:none}
  .obranch{max-width:none;width:100%}
  .obranch::before{display:none}
  .obranch + .obranch{margin-top:18px;padding-top:18px;border-top:1px solid var(--line)}
}

/* ── The document, in the approval panel ────────────────────────────────────
   Deciding a routing from a title and a category is deciding it from the filing
   rather than from the letter. */
.previewbox{margin-top:16px;border:1px solid var(--line);border-radius:2px;overflow:hidden}
.previewhd{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:9px 12px;border-bottom:1px solid var(--line);background:var(--surface)}
.previewhd .n{font-size:12px;color:var(--ink-mute);font-family:var(--mono)}
.previewpdf{display:block;width:100%;height:320px;border:0;background:var(--surface)}
.previewimg{display:block;width:100%;max-height:320px;object-fit:contain;background:var(--surface)}
.previewnone{margin:0;padding:16px 14px;font-size:13px;color:var(--ink-dim);line-height:1.5}
.previewfiles{display:flex;flex-direction:column;gap:1px;border-top:1px solid var(--line)}
.previewfiles a{display:flex;align-items:center;gap:8px;padding:8px 12px;font-size:12.5px;
  color:var(--ink);text-decoration:none;min-width:0}
.previewfiles a:hover{background:var(--surface);text-decoration:none}
.previewfiles a svg{color:var(--ink-mute);flex:none}
.previewfiles a .num{margin-left:auto;color:var(--ink-mute);flex:none}

/* Attaching a file from the record, and the preview under it.
   One row, because the whole interaction is "pick a file, say why, attach" — a stacked
   form here would push the Files table below the fold on a laptop. The row wraps rather
   than scrolls: the reason box is the part that gives. */
.attachrow{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:11px 14px;border-bottom:1px solid var(--line);background:var(--surface)}
.attachrow .lbl{margin:0;flex:none}
.attachrow .inp{width:auto;flex:none}
.attachrow .inp.file{flex:none;padding:6px 10px;line-height:20px;
  font-size:12.5px;background:var(--card);max-width:100%}
.attachrow .inp[name="reason"]{flex:1 1 220px;min-width:160px}
.attachrow .btn{flex:none}
.attacherr{margin:0;padding:9px 14px;border-bottom:1px solid var(--line);
  font-size:12.5px;color:var(--alert);background:var(--alert-bg)}
.attachnote{margin:0;padding:8px 14px;border-bottom:1px solid var(--line);
  font-size:11.5px;color:var(--ink-mute)}
/* The preview sits INSIDE the Files box, so it drops its own outer margin. */
.filepreview{padding:0 14px 4px}
.filepreview .previewbox{margin-top:14px}
.filepreview .previewnone{padding-left:0;padding-right:0}

/* Naming the people a document goes to.
   A scrolling list of real rows rather than a native multi-select: the position that
   tells two people apart has room to sit under the name, a ticked row stays visibly
   ticked, and picking a second person is a click rather than a keystroke nobody is
   told about. */
.picklist{max-height:196px;overflow-y:auto;border:1px solid var(--line);
  border-radius:var(--r-ctl);background:var(--card)}
.pickrow{display:flex;align-items:flex-start;gap:9px;padding:7px 10px;cursor:pointer;
  border-bottom:1px solid var(--line)}
.pickrow:last-child{border-bottom:0}
.pickrow:hover{background:var(--surface)}
.pickrow input{margin:2px 0 0;width:15px;height:15px;flex:none;accent-color:var(--navy);cursor:pointer}
.pickwho{display:flex;flex-direction:column;gap:1px;min-width:0}
.pickwho .nm{font-size:13px;line-height:1.3;color:var(--ink)}
.pickwho .pos{font-size:11.5px;line-height:1.3;color:var(--ink-mute)}
/* A ticked row reads as chosen at a glance, which the grey selection band never did. */
.pickrow:has(input:checked){background:var(--navy-wash)}
.pickrow:has(input:checked) .nm{font-weight:600;color:var(--navy)}
/* A note under a value, not beside it: the record grid is two columns, and a hint that
   takes the next cell reads as a field with no label. */
.fld .fldnote{display:block;margin-top:2px;font-size:11.5px;line-height:1.35;color:var(--ink-mute)}
/* A grid row opens from its own cells rather than from a button in an eighth column that
   a 1024-wide screen cuts off. The title reads as text until you hover it. */
.rowlink{color:inherit;text-decoration:none;display:block;min-width:0}
.rowlink:hover{color:var(--navy);text-decoration:underline}
/* Who wrote the note, under it — the Director reads two different sentences here (the
   record's instruction and the clerk's own words) and needs to tell them apart. */
.approval-ask .by{display:block;margin-top:4px;font-style:normal;font-size:11.5px;color:var(--ink-mute)}
/* One command-bar popover can now hold several branches; they need a line between them. */
.cmdpop .popdiv{height:1px;background:var(--line);margin:14px -14px}
/* The unit that owns an open branch, in the branch's own heading. */
.bpfpanel .hd .unit{color:var(--navy);font-weight:600}
/* Approve and Return, side by side in a grid cell. */
.rowacts{display:flex;align-items:center;gap:8px}
.rowacts .cmddialog{position:relative}
.rowacts .cmdpop{right:0;min-width:250px}
/* A bar carrying only the account group still holds its height, so the page below it
   starts where it does on every other screen. */
.cmdbar.bare{justify-content:flex-end}

/* The counter's form: two columns that are two COLUMNS.
   The record's .formgrid alternates left and right cell by cell, which is right for
   reading a record and wrong for typing one — tab would bounce between the document and
   the correspondent on every field. Here each column is its own stack, so tab runs down
   the document and then down the correspondent, the order the paper is read in. */
.formcols{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 40px;align-items:start}
/* A narrower label track than the record's 150px: this screen is typed into, so the
   width belongs to the controls. The label sits against the first line of its control
   rather than in the middle of a field that carries a note under it. */
.formcols .fld{grid-template-columns:128px minmax(0,1fr);gap:12px;align-items:start}
.formcols .fld > .l{min-height:32px;flex-wrap:wrap;gap:0 6px}
@media (max-width: 900px){ .formcols{grid-template-columns:minmax(0,1fr)} }
/* A field whose control is taller than one line stops centring its label against it. */
.fld.tall{align-items:start;padding-top:10px}
.fld .ed.tall{height:auto;min-height:62px;padding:7px 9px;line-height:1.45;resize:vertical}
.fld .ed.file{height:auto;padding:6px 9px;line-height:20px;font-size:12.5px;background:var(--card)}
.fld .hint{font-weight:400;color:var(--ink-mute)}
/* A second way to the same verb, for the width where the command bar is off the screen. */
.formfoot{display:flex;align-items:center;gap:14px;margin-top:26px;padding-top:18px;
  border-top:1px solid var(--line)}
.formfoot span{font-size:12.5px;color:var(--ink-mute)}

/* Your own account: the security block's controls, and the enrolment QR. */
a.avatar{text-decoration:none}
a.avatar:hover{box-shadow:0 0 0 2px var(--gold)}
.secact{display:flex;gap:8px;margin-top:8px;flex-wrap:wrap}
.secconfirm{display:flex;gap:8px;margin-top:10px}
.secconfirm .inp{width:140px}
.qrbox{margin-top:10px;padding:10px;display:inline-block;background:var(--card);
  border:1px solid var(--line);border-radius:2px}
.qrbox svg{display:block;width:150px;height:150px}
.pwform{display:grid;gap:8px;max-width:320px}
.reveal{margin-top:10px}
.reveal > summary{cursor:pointer;font-size:12.5px;color:var(--navy);font-weight:600}
.codes{margin:8px 0 0;padding:0;list-style:none;display:grid;grid-template-columns:1fr 1fr;gap:4px;
  font-size:12.5px}
/* The one-column auth pages that are not the sign-in screen. */
.authwrap{max-width:420px;margin:40px auto}
.authwrap h1{margin:0 0 6px;font-size:21px;font-weight:700;letter-spacing:-.025em}
.secpage{max-width:560px}
.secpage p{margin:0 0 12px}

/* The dashboard, compact.
   Five figures in a strip instead of four cards in two rows: the icon tile said nothing
   the label did not, and cost 250px of height per number. Two of the five are links,
   because at risk and overdue are the only figures anyone acts on. */
/* Five across, always — auto-fit put the fifth on a row of its own the moment the
   window narrowed, which is the wrap the old cards were replaced for. */
.stats{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:12px;margin-bottom:16px}
/* A strip of three, where there are three. Five fixed columns left two empty. */
.stats.three{grid-template-columns:repeat(3,minmax(0,1fr))}
@media (max-width: 880px){ .stats{grid-template-columns:repeat(3,minmax(0,1fr))} }
@media (max-width: 620px){ .stats{grid-template-columns:repeat(2,minmax(0,1fr))} }
.stat{display:grid;gap:2px;align-content:start;padding:12px 14px;background:var(--card);
  border:1px solid var(--line);border-radius:2px;text-decoration:none;color:inherit}
a.stat:hover{border-color:var(--navy);text-decoration:none}
.stat .l{font-size:11.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-mute)}
.stat .n{font-size:25px;font-weight:700;letter-spacing:-.02em;line-height:1.15}
.stat .n.warn{color:var(--pending)} .stat .n.bad{color:var(--alert)} .stat .n.good{color:var(--success)}
.stat .s{font-size:11.5px;color:var(--ink-dim)}
/* What came in, wide; what is late, narrow. Both above the reporting. */
.dashsplit{display:grid;grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);gap:16px;align-items:start}
@media (max-width: 900px){ .dashsplit{grid-template-columns:minmax(0,1fr)} }
/* Seven meters in a tower is a scroll; in two columns it is a glance. */
.meters{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:4px 28px;padding:14px 16px}
.meters > div{margin-bottom:10px !important}
.meternote{grid-column:1/-1;margin:4px 0 0;font-size:12px;color:var(--ink-mute)}

/* Your own account, compact.
   A value and its control on one line, figures as figures, and the password form folded
   away — three stacked inputs is two hundred pixels for something done once a year. */
.fld .rowline{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.fld .dim{color:var(--ink-mute);font-weight:400}
.stats.mine{grid-template-columns:repeat(4,minmax(0,1fr));gap:0 18px;margin:8px 0 0;
  padding-top:10px;border-top:1px solid var(--line)}
.stats.mine .stat{padding:0;border:0;background:none;border-radius:0}
.stats.mine a.stat:hover{border:0}
.stats.mine a.stat:hover .n{color:var(--navy)}
.stats.mine .n{font-size:21px;line-height:1.2}
.stats.mine .s{line-height:1.35}
.minefoot{margin:10px 0 0;font-size:12.5px;color:var(--ink-dim)}
.fld .reveal > summary{display:inline-block}
.fld .pwform{margin-top:8px;max-width:210px;gap:6px}

/* Whose account this is, above what can be changed about it. */
.mehead{display:flex;align-items:center;gap:14px;margin:10px 0 4px}
.mehead .avatar.lg{width:50px;height:50px;font-size:17px;font-weight:700}
.mehead .nm{font-size:18px;font-weight:700;letter-spacing:-.015em;line-height:1.25}
.mehead .sub{font-size:12.5px;color:var(--ink-dim);margin-top:1px}
.mehead .marks{display:flex;flex-wrap:wrap;gap:6px;margin-top:7px}

/* The activity log: one row to add a line, one table for the week. */
.logrow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:11px 14px;
  border-bottom:1px solid var(--line);background:var(--surface)}
.logrow .inp{width:auto;flex:none}
.logrow .inp.grow{flex:1 1 220px;min-width:160px}
.logrow .inp.hrs{width:82px}
/* A select is as wide as its longest option unless it is told otherwise, and one of
   these units is "Project Evaluation and Monitoring Unit" — which pushed the button
   onto a second line. */
.logrow .inp.unit{width:132px}
.logrow .inp.stat{width:114px}
.sheet tr.today > td{background:var(--navy-wash)}
/* A note that qualifies the row above it, inside the table rather than under it. */
.sheet tr.notes > td{padding:4px 12px 8px;font-size:11.5px;color:var(--ink-mute);
  border-bottom:1px solid var(--line);height:auto;line-height:1.4}

/* Throughput: a person in a table cell, and two bars read against each other. */
.sheet .who{display:flex;align-items:center;gap:9px;min-width:0}
.sheet .who .sub{display:block;font-size:11px;color:var(--ink-mute)}
.bars{display:grid;gap:3px;padding:6px 0}
.bars .meter{height:9px;border-radius:2px}
.bars .meter > i{border-radius:2px}
.swatch{width:8px;height:8px;border-radius:2px;display:block}

/* ---- Reports -------------------------------------------------------------------
   The catalogue, and a report rendered as the page it prints. */
.reportlist{display:grid;gap:10px}
.reportcard{display:flex;align-items:flex-start;justify-content:space-between;gap:20px;
  padding:13px 16px;border:1px solid var(--line);border-radius:2px;background:var(--card)}
.reportcard:hover{border-color:var(--line-strong)}
.reportcard .rt{font-size:14.5px;font-weight:600;color:var(--navy);text-decoration:none}
.reportcard .rt:hover{text-decoration:underline}
.reportcard .rp{margin:3px 0 0;font-size:12.5px;color:var(--ink-dim);line-height:1.45;max-width:78ch}
.reportcard .ra{display:flex;align-items:center;gap:12px;flex:none}
.reportcard .per{font-size:11.5px;color:var(--ink-mute);white-space:nowrap}

/* The page itself. On screen it sits on the app's ground; on paper it is the page. */
/* The page, at the size it prints. A4 portrait is 210mm wide and A4 landscape 297mm;
   take the 14mm margins off each and the preview is held to exactly the width the paper
   gives it, so a column that would fall off the printed edge falls off here too. */
.paper{background:var(--card);border:1px solid var(--line);border-radius:2px;
  padding:20px 22px 18px;max-width:182mm}
.paper.landscape{max-width:269mm}
.letterhead{display:flex;align-items:flex-start;justify-content:space-between;gap:24px;
  padding-bottom:10px;margin-bottom:12px;border-bottom:2px solid var(--navy)}
.letterhead .office{font-size:11.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-mute)}
.letterhead h1{margin:1px 0 0;font-size:17px;font-weight:700;letter-spacing:-.02em}
.letterhead .cover{margin:3px 0 0;font-size:13px;color:var(--ink-dim)}
.letterhead .meta{text-align:right;font-size:11px;color:var(--ink-mute);line-height:1.6;flex:none}
/* A report's columns are sized by what is in them, not by an eighth each: .sheet is
   table-layout:fixed for grids whose widths are declared, and a report declares none. */
.paperscroll{overflow-x:auto}
.sheet.report{table-layout:auto;width:100%}
.sheet.report th{background:none;border-bottom:1px solid var(--ink-mute);color:var(--ink);
  font-size:11.5px;white-space:nowrap}
.sheet.report td{white-space:normal}
/* Report cells are a register's, not a screen's: one line each unless the column is
   prose, small, and tight — fifteen rows of correspondence should be one sheet. */
.sheet.report td{height:auto;padding:3px 8px;vertical-align:top;font-size:11.5px;
  line-height:1.35;white-space:nowrap}
.sheet.report td.wrap{white-space:normal;min-width:20ch;max-width:44ch}
.sheet.report td.num,.sheet.report .mono{font-size:11px}
.papernote{margin:12px 0 0;font-size:11.5px;color:var(--ink-mute);line-height:1.5;max-width:90ch}

/* ---- Print ----------------------------------------------------------------------
   The preview IS the output, so printing hides the application and leaves the page.
   Nothing here re-renders anything: it removes the furniture. */
@media print{
  /* A4, named rather than left to the browser: "Save as PDF" otherwise prints whatever
     the machine's default page happens to be — US Letter is 6mm narrower than A4 and
     quietly drops the right-hand column of a wide register. */
  @page{size:A4;margin:14mm}
  @page landscapepage{size:A4 landscape;margin:12mm}
  .paper.landscape{page:landscapepage}
  .paper,.paper.landscape{max-width:none}
  .rail,.raildrawer,.cmdbar,.viewhint,.screenonly,.notice,.boxft{display:none !important}
  /* The page fades in from opacity 0. A print taken before the fade has run — headless
     Chrome's print-to-PDF, a print triggered on load — came out as blank pages. Paper
     does not animate. */
  .wrap{animation:none !important}
  .shell,.pane,.main,.wrap{display:block !important;margin:0 !important;padding:0 !important;
    max-width:none !important;background:#fff !important}
  .paper{border:0;border-radius:0;padding:0}
  .letterhead{border-bottom:2px solid #000}
  .letterhead .office,.letterhead .meta,.papernote{color:#333}
  .paperscroll{overflow:visible !important}
  .sheet.report{font-size:9.5pt}
  .sheet.report td{padding:4px 7px}
  .sheet.report th{padding:4px 7px}
  .sheet.report th{border-bottom:1px solid #000;color:#000}
  .sheet.report tr{page-break-inside:avoid}
  .sheet.report thead{display:table-header-group}
  a[href]{color:#000;text-decoration:none}
}

/* Where the work is sitting: a queue depth per stage, and the age of the oldest thing
   in it. Four columns rather than a chart, because five stages is a list.

   NOT .stages — that name belongs to the stage ribbon on the record and the tracker,
   whose grid-template-columns would have won here and put two queues on a line. Third
   collision in this stylesheet; the rule is to take a new name, not to out-specify. */
.wherework{padding:10px 16px 14px;display:grid;gap:7px}
.whererow{display:grid;grid-template-columns:minmax(0,1fr) minmax(80px,2.2fr) 34px 116px;
  gap:12px;align-items:center;font-size:12.5px}
.whererow .nm{color:var(--ink);font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.whererow .meter{height:9px;border-radius:2px}
.whererow .meter > i{border-radius:2px;background:var(--navy)}
.whererow .ct{font-family:var(--mono);font-size:12px;text-align:right}
.whererow .ag{font-size:11.5px;color:var(--ink-mute);text-align:right;white-space:nowrap}
@media (max-width: 760px){ .stagerow{grid-template-columns:minmax(0,1fr) 34px} .stagerow .meter,.whererow .ag{display:none} }

/* ======================================================================
   THE CPDO SEAL
   The artwork is a circular seal printed on white, and the places it has
   to sit — the rail, the dark footer — are navy. A bare image there shows
   a white square with a circle in it, so the mark IS the white disc and
   the seal is contained inside it. Sizes stay wherever they were set.
   ====================================================================== */
.brand-mark,.railapp .mark,.railtoggle .mark{
  background:#fff;border-radius:50%;overflow:hidden;padding:0}
.brand-mark img,.railapp .mark img,.railtoggle .mark img{
  width:100%;height:100%;object-fit:contain;display:block}

/* Visually hidden, still read aloud. A column of Remove buttons needs a header for a
 * screen reader to say what the column is; printing the word over the buttons would be
 * noise for everyone else. */
.vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0}

/* Subgrid toolbars. Their grids each carry their own small command strip in the
 * header; ours carried a count chip, which reads as a section label rather than as
 * a grid you can act on. */
.boxhd .gridtools{margin-left:auto;display:flex;align-items:center;gap:14px}
.gridtool{font-size:12.5px;font-weight:600;color:var(--navy);text-decoration:none;
  white-space:nowrap}
.gridtool:hover{text-decoration:underline}

/* The top-bar search box. Their staff type where they are standing rather than
 * clicking through to a page that has a box on it. */
.cmdsearch{display:flex;align-items:center;gap:4px;margin-right:6px;
  border:1px solid var(--line-strong);border-radius:2px;background:var(--card);
  padding:0 2px 0 0;max-width:320px;flex:1 1 200px}
.cmdsearch input{border:0;outline:0;background:transparent;font:inherit;font-size:13px;
  color:var(--ink);padding:6px 8px 6px 0;width:100%;min-width:0}
.cmdsearch:focus-within{border-color:var(--navy);box-shadow:0 0 0 1px var(--navy)}
.cmdsearch .iconbtn{flex:none}
@media (max-width:900px){.cmdsearch input{display:none}.cmdsearch{border:0;flex:none}}

/* ── PowerDTS components, copied from the approved mockup ──────────────────
   scratchpad/mockups/powerdts-record.html, drawn from Mike's photographs. The
   values below are theirs, not a reinterpretation of theirs. */

/* Doc Approval. Their field is a toggle; ours carries a third state in the word
 * beside it, because the Director can return a letter and their control cannot
 * say so. */
.approvaltoggle{display:inline-flex;align-items:center;gap:8px}
.toggle{width:30px;height:16px;border-radius:9px;background:var(--track-off);position:relative;
  flex:none;display:inline-block}
.toggle i{position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;
  background:var(--knob);transition:left .12s ease}
.toggle.on{background:var(--navy)}
.toggle.on i{left:16px}

/* Sort carets on subgrid headers. Presentation only — the grids are short enough
 * that nobody has asked to sort them, and a caret that does nothing when clicked
 * is worse than none. They are marked aria-hidden for that reason. */
.sortcaret{color:var(--ink-mute);font-size:9px;margin-left:3px}

/* Their empty state: a grid glyph over the sentence, inside the grid's own border. */
.emptygrid{background:var(--card);border:1px solid var(--line);padding:38px 20px;
  text-align:center;color:var(--ink-mute);font-size:13px}
.emptygrid .glyph{width:52px;height:52px;margin:0 auto 12px;border-radius:2px;
  background:var(--glyph-bg);display:grid;grid-template-columns:repeat(3,1fr);
  grid-template-rows:repeat(3,1fr);gap:2px;padding:6px}
.emptygrid .glyph i{background:var(--glyph-dot);border-radius:1px;display:block}

/* The Activities editor surface. */
.rte{border:1px solid var(--line);background:var(--card);margin-top:8px}
.rtebar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:6px 9px;
  border-bottom:1px solid var(--line);font-size:12.5px;color:var(--ink-dim)}
.rtebar .sel{border:1px solid var(--line);border-radius:2px;padding:2px 7px;
  background:var(--card);font-size:12.5px}
.rtebar b,.rtebar i,.rtebar u,.rtebar s{color:var(--ink);padding:0 2px;font-style:normal}
.rtebody{padding:12px 11px;font-size:13.5px;min-height:74px}

/* ─── The Unit Plan ───────────────────────────────────────────────────────────
   Microsoft Planner's board, in this application's language. The layout is theirs
   because the Admin Unit already runs its month on it and recognising a screen costs
   an afternoon where learning one costs a training programme. The surfaces, the
   type and the 2px corners are ours. See docs/DTS-PLAN-G-UNIT-PLAN.md. */

.wb{display:flex;gap:14px;align-items:flex-start;overflow-x:auto;padding:4px 2px 18px}
.wbcol{flex:0 0 272px;min-width:272px}
.wbcolhd{display:flex;align-items:baseline;gap:8px;padding:0 2px 8px}
.wbcolhd h3{margin:0;font-size:14px;font-weight:600;color:var(--ink)}
.wbcolhd .n{font-size:12px;color:var(--ink-mute);font-variant-numeric:tabular-nums}
.wbadd{display:block;width:100%;text-align:left;padding:6px 2px;font-size:13px;
  color:var(--navy);text-decoration:none}
.wbadd:hover{text-decoration:underline}

.wbcard{display:block;background:var(--card);border:1px solid var(--line);border-radius:2px;
  padding:10px 11px;margin-bottom:8px;text-decoration:none;color:inherit}
.wbcard:hover{box-shadow:var(--shadow-lift)}
.wbcard .t{display:block;font-size:13px;line-height:1.35;color:var(--ink);margin-bottom:8px}
.wbcard .ref{display:block;font-size:11.5px;color:var(--ink-mute);margin-top:2px}
.wbmeta{display:flex;align-items:center;gap:10px;font-size:12px;color:var(--ink-dim);flex-wrap:wrap}
.wbmeta .amt{margin-left:auto;font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.wbfoot{display:flex;align-items:center;gap:6px;margin-top:9px;padding-top:9px;
  border-top:1px solid var(--line)}
.wbfoot .avatar{width:22px;height:22px;font-size:9.5px}
.wbfoot .who{margin-left:auto;display:flex;gap:3px}
.wbfold{font-size:12.5px;color:var(--ink-dim);padding:7px 2px;display:flex;align-items:center;
  gap:7px;border-top:1px solid var(--line);margin-top:4px}
.wbfold .n{margin-left:auto;font-variant-numeric:tabular-nums}
.wbdone{color:var(--ink-mute);text-decoration:line-through}

/* Priority and status as marks. Planner uses coloured glyphs; these are drawn from the
   palette so the same mark reads on a card and in a grid row. */
.pri{display:inline-flex;align-items:center;gap:4px;font-size:12px;white-space:nowrap}
.pri i{width:3px;height:11px;border-radius:1px;display:inline-block;flex:none}
.pri.urgent{color:var(--alert)} .pri.urgent i{background:var(--alert)}
.pri.important i{background:var(--gold-deep)}
.pri.medium i{background:var(--navy)}
.pri.low i{background:var(--ink-mute)}
.st{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--ink-dim);white-space:nowrap}
.st i{width:9px;height:9px;border-radius:50%;display:inline-block;flex:none;
  border:1.5px solid var(--ink-mute)}
.st.prog i{border-color:var(--navy);background:linear-gradient(90deg,var(--navy) 50%,transparent 50%)}
/* Teal, not --success green: the same colour the charts use for Completed, so a
   card and a bar never disagree about what "done" looks like. See the note above. */
.st.done i{border-color:var(--work-done);background:var(--work-done)}

.viewbar{display:flex;align-items:center;gap:10px;margin:0 0 14px;flex-wrap:wrap}
.viewbar .lbl{font-size:12.5px;color:var(--ink-dim)}
.viewbar .inp{height:30px;font-size:13px}
.chartstrip{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:14px}
.donut{display:grid;place-items:center;height:150px}
.donut b{font-size:30px;font-weight:600;color:var(--ink);line-height:1;display:block;text-align:center}
.donut span{display:block;font-size:12px;color:var(--ink-dim);text-align:center;margin-top:3px}

/* ─── Unit Plan charts ────────────────────────────────────────────────────────
   Four states, and the pair that matters is Late against Completed.

   #107C10 (our --success green) against #A4262C red measures ΔE 2.9 under
   deuteranopia — indistinguishable to a red-green colourblind reader, which is
   roughly one man in twelve. Teal carries blue content and separates where green
   cannot: #0E7C7B scores 11.2, above the ≥8 target, with every state clearing 3:1
   against the card. Measured with the dataviz validator, not judged by eye.

   Grey for "not started" reads as neutral on purpose — nothing has happened yet —
   and the muted teal sits in the Fluent palette deliberately. Both are below the
   chroma floor a CATEGORICAL palette would demand; this is a status palette, and
   it ships with a legend and a count beside every segment so identity is never
   carried by colour alone. */
:root{
  --work-none:#797673;
  --work-prog:#0078D4;
  --work-late:#A4262C;
  --work-done:#0E7C7B;
}

.stackbar{display:flex;height:14px;background:var(--track);border-radius:2px;overflow:hidden;gap:2px}
.stackbar i{display:block;height:100%}
.stackbar .s-none{background:var(--work-none)}
.stackbar .s-prog{background:var(--work-prog)}
.stackbar .s-late{background:var(--work-late)}
.stackbar .s-done{background:var(--work-done)}

.stackrow{display:grid;grid-template-columns:116px 1fr 34px;align-items:center;gap:10px;padding:5px 0}
.stackrow .nm{font-size:12.5px;color:var(--ink-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.stackrow .ct{font-size:12.5px;color:var(--ink);text-align:right;font-variant-numeric:tabular-nums}

.chartlegend{display:flex;flex-wrap:wrap;gap:12px;padding:10px 14px;border-top:1px solid var(--line);
  font-size:12px;color:var(--ink-dim)}
.chartlegend span{display:inline-flex;align-items:center;gap:5px}
.chartlegend i{width:9px;height:9px;border-radius:2px;display:inline-block}

.donutwrap{display:grid;place-items:center;padding:14px 0 4px}
.donutwrap svg{display:block}
.donutwrap .mid{font-size:26px;font-weight:600;fill:var(--ink)}
.donutwrap .sub{font-size:10.5px;fill:var(--ink-dim)}


/* Search highlighting. The browser default is #FFFF00 with black text — readable, and a
   slab of pure yellow in a Fluent dark window. The pending wash already means "look here"
   everywhere else in this application and it is defined in both themes. */
mark{background:var(--pending-bg);color:var(--pending-ink);padding:0 2px;border-radius:2px}

/* ─── Dark ────────────────────────────────────────────────────────────────────
   Tokens only. Every component already draws through them, so nothing below the
   palette knows which theme it is in — and anything that still held a literal was
   tokenised first, because a dark block is worthless while a white sits underneath it.

   Three states, not two. An explicit choice stamps data-theme on <html>; the default
   is "follow the device", which stamps nothing and leaves prefers-color-scheme to
   decide. The media query is guarded so an explicit LIGHT beats a dark device, and the
   [data-theme="dark"] block repeats it so an explicit DARK beats a light one. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
  color-scheme:dark;

  /* Fluent's dark neutrals. CPDO already works in a dark Microsoft app — the Planner
     screenshots Mike sent on 22 October are dark — so this is the same move the rest of
     the palette makes: their system's colours, not ours. */
  --page:#1B1A19; --surface:#201F1E; --card:#292827;
  --line:#3B3A39; --line-strong:#484644; --track:#3B3A39;
  --ink:#F3F2F1; --ink-dim:#C8C6C4; --ink-mute:#8A8886;

  /* The accent lifts. #0078D4 on a #292827 card is under 3:1 and reads as a bruise;
     Fluent's dark blue is a step lighter for exactly this reason. */
  --navy:#2899F5; --navy-600:#3AA0F3; --navy-dark:#4CA8F7;
  --navy-tint:#0B2740; --navy-wash:#15202B;

  --gold:#FFB900; --gold-soft:#FFD335; --gold-deep:#FFC83D;

  --success:#54B054; --success-bg:#143B14;
  --pending:#A19F9D; --pending-bg:#3A3118; --pending-line:#6B5A1F; --pending-ink:#FFD98A;
  --alert:#F1707B;   --alert-bg:#3B1B1E;

  --hover:#323130;
  --knob:#F3F2F1; --track-off:#605E5C;
  --glyph-bg:#323130; --glyph-dot:#484644;
  --ring:#292827;
  --scrim:rgba(0,0,0,.55);
  --shadow-pop:0 18px 48px rgba(0,0,0,.5);
  --shadow-pop-left:-18px 0 48px rgba(0,0,0,.5);
  --shadow-hover:0 0 0 1px var(--line-strong);
  --shadow-lift:0 1.6px 3.6px rgba(0,0,0,.45), 0 .3px .9px rgba(0,0,0,.3);

  /* The four chart states, re-measured against the dark card rather than flipped.
     Worst adjacent pair is Completed against Late at ΔE 14.7 (deutan), normal-vision
     17.5, every state clearing 3:1 — the light set's own values do not survive the
     move, which is why these are their own steps. */
  --work-none:#8A8886; --work-prog:#2899F5; --work-late:#E04756; --work-done:#4FC1B8;
  }
}

:root[data-theme="dark"] {
  color-scheme:dark;

  /* Fluent's dark neutrals. CPDO already works in a dark Microsoft app — the Planner
     screenshots Mike sent on 22 October are dark — so this is the same move the rest of
     the palette makes: their system's colours, not ours. */
  --page:#1B1A19; --surface:#201F1E; --card:#292827;
  --line:#3B3A39; --line-strong:#484644; --track:#3B3A39;
  --ink:#F3F2F1; --ink-dim:#C8C6C4; --ink-mute:#8A8886;

  /* The accent lifts. #0078D4 on a #292827 card is under 3:1 and reads as a bruise;
     Fluent's dark blue is a step lighter for exactly this reason. */
  --navy:#2899F5; --navy-600:#3AA0F3; --navy-dark:#4CA8F7;
  --navy-tint:#0B2740; --navy-wash:#15202B;

  --gold:#FFB900; --gold-soft:#FFD335; --gold-deep:#FFC83D;

  --success:#54B054; --success-bg:#143B14;
  --pending:#A19F9D; --pending-bg:#3A3118; --pending-line:#6B5A1F; --pending-ink:#FFD98A;
  --alert:#F1707B;   --alert-bg:#3B1B1E;

  --hover:#323130;
  --knob:#F3F2F1; --track-off:#605E5C;
  --glyph-bg:#323130; --glyph-dot:#484644;
  --ring:#292827;
  --scrim:rgba(0,0,0,.55);
  --shadow-pop:0 18px 48px rgba(0,0,0,.5);
  --shadow-pop-left:-18px 0 48px rgba(0,0,0,.5);
  --shadow-hover:0 0 0 1px var(--line-strong);
  --shadow-lift:0 1.6px 3.6px rgba(0,0,0,.45), 0 .3px .9px rgba(0,0,0,.3);

  /* The four chart states, re-measured against the dark card rather than flipped.
     Worst adjacent pair is Completed against Late at ΔE 14.7 (deutan), normal-vision
     17.5, every state clearing 3:1 — the light set's own values do not survive the
     move, which is why these are their own steps. */
  --work-none:#8A8886; --work-prog:#2899F5; --work-late:#E04756; --work-done:#4FC1B8;
}

/* The seal keeps its white disc in both themes: it is a printed emblem with its own
   colours, and a logo that changes with the furniture is a logo nobody recognises. */

/* The checklist tick, which IS the control — a list you can read and not tick is a list
   of things somebody else is doing. Sized to the 16px box the rest of the grid uses. */
.tickbtn{width:18px;height:18px;border:1.5px solid var(--line-strong);border-radius:2px;
  background:var(--card);color:var(--work-done);font-size:12px;line-height:1;cursor:pointer;
  display:grid;place-items:center;padding:0}
.tickbtn:hover{border-color:var(--navy)}
.tickbtn.on{border-color:var(--work-done)}

/* Notes: full width and room for a paragraph. It was four rows in a half-width column. */
.notesbox{width:100%;height:auto;min-height:190px;padding:10px;border:1px solid var(--line);
  border-radius:2px;background:var(--card);resize:vertical;line-height:1.5}
.notesbox:focus{outline:none;border-color:var(--navy);box-shadow:0 0 0 1px var(--navy)}

/* A tab that LEAVES the screen it sits on. The Unit Plan's first three tabs are views of
   the same board; Calendar is the office's one calendar. Drawn identically it read as a
   fourth view and stranded whoever clicked it. */
.formtabs .tabout{color:var(--ink-dim)}
.formtabs .tabout span{font-size:11px;opacity:.75;margin-left:1px}
.formtabs .tabout:hover{color:var(--navy)}

/* ===== My Tasks (Plan H) =====================================================
   The Unit Plan items assigned to me, grouped by when they are due, with time logged
   on each row. Tokens only, so the dark palette applies without a block of its own. */
.mytasks tr.mtgrp td{background:var(--surface);font-size:11.5px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-dim);padding:9px 12px 7px;border-top:1px solid var(--line)}
.mytasks tr.mtgrp td .n{font-weight:600;color:var(--ink-mute);margin-left:6px;letter-spacing:0}
.mytasks tr.mtgrp.bad td{color:var(--alert)}
.mytasks tr.mtgrp.done td{color:var(--success)}
.mytasks td.mytime{font-variant-numeric:tabular-nums;font-weight:600;color:var(--navy)}
.mytasks td.mtact{text-align:right;white-space:nowrap}
.mytasks td.mtact .mtact-in{display:inline-flex;align-items:center;gap:12px}
.mytasks td.mtact form{margin:0}
.mytasks td.mtact .linkbtn{font-size:13px}
.mytasks tr.open > td{background:var(--navy-tint)}
.mytasks tr.mtlog > td{background:var(--navy-tint);padding:0 12px 10px;border-top:0}
.mytasks tr.mtlog .logrow{border:1px solid var(--line);border-radius:6px;background:var(--card)}
.logrow .lbl{font-size:12.5px;font-weight:600;color:var(--ink-dim);white-space:nowrap}
.logrow .inp.task{max-width:240px}
.mtfin{display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--ink-dim);white-space:nowrap}
.taskchip{display:inline-flex;flex-direction:column;gap:1px;padding:3px 8px;border-radius:5px;
  background:var(--navy-tint);color:var(--navy);font-weight:600;font-size:12.5px;line-height:1.25;
  text-decoration:none;max-width:100%}
.taskchip span{font-weight:500;font-size:11px;color:var(--ink-dim)}
.taskchip:hover{text-decoration:underline}
.othr{font-size:12.5px;color:var(--ink-dim);font-style:italic}
.sheet .tag{white-space:nowrap}
.recsheets.three{grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}

/* ===== Monthly accomplishment report (Plan H) ================================ */
.acband{display:flex;border:1px solid var(--line);margin:4px 0 14px}
.acband div{flex:1;padding:8px 12px;border-right:1px solid var(--line)}
.acband div:last-child{border-right:0}
.acband b{display:block;font-size:20px;font-weight:700;color:var(--navy);font-variant-numeric:tabular-nums}
.acband span{font-size:11.5px;color:var(--ink-dim)}
.paper .formsec-h{margin-top:22px}
.sheet.report td .sub{display:block;font-size:11px;color:var(--ink-mute)}
.sheet.report tr.bkt td .sub{display:inline;margin-left:4px}
.sheet.report tr.tot td{border-top:1.5px solid var(--line-strong)}
.sheet.report tr.bkt td{background:var(--surface);padding-top:8px}
.sheet.report.sigs{margin-top:30px}
.sheet.report.sigs td{border:0;padding-top:10px;vertical-align:top}
.sigcap{font-size:11px;letter-spacing:.07em;text-transform:uppercase;color:var(--ink-dim);margin-bottom:36px}
/* currentColor, not #000: the line must show on the dark paper on screen too. */
.sigline{border-top:1px solid currentColor;padding-top:4px;max-width:300px}
.sigdate{margin-top:14px;font-size:12px;color:var(--ink-dim)}
